[jboss-svn-commits] JBL Code SVN: r30780 - in labs/jbossrules/trunk/drools-docs/drools-docs-planner: src/main/docbook/en-US and 6 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Sun Dec 20 11:39:22 EST 2009


Author: ge0ffrey
Date: 2009-12-20 11:39:21 -0500 (Sun, 20 Dec 2009)
New Revision: 30780

Added:
   labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Benchmarking_and_tweaking/
   labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Benchmarking_and_tweaking/Section-Benchmarking_and_tweaking.xml
   labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Local_search/
   labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Local_search/Section-Local_search.xml
   labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Planner_configuration/
   labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Planner_configuration/Section-Planner_configuration.xml
   labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Planner_introduction/
   labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Planner_introduction/Section-Planner_introduction.xml
   labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Score_calculation/
   labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Score_calculation/Section-Score_calculation.xml
   labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Use_cases_and_examples/
   labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Use_cases_and_examples/Section-Use_cases_and_examples.xml
Removed:
   labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Solver/
Modified:
   labs/jbossrules/trunk/drools-docs/drools-docs-planner/pom.xml
   labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/master.xml
Log:
refactor drools planner manual into multiple chapters

Modified: labs/jbossrules/trunk/drools-docs/drools-docs-planner/pom.xml
===================================================================
--- labs/jbossrules/trunk/drools-docs/drools-docs-planner/pom.xml	2009-12-20 13:18:11 UTC (rev 30779)
+++ labs/jbossrules/trunk/drools-docs/drools-docs-planner/pom.xml	2009-12-20 16:39:21 UTC (rev 30780)
@@ -11,7 +11,6 @@
   </parent>  
   
     <artifactId>drools-docs-planner</artifactId>
-
     <packaging>jdocbook</packaging>
     <name>Drools :: Documentation :: Drools :: Planner</name>
     <description>Drools Planner Documentation</description>

