[jboss-svn-commits] JBL Code SVN: r15151 - labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Sun Sep 16 08:33:35 EDT 2007
Author: ge0ffrey
Date: 2007-09-16 08:33:33 -0400 (Sun, 16 Sep 2007)
New Revision: 15151
Added:
labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Score_calculation.xml
labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Solver_configuration.xml
labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/screenshotSolvedNQueens8.png
Modified:
labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Local_Search_Solver.xml
labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Solver_introduction.xml
Log:
section 2 & 3
Modified: labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Local_Search_Solver.xml
===================================================================
--- labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Local_Search_Solver.xml 2007-09-16 05:17:24 UTC (rev 15150)
+++ labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Local_Search_Solver.xml 2007-09-16 12:33:33 UTC (rev 15151)
@@ -30,4 +30,10 @@
<para>Drools-solver's local search implementation combines both and offers
additional support for benchmarking etc.</para>
</section>
+
+ <section>
+ <title>Getting started</title>
+
+ <para></para>
+ </section>
</section>
\ No newline at end of file
Added: labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Score_calculation.xml
===================================================================
--- labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Score_calculation.xml (rev 0)
+++ labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Score_calculation.xml 2007-09-16 12:33:33 UTC (rev 15151)
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<section>
+ <title>Score calculation with a rule engine</title>
+
+ <section>
+ <title>Rule based score calculation</title>
+
+ <para>Score calculation of a planning problem is based on constraints
+ (such as hard constraints, soft constraints, rewards, ...). A rules
+ engine, such as drools, make it easy to implement those constraints as
+ <emphasis>score rules</emphasis>.</para>
+
+ <para>Here's an example of a constraint implemented as a score rule in
+ drools:</para>
+
+ <example>
+ <title>Score rule for multiple queens on the same horizontal
+ line</title>
+
+ <programlisting>rule "multipleQueensHorizontal"
+ when
+ $q1 : Queen($id : id, $y : y);
+ $q2 : Queen(id > $id, y == $y);
+ then
+ // trigger a change in the score
+end</programlisting>
+ </example>
+
+ <para>This score rule will fire once for each 2 queens with the same
+ <literal>y</literal>. The <literal>(id > $id)</literal> condition is
+ needed to assure that for 2 queens a and b, it can only fire for (a,b) and
+ not for (b,a), (a,a) or (b,b).</para>
+
+ <para>It's recommended to use drools in forward-chaining mode (which is
+ the default), as for most solver implementations this will create the
+ effect of a <emphasis>delta based score calculation</emphasis> instead of
+ a full score calculation on each solution evaluation. For example, if
+ queen a moves from y <literal>0</literal> to <literal>3</literal>, it
+ won't bother to recalculate the "multiple queens on the same horizontal
+ line" constraint for queens with y <literal>1</literal> or
+ <literal>2</literal>. This is a huge performance gain. <emphasis
+ role="bold">Drools-solver gives you this huge performance gain without
+ forcing you to write very complicated delta based score calculation
+ algorithms.</emphasis> Just let the drools rule engine do the hard
+ work.</para>
+
+ <para><emphasis role="bold">Adding more constraints is scalable and
+ easy</emphasis> (if you understand the drools rule syntax). This allows
+ you to add it a bunch of soft constraint score rules on top of the hard
+ constraints score rules with few effort. For example, for a freight
+ routing problem you could add a soft constraint to avoid the certain
+ flagged highways at rush hour.</para>
+ </section>
+
+ <section>
+ <title>The ScoreCalculator interface</title>
+
+ <para>The <literal>ScoreCalculator</literal> interface allows the solver
+ to calculate the score of the currently evaluated solution. The score must
+ a <literal>Number</literal> instance and the instance type (for example
+ <literal>Double</literal> or <literal>Integer</literal>) must be stable
+ through the problem.</para>
+
+ <para>The solver aims to find the solution with the highest score. Most
+ planning problems tend to use negative scores (the amount of negative
+ constraints being broken) with an impossible perfect score of 0.</para>
+
+ <para>A <literal>ScoreCalculator</literal> instance is configured in the
+ solver configuration:</para>
+
+ <programlisting> <scoreCalculator>
+ <scoreCalculatorType>SIMPLE</scoreCalculatorType>
+ </scoreCalculator></programlisting>
+
+ <para>There are a couple of build-in <literal>ScoreCalculator</literal>
+ implementations:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>SIMPLE: A <literal>SimpleScoreCalculator</literal> instance
+ which has a <literal>setScore(Number)</literal> method for use in the
+ score rules.</para>
+ </listitem>
+
+ <listitem>
+ <para>HARD_AND_SOFT_CONSTRAINTS: A
+ <literal>HardAndSoftConstraintScoreCalculator</literal> instance,
+ which has a <literal>setHardConstraintsBroken(Number)</literal> and a
+ <literal>setSoftConstraintsBroken(Number)</literal> method for use in
+ the score rules.</para>
+ </listitem>
+
+ <listitem>
+ <para>DYNAMIC_HARD_AND_SOFT_CONSTRAINTS: A special
+ <literal>HardAndSoftConstraintScoreCalculator</literal> instance, for
+ more information see the javadocs. </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>You can plug in your own custom <literal>ScoreCalculator</literal>
+ too.</para>
+
+ <para>The <literal>ScoreCalculator</literal> instance is asserted into the
+ working memory as a global called <literal>scoreCalculator</literal>. Your
+ score rules will (indirectly) update that instance. Usually you 'll make a
+ single rule as an aggregation of the other rules to update the
+ score:</para>
+
+ <programlisting>global SimpleScoreCalculator scoreCalculator;
+
+// ...
+
+rule "multipleQueensHorizontal"
+ // ...
+end
+
+rule "multipleQueensAscendingDiagonal"
+ // ...
+end
+
+rule "multipleQueensDescendingDiagonal"
+ // ...
+end
+
+rule "constraintsBroken"
+ when
+ $hardCount : Number() from accumulate(
+ $w : ...,
+ count($w)
+ );
+ then
+ scoreCalculator.setScore(- $hardCount);
+end</programlisting>
+ </section>
+
+ <section>
+ <title>Tips and tricks</title>
+
+ <itemizedlist>
+ <listitem>
+ <para>If you know a certain constraint can never be broken, don't
+ bother writing a score rule for it. For example the NQueens example
+ doesn't have a "multipleQueensVertical" rule because a queen's
+ <literal>x</literal> never changes. </para>
+ </listitem>
+
+ <listitem>
+ <para>Verify that your score calculation happens in the correct Number
+ type. If you're making the sum of nothing but integer values, don't
+ let drools use Double's or your performance will hurt.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+</section>
\ No newline at end of file
Added: labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Solver_configuration.xml
===================================================================
--- labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Solver_configuration.xml (rev 0)
+++ labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Solver_configuration.xml 2007-09-16 12:33:33 UTC (rev 15151)
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<section>
+ <title>Solver configuration</title>
+
+ <section>
+ <title>The Solver interface</title>
+
+ <para>Every build-in solver implemented in drools-solver implements the
+ <literal>Solver</literal> interface:</para>
+
+ <programlisting>public interface Solver {
+
+ void setStartingSolution(Solution solution);
+
+ Number getBestScore();
+ Solution getBestSolution();
+
+ void solve();
+
+ // ...
+
+}</programlisting>
+
+ <para>Solving a planning problem with drools-solver consists out of 4
+ steps:</para>
+
+ <orderedlist>
+ <listitem>
+ <para>Build a solver, for example a tabu search solver for any NQueens
+ puzzle.</para>
+ </listitem>
+
+ <listitem>
+ <para>Set a starting solution on the solver, for example an 4 Queens
+ puzzle instance.</para>
+ </listitem>
+
+ <listitem>
+ <para>Solve it.</para>
+ </listitem>
+
+ <listitem>
+ <para>Get the best solution found by the solver.</para>
+ </listitem>
+ </orderedlist>
+
+ <para>A <literal>Solver</literal> should currently directly be accessed
+ from a single thread. Support from accessing it from a different thread,
+ for example to finish solving early or to change the problem facts in
+ real-time, will be added in future releases.</para>
+ </section>
+
+ <section>
+ <title>Building a solver</title>
+
+ <para>You can build a <literal>Solver</literal> instance with the
+ <literal>XmlSolverConfigurer</literal> by configuring it with a solver
+ configuration xml file:</para>
+
+ <programlisting> XmlSolverConfigurer configurer = new XmlSolverConfigurer();
+ configurer.configure("/org/drools/solver/examples/nqueens/solver/nqueensSolverConfig.xml");
+ Solver solver = configurer.buildSolver();</programlisting>
+
+ <para>A basic solver configuration file looks something like this:</para>
+
+ <programlisting><?xml version="1.0" encoding="UTF-8"?>
+<localSearchSolver>
+ <scoreDrl>/org/drools/solver/examples/nqueens/solver/nQueensScoreRules.drl</scoreDrl>
+ <scoreCalculator>
+ <scoreCalculatorType>SIMPLE</scoreCalculatorType>
+ </scoreCalculator>
+ <finish>
+ <feasableScore>0.0</feasableScore>
+ </finish>
+ <selector>
+ <moveFactoryClass>org.drools.solver.examples.nqueens.solver.NQueensMoveFactory</moveFactoryClass>
+ </selector>
+ <accepter>
+ <completeSolutionTabuSize>1000</completeSolutionTabuSize>
+ </accepter>
+ <forager>
+ <foragerType>MAX_SCORE_OF_ALL</foragerType>
+ </forager>
+</localSearchSolver></programlisting>
+
+ <para>This is a tabu search configuration (which is a form of local
+ search) for NQueens. We 'll explain the various parts of a configuration
+ later in this manual.</para>
+
+ <para><emphasis role="bold">Drools-solver makes it relatively easy to
+ switch a solver type just by changing the configuration.</emphasis>
+ There's even a benchmark utility which allows you to play out different
+ configurations against each other and report the most appropriate
+ configuration for your problem. You could for example play out tabu search
+ versus simulated annealing, on a set of instances of your planning
+ problem.</para>
+ </section>
+
+ <section>
+ <title>The Solution interface</title>
+
+ <para>A Solver can only solve 1 problem at a time. One problem has a lot
+ of solutions, but few optimal solutions.</para>
+
+ <para>You need to present the problem as a starting
+ <literal>Solution</literal> instance to the Solver. Usually you will make
+ that starting solution with a simple filler algorithm, for example: all
+ queens on a different x and all on y = 0. It will probably be far from
+ optimal, but that's ok, as it's the solver's job to find a much better
+ solution.</para>
+
+ <para>Here is the <literal>Solution</literal> interface:</para>
+
+ <programlisting>public interface Solution {
+
+ Solution cloneSolution();
+
+ Collection<? extends Object> getFacts();
+
+}</programlisting>
+
+ <para>Most solvers use the <literal>cloneSolution()</literal> method to
+ clone the solution each time they encounter a new best solution. The
+ <literal>cloneSolution()</literal> method should clone no more and no less
+ than the parts of the <literal>Solution</literal> that can change during
+ solving. For example, in the lesson schedule example the lessons are
+ cloned, but teachers, groups and timeslots are not cloned because only a
+ lesson's appointed timeslot changes during solving:</para>
+
+ <programlisting> /**
+ * Clone will only deep copy the lessons
+ */
+ public LessonSchedule cloneSolution() {
+ LessonSchedule clone = new LessonSchedule();
+ clone.timeslotList = timeslotList; // No Deep copy
+ clone.teacherList = teacherList; // No Deep copy
+ clone.groupList = groupList; // No Deep copy
+ List<Lesson> clonedLessonList = new ArrayList<Lesson>(lessonList.size());
+ for (Lesson lesson : lessonList) {
+ clonedLessonList.add(lesson.clone());
+ }
+ clone.lessonList = clonedLessonList;
+ return clone;
+ }</programlisting>
+
+ <para>The <literal>NQueens</literal> implementation just clones all
+ <literal>Queen</literal> instances.</para>
+
+ <para>All Objects returned by the <literal>getFacts()</literal> method
+ will be asserted into the drools working memory. Those facts can be used
+ by the score calculation rules. For example, <literal>NQueens</literal>
+ just returns all <literal>Queen</literal> instances.</para>
+
+ <programlisting> public Collection<? extends Object> getFacts() {
+ return queenList;
+ }</programlisting>
+ </section>
+
+ <section>
+ <title>Solving a problem</title>
+
+ <para>Solving a problem is quite easy once you have a solver and the
+ starting solution:</para>
+
+ <programlisting> solver.setStartingSolution(startingSolution);
+ solver.solve();
+ Solution bestSolution = solver.getBestSolution();</programlisting>
+
+ <para>The <literal>solve()</literal> method will take a long time
+ (depending on the problem size and the solver configuration). After a
+ problem is solved, you can reuse the same solver to solve another problem
+ (of the same problem type).</para>
+ </section>
+</section>
\ No newline at end of file
Modified: labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Solver_introduction.xml
===================================================================
--- labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Solver_introduction.xml 2007-09-16 05:17:24 UTC (rev 15150)
+++ labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Solver_introduction.xml 2007-09-16 12:33:33 UTC (rev 15151)
@@ -9,6 +9,32 @@
module of drools-solver. The API is far from stable and backward
incompatible changes occur now and then. A recipe to upgrade and apply
those API changes between versions will be maintained soon.</para>
+
+ <para>No releases have been made yet, but you can easily build it from
+ source yourself by checking out drools and building with the solver
+ profile:</para>
+
+ <programlisting>$ svn checkout http://anonsvn.labs.jboss.com/labs/jbossrules/trunk/ drools
+...
+$ cd drools
+$ mvn -Psolver clean install
+...</programlisting>
+
+ <para>After that, you can run an example directly from the command line
+ like this:</para>
+
+ <programlisting>$ cd drools-solver/drools-solver-examples/
+$ mvn exec:java -Dexec.mainClass="org.drools.solver.examples.nqueens.app.NQueensApp"
+...</programlisting>
+
+ <para>Here's a screenshot of the NQueens example, which is the simplest of
+ all the examples:</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="screenshotSolvedNQueens8.png" />
+ </imageobject>
+ </mediaobject>
</section>
<section>
@@ -55,7 +81,7 @@
</listitem>
</itemizedlist>
- <para>Usually a planning problem consists out of a number of constraints.
+ <para>A planning problem consists out of a number of constraints.
Generally, there are 3 types of constraints:</para>
<itemizedlist>
@@ -81,27 +107,28 @@
</itemizedlist>
<para>The constraints define the score function of a planning problem.
- Usually a planning problems has a very large number of possible solutions.
- Each solution has a score. Usually, most solutions are not feasible,
+ Planning problems tend to have a very large number of possible solutions.
+ Each solution has a score. Most of those solutions are not feasible,
because they break a negative hard constraint. Usually, of all the
- feasible solutions (if any), there is only 1 or very few optimal
- solutions.</para>
+ feasible solutions (if any), there is only 1 optimal solution, but
+ sometimes there are a few.</para>
<para>The drools rule engine turns out to be a very good way to implement
- a score function a number of rule constraints.</para>
+ a score function based on a number of rule constraints.</para>
</section>
<section>
<title>Types of solvers</title>
<para>Different solvers solve problems in different ways. Each type has
- advantages and disadvantages. These are a few of the solver types.</para>
+ advantages and disadvantages. We 'll roughly discuss a few of the solver
+ types. You can safely skip this section.</para>
<section>
<title>Brute force</title>
<para>Brute force creates and evaluates every possible solution, usually
- by create a search tree.</para>
+ by creating a search tree.</para>
<para>Advantages:</para>
@@ -150,7 +177,7 @@
<itemizedlist>
<listitem>
- <para>It scales very badly.</para>
+ <para>It still scales very badly.</para>
</listitem>
</itemizedlist>
@@ -340,11 +367,12 @@
</mediaobject>
</figure>
- <para>A Queen instance has an x (its column, for example: 1 is column A,
- 2 is column B, ...) and a y (its row, for example: 1 is row 1, 2 is row
- 2, ...). Based on the x and y, the ascending diagonal line as well as
- the descending diagonal line can be calculated. The x and y indexes
- start from the upper left corner of the chessboard.</para>
+ <para>A <literal>Queen</literal> instance has an x (its column, for
+ example: 0 is column A, 1 is column B, ...) and a y (its row, for
+ example: 0 is row 1, 1 is row 2, ...). Based on the x and y, the
+ ascending diagonal line as well as the descending diagonal line can be
+ calculated. The x and y indexes start from the upper left corner of the
+ chessboard.</para>
<table>
<title>A solution for the 4 queens puzzle show in the domain
@@ -377,23 +405,23 @@
<entry>A2</entry>
+ <entry>0</entry>
+
<entry>1</entry>
- <entry>2</entry>
+ <entry>1 (**)</entry>
- <entry>3 (**)</entry>
-
<entry>-1</entry>
</row>
<row>
<entry>B1</entry>
- <entry>2</entry>
+ <entry>1</entry>
- <entry>1 (*)</entry>
+ <entry>0 (*)</entry>
- <entry>3 (**)</entry>
+ <entry>1 (**)</entry>
<entry>1</entry>
</row>
@@ -401,11 +429,11 @@
<row>
<entry>C3</entry>
- <entry>3</entry>
+ <entry>2</entry>
- <entry>3</entry>
+ <entry>2</entry>
- <entry>6</entry>
+ <entry>4</entry>
<entry>0</entry>
</row>
@@ -413,11 +441,11 @@
<row>
<entry>D1</entry>
- <entry>4</entry>
+ <entry>3</entry>
- <entry>1 (*)</entry>
+ <entry>0 (*)</entry>
- <entry>5</entry>
+ <entry>3</entry>
<entry>3</entry>
</row>
@@ -425,10 +453,10 @@
</tgroup>
</table>
- <para>A single NQueens instance contains a list of all Queens. It is
- effectively the <emphasis>Solution</emphasis> object which will be
- supplied to and retrieved from drools-solver. Notice that in the 4
- queens example, NQueens's <literal>getN()</literal> method will always
+ <para>A single <literal>NQueens</literal> instance contains a list of
+ all Queens. It is the <literal>Solution</literal> implementation which
+ will be supplied to and retrieved from drools-solver. Notice that in the
+ 4 queens example, NQueens's <literal>getN()</literal> method will always
return 4.</para>
<para>You can find the source code of this example (as well as well as
Added: labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/screenshotSolvedNQueens8.png
===================================================================
(Binary files differ)
Property changes on: labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/screenshotSolvedNQueens8.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
More information about the jboss-svn-commits
mailing list