Browse Source

Descente OK

Paul Faure 4 months ago
parent
commit
2824abf3a5

+ 16
- 0
src/main/java/jobshop/encodings/ResourceOrder.java View File

@@ -72,6 +72,22 @@ public final class ResourceOrder extends Encoding {
72 72
         return tasksByMachine[machine][taskIndex];
73 73
     }
74 74
 
75
+    /** Returns the index of a particular task scheduled on a particular machine.
76
+     *
77
+     * @param machine Machine on which the task to retrieve is scheduled.
78
+     * @param task Task in the queue for this machine.
79
+     * @return The index of the task scheduled on a machine.
80
+     */
81
+    public int getIndexOfTaskOnMachine(int machine, Task task) {
82
+        int i = 0;
83
+        boolean found = false;
84
+        while (i<instance.numJobs && !found) {
85
+            found = getTaskOfMachine(machine, i).equals(task);
86
+            i++;
87
+        }
88
+        return i - 1;
89
+    }
90
+
75 91
     /** Exchange the order of two tasks that are scheduled on a given machine.
76 92
      *
77 93
      * @param machine Machine on which the two tasks appear (line on which to perform the exchange)

+ 43
- 1
src/main/java/jobshop/solvers/DescentSolver.java View File

@@ -3,7 +3,17 @@ package jobshop.solvers;
3 3
 import jobshop.Instance;
4 4
 import jobshop.Result;
5 5
 import jobshop.encodings.ResourceOrder;
6
+import jobshop.encodings.Schedule;
7
+import jobshop.solvers.neighborhood.Neighbor;
6 8
 import jobshop.solvers.neighborhood.Neighborhood;
9
+import jobshop.solvers.neighborhood.Nowicki;
10
+
11
+import java.io.IOException;
12
+import java.nio.file.Paths;
13
+import java.util.ArrayList;
14
+import java.util.Iterator;
15
+import java.util.List;
16
+import java.util.stream.Collectors;
7 17
 
8 18
 /** An empty shell to implement a descent solver. */