Copied: labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Benchmarking_and_tweaking/Section-Benchmarking_and_tweaking.xml (from rev 30778, labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Solver/Section-Benchmarking_and_tweaking.xml)
===================================================================
--- labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Benchmarking_and_tweaking/Section-Benchmarking_and_tweaking.xml	                        (rev 0)
+++ labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Benchmarking_and_tweaking/Section-Benchmarking_and_tweaking.xml	2009-12-20 16:39:21 UTC (rev 30780)
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
+                             http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd"
+         version="5.0" xml:base="./">
+
+  <title>Benchmarking and tweaking</title>
+
+  <section>
+    <title>Finding the best configuration</title>
+
+    <para>Drools-solver supports several solver types, but you're probably wondering which is the best one? Although
+      some solver types generally perform better then others, it really depends on your problem domain. Most solver types
+      also have settings which can be tweaked. Those settings can influence the results of a solver a lot, although most
+      settings perform pretty good out-of-the-box.
+    </para>
+
+    <para>Luckily, drools-solver includes with a benchmarker, which allows you to play out different solver types and
+      different settings against each other, so you can pick the best configuration for your problem domain.
+    </para>
+  </section>
+
+  <section>
+    <title>Building a Benchmarker</title>
+
+    <para>You can build a
+      <literal>Benchmarker</literal>
+      instance with the<literal>XmlSolverBenchmarker</literal>.
+      Configure it with a benchmarker configuration xml file:
+    </para>
+
+    <programlisting>XmlSolverBenchmarker benchmarker = new XmlSolverBenchmarker();
+      benchmarker.configure("/org/drools/solver/examples/nqueens/benchmark/nqueensSolverBenchmarkConfig.xml");
+      benchmarker.benchmark();
+      benchmarker.writeResults(resultFile);
+    </programlisting>
+
+    <para>A basic benchmarker configuration file looks something like this:</para>
+
+    <programlisting>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
+      &lt;solverBenchmarkSuite&gt;
+      &lt;solvedSolutionFilesDirectory&gt;local/data/nqueens/solved&lt;/solvedSolutionFilesDirectory&gt;
+
+      &lt;inheritedUnsolvedSolutionFile&gt;data/nqueens/unsolved/unsolvedNQueens32.xml&lt;/inheritedUnsolvedSolutionFile&gt;
+      &lt;inheritedUnsolvedSolutionFile&gt;data/nqueens/unsolved/unsolvedNQueens64.xml&lt;/inheritedUnsolvedSolutionFile&gt;
+      &lt;inheritedLocalSearchSolver&gt;
+      &lt;scoreDrl&gt;/org/drools/solver/examples/nqueens/solver/nQueensScoreRules.drl&lt;/scoreDrl&gt;
+      &lt;scoreDefinition&gt;
+      &lt;scoreDefinitionType&gt;SIMPLE&lt;/scoreDefinitionType&gt;
+      &lt;/scoreDefinition&gt;
+      &lt;termination&gt;
+      &lt;maximumSecondsSpend&gt;20&lt;/maximumSecondsSpend&gt;
+      &lt;/termination&gt;
+      &lt;selector&gt;
+      &lt;moveFactoryClass&gt;org.drools.solver.examples.nqueens.solver.move.factory.NQueensMoveFactory&lt;/moveFactoryClass&gt;
+      &lt;/selector&gt;
+      &lt;forager&gt;
+      &lt;foragerType&gt;MAX_SCORE_OF_ALL&lt;/foragerType&gt;
+      &lt;/forager&gt;
+      &lt;/inheritedLocalSearchSolver&gt;
+
+      &lt;solverBenchmark&gt;
+      &lt;name&gt;Solution tabu&lt;/name&gt;
+      &lt;localSearchSolver&gt;
+      &lt;accepter&gt;
+      &lt;completeSolutionTabuSize&gt;1000&lt;/completeSolutionTabuSize&gt;
+      &lt;/accepter&gt;
+      &lt;/localSearchSolver&gt;
+      &lt;/solverBenchmark&gt;
+      &lt;solverBenchmark&gt;
+      &lt;name&gt;Move tabu 5&lt;/name&gt;
+      &lt;localSearchSolver&gt;
+      &lt;accepter&gt;
+      &lt;completeMoveTabuSize&gt;5&lt;/completeMoveTabuSize&gt;
+      &lt;/accepter&gt;
+      &lt;/localSearchSolver&gt;
+      &lt;/solverBenchmark&gt;
+      &lt;solverBenchmark&gt;
+      &lt;name&gt;Move tabu 7&lt;/name&gt;
+      &lt;localSearchSolver&gt;
+      &lt;accepter&gt;
+      &lt;completeMoveTabuSize&gt;7&lt;/completeMoveTabuSize&gt;
+      &lt;/accepter&gt;
+      &lt;/localSearchSolver&gt;
+      &lt;/solverBenchmark&gt;
+      &lt;solverBenchmark&gt;
+      &lt;name&gt;Solution tabu and move tabu 7&lt;/name&gt;
+      &lt;localSearchSolver&gt;
+      &lt;accepter&gt;
+      &lt;completeSolutionTabuSize&gt;1000&lt;/completeSolutionTabuSize&gt;
+      &lt;completeMoveTabuSize&gt;7&lt;/completeMoveTabuSize&gt;
+      &lt;/accepter&gt;
+      &lt;/localSearchSolver&gt;
+      &lt;/solverBenchmark&gt;
+      &lt;/solverBenchmarkSuite&gt;</programlisting>
+
+    <para>This benchmarker will try 4 configurations (1 solution tabu, 2 move tabu's and 1 solution-move tabu) on 2 data
+      sets (32 and 64 queens), so it will run 8 solvers.
+    </para>
+
+    <para>Every
+      <literal>solverBenchmark</literal>
+      entity contains a solver configuration (for example a local search
+      solver) and one or more
+      <literal>unsolvedSolutionFile</literal>
+      entities. It will run the solver configuration on
+      each of those unsolved solution files. A
+      <literal>name</literal>
+      is optional and generated if absent. The common
+      part of multiple
+      <literal>solverBenchmark</literal>
+      entities can be extracted to the
+      <literal>inherited</literal>
+      entities and can be overwritten per
+      <literal>solverBenchmark</literal>
+      entity.
+    </para>
+
+    <para>If you specify a
+      <literal>solvedSolutionFilesDirectory</literal>
+      (relative to the working directory), the best
+      solution of each solver run will be written to that directory.
+    </para>
+  </section>
+</chapter>


Property changes on: labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Benchmarking_and_tweaking/Section-Benchmarking_and_tweaking.xml
___________________________________________________________________
Name: svn:executable
   + *

Copied: labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Local_search/Section-Local_search.xml (from rev 30778, labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Solver/Section-Local_Search_Solver.xml)
===================================================================
--- labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Local_search/Section-Local_search.xml	                        (rev 0)
+++ labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Local_search/Section-Local_search.xml	2009-12-20 16:39:21 UTC (rev 30780)
@@ -0,0 +1,771 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
+                             http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd"
+         version="5.0" xml:base="./">
+
+  <title>Local search solver</title>
+
+  <section>
+    <title>Overview</title>
+
+    <para>In number of possible solutions for a planning problem can be mind blowing. For example:</para>
+
+    <itemizedlist>
+      <listitem>
+        <para>4 queens has 256 possible solutions (<literal>n ^ n</literal>) and 2 optimal solutions.</para>
+      </listitem>
+
+      <listitem>
+        <para>5 queens has 3125 possible solutions (<literal>n ^ n</literal>) and 1 optimal solution.</para>
+      </listitem>
+
+      <listitem>
+        <para>8 queens has 16777216 possible solutions (<literal>n ^ n</literal>) and 92 optimal solutions.</para>
+      </listitem>
+
+      <listitem>
+        <para>Most real-life planning problems have an incredible number of possible solutions and only 1 optimal
+        solution.</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>An algorithm that checks every possible solution (even with pruning) can easily run for billions of years on a
+    single real-life planning problem. Most of the time, we are happy with a feasible solution found in a limited amount
+    of time. Local search tends to find a feasible solution relatively fast. Because it acts very much like a human, it
+    is also pretty natural to program.</para>
+
+    <para>Local search solves a problem by making a move on the current solution which changes it into a better
+    solution. It does that number of times till it is satisfied with the solution. It starts with the starting
+    solution.</para>
+
+    <para>A local search algorithm and the drools rule engine turn out to be a really nice combination, because:</para>
+
+    <itemizedlist>
+      <listitem>
+        <para>A rule engine such as Drools is <emphasis role="bold">great for calculating the score</emphasis> of a
+        solution of a planning problem. It make it easy to add additional soft or hard constraints such as "a teacher
+        shouldn't teach more then 7 hours a day". However it tends to be too complex to use to actually find new
+        solutions.</para>
+      </listitem>
+
+      <listitem>
+        <para>A local search algorithm is <emphasis role="bold">great at finding new improving solutions</emphasis> for
+        a planning problem, without brute-forcing every possibility. However it needs to know the score of a solution
+        and normally offers no support in calculating that score.</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>Drools-solver's local search implementation combines both. On top of that, it also offers additional support
+    for benchmarking etc.</para>
+  </section>
+
+  <section>
+    <title>A move</title>
+
+    <para>A move is the change from a solution A to a solution B. For example, below you can see a single move on the
+    starting solution of 4 queens that moves a single queen to another row:</para>
+
+    <figure>
+      <title>A single move (4 queens example)</title>
+
+      <mediaobject>
+        <imageobject>
+          <imagedata fileref="images/Chapter-Local_search/singleMoveNQueens04.png" format="PNG"></imagedata>
+        </imageobject>
+      </mediaobject>
+    </figure>
+
+    <para>A move can have a small or large impact. In the above example, the move of queen <emphasis>C0 to C2</emphasis>
+    is a small move. Some moves are the same move type. These are some possibilities for move types in n queens:</para>
+
+    <itemizedlist>
+      <listitem>
+        <para>Move a single queen to another row. This is a small move. For example, move queen <emphasis>C0 to
+        C2</emphasis>.</para>
+      </listitem>
+
+      <listitem>
+        <para>Move all queens a number of rows down or up. This a big move.</para>
+      </listitem>
+
+      <listitem>
+        <para>Move a single queen to another column. This is a small move. For example, move queen <emphasis>C2 to
+        A0</emphasis> (placing it on top of queen A0).</para>
+      </listitem>
+
+      <listitem>
+        <para>Add a queen to the board at a certain row and column.</para>
+      </listitem>
+
+      <listitem>
+        <para>Remove a queen from the board.</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>Because we have decided that all queens will be on the board at all times and each queen has an appointed
+    column (for performance reasons), only the first 2 move types are usable in our example. Furthermore, we 're only
+    using the first move type in the example because we think it gives the best performance, but you are welcome to
+    prove us wrong.</para>
+
+    <para>Each of your move types will be an implementation of the <literal>Move</literal> interface:</para>
+
+    <programlisting>public interface Move {
+
+    boolean isMoveDoable(EvaluationHandler evaluationHandler);
+
+    Move createUndoMove(EvaluationHandler evaluationHandler);
+
+    void doMove(EvaluationHandler evaluationHandler);
+
+}</programlisting>
+
+    <para>Let's take a look at the <literal>Move</literal> implementation for 4 queens which moves a queen to a
+    different row:</para>
+
+    <programlisting>public class YChangeMove implements Move {
+
+    private Queen queen;
+    private int toY;
+
+    public YChangeMove(Queen queen, int toY) {
+        this.queen = queen;
+        this.toY = toY;
+    }
+
+    // ... see below
+
+}</programlisting>
+
+    <para>An instance of <literal>YChangeMove</literal> moves a queen from it's current y to a different y.</para>
+
+    <para>Drool-solver calls the <literal>doMove(WorkingMemory)</literal> method to do a move. The
+    <literal>Move</literal> implementation must notify the working memory of any changes it does on the solution
+    facts:</para>
+
+    <programlisting>    public void doMove(WorkingMemory workingMemory) {
+        FactHandle queenHandle = workingMemory.getFactHandle(queen);
+        workingMemory.modifyRetract(queenHandle); // before changes are made
+        queen.setY(toY);
+        workingMemory.modifyInsert(queenHandle, queen); // after changes are made
+    }</programlisting>
+
+    <para>Drools-solver disables shadow facts for increased performance, so you cannot use the
+    <literal>workingMemory.update(FactHandle, Object)</literal> method, instead you need to call the
+    <literal>workingMemory.modifyRetract(FactHandle)</literal> method before modifying the fact and the
+    <literal>workingMemory.modifyInsert(FactHandle, Object)</literal> method after modifying the fact. Note that you can
+    alter multiple facts in a single move and effectively create a big move (also known as a coarse-grained
+    move).</para>
+
+    <para>Drools-solver automatically filters out <emphasis>non doable moves</emphasis> by calling the
+    <literal>isDoable(WorkingMemory)</literal> method on a move. A <emphasis>non doable move</emphasis> is:</para>
+
+    <itemizedlist>
+      <listitem>
+        <para>A move that changes nothing on the current solution. For example, moving queen B0 to row 0 is not
+        doable.</para>
+      </listitem>
+
+      <listitem>
+        <para>A move that is impossible to do on the current solution. For example, moving queen B0 to row 10 is not
+        doable because it would move it outside the board limits.</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>In the n queens example, a move which moves the queen from it's current row to the same row isn't
+    doable:</para>
+
+    <programlisting>    public boolean isMoveDoable(WorkingMemory workingMemory) {
+        int fromY = queen.getY();
+        return fromY != toY;
+    }</programlisting>
+
+    <para>Because we won't generate a move which can move a queen outside the board limits, we don't need to check it. A
+    move that is currently not doable can become doable on a later solution.</para>
+
+    <para>Each move has an <emphasis>undo move</emphasis>: a move (usually of the same type) which does the exact
+    opposite. In the above example the undo move of <emphasis>C0 to C2</emphasis> would be the move <emphasis>C2 to
+    C0</emphasis>. An undo move can be created from a move, but only before the move has been done on the current
+    solution.</para>
+
+    <programlisting>    public Move createUndoMove(WorkingMemory workingMemory) {
+        return new YChangeMove(queen, queen.getY());
+    }</programlisting>
+
+    <para>Notice that if C0 would have already been moved to C2, the undo move would create the move <emphasis>C2 to
+    C2</emphasis>, instead of the move <emphasis>C2 to C0</emphasis>.</para>
+
+    <para>The local search solver can do and undo a move more than once, even on different (successive)
+    solutions.</para>
+
+    <para>A move must implement the <literal>equals()</literal> and <literal>hashcode()</literal> methods. 2 moves which
+    make the same change on a solution, must be equal.</para>
+
+    <programlisting>    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        } else if (o instanceof YChangeMove) {
+            YChangeMove other = (YChangeMove) o;
+            return new EqualsBuilder()
+                    .append(queen, other.queen)
+                    .append(toY, other.toY)
+                    .isEquals();
+        } else {
+            return false;
+        }
+    }
+
+    public int hashCode() {
+        return new HashCodeBuilder()
+                .append(queen)
+                .append(toY)
+                .toHashCode();
+    }</programlisting>
+
+    <para>In the above example, the <literal>Queen</literal> class uses the default <literal>Object</literal>
+    <literal>equal()</literal> and <literal>hashcode()</literal> implementations. Notice that it checks if the other
+    move is an instance of the same move type. This is important because a move will be compared to a move with another
+    move type if you're using more then 1 move type.</para>
+
+    <para>It's also recommended to implement the <literal>toString()</literal> method as it allows you to read
+    drools-solver's logging more easily:</para>
+
+    <programlisting>    public String toString() {
+        return queen + " =&gt; " + toY;
+    }</programlisting>
+
+    <para>Now that we can make a single move, let's take a look at generating moves.</para>
+  </section>
+
+  <section>
+    <title>Move generation</title>
+
+    <para>At each solution, local search will try all possible moves and pick the best move to change to the next
+    solution. It's up to you to generate those moves. Let's take a look at all the possible moves on the starting
+    solution of 4 queens:</para>
+
+    <figure>
+      <title>Possible moves at step 0 (4 queens example)</title>
+
+      <mediaobject>
+        <imageobject>
+          <imagedata fileref="images/Chapter-Local_search/possibleMovesNQueens04.png" format="PNG"></imagedata>
+        </imageobject>
+      </mediaobject>
+    </figure>
+
+    <para>As you can see, not all the moves are doable. At the starting solution we have 12 doable moves (<literal>n *
+    (n - 1)</literal>), one of which will be move which changes the starting solution into the next solution. Notice
+    that the number of possible solutions is 256 (<literal>n ^ n</literal>), much more that the amount of doable moves.
+    Don't create a move to every possible solution. Instead use moves which can be sequentially combined to reach every
+    possible solution.</para>
+
+    <para>It's highly recommended that you verify all solutions are connected by your move set. This means that by
+    combining a finite number of moves you can reach any solution from any solution. Otherwise you're already excluding
+    solutions at the start. Especially if you're using only big moves, you should check it. Just because big moves
+    outperform small moves in a short test run, it doesn't mean that they will outperform them in a long test
+    run.</para>
+
+    <para>You can mix different move types. Usually you're better off preferring small (fine-grained) moves over big
+    (course-grained) moves because the score delta calculation will pay off more. However, as the traveling tournament
+    example proves, if you can remove a hard constraint by using a certain set of big moves, you can win performance and
+    scalability. Try it yourself: run both the simple (small moves) and the smart (big moves) version of the traveling
+    tournament example. The smart version evaluates a lot less unfeasible solutions, which enables it to outperform and
+    outscale the simple version.</para>
+
+    <para>Move generation currently happens with a <literal>MoveFactory</literal>:</para>
+
+    <programlisting>public class NQueensMoveFactory extends CachedMoveListMoveFactory {
+
+    public List&lt;Move&gt; createMoveList(Solution solution) {
+        NQueens nQueens = (NQueens) solution;
+        List&lt;Move&gt; moveList = new ArrayList&lt;Move&gt;();
+        for (Queen queen : nQueens.getQueenList()) {
+            for (int n : nQueens.createNList()) {
+                moveList.add(new YChangeMove(queen, n));
+            }
+        }
+        return moveList;
+    }
+
+}</programlisting>
+
+    <para>But we'll be making move generation part of the drl's soon.</para>
+  </section>
+
+  <section>
+    <title>A step</title>
+
+    <para>A step is the winning move. The local search solver tries every move on the current solution and picks the
+    best accepted move as the step:</para>
+
+    <figure>
+      <title>Decide the next step at step 0 (4 queens example)</title>
+
+      <mediaobject>
+        <imageobject>
+          <imagedata fileref="images/Chapter-Local_search/decideNextStepNQueens04.png" format="PNG"></imagedata>
+        </imageobject>
+      </mediaobject>
+    </figure>
+
+    <para>Because the move <emphasis>B0 to B3</emphasis> has the highest score (<literal>-3</literal>), it is picked as
+    the next step. Notice that <emphasis>C0 to C3</emphasis> (not shown) could also have been picked because it also has
+    the score <literal>-3</literal>. If multiple moves have the same highest score, one is picked randomly, in this case
+    <emphasis>B0 to B3</emphasis>.</para>
+
+    <para>The step is made and from that new solution, the local search solver tries all the possible moves again, to
+    decide the next step after that. It continually does this in a loop, and we get something like this:</para>
+
+    <figure>
+      <title>All steps (4 queens example)</title>
+
+      <mediaobject>
+        <imageobject>
+          <imagedata fileref="images/Chapter-Local_search/allStepsNQueens04.png" format="PNG"></imagedata>
+        </imageobject>
+      </mediaobject>
+    </figure>
+
+    <para>Notice that the local search solver doesn't use a search tree, but a search path. The search path is
+    highlighted by the green arrows. At each step it tries all possible moves, but unless it's the step, it doesn't
+    investigate that solution further. This is one of the reasons why local search is very scalable.</para>
+
+    <para>As you can see, the local search solver solves the 4 queens problem by starting with the starting solution and
+    make the following steps sequentially:</para>
+
+    <orderedlist>
+      <listitem>
+        <para><emphasis>B0 to B3</emphasis></para>
+      </listitem>
+
+      <listitem>
+        <para><emphasis>D0 to B2</emphasis></para>
+      </listitem>
+
+      <listitem>
+        <para><emphasis>A0 to B1</emphasis></para>
+      </listitem>
+    </orderedlist>
+
+    <para>If we turn on INFO logging, this is reflected into the logging:</para>
+
+    <programlisting>INFO  Solving with random seed (0).
+INFO  Initial score (-6) is starting best score. Updating best solution and best score.
+INFO  Step (0), time spend (0) doing next step ([Queen-1] 1 @ 0 =&gt; 3).
+INFO  New score (-3) is better then last best score (-6). Updating best solution and best score.
+INFO  Step (1), time spend (0) doing next step ([Queen-3] 3 @ 0 =&gt; 2).
+INFO  New score (-1) is better then last best score (-3). Updating best solution and best score.
+INFO  Step (2), time spend (15) doing next step ([Queen-0] 0 @ 0 =&gt; 1).
+INFO  New score (0) is better then last best score (-1). Updating best solution and best score.
+INFO  Solved in 3 steps and 15 time millis spend.</programlisting>
+
+    <para>Notice that the logging used the <literal>toString()</literal> method from our <literal>Move</literal>
+    implementation: <literal>[Queen-1] 1 @ 0 =&gt; 3</literal>.</para>
+
+    <para>The local search solver solves the 4 queens problem in 3 steps, by evaluating only 37 possible solutions (3
+    steps with 12 moves each + 1 starting solution), which is only fraction of all 256 possible solutions. It solves 16
+    queens in 31 steps, by evaluating only 7441 out of 18446744073709551616 possible solutions.</para>
+  </section>
+
+  <section>
+    <title>Getting stuck in local optima</title>
+
+    <para>A <emphasis>simple local search</emphasis> always takes improving moves. This may seem like a good thing, but
+    it's not. It suffers from a number of problems:</para>
+
+    <itemizedlist>
+      <listitem>
+        <para>It can get stuck in a local optimum. For example if it reaches a solution X with a score -1 and there is
+        no improving move, it is forced to take a next step that leads to a solution Y with score -2, after that
+        however, it's very real that it will pick the step back to solution X with score -1. It will then start looping
+        between solution X and Y.</para>
+      </listitem>
+
+      <listitem>
+        <para>It can start walking in it's own footsteps, picking the same next step at every step.</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>Of course drools-solver implements better local searches, such <emphasis>tabu search</emphasis> and
+    <emphasis>simulated annealing</emphasis> which can avoid these problems. It's recommended to never use a simple
+    local search, unless you're absolutely sure there are no local optima in your planning problem.</para>
+  </section>
+
+  <section>
+    <title>Deciding the next step</title>
+
+    <para>The local search solver decides the next step with the aid of 3 configurable components:</para>
+
+    <itemizedlist>
+      <listitem>
+        <para>A <emphasis>selector</emphasis> which selects (or generates) the possible moves of the current
+        solution.</para>
+      </listitem>
+
+      <listitem>
+        <para>An <emphasis>accepter</emphasis> which filters out unacceptable moves. It can also weigh a move it
+        accepts.</para>
+      </listitem>
+
+      <listitem>
+        <para>A <emphasis>forager</emphasis> which gathers all accepted moves and picks the next step from them.</para>
+      </listitem>
+    </itemizedlist>
+
+    <figure>
+      <title>Decide the next step at step 0 (4 queens example)</title>
+
+      <mediaobject>
+        <imageobject>
+          <imagedata fileref="images/Chapter-Local_search/decideNextStepNQueens04.png" format="PNG"></imagedata>
+        </imageobject>
+      </mediaobject>
+    </figure>
+
+    <para>In the above example the selector generated the moves shown with the blue lines, the accepter accepted all of
+    them and the forager picked the move <emphasis>B0 to B3</emphasis>.</para>
+
+    <para>If we turn on DEBUG logging, we can see the decision making in the log:</para>
+
+    <programlisting>INFO  Solving with random seed (0).
+INFO  Initial score (-6) is starting best score. Updating best solution and best score.
+DEBUG     Move ([Queen-0] 0 @ 0 =&gt; 0) ignored because not doable.
+DEBUG     Move ([Queen-0] 0 @ 1 =&gt; 1) with score (-4) and acceptChance (1.0).
+DEBUG     Move ([Queen-0] 0 @ 2 =&gt; 2) with score (-4) and acceptChance (1.0).
+...
+DEBUG     Move ([Queen-1] 1 @ 3 =&gt; 3) with score (-3) and acceptChance (1.0).
+...
+DEBUG     Move ([Queen-3] 3 @ 3 =&gt; 3) with score (-4) and acceptChance (1.0).
+INFO  Step (0), time spend (0) doing next step ([Queen-1] 1 @ 0 =&gt; 3).
+INFO  New score (-3) is better then last best score (-6). Updating best solution and best score.
+...</programlisting>
+
+    <section>
+      <title>Selector</title>
+
+      <para>A selector is currently based on a <literal>MoveFactory</literal>.</para>
+
+      <programlisting>    &lt;selector&gt;
+        &lt;moveFactoryClass&gt;org.drools.solver.examples.nqueens.solver.NQueensMoveFactory&lt;/moveFactoryClass&gt;
+    &lt;/selector&gt;</programlisting>
+
+      <para>You're not obligated to generate the same stable set of moves at each step. You could start with generating
+      only big moves initially, and gradually switch to small moves. There's no build-in support for this yet
+      though.</para>
+
+      <para>If there are many possible moves, it can become inefficient to evaluate all of them every step. With
+      relativeSelection only a random subset of them is evaluated:</para>
+
+      <programlisting>    &lt;selector&gt;
+       &lt;moveFactoryClass&gt;org.drools.solver.examples.itc2007.examination.solver.move.factory.RoomChangeMoveFactory&lt;/moveFactoryClass&gt;
+       &lt;relativeSelection&gt;0.002&lt;/relativeSelection&gt;
+    &lt;/selector&gt;</programlisting>
+    </section>
+
+    <section>
+      <title>Accepter</title>
+
+      <para>An accepter is used (together with a forager) to active tabu search, simulated annealing, great deluge, ...
+      For each move it generates an accept chance. If a move is rejected it is given an accept chance of
+      <literal>0.0</literal>.</para>
+
+      <para>You can implement your own <literal>Accepter</literal>, although the build-in accepters should suffice for
+      most needs. You can also combine multiple accepters.</para>
+
+      <section>
+        <title>Tabu search accepter</title>
+
+        <para>When tabu search takes steps it creates tabu's. It does not accept a move as the next step if that move
+        breaks tabu. Drools-solver implements several tabu types:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para><emphasis>Solution tabu</emphasis> makes recently visited solutions tabu. It does not accept a move
+            that leads to one of those solutions. If you can spare the memory, don't be cheap on the tabu size. We
+            recommend this type of tabu because it tends to give the best results and requires little or no
+            tweaking.</para>
+
+            <programlisting>    &lt;accepter&gt;
+        &lt;completeSolutionTabuSize&gt;1000&lt;/completeSolutionTabuSize&gt;
+    &lt;/accepter&gt;</programlisting>
+          </listitem>
+
+          <listitem>
+            <para><emphasis>Move tabu</emphasis> makes recent steps tabu. It does not accept a move equal to one of
+            those steps.</para>
+
+            <programlisting>    &lt;accepter&gt;
+        &lt;completeMoveTabuSize&gt;1000&lt;/completeMoveTabuSize&gt;
+    &lt;/accepter&gt;</programlisting>
+          </listitem>
+
+          <listitem>
+            <para><emphasis>Undo move tabu </emphasis>makes the undo move of recent steps tabu.</para>
+
+            <programlisting>    &lt;accepter&gt;
+        &lt;completeUndoMoveTabuSize&gt;1000&lt;/completeUndoMoveTabuSize&gt;
+    &lt;/accepter&gt;</programlisting>
+          </listitem>
+
+          <listitem>
+            <para><emphasis>Property tabu</emphasis> makes a property of recent steps tabu. For example, it can make the
+            queen tabu, so that a recently moved queen can't be moved.</para>
+
+            <programlisting>    &lt;accepter&gt;
+        &lt;completePropertyTabuSize&gt;1000&lt;/completePropertyTabuSize&gt;
+    &lt;/accepter&gt;</programlisting>
+
+            <para>To use property tabu, your moves must implement the <literal>TabuPropertyEnabled</literal> interface,
+            for example:</para>
+
+            <programlisting>public class YChangeMove implements Move, TabuPropertyEnabled {
+
+    private Queen queen;
+    private int toY;
+
+    // ...
+
+    public List&lt;? extends Object&gt; getTabuPropertyList() {
+        return Collections.singletonList(queen);
+    }
+
+}</programlisting>
+          </listitem>
+        </itemizedlist>
+
+        <para>You can even combine tabu types:</para>
+
+        <programlisting>    &lt;accepter&gt;
+        &lt;completeSolutionTabuSize&gt;1000&lt;/completeSolutionTabuSize&gt;
+        &lt;completeUndoMoveTabuSize&gt;10&lt;/completeUndoMoveTabuSize&gt;
+    &lt;/accepter&gt;</programlisting>
+
+        <para>If you pick a too small tabu size, your solver can still get stuck in a local optimum. On the other hand,
+        with the exception of solution tabu, if you pick a too large tabu size, your solver can get stuck by bouncing of
+        the walls. Use the benchmarker to fine tweak your configuration.</para>
+
+        <para>A tabu search accepter should be combined with a <emphasis>maximum score of all</emphasis> or
+        <emphasis>first best score improving</emphasis> forager.</para>
+      </section>
+
+      <section>
+        <title>Simulated annealing accepter</title>
+
+        <para>Simulated annealing does not pick the move with the highest score, neither does it evaluate all moves. At
+        least at first.</para>
+
+        <para>It gives unimproving moves a chance, depending on it's score and the temperature. The
+        <emphasis>temperature</emphasis> is relative to how long it has been solving. In the end, it gradually turns
+        into a simple local search, only accepting improving moves.</para>
+
+        <para>A simulated annealing accepter should be combined with a <emphasis>first randomly accepted</emphasis>
+        forager.</para>
+      </section>
+    </section>
+
+    <section>
+      <title>Forager</title>
+
+      <para>A forager gathers all accepted moves and picks the move which is the next step. A forager can choose to
+      allow only a subset of all selected moves to be evaluated, by quitting early if a suitable move has been
+      accepted.</para>
+
+      <para>You can implement your own <literal>Forager</literal>, although the build-in foragers should suffice for
+      most needs.</para>
+
+      <section>
+        <title>Maximum score of all forager</title>
+
+        <para>Allows all selected moves to be evaluated and picks the accepted move with the highest score. If several
+        accepted moves have the highest score, one is picked randomly, weighted on their accept chance.</para>
+
+        <programlisting>    &lt;forager&gt;
+        &lt;foragerType&gt;MAX_SCORE_OF_ALL&lt;/foragerType&gt;
+    &lt;/forager&gt;</programlisting>
+      </section>
+
+      <section>
+        <title>First best score improving forager</title>
+
+        <para>Picks the first accepted move that improves the best score. If none improve the best score, it behaves
+        exactly like the maximum score of all forager.</para>
+
+        <programlisting>    &lt;forager&gt;
+        &lt;foragerType&gt;FIRST_BEST_SCORE_IMPROVING&lt;/foragerType&gt;
+    &lt;/forager&gt;</programlisting>
+      </section>
+
+      <section>
+        <title>First last step score improving forager</title>
+
+        <para>Picks the first accepted move that improves the last step score. If none improve the last step score, it
+        behaves exactly like the maximum score of all forager.</para>
+
+        <programlisting>    &lt;forager&gt;
+        &lt;foragerType&gt;FIRST_BEST_SCORE_IMPROVING&lt;/foragerType&gt;
+    &lt;/forager&gt;</programlisting>
+      </section>
+
+      <section>
+        <title>First randomly accepted forager</title>
+
+        <para>Generates a random number for each accepted move and if the move's accept chance is higher, it picks that
+        move as the next move.</para>
+
+        <programlisting>    &lt;forager&gt;
+        &lt;foragerType&gt;FIRST_RANDOMLY_ACCEPTED&lt;/foragerType&gt;
+    &lt;/forager&gt;</programlisting>
+      </section>
+    </section>
+  </section>
+
+  <section>
+    <title>Best solution</title>
+
+    <para>Because the current solution can degrade (especially in tabu search and simulated annealing), the local search
+    solver remembers the best solution it has encountered through the entire search path. Each time the current solution
+    is better than the last best solution, the current solution is cloned and referenced as the new best
+    solution.</para>
+
+    <para>You can listen to solver events, including when the best solution changes during solving, by adding a
+    <literal>SolverEventListener</literal> to the <literal>Solver</literal>:</para>
+
+    <programlisting>public interface Solver {
+
+    // ...
+
+    void addEventListener(SolverEventListener eventListener);
+    void removeEventListener(SolverEventListener eventListener);
+
+}</programlisting>
+  </section>
+
+  <section>
+    <title>Termination</title>
+
+    <para>Sooner or later the local search solver will have to stop solving. This can be because of a number of reasons:
+    the time is up, the perfect score has been reached, ... The only thing you can't depend on is on finding the optimal
+    solution (unless you know the optimal score), because a local search solver doesn't know that when it finds the
+    optimal solution. For real-life problems this doesn't turn out to be much of a problem, because finding the optimal
+    solution would take years, so you 'll want to terminate sooner anyway.</para>
+
+    <para>You can configure when a local search solver needs to stop by configuring a Termination. You can implement
+    your own <literal>Termination</literal>, although the build-in Terminations should suffice for most needs.</para>
+
+    <section>
+      <title>TimeMillisSpendTermination</title>
+
+      <para>Terminates when an amount of time has been reached:</para>
+
+      <programlisting>    &lt;termination&gt;
+        &lt;maximumMinutesSpend&gt;2&lt;/maximumMinutesSpend&gt;
+    &lt;/termination&gt;</programlisting>
+
+      <para>or</para>
+
+      <programlisting>    &lt;termination&gt;
+        &lt;maximumHoursSpend&gt;1&lt;/maximumHoursSpend&gt;
+    &lt;/termination&gt;</programlisting>
+
+      <para>Note that the time taken by a <literal>StartingSolutionInitializer</literal> also is taken into account by
+      this Termination. So if you give the solver 2 minutes to solve something, but the initializer takes 1 minute, the
+      local search solver will only have a minute left.</para>
+
+      <para>Note that if you use this Termination, you will most likely sacrifice reproducability. The best solution
+      will depend on available CPU time, not only because it influences the amount of steps taken, but also because time
+      gradient based algorithms (such as simulated annealing) will probably act differently on each run.</para>
+    </section>
+
+    <section>
+      <title>StepCountTermination</title>
+
+      <para>Terminates when an amount of steps has been reached:</para>
+
+      <programlisting>    &lt;termination&gt;
+        &lt;maximumStepCount&gt;100&lt;/maximumStepCount&gt;
+    &lt;/termination&gt;</programlisting>
+    </section>
+
+    <section>
+      <title>ScoreAttainedTermination</title>
+
+      <para>Terminates when a certain score has been reached. You can use this Termination if you know the perfect
+      score, for example for 4 queens:</para>
+
+      <programlisting>    &lt;termination&gt;
+        &lt;scoreAttained&gt;0&lt;/scoreAttained&gt;
+    &lt;/termination&gt;</programlisting>
+
+      <para>You can also use this Termination to terminate once it reaches a feasible solution. For a solver problem
+      with hard and soft contraints, it could look like this:</para>
+
+      <programlisting>    &lt;termination&gt;
+        &lt;scoreAttained&gt;0hard/-5000soft&lt;/scoreAttained&gt;
+    &lt;/termination&gt;</programlisting>
+    </section>
+
+    <section>
+      <title>UnimprovedStepCountTermination</title>
+
+      <para>Terminates when the best score hasn't improved in a number of steps:</para>
+
+      <programlisting>    &lt;termination&gt;
+        &lt;maximumUnimprovedStepCount&gt;100&lt;/maximumUnimprovedStepCount&gt;
+    &lt;/termination&gt;</programlisting>
+
+      <para>If it hasn't improved recently, it's probably not going to improve soon anyway and it's not worth the effort
+      to continue. We have observed that once a new best solution is found (even after a long time of no improvement on
+      the best solution), the next few step tend to improve the best solution too.</para>
+    </section>
+
+    <section>
+      <title>Combining Terminations</title>
+
+      <para>Terminations can be combined, for example: terminate after 100 steps or if a score of 0 has been
+      reached:</para>
+
+      <programlisting>    &lt;termination&gt;
+        &lt;terminationCompositionStyle&gt;OR&lt;/terminationCompositionStyle&gt;
+        &lt;maximumStepCount&gt;100&lt;/maximumStepCount&gt;
+        &lt;scoreAttained&gt;0&lt;/scoreAttained&gt;
+    &lt;/termination&gt;</programlisting>
+
+      <para>Alternatively you can use AND, for example: terminate after reaching a feasible score of at least -100 and
+      no improvements in 5 steps:</para>
+
+      <programlisting>    &lt;termination&gt;
+        &lt;terminationCompositionStyle&gt;AND&lt;/terminationCompositionStyle&gt;
+        &lt;maximumUnimprovedStepCount&gt;5&lt;/maximumUnimprovedStepCount&gt;
+        &lt;scoreAttained&gt;-100&lt;/scoreAttained&gt;
+    &lt;/termination&gt;</programlisting>
+
+      <para>This ensures it doesn't just terminate after finding a feasible solution, but also makes any obvious
+      improvements on that solution before terminating.</para>
+    </section>
+
+    <section>
+      <title>Another thread can ask a Solver to terminate early</title>
+
+      <para>Sometimes you 'll want to terminate a Solver early from another thread, for example because a user action or
+      a server restart. That cannot be configured by a <literal>Termination</literal> as it's impossible to predict when
+      and if it will occur. Therefor the <literal>Solver</literal> interface has these 2 thread-safe methods:</para>
+
+      <programlisting>public interface Solver {
+
+    // ...
+
+    boolean terminateEarly();
+    boolean isTerminatedEarly();
+
+}</programlisting>
+
+      <para>If you call the <literal>terminateEarly()</literal> method from another thread, the
+      <literal>Solver</literal> will terminate at its earliest convenience and the <literal>solve()</literal> method
+      will return in the original solver thread.</para>
+    </section>
+  </section>
+</chapter>


