<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body text="#000000" bgcolor="#ffffff">
    Hi guys<br>
    <br>
    For Drools Planner 5.3.0 (not the upcoming release)<br>
    I am working on a separate branch [1] to allow Planner to understand
    your domain model better.<br>
    <b>This will force some big changes upon you as a user</b>, but it
    will also allow many new features.<br>
    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.<br>
    I'll push those changes to master in a day or 2 ... unless someone
    finds a good reason not too.<br>
    <br>
    Any feed-back, especially on concept names, is welcome.<br>
    <br>
    <b>The Bad News</b><br>
    <br>
    You'd have to do some serious upgrading changes. Although I am
    confident this can be done in an hour or 2.<br>
    Here is the upgrading recipe as in github. Please go through to this
    list to understand the impact of these changes.<br>
    Once the changes are on master, I 'll update the reference manual.<br>
    <br>
    <br>
    [MAJOR] You need to define your solution class in the configuration
    now:<br>
    Before in *SolverConfig.xml and *BenchmarkConfig.xml:<br>
        &lt;localSearchSolver&gt;<br>
            &lt;scoreDrl&gt;...&lt;/scoreDrl&gt;<br>
    After in *SolverConfig.xml and *BenchmarkConfig.xml:<br>
        &lt;localSearchSolver&gt;<br>
           
&lt;solutionClass&gt;org.drools.planner.examples.curriculumcourse.domain.CurriculumCourseSchedule&lt;/solutionClass&gt;<br>
            &lt;scoreDrl&gt;...&lt;/scoreDrl&gt;<br>
    <br>
    [RECOMMENDED] Understand the concept of a "planning entity" class.<br>
    The class (or classes) that change during planning (and do not
    implement Solution) are a planning entity.<br>
    For example: ShiftAssignment, BedDesignation, Queen,
    CloudAssignment, ...<br>
    The other domain classes are considered normal planning facts,<br>
    for example Shift, Employee, Bed, Room, Department, ...<br>
    They do not change during planning (at least not without pausing the
    solver).<br>
    Read the manual to understand the "planning entity" concept better.<br>
    <br>
    [MAJOR] You need to define your planning entity class(es) in the
    configuration now:<br>
    Before in *SolverConfig.xml and *BenchmarkConfig.xml:<br>
        &lt;localSearchSolver&gt;<br>
            &lt;solutionClass&gt;....&lt;/solutionClass&gt;<br>
            &lt;scoreDrl&gt;...&lt;/scoreDrl&gt;<br>
    After in *SolverConfig.xml and *BenchmarkConfig.xml:<br>
        &lt;localSearchSolver&gt;<br>
            &lt;solutionClass&gt;....&lt;/solutionClass&gt;<br>
           
