I'll be sure to do those tests. However I don't know if I can publish these
results, since it is part of my thesis, but I imagine that Mr. Demeester
won't have any problem with sharing these results with you.
Sincerely,
Wim Vancroonenburg.
----- Original Message -----
From: "Geoffrey De Smet" <ge0ffrey.spam(a)gmail.com>
Newsgroups: gmane.comp.java.drools.user
To: <rules-users(a)lists.jboss.org>
Sent: Saturday, February 14, 2009 10:12 AM
Subject: Re: Drools-solver performance optimizations?
I've worked at Kaho and I know Peter De Meester, his custom
algorithms do
pretty well :)
I am really interested in how the different components measure up in
speed:
- calculating a single score (no doubt drools-solver will lose this one
due to the warmup time of drools)
- calculating 10.000 scores after calculating 10.000 scores to give
hotspot compiling some time to warm up. Each scores changes into the next
by a move (to allow score delta calculation).
- number of calculated scores per second and only start measuring after
100 seconds
- average number of moves per minute
- average number of moves per step
- average number of steps per minute
You'd do me a grand favor by publishing any results on this mailing list,
so we can find out where and how drools-solver needs improving.
Patches on drools-solver are always welcome of course too.
One thing that drools-solver currently lacks is build-in support for
rotating (phasing) through different local search solvers (first simulated
annealing, then tabu search, then great deluge, then start over). It
shouldn't be hard to implement that on top of drools-solver for now.
Also drools-solver currently only utilizes one CPU (it's single threaded).
Multi-thread support is coming. So you might want to take a look at how
the number of CPU's affect the other algorithms.
Anyway, first clean up your rules, tweak relativeSelection, use a starting
solution initializer, tweak other configuration, ...: that will make a big
difference. It's a game of perseverance - may the best algorithm win :)
With kind regards,
Geoffrey De Smet
Wim Vancroonenburg schreef:
> Thanks to everybody for the tips. I will see what I can do with them to
> squeeze out that last bit of performance.
>
> To Geoffrey:
>
> I just wanted to let you know that I'm the thesis student from KAHOSL
> that is using Drools Solver for the Patient Admission Scheduling-problem.
> The performance of Drools Solver isn't bad, but I'm trying to match my
> promotor's code. His code is substantialy faster at the moment (a
> hyperheuristic implementation). So I'm trying to squeeze out every bit of
> performance. Thanks for the tips and the quick response by the way.
>
> Sincerely,
>
> Wim Vancroonenburg.
>
>
> ----- Original Message ----- From: "Geoffrey De Smet"
> <ge0ffrey.spam(a)gmail.com>
> Newsgroups: gmane.comp.java.drools.user
> To: <rules-users(a)lists.jboss.org>
> Sent: Friday, February 13, 2009 3:32 PM
> Subject: Re: Drools-solver performance optimizations?
>
>
>> Take a look at some of the tricks in the ITC2007 examination example:
>>
>> - <relativeSelection>0.002</relativeSelection> Real-world problems
are
>> so big that you can't evaluate all moves for every step. You need to
>> take a random percentage (for example 0.2%) of all moves to evaluate.
>> If you aren't using this, use it and you should see a big difference.
>> Once you're a 100% confident in your score function, use the benchmarker
>> to determine the perfect relativeSelection.
>>
>> - I calculate a TopicConflict list before starting the solver and use it
>> in my score drl, because none of the move change the result of that
>> calculation - and it's used a lot.
>>
>> - avoid backwards chaining functions when possible, like accumulate,
>> exists, collect, ... Forward chaining = free score delta calculation.
>>
>> - Use the most limiting facts first, so
>> $room : Room(sexRestriction == Sex.Dependent && capacity > 1);
>> before
>> $n : Night();
>>
>>
>> Most of your rules look good. I do recommend turning them off one by one
>> to see if none outclasses all others in CPU consumption, so you know
>> which one to put your time into.
>>
>> I would rewrite the patientsToBeAssignedToRoomsOfAppropriateSex as such
>>
>> rule "patientsToBeAssignedToRoomsOfAppropriateSex"
>> when
>> $room : Room(sexRestriction == Sex.Dependent && capacity
>> > 1);
>> ps1 : PatientStay(bed.room == $room, n : night, $leftId
>> : id, g : patient.admission.sex)
>> ps2 : PatientStay(bed.room == $room, night == $n,
>> patient.admission.sex != $g, id > $leftId)
>> then
>> insertLogical(new
>>
IntConstraintOccurrence("patientsToBeAssignedToRoomsOfAppropriateSex",ConstraintType.NEGATIVE_HARD,
>> 50, $ps1, $ps2));
>> end
>>
>> I do the id thing because otherwise it would match twice, once for A and
>> B and once for B and A
>>
>> PS: be carefull with "PatientStay(bed.room == ...), IIRC it gets MVEL'ed
>> (= a bit performance loss) or flattening is a problem because the move
>> only does an update(PatientStay) (=> score gets corrupted on second
>> calculation)
>> PatientStay(room == ...) with PatiantStay.getRoom(){return
>> getBed().getRoom()) isn't dangerous
>> Mark or Edson could probably answer this question.
>>
>>
>> With kind regards,
>> Geoffrey De Smet
>>
>>
>> Wim Vancroonenburg schreef:
>>> Hi,
>>>
>>> I'm a student currently evaluating Drools Solver for my dissertation. I
>>> am currently trying to solve an optimization problem with two different
>>> solvers (one of which is Drools Solver) and I am comparing the results
>>> with earlier obtained results from literature. However I am having some
>>> troubles with the performance of Drools Solver, and I was hoping if
>>> someone could look at my rules to see if they could be tuned:
>>>
>>> rule "patientsToBeAssignedToRoomsOfAppropriateSex"
>>> when
>>> $n : Night();
>>> $room : Room(sexRestriction == Sex.Dependent &&
>>> capacity > 1);
>>> $genders : ArrayList(size>1) from collect(
>>> PatientStay(bed.room == $room, night == $n) );
>>
>>> exists PatientStay(bed.room == $room, night == $n, $a :
>>> admission,
>>> eval(((PatientStay)$genders.get(0)).getAdmission().getPatient().getSex()
>>> != $a.getPatient().getSex()));
>>> then
>>> insertLogical(new
>>>
IntConstraintOccurrence("patientsToBeAssignedToRoomsOfAppropriateSex",ConstraintType.NEGATIVE_HARD,50,$room,$n));
>>> end
>>>
>>> rule "hasRequiredRoomProperties"
>>> when
>>> $pr : RequiredRoomPropertiesConstraint($a : admission,
>>> $r : room, $w : weight );
>>> $ps : PatientStay(admission == $a, bed.room == $r);
>>> then
>>> insertLogical(new
>>>
IntConstraintOccurrence("hasPreferredRoomProperties",ConstraintType.NEGATIVE_SOFT,50*$w,$ps));
>>> end
>>>
>>> rule "unplannedTransfers"
>>> when
>>> $ps : PatientStay($a : admission, $b : bed, $n :
>>> night);
>>> $ps2 : PatientStay(admission == $a, bed != $b, $n2 :
>>> night,eval($n.getIndex()+1 == $n2.getIndex()));
>>> then
>>> insertLogical(new
>>>
IntConstraintOccurrence("unplannedTransfers",ConstraintType.NEGATIVE_SOFT,110,$ps,$ps2));
>>> end
>>>
>>> rule "hasPreferredRoomProperties"
>>> when
>>> $pr : PreferredRoomPropertiesConstraint($a : admission,
>>> $r : room, $w : weight );
>>> $ps : PatientStay(admission == $a, bed.room == $r);
>>> then
>>> insertLogical(new
>>>
IntConstraintOccurrence("hasPreferredRoomProperties",ConstraintType.NEGATIVE_SOFT,20*$w,$ps));
>>> end
>>>
>>> rule "meetsRoomPreference"
>>> when
>>> $mr : MeetsRoomPreferenceConstraint($a : admission, $r
>>> : room);
>>> $ps : PatientStay(admission == $a, bed.room == $r);
>>> then
>>> insertLogical(new
>>>
IntConstraintOccurrence("meetsRoomPreference",ConstraintType.NEGATIVE_SOFT,8,$ps));
>>> end
>>>
>>> rule "inGoodDepartment"
>>> when
>>> $gd : GoodDepartmentConstraint($a : admission, $d :
>>> department);
>>> $ps : PatientStay(admission == $a, $b : bed,
>>> eval($b.getRoom().getDepartment().equals($d)));
>>> then
>>> insertLogical(new
>>>
IntConstraintOccurrence("inGoodDepartment",ConstraintType.NEGATIVE_SOFT,10,$ps));
>>> end
>>>
>>> rule "inGoodRoom"
>>> when
>>> $gr : GoodRoomConstraint($a : admission, $r : room, $w
>>> : weight);
>>> $ps : PatientStay(admission == $a, bed.room == $r);
>>> then
>>> insertLogical(new
>>>
IntConstraintOccurrence("inGoodRoom",ConstraintType.NEGATIVE_SOFT,10*$w,$ps));
>>> end
>>>
>>> rule "calcScore"
>>> salience -10
>>> when
>>> $count : Number() from accumulate(
>>> IntConstraintOccurrence($w : weight) ,
>>>
>>> sum($w) );
>>> then
>>> scoreCalculator.setScore(-$count.doubleValue());
>>> end
>>>
>>> The classes with **Constraint in it are possible combinations that
>>> cause a constraint to be violated, and are calculated and inserted at
>>> initialization time (and are never changed). I know that the rule
>>> "patientsToBeAssignedToRoomsOfAppropriateSex" is fairly complex,
but
>>> even when I remove it, the performance is not fantastic. Is there
>>> anything else I can do to get better performance? I'm already using JDK
>>> 1.6 and -server mode. Furthermore, all classes used here have their
>>> default equals and hashCode methods, so they don't have an impact on
>>> performance.
>>>
>>> Sincerely,
>>>
>>> Wim Vancroonenburg
>>>
>>>
>>> ------------------------------------------------------------------------
>>>
>>> _______________________________________________
>>> rules-users mailing list
>>> rules-users(a)lists.jboss.org
>>>
https://lists.jboss.org/mailman/listinfo/rules-users
>>
>> _______________________________________________
>> rules-users mailing list
>> rules-users(a)lists.jboss.org
>>
https://lists.jboss.org/mailman/listinfo/rules-users
>>
>
> _______________________________________________
> rules-users mailing list
> rules-users(a)lists.jboss.org
>
https://lists.jboss.org/mailman/listinfo/rules-users
>
_______________________________________________
rules-users mailing list
rules-users(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users