Property changes on: labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Local_search/Section-Local_search.xml
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + text/plain

Copied: labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Planner_configuration/Section-Planner_configuration.xml (from rev 30778, labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Solver/Section-Solver_configuration.xml)
===================================================================
--- labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Planner_configuration/Section-Planner_configuration.xml	                        (rev 0)
+++ labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Planner_configuration/Section-Planner_configuration.xml	2009-12-20 16:39:21 UTC (rev 30780)
@@ -0,0 +1,514 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
+                             http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd"
+         version="5.0" xml:base="./">
+
+  <title>Solver configuration</title>
+
+  <section>
+    <title>Types of solvers</title>
+
+    <para>Different solvers solve problems in different ways. Each type has advantages and disadvantages. We 'll roughly
+    discuss a few of the solver types here. You can safely skip this section.</para>
+
+    <section>
+      <title>Brute force</title>
+
+      <para>Brute force creates and evaluates every possible solution, usually by creating a search tree.</para>
+
+      <para>Advantages:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>It knows when it has found an optimal solution. If there is more then 1 optimal solution, it finds all
+          optimal solutions.</para>
+        </listitem>
+
+        <listitem>
+          <para>It is straightforward and simple to implement.</para>
+        </listitem>
+      </itemizedlist>
+
+      <para>Disadvantages:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>It performs and scales horribly. Mostly unusable for a real-world problem due to time
+          limitations.</para>
+        </listitem>
+      </itemizedlist>
+
+      <para>Brute force is currently not implemented in drools-solver. But we have plans to implement it in the future,
+      as a reference for validating the output of the other solver types.</para>
+    </section>
+
+    <section>
+      <title>Branch and bound</title>
+
+      <para>Branch and bound is an improvement over brute force, as it prunes away subsets of solutions which cannot
+      have a better solution than the best solution already found at that point.</para>
+
+      <para>Advantages:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>It knows when it has found an optimal solution. If there is more then 1 optimal solution, it can find
+          all optimal solutions if needed.</para>
+        </listitem>
+
+        <listitem>
+          <para>It can determine the bounds of a problem, which gives an indication of the quality of a solution.</para>
+        </listitem>
+      </itemizedlist>
+
+      <para>Disadvantages:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>It still scales very badly. Mostly unusable for a real-world problem due to time limitations.</para>
+        </listitem>
+      </itemizedlist>
+
+      <para>Branch and bound is currently not implemented in drools-solver. But we have plans to implement it in the
+      future, as a reference for validating the output of the other solver types.</para>
+    </section>
+
+    <section>
+      <title>Simplex</title>
+
+      <para>Simplex is an algorithm to find the numerical solution of a linear programming problem.</para>
+
+      <para>Advantages:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>It knows when it has found an optimal solution.</para>
+        </listitem>
+      </itemizedlist>
+
+      <para>Disadvantages:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>It's complex and mathematical to implement constraints.</para>
+        </listitem>
+      </itemizedlist>
+
+      <para>Drools-solver does not implement simplex.</para>
+    </section>
+
+    <section>
+      <title>Genetic algorithms</title>
+
+      <para>Advantages:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>It's scalable</para>
+        </listitem>
+
+        <listitem>
+          <para>Given a limited time, it can still deliver a pretty decent solution.</para>
+        </listitem>
+      </itemizedlist>
+
+      <para>Disadvantages:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>It does not know when it has found an optimal solution.</para>
+        </listitem>
+
+        <listitem>
+          <para>If the optimal score is unknown (which is usually the case), it must be told when to stop looking (for
+          example based on time spend, user input, ...).</para>
+        </listitem>
+      </itemizedlist>
+
+      <para>The genetic algorithm is currently not implemented in drools-solver.</para>
+    </section>
+
+    <section>
+      <title>Local search (tabu search, simulated annealing, ...)</title>
+
+      <para>Local search starts from an initial solution and evolves that single solution into a mostly better and
+      better solution. It uses a single search path of solutions, not a search tree. At each solution in this path it
+      evaluates a number of moves on the solution and applies the most suitable move to take the step to the next
+      solution.</para>
+
+      <para>Local search works a lot like a human planner: it uses a single search path and moves facts around to find a
+      good feasible solution.</para>
+
+      <para>A simple local search can easily get stuck in a local optima, but improvements (such as tabu search and
+      simulated annealing) address this problem.</para>
+
+      <para>Advantages:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>It's relatively simple and natural to implement constraints (at least in drools-solver's
+          implementation).</para>
+        </listitem>
+
+        <listitem>
+          <para>It's very scalable, even when adding extra constraints (at least in drools-solver's
+          implementation).</para>
+        </listitem>
+
+        <listitem>
+          <para>Given a limited time, it can still deliver a pretty decent solution.</para>
+        </listitem>
+      </itemizedlist>
+
+      <para>Disadvantages:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>It does not know when it has found an optimal solution.</para>
+        </listitem>
+
+        <listitem>
+          <para>If the optimal score is unknown (which is usually the case), it must be told when to stop looking (for
+          example based on time spend, user input, ...).</para>
+        </listitem>
+      </itemizedlist>
+
+      <para>Drools-solver implements local search, including tabu search and simulated annealing.</para>
+    </section>
+  </section>
+
+  <section>
+    <title>The size of real world problems</title>
+
+    <para>As a planning problem gets bigger, the search space tends to blow up really fast. It's not uncommon to see
+    that it's possible to optimally plan 5 people in less then a second, while planning 6 people optimally would take
+    years. Take a look at the problem size of the examples: many instances have a lot more possible solutions than there
+    are supposedly atoms in the known universe (10^80).</para>
+
+    <para>Planning competitions (such as the International Timetabling Competition) show that local search variations
+    (tabu search, simulated annealing, ...) usually perform best for real-world problems given real-world time
+    limitations.</para>
+  </section>
+
+  <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);
+
+    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 a 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 only be accessed from a single thread, except for the methods that are
+    specifically javadocced as thread-safe.</para>
+  </section>
+
+  <section>
+    <title>Building a solver</title>
+
+    <para>You can build a <literal>Solver</literal> instance with the <literal>XmlSolverConfigurer</literal>. Configure
+    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>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
+&lt;localSearchSolver&gt;
+    &lt;scoreDrl&gt;/org/drools/solver/examples/nqueens/solver/nQueensScoreRules.drl&lt;/scoreDrl&gt;
+    &lt;scoreDefinition&gt;
+        &lt;scoreDefinitionType&gt;SIMPLE&lt;/scoreDefinitionType&gt;
+    &lt;/scoreDefinition&gt;
+    &lt;termination&gt;
+        &lt;scoreAttained&gt;0&lt;/scoreAttained&gt;
+    &lt;/termination&gt;
+    &lt;selector&gt;
+        &lt;moveFactoryClass&gt;org.drools.solver.examples.nqueens.solver.NQueensMoveFactory&lt;/moveFactoryClass&gt;
+    &lt;/selector&gt;
+    &lt;accepter&gt;
+        &lt;completeSolutionTabuSize&gt;1000&lt;/completeSolutionTabuSize&gt;
+    &lt;/accepter&gt;
+    &lt;forager&gt;
+        &lt;foragerType&gt;MAX_SCORE_OF_ALL&lt;/foragerType&gt;
+    &lt;/forager&gt;
+&lt;/localSearchSolver&gt;</programlisting>
+
+    <para>This is a tabu search configuration for n queens. 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 4 queens and 64 queens.</para>
+
+    <para>A solver has a single <literal>Random</literal> instance. Some solver configurations use that instance a lot
+    more than others. For example simulated annealing depends highly on random numbers, while tabu search only depends
+    on it to deal with score ties. In any case, during your testing it's advisable to set that <literal>Random</literal>
+    instance, so your tests are reproducible.</para>
+  </section>
+
+  <section>
+    <title>The Solution interface</title>
+
+    <para>A Solver can only solve 1 problem at a time.</para>
+
+    <para>You need to present the problem as a starting <literal>Solution</literal> instance to the solver.</para>
+
+    <para>You need to implement the <literal>Solution</literal> interface:</para>
+
+    <programlisting>public interface Solution {
+
+    Score getScore();
+    void setScore(Score score);
+
+    Collection&lt;? extends Object&gt; getFacts();
+
+    Solution cloneSolution();
+
+}</programlisting>
+
+    <para>For example, an NQueens instance just holds a list of all it's queens:</para>
+
+    <programlisting>public class NQueens implements Solution {
+
+    private List&lt;Queen&gt; queenList;
+
+    // ...
+
+}</programlisting>
+
+    <section>
+      <title>The getScore and setScore methods</title>
+
+      <para>A <literal>Solution</literal> requires a score property. The score property is null if the
+      <literal>Solution</literal> is unitialized or if the score has not yet been (re)calculated.The score property is
+      ussually typed to the specific <literal>Score</literal> implementation you use. For example, NQueens uses a
+      <literal>SimpleScore</literal>:</para>
+
+      <programlisting>    private SimpleScore score;
+
+    public SimpleScore getScore() {
+        return score;
+    }
+
+    public void setScore(Score score) {
+        this.score = (SimpleScore) score;
+    }</programlisting>
+    </section>
+
+    <section>
+      <title>The getFacts method</title>
+
+      <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 rules. For example, <literal>NQueens</literal> just returns all
+      <literal>Queen</literal> instances.</para>
+
+      <programlisting>    public Collection&lt;? extends Object&gt; getFacts() {
+        return queenList;
+    }</programlisting>
+    </section>
+
+    <section>
+      <title>The cloneSolution method</title>
+
+      <para>Most solvers use the <literal>cloneSolution()</literal> method to clone the solution each time they
+      encounter a new best solution. The <literal>NQueens</literal> implementation just clones all
+      <literal>Queen</literal> instances:</para>
+
+      <programlisting>    public NQueens cloneSolution() {
+        NQueens clone = new NQueens();
+        List&lt;Queen&gt; clonedQueenList = new ArrayList&lt;Queen&gt;(queenList.size());
+        for (Queen queen : queenList) {
+            clonedQueenList.add(queen.clone());
+        }
+        clone.queenList = clonedQueenList;
+        clone.score = score;
+        return clone;
+    }</programlisting>
+
+      <para>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&lt;Lesson&gt; clonedLessonList = new ArrayList&lt;Lesson&gt;(lessonList.size());
+        for (Lesson lesson : lessonList) {
+            clonedLessonList.add(lesson.clone());
+        }
+        clone.lessonList = clonedLessonList;
+        clone.score = score;
+        return clone;
+    }</programlisting>
+    </section>
+  </section>
+
+  <section>
+    <title>The starting solution</title>
+
+    <para>First, you will need to make a starting solution and set that on the solver:</para>
+
+    <programlisting>solver.setStartingSolution(startingSolution);</programlisting>
+  </section>
+
+  <section>
+    <title>A simple filler algorithm</title>
+
+    <para>For 4 queens we use a simple filler algorithm that creates a starting solution with all queens on a different
+    x and on the same y (with y = 0).</para>
+
+    <figure>
+      <title>Starting solution for the 4 queens puzzle</title>
+
+      <mediaobject>
+        <imageobject>
+          <imagedata fileref="images/Chapter-Planner_configuration/unsolvedNQueens04.png" format="PNG"></imagedata>
+        </imageobject>
+      </mediaobject>
+    </figure>
+
+    <para>Here's how we generate it:</para>
+
+    <programlisting>    private NQueens createNQueens(int n) {
+        NQueens nQueens = new NQueens();
+        nQueens.setId(0L);
+        List&lt;Queen&gt; queenList = new ArrayList&lt;Queen&gt;(n);
+        for (int i = 0; i &lt; n; i++) {
+            Queen queen = new Queen();
+            queen.setId((long) i);
+            queen.setX(i); // Different column
+            queen.setY(0); // Same row
+            queenList.add(queen);
+        }
+        nQueens.setQueenList(queenList);
+        return nQueens;
+    }</programlisting>
+
+    <para>The starting solution will probably be far from optimal (or even feasible). Here, it's actually the worst
+    possible solution. However, we 'll let the solver find a much better solution for us anyway.</para>
+
+    <section>
+      <title>StartingSolutionInitializer</title>
+
+      <para>For large problems, a simple filler algorithm like <literal>createNQueens(int)</literal> doesn't suffice. A
+      (local search) solver starting from a bad starting solution wastes a lot of time to reach a solution which an
+      initializer algorithm can generate in a fraction of that time.</para>
+
+      <para>An initializer algorithm ussually works something like this:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>It sorts the unplanned elements in a queue according to some general rules, for example by exam student
+          size.</para>
+        </listitem>
+
+        <listitem>
+          <para>Next, it plans them in the order they come from the queue. Each element is put the best, still available
+          spot.</para>
+        </listitem>
+
+        <listitem>
+          <para>It doesn't change an already planned element. It exits when the queue is empty and all elements are
+          planned.</para>
+        </listitem>
+      </itemizedlist>
+
+      <para>Such an algorithm is very deterministic: it's really fast, but you can't give it more time to generate an
+      even better solution. In some cases the solution it generates will be feasible, but in most cases it won't. You
+      'll need a real solver to get to a feasible or more optimal solution. Nevertheless you 'll want to such an
+      initializer to give the real solver a serious head start. You can do this by implementing the
+      <literal>StartingSolutionInitializer</literal> interface:</para>
+
+      <programlisting>public interface StartingSolutionInitializer extends SolverAware {
+
+    boolean isSolutionInitialized(Solution solution);
+
+    void initializeSolution(Solution solution);
+
+}</programlisting>
+
+      <para>You'll need to set a (uninitialized) solution on the solver. Once the solver starts, it will first call the
+      <literal>StartingSolutionInitializer</literal> to initialize the solution. If the
+      <literal>StartingSolutionInitializer</literal> adds, edits or removes facts it needs to notify the workingMemory
+      about this. It can use score calculation during its intialization process.</para>
+
+      <para>Here's an example on how you add the <literal>StartingSolutionInitializer</literal> to the
+      configuration:</para>
+
+      <programlisting>&lt;localSearchSolver&gt;
+    ...
+    &lt;startingSolutionInitializerClass&gt;org.drools.solver.examples.itc2007.examination.solver.solution.initializer.ExaminationStartingSolutionInitializer&lt;/startingSolutionInitializerClass&gt;
+    ...
+&lt;/localSearchSolver&gt;</programlisting>
+    </section>
+  </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). The solver will remember (actually clone) the best solution it encounters during its solving.
+    Depending on a number factors (including problem size, how long you allow the solver to work, which solver type you
+    use, ...), that best solution will be a feasible or even an optimal solution.</para>
+
+    <figure>
+      <title>Best solution for the 4 queens puzzle (also an optimal solution)</title>
+
+      <mediaobject>
+        <imageobject>
+          <imagedata fileref="images/Chapter-Planner_configuration/solvedNQueens04.png" format="PNG"></imagedata>
+        </imageobject>
+      </mediaobject>
+    </figure>
+
+    <para>After a problem is solved, you can reuse the same solver instance to solve another problem (of the same
+    problem type).</para>
+  </section>
+</chapter>