&lt;planningEntityClass&gt;org.drools.planner.examples.curriculumcourse.domain.Lecture&lt;/planningEntityClass&gt;<br>
            &lt;scoreDrl&gt;...&lt;/scoreDrl&gt;<br>
    <br>
    [MAJOR] You need to annotate your planning entity class(es) with the
    @PlanningEntity annotation<br>
    Before in *.java:<br>
        public class Lecture ... {<br>
            ...<br>
        }<br>
    After in *.java:<br>
        @PlanningEntity<br>
        public class Lecture ... {<br>
            ...<br>
        }<br>
    <br>
    [RECOMMENDED] Understand the concept of a "planning variable"
    property.<br>
    The property (or properties) on a planning entity class that are
    changed (through their setter) during planning<br>
    are planning variables.<br>
    For example: ShiftAssignment.getEmployee(), BedDesignation.getBed(),
    Queen.getY(), ...<br>
    Note that most planning entities have 1 property which defines the
    planning entity<br>
    and that property is NOT a planning variable.<br>
    For example: ShiftAssignment.getShift(),
    BedDesignation.getAdmissionPart(), Queen.getX(), ...<br>
    Read the manual to understand the "planning variable" concept
    better.<br>
    <br>
    [MAJOR] You need to annotate your planning variable property(ies)
    with the @PlanningVariable annotation.<br>
    Furthermore, you need to annotate a @ValueRange* annotation on to
    define the allowed values.<br>
    Commonly, you 'll use @ValueRangeFromSolutionProperty which
    specifies a property name on the solution<br>
    which returns a collection of the allowed values for that variable.<br>
    Before in *.java:<br>
        @PlanningEntity<br>
        public class Lecture ... {<br>
    <br>
            private Course course;<br>
            private int lectureIndexInCourse;<br>
    <br>
            // Changed by moves, between score calculations.<br>
            private Period period;<br>
            private Room room;<br>
    <br>
            public Course getCourse() {...}<br>
            public void setCourse(Course course) {...}<br>
    <br>
            public int getLectureIndexInCourse() {...}<br>
            public void setLectureIndexInCourse(int
    lectureIndexInCourse) {...}<br>
    <br>
            public Period getPeriod() {...}<br>
            public void setPeriod(Period period) {...}<br>
    <br>
            public Room getRoom() {...}<br>
            public void setRoom(Room room) {...}<br>
    <br>
            ...<br>
    <br>
            public int getStudentSize() {<br>
                return course.getStudentSize();<br>
            }<br>
    <br>
            public Day getDay() {<br>
                return period.getDay();<br>
            }<br>
    <br>
        }<br>
    After in *.java:<br>
        @PlanningEntity<br>
        public class Lecture ... {<br>
    <br>
            private Course course;<br>
            private int lectureIndexInCourse;<br>
    <br>
            // Changed by moves, between score calculations.<br>
            private Period period;<br>
            private Room room;<br>
    <br>
            // This is not a PlanningVariable: it defines the planning
    entity<br>
            public Course getCourse() {...}<br>
            public void setCourse(Course course) {...}<br>
    <br>
            // This is not a PlanningVariable: it defines the planning
    entity<br>
            public int getLectureIndexInCourse() {...}<br>
            public void setLectureIndexInCourse(int
    lectureIndexInCourse) {...}<br>
    <br>
            @PlanningVariable<br>
            @ValueRangeFromSolutionProperty(propertyName = "periodList")<br>
            public Period getPeriod() {...}<br>
            public void setPeriod(Period period) {...}<br>
    <br>
            @PlanningVariable<br>
            @ValueRangeFromSolutionProperty(propertyName = "roomList")<br>
            public Room getRoom() {...}<br>
            public void setRoom(Room room) {...}<br>
    <br>
            ...<br>
    <br>
            // This is not a PlanningVariable: no setter<br>
            public int getStudentSize() {<br>
                return course.getStudentSize();<br>
            }<br>
    <br>
            // This is not a PlanningVariable: no setter<br>
            public Day getDay() {<br>
                return period.getDay();<br>
            }<br>
    <br>
        }<br>
    <br>
    [MAJOR] Annotate every property on your Solution that returns a
    collection of planning entities<br>
    with @PlanningEntityCollectionProperty.<br>
    Before in *.java:<br>
        public class CurriculumCourseSchedule ... implements
    Solution&lt;...&gt; {<br>
    <br>
            private List&lt;Lecture&gt; lectureList;<br>
    <br>
            ...<br>
    <br>
            public List&lt;Lecture&gt; getLectureList() {...}<br>
            public void setLectureList(List&lt;Lecture&gt; lectureList)
    {...}<br>
    <br>
        }<br>
    After in *.java:<br>
        public class CurriculumCourseSchedule ... implements
    Solution&lt;...&gt; {<br>
    <br>
            private List&lt;Lecture&gt; lectureList;<br>
    <br>
            ...<br>
    <br>
            @PlanningEntityCollectionProperty<br>
            public List&lt;Lecture&gt; getLectureList() {...}<br>
            public void setLectureList(List&lt;Lecture&gt; lectureList)
    {...}<br>
    <br>
        }<br>
    <br>
    [MAJOR] The method getFacts() has been removed from the Solution
    interface.<br>
    Annotate every property that returns a fact or fact collection with
    the @PlanningFactProperty<br>
    or @PlanningFactCollectionProperty annotation respectively,<br>
    except those already annotated with
    @PlanningEntityCollectionProperty.<br>
    Properties annotated with these annotations are inserted into the
    working memory as facts:<br>
    - @PlanningFactProperty<br>
    - @PlanningFactCollectionProperty: each element in the collection<br>
    - @PlanningEntityCollectionProperty: each planning entity in the
    collection that is initialized<br>
    Remove the getFacts() method.<br>
    Before in *.java:<br>
        public class ... implements Solution&lt;...&gt; {<br>
    <br>
            private InstitutionalWeighting institutionalWeighting;<br>
    <br>
            private List&lt;Teacher&gt; teacherList;<br>
            private List&lt;Curriculum&gt; curriculumList;<br>
            ...<br>
            private List&lt;UnavailablePeriodConstraint&gt;
    unavailablePeriodConstraintList;<br>
    <br>
            private List&lt;Lecture&gt; lectureList;<br>
    <br>
            private HardAndSoftScore score;<br>
    <br>
            ...<br>
    <br>
            public String getName() {...}<br>
    <br>
            public InstitutionalWeighting getInstitutionalWeighting()
    {...}<br>
    <br>
            public List&lt;Teacher&gt; getTeacherList() {...}<br>
    <br>
            public List&lt;Curriculum&gt; getCurriculumList() {...}<br>
    <br>
            ...<br>
    <br>
            public List&lt;UnavailablePeriodConstraint&gt;
    getUnavailablePeriodConstraintList() {...}<br>
    <br>
            @PlanningEntityCollectionProperty<br>
            public List&lt;Lecture&gt; getLectureList() {...}<br>
    <br>
            public ...Score getScore() {...}<br>
    <br>
            public Collection&lt;? extends Object&gt; getFacts() {<br>
                List&lt;Object&gt; facts = new
    ArrayList&lt;Object&gt;();<br>
                facts.addAll(teacherList);<br>
                facts.addAll(curriculumList);<br>
                ...<br>
                facts.addAll(unavailablePeriodConstraintList);<br>
                if (isInitialized()) {<br>
                    facts.addAll(lectureList);<br>
                }<br>
                facts.addAll(calculateTopicConflictList());<br>
                return facts;<br>
            }<br>
    <br>
            public List&lt;TopicConflict&gt;
    calculateTopicConflictList() {...}<br>
    <br>
        }<br>
    After in *.java:<br>
        public class ... implements Solution&lt;...&gt; {<br>
    <br>
            private InstitutionalWeighting institutionalWeighting;<br>
    <br>
            private List&lt;Teacher&gt; teacherList;<br>
            private List&lt;Curriculum&gt; curriculumList;<br>
            ...<br>
            private List&lt;UnavailablePeriodConstraint&gt;
    unavailablePeriodConstraintList;<br>
    <br>
            private List&lt;Lecture&gt; lectureList;<br>
    <br>
            private HardAndSoftScore score;<br>
    <br>
            ...<br>
    <br>
            // This is not a PlanningFactProperty: the name is inserted
    into the working memory<br>
            public String getName() {...}<br>
    <br>
            @PlanningFactProperty<br>
            public InstitutionalWeighting getInstitutionalWeighting()
    {...}<br>
    <br>
            @PlanningFactCollectionProperty<br>
            public List&lt;Teacher&gt; getTeacherList() {...}<br>
    <br>
            @PlanningFactCollectionProperty<br>
            public List&lt;Curriculum&gt; getCurriculumList() {...}<br>
    <br>
            ...<br>
    <br>
            @PlanningFactCollectionProperty<br>
            public List&lt;UnavailablePeriodConstraint&gt;
    getUnavailablePeriodConstraintList() {...}<br>
    <br>
            // This is not a PlanningFactCollectionProperty: it is a
    PlanningEntityCollectionProperty<br>
            @PlanningEntityCollectionProperty<br>
            public List&lt;Lecture&gt; getLectureList() {...}<br>
    <br>
            // This is not a PlanningFactProperty: the score is inserted
    into the working memory<br>
            public ...Score getScore() {...}<br>
    <br>
            // renamed from calculateTopicConflictList because these are
    also facts needed in the working memory<br>
            @PlanningFactCollectionProperty<br>
            public List&lt;TopicConflict&gt; getTopicConflictList()
    {...}<br>
    <br>
        }<br>
    <br>
    [RECOMMEND] A planning entity is considered uninitialized if one if
    at least on of its planning variables is null.<br>
    Therefor it's now possible to start from a partially initialized
    solution,<br>
    for example during real-time re-planning as new facts events come
    in.<br>
    <br>
    [MAJOR] The StartingSolutionInitializer no longer has a
    isSolutionInitialized(AbstractSolverScope) method<br>
    Before in *StartingSolutionInitializer.java:<br>
        public class ...StartingSolutionInitializer extends
    AbstractStartingSolutionInitializer {<br>
    <br>
            @Override<br>
            public boolean isSolutionInitialized(AbstractSolverScope
    abstractSolverScope) {<br>
                ...<br>
            }<br>
    <br>
            ...<br>
    <br>
        }<br>
    After in *StartingSolutionInitializer.java:<br>
        public class ...StartingSolutionInitializer extends
    AbstractStartingSolutionInitializer {<br>
    <br>
            ...<br>
    <br>
        }<br>
    <br>
    [MAJOR] The planning entity collection in the Solution can never be
    null,<br>
    but some (or all) of its planning entity's can be uninitialized.<br>
    So create them before setting the starting solution, instead of in
    your StartingSolutionInitializer.<br>
    Before in *.java:<br>
        public class ... {<br>
    <br>
            public void ...() {<br>
                CurriculumCourseSchedule schedule = new
    CurriculumCourseSchedule();<br>
                schedule.setTeacherList(teacherList);<br>
                schedule.setCourseList(courseList);<br>
                ...<br>
                solver.setStartingSolution(schedule);<br>
            }<br>
    <br>
        }<br>
    After in *.java:<br>
        public class ... {<br>
    <br>
            public void ...() {<br>
                CurriculumCourseSchedule schedule = new
    CurriculumCourseSchedule();<br>
                schedule.setTeacherList(teacherList);<br>
                schedule.setCourseList(courseList);<br>
                ...<br>
               
    schedule.setLectureList(createLectureList(schedule.getCourseList()));<br>
                solver.setStartingSolution(schedule);<br>
            }<br>
    <br>
            private List&lt;Lecture&gt;
    createLectureList(List&lt;Course&gt; courseList) {<br>
                List&lt;Lecture&gt; lectureList = new
    ArrayList&lt;Lecture&gt;(courseList.size());<br>
                long id = 0L;<br>
                for (Course course : courseList) {<br>
                    for (int i = 0; i &lt; course.getLectureSize(); i++)
    {<br>
                        Lecture lecture = new Lecture();<br>
                        lecture.setId((long) id);<br>
                        id++;<br>
                        lecture.setCourse(course);<br>
                        // Make sure to set all non PlanningVariable
    properties<br>
                        lecture.setLectureIndexInCourse(i);<br>
                        // Notice that we lave the PlanningVariable
    properties on null<br>
                        lectureList.add(lecture);<br>
                    }<br>
                }<br>
                return lectureList;<br>
            }<br>
    <br>
        }<br>
    <br>
    [RECOMMENDED] Remove the isInitialized() from Solution if you copied
    that from the examples.<br>
    Before in *.java:<br>
        public class ... implements Solution&lt;...&gt; {<br>
    <br>
            public boolean isInitialized() {<br>
                return (lectureList != null);<br>
            }<br>
            <br>
            ...<br>
    <br>
        }<br>
    After in *.java:<br>
        public class ... implements Solution&lt;...&gt; {<br>
    <br>
            ...<br>
    <br>
        }<br>
    <br>
    <b><br>
      The Good News</b><br>
    <br>
    I already have written a brute force solver (only useful for very
    very small toy problems of course).<br>
    In time, I 'll write a branch and bound solver (only useful for very
    small toy problems of course).<br>
    <br>
    I 'll write generic, high-quality StartingSolutionInitializers that
    work on any program,<br>
    such as First Fit Decreasing and Cheapest Insertion.<br>
    A good StartingSolutionInitializer is really important to get a good
    result from Planner.<br>
    Currently writing a StartingSolutionInitializer was a bit of a black
    art.<br>
    Some users use a highly under optimized version or - even worse -
    none at all.<br>
    <br>
    Phasing. This will be fun.<br>
    You 'll be able to do configure this really easily:<br>
      Phase 1 = First Fit Decreasing (for initialization)<br>
      Phase 2 = Simulated Annealing (after initialization)<br>
      Phase 3 = Tabu search (when things get really hard)<br>
    Notice that a StartingSolutionInitializer is just a phase.<br>
    <br>
    [1] <a class="moz-txt-link-freetext"
      href="https://github.com/droolsjbpm/drools-planner/pull/2/files">https://github.com/droolsjbpm/drools-planner/pull/2/files</a>
    <pre class="moz-signature" cols="72">-- 
With kind regards,
Geoffrey De Smet</pre>
  </body>
</html>