<html><body><div style="color:#000; background-color:#fff; font-family:tahoma, new york, times, serif;font-size:10pt">Hi, me once more.<br><br>I guess you figured out by now that I am quite a newbie to Drools (planning).<br>Problem is I need to write a POC in max 3 to 4 days...<br>I'm drifting, so please help...<br><br>I have written a basic solution for planning plane-maintenance.<br>I stripped it to it's very basics and it works... if I keep the number of planes, periods and technicians to a very minimum.<br>I removed all additional constraints like skill matching and availability during a period...<br><br>Planning maintenance for 3 planes with each 2 required technicians, 4 available periods and a list of 10 available technicians delivers a solution in about 3 seconds.<br>Simply increasing the number of technicians per plane from 2 to 3 results in an indefinite solving time (I did not wait longer than a few minutes).<br>Decreasing the numbers
 obviously works, at an elapsed time slightly under 3 seconds.<br><br>I finally need to plan about 500 plane maintenance jobs (3 to 4 technicians per maintenance job) over 12 available periods with about 400 available technicians..<br>So there must be something wrong/incomplete in my solution.<br><br>What I did:<br><br>I have created a planningEntity M<span class="tab">aintenanceTask with two planning variables (technician and period)&nbsp; and a simple rule file.<br>(See all below)<br>Running this solution thus results in such poor solving time.<br><br>Can you please advice me in what I am doing wrong?<br><br>Many thanks!!<br><br><span style="font-weight: bold;">PlanningEntity (</span></span><span class="tab"><span style="font-weight: bold;"><span class="tab">MaintenanceTask .java</span>):</span><br><br>@PlanningEntity(difficultyWeightFactoryClass = TaskDifficultyWeightFactory.class)<br>public class MaintenanceTask {<br><br>&nbsp;&nbsp;&nbsp; private
 Period period;<br>&nbsp;&nbsp;&nbsp; private Project project;<br>&nbsp;&nbsp;&nbsp; private Technician technician;<br><br>&nbsp;&nbsp;&nbsp; public </span><span class="tab"><span class="tab">MaintenanceTask </span>(Project aProject) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; this.project = aProject;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; public String getId(){<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return project.getId()+"-"+hashCode();<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; @PlanningVariable<br>&nbsp;&nbsp;&nbsp; @ValueRange(type = ValueRangeType.FROM_SOLUTION_PROPERTY, solutionProperty = "technicians")<br>&nbsp;&nbsp;&nbsp; public </span><span class="tab"><span class="tab">Technician </span>getTechnician() {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return technician;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; public void setTechnician(Technician aTechnician) {<br>&nbsp;&nbsp;&nbsp;
 &nbsp;&nbsp;&nbsp; this.technican= </span><span class="tab"><span class="tab">aTechnician</span>;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; @PlanningVariable<br>&nbsp;&nbsp;&nbsp; @ValueRange(type = ValueRangeType.FROM_SOLUTION_PROPERTY, solutionProperty = "periods")<br>&nbsp;&nbsp;&nbsp; public Period getPeriod() {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return period;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; public void setPeriod(Period aPeriod) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; this.period = </span><span class="tab"><span class="tab">aPeriod</span>;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; public String getPeriodId(){<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return period == null ? null : period.getId();<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; public String getProjectId(){<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return project </span><span class="tab"><span
 class="tab">== null ? null :</span> <span class="tab">project.getId();</span></span><br><span class="tab">&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp; public </span><span class="tab"><span class="tab">MaintenanceTask </span>clone() {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span><span class="tab"><span class="tab">MaintenanceTask </span>clone = new </span><span class="tab"><span class="tab">MaintenanceTask </span>(project);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; clone.period = this.period;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; clone.technician= this.</span><span class="tab"><span class="tab">technician</span>;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return clone;<br>&nbsp;&nbsp;&nbsp; }<br><br>}<br><br></span><div><span><span style="font-weight: bold;">Project.java</span></span></div><div style="color: rgb(0, 0, 0); font-size: 13.3333px; font-family: tahoma,new york,times,serif; background-color: transparent; font-style:
 normal;"><br><span></span></div><div style="color: rgb(0, 0, 0); font-size: 13.3333px; font-family: tahoma,new york,times,serif; background-color: transparent; font-style: normal;"><span>public class Project {<br>&nbsp;&nbsp;&nbsp; private Plane plane;<br>&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; public Project(Plane aPlane) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.plane = aPlane;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; public Plane getPlane() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return plane;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; public String getId() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return getPlane().getName();<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; public int getTechnicianLoad(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return getPlane().getTechnicianLoad();<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; public
 </span><span><span>List&lt;MaintenanceTask&gt;</span> getTasks() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List&lt;MaintenanceTask&gt; tasks = new ArrayList&lt;MaintenanceTask&gt;();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; getTechnicianLoad(); i++) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tasks.add(new MaintenanceTask(this));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return tasks;<br>&nbsp;&nbsp;&nbsp; }<br>}</span></div><div style="color: rgb(0, 0, 0); font-size: 13.3333px; font-family: tahoma,new york,times,serif; background-color: transparent; font-style: normal;"><br><span></span></div><div style="color: rgb(0, 0, 0); font-size: 13.3333px; font-family: tahoma,new york,times,serif; background-color: transparent; font-style: normal;"><span>Technician.java and Period.java are at this moment basically just classes having an getId and
 getName method, nothing more.</span></div><div style="color: rgb(0, 0, 0); font-size: 13.3333px; font-family: tahoma,new york,times,serif; background-color: transparent; font-style: normal;"><span>Plane.java has </span>a method <span>getTechnicianLoad that returns the number of required technicians for the maintenance.</span></div><div style="color: rgb(0, 0, 0); font-size: 13.3333px; font-family: tahoma,new york,times,serif; background-color: transparent; font-style: normal;"><br><span></span></div><div style="color: rgb(0, 0, 0); font-size: 13.3333px; font-family: tahoma,new york,times,serif; background-color: transparent; font-style: normal;"><span><span style="font-weight: bold;">This is the config file</span> (basically copy from one of the examples)<br></span></div><div style="color: rgb(0, 0, 0); font-size: 13.3333px; font-family: tahoma,new york,times,serif; background-color: transparent; font-style: normal;"><br><span></span></div><div
 style="color: rgb(0, 0, 0); font-size: 13.3333px; font-family: tahoma,new york,times,serif; background-color: transparent; font-style: normal;"><span>&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br>&lt;solver&gt;<br>&nbsp; &lt;!-- Domain model configuration --&gt;<br>&nbsp; &lt;solutionClass&gt;be.axi.planner.domain.MaintenanceSchedule&lt;/solutionClass&gt;<br>&nbsp; &lt;planningEntityClass&gt;be.axi.planner.domain.MaintenanceTask&lt;/planningEntityClass&gt;<br><br>&nbsp; &lt;!-- Score configuration --&gt;<br>&nbsp; &lt;scoreDirectorFactory&gt;<br>&nbsp;&nbsp;&nbsp; &lt;scoreDefinitionType&gt;SIMPLE&lt;/scoreDefinitionType&gt;<br>&nbsp;&nbsp;&nbsp; &lt;scoreDrl&gt;/maintenancePlannerRules.drl&lt;/scoreDrl&gt;<br>&nbsp; &lt;/scoreDirectorFactory&gt;<br><br>&nbsp; &lt;termination&gt;<br>&nbsp;&nbsp;&nbsp; &lt;maximumSecondsSpend&gt;700&lt;/maximumSecondsSpend&gt;<br>&nbsp; &lt;/termination&gt;</span></div><div style="color: rgb(0, 0, 0); font-size:
 13.3333px; font-family: tahoma,new york,times,serif; background-color: transparent; font-style: normal;"><span><br></span></div><div style="color: rgb(0, 0, 0); font-size: 13.3333px; font-family: tahoma,new york,times,serif; background-color: transparent; font-style: normal;"><span>&nbsp; &lt;constructionHeuristic&gt;<br>&nbsp;&nbsp;&nbsp; &lt;constructionHeuristicType&gt;FIRST_FIT_DECREASING&lt;/constructionHeuristicType&gt;<br>&nbsp;&nbsp;&nbsp; &lt;constructionHeuristicPickEarlyType&gt;FIRST_LAST_STEP_SCORE_EQUAL_OR_IMPROVING&lt;/constructionHeuristicPickEarlyType&gt;<br>&nbsp; &lt;/constructionHeuristic&gt;<br>&nbsp; &lt;localSearch&gt;<br>&nbsp;&nbsp;&nbsp; &lt;selector&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;moveFactoryClass&gt;org.drools.planner.core.move.generic.GenericChangeMoveFactory&lt;/moveFactoryClass&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;!-- GenericChangeMoveFactory is the generic form of RowChangeMoveFactory:
 --&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;!--&lt;moveFactoryClass&gt;org.drools.planner.examples.nqueens.solver.move.factory.RowChangeMoveFactory&lt;/moveFactoryClass&gt;--&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/selector&gt;<br>&nbsp;&nbsp;&nbsp; &lt;acceptor&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;solutionTabuSize&gt;1000&lt;/solutionTabuSize&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;planningEntityTabuSize&gt;7&lt;/planningEntityTabuSize&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/acceptor&gt;<br>&nbsp;&nbsp;&nbsp; &lt;forager&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;minimalAcceptedSelection&gt;800&lt;/minimalAcceptedSelection&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/forager&gt;<br>&nbsp; &lt;/localSearch&gt;<br>&lt;/solver&gt;</span></div><div style="color: rgb(0, 0, 0); font-size: 13.3333px; font-family: tahoma,new york,times,serif; background-color: transparent; font-style: normal;"><br><span></span></div><div style="color: rgb(0, 0, 0); font-size: 13.3333px; font-family:
 tahoma,new york,times,serif; background-color: transparent; font-style: normal;"><span><span style="font-weight: bold;">this is the rules file</span>:</span></div><div style="color: rgb(0, 0, 0); font-size: 13.3333px; font-family: tahoma,new york,times,serif; background-color: transparent; font-style: normal;"><br><span></span></div><div style="color: rgb(0, 0, 0); font-size: 13.3333px; font-family: tahoma,new york,times,serif; background-color: transparent; font-style: normal;"><span>package org.drools.planner.examples.pas.solver;<br>&nbsp;&nbsp;&nbsp; dialect "java"<br><br>import org.drools.planner.core.score.buildin.simple.SimpleScoreHolder;<br>import org.drools.planner.core.score.constraint.IntConstraintOccurrence;<br>import org.drools.planner.core.score.constraint.UnweightedConstraintOccurrence<br>import org.drools.planner.core.score.constraint.ConstraintType;<br><br>import be.axi.planner.domain.MaintenanceTask;<br><br>global SimpleScoreHolder
 scoreHolder;<br><br>// ############################################################################<br>// Hard constraints<br>// ############################################################################<br><br>rule "noMultipleAssignmentsInOnePeriod"<br>&nbsp;&nbsp;&nbsp; when<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $t1 : MaintenanceTask($id : id, $periodId : periodId, $technician : technician )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $t2 : MaintenanceTask(id != $id,&nbsp; periodId == $periodId, technician == $technician)<br>&nbsp;&nbsp;&nbsp; then<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; insertLogical(new UnweightedConstraintOccurrence("noMultipleAssignmentsInOnePeriod", $t1, $t2));<br>end<br><br>rule "tasksInSameProjectMustBeInSamePeriod"<br>&nbsp;&nbsp;&nbsp; when<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $t1 : MaintenanceTask($id : id, $periodId : periodId, $projectId : projectId )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 $t2 : MaintenanceTask(id != $id,&nbsp; periodId != $periodId, projectId == $projectId)<br>&nbsp;&nbsp;&nbsp; then<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; insertLogical(new UnweightedConstraintOccurrence("tasksInSameProjectMustBeInSamePeriod", $t1, $t2));<br>end<br><br>// ############################################################################<br>// Calculate score<br>// ############################################################################<br><br>rule "hardConstraintsBroken"<br>&nbsp;&nbsp;&nbsp; when<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $occurrenceCount : Number() from accumulate(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $unweightedConstraintOccurrence : UnweightedConstraintOccurrence(),<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; count($unweightedConstraintOccurrence)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; )<br>&nbsp;&nbsp;&nbsp;
 then<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scoreHolder.setScore(- $occurrenceCount.intValue());<br>end<br></span></div><div style="color: rgb(0, 0, 0); font-size: 13.3333px; font-family: tahoma,new york,times,serif; background-color: transparent; font-style: normal;"><br></div><div style="color: rgb(0, 0, 0); font-size: 13.3333px; font-family: tahoma,new york,times,serif; background-color: transparent; font-style: normal;"><span style="font-weight: bold;">Solution file:</span></div><div style="color: rgb(0, 0, 0); font-size: 13.3333px; font-family: tahoma,new york,times,serif; background-color: transparent; font-style: normal;"><br></div><div style="color: rgb(0, 0, 0); font-size: 13.3333px; font-family: tahoma,new york,times,serif; background-color: transparent; font-style: normal;">package be.axi.planner.domain;<br><br>import java.util.ArrayList;<br>import java.util.Collection;<br>import java.util.List;<br><br>import
 org.drools.planner.api.domain.solution.PlanningEntityCollectionProperty;<br>import org.drools.planner.core.score.buildin.simple.SimpleScore;<br>import org.drools.planner.core.solution.Solution;<br><br><br>public class MaintenanceSchedule implements Solution&lt;SimpleScore&gt;{<br><br>&nbsp;&nbsp;&nbsp; private SimpleScore score;<br>&nbsp;&nbsp;&nbsp; private List&lt;MaintenanceTask&gt; maintenanceTasks;<br>&nbsp;&nbsp;&nbsp; private List&lt;Period&gt; periods;<br>&nbsp;&nbsp;&nbsp; private List&lt;Technician&gt; technicians;<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; public MaintenanceSchedule cloneSolution() {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; MaintenanceSchedule clone = new MaintenanceSchedule();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clone.periods = this.periods;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clone.technicians = this.technicians;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List&lt;MaintenanceTask&gt; clonedTasks =
 new ArrayList&lt;MaintenanceTask&gt;(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; maintenanceTasks.size());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (MaintenanceTask task : maintenanceTasks) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; MaintenanceTask clonedTask = task.clone();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; clonedTasks.add(clonedTask);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clone.maintenanceTasks = clonedTasks;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clone.score = this.score;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return clone;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; public Collection&lt;? extends Object&gt; getProblemFacts() {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("&gt;&gt;getting
 problemfacts");<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; List&lt;Object&gt; facts = new ArrayList&lt;Object&gt;();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; facts.addAll(periods);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; facts.addAll(technicians);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Do not add the planning entity's (maintenaceTasks) because that will be done automatically<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return facts;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; public SimpleScore getScore() {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return this.score;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; public void setScore(SimpleScore aScore) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; this.score = aScore;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (aScore != null){<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("Score set to " + aScore.getScore());<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
 }<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; @PlanningEntityCollectionProperty<br>&nbsp;&nbsp;&nbsp; public List&lt;MaintenanceTask&gt; getMaintenanceTasks() {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("getting tasks: #" +maintenanceTasks.size());<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return maintenanceTasks;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; public void setMaintenanceTasks(List&lt;MaintenanceTask&gt; aMaintenanceTasks) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("setting tasks");<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; this.maintenanceTasks = aMaintenanceTasks;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; public void setTechnicians(List&lt;Technician&gt; aTechnicians) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("setting Technicians");<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; this.technicians = aTechnicians;<br>&nbsp;&nbsp;&nbsp;
 }<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; public List&lt;Technician&gt; getTechnicians() {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("Getting Technicians: #"+technicians.size());<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return technicians;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; public List&lt;Period&gt; getPeriods() {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("getting periods");<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return periods;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; public void setPeriods(List&lt;Period&gt; periods) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; this.periods = periods;<br>&nbsp;&nbsp;&nbsp; }<br><br>}<br><br><br><br></div><div style="color: rgb(0, 0, 0); font-size: 13.3333px; font-family: tahoma,new york,times,serif; background-color: transparent; font-style:
 normal;"><br><span></span></div><div>-----------------<br>http://www.codessentials.com - Your essential software, for free!<br>Follow us at http://twitter.com/#!/Codessentials<br></div>  <div style="font-family: tahoma, new york, times, serif; font-size: 10pt;"> <div style="font-family: times new roman, new york, times, serif; font-size: 12pt;"> <div dir="ltr"> <font face="Arial" size="2"> <hr size="1">  <b><span style="font-weight:bold;">From:</span></b> Geoffrey De Smet &lt;ge0ffrey.spam@gmail.com&gt;<br> <b><span style="font-weight: bold;">To:</span></b> rules-users@lists.jboss.org <br> <b><span style="font-weight: bold;">Sent:</span></b> Friday, August 31, 2012 10:54 AM<br> <b><span style="font-weight: bold;">Subject:</span></b> Re: [rules-users] Best model for planning? technicians, airplanes and shifts<br> </font> </div> <br>
Op 31-08-12 09:46, Michiel Vermandel schreef:<br>&gt; Thank you for the response.<br>&gt; I think I forgot one level of complexity (?):<br>&gt;<br>&gt; The moment of maintenance of a plane is not fixed.<br>&gt;<br>&gt; We have 12 "periods" per year for maintenance.<br>&gt; One period every month.<br>&gt;<br>&gt; We need to make the planning in such way that the list of planes is<br>&gt; planned somewhere in these 12 periods.<br>&gt; But it is not important that a specific plane is maintained at a<br>&gt; specific period.<br>&gt; It has though a calendar of unavailability.<br>&gt;<br>&gt; So the job (==Shift) of the Task (==ShiftAssignment) has no hard<br>&gt; constraint on period.<br>&gt;<br>&gt; We need to find that combination with the best match between required<br>&gt; skills for the job and available technicians.<br>&gt; It's better to plan the job on a later period if at that time a more<br>&gt; skilled technician is available.<br>&gt;<br>&gt; I
 hope this is a bit clear.<br>&gt;<br>&gt; So, given this addition, should I take as planning variables:<br>&gt;<br>&gt; 1) Period (List of 12 periods)<br>&gt; 2) Technician<br><br>Good idea<br><br>&gt;<br>&gt; Then use period to check availability on both plane and technician<br>&gt; (hard-constraint)<br>I see 3:<br>- plane availability<br>- technician conflicts (2 tasks at the same time)<br>- technician availability<br>&gt; Then give a better weight on skill-match (soft-constrain)?<br><br>yes (and possible others, such as work load, technician desires, ...)<br><br>&gt;<br>&gt; Thank you.<br>&gt;<br>&gt; Michiel<br>&gt;<br>&gt; -----------------<br>&gt; http://www.codessentials.com - Your essential software, for free!<br>&gt; Follow us at http://twitter.com/#!/Codessentials<br>&gt; ------------------------------------------------------------------------<br>&gt; *From:* Geoffrey De Smet &lt;<a ymailto="mailto:ge0ffrey.spam@gmail.com"
 href="mailto:ge0ffrey.spam@gmail.com">ge0ffrey.spam@gmail.com</a>&gt;<br>&gt; *To:* <a ymailto="mailto:rules-users@lists.jboss.org" href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a><br>&gt; *Sent:* Friday, August 31, 2012 9:08 AM<br>&gt; *Subject:* Re: [rules-users] Best model for planning? technicians,<br>&gt; airplanes and shifts<br>&gt;<br>&gt; Op 30-08-12 18:02, mvermand schreef:<br>&gt;&nbsp; &gt; Hi,<br>&gt;&nbsp; &gt;<br>&gt;&nbsp; &gt; I'd like some advice on how to make my model.<br>&gt;&nbsp; &gt;<br>&gt;&nbsp; &gt; I need to plan maintenance-schedules for - let's say - airplanes.<br>&gt;&nbsp; &gt; Constraints are:<br>&gt;&nbsp; &gt; - planes are only at given moments available for maintenance (when not in<br>&gt;&nbsp; &gt; the air ;-)<br>&gt;&nbsp; &gt; - maintenance of a planes requires a number of techniciens (with specific<br>&gt;&nbsp; &gt; skills).<br>&gt;&nbsp; &gt; - techniciens have skills and also shifts and
 vacation.<br>&gt;&nbsp; &gt;<br>&gt;<br>&gt; Sounds like the nurse rostering example in Planner :)<br>&gt; In nurse rostering, such a Shift has a ShiftDate and a ShiftType.<br>&gt; The difference is, you need to assign jobs instead of shifts.<br>&gt;<br>&gt;&nbsp; &gt; Now, first I tought to make the maintenance of a plane the<br>&gt; planningEntity.<br>&gt;&nbsp; &gt; But I did not know how to populate and match the techniciens.<br>&gt;<br>&gt; I wouldn't make plane the planningEntity either, it's on the one side of<br>&gt; the manyToOne relation.<br>&gt;<br>&gt;&nbsp; &gt;<br>&gt;&nbsp; &gt; So, second I tought to make a new Task-class the planningEntity.<br>&gt;&nbsp; &gt; A Task is a job that needs to be done by a technicien with specific<br>&gt; skills.<br>&gt;&nbsp; &gt; Maintaining a plane requires then a number of tasks.<br>&gt;<br>&gt; Good idea. In nurse rostering, a Task is called a ShiftAssignment.<br>&gt; You can generate all Tasks in
 advance based on the Planes and their jobs<br>&gt; and the number of technicians needed by each job.<br>&gt;<br>&gt; I recommend to make separate Task instances for multiple technicians<br>&gt; that perform the same job together on the same plane. In nurse rostering<br>&gt; there are also multiple ShiftAssignments (=tasks) per Shift (=job).<br>&gt;<br>&gt;&nbsp; &gt;<br>&gt;&nbsp; &gt; If I choose this model, I think I'll have to pass two Plannings<br>&gt; variables to<br>&gt;&nbsp; &gt; the Task planningEntity:<br>&gt;&nbsp; &gt; 1) a Maintenance-fact (Plane + Period + list of required tasks) and<br>&gt;<br>&gt; I don't think this is a planner variable on the planning entity Task.<br>&gt; It really defines the Task: what job on what plane (and some of sort of<br>&gt; requiredTechnicanCountIndex)<br>&gt;<br>&gt;&nbsp; &gt; 2) a Technicien-fact (?)<br>&gt; This is a planning variable.<br>&gt; You're assigning task to techinicians.<br>&gt; Each task has
 exactly 1 technician (because a job has multiple tasks,<br>&gt; one per required technician).<br>&gt; Each technician can work on multiple tasks, but the hard/soft<br>&gt; constraints make sure that it's not at the same time.<br>&gt;<br>&gt;&nbsp; &gt;<br>&gt;&nbsp; &gt; Then I'll need to check if availabity of plane and availability of<br>&gt;&nbsp; &gt; technicien match and also skill-requirement of task and skills of<br>&gt;&nbsp; &gt; technicien.<br>&gt;<br>&gt; Yep, with constraints<br>&gt;<br>&gt;&nbsp; &gt;<br>&gt;&nbsp; &gt; Do you think this second model is the right one?<br>&gt;&nbsp; &gt;<br>&gt;&nbsp; &gt; Will it perform well?<br>&gt;&nbsp; &gt; =&gt; ? matching all combinations of plane availabilty and<br>&gt;&nbsp; &gt; techniciens-availability and -skills.<br>&gt;<br>&gt; It should, see the nurse rostering problem.<br>&gt; In Planner 5.5.0.Beta1, I would add a filter on the swap move selector<br>&gt; to prevent it from swapping 2
 technicians assigned to different tasks on<br>&gt; the same job.<br>&gt;<br>&gt; <a href="https://github.com/droolsjbpm/drools-planner/blob/master/drools-planner-examples/src/main/java/org/drools/planner/examples/curriculumcourse/solver/move/DifferentCourseSwapMoveFilter.javatd" target="_blank">https://github.com/droolsjbpm/drools-planner/blob/master/drools-planner-examples/src/main/java/org/drools/planner/examples/curriculumcourse/solver/move/DifferentCourseSwapMoveFilter.javatd</a><br>&gt;<br>&gt;&nbsp; &gt;<br>&gt;&nbsp; &gt; Thanks in advance<br>&gt;&nbsp; &gt;<br>&gt;&nbsp; &gt;<br>&gt;&nbsp; &gt;<br>&gt;&nbsp; &gt; --<br>&gt;&nbsp; &gt; View this message in context:<br>&gt; <a href="http://drools.46999.n3.nabble.com/Best-model-for-planning-tp4019464.html" target="_blank">http://drools.46999.n3.nabble.com/Best-model-for-planning-tp4019464.html</a><br>&gt;&nbsp; &gt; Sent from the Drools: User forum mailing list archive at Nabble.com<br>&gt; &lt;<a
 href="http://nabble.com/" target="_blank">http://nabble.com/</a>&gt;.<br>&gt;&nbsp; &gt; _______________________________________________<br>&gt;&nbsp; &gt; rules-users mailing list<br>&gt;&nbsp; &gt; <a ymailto="mailto:rules-users@lists.jboss.org" href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a> &lt;mailto:<a ymailto="mailto:rules-users@lists.jboss.org" href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a>&gt;<br>&gt;&nbsp; &gt; <a href="https://lists.jboss.org/mailman/listinfo/rules-users" target="_blank">https://lists.jboss.org/mailman/listinfo/rules-users</a><br>&gt;&nbsp; &gt;<br>&gt;<br>&gt;<br>&gt; _______________________________________________<br>&gt; rules-users mailing list<br>&gt; <a ymailto="mailto:rules-users@lists.jboss.org" href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a> &lt;mailto:<a ymailto="mailto:rules-users@lists.jboss.org"
 href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a>&gt;<br>&gt; <a href="https://lists.jboss.org/mailman/listinfo/rules-users" target="_blank">https://lists.jboss.org/mailman/listinfo/rules-users</a><br>&gt;<br>&gt;<br>&gt;<br>&gt;<br>&gt; _______________________________________________<br>&gt; rules-users mailing list<br>&gt; <a ymailto="mailto:rules-users@lists.jboss.org" href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a><br>&gt; <a href="https://lists.jboss.org/mailman/listinfo/rules-users" target="_blank">https://lists.jboss.org/mailman/listinfo/rules-users</a><br>&gt;<br><br><br>_______________________________________________<br>rules-users mailing list<br><a ymailto="mailto:rules-users@lists.jboss.org" href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a><br><a href="https://lists.jboss.org/mailman/listinfo/rules-users"
 target="_blank">https://lists.jboss.org/mailman/listinfo/rules-users</a><br><br><br> </div> </div>  </div></body></html>