[rules-dev] Planner big user impacting changes: declarative metamodel

Geoffrey De Smet ge0ffrey.spam at gmail.com
Sun May 29 05:00:51 EDT 2011


After discussing with ubba, I 've decided to revert a small part of this 
change:
   @PlanningFactCollectionProperty (and @PlanningFactProperty) goes to 
to trashcan
and the Solution.getFacts() method is reinstated (but shouldn't insert 
the planning entities no more).

Op 29-05-11 10:22, Geoffrey De Smet schreef:
> Op 27-05-11 22:39, Michael Anstis schreef:
>> Phew! I made it to the end of the email ;)
>>
>> All very interest Geoffrey, but have you explained the purpose of the 
>> annotations? Why must I now annotate things, what value is it bringing?
> The real value will be explained in the manual later and visible when 
> we build stuff on this :)
> This mail is mainly to rattle people's cages:
> *can you live with the bad side of these changes or not?*
> Speak up now, before I go further on this path and there's no going back.
>
>>
>> I don't, personally, have any problem with them - there are many 
>> libraries that use them - but their purpose is well understood: e.g. 
>> @Entity, @Resource etc
> Good point that I need to explain it better to open up the discussion.
> Basically, Planner needs to know what are you planning variables (of 
> the planning entity classes) and what are allowed values of each 
> planning variable (ignoring the non-build-in constraints).
> It's also the first step to declarative moves.
>>
>> Perhaps I missed something?
>>
>> With kind regards
>>
>> Mike
>>
>> On 27 May 2011 11:13, Geoffrey De Smet <ge0ffrey.spam at gmail.com 
>> <mailto:ge0ffrey.spam at gmail.com>> wrote:
>>
>>     Hi guys
>>
>>     For Drools Planner 5.3.0 (not the upcoming release)
>>     I am working on a separate branch [1] to allow Planner to
>>     understand your domain model better.
>>     *This will force some big changes upon you as a user*, but it
>>     will also allow many new features.
>>     Reading and replying to this mail is your chance to steer those
>>     changes, and verify that they are a good thing for your
>>     implementation too.
>>     I'll push those changes to master in a day or 2 ... unless
>>     someone finds a good reason not too.
>>
>>     Any feed-back, especially on concept names, is welcome.
>>
>>     *The Bad News*
>>
>>     You'd have to do some serious upgrading changes. Although I am
>>     confident this can be done in an hour or 2.
>>     Here is the upgrading recipe as in github. Please go through to
>>     this list to understand the impact of these changes.
>>     Once the changes are on master, I 'll update the reference manual.
>>
>>
>>     [MAJOR] You need to define your solution class in the
>>     configuration now:
>>     Before in *SolverConfig.xml and *BenchmarkConfig.xml:
>>     <localSearchSolver>
>>     <scoreDrl>...</scoreDrl>
>>     After in *SolverConfig.xml and *BenchmarkConfig.xml:
>>     <localSearchSolver>
>>     <solutionClass>org.drools.planner.examples.curriculumcourse.domain.CurriculumCourseSchedule</solutionClass>
>>     <scoreDrl>...</scoreDrl>
>>
>>     [RECOMMENDED] Understand the concept of a "planning entity" class.
>>     The class (or classes) that change during planning (and do not
>>     implement Solution) are a planning entity.
>>     For example: ShiftAssignment, BedDesignation, Queen,
>>     CloudAssignment, ...
>>     The other domain classes are considered normal planning facts,
>>     for example Shift, Employee, Bed, Room, Department, ...
>>     They do not change during planning (at least not without pausing
>>     the solver).
>>     Read the manual to understand the "planning entity" concept better.
>>
>>     [MAJOR] You need to define your planning entity class(es) in the
>>     configuration now:
>>     Before in *SolverConfig.xml and *BenchmarkConfig.xml:
>>     <localSearchSolver>
>>     <solutionClass>....</solutionClass>
>>     <scoreDrl>...</scoreDrl>
>>     After in *SolverConfig.xml and *BenchmarkConfig.xml:
>>     <localSearchSolver>
>>     <solutionClass>....</solutionClass>
>>     <planningEntityClass>org.drools.planner.examples.curriculumcourse.domain.Lecture</planningEntityClass>
>>     <scoreDrl>...</scoreDrl>
>>
>>     [MAJOR] You need to annotate your planning entity class(es) with
>>     the @PlanningEntity annotation
>>     Before in *.java:
>>         public class Lecture ... {
>>             ...
>>         }
>>     After in *.java:
>>         @PlanningEntity
>>         public class Lecture ... {
>>             ...
>>         }
>>
>>     [RECOMMENDED] Understand the concept of a "planning variable"
>>     property.
>>     The property (or properties) on a planning entity class that are
>>     changed (through their setter) during planning
>>     are planning variables.
>>     For example: ShiftAssignment.getEmployee(),
>>     BedDesignation.getBed(), Queen.getY(), ...
>>     Note that most planning entities have 1 property which defines
>>     the planning entity
>>     and that property is NOT a planning variable.
>>     For example: ShiftAssignment.getShift(),
>>     BedDesignation.getAdmissionPart(), Queen.getX(), ...
>>     Read the manual to understand the "planning variable" concept better.
>>
>>     [MAJOR] You need to annotate your planning variable property(ies)
>>     with the @PlanningVariable annotation.
>>     Furthermore, you need to annotate a @ValueRange* annotation on to
>>     define the allowed values.
>>     Commonly, you 'll use @ValueRangeFromSolutionProperty which
>>     specifies a property name on the solution
>>     which returns a collection of the allowed values for that variable.
>>     Before in *.java:
>>         @PlanningEntity
>>         public class Lecture ... {
>>
>>             private Course course;
>>             private int lectureIndexInCourse;
>>
>>             // Changed by moves, between score calculations.
>>             private Period period;
>>             private Room room;
>>
>>             public Course getCourse() {...}
>>             public void setCourse(Course course) {...}
>>
>>             public int getLectureIndexInCourse() {...}
>>             public void setLectureIndexInCourse(int
>>     lectureIndexInCourse) {...}
>>
>>             public Period getPeriod() {...}
>>             public void setPeriod(Period period) {...}
>>
>>             public Room getRoom() {...}
>>             public void setRoom(Room room) {...}
>>
>>             ...
>>
>>             public int getStudentSize() {
>>                 return course.getStudentSize();
>>             }
>>
>>             public Day getDay() {
>>                 return period.getDay();
>>             }
>>
>>         }
>>     After in *.java:
>>         @PlanningEntity
>>         public class Lecture ... {
>>
>>             private Course course;
>>             private int lectureIndexInCourse;
>>
>>             // Changed by moves, between score calculations.
>>             private Period period;
>>             private Room room;
>>
>>             // This is not a PlanningVariable: it defines the
>>     planning entity
>>             public Course getCourse() {...}
>>             public void setCourse(Course course) {...}
>>
>>             // This is not a PlanningVariable: it defines the
>>     planning entity
>>             public int getLectureIndexInCourse() {...}
>>             public void setLectureIndexInCourse(int
>>     lectureIndexInCourse) {...}
>>
>>             @PlanningVariable
>>             @ValueRangeFromSolutionProperty(propertyName = "periodList")
>>             public Period getPeriod() {...}
>>             public void setPeriod(Period period) {...}
>>
>>             @PlanningVariable
>>             @ValueRangeFromSolutionProperty(propertyName = "roomList")
>>             public Room getRoom() {...}
>>             public void setRoom(Room room) {...}
>>
>>             ...
>>
>>             // This is not a PlanningVariable: no setter
>>             public int getStudentSize() {
>>                 return course.getStudentSize();
>>             }
>>
>>             // This is not a PlanningVariable: no setter
>>             public Day getDay() {
>>                 return period.getDay();
>>             }
>>
>>         }
>>
>>     [MAJOR] Annotate every property on your Solution that returns a
>>     collection of planning entities
>>     with @PlanningEntityCollectionProperty.
>>     Before in *.java:
>>         public class CurriculumCourseSchedule ... implements
>>     Solution<...> {
>>
>>             private List<Lecture> lectureList;
>>
>>             ...
>>
>>             public List<Lecture> getLectureList() {...}
>>             public void setLectureList(List<Lecture> lectureList) {...}
>>
>>         }
>>     After in *.java:
>>         public class CurriculumCourseSchedule ... implements
>>     Solution<...> {
>>
>>             private List<Lecture> lectureList;
>>
>>             ...
>>
>>             @PlanningEntityCollectionProperty
>>             public List<Lecture> getLectureList() {...}
>>             public void setLectureList(List<Lecture> lectureList) {...}
>>
>>         }
>>
>>     [MAJOR] The method getFacts() has been removed from the Solution
>>     interface.
>>     Annotate every property that returns a fact or fact collection
>>     with the @PlanningFactProperty
>>     or @PlanningFactCollectionProperty annotation respectively,
>>     except those already annotated with
>>     @PlanningEntityCollectionProperty.
>>     Properties annotated with these annotations are inserted into the
>>     working memory as facts:
>>     - @PlanningFactProperty
>>     - @PlanningFactCollectionProperty: each element in the collection
>>     - @PlanningEntityCollectionProperty: each planning entity in the
>>     collection that is initialized
>>     Remove the getFacts() method.
>>     Before in *.java:
>>         public class ... implements Solution<...> {
>>
>>             private InstitutionalWeighting institutionalWeighting;
>>
>>             private List<Teacher> teacherList;
>>             private List<Curriculum> curriculumList;
>>             ...
>>             private List<UnavailablePeriodConstraint>
>>     unavailablePeriodConstraintList;
>>
>>             private List<Lecture> lectureList;
>>
>>             private HardAndSoftScore score;
>>
>>             ...
>>
>>             public String getName() {...}
>>
>>             public InstitutionalWeighting getInstitutionalWeighting()
>>     {...}
>>
>>             public List<Teacher> getTeacherList() {...}
>>
>>             public List<Curriculum> getCurriculumList() {...}
>>
>>             ...
>>
>>             public List<UnavailablePeriodConstraint>
>>     getUnavailablePeriodConstraintList() {...}
>>
>>             @PlanningEntityCollectionProperty
>>             public List<Lecture> getLectureList() {...}
>>
>>             public ...Score getScore() {...}
>>
>>             public Collection<? extends Object> getFacts() {
>>                 List<Object> facts = new ArrayList<Object>();
>>                 facts.addAll(teacherList);
>>                 facts.addAll(curriculumList);
>>                 ...
>>                 facts.addAll(unavailablePeriodConstraintList);
>>                 if (isInitialized()) {
>>                     facts.addAll(lectureList);
>>                 }
>>                 facts.addAll(calculateTopicConflictList());
>>                 return facts;
>>             }
>>
>>             public List<TopicConflict> calculateTopicConflictList() {...}
>>
>>         }
>>     After in *.java:
>>         public class ... implements Solution<...> {
>>
>>             private InstitutionalWeighting institutionalWeighting;
>>
>>             private List<Teacher> teacherList;
>>             private List<Curriculum> curriculumList;
>>             ...
>>             private List<UnavailablePeriodConstraint>
>>     unavailablePeriodConstraintList;
>>
>>             private List<Lecture> lectureList;
>>
>>             private HardAndSoftScore score;
>>
>>             ...
>>
>>             // This is not a PlanningFactProperty: the name is
>>     inserted into the working memory
>>             public String getName() {...}
>>
>>             @PlanningFactProperty
>>             public InstitutionalWeighting getInstitutionalWeighting()
>>     {...}
>>
>>             @PlanningFactCollectionProperty
>>             public List<Teacher> getTeacherList() {...}
>>
>>             @PlanningFactCollectionProperty
>>             public List<Curriculum> getCurriculumList() {...}
>>
>>             ...
>>
>>             @PlanningFactCollectionProperty
>>             public List<UnavailablePeriodConstraint>
>>     getUnavailablePeriodConstraintList() {...}
>>
>>             // This is not a PlanningFactCollectionProperty: it is a
>>     PlanningEntityCollectionProperty
>>             @PlanningEntityCollectionProperty
>>             public List<Lecture> getLectureList() {...}
>>
>>             // This is not a PlanningFactProperty: the score is
>>     inserted into the working memory
>>             public ...Score getScore() {...}
>>
>>             // renamed from calculateTopicConflictList because these
>>     are also facts needed in the working memory
>>             @PlanningFactCollectionProperty
>>             public List<TopicConflict> getTopicConflictList() {...}
>>
>>         }
>>
>>     [RECOMMEND] A planning entity is considered uninitialized if one
>>     if at least on of its planning variables is null.
>>     Therefor it's now possible to start from a partially initialized
>>     solution,
>>     for example during real-time re-planning as new facts events come in.
>>
>>     [MAJOR] The StartingSolutionInitializer no longer has a
>>     isSolutionInitialized(AbstractSolverScope) method
>>     Before in *StartingSolutionInitializer.java:
>>         public class ...StartingSolutionInitializer extends
>>     AbstractStartingSolutionInitializer {
>>
>>             @Override
>>             public boolean isSolutionInitialized(AbstractSolverScope
>>     abstractSolverScope) {
>>                 ...
>>             }
>>
>>             ...
>>
>>         }
>>     After in *StartingSolutionInitializer.java:
>>         public class ...StartingSolutionInitializer extends
>>     AbstractStartingSolutionInitializer {
>>
>>             ...
>>
>>         }
>>
>>     [MAJOR] The planning entity collection in the Solution can never
>>     be null,
>>     but some (or all) of its planning entity's can be uninitialized.
>>     So create them before setting the starting solution, instead of
>>     in your StartingSolutionInitializer.
>>     Before in *.java:
>>         public class ... {
>>
>>             public void ...() {
>>                 CurriculumCourseSchedule schedule = new
>>     CurriculumCourseSchedule();
>>                 schedule.setTeacherList(teacherList);
>>                 schedule.setCourseList(courseList);
>>                 ...
>>                 solver.setStartingSolution(schedule);
>>             }
>>
>>         }
>>     After in *.java:
>>         public class ... {
>>
>>             public void ...() {
>>                 CurriculumCourseSchedule schedule = new
>>     CurriculumCourseSchedule();
>>                 schedule.setTeacherList(teacherList);
>>                 schedule.setCourseList(courseList);
>>                 ...
>>                
>>     schedule.setLectureList(createLectureList(schedule.getCourseList()));
>>                 solver.setStartingSolution(schedule);
>>             }
>>
>>             private List<Lecture> createLectureList(List<Course>
>>     courseList) {
>>                 List<Lecture> lectureList = new
>>     ArrayList<Lecture>(courseList.size());
>>                 long id = 0L;
>>                 for (Course course : courseList) {
>>                     for (int i = 0; i < course.getLectureSize(); i++) {
>>                         Lecture lecture = new Lecture();
>>                         lecture.setId((long) id);
>>                         id++;
>>                         lecture.setCourse(course);
>>                         // Make sure to set all non PlanningVariable
>>     properties
>>                         lecture.setLectureIndexInCourse(i);
>>                         // Notice that we lave the PlanningVariable
>>     properties on null
>>                         lectureList.add(lecture);
>>                     }
>>                 }
>>                 return lectureList;
>>             }
>>
>>         }
>>
>>     [RECOMMENDED] Remove the isInitialized() from Solution if you
>>     copied that from the examples.
>>     Before in *.java:
>>         public class ... implements Solution<...> {
>>
>>             public boolean isInitialized() {
>>                 return (lectureList != null);
>>             }
>>
>>             ...
>>
>>         }
>>     After in *.java:
>>         public class ... implements Solution<...> {
>>
>>             ...
>>
>>         }
>>
>>     *
>>     The Good News*
>>
>>     I already have written a brute force solver (only useful for very
>>     very small toy problems of course).
>>     In time, I 'll write a branch and bound solver (only useful for
>>     very small toy problems of course).
>>
>>     I 'll write generic, high-quality StartingSolutionInitializers
>>     that work on any program,
>>     such as First Fit Decreasing and Cheapest Insertion.
>>     A good StartingSolutionInitializer is really important to get a
>>     good result from Planner.
>>     Currently writing a StartingSolutionInitializer was a bit of a
>>     black art.
>>     Some users use a highly under optimized version or - even worse -
>>     none at all.
>>
>>     Phasing. This will be fun.
>>     You 'll be able to do configure this really easily:
>>       Phase 1 = First Fit Decreasing (for initialization)
>>       Phase 2 = Simulated Annealing (after initialization)
>>       Phase 3 = Tabu search (when things get really hard)
>>     Notice that a StartingSolutionInitializer is just a phase.
>>
>>     [1] https://github.com/droolsjbpm/drools-planner/pull/2/files
>>
>>     -- 
>>     With kind regards,
>>     Geoffrey De Smet
>>
>>
>>     _______________________________________________
>>     rules-dev mailing list
>>     rules-dev at lists.jboss.org <mailto:rules-dev at lists.jboss.org>
>>     https://lists.jboss.org/mailman/listinfo/rules-dev
>>
>>
>>
>> _______________________________________________
>> rules-dev mailing list
>> rules-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/rules-dev
>
> -- 
> With kind regards,
> Geoffrey De Smet
>
>
> _______________________________________________
> rules-dev mailing list
> rules-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-dev

-- 
With kind regards,
Geoffrey De Smet

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/rules-dev/attachments/20110529/c4fc7402/attachment-0001.html 


More information about the rules-dev mailing list