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?
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 Perhaps I missed something? With kind regards Mike On 27 May 2011 11:13, Geoffrey De Smet <ge0ffrey.s...@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@lists.jboss.org > https://lists.jboss.org/mailman/listinfo/rules-dev > >
_______________________________________________ rules-dev mailing list rules-dev@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-dev