Я рассматриваю возможность создания приложения, которое по своей сути будет состоять из тысяч операторов if ... then ... else. Цель приложения - уметь предсказывать, как коровы передвигаются в любом ландшафте. На них влияют такие вещи, как солнце, ветер, источник пищи, внезапные события и т. Д.
Как можно управлять таким приложением? Я полагаю, что после нескольких сотен IF-операторов было бы так же непредсказуемо, как отреагирует программа, а отладка того, что привело к определенной реакции, означала бы, что каждый раз придется обходить все дерево IF-операторов.
Я читал немного о правилах двигателей, но я не вижу, как они обойдут эту сложность.
Ответы:
Язык логического программирования Prolog может быть тем, что вы ищете. Ваше заявление о проблеме не достаточно конкретное, чтобы я мог оценить, подходит ли оно вам, но оно скорее похоже на то, что вы говорите.
Программа Prolog состоит из применяемых фактов и правил. Вот простое примерное правило, которое гласит: «Корова переезжает в другое место, если она голодна и в новом месте больше еды, чем в старом»:
Все, что написано заглавными буквами, - это переменные, вещи, о которых вы не знаете. Пролог пытается найти значения для этих переменных, которые удовлетворяют всем условиям. Этот процесс выполняется с помощью мощного алгоритма, называемого унификацией, который является сердцем Prolog и подобных логических сред программирования.
В дополнение к правилам предоставляется база данных фактов. Простой пример, который работает с правилами выше, может быть что-то вроде:
Обратите внимание, что white_cow, пастбище и т. Д. Не написаны заглавными буквами. Они не переменные, они атомы.
Наконец, вы делаете запрос и спрашиваете, что произойдет.
Первый запрос спрашивает, куда двинется белая корова. Учитывая приведенные выше правила и факты, ответ - нет. Это можно интерпретировать как «я не знаю» или «оно не двигается» в зависимости от того, что вы хотите.
Второй запрос спрашивает, куда движется черная корова. Он движется на пастбище, чтобы поесть.
Последний запрос спрашивает, куда движутся все коровы. В результате вы получаете все возможные варианты (Корова, Назначение), которые имеют смысл. В этом случае черный бык движется на пастбище, как и ожидалось. Однако у злого быка есть два варианта, которые удовлетворяют правилам: он может либо перебраться на пастбище, либо в сарай.
Примечание. Прошло много лет с тех пор, как я в последний раз писал Пролог, все примеры могут быть синтаксически недействительными, но идея должна быть правильной.
источник
Решая проблему if web, вы можете создать механизм правил, где каждое конкретное правило кодируется независимо. Дополнительным уточнением для этого было бы создание предметно-ориентированного языка (DSL) для создания правил, однако один только DSL перемещает проблему только из одной базы кода (основной) в другую (DSL). Без структуры DSL не будет лучше, чем родной язык (Java, C # и т. Д.), Поэтому мы вернемся к нему после того, как найдем улучшенный структурный подход.
Основная проблема заключается в том, что у вас есть проблема с моделированием. Всякий раз, когда вы сталкиваетесь с комбинаторными ситуациями, подобными этой, это явный признак того, что ваша абстракция модели, которая описывает ситуацию, является слишком грубой. Скорее всего, вы объединяете элементы, которые должны принадлежать разным моделям, в одну сущность.
Если вы продолжаете ломать свою модель, вы в конечном итоге полностью утратите этот комбинаторный эффект. Однако, выбирая этот путь, легко потеряться в своем дизайне, создавая еще большую неразбериху, перфекционизм здесь не обязательно ваш друг.
Конечные автоматы и механизмы правил являются лишь примером того, как эту проблему можно решить и сделать более управляемой. Основная идея здесь заключается в том, что хороший способ избавиться от такой комбинаторной проблемы, как эта, часто состоит в том, чтобы создать дизайн и повторять его ad-nauseam на вложенных уровнях абстракции до тех пор, пока ваша система не будет работать удовлетворительно. Сродни тому, как фракталы используются для создания сложных паттернов. Правила остаются неизменными, независимо от того, смотрите ли вы на свою систему под микроскопом или с высоты птичьего полета.
Пример применения этого в вашем домене.
Вы пытаетесь смоделировать, как коровы движутся по местности. Хотя в вашем вопросе нет подробностей, я бы предположил, что большое количество ifs включает фрагмент решения, например,
if cow.isStanding then cow.canRun = true
но вы застряли, когда добавляете детали местности, например. Поэтому для каждого действия, которое вы хотите предпринять, вы должны проверить все возможные аспекты и повторить эти проверки для следующего возможного действия.Сначала нам нужен наш повторяемый дизайн, который в этом случае будет FSM для моделирования изменяющихся состояний симуляции. Поэтому первое, что я хотел бы сделать, это реализовать эталонный FSM, определив интерфейс состояния, интерфейс перехода и, возможно, контекст переходакоторый может содержать общую информацию, которая будет доступна другим двум. Базовая реализация FSM будет переключаться с одного перехода на другой независимо от контекста, вот где появляется механизм правил. Механизм правил четко инкапсулирует условия, которые должны быть выполнены, если переход должен состояться. Механизм правил здесь может быть простым списком правил, каждое из которых имеет функцию оценки, возвращающую логическое значение. Чтобы проверить, должен ли переход произойти, мы выполняем итерацию списка правил, и если какое-либо из них оценивается как ложное, переход не происходит. Сам переход будет содержать поведенческий код для изменения текущего состояния FSM (и других возможных задач).
Теперь, если я начну реализовывать симуляцию как один большой FSM на уровне GOD, я получу МНОГО возможных состояний, переходов и т. Д. Беспорядок if-else выглядит так, как будто он исправлен, но на самом деле он просто распространяется: каждый IF Теперь правило, которое выполняет проверку на предмет конкретной информации контекста (которая на данный момент в значительной степени содержит все), и каждое тело IF находится где-то в коде перехода.
Введите разбивку по фракталам: первым шагом будет создание FSM для каждой коровы, где состояния - это собственные внутренние состояния коровы (стоя, бег, ходьба, выпас и т. Д.), И переходы между ними будут зависеть от окружающей среды. Возможно, что график неполон, например, выпас доступен только из стоячего состояния, любой другой переход запрещен, потому что просто отсутствует в модели. Здесь вы эффективно разделяете данные в двух разных моделях: корова и рельеф. У каждого свои свойства. Эта разбивка позволит вам упростить общую конструкцию двигателя. Теперь вместо единого механизма правил, который решает все, у вас есть несколько более простых механизмов правил (по одному для каждого перехода), которые определяют очень конкретные детали.
Поскольку я повторно использую тот же код для FSM, это в основном конфигурация FSM. Помните, когда мы упоминали о DSL раньше? Именно здесь DSL может принести много пользы, если у вас есть множество правил и переходов для написания.
Идти глубже
Теперь БОГУ больше не приходится сталкиваться со всей сложностью управления внутренними состояниями коровы, но мы можем продвинуть это дальше. Например, в управлении ландшафтом все еще много сложностей. Здесь вы решаете, где достаточно разбивки. Если, например, в вашем БОГе вы в конечном итоге управляете динамикой местности (длинная трава, грязь, сухая грязь, короткая трава и т. Д.), Мы можем повторить ту же схему. Ничто не мешает вам внедрить такую логику в сам ландшафт, выделяя все состояния ландшафта (длинная трава, короткая трава, грязная, сухая и т. Д.) В новый FSM ландшафта с переходами между состояниями и, возможно, простыми правилами. Например, чтобы попасть в мутное состояние, механизм правил должен проверить контекст, чтобы найти жидкости, иначе это невозможно. Теперь БОГ стал еще проще.
Вы можете завершить систему FSM, сделав их автономными и дать каждому поток. Этот последний шаг не обязателен, но он позволяет вам динамически изменять взаимодействие системы, регулируя то, как вы делегируете свое решение (запуск специализированного FSM или просто возвращение предварительно определенного состояния).
Помните, как мы упоминали, что переходы могут также выполнять «другие возможные задачи»? Давайте рассмотрим это, добавив возможность взаимодействия различных моделей (FSM) друг с другом. Вы можете определить набор событий и позволить каждому FSM зарегистрировать прослушиватель этих событий. Таким образом, если, например, корова входит в гекс местности, гекс может зарегистрировать слушателей для изменений перехода. Здесь это становится немного сложнее, потому что каждый FSM реализован на очень высоком уровне без каких-либо знаний о конкретной области, которую он скрывает. Однако вы можете добиться этого, если бы корова опубликовала список событий, и ячейка может зарегистрироваться, если увидит события, на которые она может реагировать. Хорошая иерархия семейства событий - это хорошая инвестиция.
Вы можете продвинуться еще глубже, смоделировав уровни питательных веществ и цикл роста травы, с ... как вы уже догадались ... FSM травы, встроенной в собственную модель участка местности.
Если вы продвигаете идею достаточно далеко, БОГу мало что нужно сделать, поскольку все аспекты в значительной степени управляются самостоятельно, освобождая время, чтобы тратить на более благочестивые вещи.
резюмировать
Как указано выше, FSM здесь не является решением, а просто средством для иллюстрации того, что решение такой проблемы не в коде, а в том, как вы моделируете свою проблему. Есть, скорее всего, другие решения, которые возможны и, скорее всего, намного лучше, чем мое предложение FSM. Однако подход «фракталы» остается хорошим способом справиться с этой трудностью. Если все сделано правильно, вы можете динамически распределять более глубокие уровни там, где это имеет значение, а также предлагать более простые модели, где это имеет значение. Вы можете ставить в очередь изменения и применять их, когда ресурсы становятся более доступными. В последовательности действий, возможно, не так важно рассчитывать перенос питательных веществ от коровы к травяному пятну. Однако вы можете записать эти переходы и применить изменения позднее или просто приблизить их с помощью обоснованного предположения, просто заменив механизмы правил или, возможно, заменив реализацию FSM вместе с более простой наивной версией для элементов, которые не находятся в прямой области интерес (эта корова на другом конце поля), чтобы позволить более подробные взаимодействия, чтобы получить фокус и большую долю ресурсов. Все это, не пересматривая систему в целом; Так как каждая деталь хорошо изолирована, становится проще создать замену, ограничивающую или расширяющую глубину вашей модели. Используя стандартный дизайн, вы можете опираться на это и максимизировать инвестиции, сделанные в специальные инструменты, такие как DSL, для определения правил или стандартного словаря для событий, снова начиная с очень высокого уровня и добавляя уточнения по мере необходимости. Так как каждая деталь хорошо изолирована, становится проще создать замену, ограничивающую или расширяющую глубину вашей модели. Используя стандартный дизайн, вы можете опираться на это и максимизировать инвестиции, сделанные в специальные инструменты, такие как DSL, для определения правил или стандартного словаря для событий, снова начиная с очень высокого уровня и добавляя уточнения по мере необходимости. Так как каждая деталь хорошо изолирована, становится проще создать замену, ограничивающую или расширяющую глубину вашей модели. Используя стандартный дизайн, вы можете опираться на это и максимизировать инвестиции, сделанные в специальные инструменты, такие как DSL, для определения правил или стандартного словаря для событий, снова начиная с очень высокого уровня и добавляя уточнения по мере необходимости.
Я хотел бы привести пример кода, но это все, что я могу позволить себе сделать прямо сейчас.
источник
Похоже, что все эти условные операторы, о которых вы говорите, должны быть данными, которые настраивают вашу программу, а не частью самой вашей программы. Если вы можете обращаться с ними таким образом, то вы сможете изменить способ работы вашей программы, просто изменив ее конфигурацию вместо того, чтобы изменять код и перекомпилировать каждый раз, когда вы хотите улучшить свою модель.
Существует множество различных способов моделирования реального мира в зависимости от характера вашей проблемы. Ваши различные условия могут стать правилами или ограничениями, которые применяются к симуляции. Вместо того, чтобы иметь код, который выглядит так:
вместо этого вы можете иметь код, который выглядит следующим образом:
Или, если вы можете разработать линейную программу, которая моделирует поведение коровы с учетом количества входных данных, каждое ограничение может стать линией в системе уравнений. Затем вы можете превратить это в марковскую модель, которую вы можете повторить.
Трудно сказать, каков правильный подход для вашей ситуации, но я думаю, что вам будет намного легче, если вы считаете, что ваши ограничения являются входными данными для вашей программы, а не для кода.
источник
Никто не упомянул об этом, поэтому я подумал, что скажу это прямо:
Тысячи правил «Если .. Тогда .. Остальное» - признак плохо разработанного приложения.
В то время как доменное представление данных может выглядеть как эти правила, вы абсолютно уверены, что ваша реализация должна напоминать доменное представление?
источник
Пожалуйста, используйте программное обеспечение / компьютерные языки, которые подходят для этой задачи. Matlab очень часто используется для моделирования сложных систем, где вы можете иметь буквально тысячи условий. Не используя предложения if / then / else, но путем численного анализа. R - это компьютерный язык с открытым исходным кодом, который наполнен инструментами и пакетами для того же. Но это означает, что вам также необходимо пересмотреть свою модель в более математических терминах, чтобы вы могли включить в модели как основные влияния, так и взаимодействия между ними.
Если вы еще этого не сделали, пожалуйста, пройдите курс о моделировании и симуляции. Последнее, что вы должны сделать, это подумать о написании такой модели с точки зрения «если - то - еще». У нас есть цепочки Монте-Карло Маркова, машины опорных векторов, нейронные сети, анализ скрытых переменных, ... Пожалуйста, не забрасывайте себя на 100 лет назад, игнорируя богатство доступных инструментов моделирования.
источник
Механизмы правил могут помочь, потому что, если существует так много правил if / then, может быть полезно получить их все в одном месте вне программы, где пользователи могут редактировать их без необходимости знания языка программирования. Также могут быть доступны инструменты визуализации.
Вы также можете посмотреть на решения логического программирования (например, Prolog). Вы можете быстро изменить список операторов if / then и заставить его выполнять такие вещи, как поиск, приведет ли любая комбинация входных данных к определенным результатам и т. Д. Кроме того, в логике предикатов первого порядка может быть чище, чем в процедурном коде (или чем в объектно-ориентированный код).
источник
Меня вдруг осенило:
Вам необходимо использовать дерево обучения принятию решений (алгоритм ID3).
Весьма вероятно, что кто-то реализовал это на вашем языке. Если нет, вы можете портировать существующую библиотеку
источник
Это скорее вики-ответ сообщества, объединяющий различные инструменты моделирования, предложенные другими ответами. Я только добавил дополнительные ссылки на ресурсы.
Я не думаю, что есть необходимость повторять, что вы должны использовать другой подход к тысячам жестко закодированных операторов if / else.
источник
Каждое большое приложение содержит тысячи
if-then-else
операторов, не считая других элементов управления потоками, и эти приложения по-прежнему отлажены и поддерживаются, несмотря на их сложность.Кроме того, количество операторов не делает поток непредсказуемым . Асинхронное программирование делает. Если вы используете детерминированные алгоритмы синхронно, вы будете иметь 100% предсказуемое поведение, каждый раз.
Вероятно, вам следует лучше объяснить, что вы пытаетесь сделать в Stack Overflow или Code Review, чтобы люди могли предложить вам точные методы рефакторинга . Вы также можете задать более точные вопросы, например, «Как мне избежать вложения слишком большого количества
if
утверждений <учитывая фрагмент кода>».источник
if
утверждений быстро становятся в лучшем случае громоздкими, поэтому требуется лучший подход.Сделайте ваше приложение управляемым, разработав его хорошо. Создайте свое приложение, разделив различную бизнес-логику на отдельные классы / модули. Напишите модульные тесты, которые тестируют каждый из этих классов / модулей в отдельности. Это очень важно и поможет вам обеспечить реализацию бизнес-логики, как ожидается.
источник
Вероятно, не будет единого способа спроектировать выход из вашей проблемы, но вы можете управлять сложностью этого по частям, если вы попытаетесь выделить различные области, где вы обнаружите, что пишете большие блоки операторов if и применяете решения к каждой из этих небольших проблем.
Посмотрите на методы, как правила, о которых говорили в рефакторинге для способов разбить большие условные выражения на управляемые куски - например, несколько операторов с общим интерфейсом могут заменить оператор case.
Ранний выход тоже очень помогает. Если у вас есть условия ошибки, уберите их в начале функции, выдав исключение или вернув вместо того, чтобы позволить им вложиться.
Если вы разбиваете свои условия на функции предикатов, может быть легче отслеживать их. Кроме того, если вы можете получить их в стандартной форме, может быть возможно получить их в структуре данных, которая создается динамически, а не жестко закодированной.
источник
Я бы предложил вам использовать механизм правил. В случае Java может быть полезен jBPM или Oracle BPM. Механизмы правил в основном позволяют настраивать приложение через XML.
источник
Проблема не решается с помощью «правил», описанных процедурным кодом «если-то» или многочисленными решениями правил, разработанными для бизнес-приложений. Машинное обучение предоставляет ряд механизмов для моделирования таких сценариев.
По сути, необходимо сформулировать некую схему для конкретного представления факторов (например, солнца, ветра, источника пищи, внезапных событий и т. Д.), Влияющих на «систему» (т. Е. Коров на пастбище). Несмотря на ошибочное мнение о том, что можно создать реально ценное функциональное представление, в отличие от дискретного, ни один компьютер в реальном мире (включая нервную систему человека) не основан на реальной стоимости или не вычисляет на основе реальных ценностей.
Если у вас есть числовое представление для соответствующих факторов, вы можете построить любую из нескольких математических моделей. Я бы предложил двудольный график, где один набор узлов представляет коров, а другой - единицу площади пастбищ. Корова в любом случае занимает некоторую единицу площади пастбища. Тогда для каждой коровы существует полезное значение, связанное с текущим и всеми другими единицами пастбища. Если модель предполагает, что корова стремится оптимизировать (что бы это ни значило для коровы) полезную ценность своей единицы пастбища, тогда коровы будут переходить от единицы к единице в попытке оптимизировать.
Клеточный автомат работает хорошо для выполнения модели. Основная математика в реальном мире математики, мотивирующая движение коровы, - это модель градиента поля. Коровы переходят из позиций воспринимаемой более низкой полезности в позиции воспринимаемой более высокой полезности.
Если кто-то вносит изменения в окружающую среду в систему, он не переходит к устойчивому решению положения коров. Это также станет моделью, к которой могут быть применены аспекты теории игр; не то, чтобы такое обязательно добавило бы много к этому случаю.
Преимущество здесь в том, что забой коров или приобретение новых коров можно легко контролировать, вычитая и добавляя «коровьи» клетки к двудольному графику во время работы модели.
источник
Я не думаю, что вы должны определять так много утверждений if-else. С моей точки зрения, ваша проблема состоит из нескольких компонентов:
Он должен быть асинхронным или многопоточным, потому что у вас есть несколько коров с разными личностями, разной конфигурации. Каждая корова спрашивает себя, в каком направлении идти перед следующим ходом. На мой взгляд, код синхронизации - плохой инструмент для решения этой проблемы.
Конфигурация дерева решений постоянно меняется. Это зависит от положения фактической коровы, погоды, времени, рельефа местности и т. Д. Вместо того, чтобы строить сложное, если-либо, дерево, я думаю, что мы должны свести проблему к розе ветров или направлению - функции веса : рисунок 1 - направление - весовые функции по некоторым правилам
Корова всегда должна идти в направлении, которое имеет наибольшую суммарную массу. Таким образом, вместо построения большого дерева решений вы можете добавить набор правил (с разным направлением - функциями веса) для каждой коровы и просто обрабатывать результат каждый раз, когда вы спрашиваете направление. Вы можете перенастроить эти правила при каждом изменении позиции, или по прошествии времени, или вы можете добавить эти детали в качестве параметров, которые должно получить каждое правило. Это решение о реализации. Самый простой способ получить направление, добавить простой цикл от 0 ° до 360 ° с шагом 1 °. После этого вы можете посчитать суммарный вес каждого направления 360 и выполнить функцию max (), чтобы получить правильное направление.
Для этого не обязательно нужна нейронная сеть, только один класс для каждого правила, один класс для коров, может быть, для местности и т. Д. И один класс для сценария (например, 3 коровы с разными правилами и 1 конкретная местность). Рисунок 2 - корова приложения асинхронных узлов и соединений
примечание: вам, вероятно, понадобится система обмена сообщениями для реализации чего-то подобного
Таким образом, если создание коров не является частью вашей проблемы, вам не нужна нейронная сеть или генетические алгоритмы. Я не эксперт по ИИ, но, думаю, если вы хотите адаптировать своих коров к реальным, то вы можете сделать это просто с помощью генетического алгоритма и соответствующего набора правил. Если я хорошо понимаю, вам нужна популяция коров со случайными настройками правил. После этого вы можете сравнить поведение реальных коров с поведением вашей модели популяции и сохранить 10%, которые идут ближе всего к реальным. После этого вы можете добавить новые ограничения конфигурации правил для вашей фабрики коров, основываясь на 10%, которые вы сохранили, и добавить новых случайных коров в популяцию и т. Д., Пока не получите модель коровы, которая ведет себя так же, как настоящие ...
источник
Я бы добавил, что может быть так, что если у вас действительно есть тысячи ЕСЛИ ... ТОГДА правил, вы можете быть слишком точными. Что бы это ни стоило, разговоры о моделировании нейронной сети, которые я посещал, часто начинаются с заявления о том, как с помощью «простого набора правил» они могут генерировать довольно сложное и разумно соответствующее поведению поведение (в этих случаях реальных нейронов в действии). Итак, вы уверены, вам нужны тысячи условий? Я имею в виду, помимо 4-5 аспектов погоды, местоположения источников пищи, внезапных событий, стада и рельефа, у вас действительно будет много других переменных? Конечно, если бы вы попытались сделать все возможные комбинации сочетания этих условий, то вы могли бы легко иметь много тысяч правил, но это не правильный подход. Возможно, подход в стиле нечеткой логики, в котором различные факторы вносят смещение в положение каждой коровы, которое в сочетании с общим решением, позволит вам сделать это в гораздо меньшем количестве правил.
Я также согласен со всеми остальными, что набор правил должен быть отделен от общего потока кода, чтобы вы могли легко настроить его без изменения программы. Вы даже можете придумать конкурирующие наборы правил и посмотреть, как они справляются с реальными данными о движении коров. Звучит весело.
источник
Экспертные системы были упомянуты, которые являются областью ИИ. Чтобы немного подробнее остановиться на этом, ознакомление с механизмами вывода может помочь вам в этом. Поиск Google мог бы быть более полезным - написание DSL является простой частью, вы могли бы сделать это тривиально с парсером, таким как Gold Parser. Трудная часть состоит в том, чтобы создать дерево решений и эффективно выполнять их.
Многие медицинские системы уже используют эти двигатели, например британский веб-сайт NHS Direct .
Если вы являетесь .NET'er, то Infer.NET может быть полезен для вас.
источник
Поскольку вы смотрите на движение коровы, они застряли в направлении 360 градусов (коровы не могут летать.) У вас также есть скорость, с которой вы путешествуете. Это может быть определено как вектор.
Теперь, как вы справляетесь с такими вещами, как положение солнца, склон холма, громкий шум?
Каждая из степеней будет переменной, обозначающей желание идти в этом направлении. Скажем, что ветка щелкает справа от коровы под углом 90 градусов (при условии, что корова смотрит на 0 градусов). Желание идти направо будет падать, а желание идти 270 (слева) будет возрастать. Пройдите через все стимулы, добавляя или вычитая их влияние на желание коров идти в направлении. Как только все стимулы будут применены, корова пойдет в направлении наивысшего желания.
Вы также можете применять градиенты, чтобы стимулы не были бинарными. Например, холм не прямо вверх в одном направлении. Может быть, корова находится в долине или на дороге на холме, где ее плоскость была прямо впереди, на 45 * немного выше, на 90 * немного вниз. На 180 * крутой подъем в гору.
Затем вы можете отрегулировать вес события и направление его влияния. Вместо списка «если тогда», у вас есть один тест, ищущий макс. Кроме того, когда вы хотите добавить стимулы, вы можете просто применить их перед тестом, и вам не нужно иметь дело с добавлением все большей и большей сложности.
Вместо того, чтобы сказать, что корова пойдет в любом направлении 360, давайте просто разбить ее на 36 направлений. Каждое существо 10 градусов
Вместо того, чтобы сказать, что корова пойдет в любом направлении 360, давайте просто разбить ее на 36 направлений. Каждое существо 10 градусов. В зависимости от того, насколько конкретно вам нужно быть.
источник
Используйте ООП. Как насчет создания группы классов, которые обрабатывают базовые условия и запускают случайные методы для имитации того, что вы делаете.
Получить программиста, чтобы помочь.
источник
COW_METHODS
Кажется, что вызываемый класс является не чем иным, как набором слабо связанных методов. Где разделение интересов? Связанный с вопросом, как это помогает спрашивающему?