I think you're confusing what a Solution is or should be.
A solution, say
public class AttackSequence implements Solution
should have all the static facts (= facts that don't changes during
planning such as starting army size and starting land mass per country)
and also a collection of attacks:
private Set<Attack> attackSet; // Can be a list too, but I would NOT
say the order of the list is the attack order
Then an attack is
public class Attack {
private int sequence; // This defines the order in which the
attacks run. Must be unique over all Attack instances!
private Attacker attacker;
private Target target;
}
OK, so a Solution is just a sequence of attacks.
So what's a Move?
A move is going from Solution A to solution B.
For example: switch the sequence number of 2 Attack instances on
Solution A and you get Solution B.
So what about the Score?
Your score rules should detect things like you spoke off and affect the
score of that solution accordingly.
when
// There is an attack
Attack ($s : sequence, $t : target)
// And the next attack is on the same target
Attack (sequence == $s + 1, target == $t)
then
// affect the score
Op 13-01-11 23:03, aliquip schreef:
I’ve known about drools planner for quite some time and always wanted
to play
with it, but now that I finally found something to solve with it, I’m afraid
that I don’t fully understand drools planner, or I’m simply using it wrong.
The problem I try to solve/optimize is optimizing a sequence of events,
where each event can be influence by the previous events.
Background info (not essential for my main question):
-----------------------------------------------------------------------
More specifically I try to optimize a series of “attacks” for the webgame
utopia, so that they do most damage, each attack changes the targets. To put
it simply:
We have the following attackers and targets
1. Attacker A: [offense :55, nw:100, attacks_made: 0]
2. Attacker B: [offense :75, nw:150, attacks_made: 0]
3. Attacker C: [offense :40, nw:80, attacks_made: 0]
1. Target A: [defense :30, nw:50, land:500]
2. Target B: [defense :21, nw:50, land: 500]
3. Target C: [defense :60, nw:80, land: 800]
Particularities: each attacker can, at max make 4 attacks, but each attack
uses offense. Each attack destroys defense, nw and land. Attacks take 10% of
land or less (less when nw attacker is largetly different from that of the
target).
So for example the following sequence is possible
• Attacker B: [offense :80, nw:150, attacks_made: 0] attacks Target C:
[defense :60, nw:80, land: 800]
• -> new status Attacker B: [offense :20, nw:150, attacks_made: 1]
• -> new status Target C: [defense :54, nw:70, land: 720]
• Attacker A: [offense :55, nw:100, attacks_made: 0] attacks Target C:
[defense :54, nw:70, land: 720]
• -> new status Attacker A: [offense 1, nw:100, attacks_made: 1]
• -> new status Target C: [defense :49, nw:65, land: 620]
• Attacker C: [offense :40, nw:80, attacks_made: 0] attacks Target B:
[defense :21, nw:50, land: 500]
• new status Attacker C xxxx
• new status Target B: [defense :19, nw:45, land: 450]>Now Attacker B can
attack this target<
• Attacker B: [offense :20, nw:150, attacks_made: 1] attacks Target B:
[defense :19, nw:45, land: 450
• etc
• etc
In my implementation, the solver has a sequence of attack. The possible
moves are attacks and undo attacks. Undo attacks are nasty, because when
there are, for example 20 attacks, and the 15th is undo, attacks 16 is
invalid if it’s on the same target as attack 15, or is by the same attacker,
attack 17 is invalid if it’s by the same attacker or on the same target as
15 OR attacks 16 was invalid and 17 has same attacker or target, etc. This
is taken care of by removing all invalidated attacks.
This has 1 large problem: removing an attack that invalidates multiple
attacks has an enormous impact on
the score.
-----------------------------------------------------------------------
Anyway, my problem is that I don’t fully understand what is going on, or I
have a bug in my logic, I suppose the last.
What I expected the solver to do:
• clone the solution to clone[1]
• clone clone[1] to clone[1.1], do some semi random moves on clone[1.1]
• clone clone[1] to clone[1.2], do some semi random moves on clone[1.2]
• clone clone[1] to clone[1.3], do some semi random moves on clone[1.3]
• get the solution with the best score, for example clone[1.3]
• clone clone[1.3] to clone[1.3.1], do some semi random moves on
clone[1.3.1]
• clone clone[1.3] to clone[1.3.2], do some semi random moves on
clone[1.3.2]
• etc
• get the solution with the best score, for example clone[1.3.1]
• clone clone[1.3.1] to clone[1.3.1.1], do some semi random moves on
clone[1.3.1.1]
• etc
• etc
But what appears to happen is:
• clone the solution to clone[1]
• do move on clone[1], if result is better than previous result, clone
clone[1] to clone[1.1]
• do move on clone[1], if result is better than previous result, clone
clone[1] to clone[1.2]
• do move on clone[1], if result is better than previous result, clone
clone[1] to clone[1.3]
• etc
• etc
Thus effectively for every move the same, initial, solution is used. And all
the clones are used for is to remember the best solution.
This is important for my problem because a solution has a sequence of
events, a move either adds an event, or removes one or multiple events. It
turns out that, even though the solution is cloned, my moves always affect
the sequence in the original solution. This seems strange to me.
Any insights that could help me understand whether or t what I’m doing makes
sense?
--
With kind regards,
Geoffrey De Smet