[jboss-svn-commits] JBL Code SVN: r26249 - in labs/jbossrules/trunk/drools-docs/drools-docs-solver/src/main/docbook/en-US: Chapter-Solver and 1 other directory.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Fri Apr 24 14:51:18 EDT 2009
Author: ge0ffrey
Date: 2009-04-24 14:51:18 -0400 (Fri, 24 Apr 2009)
New Revision: 26249
Modified:
labs/jbossrules/trunk/drools-docs/drools-docs-solver/src/main/docbook/en-US/Chapter-Solver/Section-Local_Search_Solver.xml
labs/jbossrules/trunk/drools-docs/drools-docs-solver/src/main/docbook/en-US/Chapter-Solver/Section-Score_calculation.xml
labs/jbossrules/trunk/drools-docs/drools-docs-solver/src/main/docbook/en-US/Chapter-Solver/Section-Solver_configuration.xml
labs/jbossrules/trunk/drools-docs/drools-docs-solver/src/main/docbook/en-US/Chapter-Solver/Section-Solver_introduction.xml
labs/jbossrules/trunk/drools-docs/drools-docs-solver/src/main/docbook/en-US/master.xml
Log:
score refactor documentation update
Modified: labs/jbossrules/trunk/drools-docs/drools-docs-solver/src/main/docbook/en-US/Chapter-Solver/Section-Local_Search_Solver.xml
===================================================================
--- labs/jbossrules/trunk/drools-docs/drools-docs-solver/src/main/docbook/en-US/Chapter-Solver/Section-Local_Search_Solver.xml 2009-04-24 18:31:14 UTC (rev 26248)
+++ labs/jbossrules/trunk/drools-docs/drools-docs-solver/src/main/docbook/en-US/Chapter-Solver/Section-Local_Search_Solver.xml 2009-04-24 18:51:18 UTC (rev 26249)
@@ -1,115 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
-<section 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" xml:base="../../">
+<section version="5.0" xml:base="../../" 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">
<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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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 a couple 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>An algorithm that checks every possible solution (even with pruning) can easily run for a couple 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 making a move on the current solution
- to change 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>Local search solves a problem making a move on the current solution to change 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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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-Solver/singleMoveNQueens04.png" format="PNG" />
+ <imagedata fileref="images/Chapter-Solver/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>
+ <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>
+ <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>
+ <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>
+ <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>
@@ -121,14 +101,12 @@
</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>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>
+ <para>Each of your move types will be an implementation of the <literal>Move</literal> interface:</para>
<programlisting>public interface Move {
@@ -140,8 +118,8 @@
}</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>
+ <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 {
@@ -157,12 +135,10 @@
}</programlisting>
- <para>An instance of <literal>YChangeMove</literal> moves a queen from
- it's current y to a different y.</para>
+ <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
+ <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) {
@@ -172,64 +148,56 @@
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 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>
+ <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>
+ <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>
+ <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>
+ <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>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>
+ <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>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>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>
+ <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) {
@@ -252,31 +220,26 @@
.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>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>
+ <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 + " => " + toY;
}</programlisting>
- <para>Now that we can make a single move, let's take a look at generating
- moves.</para>
+ <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
+ <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>
@@ -284,39 +247,31 @@
<mediaobject>
<imageobject>
- <imagedata fileref="images/Chapter-Solver/possibleMovesNQueens04.png" format="PNG" />
+ <imagedata fileref="images/Chapter-Solver/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>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>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>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>
+ <para>Move generation currently happens with a <literal>MoveFactory</literal>:</para>
<programlisting>public class NQueensMoveFactory extends CachedMoveListMoveFactory {
@@ -339,50 +294,43 @@
<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>
+ <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-Solver/decideNextStepNQueens04.png" format="PNG" />
+ <imagedata fileref="images/Chapter-Solver/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
+ <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>
+ <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-Solver/allStepsNQueens04.png" format="PNG" />
+ <imagedata fileref="images/Chapter-Solver/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>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>
+ <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>
@@ -398,80 +346,68 @@
</listitem>
</orderedlist>
- <para>If we turn on INFO logging, this is reflected into the
- logging:</para>
+ <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.0) is starting best score. Updating best solution and best score.
+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 => 3).
-INFO New score (-3.0) is better then last best score (-6.0). Updating best solution and best score.
+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 => 2).
-INFO New score (-1.0) is better then last best score (-3.0). Updating best solution and best score.
+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 => 1).
-INFO New score (0.0) is better then last best score (-1.0). Updating best solution and best score.
+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 => 3</literal>.</para>
+ <para>Notice that the logging used the <literal>toString()</literal> method from our <literal>Move</literal>
+ implementation: <literal>[Queen-1] 1 @ 0 => 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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <para>A <emphasis>forager</emphasis> which gathers all accepted moves and picks the next step from them.</para>
</listitem>
</itemizedlist>
@@ -480,73 +416,73 @@
<mediaobject>
<imageobject>
- <imagedata fileref="images/Chapter-Solver/decideNextStepNQueens04.png" format="PNG" />
+ <imagedata fileref="images/Chapter-Solver/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>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>
+ <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.0) is starting best score. Updating best solution and best score.
+INFO Initial score (-6) is starting best score. Updating best solution and best score.
DEBUG Move ([Queen-0] 0 @ 0 => 0) ignored because not doable.
-DEBUG Move ([Queen-0] 0 @ 1 => 1) with score (-4.0) and acceptChance (1.0).
-DEBUG Move ([Queen-0] 0 @ 2 => 2) with score (-4.0) and acceptChance (1.0).
+DEBUG Move ([Queen-0] 0 @ 1 => 1) with score (-4) and acceptChance (1.0).
+DEBUG Move ([Queen-0] 0 @ 2 => 2) with score (-4) and acceptChance (1.0).
...
-DEBUG Move ([Queen-1] 1 @ 3 => 3) with score (-3.0) and acceptChance (1.0).
+DEBUG Move ([Queen-1] 1 @ 3 => 3) with score (-3) and acceptChance (1.0).
...
-DEBUG Move ([Queen-3] 3 @ 3 => 3) with score (-4.0) and acceptChance (1.0).
+DEBUG Move ([Queen-3] 3 @ 3 => 3) with score (-4) and acceptChance (1.0).
INFO Step (0), time spend (0) doing next step ([Queen-1] 1 @ 0 => 3).
-INFO New score (-3.0) is better then last best score (-6.0). Updating best solution and best score.
+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>.
- We're working on improving this.</para>
+ <para>A selector is currently based on a <literal>MoveFactory</literal>.</para>
<programlisting> <selector>
<moveFactoryClass>org.drools.solver.examples.nqueens.solver.NQueensMoveFactory</moveFactoryClass>
</selector></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>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> <selector>
+ <moveFactoryClass>org.drools.solver.examples.itc2007.examination.solver.move.factory.RoomChangeMoveFactory</moveFactoryClass>
+ <relativeSelection>0.002</relativeSelection>
+ </selector></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>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>
+ <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>
+ <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>
+ <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> <accepter>
<completeSolutionTabuSize>1000</completeSolutionTabuSize>
@@ -554,8 +490,8 @@
</listitem>
<listitem>
- <para><emphasis>Move tabu</emphasis> makes recent steps tabu. It
- does not accept a move equal to one of those steps.</para>
+ <para><emphasis>Move tabu</emphasis> makes recent steps tabu. It does not accept a move equal to one of
+ those steps.</para>
<programlisting> <accepter>
<completeMoveTabuSize>1000</completeMoveTabuSize>
@@ -563,8 +499,7 @@
</listitem>
<listitem>
- <para><emphasis>Undo move tabu </emphasis>makes the undo move of
- recent steps tabu.</para>
+ <para><emphasis>Undo move tabu </emphasis>makes the undo move of recent steps tabu.</para>
<programlisting> <accepter>
<completeUndoMoveTabuSize>1000</completeUndoMoveTabuSize>
@@ -572,17 +507,15 @@
</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>
+ <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> <accepter>
<completePropertyTabuSize>1000</completePropertyTabuSize>
</accepter></programlisting>
- <para>To use property tabu, your moves must implement the
- <literal>TabuPropertyEnabled</literal> interface, for
- example:</para>
+ <para>To use property tabu, your moves must implement the <literal>TabuPropertyEnabled</literal> interface,
+ for example:</para>
<programlisting>public class YChangeMove implements Move, TabuPropertyEnabled {
@@ -606,51 +539,44 @@
<completeUndoMoveTabuSize>10</completeUndoMoveTabuSize>
</accepter></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>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>
+ <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>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>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>
+ <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>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>
+ <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>
+ <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> <forager>
<foragerType>MAX_SCORE_OF_ALL</foragerType>
@@ -660,9 +586,8 @@
<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>
+ <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> <forager>
<foragerType>FIRST_BEST_SCORE_IMPROVING</foragerType>
@@ -672,9 +597,8 @@
<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>
+ <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> <forager>
<foragerType>FIRST_BEST_SCORE_IMPROVING</foragerType>
@@ -684,9 +608,8 @@
<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>
+ <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> <forager>
<foragerType>FIRST_RANDOMLY_ACCEPTED</foragerType>
@@ -698,29 +621,23 @@
<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>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>
</section>
<section>
<title>Finish</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 finish early anyway.</para>
+ <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 finish early anyway.</para>
- <para>You can configure when a local search solver needs to stop by
- configuring a Finish. You can implement your own
- <literal>Finish</literal>, although the build-in finishes should suffice
- for most needs.</para>
+ <para>You can configure when a local search solver needs to stop by configuring a Finish. You can implement your own
+ <literal>Finish</literal>, although the build-in finishes should suffice for most needs.</para>
<section>
<title>TimeMillisSpendFinish</title>
@@ -737,17 +654,13 @@
<maximumHouresSpend>1</maximumHouresSpend>
</finish></programlisting>
- <para>Note that the time taken by a
- <literal>StartingSolutionInitializer</literal> also is taken into
- account by this finish. 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 the time taken by a <literal>StartingSolutionInitializer</literal> also is taken into account by
+ this finish. 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 finish, 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>
+ <para>Note that if you use this finish, 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>
@@ -763,56 +676,56 @@
<section>
<title>FeasableScoreFinish</title>
- <para>Finishes when a feasible score has been reached. You can also use
- this finish if you know the perfect score, for example for 4
- queens:</para>
+ <para>Finishes when a feasible score has been reached. You can also use this finish if you know the perfect score,
+ for example for 4 queens:</para>
<programlisting> <finish>
- <feasableScore>0.0</feasableScore>
+ <feasableScore>0</feasableScore>
</finish></programlisting>
+
+ <para>For a solver problem with hard and soft contraints, you can define it like this:</para>
+
+ <programlisting> <finish>
+ <feasableScore>0hard/-5000soft</feasableScore>
+ </finish></programlisting>
</section>
<section>
<title>UnimprovedStepCountFinish</title>
- <para>Finishes when the best score hasn't improved in a number of
- steps:</para>
+ <para>Finishes when the best score hasn't improved in a number of steps:</para>
<programlisting> <finish>
<maximumUnimprovedStepCount>100</maximumUnimprovedStepCount>
</finish></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>
+ <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 finishes</title>
- <para>Finishes can be combined, for example: finish after 100 steps or
- if a score of 0.0 has been reached:</para>
+ <para>Finishes can be combined, for example: finish after 100 steps or if a score of 0 has been reached:</para>
<programlisting> <finish>
<finishCompositionStyle>OR</finishCompositionStyle>
<maximumStepCount>100</maximumStepCount>
- <feasableScore>0.0</feasableScore>
+ <feasableScore>0</feasableScore>
</finish></programlisting>
- <para>Alternatively you can use AND, for example: finish after reaching
- a feasible score of at least -100 and no improvements in 5 steps:</para>
+ <para>Alternatively you can use AND, for example: finish after reaching a feasible score of at least -100 and no
+ improvements in 5 steps:</para>
<programlisting> <finish>
<finishCompositionStyle>AND</finishCompositionStyle>
<maximumUnimprovedStepCount>5</maximumUnimprovedStepCount>
- <feasableScore>-100.0</feasableScore>
+ <feasableScore>-100</feasableScore>
</finish></programlisting>
- <para>This ensures it doesn't just finish after finding a feasible
- solution, but also makes any obvious improvements on that solution
- before finishing.</para>
+ <para>This ensures it doesn't just finish after finding a feasible solution, but also makes any obvious
+ improvements on that solution before finishing.</para>
</section>
</section>
</section>
Modified: labs/jbossrules/trunk/drools-docs/drools-docs-solver/src/main/docbook/en-US/Chapter-Solver/Section-Score_calculation.xml
===================================================================
--- labs/jbossrules/trunk/drools-docs/drools-docs-solver/src/main/docbook/en-US/Chapter-Solver/Section-Score_calculation.xml 2009-04-24 18:31:14 UTC (rev 26248)
+++ labs/jbossrules/trunk/drools-docs/drools-docs-solver/src/main/docbook/en-US/Chapter-Solver/Section-Score_calculation.xml 2009-04-24 18:51:18 UTC (rev 26249)
@@ -1,23 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
-<section 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" xml:base="../../">
+<section version="5.0" xml:base="../../" 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">
<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
+ <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>
+ <para>Here's an example of a constraint implemented as a score rule in drools:</para>
<programlisting>rule "multipleQueensHorizontal"
when
@@ -27,118 +22,86 @@
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 > $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>
+ <para>This score rule will fire once for every 2 queens with the same <literal>y</literal>. The <literal>(id >
+ $id)</literal> condition is needed to assure that for 2 queens A and B, it can only fire for (A, B) and not for (B,
+ A), (A, A) or (B, B). 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-Solver/unsolvedNQueens04.png" format="PNG" />
+ <imagedata fileref="images/Chapter-Solver/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
+ <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>
+ <para>You need to add your score rules drl files in the solver configuration, for example:</para>
<programlisting> <scoreDrl>/org/drools/solver/examples/nqueens/solver/nQueensScoreRules.drl</scoreDrl></programlisting>
- <para>You can add multiple <literal><scoreDrl></literal> entries if
- needed.</para>
+ <para>You can add multiple <literal><scoreDrl></literal> entries if needed.</para>
- <para>It's recommended to use drools in forward-chaining mode (which is
- the default behaviour), as for most solver implementations this will
- create the effect of a <emphasis>delta based score calculation</emphasis>
- instead of a full score calculation on each solution evaluation. For
- example, if 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>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> (if you understand the
- drools rule syntax). This allows you to add it a bunch of soft constraint
- score rules on top of the hard constraints score rules with 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>
+ <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 it 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 ScoreCalculator interface</title>
+ <title>The ScoreDefinition interface</title>
- <para>The <literal>ScoreCalculator</literal> interface allows the solver
- to calculate the score of the currently evaluated solution. The score must
- a <literal>Number</literal> instance and the instance type (for example
- <literal>Double</literal> or <literal>Integer</literal>) must be stable
- throughout the problem.</para>
+ <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>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 that can attack each other.</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>ScoreCalculator</literal> instance is configured in the
- solver configuration:</para>
+ <para>A <literal>ScoreDefinition</literal> instance is configured in the solver configuration:</para>
- <programlisting> <scoreCalculator>
- <scoreCalculatorType>SIMPLE</scoreCalculatorType>
- </scoreCalculator></programlisting>
+ <programlisting> <scoreDefinition>
+ <scoreDefinitionType>SIMPLE</scoreDefinitionType>
+ </scoreDefinition></programlisting>
- <para>There are a couple of build-in <literal>ScoreCalculator</literal>
- implementations:</para>
+ <para>There are a couple of build-in <literal>ScoreDefinition</literal> implementations:</para>
<itemizedlist>
<listitem>
- <para>SIMPLE: A <literal>SimpleScoreCalculator</literal> instance
- which has a <literal>setScore(Number)</literal> method for use in the
- score rules.</para>
+ <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_CONSTRAINTS: A
- <literal>HardAndSoftConstraintScoreCalculator</literal> instance,
- which has a <literal>setHardConstraintsBroken(Number)</literal> and a
- <literal>setSoftConstraintsBroken(Number)</literal> method for use in
- the score rules.</para>
+ <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>
-
- <listitem>
- <para>DYNAMIC_HARD_AND_SOFT_CONSTRAINTS: A special
- <literal>HardAndSoftConstraintScoreCalculator</literal> instance, for
- more information see the javadocs.</para>
- </listitem>
</itemizedlist>
- <para>You can implement your own <literal>ScoreCalculator</literal>,
- although the build-in score calculators should suffice for most
- needs.</para>
+ <para>You can implement your own <literal>ScoreDefinition</literal>, although the build-in score definitions should
+ suffice for most needs.</para>
- <para>The <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>
+ <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;
@@ -178,16 +141,13 @@
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>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>
+ <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"
@@ -220,64 +180,55 @@
<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>
+ <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>Verify that your score calculation happens in the correct Number
- 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>
+ <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>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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
</section>
Modified: labs/jbossrules/trunk/drools-docs/drools-docs-solver/src/main/docbook/en-US/Chapter-Solver/Section-Solver_configuration.xml
===================================================================
--- labs/jbossrules/trunk/drools-docs/drools-docs-solver/src/main/docbook/en-US/Chapter-Solver/Section-Solver_configuration.xml 2009-04-24 18:31:14 UTC (rev 26248)
+++ labs/jbossrules/trunk/drools-docs/drools-docs-solver/src/main/docbook/en-US/Chapter-Solver/Section-Solver_configuration.xml 2009-04-24 18:51:18 UTC (rev 26249)
@@ -1,32 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
-<section 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" xml:base="../../">
+<section version="5.0" xml:base="../../" 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">
<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>
+ <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>Brute force creates and evaluates every possible solution, usually by creating a search tree.</para>
<para>Advantages:</para>
<itemizedlist>
<listitem>
- <para>It finds an optimal solution. If there is more then 1 optimal
- solution, it finds all optimal solutions.</para>
+ <para>It finds an optimal solution. If there is more then 1 optimal solution, it finds all optimal
+ solutions.</para>
</listitem>
<listitem>
@@ -38,29 +33,27 @@
<itemizedlist>
<listitem>
- <para>It has a horrible performance and scalability. Mostly unusable
- for a real-world problem due to time constraints.</para>
+ <para>It has a horrible performance and scalability. Mostly unusable for a real-world problem due to time
+ constraints.</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>
+ <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>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 finds an optimal solution. If there is more then 1 optimal
- solution, it can find all optimal solutions if needed.</para>
+ <para>It finds an optimal solution. If there is more then 1 optimal solution, it can find all optimal
+ solutions if needed.</para>
</listitem>
</itemizedlist>
@@ -72,17 +65,15 @@
</listitem>
</itemizedlist>
- <para>Branch and bound is currently not implemented in
- drools-solver.</para>
+ <para>Branch and bound is currently not implemented in drools-solver.</para>
</section>
<section>
<title>Simplex</title>
- <para>Simplex turns all constraints and data into a big equation, which
- it transmutes into a mathematical function without local optima. It then
- finds an optimal solution to the planning problem by finding an optima
- of that mathematical function.</para>
+ <para>Simplex turns all constraints and data into a big equation, which it transmutes into a mathematical function
+ without local optima. It then finds an optimal solution to the planning problem by finding an optima of that
+ mathematical function.</para>
<para>Advantages:</para>
@@ -96,8 +87,7 @@
<itemizedlist>
<listitem>
- <para>It's usually rather complex and mathematical to implement
- constraints.</para>
+ <para>It's usually rather complex and mathematical to implement constraints.</para>
</listitem>
</itemizedlist>
@@ -107,37 +97,32 @@
<section>
<title>Local search (tabu search, simulated annealing, ...)</title>
- <para>Local search starts from an initial solution and evolves that
- single solution into a better and better solution. It uses a single
- search path of solutions. At each solution in this path it evaluates a
- number of possible moves on the solution and applies the most suitable
- move to take the step to the next solution.</para>
+ <para>Local search starts from an initial solution and evolves that single solution into a better and better
+ solution. It uses a single search path of solutions. At each solution in this path it evaluates a number of
+ possible 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>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>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>
+ <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>
+ <para>It's very scalable, even when adding extra constraints (at least in drools-solver's
+ implementation).</para>
</listitem>
<listitem>
- <para>It generally needs to worry about less negative hard
- constraints, because the move pattern can fulfill a number of the
- negative hard constraints.</para>
+ <para>It generally needs to worry about less negative hard constraints, because the move pattern can fulfill a
+ number of the negative hard constraints.</para>
</listitem>
</itemizedlist>
@@ -149,28 +134,25 @@
</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>
+ <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>
+ <para>Drools-solver implements local search, including tabu search and simulated annealing.</para>
</section>
</section>
<section>
<title>The Solver interface</title>
- <para>Every build-in solver implemented in drools-solver implements the
- <literal>Solver</literal> interface:</para>
+ <para>Every build-in solver implemented in drools-solver implements the <literal>Solver</literal> interface:</para>
<programlisting>public interface Solver {
void setStartingSolution(Solution solution);
- Number getBestScore();
+ Score getBestScore();
Solution getBestSolution();
void solve();
@@ -179,18 +161,15 @@
}</programlisting>
- <para>Solving a planning problem with drools-solver consists out of 4
- steps:</para>
+ <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>
+ <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>
+ <para>Set a starting solution on the solver, for example a 4 Queens puzzle instance.</para>
</listitem>
<listitem>
@@ -202,18 +181,16 @@
</listitem>
</orderedlist>
- <para>A <literal>Solver</literal> should currently directly be accessed
- from a single thread. Support from accessing it from a different thread,
- for example to finish solving early or to change the problem facts in
- real-time, will be added in future releases.</para>
+ <para>A <literal>Solver</literal> should currently directly be accessed from a single thread. Support from accessing
+ it from a different thread, for example to finish solving early or to change the problem facts in real-time, will be
+ added in future releases.</para>
</section>
<section>
<title>Building a solver</title>
- <para>You can build a <literal>Solver</literal> instance with the
- <literal>XmlSolverConfigurer</literal>. Configure it with a solver
- configuration xml file:</para>
+ <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");
@@ -224,11 +201,11 @@
<programlisting><?xml version="1.0" encoding="UTF-8"?>
<localSearchSolver>
<scoreDrl>/org/drools/solver/examples/nqueens/solver/nQueensScoreRules.drl</scoreDrl>
- <scoreCalculator>
- <scoreCalculatorType>SIMPLE</scoreCalculatorType>
- </scoreCalculator>
+ <scoreDefinition>
+ <scoreDefinitionType>SIMPLE</scoreDefinitionType>
+ </scoreDefinition>
<finish>
- <feasableScore>0.0</feasableScore>
+ <feasableScore>0</feasableScore>
</finish>
<selector>
<moveFactoryClass>org.drools.solver.examples.nqueens.solver.NQueensMoveFactory</moveFactoryClass>
@@ -241,21 +218,17 @@
</forager>
</localSearchSolver></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>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><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>
+ <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>
@@ -264,11 +237,9 @@
<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 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>
+ <para>You need to implement the <literal>Solution</literal> interface:</para>
<programlisting>public interface Solution {
@@ -278,8 +249,7 @@
}</programlisting>
- <para>For example, an NQueens instance just holds a list of all it's
- queens:</para>
+ <para>For example, an NQueens instance just holds a list of all it's queens:</para>
<programlisting>public class NQueens implements Solution {
@@ -292,10 +262,9 @@
<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>
+ <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<? extends Object> getFacts() {
return queenList;
@@ -305,9 +274,8 @@
<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
+ <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() {
@@ -320,12 +288,10 @@
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>
+ <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
@@ -348,8 +314,7 @@
<section>
<title>The starting solution</title>
- <para>First, you will need to make a starting solution and set that on the
- solver:</para>
+ <para>First, you will need to make a starting solution and set that on the solver:</para>
<programlisting>solver.setStartingSolution(startingSolution);</programlisting>
</section>
@@ -357,16 +322,15 @@
<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>
+ <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-Solver/unsolvedNQueens04.png" format="PNG" />
+ <imagedata fileref="images/Chapter-Solver/unsolvedNQueens04.png" format="PNG"></imagedata>
</imageobject>
</mediaobject>
</figure>
@@ -388,45 +352,39 @@
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>
+ <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>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>
+ <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>
+ <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>
+ <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>
+ <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
+ <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 {
@@ -437,15 +395,12 @@
}</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>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
+ <para>Here's an example on how you add the <literal>StartingSolutionInitializer</literal> to the
configuration:</para>
<programlisting><localSearchSolver>
@@ -459,32 +414,28 @@
<section>
<title>Solving a problem</title>
- <para>Solving a problem is quite easy once you have a solver and the
- starting solution:</para>
+ <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>
+ <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>
+ <title>Best solution for the 4 queens puzzle (also an optimal solution)</title>
<mediaobject>
<imageobject>
- <imagedata fileref="images/Chapter-Solver/solvedNQueens04.png" format="PNG" />
+ <imagedata fileref="images/Chapter-Solver/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>
+ <para>After a problem is solved, you can reuse the same solver instance to solve another problem (of the same
+ problem type).</para>
</section>
</section>
Modified: labs/jbossrules/trunk/drools-docs/drools-docs-solver/src/main/docbook/en-US/Chapter-Solver/Section-Solver_introduction.xml
===================================================================
--- labs/jbossrules/trunk/drools-docs/drools-docs-solver/src/main/docbook/en-US/Chapter-Solver/Section-Solver_introduction.xml 2009-04-24 18:31:14 UTC (rev 26248)
+++ labs/jbossrules/trunk/drools-docs/drools-docs-solver/src/main/docbook/en-US/Chapter-Solver/Section-Solver_introduction.xml 2009-04-24 18:51:18 UTC (rev 26249)
@@ -1,19 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
-<section 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" xml:base="../../">
+<section version="5.0" xml:base="../../" 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">
<title>Solver introduction</title>
<section>
<title>What is a Solver?</title>
- <para>Drools-solver combines a search algorithm with the power of the
- drools rule engine to solve planning problems. Good examples of such
- planning problems include:</para>
+ <para>Drools-solver combines a search algorithm with the power of the drools rule engine to solve planning problems.
+ Good examples of such planning problems include:</para>
<itemizedlist>
<listitem>
@@ -37,102 +33,90 @@
</listitem>
<listitem>
- <para><ulink
- url="http://en.wikipedia.org/wiki/Travelling_salesman_problem">The
- traveling salesman problem</ulink></para>
+ <para><ulink url="http://en.wikipedia.org/wiki/Travelling_salesman_problem">The traveling salesman
+ problem</ulink></para>
</listitem>
<listitem>
- <para><ulink url="http://mat.gsia.cmu.edu/TOURN/">The traveling
- tournament problem</ulink></para>
+ <para><ulink url="http://mat.gsia.cmu.edu/TOURN/">The traveling tournament problem</ulink></para>
</listitem>
<listitem>
- <para>Miss manners too (although drools-solver would solve this
- differently than the pure drools rule engine example)</para>
+ <para>Miss manners too (although drools-solver would solve 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>
+ <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>
+ <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>
+ <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>
+ <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
+ <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. We can break down the solutions of a planning
- problem into 3 categories:</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
+ <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.</para>
+ <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>
+ <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>
+ <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 an <emphasis role="bold">experimental</emphasis>
- module of Drools. The API is far from stable and backward incompatible
- changes occur now and then. A recipe to upgrade and apply those API
- changes between versions will be maintained soon.</para>
+ <para>Drools-solver is an <emphasis role="bold">beta</emphasis> 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>You can download an alfa release of Drools-solver from <ulink
- url="http://www.jboss.org/drools/downloads.html">the drools download
- site</ulink>.</para>
+ <para>You can download a beta release of Drools-solver from <ulink
+ url="http://www.jboss.org/drools/downloads.html">the drools download site</ulink>. It is also available on
+ <ulink />the jboss maven repository.</para>
</section>
<section>
<title>Building drools-solver and running an example</title>
- <para>You can also easily build it from source yourself. Check out drools
- from subversion and do a maven 2 build with the solver profile:</para>
+ <para>You can also easily build it from source yourself. Check out drools from subversion and do a maven 2 build
+ with the solver profile:</para>
<programlisting>$ svn checkout http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/ drools
...
@@ -140,29 +124,28 @@
$ mvn -Dmaven.test.skip clean install
...</programlisting>
- <para>After that, you can run any example directly from the command line,
- for example to run the n queens example, run:</para>
+ <para>After that, you can run any example directly from the command line, for example to run the n queens example,
+ run:</para>
<programlisting>$ cd drools-solver/drools-solver-examples/
$ mvn exec:exec -Dexec.mainClass="org.drools.solver.examples.nqueens.app.NQueensApp"
...</programlisting>
- <para>You will use drools-solver with the latest, unstable snapshot of the
- drools rule engine. If you would rather use a stable version of the drools
- rule engine, edit <literal>/drools-solver/pom.xml</literal> and overwrite
- the drools jar versions, before building and running the examples:</para>
+ <para>You will use drools-solver with the latest, unstable snapshot of the drools rule engine. If you would rather
+ use a stable version of the drools rule engine, edit <literal>/drools-solver/pom.xml</literal> and overwrite the
+ drools jar versions, before building and running the examples:</para>
<programlisting> <dependencyManagement>
<dependencies>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
- <version>4.0.3</version>
+ <version>5.0.1</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
- <version>4.0.3</version>
+ <version>5.0.1</version>
</dependency>
</dependencies>
</dependencyManagement></programlisting>
Modified: labs/jbossrules/trunk/drools-docs/drools-docs-solver/src/main/docbook/en-US/master.xml
===================================================================
--- labs/jbossrules/trunk/drools-docs/drools-docs-solver/src/main/docbook/en-US/master.xml 2009-04-24 18:31:14 UTC (rev 26248)
+++ labs/jbossrules/trunk/drools-docs/drools-docs-solver/src/main/docbook/en-US/master.xml 2009-04-24 18:51:18 UTC (rev 26249)
@@ -1,28 +1,27 @@
-<?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"
+<?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">
- <info>
- <title>Drools Solver (experimental)</title>
-
- <releaseinfo>5.0.1.SNAPSHOT</releaseinfo>
-
- <author>
- <firstname>Geoffrey</firstname>
-
- <surname>De Smet</surname>
- </author>
- </info>
-
- <!--
- <preface id="preface" revision="2"> <title>Preface</title>
-
- <mediaobject> <imageobject> <imagedata fileref="drools_logo.png" />
- </imageobject> </mediaobject> <para /> </preface>
- -->
-
-
- <xi:include href="Chapter-Solver/Chapter-Solver.xml" />
- <index />
+ <info>
+ <title>Drools Solver</title>
+
+ <releaseinfo>5.0.1.SNAPSHOT</releaseinfo>
+
+ <author>
+ <firstname>Geoffrey</firstname>
+ <surname>De Smet</surname>
+ </author>
+ </info>
+
+ <!--
+ <preface id="preface" revision="2"> <title>Preface</title>
+
+ <mediaobject> <imageobject> <imagedata fileref="drools_logo.png" />
+ </imageobject> </mediaobject> <para /> </preface>
+ -->
+
+
+ <xi:include href="Chapter-Solver/Chapter-Solver.xml" />
+ <index />
</book>
More information about the jboss-svn-commits
mailing list