Оценщик логических правил - PullRequest
2 голосов
/ 29 октября 2008

По сути, у меня есть опрос, и люди часто отвечают на вопросы, такие как тест, и есть разные пути, пока это довольно просто, но я хотел сделать его более динамичным, чтобы у меня было общее правило для теста со всеми путями, чтобы было легче работать с оценщиком в настоящее время. просто разрешите AND, и каждое OR по существу становится другим правилом в наборе,

QuestionID, тогда я формирую кучу правил И, как так <rule id="1"> <true> <question ID=123> <question ID=124> </true> <false> <question ID=127> <question ID=128> </false> </rule> <rule id="2"><true> <question ID=123> <question ID=125> </true> <false> <question ID=127> </false> </rule>

это правило 1 гласит, что если на вопросы 123 и 124 дан ответ «истина», а 127, 128 «ложь», они проходят. ИЛИ (правило 2), если 123 и 125 истинны, а 127 ложны, они также проходят. Это становится утомительным, если есть много комбинаций, поэтому я хочу реализовать ИЛИ в логике, я просто не уверен, что лучший подход для этой проблемы.

Я думаю, что механизм правил слишком сложен, должен быть более простой способ, возможно, построить граф, как в LINQ, и затем оценить, чтобы проверить, проходят ли они,

спасибо!

- не специалист.

Ответы [ 4 ]

2 голосов
/ 29 октября 2008

Это не должно быть сложным: вы уже прошли большую часть пути, поскольку your и elements эффективно реализуют правило типа AND. Я хотел бы представить элемент, который может содержать и элементы.

В вашем распоряжении вы могли бы:

  • Класс RuleBase с методом "public abstract bool Evaluate ()"
  • Классы TrueRule, FalseRule и OrRule, которые содержат списки объектов RuleBase
  • Класс QuestionRule, который относится к конкретному вопросу

Вы бы применили метод Evaluate для каждого из них следующим образом:

  • TrueRule: возвращает true, только если все содержащиеся в нем правила возвращают true из Evaluate
  • FalseRule: возвращает true, только если все содержащиеся в нем правила возвращают false из Evaluate
  • OrRule: возвращает true, если хотя бы одно из содержащихся в нем правил возвращает true из Evaluate
  • QuestionRule: возвращает ответ на исходный вопрос

Эта иерархия классов реализует простое абстрактное синтаксическое дерево (AST). LINQ в форме класса System.Expressions.Expression делает почти то же самое, но полезно написать свой собственный, если неясно, как все сходится.

1 голос
/ 18 апреля 2011

Если вы используете правильный движок правил, который поддерживает вывод, он будет более эффективным и расширяемым.

Взгляните на http://www.flexrule.com, который представляет собой гибкий, расширяемый механизм правил, поддерживающий три типа правил. Процедурные правила, правила логического вывода и потока правил могут быть выведены из вашего приложения и выполнены с использованием этой инфраструктуры.

0 голосов
/ 29 октября 2008

Я бы предложил поставить ответы на вопросы, а не использовать true и false для группировки вопросов. Я думаю, что это делает для XML, который легче читать, которая является дискуссионным. Что не подлежит обсуждению, так это то, что он позволяет оценивать элемент question независимо, т.е. без знания контекста, в котором вы пытаетесь его оценить. Это упрощает код.

Я бы также взял страницу из XML-схемы и реализовал вашу логику ИЛИ как элемент choice. Элемент choice имеет значение true, если любой из его дочерних элементов равен true. Вы можете, конечно, вкладывать их:

<rule id="1">
   <question id="123" answer="true" />
   <question id="124" answer="false" />
   <choice id="1">
      <question id="125" answer='true' />
      <choice id="2">
         <question id="126" answer='false' />
         <question id="127" answer='false' />
      </choice>
   </choice>
</rule>

Это дает вам четыре довольно простых для реализации метода, каждый из которых используется предшествующим ему:

  • bool GetProvidedAnswer(int questionID)
  • bool IsQuestionCorrect(XmlElement question)
  • bool IsChoiceCorrect(XmlElement choice)
  • bool IsRuleSatisfied(XmlElement rule)

Структура XML делает эти методы довольно простыми для реализации:

 bool IsRuleSatisfied(XmlElement rule)
 {
    bool satisfied = true;
    foreach (XmlElement child in rule.SelectNodes("*"))
    {
       if (child.Name == "question")
       {
          satisfied = satisfied && IsQuestionCorrect(child);
       }
       if (child.Name == "choice")
       {
          satisfed = satisfied && IsChoiceCorrect(child);
       }
       if (!satisfied)
       {
          return false;
       }
   }
   return true;
}

Возможно, стоит добавить List<XmlElement> к параметрам методов IsFooCorrect. (Если механизм правил находится в классе, вы можете сделать его полем класса.) Сделайте так, чтобы `все методы добавляли текущий элемент в список, если ответ неправильный. Затем вы можете просмотреть содержимое этого списка, чтобы точно знать, почему не удалось выполнить правило.

0 голосов
/ 29 октября 2008

Я не уверен, что полностью понимаю проблему, которую вы пытаетесь решить, но вы можете использовать простой XPath для получения идентификаторов:

Это даст вам все "истинные" идентификаторы, где идентификатор правила = 1: / Правило [@ ид = "1"] / истинного // @ ID

То же, что и выше, только оно дает вам ложные идентификаторы: / Правило [@ ид = "1"] / ложь // @ ID

Наконец, ссылка на введение в XPath в .NET http://www.developer.com/xml/article.php/3383961

Удачи

...