[jboss-svn-commits] JBL Code SVN: r15300 - labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Sun Sep 23 07:05:53 EDT 2007
Author: ge0ffrey
Date: 2007-09-23 07:05:52 -0400 (Sun, 23 Sep 2007)
New Revision: 15300
Modified:
labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Local_Search_Solver.xml
labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Score_calculation.xml
labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Solver_configuration.xml
labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Solver_introduction.xml
Log:
rereading of all sections
Modified: labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Local_Search_Solver.xml
===================================================================
--- labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Local_Search_Solver.xml 2007-09-23 10:46:06 UTC (rev 15299)
+++ labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Local_Search_Solver.xml 2007-09-23 11:05:52 UTC (rev 15300)
@@ -38,8 +38,8 @@
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 than does that number of times
- till it is satisfied with the solution. It starts with the starting
+ 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
@@ -71,7 +71,7 @@
<title>A move</title>
<para>A move is the change from a solution A to a solution B. For example,
- here you can see a single move on the starting solution of 4 queens that
+ below you can see a single move on the starting solution of 4 queens that
moves a single queen to another row:</para>
<figure>
@@ -89,13 +89,14 @@
</figure>
<para>A move can have a small or large impact. In the above example, the
- move of queen C0 to C2 is a small move. Some moves are of the same type.
- Here are some possibilities for move types in 4 queens:</para>
+ 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 C0 to C2.</para>
+ example, move queen <emphasis>C0 to C2</emphasis>.</para>
</listitem>
<listitem>
@@ -105,11 +106,12 @@
<listitem>
<para>Move a single queen to another column. This is a small move. For
- example queen on C2 to A0 (placing it on top of queen A0).</para>
+ example, move queen <emphasis>C2 to A0</emphasis> (placing it on top
+ of queen A0).</para>
</listitem>
<listitem>
- <para>Add a queen to board at a certain row and column.</para>
+ <para>Add a queen to the board at a certain row and column.</para>
</listitem>
<listitem>
@@ -120,7 +122,7 @@
<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 this gives
+ 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
@@ -173,41 +175,49 @@
<itemizedlist>
<listitem>
- <para>A move that changes nothing on the current solution. For example
- a move in the starting solution to move queen B to y 1 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 a move to move a queen B to row 10 is not doable.</para>
+ example, moving queen B0 to row 10 is not doable because it would move
+ it outside the board limits.</para>
</listitem>
</itemizedlist>
- <para>For 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>A move that is currently non 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 C0 to C2 would be the move C2 to C0. An undo move can be
- created from a move, but only before the move has been done on the current
- solution.</para>
+ undo move of <emphasis>C0 to C2</emphasis> would be the move <emphasis>C2
+ to C0</emphasis>. An undo move can be created from a move, but only before
+ the move has been done on the current solution.</para>
<programlisting> public Move createUndoMove(WorkingMemory workingMemory) {
return new YChangeMove(queen, queen.getY());
}</programlisting>
+ <para>Notice that if C0 would have already been moved to C2, the undo move
+ would create the move <emphasis>C2 to C2</emphasis>, instead of the move
+ <emphasis>C2 to C0</emphasis>.</para>
+
+ <para>The local search solver can do and undo a move more than once, even
+ on different (successive) solutions.</para>
+
<para>A move must implement the <literal>equals()</literal> and
- <literal>hashcode()</literal> methods so that 2 moves which make the same
- change on a solution are equal.</para>
+ <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) {
@@ -230,8 +240,16 @@
.toHashCode();
}</programlisting>
+ <para>In the above example, the <literal>Queen</literal> class uses the
+ default <literal>Object</literal> <literal>equal()</literal> and
+ <literal>hashcode()</literal> implementations. Notice that it checks if
+ the other move is an instance of the same move type. This is important
+ because a move will be compared to a move with another move type if you're
+ using more then 1 move type.</para>
+
<para>It's also recommended to implement the <literal>toString()</literal>
- method as it will allow you to read drools-solver's logging:</para>
+ method as it allows you to read drools-solver's logging more
+ easily:</para>
<programlisting> public String toString() {
return queen + " => " + toY;
@@ -245,9 +263,9 @@
<title>Move generation</title>
<para>At each solution, local search will try all possible moves and pick
- the best move as the step 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>
+ the best move to change to the next solution. It's up to you to generate
+ those moves. Let's take a look at all the possible moves on the starting
+ solution of 4 queens:</para>
<figure>
<title>Possible moves at step 0 (4 queens example)</title>
@@ -267,14 +285,14 @@
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 make a
- move to every possible solution. Instead use a number of small moves which
- can be sequentially combined to get to every possible solution.</para>
+ ^ 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
+ 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 on a
long test run.</para>
@@ -286,7 +304,7 @@
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.</para>
+ solutions and exponentially outperformces the simple version.</para>
<para>Move generation currently happens with a
<literal>MoveFactory</literal>:</para>
@@ -313,7 +331,8 @@
<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:</para>
+ 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>
@@ -329,15 +348,15 @@
</mediaobject>
</figure>
- <para>Because the move <emphasis>B0 to 3</emphasis> has the highest score
+ <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 3</emphasis> (not shown) could also have been picked
- because it also has score <literal>-3</literal>. If multiple moves have
- the same highest score, one is picked randomly, in this case <emphasis>B0
- to 3</emphasis>.</para>
+ <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 the possible moves again, to decide the next step after that. It
+ 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>
@@ -366,15 +385,15 @@
<orderedlist>
<listitem>
- <para><emphasis>B0 to 3</emphasis></para>
+ <para><emphasis>B0 to B3</emphasis></para>
</listitem>
<listitem>
- <para><emphasis>D0 to 2</emphasis></para>
+ <para><emphasis>D0 to B2</emphasis></para>
</listitem>
<listitem>
- <para><emphasis>A0 to 1</emphasis></para>
+ <para><emphasis>A0 to B1</emphasis></para>
</listitem>
</orderedlist>
@@ -387,7 +406,7 @@
INFO New score (-3.0) is better then last best score (-6.0). 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 Step (2), time spend (0) doing next step ([Queen-0] 0 @ 0 => 1).
+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 Solved in 3 steps and 15 time millis spend.</programlisting>
@@ -407,8 +426,8 @@
<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
- forces to take a next step that leads to a solution Y with score -2,
- however it's very real that after that it will pick the step back to
+ 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>
@@ -419,32 +438,33 @@
</listitem>
</itemizedlist>
- <para>Luckily drools-solver implements better local searches, such tabu
- search and simulated annealing which don't have 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>Luckily drools-solver implements better local searches, such
+ <emphasis>tabu search</emphasis> and <emphasis>simulated
+ annealing</emphasis> which don't have 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 3
- components:</para>
+ <para>The local search solver decides the next step with the aid of 3
+ configurable components:</para>
<itemizedlist>
<listitem>
- <para>A selector 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 accepter which filters out unacceptable moves. It can also
- weigh the moves 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 forager 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>
@@ -464,7 +484,7 @@
<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 3</emphasis>.</para>
+ move <emphasis>B0 to B3</emphasis>.</para>
<para>If we turn on DEBUG logging, we can see the decision making in the
log:</para>
@@ -479,7 +499,8 @@
...
DEBUG Move ([Queen-3] 3 @ 3 => 3) with score (-4.0) 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.</programlisting>
+INFO New score (-3.0) is better then last best score (-6.0). Updating best solution and best score.
+...</programlisting>
<section>
<title>Selector</title>
@@ -507,7 +528,7 @@
<para>You can implement your own <literal>Accepter</literal>, although
the build-in accepters should suffice for most needs. You can also
- combine several accepters, although that's probably a bad idea.</para>
+ combine multiple accepters.</para>
<section>
<title>Tabu search accepter</title>
@@ -520,7 +541,7 @@
<listitem>
<para><emphasis>Solution tabu</emphasis> makes recently visited
solutions tabu. It does not accept a move that leads to one of
- those solutions.</para>
+ those solutions. We recommend this type of tabu.</para>
<programlisting> <accepter>
<completeSolutionTabuSize>1000</completeSolutionTabuSize>
@@ -547,8 +568,8 @@
<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>
+ 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>
@@ -573,15 +594,15 @@
</listitem>
</itemizedlist>
- <para>You can even combine them:</para>
+ <para>You can even combine tabu types:</para>
<programlisting> <accepter>
<completeSolutionTabuSize>1000</completeSolutionTabuSize>
<completeUndoMoveTabuSize>10</completeUndoMoveTabuSize>
</accepter></programlisting>
- <para>Tabu search should be used with a
- <literal>MaxScoreOfAllForager</literal> or a
+ <para>A tabu search accepter should be used with a
+ <literal>MaxScoreOfAllForager</literal> (recommended) or a
<literal>FirstImprovingScoreForager</literal>.</para>
</section>
@@ -589,13 +610,14 @@
<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. It gives
- unimproving moves a chance, depending on it's score and the
- temperature. The temperature depends on how long it has been solving.
- In the end, it gradually turns into a simple local search, only
- accepting improving moves.</para>
+ score, neither does it evaluate all moves. At least at first.</para>
- <para>Simulated annealing must be used with a
+ <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 used with a
<literal>FirstRandomlyAcceptedForager</literal>.</para>
</section>
</section>
@@ -628,7 +650,7 @@
<title>First improving score forager</title>
<para>Picks the first accepted move that improves the score of the
- current solution. Ignores accept chance.</para>
+ current solution. It ignores accept chance.</para>
</section>
<section>
@@ -655,14 +677,14 @@
<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 it can't be is because the
- optimal solution has been reached (unless you know the perfect 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 much of a problem,
- because finding the optimal solution would take years (or centuries), so
- you 'll want to finish early anyway.</para>
+ 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 solver search solver needs to stop by
+ <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>
@@ -697,7 +719,7 @@
<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 in 4
+ this finish if you know the perfect score, for example for 4
queens:</para>
<programlisting> <finish>
@@ -717,8 +739,9 @@
<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
- in several problems, that once a new best solution is found, the next
- few step tend to give an even better solution.</para>
+ 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>
Modified: labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Score_calculation.xml
===================================================================
--- labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Score_calculation.xml 2007-09-23 10:46:06 UTC (rev 15299)
+++ labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Score_calculation.xml 2007-09-23 11:05:52 UTC (rev 15300)
@@ -5,7 +5,7 @@
<section>
<title>Rule based score calculation</title>
- <para>Score calculation of a planning problem is based on constraints
+ <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>
@@ -28,9 +28,9 @@
<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>
+ 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>
@@ -50,8 +50,8 @@
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>. More
- on that later.</para>
+ 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>
@@ -78,7 +78,7 @@
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 a reasonable performance cost. For example, for a freight routing
+ 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>
@@ -94,12 +94,12 @@
<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 encounters during its solving.</para>
+ 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 is why the score of a solution of 4 queens is the negative of the
- number of queen couples that can attack each other.</para>
+ 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>A <literal>ScoreCalculator</literal> instance is configured in the
solver configuration:</para>
@@ -133,13 +133,14 @@
</listitem>
</itemizedlist>
- <para>You can plug in your own custom <literal>ScoreCalculator</literal>
- too.</para>
+ <para>You can implement your own <literal>ScoreCalculator</literal>,
+ although the build-in score calculators 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 will (indirectly) update that instance. Usually you 'll make a
- single rule as an aggregation of the other rules to update the
+ 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;
@@ -211,16 +212,21 @@
<itemizedlist>
<listitem>
<para>If you know a certain constraint can never be broken, don't
- bother writing a score rule for it. For example the NQueens example
+ 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. This gives a performance gain,
- because</para>
+ <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 nothing but integer values, don't
- let drools use Double's or your performance will hurt.</para>
+ 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>
@@ -230,30 +236,35 @@
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. But always remember that premature optimization
- is the root of all evil.</para>
+ as 10 traveling teams.</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>, for
- example: <literal>eval(day.getIndex() == $day1.getIndex() +
- 3)</literal>.</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.</para>
+ forward chain, so avoid query's. It kills scalibilty.</para>
</listitem>
<listitem>
- <para>If performance is important (and it will), 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>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>If performance is important (and it will be), 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>
Modified: labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Solver_configuration.xml
===================================================================
--- labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Solver_configuration.xml 2007-09-23 10:46:06 UTC (rev 15299)
+++ labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Solver_configuration.xml 2007-09-23 11:05:52 UTC (rev 15300)
@@ -31,7 +31,7 @@
</listitem>
<listitem>
- <para>Set a starting solution on the solver, for example an 4 Queens
+ <para>Set a starting solution on the solver, for example a 4 Queens
puzzle instance.</para>
</listitem>
@@ -54,7 +54,7 @@
<title>Building a solver</title>
<para>You can build a <literal>Solver</literal> instance with the
- <literal>XmlSolverConfigurer</literal> by configuring it with a solver
+ <literal>XmlSolverConfigurer</literal>. Configure it with a solver
configuration xml file:</para>
<programlisting> XmlSolverConfigurer configurer = new XmlSolverConfigurer();
@@ -83,7 +83,7 @@
</forager>
</localSearchSolver></programlisting>
- <para>This is a tabu search configuration for NQueens. We 'll explain the
+ <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
@@ -91,25 +91,23 @@
There's even a benchmark utility which allows you to play out different
configurations against each other and report the most appropriate
configuration for your problem. You could for example play out tabu search
- versus simulated annealing, on a set of instances of your planning
- problem.</para>
+ versus simulated annealing, on 4 queens and 64 queens.</para>
<para>A solver has a single <literal>Random</literal> instance. Some
- solver configuration 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 see that <literal>Random</literal> instance, so
- your tests are reproducible.</para>
+ solver configurations use that instance a lot more than others. For
+ example simulated annealing depends highly on random numbers, while tabu
+ search only depends on it to deal with score ties. In any case, during
+ your testing it's advisable to set that <literal>Random</literal>
+ instance, so your tests are reproducible.</para>
</section>
<section>
<title>The Solution interface</title>
- <para>A Solver can only solve 1 problem at a time. One problem has a lot
- of solutions, but few optimal solutions.</para>
+ <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. Usually you will make
+ <literal>Solution</literal> instance to the solver. Usually you will make
that starting solution with a simple filler algorithm. For example for 4
queens we use a starting solution with all queens on a different x and on
the same y (with y = 0).</para>
@@ -132,7 +130,8 @@
feasible), but that's OK, as it's the solver's job to find a much better
solution.</para>
- <para>Here is the <literal>Solution</literal> interface:</para>
+ <para>You need to implement the <literal>Solution</literal>
+ interface:</para>
<programlisting>public interface Solution {
@@ -142,14 +141,37 @@
}</programlisting>
+ <para>For example:</para>
+
+ <programlisting>public class NQueens implements Solution {
+
+ private List<Queen> queenList;
+
+ // ...
+
+}</programlisting>
+
<para>Most solvers use the <literal>cloneSolution()</literal> method to
clone the solution each time they encounter a new best solution. The
- <literal>cloneSolution()</literal> method should clone no more and no less
- than the parts of the <literal>Solution</literal> that can change during
- solving. For example, in the lesson schedule example the lessons are
- cloned, but teachers, groups and timeslots are not cloned because only a
- lesson's appointed timeslot changes during solving:</para>
+ <literal>NQueens</literal> implementation just clones all
+ <literal>Queen</literal> instances:</para>
+ <programlisting> public NQueens cloneSolution() {
+ NQueens clone = new NQueens();
+ List<Queen> clonedQueenList = new ArrayList<Queen>(queenList.size());
+ for (Queen queen : queenList) {
+ clonedQueenList.add(queen.clone());
+ }
+ clone.queenList = clonedQueenList;
+ return clone;
+ }</programlisting>
+
+ <para>The <literal>cloneSolution()</literal> method should clone no more
+ and no less than the parts of the <literal>Solution</literal> that can
+ change during solving. For example, in the lesson schedule example the
+ lessons are cloned, but teachers, groups and timeslots are not cloned
+ because only a lesson's appointed timeslot changes during solving:</para>
+
<programlisting> /**
* Clone will only deep copy the lessons
*/
@@ -166,13 +188,10 @@
return clone;
}</programlisting>
- <para>The <literal>NQueens</literal> implementation just clones all
- <literal>Queen</literal> instances.</para>
-
<para>All Objects returned by the <literal>getFacts()</literal> method
will be asserted into the drools working memory. Those facts can be used
- by the score calculation rules. For example, <literal>NQueens</literal>
- just returns all <literal>Queen</literal> instances.</para>
+ 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;
Modified: labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Solver_introduction.xml
===================================================================
--- labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Solver_introduction.xml 2007-09-23 10:46:06 UTC (rev 15299)
+++ labs/jbossrules/trunk/documentation/manual/en/Chapter-Solver/Section-Solver_introduction.xml 2007-09-23 11:05:52 UTC (rev 15300)
@@ -11,8 +11,8 @@
those API changes between versions will be maintained soon.</para>
<para>No releases have been made yet, but you can easily build it from
- source yourself by checking out drools and building with the solver
- profile:</para>
+ source yourself by checking out drools and doing a maven 2 build with the
+ solver profile:</para>
<programlisting>$ svn checkout http://anonsvn.labs.jboss.com/labs/jbossrules/trunk/ drools
...
@@ -20,7 +20,7 @@
$ mvn -Psolver clean install
...</programlisting>
- <para>After that, you can run an example directly from the command line
+ <para>After that, you can run any example directly from the command line
like this:</para>
<programlisting>$ cd drools-solver/drools-solver-examples/
@@ -89,35 +89,56 @@
<itemizedlist>
<listitem>
- <para>A <emphasis role="bold">(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 role="bold">(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 role="bold">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>The constraints define the score function of a planning problem.
- Planning problems tend to have a very large number of possible solutions.
- Each solution has a score. Most of those solutions are not feasible,
- because they break a negative hard constraint. Usually, of all the
- feasible solutions (if any), there is only 1 optimal solution, but
- sometimes there are a few.</para>
+ <para>These constraints define the <emphasis>score function</emphasis> of
+ a planning problem. A planning problem has a number of
+ <emphasis>solutions</emphasis>. Each possible solution has a score. We can
+ break down the solutions to a planning problem into 3 categories:</para>
- <para>The drools rule engine turns out to be a very good way to implement
- a score function based on a number of rule constraints.</para>
+ <itemizedlist>
+ <listitem>
+ <para>A <emphasis>possible solution</emphasis> is a solution that does
+ or does not break any number of constraints. Planning problems tend to
+ have a incredibly large number of possible solutions. Most of those
+ solutions are worthless.</para>
+ </listitem>
+
+ <listitem>
+ <para>A <emphasis>feasible solution</emphasis> is a solution that does
+ not break any (negative) hard constraints. The number of feasible
+ solutions tends to be relative to the number of possible solutions.
+ Sometimes there are no feasible solutions.</para>
+ </listitem>
+
+ <listitem>
+ <para>An <emphasis>optimal solution</emphasis> is a solution with the
+ highest score. Planning problems tend to have 1 or a few optimal
+ solutions. There is always at least 1 optimal solution, even in the
+ remote case that it's not a feasible solution because there are no
+ feasible solutions.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>As we'll see later, <emphasis role="bold">the drools rule engine
+ turns out to be a very good way to implement a score
+ function</emphasis>.</para>
</section>
<section>
@@ -125,7 +146,7 @@
<para>Different solvers solve problems in different ways. Each type has
advantages and disadvantages. We 'll roughly discuss a few of the solver
- types. You can safely skip this section.</para>
+ types here. You can safely skip this section.</para>
<section>
<title>Brute force</title>
@@ -165,7 +186,7 @@
<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 found at that point.</para>
+ best solution already found at that point.</para>
<para>Advantages:</para>
@@ -191,10 +212,10 @@
<section>
<title>Simplex</title>
- <para>Simplex turns all constraints into a big equation, which it than
+ <para>Simplex turns all constraints into a big equation, which it
transmutes into a mathematical function without local optima. It then
- finds an optimal solution by finding an optima of that mathematical
- function.</para>
+ finds an optimal solution to the planning problem by finding an optima
+ of that mathematical function.</para>
<para>Advantages:</para>
@@ -226,7 +247,8 @@
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 very good solution.</para>
+ search path and moves facts around to find a good feasible
+ solution.</para>
<para>A vanilla local search can easily get stuck in a local optima, but
improvements (such as tabu search and simulated annealing) address this
@@ -246,8 +268,9 @@
</listitem>
<listitem>
- <para>Generally needs less negative hard constraints, as the move
- pattern fulfills 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>
@@ -259,7 +282,7 @@
</listitem>
<listitem>
- <para>If the perfect score is unknown (which is usually the case),
+ <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>
@@ -276,8 +299,8 @@
<section>
<title>Problem statement</title>
- <para>The n queens puzzle is a puzzle with the follow
- constraints:</para>
+ <para>The <emphasis>n queens puzzle</emphasis> is a puzzle with the
+ follow constraints:</para>
<itemizedlist>
<listitem>
@@ -295,9 +318,9 @@
</listitem>
</itemizedlist>
- <para>The most common puzzle is the 8 queens puzzle, with <emphasis>n =
- 8</emphasis>. We 'll explain drools-solver using the 4 queens puzzle as
- the primary example.</para>
+ <para>The most common n queens puzzle is the 8 queens puzzle, with
+ <emphasis>n = 8</emphasis>. We 'll explain drools-solver using the 4
+ queens puzzle as the primary example.</para>
<para>A proposed solution could be:</para>
@@ -378,7 +401,7 @@
chessboard.</para>
<table>
- <title>A solution for the 4 queens puzzle show in the domain
+ <title>A solution for the 4 queens puzzle shown in the domain
model</title>
<tgroup cols="6">
@@ -407,7 +430,7 @@
</imageobject>
</mediaobject></entry>
- <entry>A2</entry>
+ <entry>A1</entry>
<entry>0</entry>
@@ -419,7 +442,7 @@
</row>
<row>
- <entry>B1</entry>
+ <entry>B0</entry>
<entry>1</entry>
@@ -431,7 +454,7 @@
</row>
<row>
- <entry>C3</entry>
+ <entry>C2</entry>
<entry>2</entry>
@@ -443,7 +466,7 @@
</row>
<row>
- <entry>D1</entry>
+ <entry>D0</entry>
<entry>3</entry>
@@ -458,10 +481,10 @@
</table>
<para>A single <literal>NQueens</literal> instance contains a list of
- all Queens. It is the <literal>Solution</literal> implementation which
- will be supplied to and retrieved from drools-solver. Notice that in the
- 4 queens example, NQueens's <literal>getN()</literal> method will always
- return 4.</para>
+ all <literal>Queen</literal> instances. It is the
+ <literal>Solution</literal> implementation which will be supplied to and
+ retrieved from drools-solver. Notice that in the 4 queens example,
+ NQueens's <literal>getN()</literal> method will always return 4.</para>
<para>You can find the source code of this example (as well as well as
several other examples) in the drools-solver-examples src
More information about the jboss-svn-commits
mailing list