Source code: https://github.com/SocraticGrid/sg-agents/tree/master/drools-agents/SIM
Drools Planner (aka Optaplanner)
Drools planner is a planning engine that optimizes planning problems. It combines optimization heuristics and metaheuristics with very efficient score calculation.
...
- NP-Complete: any given solution to can be verified quickly (in polynomial time) but there is no known efficient way to locate a solution in the first place.
- Has Constraints: Negative Hard Constraints (Must not be broken by a solution); Negative/Positive Soft Constraints (Could be broken by a solution).
- Huge Search space
Domain Model
Planning Entity: class(es) that changes during the planning.
Planning Variable: The properties that change during planning. The set of possible values must be provided. 2 different approaches:
...
For the calculation of the score, Planner uses Drools.
SIM-Agent
Class Diagram
Problem Facts
The following is the list of Problem Facts:
...
The different providers associated to a Patient are never set by planner!
Planning Entity
Only 1 planning Entity is defined: Visit.
The current implementation starts with a predefined set of Visits for each Patient. The number and type of Visits depends on the Patient's severity:
...
As we can see, the Type and Patient of a Visit are fixed and never change during the planning.
The planning variables in this case are VisitDate and Provider.
Moves
VisitDateChangeMoveFactory: Creates all the possible combinations of Visits and Dates.
VisitTimeSwapMoveFactory: Creates a permutation of all the Visits to swap their Dates. (It is not clear to me if all these moves are not already included in the previous factory)
AssignCareProviderMoveFactory: Creates a combination of all the Providers for the different Visits.
Constraints Examples: Link
Hard Constraints
Code Block |
---|
rule "PTSD therapy must be provided either by a Therapist (non-MD) or a Psychiatrist (MD)" salience 10 when $vis : Visit( type == VisitType.THERAPY, $pro : provider) Provider( this == $pro, role != ProviderRole.THERAPIST && != ProviderRole.PSYCHIATRIST ) then insertLogical( new IntConstraintOccurrence( drools.getRule().getName(), ConstraintType.NEGATIVE_HARD, 1, $vis, $pro ) ); end rule "Therapy sessions must be scheduled regularly" when $vis : Visit( type == VisitType.THERAPY, $date : date != null, $expectedWeek : expectedWeek > 0, $actualWeek : date.weekIndex, date.weekIndex != $expectedWeek ) then insertLogical( new IntConstraintOccurrence( drools.getRule().getName(), ConstraintType.NEGATIVE_HARD, 10, $vis ) ); end rule "A patient getting Group Therapy should receive 6 sessions total @ 1/wk" when $vis1 : Visit( type == VisitType.GROUP, $date1 : date != null, $seqNum : seqNum, $pat : patient, $onWeek : date.weekIndex ) $vis2 : Visit( this != $vis1, type == VisitType.GROUP, $date2 : date != null, patient == $pat, seqNum == $seqNum + 1, $nextWeek : date.weekIndex, date.weekIndex != $onWeek + 1 ) then insertLogical( new IntConstraintOccurrence( drools.getRule().getName(), ConstraintType.NEGATIVE_HARD, 10, $vis1, $vis2 ) ); end rule "No two therapy visits on the same day in the same week (for severe cases)" when $vis1 : Visit( type == VisitType.THERAPY, $date1 : date != null, $pro : provider, $pat : patient, $onWeek : date.weekIndex, $onDay : date.dayIndex ) $vis2 : Visit( this != $vis1, type == VisitType.THERAPY, $date2 : date != null, provider == $pro, patient == $pat, date.weekIndex == $onWeek, date.dayIndex == $onDay ) then insertLogical( new IntConstraintOccurrence( drools.getRule().getName(), ConstraintType.NEGATIVE_HARD, 1, $vis1, $vis2 ) ); end rule "Therapist and Psychiatrists can see a maximum of 8 PTSD therapy patients a week" when $bus : BusyWeek( $pro : provider, $week : weekIndex ) accumulate ( $vis : Visit( type == VisitType.THERAPY, provider == $pro, $date : date != null, date.weekIndex == $week ), $num : count( $vis ); $num > 8 ) then insertLogical( new IntConstraintOccurrence( drools.getRule().getName(), ConstraintType.NEGATIVE_HARD, 1, $bus ) ); end |
Soft Constraints
Code Block |
---|
rule "Patient should see the same provider" when $vis1 : Visit( $type : type, $pro : provider != null, $pat : patient ) $vis2 : Visit( this != $vis1, $date2 : date != null, type == $type, patient == $pat, provider != null, provider != $pro ) then insertLogical( new IntConstraintOccurrence( drools.getRule().getName(), ConstraintType.NEGATIVE_SOFT, 4, $vis1, $vis2 ) ); end rule "Therapy sessions should be scheduled at the same day and time over weeks" when $vis1 : Visit( type == VisitType.THERAPY, $date1 : date != null, $pro : provider, $pat : patient, $onWeek : date.weekIndex, $onDay : date.dayIndex, $morn : date.morning ) $vis2 : Visit( this != $vis1, type == VisitType.THERAPY, $date2 : date != null, provider == $pro, patient == $pat, date.weekIndex != $onWeek, date.dayIndex != $onDay || date.morning != $morn ) then insertLogical( new IntConstraintOccurrence( drools.getRule().getName(), ConstraintType.NEGATIVE_SOFT, 10, $vis1, $vis2 ) ); end rule "a patient being seen for Group Therapy should not have their session on the same day as Individual therapy" when $vis1 : Visit( type == VisitType.GROUP, $date1 : date != null, $pat : patient, $onWeek : date.weekIndex, $onDay : date.dayIndex ) $vis2 : Visit( type == VisitType.THERAPY, $date2 : date != null, patient == $pat, date.weekIndex == $onWeek, date.dayIndex == $onDay ) then insertLogical( new IntConstraintOccurrence( drools.getRule().getName(), ConstraintType.NEGATIVE_SOFT, 3, $vis1, $vis2 ) ); end |
Initial State Sample vs. Final State Sample
Visit{patient=patient 0, seqNum=1, expWeek=1, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 0, seqNum=1, expWeek=1, type=THERAPY, provider=Dr. 2, MD, date=Week 1 || Mon PM}
Visit{patient=patient 0, seqNum=2, expWeek=2, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 0, seqNum=2, expWeek=2, type=THERAPY, provider=Dr. 2, MD, date=Week 2 || Mon PM}
Visit{patient=patient 0, seqNum=3, expWeek=3, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 0, seqNum=3, expWeek=3, type=THERAPY, provider=Dr. 2, MD, date=Week 3 || Mon PM}
Visit{patient=patient 0, seqNum=4, expWeek=4, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 0, seqNum=4, expWeek=4, type=THERAPY, provider=Dr. 2, MD, date=Week 4 || Mon PM}
Visit{patient=patient 0, seqNum=5, expWeek=5, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 0, seqNum=5, expWeek=5, type=THERAPY, provider=Dr. 2, MD, date=Week 5 || Mon PM}
Visit{patient=patient 0, seqNum=6, expWeek=6, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 0, seqNum=6, expWeek=6, type=THERAPY, provider=Dr. 2, MD, date=Week 6 || Mon PM}
Visit{patient=patient 0, seqNum=7, expWeek=7, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 0, seqNum=7, expWeek=7, type=THERAPY, provider=Dr. 2, MD, date=Week 7 || Mon PM}
Visit{patient=patient 0, seqNum=8, expWeek=8, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 0, seqNum=8, expWeek=8, type=THERAPY, provider=Dr. 2, MD, date=Week 8 || Mon PM}
Visit{patient=patient 0, seqNum=9, expWeek=9, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 0, seqNum=9, expWeek=9, type=THERAPY, provider=Dr. 2, MD, date=Week 9 || Mon PM}
Visit{patient=patient 0, seqNum=10, expWeek=10, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 0, seqNum=10, expWeek=10, type=THERAPY, provider=Dr. 2, MD, date=Week 10 || Mon PM}
Visit{patient=patient 0, seqNum=11, expWeek=11, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 0, seqNum=11, expWeek=11, type=THERAPY, provider=Dr. 2, MD, date=Week 11 || Mon PM}
Visit{patient=patient 0, seqNum=12, expWeek=12, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 0, seqNum=12, expWeek=12, type=THERAPY, provider=Dr. 2, MD, date=Week 12 || Mon PM}
Visit{patient=patient 0, seqNum=13, expWeek=13, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 0, seqNum=13, expWeek=13, type=THERAPY, provider=Dr. 2, MD, date=Week 13 || Mon PM}
Visit{patient=patient 0, seqNum=14, expWeek=14, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 0, seqNum=14, expWeek=14, type=THERAPY, provider=Dr. 2, MD, date=Week 14 || Mon PM}
Visit{patient=patient 0, seqNum=15, expWeek=15, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 0, seqNum=15, expWeek=15, type=THERAPY, provider=Dr. 2, MD, date=Week 15 || Mon PM}
Visit{patient=patient 0, seqNum=16, expWeek=17, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 0, seqNum=16, expWeek=17, type=THERAPY, provider=Dr. 2, MD, date=Week 17 || Mon PM}
Visit{patient=patient 0, seqNum=17, expWeek=19, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 0, seqNum=17, expWeek=19, type=THERAPY, provider=Dr. 2, MD, date=Week 19 || Mon PM}
Visit{patient=patient 0, seqNum=18, expWeek=21, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 0, seqNum=18, expWeek=21, type=THERAPY, provider=Dr. 2, MD, date=Week 21 || Mon PM}
Visit{patient=patient 0, seqNum=19, expWeek=23, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 0, seqNum=19, expWeek=23, type=THERAPY, provider=Dr. 2, MD, date=Week 23 || Mon PM}
Visit{patient=patient 0, seqNum=20, expWeek=25, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 0, seqNum=20, expWeek=25, type=THERAPY, provider=Dr. 2, MD, date=Week 25 || Mon PM}
Visit{patient=patient 0, seqNum=1, type=COUNSELING, provider=null, date=null} -> Visit{patient=patient 0, seqNum=1, type=COUNSELING, provider=Mr. 0, date=Week 1 || Mon PM}
Visit{patient=patient 0, seqNum=2, type=COUNSELING, provider=null, date=null} -> Visit{patient=patient 0, seqNum=2, type=COUNSELING, provider=Mr. 0, date=Week 24 || Tue AM}
Visit{patient=patient 0, seqNum=3, type=COUNSELING, provider=null, date=null} -> Visit{patient=patient 0, seqNum=3, type=COUNSELING, provider=Mr. 0, date=Week 9 || Mon PM}
Visit{patient=patient 0, seqNum=4, type=COUNSELING, provider=null, date=null} -> Visit{patient=patient 0, seqNum=4, type=COUNSELING, provider=Mr. 0, date=Week 13 || Mon PM}
Visit{patient=patient 0, seqNum=5, type=COUNSELING, provider=null, date=null} -> Visit{patient=patient 0, seqNum=5, type=COUNSELING, provider=Mr. 0, date=Week 17 || Mon PM}
Visit{patient=patient 0, seqNum=6, type=COUNSELING, provider=null, date=null} -> Visit{patient=patient 0, seqNum=6, type=COUNSELING, provider=Mr. 0, date=Week 21 || Mon PM}
Visit{patient=patient 0, seqNum=1, type=GROUP, provider=null, date=null} -> Visit{patient=patient 0, seqNum=1, type=GROUP, provider=Dr. 0, MD, date=Week 2 || Tue PM}
Visit{patient=patient 0, seqNum=2, type=GROUP, provider=null, date=null} -> Visit{patient=patient 0, seqNum=2, type=GROUP, provider=Dr. 0, MD, date=Week 3 || Tue PM}
Visit{patient=patient 0, seqNum=3, type=GROUP, provider=null, date=null} -> Visit{patient=patient 0, seqNum=3, type=GROUP, provider=Dr. 0, MD, date=Week 4 || Tue PM}
Visit{patient=patient 0, seqNum=4, type=GROUP, provider=null, date=null} -> Visit{patient=patient 0, seqNum=4, type=GROUP, provider=Dr. 0, MD, date=Week 5 || Tue PM}
Visit{patient=patient 0, seqNum=5, type=GROUP, provider=null, date=null} -> Visit{patient=patient 0, seqNum=5, type=GROUP, provider=Dr. 0, MD, date=Week 6 || Tue PM}
Visit{patient=patient 0, seqNum=6, type=GROUP, provider=null, date=null} -> Visit{patient=patient 0, seqNum=6, type=GROUP, provider=Dr. 0, MD, date=Week 7 || Tue PM}
Visit{patient=patient 1, seqNum=1, expWeek=1, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=1, expWeek=1, type=THERAPY, provider=Dr. 2, date=Week 1 || Mon PM}
Visit{patient=patient 1, seqNum=2, expWeek=1, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=2, expWeek=1, type=THERAPY, provider=Dr. 2, date=Week 1 || Tue PM}
Visit{patient=patient 1, seqNum=3, expWeek=2, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=3, expWeek=2, type=THERAPY, provider=Dr. 2, date=Week 2 || Mon PM}
Visit{patient=patient 1, seqNum=4, expWeek=2, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=4, expWeek=2, type=THERAPY, provider=Dr. 2, date=Week 2 || Tue PM}
Visit{patient=patient 1, seqNum=5, expWeek=3, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=5, expWeek=3, type=THERAPY, provider=Dr. 2, date=Week 3 || Mon PM}
Visit{patient=patient 1, seqNum=6, expWeek=3, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=6, expWeek=3, type=THERAPY, provider=Dr. 2, date=Week 3 || Tue PM}
Visit{patient=patient 1, seqNum=7, expWeek=4, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=7, expWeek=4, type=THERAPY, provider=Dr. 2, date=Week 4 || Mon PM}
Visit{patient=patient 1, seqNum=8, expWeek=4, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=8, expWeek=4, type=THERAPY, provider=Dr. 2, date=Week 4 || Tue PM}
Visit{patient=patient 1, seqNum=9, expWeek=5, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=9, expWeek=5, type=THERAPY, provider=Dr. 2, date=Week 5 || Mon PM}
Visit{patient=patient 1, seqNum=10, expWeek=5, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=10, expWeek=5, type=THERAPY, provider=Dr. 2, date=Week 5 || Tue PM}
Visit{patient=patient 1, seqNum=11, expWeek=6, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=11, expWeek=6, type=THERAPY, provider=Dr. 2, date=Week 6 || Mon PM}
Visit{patient=patient 1, seqNum=12, expWeek=6, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=12, expWeek=6, type=THERAPY, provider=Dr. 2, date=Week 6 || Tue PM}
Visit{patient=patient 1, seqNum=13, expWeek=7, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=13, expWeek=7, type=THERAPY, provider=Dr. 2, date=Week 7 || Mon PM}
Visit{patient=patient 1, seqNum=14, expWeek=7, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=14, expWeek=7, type=THERAPY, provider=Dr. 2, date=Week 7 || Tue PM}
Visit{patient=patient 1, seqNum=15, expWeek=8, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=15, expWeek=8, type=THERAPY, provider=Dr. 2, date=Week 8 || Mon PM}
Visit{patient=patient 1, seqNum=16, expWeek=8, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=16, expWeek=8, type=THERAPY, provider=Dr. 2, date=Week 8 || Tue PM}
Visit{patient=patient 1, seqNum=17, expWeek=9, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=17, expWeek=9, type=THERAPY, provider=Dr. 2, date=Week 9 || Mon PM}
Visit{patient=patient 1, seqNum=18, expWeek=9, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=18, expWeek=9, type=THERAPY, provider=Dr. 2, date=Week 9 || Tue PM}
Visit{patient=patient 1, seqNum=19, expWeek=10, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=19, expWeek=10, type=THERAPY, provider=Dr. 2, date=Week 10 || Mon PM}
Visit{patient=patient 1, seqNum=20, expWeek=10, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=20, expWeek=10, type=THERAPY, provider=Dr. 2, date=Week 10 || Tue PM}
Visit{patient=patient 1, seqNum=21, expWeek=11, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=21, expWeek=11, type=THERAPY, provider=Dr. 2, date=Week 11 || Mon PM}
Visit{patient=patient 1, seqNum=22, expWeek=12, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=22, expWeek=12, type=THERAPY, provider=Dr. 2, date=Week 12 || Mon PM}
Visit{patient=patient 1, seqNum=23, expWeek=13, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=23, expWeek=13, type=THERAPY, provider=Dr. 2, date=Week 13 || Mon PM}
Visit{patient=patient 1, seqNum=24, expWeek=14, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=24, expWeek=14, type=THERAPY, provider=Dr. 2, date=Week 14 || Mon PM}
Visit{patient=patient 1, seqNum=25, expWeek=15, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=25, expWeek=15, type=THERAPY, provider=Dr. 2, date=Week 15 || Mon PM}
Visit{patient=patient 1, seqNum=26, expWeek=17, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=26, expWeek=17, type=THERAPY, provider=Dr. 2, date=Week 17 || Mon PM}
Visit{patient=patient 1, seqNum=27, expWeek=19, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=27, expWeek=19, type=THERAPY, provider=Dr. 2, date=Week 19 || Mon PM}
Visit{patient=patient 1, seqNum=28, expWeek=21, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=28, expWeek=21, type=THERAPY, provider=Dr. 2, date=Week 21 || Mon PM}
Visit{patient=patient 1, seqNum=29, expWeek=25, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=29, expWeek=25, type=THERAPY, provider=Dr. 2, date=Week 25 || Mon PM}
Visit{patient=patient 1, seqNum=30, expWeek=29, type=THERAPY, provider=null, date=null} -> Visit{patient=patient 1, seqNum=30, expWeek=29, type=THERAPY, provider=Dr. 2, date=Week 29 || Mon PM}
Visit{patient=patient 1, seqNum=1, type=COUNSELING, provider=null, date=null} -> Visit{patient=patient 1, seqNum=1, type=COUNSELING, provider=Mr. 0, date=Week 23 || Thu AM}
Visit{patient=patient 1, seqNum=2, type=COUNSELING, provider=null, date=null} -> Visit{patient=patient 1, seqNum=2, type=COUNSELING, provider=Mr. 0, date=Week 11 || Mon PM}
Visit{patient=patient 1, seqNum=3, type=COUNSELING, provider=null, date=null} -> Visit{patient=patient 1, seqNum=3, type=COUNSELING, provider=Mr. 0, date=Week 12 || Mon PM}
Visit{patient=patient 1, seqNum=4, type=COUNSELING, provider=null, date=null} -> Visit{patient=patient 1, seqNum=4, type=COUNSELING, provider=Mr. 0, date=Week 13 || Mon PM}
Visit{patient=patient 1, seqNum=5, type=COUNSELING, provider=null, date=null} -> Visit{patient=patient 1, seqNum=5, type=COUNSELING, provider=Mr. 0, date=Week 17 || Mon PM}
Visit{patient=patient 1, seqNum=6, type=COUNSELING, provider=null, date=null} -> Visit{patient=patient 1, seqNum=6, type=COUNSELING, provider=Mr. 0, date=Week 21 || Mon PM}
Visit{patient=patient 1, seqNum=7, type=COUNSELING, provider=null, date=null} -> Visit{patient=patient 1, seqNum=7, type=COUNSELING, provider=Mr. 0, date=Week 25 || Mon PM}
Visit{patient=patient 1, seqNum=1, type=MEDICATION, provider=null, date=null} -> Visit{patient=patient 1, seqNum=1, type=MEDICATION, provider=Dr. 0, MD, date=Week 1 || Mon PM}
Visit{patient=patient 1, seqNum=2, type=MEDICATION, provider=null, date=null} -> Visit{patient=patient 1, seqNum=2, type=MEDICATION, provider=Dr. 0, MD, date=Week 5 || Mon PM}
Visit{patient=patient 1, seqNum=3, type=MEDICATION, provider=null, date=null} -> Visit{patient=patient 1, seqNum=3, type=MEDICATION, provider=Dr. 0, MD, date=Week 9 || Mon PM}
Visit{patient=patient 1, seqNum=4, type=MEDICATION, provider=null, date=null} -> Visit{patient=patient 1, seqNum=4, type=MEDICATION, provider=Dr. 0, MD, date=Week 13 || Mon PM}
Visit{patient=patient 1, seqNum=5, type=MEDICATION, provider=null, date=null} -> Visit{patient=patient 1, seqNum=5, type=MEDICATION, provider=Dr. 0, MD, date=Week 17 || Mon PM}
Visit{patient=patient 1, seqNum=6, type=MEDICATION, provider=null, date=null} -> Visit{patient=patient 1, seqNum=6, type=MEDICATION, provider=Dr. 0, MD, date=Week 21 || Mon PM}
Visit{patient=patient 1, seqNum=7, type=MEDICATION, provider=null, date=null} -> Visit{patient=patient 1, seqNum=7, type=MEDICATION, provider=Dr. 0, MD, date=Week 25 || Mon PM}