9 19
 public class DescentSolver implements Solver {
@@ -23,7 +33,39 @@ public class DescentSolver implements Solver {
23 33
 
24 34
     @Override
25 35
     public Result solve(Instance instance, long deadline) {
26
-        throw new UnsupportedOperationException();
36
+        Schedule schedule = baseSolver.solve(instance, deadline).schedule.get();
37
+        ResourceOrder resourceOrder = new ResourceOrder(schedule);
38
+        boolean ended = false;
39
+        int bestMakespan;
40
+        Neighbor<ResourceOrder> bestNeighbor;
41
+
42
+        while (!ended) {
43
+            schedule = resourceOrder.toSchedule().get();
44
+            bestMakespan = schedule.makespan();
45
+            bestNeighbor = null;
46
+            List<Neighbor<ResourceOrder>> generatedNeighbors = neighborhood.generateNeighbors(resourceOrder);
47
+            Iterator<Neighbor<ResourceOrder>> iter = generatedNeighbors.iterator();
48
+            while (iter.hasNext()) {
49
+                Neighbor<ResourceOrder> neighbor = iter.next();
50
+                neighbor.applyOn(resourceOrder);
51
+                try {
52
+                    Schedule currentSchedule = resourceOrder.toSchedule().get();
53
+                    int currentMakespan = currentSchedule.makespan();
54
+                    if (currentMakespan < bestMakespan) {
55
+                        bestMakespan = currentMakespan;
56
+                        bestNeighbor = neighbor;
57
+                    }
58
+                } catch (Exception e) {
59
+                }
60
+                neighbor.undoApplyOn(resourceOrder);
61
+            }
62
+            if (bestNeighbor == null) {
63
+                ended = true;
64
+            } else {
65
+                bestNeighbor.applyOn(resourceOrder);
66
+            }
67
+        }
68
+        return new Result(instance, resourceOrder.toSchedule(), Result.ExitCause.ProvedOptimal);
27 69
     }
28 70
 
29 71
 }

+ 96
- 35
src/main/java/jobshop/solvers/GreedySolver.java View File

@@ -23,6 +23,9 @@ public class GreedySolver implements Solver {
23 23
     final Priority priority;
24 24
 
25 25
     final ArrayList<Task> tachesRestantes;
26
+    int[] machineFreeDate;
27
+    int[] jobFreeDate;
28
+
26 29
 
27 30
 
28 31
     /** Creates a new greedy solver that will use the given priority. */
@@ -31,8 +34,12 @@ public class GreedySolver implements Solver {
31 34
         this.tachesRestantes = new ArrayList<>();
32 35
     }
33 36
 
37
+    private int getEarliestDate(Instance instance, Task task) {
38
+        return Math.max(machineFreeDate[instance.machine(task)], jobFreeDate[task.job]);
39
+    }
40
+
34 41
     /** return true if t1 est plus prioritaire que t1 **/
35
-    private boolean prioritaire(Instance instance, Task t1, Task t2) throws Exception {
42
+    private boolean prioritaire(Instance instance, Task t1, Task t2) {
36 43
         boolean rt = false;
37 44
         switch(priority) {
38 45
             case SPT:
@@ -65,51 +72,107 @@ public class GreedySolver implements Solver {
65 72
                 rt = sigmaT1 >= sigmaT2;
66 73
                 break;
67 74
             case EST_SPT:
68
-                throw new Exception("UNKNOWN PRIORITY");
69
-                //break;
75
+                if (getEarliestDate(instance, t1) < getEarliestDate(instance, t2)) {
76
+                    rt = true;
77
+                } else if (getEarliestDate(instance, t1) > getEarliestDate(instance, t2)) {
78
+                    rt = false;
79
+                } else {
80
+                    rt = instance.duration(t1) <= instance.duration(t2);
81
+                }
82
+                break;
70 83
             case EST_LPT:
71
-                throw new Exception("UNKNOWN PRIORITY");
72
-                //break;
84
+                if (getEarliestDate(instance, t1) < getEarliestDate(instance, t2)) {
85
+                    rt = true;
86
+                } else if (getEarliestDate(instance, t1) > getEarliestDate(instance, t2)) {
87
+                    rt = false;
88
+                } else {
89
+                    rt = instance.duration(t1) >= instance.duration(t2);
90
+                }
91
+                break;
73 92
             case EST_SRPT:
74
-                throw new Exception("UNKNOWN PRIORITY");
75
-                //break;
93
+                if (getEarliestDate(instance, t1) < getEarliestDate(instance, t2)) {
94
+                    rt = true;
95
+                } else if (getEarliestDate(instance, t1) > getEarliestDate(instance, t2)) {
96
+                    rt = false;
97
+                } else {
98
+                    sigmaT1 = 0;
99
+                    sigmaT2 = 0;
100
+                    for (i=t1.task; i<instance.numTasks; i++) {
101
+                        sigmaT1 += instance.duration(t1.job, i);
102
+                    }
103
+                    for (i=t2.task; i<instance.numTasks; i++) {
104
+                        sigmaT2 += instance.duration(t2.job, i);
105
+                    }
106
+                    rt = sigmaT1 <= sigmaT2;
107
+                }
108
+                break;
76 109
             case EST_LRPT:
77
-                throw new Exception("UNKNOWN PRIORITY");
78
-                //break;
110
+                if (getEarliestDate(instance, t1) < getEarliestDate(instance, t2)) {
111
+                    rt = true;
112
+                } else if (getEarliestDate(instance, t1) > getEarliestDate(instance, t2)) {
113
+                    rt = false;
114
+                } else {
115
+                    sigmaT1 = 0;
116
+                    sigmaT2 = 0;
117
+                    for (i=t1.task; i<instance.numTasks; i++) {
118
+                        sigmaT1 += instance.duration(t1.job, i);
119
+                    }
120
+                    for (i=t2.task; i<instance.numTasks; i++) {
121
+                        sigmaT2 += instance.duration(t2.job, i);
122
+                    }
123
+                    rt = sigmaT1 >= sigmaT2;
124
+                }
125
+                break;
79 126
         }
80 127
         return rt;
81 128
     }
82 129
 
83
-    private void addTask(Instance instance, Task task) throws Exception {
84
-        Iterator<Task> iter = this.tachesRestantes.iterator();
85
-        int index = 0;
86
-        boolean trouve = false;
87
-        while (iter.hasNext() && !trouve) {
88
-            Task current = iter.next();
89
-            if (this.prioritaire(instance, task, current)) {
90
-                trouve = true;
91
-            } else {
92
-                index++;
130
+    private void addTask(Instance instance, Task task) {
131
+        if (priority == Priority.SPT || priority == Priority.LPT || priority == Priority.SRPT || priority == Priority.LRPT) {
132
+            Iterator<Task> iter = this.tachesRestantes.iterator();
133
+            int index = 0;
134
+            boolean trouve = false;
135
+            while (iter.hasNext() && !trouve) {
136
+                Task current = iter.next();
137
+                if (this.prioritaire(instance, task, current)) {
138
+                    trouve = true;
139
+                } else {
140
+                    index++;
141
+                }
93 142
             }
143
+            this.tachesRestantes.add(index, task);
144
+        } else {
145
+            this.tachesRestantes.add(task);
94 146
         }
95
-        this.tachesRestantes.add(index, task);
96 147
     }
97 148
 
98
-    private Task getTask() {
99
-        return this.tachesRestantes.remove(0);
149
+    private Task getTask(Instance instance) {
150
+        if (priority == Priority.SPT || priority == Priority.LPT || priority == Priority.SRPT || priority == Priority.LRPT) {
151
+            return this.tachesRestantes.remove(0);
152
+        } else {
153
+            int indexBest = 0;
154
+            int indexChallenger;
155
+            for (indexChallenger = 1; indexChallenger < tachesRestantes.size(); indexChallenger++) {
156
+                if (prioritaire(instance, tachesRestantes.get(indexChallenger), tachesRestantes.get(indexBest))) {
157
+                    indexBest = indexChallenger;
158
+                }
159
+            }
160
+            return  this.tachesRestantes.remove(indexBest);
161
+        }
100 162
     }
101 163
 
102 164
     @Override
103 165
     public Result solve(Instance instance, long deadline) {
104 166
         //Initialisation
167
+        jobFreeDate = new int[instance.numJobs];
168
+        machineFreeDate = new int[instance.numMachines];
105 169
         int i;
106 170
         for (i=0; i<instance.numJobs; i++) {
107
-            try {
108
-                this.addTask(instance, new Task(i,0));
109
-            } catch (Exception e) {
110
-                System.out.println("ERREUR POLITIQUE DE PRIORITE INCONNUE");
111
-                System.exit(2);
112
-            }
171
+            this.addTask(instance, new Task(i,0));
172
+            this.jobFreeDate[i] = 0;
173
+        }
174
+        for (i=0; i<instance.numMachines; i++) {
175
+            this.machineFreeDate[i] = 0;
113 176
         }
114 177
         ResourceOrder resourceOrder = new ResourceOrder(instance);
115 178
         Task task;
@@ -117,16 +180,14 @@ public class GreedySolver implements Solver {
117 180
 
118 181
         //Itérations
119 182
         while (!this.tachesRestantes.isEmpty()) {
120
-            task = this.getTask();
183
+            task = this.getTask(instance);
184
+            int startTime = getEarliestDate(instance, task);
121 185
             resourceOrder.addTaskToMachine(instance.machine(task), task);
186
+            this.machineFreeDate[instance.machine(task)] = startTime + instance.duration(task);
187
+            this.jobFreeDate[task.job] = startTime + instance.duration(task);
122 188
             nextTask = instance.nextTask(task);
123 189
             if (nextTask != null) {
124
-                try {
125
-                    this.addTask(instance, new Task(task.job, task.task + 1));
126
-                } catch (Exception e) {
127
-                    System.out.println("ERREUR POLITIQUE DE PRIORITE INCONNUE");
128
-                    System.exit(2);
129
-                }
190
+                this.addTask(instance, new Task(task.job, task.task + 1));
130 191
             }
131 192
         }
132 193
         return new Result (instance, resourceOrder.toSchedule(), ProvedOptimal);

+ 10
- 0
src/main/java/jobshop/solvers/Solver.java View File

@@ -2,6 +2,8 @@ package jobshop.solvers;
2 2
 
3 3
 import jobshop.Instance;
4 4
 import jobshop.Result;
5
+import jobshop.encodings.ResourceOrder;
6
+import jobshop.solvers.neighborhood.Nowicki;
5 7
 
6 8
 /** Common interface that must implemented by all solvers. */
7 9
 public interface Solver {
@@ -28,6 +30,14 @@ public interface Solver {
28 30
             case "est_lpt": return new GreedySolver(GreedySolver.Priority.EST_LPT);
29 31
             case "est_srpt": return new GreedySolver(GreedySolver.Priority.EST_SRPT);
30 32
             case "est_lrpt": return new GreedySolver(GreedySolver.Priority.EST_LRPT);
33
+            case "descent_spt": return new DescentSolver(new Nowicki(), new GreedySolver(GreedySolver.Priority.SPT));
34
+            case "descent_lpt": return new DescentSolver(new Nowicki(), new GreedySolver(GreedySolver.Priority.LPT));
35
+            case "descent_srpt": return new DescentSolver(new Nowicki(), new GreedySolver(GreedySolver.Priority.SRPT));
36
+            case "descent_lrpt": return new DescentSolver(new Nowicki(), new GreedySolver(GreedySolver.Priority.LRPT));
37
+            case "descent_est_spt": return new DescentSolver(new Nowicki(), new GreedySolver(GreedySolver.Priority.EST_SPT));
38
+            case "descent_est_lpt": return new DescentSolver(new Nowicki(), new GreedySolver(GreedySolver.Priority.EST_LPT));
39
+            case "descent_est_srpt": return new DescentSolver(new Nowicki(), new GreedySolver(GreedySolver.Priority.EST_SRPT));
40
+            case "descent_est_lrpt": return new DescentSolver(new Nowicki(), new GreedySolver(GreedySolver.Priority.EST_LRPT));
31 41
             // TODO: add new solvers
32 42
             default: throw new RuntimeException("Unknown solver: "+ name);
33 43
         }

+ 45
- 6
src/main/java/jobshop/solvers/neighborhood/Nowicki.java View File

@@ -1,8 +1,10 @@
1 1
 package jobshop.solvers.neighborhood;
2 2
 
3 3
 import jobshop.encodings.ResourceOrder;
4
+import jobshop.encodings.Task;
4 5
 
5 6
 import java.util.ArrayList;
7
+import java.util.Iterator;
6 8
 import java.util.List;
7 9
 
8 10
 /** Implementation of the Nowicki and Smutnicki neighborhood.
@@ -78,13 +80,13 @@ public class Nowicki extends Neighborhood<ResourceOrder> {
78 80
         /** Apply this swap on the given ResourceOrder, transforming it into a new solution. */
79 81
         @Override
80 82
         public void applyOn(ResourceOrder current) {
81
-            throw new UnsupportedOperationException();
83
+            current.swapTasks(machine, t1, t2);
82 84
         }
83 85
 
84 86
         /** Unapply this swap on the neighbor, transforming it back into the original solution. */
85 87
         @Override
86 88
         public void undoApplyOn(ResourceOrder current) {
87
-            throw new UnsupportedOperationException();
89
+            current.swapTasks(machine, t1, t2);
88 90
         }
89 91
     }
90 92
 
@@ -109,13 +111,50 @@ public class Nowicki extends Neighborhood<ResourceOrder> {
109 111
 
110 112
     /** Returns a list of all the blocks of the critical path. */
111 113
     List<Block> blocksOfCriticalPath(ResourceOrder order) {
112
-        throw new UnsupportedOperationException();
114
+        ArrayList<Block> results = new ArrayList<>();
115
+
116
+        List<Task> criticalPath = order.toSchedule().get().criticalPath();
117
+        int currentMachine = -1;
118
+        int currentFirstIndex = -1;
119
+        int currentLastIndex = -1;
120
+
121
+        Iterator<Task> iter = criticalPath.iterator();
122
+        Task currentTask;
123
+        if (iter.hasNext()) {
124
+            currentTask = iter.next();
125
+            currentMachine = order.instance.machine(currentTask);
126
+            currentFirstIndex = order.getIndexOfTaskOnMachine(currentMachine, currentTask);
127
+            currentLastIndex = currentFirstIndex;
128
+        }
129
+        while (iter.hasNext()) {
130
+            currentTask = iter.next();
131
+            if (currentMachine == order.instance.machine(currentTask)) {
132
+                currentLastIndex = order.getIndexOfTaskOnMachine(currentMachine, currentTask);
133
+            } else {
134
+                if (currentLastIndex > currentFirstIndex) {
135
+                    results.add(new Block(currentMachine, currentFirstIndex, currentLastIndex));
136
+                }
137
+                currentMachine = order.instance.machine(currentTask);
138
+                currentFirstIndex = order.getIndexOfTaskOnMachine(currentMachine, currentTask);
139
+                currentLastIndex = currentFirstIndex;
140
+            }
141
+        }
142
+        if (currentLastIndex > currentFirstIndex) {
143
+            results.add(new Block(currentMachine, currentFirstIndex, currentLastIndex));
144
+        }
145
+
146
+        return results;
113 147
     }
114 148
 
115 149
     /** For a given block, return the possible swaps for the Nowicki and Smutnicki neighborhood */
116 150
     List<Swap> neighbors(Block block) {
117
-        throw new UnsupportedOperationException();
118
-
151
+        ArrayList<Swap> swaps = new ArrayList<>();
152
+        if (block.lastTask - block.firstTask == 1) {
153
+            swaps.add(new Swap(block.machine, block.firstTask, block.lastTask));
154
+        } else {
155
+            swaps.add(new Swap(block.machine, block.firstTask, block.firstTask + 1));
156
+            swaps.add(new Swap(block.machine, block.lastTask - 1, block.lastTask));
157
+        }
158
+        return swaps;
119 159
     }
120
-
121 160
 }

+ 117
- 0
src/test/java/jobshop/solvers/GreedySolverTest.java View File

@@ -116,4 +116,121 @@ public class GreedySolverTest {
116 116
             }
117 117
         }
118 118
     }
119
+
120
+    @Test
121
+    public void testEST_SPT() {
122
+        List<String> instancesNames = BestKnownResults.instancesMatching("la");
123
+        instancesNames.addAll(BestKnownResults.instancesMatching("ft"));
124
+
125
+        List<Instance> instances = instancesNames.stream().map(name -> {
126
+            Instance instance = null;
127
+            try {
128
+                instance = Instance.fromFile(Paths.get("instances/", name));
129
+            } catch (IOException e) {
130
+                e.printStackTrace();
131
+            }
132
+            return instance;
133
+        }).collect(Collectors.toList());
134
+
135
+        GreedySolver solver = new GreedySolver(EST_SPT);
136
+        Result result;
137
+        for (int i = 0; i < instances.size(); i++) {
138
+            result = solver.solve(instances.get(i), 100000);
139
+            assert result.schedule.get().isValid();
140
+            if (BestKnownResults.isKnown(instancesNames.get(i))) {
141
+                assert result.schedule.get().makespan() >= BestKnownResults.of(instancesNames.get(i));
142
+            }
143
+        }
144
+    }
145
+
146
+    @Test
147
+    public void testEST_LPT() throws IOException {
148
+        List<String> instancesNames = BestKnownResults.instancesMatching("la");
149
+        instancesNames.addAll(BestKnownResults.instancesMatching("ft"));
150
+
151
+        List<Instance> instances = instancesNames.stream().map(name -> {
152
+            Instance instance = null;
153
+            try {
154
+                instance = Instance.fromFile(Paths.get("instances/", name));
155
+            } catch (IOException e) {
156
+                e.printStackTrace();
157
+            }
158
+            return instance;
159
+        }).collect(Collectors.toList());
160
+
161
+        GreedySolver solver = new GreedySolver(EST_LPT);
162
+        Result result;
163
+        for (int i = 0; i < instances.size(); i++) {
164
+            result = solver.solve(instances.get(i), 100000);
165
+            assert result.schedule.get().isValid();
166
+            if (BestKnownResults.isKnown(instancesNames.get(i))) {
167
+                assert result.schedule.get().makespan() >= BestKnownResults.of(instancesNames.get(i));
168
+            }
169
+        }
170
+    }
171
+
172
+    @Test
173
+    public void testEST_SRPT() throws IOException {
174
+        List<String> instancesNames = BestKnownResults.instancesMatching("la");
175
+        instancesNames.addAll(BestKnownResults.instancesMatching("ft"));
176
+
177
+        List<Instance> instances = instancesNames.stream().map(name -> {
178
+            Instance instance = null;
179
+            try {
180
+                instance = Instance.fromFile(Paths.get("instances/", name));
181
+            } catch (IOException e) {
182
+                e.printStackTrace();
183
+            }
184
+            return instance;
185
+        }).collect(Collectors.toList());
186
+
187
+        GreedySolver solver = new GreedySolver(EST_SRPT);
188
+        Result result;
189
+        for (int i = 0; i < instances.size(); i++) {
190
+            result = solver.solve(instances.get(i), 100000);
191
+            assert result.schedule.get().isValid();
192
+            if (BestKnownResults.isKnown(instancesNames.get(i))) {
193
+                assert result.schedule.get().makespan() >= BestKnownResults.of(instancesNames.get(i));
194
+            }
195
+        }
196
+    }
197
+
198
+    @Test
199
+    public void testEST_LRPT() throws IOException {
200
+        List<String> instancesNames = BestKnownResults.instancesMatching("la");
201
+        instancesNames.addAll(BestKnownResults.instancesMatching("ft"));
202
+
203
+        List<Instance> instances = instancesNames.stream().map(name -> {
204
+            Instance instance = null;
205
+            try {
206
+                instance = Instance.fromFile(Paths.get("instances/", name));
207
+            } catch (IOException e) {
208
+                e.printStackTrace();
209
+            }
210
+            return instance;
211
+        }).collect(Collectors.toList());
212
+
213
+        GreedySolver solver = new GreedySolver(EST_LRPT);
214
+        Result result;
215
+        for (int i = 0; i < instances.size(); i++) {
216
+            result = solver.solve(instances.get(i), 100000);
217
+            assert result.schedule.get().isValid();
218
+            if (BestKnownResults.isKnown(instancesNames.get(i))) {
219
+                assert result.schedule.get().makespan() >= BestKnownResults.of(instancesNames.get(i));
220
+            }
221
+        }
222
+    }
223
+
224
+    @Test
225
+    public void testSusucre() throws IOException {
226
+
227
+        Instance instance = Instance.fromFile(Paths.get("instances/aaa3"));
228
+
229
+        GreedySolver solver = new GreedySolver(EST_LRPT);
230
+        Result result = solver.solve(instance, 100000);
231
+        System.out.println("SCHEDULE EST_LRPT: " + result.schedule.get().toString());
232
+        solver = new GreedySolver(EST_SPT);
233
+        result = solver.solve(instance, 100000);
234
+        System.out.println("SCHEDULE EST_SPT: " + result.schedule.get().toString());
235
+    }
119 236
 }

Loading…
Cancel
Save