Property changes on: labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Planner_configuration/Section-Planner_configuration.xml
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + text/plain

Copied: labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Planner_introduction/Section-Planner_introduction.xml (from rev 30778, labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Solver/Section-Solver_introduction.xml)
===================================================================
--- labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Planner_introduction/Section-Planner_introduction.xml	                        (rev 0)
+++ labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Planner_introduction/Section-Planner_introduction.xml	2009-12-20 16:39:21 UTC (rev 30780)
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
+                             http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd"
+         version="5.0" xml:base="./">
+
+  <title>Solver introduction</title>
+
+  <section>
+    <title>What is drools-solver?</title>
+
+    <para><emphasis role="bold">Drools-solver solves planning problems</emphasis> by combining a search algorithm with
+    the power of the drools rule engine. Good examples of such planning problems include:</para>
+
+    <itemizedlist>
+      <listitem>
+        <para>Employee shift rostering</para>
+      </listitem>
+
+      <listitem>
+        <para>Freight routing</para>
+      </listitem>
+
+      <listitem>
+        <para>Supply sorting</para>
+      </listitem>
+
+      <listitem>
+        <para>Lesson scheduling</para>
+      </listitem>
+
+      <listitem>
+        <para>Exam scheduling</para>
+      </listitem>
+
+      <listitem>
+        <para>Bin packaging</para>
+      </listitem>
+
+      <listitem>
+        <para><link xlink:href="http://en.wikipedia.org/wiki/Travelling_salesman_problem">The traveling salesman
+        problem</link></para>
+      </listitem>
+
+      <listitem>
+        <para><link xlink:href="http://mat.gsia.cmu.edu/TOURN/">The traveling tournament problem</link></para>
+      </listitem>
+
+      <listitem>
+        <para>Miss manners too (although the drools-solver example solves this differently than the pure drools rule
+        engine example)</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>A planning problem consists out of a number of constraints. Generally, there are 3 types of
+    constraints:</para>
+
+    <itemizedlist>
+      <listitem>
+        <para>A <emphasis>(negative) hard constraint</emphasis> must not be broken. For example: <emphasis>1 teacher can
+        not teach 2 different lessons at the same time</emphasis>.</para>
+      </listitem>
+
+      <listitem>
+        <para>A <emphasis>(negative) soft constraint</emphasis> should not be broken if it can be avoided. For example:
+        <emphasis>Teacher A does not like to teach on Friday afternoon</emphasis>.</para>
+      </listitem>
+
+      <listitem>
+        <para>A <emphasis>positive constraint (or reward)</emphasis> should be fulfilled if possible. For example:
+        <emphasis>Teacher B likes to teach on Monday morning</emphasis>.</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>These constraints define the <emphasis>score function</emphasis> of a planning problem. This is where the
+    drools rule engine comes into play: <emphasis role="bold">adding constraints with score rules is easy and
+    scalable</emphasis>.</para>
+
+    <para>A planning problem has a number of <emphasis>solutions</emphasis>. Each solution has a score. There are 3
+    categories of solutions:</para>
+
+    <itemizedlist>
+      <listitem>
+        <para>A <emphasis>possible solution</emphasis> is a solution that does or does not break any number of
+        constraints. Planning problems tend to have a incredibly large number of possible solutions. Most of those
+        solutions are worthless.</para>
+      </listitem>
+
+      <listitem>
+        <para>A <emphasis>feasible solution</emphasis> is a solution that does not break any (negative) hard
+        constraints. The number of feasible solutions tends to be relative to the number of possible solutions.
+        Sometimes there are no feasible solutions. Every feasible solution is a possible solution.</para>
+      </listitem>
+
+      <listitem>
+        <para>An <emphasis>optimal solution</emphasis> is a solution with the highest score. Planning problems tend to
+        have 1 or a few optimal solutions. There is always at least 1 optimal solution, even in the remote case that
+        it's not a feasible solution because there are no feasible solutions.</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>Drools-solver supports several search algorithms to efficiently wade through the incredbly large number of
+    possible solutions. <emphasis role="bold">It makes it easy to switch the search algorithm</emphasis>, by simply
+    changing the solver configuration.</para>
+  </section>
+
+  <section>
+    <title>Status of drools-solver</title>
+
+    <para>Drools-solver is a beta module of Drools. The API is almost stable but backward incompatible changes can
+    occur. With the recipe called <filename>UpgradeFromPreviousVersionRecipe.txt</filename> you can easily upgrade and
+    deal with any backwards incompatible changes between versions. You can find this recipe in subversion and in every
+    release.</para>
+
+    <para>Drools-solver, like Drools, is open source software under the Apache Software License.</para>
+  </section>
+
+  <section>
+    <title>Getting drools-solver and running the examples</title>
+
+    <section>
+      <title>Getting the release package and running the examples</title>
+
+      <para>You can download a release of drools-solver from <link
+      xlink:href="http://www.jboss.org/drools/downloads.html">the drools download site</link>. To run an example, just
+      run the script (<filename>runExamples.sh</filename> on linux or <filename>runExamples.bat</filename> on windows)
+      and pick an example:</para>
+
+      <programlisting>$ ./runExamples.sh</programlisting>
+    </section>
+
+    <section>
+      <title>Get it with maven 2</title>
+
+      <para>The drools-solver jars are available on <link xlink:href="http://repository.jboss.com/maven2/">the jboss
+      maven repository</link>. If you use maven 2, just add a dependency to <literal>drools-solver-core</literal> in
+      your project's <filename>pom.xml</filename>:</para>
+
+      <programlisting>    &lt;dependency&gt;
+        &lt;groupId&gt;org.drools.solver&lt;/groupId&gt;
+        &lt;artifactId&gt;drools-solver-core&lt;/artifactId&gt;
+        &lt;version&gt;5.x&lt;/version&gt;
+    &lt;/dependency&gt;</programlisting>
+
+      <para>You might also need to add the jboss repository in your respository manager (nexus, archiva, ...) or your
+      <filename>~/settings.xml</filename>:</para>
+
+      <programlisting>    &lt;repositories&gt;
+        &lt;repository&gt;
+            &lt;id&gt;repository.jboss.org&lt;/id&gt;
+            &lt;url&gt;http://repository.jboss.org/maven2&lt;/url&gt;
+            &lt;snapshots&gt;
+                &lt;enabled&gt;false&lt;/enabled&gt;
+            &lt;/snapshots&gt;
+            &lt;releases&gt;
+               &lt;enabled&gt;true&lt;/enabled&gt;
+            &lt;/releases&gt;
+        &lt;/repository&gt;
+        ...
+    &lt;/repositories&gt;</programlisting>
+    </section>
+
+    <section>
+      <title>Build it from source</title>
+
+      <para>You can also easily build it from source yourself. Checkout drools from subversion and do a maven 2
+      build:</para>
+
+      <programlisting>$ svn checkout http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/ drools
+...
+$ cd drools
+$ mvn -DskipTests clean install
+...</programlisting>
+
+      <para>After that, you can run any example directly from the command line, just run this command and pick an
+      example:</para>
+
+      <programlisting>$ cd drools-solver/drools-solver-examples/
+$ mvn exec:exec -Dexec.mainClass="org.drools.solver.examples.app.ExamplesApp"
+...</programlisting>
+    </section>
+  </section>
+
+  <section>
+    <title>Questions, issues and patches</title>
+
+    <para>Your questions are welcome on <link xlink:href="http://www.jboss.org/drools/lists.html">the user mailing
+    list</link>. You can read/write to the mailing list without littering your mailbox through <link
+    xlink:href="nntp://news.gmane.org/gmane.comp.java.drools.user">this newsgroup</link>.</para>
+
+    <para>Feel free to report an issue (such as a bug, improvement or a new feature request) for the drools-solver code
+    or for this manual to <link xlink:href="https://jira.jboss.org/jira/browse/JBRULES">the drools JIRA</link>. Select
+    the component <literal>drools-solver</literal>.</para>
+
+    <para>Patches are very welcome and get priority treatment! Attach them to a JIRA issue and optionally send a mail to
+    the dev mailing list to get the issue fixed fast. By open sourcing your improvements, you 'll benefit from
+    improvements made upon your improvements.</para>
+  </section>
+</chapter>


