<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
<title></title>
</head>
<body text="#000000" bgcolor="#ffffff">
Op 27-05-11 22:39, Michael Anstis schreef:
<blockquote
cite="mid:BANLkTimd5wLfJT5Ki1ktKmVn6aibFYtZCA@mail.gmail.com"
type="cite">Phew! I made it to the end of the email ;)<br>
<br>
All very interest Geoffrey, but have you explained the purpose of
the annotations? Why must I now annotate things, what value is it
bringing?<br>
</blockquote>
The real value will be explained in the manual later and visible
when we build stuff on this :)<br>
This mail is mainly to rattle people's cages:<br>
<b>can you live with the bad side of these changes or not?</b><br>
Speak up now, before I go further on this path and there's no going
back.<br>
<br>
<blockquote
cite="mid:BANLkTimd5wLfJT5Ki1ktKmVn6aibFYtZCA@mail.gmail.com"
type="cite"><br>
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<br>
</blockquote>
Good point that I need to explain it better to open up the
discussion.<br>
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).<br>
It's also the first step to declarative moves.<br>
<blockquote
cite="mid:BANLkTimd5wLfJT5Ki1ktKmVn6aibFYtZCA@mail.gmail.com"
type="cite">
<br>
Perhaps I missed something?<br>
<br>
With kind regards<br>
<br>
Mike<br>
<br>
<div class="gmail_quote">On 27 May 2011 11:13, Geoffrey De Smet <span
dir="ltr"><<a moz-do-not-send="true"
href="mailto:ge0ffrey.spam@gmail.com">ge0ffrey.spam@gmail.com</a>></span>
wrote:<br>
<blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt
0.8ex; border-left: 1px solid rgb(204, 204, 204);
padding-left: 1ex;">
<div 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>
<localSearchSolver><br>
<scoreDrl>...</scoreDrl><br>
After in *SolverConfig.xml and *BenchmarkConfig.xml:<br>
<localSearchSolver><br>
<solutionClass>org.drools.planner.examples.curriculumcourse.domain.CurriculumCourseSchedule</solutionClass><br>
<scoreDrl>...</scoreDrl><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>
<localSearchSolver><br>
<solutionClass>....</solutionClass><br>
<scoreDrl>...</scoreDrl><br>
After in *SolverConfig.xml and *BenchmarkConfig.xml:<br>
<localSearchSolver><br>
<solutionClass>....</solutionClass><br>
<planningEntityClass>org.drools.planner.examples.curriculumcourse.domain.Lecture</planningEntityClass><br>
<scoreDrl>...</scoreDrl><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<...> {<br>
<br>
private List<Lecture> lectureList;<br>
<br>
...<br>
<br>
public List<Lecture> getLectureList() {...}<br>
public void setLectureList(List<Lecture>
lectureList) {...}<br>
<br>
}<br>
After in *.java:<br>
public class CurriculumCourseSchedule ... implements
Solution<...> {<br>
<br>
private List<Lecture> lectureList;<br>
<br>
...<br>
<br>
@PlanningEntityCollectionProperty<br>
public List<Lecture> getLectureList() {...}<br>
public void setLectureList(List<Lecture>
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<...> {<br>
<br>
private InstitutionalWeighting
institutionalWeighting;<br>
<br>
private List<Teacher> teacherList;<br>
private List<Curriculum> curriculumList;<br>
...<br>
private List<UnavailablePeriodConstraint>
unavailablePeriodConstraintList;<br>
<br>
private List<Lecture> lectureList;<br>
<br>
private HardAndSoftScore score;<br>
<br>
...<br>
<br>
public String getName() {...}<br>
<br>
public InstitutionalWeighting
getInstitutionalWeighting() {...}<br>
<br>
public List<Teacher> getTeacherList() {...}<br>
<br>
public List<Curriculum> getCurriculumList()
{...}<br>
<br>
...<br>
<br>
public List<UnavailablePeriodConstraint>
getUnavailablePeriodConstraintList() {...}<br>
<br>
@PlanningEntityCollectionProperty<br>
public List<Lecture> getLectureList() {...}<br>
<br>
public ...Score getScore() {...}<br>
<br>
public Collection<? extends Object> getFacts()
{<br>
List<Object> facts = new
ArrayList<Object>();<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<TopicConflict>
calculateTopicConflictList() {...}<br>
<br>
}<br>
After in *.java:<br>
public class ... implements Solution<...> {<br>
<br>
private InstitutionalWeighting
institutionalWeighting;<br>
<br>
private List<Teacher> teacherList;<br>
private List<Curriculum> curriculumList;<br>
...<br>
private List<UnavailablePeriodConstraint>
unavailablePeriodConstraintList;<br>
<br>
private List<Lecture> 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<Teacher> getTeacherList() {...}<br>
<br>
@PlanningFactCollectionProperty<br>
public List<Curriculum> getCurriculumList()
{...}<br>
<br>
...<br>
<br>
@PlanningFactCollectionProperty<br>
public List<UnavailablePeriodConstraint>
getUnavailablePeriodConstraintList() {...}<br>
<br>
// This is not a PlanningFactCollectionProperty: it
is a PlanningEntityCollectionProperty<br>
@PlanningEntityCollectionProperty<br>
public List<Lecture> 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<TopicConflict>
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<Lecture>
createLectureList(List<Course> courseList) {<br>
List<Lecture> lectureList = new
ArrayList<Lecture>(courseList.size());<br>
long id = 0L;<br>
for (Course course : courseList) {<br>
for (int i = 0; i <
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<...> {<br>
<br>
public boolean isInitialized() {<br>
return (lectureList != null);<br>
}<br>
<br>
...<br>
<br>
}<br>
After in *.java:<br>
public class ... implements Solution<...> {<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 moz-do-not-send="true"
href="https://github.com/droolsjbpm/drools-planner/pull/2/files"
target="_blank">https://github.com/droolsjbpm/drools-planner/pull/2/files</a>
<pre cols="72">--
With kind regards,
Geoffrey De Smet</pre>
</div>
<br>
_______________________________________________<br>
rules-dev mailing list<br>
<a moz-do-not-send="true"
href="mailto:rules-dev@lists.jboss.org">rules-dev@lists.jboss.org</a><br>
<a moz-do-not-send="true"
href="https://lists.jboss.org/mailman/listinfo/rules-dev"
target="_blank">https://lists.jboss.org/mailman/listinfo/rules-dev</a><br>
<br>
</blockquote>
</div>
<br>
<pre wrap="">
<fieldset class="mimeAttachmentHeader"></fieldset>
_______________________________________________
rules-dev mailing list
<a class="moz-txt-link-abbreviated" href="mailto:rules-dev@lists.jboss.org">rules-dev@lists.jboss.org</a>
<a class="moz-txt-link-freetext" href="https://lists.jboss.org/mailman/listinfo/rules-dev">https://lists.jboss.org/mailman/listinfo/rules-dev</a>
</pre>
</blockquote>
<br>
<pre class="moz-signature" cols="72">--
With kind regards,
Geoffrey De Smet</pre>
</body>
</html>