Property changes on: labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Planner_introduction/Section-Planner_introduction.xml
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + text/plain

Copied: labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Score_calculation/Section-Score_calculation.xml (from rev 30778, labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Solver/Section-Score_calculation.xml)
===================================================================
--- labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Score_calculation/Section-Score_calculation.xml	                        (rev 0)
+++ labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Score_calculation/Section-Score_calculation.xml	2009-12-20 16:39:21 UTC (rev 30780)
@@ -0,0 +1,257 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
+                             http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd"
+         version="5.0" xml:base="./">
+
+  <title>Score calculation with a rule engine</title>
+
+  <section>
+    <title>Rule based score calculation</title>
+
+    <para>The score calculation of a planning problem is based on constraints (such as hard constraints, soft
+    constraints, rewards, ...). A rules engine, such as drools, makes 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>
+
+    <programlisting>rule "multipleQueensHorizontal"
+    when
+        $q1 : Queen($id : id, $y : y);
+        $q2 : Queen(id &gt; $id, y == $y);
+    then
+        insertLogical(new UnweightedConstraintOccurrence("multipleQueensHorizontal", $q1, $q2));
+end</programlisting>
+
+    <para>This score rule will fire once for every 2 queens with the same <literal>y</literal>. The <literal>(id &gt;
+    $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). Let's take a closer look at this score rule on the starting solution of 4 queens:</para>
+
+    <figure>
+      <title>Starting solution for the 4 queens puzzle</title>
+
+      <mediaobject>
+        <imageobject>
+          <imagedata fileref="images/Chapter-Score_calculation/unsolvedNQueens04.png" format="PNG"></imagedata>
+        </imageobject>
+      </mediaobject>
+    </figure>
+
+    <para>In this starting solution the multipleQueensHorizontal score rule will fire for 6 queen couples: (A, B), (A,
+    C), (A, D), (B, C), (B, D) and (C, D). Because none of the queens are on the same vertical or diagonal line, this
+    starting solution will have a score of <literal>-6</literal>. An optimal solution of 4 queens has a score of
+    <literal>0</literal>.</para>
+
+    <para>You need to add your score rules drl files in the solver configuration, for example:</para>
+
+    <programlisting>    &lt;scoreDrl&gt;/org/drools/solver/examples/nqueens/solver/nQueensScoreRules.drl&lt;/scoreDrl&gt;</programlisting>
+
+    <para>You can add multiple <literal>&lt;scoreDrl&gt;</literal> entries if needed.</para>
+
+    <para>It's recommended to use drools in forward-chaining mode (which is the default behaviour), as for 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 a single queen 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 a very complicated delta
+    based score calculation algorithm.</emphasis> Just let the drools rule engine do the hard work.</para>
+
+    <para><emphasis role="bold">Adding more constraints is <emphasis role="bold">easy and </emphasis>scalable</emphasis>
+    (once you understand the drools rule syntax). This allows you to add a bunch of soft constraint score rules on top
+    of the hard constraints score rules with little effort and at a reasonable performance cost. 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 ScoreDefinition interface</title>
+
+    <para>The <literal>ScoreDefinition</literal> interface defines the score representation. The score must a
+    <literal>Score</literal> instance and the instance type (for example <literal>DefaultHardAndSoftScore</literal>)
+    must be stable throughout the solver runtime.</para>
+
+    <para>The solver aims to find the solution with the highest score. <emphasis>The best solution</emphasis> is the
+    solution with the highest score that it has encountered during its solving.</para>
+
+    <para>Most planning problems tend to use negative scores (the amount of negative constraints being broken) with an
+    impossible perfect score of 0. This explains why the score of a solution of 4 queens is the negative of the number
+    of queen couples which can attack each other.</para>
+
+    <para>A <literal>ScoreDefinition</literal> instance is configured in the solver configuration:</para>
+
+    <programlisting>    &lt;scoreDefinition&gt;
+        &lt;scoreDefinitionType&gt;SIMPLE&lt;/scoreDefinitionType&gt;
+    &lt;/scoreDefinition&gt;</programlisting>
+
+    <para>There are a couple of build-in <literal>ScoreDefinition</literal> implementations:</para>
+
+    <itemizedlist>
+      <listitem>
+        <para>SIMPLE: The <literal>SimpleScoreDefinition</literal> defines the <literal>Score</literal> as a
+        <literal>SimpleScore</literal> which has a single int value, for example <literal>-123</literal>.</para>
+      </listitem>
+
+      <listitem>
+        <para>HARD_AND_SOFT: The <literal>HardAndSoftScoreDefinition</literal> defines the <literal>Score</literal> as a
+        <literal>HardAndSoftScore</literal> which has a hard int value and a soft int value, for example
+        <literal>-123hard/-456soft</literal>.</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>You can implement your own <literal>ScoreDefinition</literal>, although the build-in score definitions should
+    suffice for most needs.</para>
+
+    <para>A <literal>ScoreCalculator</literal> instance is asserted into the working memory as a global called
+    <literal>scoreCalculator</literal>. Your score rules need to (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"
+    when
+        $q1 : Queen($id : id, $y : y);
+        $q2 : Queen(id &gt; $id, y == $y);
+    then
+        insertLogical(new UnweightedConstraintOccurrence("multipleQueensHorizontal", $q1, $q2));
+end
+
+// multipleQueensVertical is obsolete because it is always 0
+
+rule "multipleQueensAscendingDiagonal"
+    when
+        $q1 : Queen($id : id, $ascendingD : ascendingD);
+        $q2 : Queen(id &gt; $id, ascendingD == $ascendingD);
+    then
+        insertLogical(new UnweightedConstraintOccurrence("multipleQueensAscendingDiagonal", $q1, $q2));
+end
+
+rule "multipleQueensDescendingDiagonal"
+    when
+        $q1 : Queen($id : id, $descendingD : descendingD);
+        $q2 : Queen(id &gt; $id, descendingD == $descendingD);
+    then
+        insertLogical(new UnweightedConstraintOccurrence("multipleQueensDescendingDiagonal", $q1, $q2));
+end
+
+rule "hardConstraintsBroken"
+    when
+        $occurrenceCount : Number() from accumulate(
+            $unweightedConstraintOccurrence : UnweightedConstraintOccurrence(),
+            count($unweightedConstraintOccurrence)
+        );
+    then
+        scoreCalculator.setScore(- $occurrenceCount.intValue());
+end</programlisting>
+
+    <para>Optionally, you can also weigh your constraints differently, by multiplying the count of each score rule with
+    its weight. For example in freight routing, you can make 5 broken "avoid crossroads" soft constraints count as much
+    as 1 broken "avoid highways at rush hour" soft constraint. This allows your business analysts to easily tweak the
+    score function as they see fit.</para>
+
+    <para>Here's an example of all the NQueens constraints written as a single rule, using multi pattern accumulates and
+    making multipleQueensHorizontal constraint outweigh the other constraints 5 times:</para>
+
+    <programlisting>// Warning: This currently triggers backwards chaining instead of forward chaining and seriously hurts performance and scalability.
+rule "constraintsBroken"
+    when
+        $multipleQueensHorizontal : Long()
+        from accumulate(
+            $q1 : Queen($id : id, $y : y)
+            and Queen(id &gt; $id, y == $y),
+           count($q1)
+        );
+        $multipleQueensAscendingDiagonal : Long()
+        from accumulate(
+            $q2 : Queen($id : id, $ascendingD : ascendingD)
+            and Queen(id &gt; $id, ascendingD == $ascendingD),
+           count($q2)
+        );
+        $multipleQueensDescendingDiagonal : Long()
+        from accumulate(
+            $q3 : Queen($id : id, $descendingD : descendingD)
+            and Queen(id &gt; $id, descendingD == $descendingD),
+           count($q3)
+        );
+    then
+        scoreCalculator.setScore(- (5 * $multipleQueensHorizontal) - $multipleQueensAscendingDiagonal - $multipleQueensDescendingDiagonal);
+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 n queens example doesn't have a "multipleQueensVertical" rule because a queen's
+        <literal>x</literal> never changes and the starting solution puts each queen on a different
+        <literal>x</literal>. This tends to give a huge performance gain, not just because the score function is faster,
+        but mainly because most solver implementations will spend less time evaluating unfeasible solutions.</para>
+      </listitem>
+
+      <listitem>
+        <para>Be watchfull for score traps. A score trap is a state in which several moves need to be done to resolve or
+        lower the weight of a single constraint occurrence. Some examples of score traps:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para>If you need 2 doctors at each table, but you're only moving 1 doctor at a time, then the solver has no
+            insentive to move a doctor to a table with no doctors. Punish a table with no doctors more then a table with
+            only 1 doctor in your score function.</para>
+          </listitem>
+
+          <listitem>
+            <para>If you only add the table as a cause of the ConstraintOccurrence and forget the jobType (which is
+            doctor or politician), then the solver has no insentive to move a docter to table which is short of a doctor
+            and a politician.</para>
+          </listitem>
+        </itemizedlist>
+      </listitem>
+
+      <listitem>
+        <para>If you use tabu search, combine it with a <literal>relativeSelection</literal> selector. Take some time to
+        tweak the value of <literal>relativeSelection</literal>.</para>
+      </listitem>
+
+      <listitem>
+        <para>Verify that your score calculation happens in the correct <literal>Number</literal> type. If you're making
+        the sum of integer values, don't let drools use Double's or your performance will hurt. Solver implementations
+        will usually spend most of their execution time running the score function.</para>
+      </listitem>
+
+      <listitem>
+        <para>Always remember that premature optimization is the root of all evil. Make sure your design is flexible
+        enough to allow configuration based tweaking.</para>
+      </listitem>
+
+      <listitem>
+        <para>Currently, don't allow drools to backward chain instead of forward chain, so avoid query's. It kills
+        scalibilty.</para>
+      </listitem>
+
+      <listitem>
+        <para>Currently, don't allow drools to switch to MVEL mode, for performance. You can avoid this by using
+        <literal>eval</literal> in the score rules, for example: <literal>eval(day.getIndex() == $day1.getIndex() +
+        3)</literal>.</para>
+      </listitem>
+
+      <listitem>
+        <para>For optimal performance, use at least java 1.6 and always use server mode (<literal>java
+        -server</literal>). We have seen performance increases of 30% by switching from java 1.5 to 1.6 and 50% by
+        turning on server mode.</para>
+      </listitem>
+
+      <listitem>
+        <para>If you're doing performance tests, always remember that the JVM needs to warm up. First load your solver
+        and do a short run, before you start benchmarking it.</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>In case you haven't figured it out yet: performance (and scalability) is very important for solving planning
+    problems. What good is a real-time freight routing solver that takes a day to find a feasible solution? Even small
+    and innocent looking problems can hide an enormous problem size. For example, they probably still don't know the
+    optimal solution of the traveling tournament problem for as little as 10 traveling teams.</para>
+  </section>
+</chapter>


Property changes on: labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Score_calculation/Section-Score_calculation.xml
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + text/plain

Copied: labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Use_cases_and_examples/Section-Use_cases_and_examples.xml (from rev 30778, labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Solver/Section-Solver_examples.xml)
===================================================================
--- labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Use_cases_and_examples/Section-Use_cases_and_examples.xml	                        (rev 0)
+++ labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Use_cases_and_examples/Section-Use_cases_and_examples.xml	2009-12-20 16:39:21 UTC (rev 30780)
@@ -0,0 +1,1003 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
+                             http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd"
+         version="5.0" xml:base="./">
+
+  <title>Solver examples</title>
+
+  <section>
+    <title>Introduction</title>
+
+    <para>Drools-solver has several examples. In this manual we explain drools-solver mainly using the n queens example.
+    So it's advisable to read at least the section about that example. For advanced users, the Examination example is
+    recommended.</para>
+
+    <para>You can find the source code of all these examples in the drools source distribution and also in subversion
+    under <literal>drools-solver/drools-solver-examples</literal>.</para>
+  </section>
+
+  <section>
+    <title>The n queens example</title>
+
+    <section>
+      <title>Screenshot</title>
+
+      <para>Here is a screenshot of the example:</para>
+
+      <figure>
+        <title>Screenshot of the n queens example</title>
+
+        <mediaobject>
+          <imageobject>
+            <imagedata fileref="images/Chapter-Use_cases_and_examples/screenshotNQueens.png"></imagedata>
+          </imageobject>
+        </mediaobject>
+      </figure>
+    </section>
+
+    <section>
+      <title>Problem statement</title>
+
+      <para>The <emphasis>n queens puzzle</emphasis> is a puzzle with the follow constraints:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>Use a chessboard of n rows and n columns.</para>
+        </listitem>
+
+        <listitem>
+          <para>Place n queens on the chessboard.</para>
+        </listitem>
+
+        <listitem>
+          <para>No 2 queens can attack each other. Note that a queen can attack any other queen on the same horizontal,
+          vertical or diagonal line.</para>
+        </listitem>
+      </itemizedlist>
+
+      <para>The most common n queens puzzle is the 8 queens puzzle, with <emphasis>n = 8</emphasis>. We 'll explain
+      drools-solver using the 4 queens puzzle as the primary example.</para>
+
+      <para>A proposed solution could be:</para>
+
+      <figure>
+        <title>A wrong solution for the 4 queens puzzle</title>
+
+        <mediaobject>
+          <imageobject>
+            <imagedata align="center" fileref="images/Chapter-Use_cases_and_examples/partiallySolvedNQueens04Explained.png" format="PNG"></imagedata>
+          </imageobject>
+        </mediaobject>
+      </figure>
+
+      <para>The above solution is wrong because queens A1 and B0 can attack each other (as can queens B0 and D0).
+      Removing queen B0 would respect the "no 2 queens can attack each other" constraint, but would break the "place n
+      queens" constraint.</para>
+    </section>
+
+    <section>
+      <title>Solution(s)</title>
+
+      <para>Below is a correct solution:</para>
+
+      <figure>
+        <title>A correct solution for the 4 queens puzzle</title>
+
+        <mediaobject>
+          <imageobject>
+            <imagedata align="center" fileref="images/Chapter-Use_cases_and_examples/solvedNQueens04.png" format="PNG"></imagedata>
+          </imageobject>
+        </mediaobject>
+      </figure>
+
+      <para>All the constraints have been met, so the solution is correct. Note that most n queens puzzles have multiple
+      correct solutions. We 'll focus on finding a single correct solution for a given n, not on finding the number of
+      possible correct solutions for a given n.</para>
+    </section>
+
+    <section>
+      <title>Problem size</title>
+
+      <para>These numbers might give you some insight on the size of this problem.</para>
+
+      <table>
+        <title>NQueens problem size</title>
+
+        <tgroup cols="5">
+          <thead>
+            <row>
+              <entry># queens (n)</entry>
+
+              <entry># possible solutions (each queen it's own column)</entry>
+
+              <entry># feasible solutions (distinct)</entry>
+
+              <entry># optimal solutions (distinct)</entry>
+
+              <entry># possible / # optimal</entry>
+            </row>
+          </thead>
+
+          <tbody>
+            <row>
+              <entry>4</entry>
+
+              <entry>256</entry>
+
+              <entry>2</entry>
+
+              <entry>2</entry>
+
+              <entry>128</entry>
+            </row>
+
+            <row>
+              <entry>8</entry>
+
+              <entry>16777216</entry>
+
+              <entry>64</entry>
+
+              <entry>64</entry>
+
+              <entry>262144</entry>
+            </row>
+
+            <row>
+              <entry>16</entry>
+
+              <entry>18446744073709551616</entry>
+
+              <entry>14772512</entry>
+
+              <entry>14772512</entry>
+
+              <entry>1248720872503</entry>
+            </row>
+
+            <row>
+              <entry>32</entry>
+
+              <entry>1.46150163733090291820368483e+48</entry>
+
+              <entry>?</entry>
+
+              <entry>?</entry>
+
+              <entry>?</entry>
+            </row>
+
+            <row>
+              <entry>64</entry>
+
+              <entry>3.94020061963944792122790401e+115</entry>
+
+              <entry>?</entry>
+
+              <entry>?</entry>
+
+              <entry>?</entry>
+            </row>
+
+            <row>
+              <entry>n</entry>
+
+              <entry>n ^ n</entry>
+
+              <entry>?</entry>
+
+              <entry># feasible solutions</entry>
+
+              <entry>?</entry>
+            </row>
+          </tbody>
+        </tgroup>
+      </table>
+
+      <para>The drools-solver implemenation has not been optimized because it functions as a beginner example.
+      Nevertheless, it can easily handle 64 queens.</para>
+    </section>
+
+    <section>
+      <title>Domain class diagram</title>
+
+      <para>Use a good domain model and it will be easier to understand and solve your problem with drools-solver. We
+      'll use this domain model for the n queens example:</para>
+
+      <figure>
+        <title>NQueens domain class diagram</title>
+
+        <mediaobject>
+          <imageobject>
+            <imagedata align="center" fileref="images/Chapter-Use_cases_and_examples/nQueensDomainDiagram.png" format="PNG"></imagedata>
+          </imageobject>
+        </mediaobject>
+      </figure>
+
+      <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 0, 1 is row 1, ...). 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 shown in the domain model</title>
+
+        <tgroup cols="6">
+          <thead>
+            <row>
+              <entry align="center">A solution</entry>
+
+              <entry align="center">Queen</entry>
+
+              <entry>x</entry>
+
+              <entry>y</entry>
+
+              <entry>ascendingD (x + y)</entry>
+
+              <entry>descendingD (x - y)</entry>
+            </row>
+          </thead>
+
+          <tbody>
+            <row>
+              <entry morerows="3"><mediaobject>
+                  <imageobject>
+                    <imagedata fileref="images/Chapter-Use_cases_and_examples/partiallySolvedNQueens04Explained.png" format="PNG"></imagedata>
+                  </imageobject>
+                </mediaobject></entry>
+
+              <entry>A1</entry>
+
+              <entry>0</entry>
+
+              <entry>1</entry>
+
+              <entry>1 (**)</entry>
+
+              <entry>-1</entry>
+            </row>
+
+            <row>
+              <entry>B0</entry>
+
+              <entry>1</entry>
+
+              <entry>0 (*)</entry>
+
+              <entry>1 (**)</entry>
+
+              <entry>1</entry>
+            </row>
+
+            <row>
+              <entry>C2</entry>
+
+              <entry>2</entry>
+
+              <entry>2</entry>
+
+              <entry>4</entry>
+
+              <entry>0</entry>
+            </row>
+
+            <row>
+              <entry>D0</entry>
+
+              <entry>3</entry>
+
+              <entry>0 (*)</entry>
+
+              <entry>3</entry>
+
+              <entry>3</entry>
+            </row>
+          </tbody>
+        </tgroup>
+      </table>
+
+      <para>A single <literal>NQueens</literal> instance contains a list of all <literal>Queen</literal> instances. 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>
+    </section>
+  </section>
+
+  <section>
+    <title>The lesson schedule example</title>
+
+    <section>
+      <title>Screenshot</title>
+
+      <para>Here is a screenshot of the example:</para>
+
+      <figure>
+        <title>Screenshot of the lesson schedule example</title>
+
+        <mediaobject>
+          <imageobject>
+            <imagedata fileref="images/Chapter-Use_cases_and_examples/screenshotLessonSchedule.png"></imagedata>
+          </imageobject>
+        </mediaobject>
+      </figure>
+    </section>
+
+    <section>
+      <title>Problem statement</title>
+
+      <para>Schedule lessons with the follow constraints:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>No teacher with 2 lessons in the same timeslot</para>
+        </listitem>
+
+        <listitem>
+          <para>No group with 2 lessons in the same timeslot</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+  </section>
+
+  <section>
+    <title>The traveling tournament example</title>
+
+    <section>
+      <title>Screenshot</title>
+
+      <para>Here is a screenshot of the example:</para>
+
+      <figure>
+        <title>Screenshot of the traveling tournament example</title>
+
+        <mediaobject>
+          <imageobject>
+            <imagedata fileref="images/Chapter-Use_cases_and_examples/screenshotTravelingTournament.png"></imagedata>
+          </imageobject>
+        </mediaobject>
+      </figure>
+    </section>
+
+    <section>
+      <title>Problem statement</title>
+
+      <para>Schedule matches between teams with the following hard constraints:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>Each team plays twice against every other team: once home and once away</para>
+        </listitem>
+
+        <listitem>
+          <para>Each team has exactly 1 match on each playing day</para>
+        </listitem>
+
+        <listitem>
+          <para>No more than 3 consecutive home or 3 consecutive away matches for any team</para>
+        </listitem>
+
+        <listitem>
+          <para>No repeaters: 2 consecutive matches of the same 2 teams (so each team plays once home and once
+          away</para>
+        </listitem>
+      </itemizedlist>
+
+      <para>and the following soft constraints:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>Minimize the total distance traveled of all teams.</para>
+        </listitem>
+      </itemizedlist>
+
+      <para><link xlink:href="http://mat.gsia.cmu.edu/TOURN/">You can find a detailed description as well as several
+      records of this problem here.</link></para>
+    </section>
+
+    <section>
+      <title>Simple and smart implementation</title>
+
+      <para>There are 2 implementations (simple and smart) to demonstrate the importance of some performance tips. The
+      <literal>ExamplesApp</literal> always runs the smart implementation, but with these commands you can compare the 2
+      implementations yourself:</para>
+
+      <programlisting>$ mvn exec:exec -Dexec.mainClass="org.drools.solver.examples.travelingtournament.app.simple.SimpleTravelingTournamentApp"
+...
+$ mvn exec:exec -Dexec.mainClass="org.drools.solver.examples.travelingtournament.app.smart.SmartTravelingTournamentApp"
+...</programlisting>
+
+      <para>The smart implementation performs and scales exponentially better than the simple implementation.</para>
+    </section>
+
+    <section>
+      <title>Problem size</title>
+
+      <para>These numbers might give you some insight on the size of this problem.</para>
+
+      <table>
+        <title>Traveling tournament problem size</title>
+
+        <tgroup cols="7">
+          <thead>
+            <row>
+              <entry># teams</entry>
+
+              <entry># days</entry>
+
+              <entry># matches</entry>
+
+              <entry># possible solutions (simple)</entry>
+
+              <entry># possible solutions (smart)</entry>
+
+              <entry># feasible solutions</entry>
+
+              <entry># optimal solutions</entry>
+            </row>
+          </thead>
+
+          <tbody>
+            <row>
+              <entry>4</entry>
+
+              <entry>6</entry>
+
+              <entry>12</entry>
+
+              <entry>2176782336</entry>
+
+              <entry>&lt;= 518400</entry>
+
+              <entry>?</entry>
+
+              <entry>1?</entry>
+            </row>
+
+            <row>
+              <entry>6</entry>
+
+              <entry>10</entry>
+
+              <entry>30</entry>
+
+              <entry>1000000000000000000000000000000</entry>
+
+              <entry>&lt;= 47784725839872000000</entry>
+
+              <entry>?</entry>
+
+              <entry>1?</entry>
+            </row>
+
+            <row>
+              <entry>8</entry>
+
+              <entry>14</entry>
+
+              <entry>56</entry>
+
+              <entry>1.52464943788290465606136043e+64</entry>
+
+              <entry>&lt;= 5.77608277425558771434498864e+43</entry>
+
+              <entry>?</entry>
+
+              <entry>1?</entry>
+            </row>
+
+            <row>
+              <entry>10</entry>
+
+              <entry>18</entry>
+
+              <entry>90</entry>
+
+              <entry>9.43029892325559280477052413e+112</entry>
+
+              <entry>&lt;= 1.07573451027871200629339068e+79</entry>
+
+              <entry>?</entry>
+
+              <entry>1?</entry>
+            </row>
+
+            <row>
+              <entry>12</entry>
+
+              <entry>22</entry>
+
+              <entry>132</entry>
+
+              <entry>1.58414112478195320415135060e+177</entry>
+
+              <entry>&lt;= 2.01650616733413376416949843e+126</entry>
+
+              <entry>?</entry>
+
+              <entry>1?</entry>
+            </row>
+
+            <row>
+              <entry>14</entry>
+
+              <entry>26</entry>
+
+              <entry>182</entry>
+
+              <entry>3.35080635695103223315189511e+257</entry>
+
+              <entry>&lt;= 1.73513467024013808570420241e+186</entry>
+
+              <entry>?</entry>
+
+              <entry>1?</entry>
+            </row>
+
+            <row>
+              <entry>16</entry>
+
+              <entry>30</entry>
+
+              <entry>240</entry>
+
+              <entry>3.22924601799855400751522483e+354</entry>
+
+              <entry>&lt;= 2.45064610271441678267620602e+259</entry>
+
+              <entry>?</entry>
+
+              <entry>1?</entry>
+            </row>
+
+            <row>
+              <entry>n</entry>
+
+              <entry>2 * (n - 1)</entry>
+
+              <entry>n * (n - 1)</entry>
+
+              <entry>(2 * (n - 1)) ^ (n * (n - 1))</entry>
+
+              <entry>&lt;= (((2 * (n - 1))!) ^ (n / 2))</entry>
+
+              <entry>?</entry>
+
+              <entry>1?</entry>
+            </row>
+          </tbody>
+        </tgroup>
+      </table>
+    </section>
+  </section>
+
+  <section>
+    <title>The ITC2007 examination example</title>
+
+    <section>
+      <title>Screenshot</title>
+
+      <para>Here is a screenshot of the example:</para>
+
+      <figure>
+        <title>Screenshot of the examination example</title>
+
+        <mediaobject>
+          <imageobject>
+            <imagedata fileref="images/Chapter-Use_cases_and_examples/screenshotExamination.png"></imagedata>
+          </imageobject>
+        </mediaobject>
+      </figure>
+    </section>
+
+    <section>
+      <title>Problem statement</title>
+
+      <para>Schedule each exam into a period and into a room. Multiple exams can share the same room during the same
+      period.</para>
+
+      <para>There are a number of hard constraints that cannot be broken:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>Exam conflict: 2 exams that share students should not occur in the same period.</para>
+        </listitem>
+
+        <listitem>
+          <para>Room capacity: A room's seating capacity should suffice at all times.</para>
+        </listitem>
+
+        <listitem>
+          <para>Period duration: A period's duration should suffice for all of its exams.</para>
+        </listitem>
+
+        <listitem>
+          <para>Period related hard constraints should be fulfilled:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para>Coincidence: 2 exams should use the same period (but possibly another room).</para>
+            </listitem>
+
+            <listitem>
+              <para>Exclusion: 2 exams should not use the same period.</para>
+            </listitem>
+
+            <listitem>
+              <para>After: 1 exam should occur in a period after another exam's period.</para>
+            </listitem>
+          </itemizedlist>
+        </listitem>
+
+        <listitem>
+          <para>Room related hard constraints should be fulfilled:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para>Exclusive: 1 exam should not have to share its room with any other exam.</para>
+            </listitem>
+          </itemizedlist>
+        </listitem>
+      </itemizedlist>
+
+      <para>There are also a number of soft constraints that should be minimized (each of which has parameterized
+      penalty's):</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>2 exams in a row.</para>
+        </listitem>
+
+        <listitem>
+          <para>2 exams in a day.</para>
+        </listitem>
+
+        <listitem>
+          <para>Period spread: 2 exams that share students should be a number of periods apart.</para>
+        </listitem>
+
+        <listitem>
+          <para>Mixed durations: 2 exams that share a room should not have different durations.</para>
+        </listitem>
+
+        <listitem>
+          <para>Front load: Large exams should be scheduled earlier in the schedule.</para>
+        </listitem>
+
+        <listitem>
+          <para>Period penalty: Some periods have a penalty when used.</para>
+        </listitem>
+
+        <listitem>
+          <para>Room penalty: Some rooms have a penalty when used.</para>
+        </listitem>
+      </itemizedlist>
+
+      <para>It uses large test data sets of real-life universities.</para>
+
+      <para><link xlink:href="http://www.cs.qub.ac.uk/itc2007/examtrack/exam_track_index.htm">You can find a more
+      detailed description of this problem here.</link></para>
+    </section>
+
+    <section>
+      <title>Problem size</title>
+
+      <para>These numbers might give you some insight on the size of this problem.</para>
+
+      <table>
+        <title>Examination problem size</title>
+
+        <tgroup cols="8">
+          <thead>
+            <row>
+              <entry>Set</entry>
+
+              <entry># students</entry>
+
+              <entry># exams/topics</entry>
+
+              <entry># periods</entry>
+
+              <entry># rooms</entry>
+
+              <entry># possible solutions</entry>
+
+              <entry># feasible solutions</entry>
+
+              <entry># optimal solutions</entry>
+            </row>
+          </thead>
+
+          <tbody>
+            <row>
+              <entry>exam_comp_set1</entry>
+
+              <entry>7883</entry>
+
+              <entry>607</entry>
+
+              <entry>54</entry>
+
+              <entry>7</entry>
+
+              <entry>10^1564</entry>
+
+              <entry>?</entry>
+
+              <entry>1?</entry>
+            </row>
+
+            <row>
+              <entry>exam_comp_set2</entry>
+
+              <entry>12484</entry>
+
+              <entry>870</entry>
+
+              <entry>40</entry>
+
+              <entry>49</entry>
+
+              <entry>10^2864</entry>
+
+              <entry>?</entry>
+
+              <entry>1?</entry>
+            </row>
+
+            <row>
+              <entry>exam_comp_set3</entry>
+
+              <entry>16365</entry>
+
+              <entry>934</entry>
+
+              <entry>36</entry>
+
+              <entry>48</entry>
+
+              <entry>10^3023</entry>
+
+              <entry>?</entry>
+
+              <entry>1?</entry>
+            </row>
+
+            <row>
+              <entry>exam_comp_set4</entry>
+
+              <entry>4421</entry>
+
+              <entry>273</entry>
+
+              <entry>21</entry>
+
+              <entry>1</entry>
+
+              <entry>10^360</entry>
+
+              <entry>?</entry>
+
+              <entry>1?</entry>
+            </row>
+
+            <row>
+              <entry>exam_comp_set5</entry>
+
+              <entry>8719</entry>
+
+              <entry>1018</entry>
+
+              <entry>42</entry>
+
+              <entry>3</entry>
+
+              <entry>10^2138</entry>
+
+              <entry>?</entry>
+
+              <entry>1?</entry>
+            </row>
+
+            <row>
+              <entry>exam_comp_set6</entry>
+
+              <entry>7909</entry>
+
+              <entry>242</entry>
+
+              <entry>16</entry>
+
+              <entry>8</entry>
+
+              <entry>10^509</entry>
+
+              <entry>?</entry>
+
+              <entry>1?</entry>
+            </row>
+
+            <row>
+              <entry>exam_comp_set7</entry>
+
+              <entry>13795</entry>
+
+              <entry>1096</entry>
+
+              <entry>80</entry>
+
+              <entry>28</entry>
+
+              <entry>10^3671</entry>
+
+              <entry>?</entry>
+
+              <entry>1?</entry>
+            </row>
+
+            <row>
+              <entry>exam_comp_set8</entry>
+
+              <entry>7718</entry>
+
+              <entry>598</entry>
+
+              <entry>80</entry>
+
+              <entry>8</entry>
+
+              <entry>10^1678</entry>
+
+              <entry>?</entry>
+
+              <entry>1?</entry>
+            </row>
+
+            <row>
+              <entry>?</entry>
+
+              <entry>s</entry>
+
+              <entry>t</entry>
+
+              <entry>p</entry>
+
+              <entry>r</entry>
+
+              <entry>(p * r) ^ e</entry>
+
+              <entry>?</entry>
+
+              <entry>1?</entry>
+            </row>
+          </tbody>
+        </tgroup>
+      </table>
+
+      <para>Geoffrey De Smet (the drools-solver lead) finished 4th in the International Timetabling Competition 2007's
+      examination track with a very early version of drools-solver. Many improvements have been made since then.</para>
+    </section>
+
+    <section>
+      <title>Domain class diagram</title>
+
+      <para>Below you can see the main examination domain classes:</para>
+
+      <figure>
+        <title>Examination domain class diagram</title>
+
+        <mediaobject>
+          <imageobject>
+            <imagedata fileref="images/Chapter-Use_cases_and_examples/examinationDomainDiagram.png"></imagedata>
+          </imageobject>
+        </mediaobject>
+      </figure>
+
+      <para>Notice that we've split up the exam concept into an <literal>Exam</literal> class and a
+      <literal>Topic</literal> class. The <literal>Exam</literal> instances change during solving, when they get another
+      period or room property. The <literal>Topic</literal>, <literal>Period</literal> and <literal>Room</literal>
+      instances never change during solving.</para>
+    </section>
+  </section>
+
+  <section>
+    <title>The ITC 2007 curriculum course example</title>
+
+    <section>
+      <title>Problem statement</title>
+
+      <para>Schedule lectures into rooms and time periods.</para>
+
+      <para><link xlink:href="http://www.cs.qub.ac.uk/itc2007/curriculmcourse/course_curriculm_index.htm">You can find a
+      more detailed description of this problem here.</link></para>
+    </section>
+  </section>
+
+  <section>
+    <title>The Manners 2009 example</title>
+
+    <section>
+      <title>Problem statement</title>
+
+      <para>In Manners 2009, miss Manners is throwing a party again.</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>This time she invited 144 guests and prepared 12 round tables with 12 seats each.</para>
+        </listitem>
+
+        <listitem>
+          <para>Every guest should sit next to someone (left and right) of the opposite gender.</para>
+        </listitem>
+
+        <listitem>
+          <para>And that neighbour should have at least one hobby in common with the guest.</para>
+        </listitem>
+
+        <listitem>
+          <para>Also, this time there should be 2 politicians, 2 doctors, 2 socialites, 2 sports stars, 2 teachers and 2
+          programmers at each table.</para>
+        </listitem>
+
+        <listitem>
+          <para>And the 2 politicians, 2 doctors, 2 sports stars and 2 programmers shouldn't be the same kind.</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+  </section>
+
+  <section>
+    <title>Patient admission scheduling (PAS)</title>
+
+    <para>In this problem, we have to assign each patient (that will come to the hospital) a bed for each night that the
+    patient will stay in the hospital. Each bed belongs to a room and each room belongs to a department. The arrival and
+    departure dates of the patients is fixed: only a bed needs to be assigned for each night.</para>
+
+    <para>There are a couple of hard constraints:</para>
+
+    <itemizedlist>
+      <listitem>
+        <para>2 patients shouldn't be assigned to the same bed in the same night.</para>
+      </listitem>
+
+      <listitem>
+        <para>A room can have a gender limitation: only females, only males, the same gender in the same night or no
+        gender limitation at all.</para>
+      </listitem>
+
+      <listitem>
+        <para>A departement can have a minimum or maximum age.</para>
+      </listitem>
+
+      <listitem>
+        <para>A patient can require a room with specific equipment(s).</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>And of course, there are also some soft constraints:</para>
+
+    <itemizedlist>
+      <listitem>
+        <para>A patient can prefer a maximum room size, for example if he/she want a single room.</para>
+      </listitem>
+
+      <listitem>
+        <para>A patient is best assigned to a department that specializes in his/her problem.</para>
+      </listitem>
+
+      <listitem>
+        <para>A patient is best assigned to a room that specializes in his/her problem.</para>
+      </listitem>
+
+      <listitem>
+        <para>A patient can prefer a room with specific equipment(s).</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>The problem is defined on <link xlink:href="http://allserv.kahosl.be/~peter/pas/">this webpage</link> and the
+    test data comes from real world hospitals.</para>
+  </section>
+</chapter>


Property changes on: labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/Chapter-Use_cases_and_examples/Section-Use_cases_and_examples.xml
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + text/plain

Modified: labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/master.xml
===================================================================
--- labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/master.xml	2009-12-20 13:18:11 UTC (rev 30779)
+++ labs/jbossrules/trunk/drools-docs/drools-docs-planner/src/main/docbook/en-US/master.xml	2009-12-20 16:39:21 UTC (rev 30780)
@@ -1,8 +1,12 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<book version="5.0" xmlns="http://docbook.org/ns/docbook"
-      xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xi="http://www.w3.org/2001/XInclude"
-      xmlns:svg="http://www.w3.org/2000/svg" xmlns:m="http://www.w3.org/1998/Math/MathML"
-      xmlns:html="http://www.w3.org/1999/xhtml" xmlns:db="http://docbook.org/ns/docbook">
+<book xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
+                             http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd"
+         version="5.0">
+
   <info>
     <title>Drools Planner User Guide</title>
 
@@ -16,6 +20,17 @@
     </author>
   </info>
 
-  <xi:include href="Chapter-Solver/Chapter-Solver.xml"/>
+	<xi:include href="Chapter-Planner_introduction/Section-Planner_introduction.xml" />
+
+	<xi:include href="Chapter-Use_cases_and_examples/Section-Use_cases_and_examples.xml" />
+
+	<xi:include href="Chapter-Planner_configuration/Section-Planner_configuration.xml" />
+
+	<xi:include href="Chapter-Score_calculation/Section-Score_calculation.xml" />
+
+	<xi:include href="Chapter-Local_search/Section-Local_search.xml" />
+
+	<xi:include href="Chapter-Benchmarking_and_tweaking/Section-Benchmarking_and_tweaking.xml" />
+
   <index/>
 </book>



More information about the jboss-svn-commits mailing list