Descent Solver: (blocksOfCriticalPath + neighbors + applyOn) completed
This commit is contained in:
förälder
6f78309d10
incheckning
f306a8c7f6
3 ändrade filer med 221 tillägg och 1 borttagningar
5
instances/aaa2
Normal file
5
instances/aaa2
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Example instance
|
||||
3 3 # num-jobs num-tasks
|
||||
2 3 0 3 1 2
|
||||
1 7 0 6 2 5
|
||||
0 2 1 10 2 4
|
|
@ -3,12 +3,15 @@ package jobshop;
|
|||
import jobshop.encodings.JobNumbers;
|
||||
import jobshop.encodings.ResourceOrder;
|
||||
import jobshop.encodings.Task;
|
||||
import jobshop.solvers.DescentSolver;
|
||||
import jobshop.solvers.GreedySolver;
|
||||
import jobshop.solvers.DescentSolver.Block;
|
||||
import jobshop.solvers.GreedySolver.PriorityESTRule;
|
||||
import jobshop.solvers.GreedySolver.PriorityRule;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
|
||||
public class DebuggingMain {
|
||||
|
||||
|
@ -49,6 +52,26 @@ public class DebuggingMain {
|
|||
|
||||
System.out.println("RESOURCE ORDER ENCODING:\n" + ro + "\n");
|
||||
|
||||
System.out.println("---------------------------------------------\n");
|
||||
|
||||
// load the aaa2 instance
|
||||
Instance instance2 = Instance.fromFile(Paths.get("instances/aaa2"));
|
||||
|
||||
ResourceOrder ro2 = new ResourceOrder(instance2);
|
||||
ro2.tasksByMachine[0][0] = new Task(2,0); //O7: Job 2, Task 0 (Machine 0)
|
||||
ro2.tasksByMachine[0][1] = new Task(1,1); //O5: Job 1, Task 1 (Machine 0)
|
||||
ro2.tasksByMachine[0][2] = new Task(0,1); //O2: Job 0, Task 1 (Machine 0)
|
||||
ro2.tasksByMachine[1][0] = new Task(1,0); //O4: Job 1, Task 0 (Machine 1)
|
||||
ro2.tasksByMachine[1][1] = new Task(2,1); //O8: Job 2, Task 1 (Machine 1)
|
||||
ro2.tasksByMachine[1][2] = new Task(0,2); //O3: Job 0, Task 2 (Machine 1)
|
||||
ro2.tasksByMachine[2][0] = new Task(2,2); //O9: Job 2, Task 2 (Machine 2)
|
||||
ro2.tasksByMachine[2][1] = new Task(0,0); //O1: Job 0, Task 0 (Machine 2)
|
||||
ro2.tasksByMachine[2][2] = new Task(1,2); //O6: Job 1, Task 2 (Machine 2)
|
||||
|
||||
System.out.println("RESOURCE ORDER ENCODING:\n" + ro2 + "\n");
|
||||
|
||||
System.out.println("---------------------------------------------\n");
|
||||
|
||||
System.out.println("Default Solver\n");
|
||||
sched = ro.toSchedule();
|
||||
|
||||
|
@ -95,7 +118,8 @@ public class DebuggingMain {
|
|||
System.out.println("MAKESPAN: " + sched.makespan());
|
||||
|
||||
System.out.println("---------------------------------------------\n");
|
||||
System.out.println("Greedy Solver: EST_SPT\n");
|
||||
System.out.println("Greedy Solver: ic void applyOn(ResourceOrder order) {\r\n" +
|
||||
" throw new UnsupportedOperationException();EST_SPT\n");
|
||||
PriorityESTRule EST_LRPT = PriorityESTRule.EST_LRPT;
|
||||
Solver solverEST_LRPT = new GreedySolver(EST_SPT);
|
||||
Result resultEST_LRPT = solverEST_LRPT.solve(instance, System.currentTimeMillis() + 10);
|
||||
|
@ -105,6 +129,21 @@ public class DebuggingMain {
|
|||
System.out.println("VALID: " + sched.isValid());
|
||||
System.out.println("MAKESPAN: " + sched.makespan());
|
||||
|
||||
System.out.println("---------------------------------------------\n");
|
||||
System.out.println("Descent Solver: \n");
|
||||
DescentSolver solverDescent = new DescentSolver();
|
||||
List<Block> criticalBlockList = solverDescent.blocksOfCriticalPath(ro2);
|
||||
for(Block b : criticalBlockList) {
|
||||
System.out.println(b);
|
||||
//System.out.println(solverDescent.neighbors(b));
|
||||
}
|
||||
/*
|
||||
sched = ro2.toSchedule();
|
||||
|
||||
System.out.println("SCHEDULE:\n" + sched);
|
||||
System.out.println("VALID: " + sched.isValid());
|
||||
System.out.println("MAKESPAN: " + sched.makespan());*/
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
|
|
176
src/main/java/jobshop/solvers/DescentSolver.java
Normal file
176
src/main/java/jobshop/solvers/DescentSolver.java
Normal file
|
@ -0,0 +1,176 @@
|
|||
package jobshop.solvers;
|
||||
|
||||
import jobshop.Instance;
|
||||
import jobshop.Result;
|
||||
import jobshop.Schedule;
|
||||
import jobshop.Solver;
|
||||
import jobshop.encodings.ResourceOrder;
|
||||
import jobshop.encodings.Task;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DescentSolver implements Solver {
|
||||
|
||||
/** A block represents a subsequence of the critical path such that all tasks in it execute on the same machine.
|
||||
* This class identifies a block in a ResourceOrder representation.
|
||||
*
|
||||
* Consider the solution in ResourceOrder representation
|
||||
* machine 0 : (0,1) (1,2) (2,2)
|
||||
* machine 1 : (0,2) (2,1) (1,1)
|
||||
* machine 2 : ...
|
||||
*
|
||||
* The block with : machine = 1, firstTask= 0 and lastTask = 1
|
||||
* Represent the task sequence : [(0,2) (2,1)]
|
||||
*
|
||||
* */
|
||||
public static class Block {
|
||||
/** machine on which the block is identified */
|
||||
final int machine;
|
||||
/** index of the first task of the block */
|
||||
final int firstTask;
|
||||
/** index of the last task of the block */
|
||||
final int lastTask;
|
||||
|
||||
Block(int machine, int firstTask, int lastTask) {
|
||||
this.machine = machine;
|
||||
this.firstTask = firstTask;
|
||||
this.lastTask = lastTask;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Block: {M" + this.machine + " | firstTask = " + this.firstTask + " | lastTask = " + this.lastTask + "}";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a swap of two tasks on the same machine in a ResourceOrder encoding.
|
||||
*
|
||||
* Consider the solution in ResourceOrder representation
|
||||
* machine 0 : (0,1) (1,2) (2,2)
|
||||
* machine 1 : (0,2) (2,1) (1,1)
|
||||
* machine 2 : ...
|
||||
*
|
||||
* The swam with : machine = 1, t1= 0 and t2 = 1
|
||||
* Represent inversion of the two tasks : (0,2) and (2,1)
|
||||
* Applying this swap on the above resource order should result in the following one :
|
||||
* machine 0 : (0,1) (1,2) (2,2)
|
||||
* machine 1 : (2,1) (0,2) (1,1)
|
||||
* machine 2 : ...
|
||||
*/
|
||||
public static class Swap {
|
||||
// machine on which to perform the swap
|
||||
final int machine;
|
||||
// index of one task to be swapped
|
||||
final int t1;
|
||||
// index of the other task to be swapped
|
||||
final int t2;
|
||||
|
||||
Swap(int machine, int t1, int t2) {
|
||||
this.machine = machine;
|
||||
this.t1 = t1;
|
||||
this.t2 = t2;
|
||||
}
|
||||
|
||||
/** Apply this swap on the given resource order, transforming it into a new solution. */
|
||||
public void applyOn(ResourceOrder order) {
|
||||
// Retrieve the tasks to be swap
|
||||
Task task1 = order.tasksByMachine[this.machine][this.t1];
|
||||
Task task2 = order.tasksByMachine[this.machine][this.t2];
|
||||
// Make the swap
|
||||
order.tasksByMachine[this.machine][this.t1] = task2;
|
||||
order.tasksByMachine[this.machine][this.t2] = task1;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Swap: {M" + this.machine + " | t1 = " + this.t1 + " | t2 = " + this.t2 + "}";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Result solve(Instance instance, long deadline) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/** Returns a list of all blocks of the critical path. */
|
||||
public List<Block> blocksOfCriticalPath(ResourceOrder order) {
|
||||
List<Block> criticalBlockList = new ArrayList<>();
|
||||
List<Integer> checkedMachines = new ArrayList<>();
|
||||
|
||||
// Obtain the critical task list from the resource order instance
|
||||
Schedule criticalSchedule = order.toSchedule();
|
||||
List<Task> criticalTaskList = criticalSchedule.criticalPath();
|
||||
|
||||
Block currentBlock;
|
||||
int currentMachine, m;
|
||||
int firstTask = 0, lastTask = 0;
|
||||
Task currentTask;
|
||||
|
||||
System.out.print("Number of Jobs : " + order.instance.numJobs + "\n");
|
||||
System.out.print("Number of Tasks : " + order.instance.numTasks + "\n");
|
||||
System.out.print("Number of Machines : " + order.instance.numMachines + "\n");
|
||||
System.out.print("Critical path : " + criticalTaskList + "\n");
|
||||
|
||||
// Initialize the block list
|
||||
for(int i = 0; i < order.instance.numMachines; i++) {
|
||||
currentBlock = new Block(i, -1, -1);
|
||||
criticalBlockList.add(i, currentBlock);
|
||||
}
|
||||
|
||||
for(int i = 0; i < criticalTaskList.size(); i++) {
|
||||
currentTask = criticalTaskList.get(i);
|
||||
currentMachine = order.instance.machine(currentTask.job, currentTask.task);
|
||||
|
||||
// When we find a machine we have not explored, we start searching for all its appearances in the critical path
|
||||
// and we safe the first and last occurrence of the machine.
|
||||
if(!checkedMachines.contains(currentMachine)) {
|
||||
firstTask = 0;
|
||||
lastTask = 0;
|
||||
for(int index = i; index < criticalTaskList.size(); index++) {
|
||||
m = order.instance.machine(criticalTaskList.get(index).job, criticalTaskList.get(index).task);
|
||||
// If we find a task running in the same machine and it is not the first task, add 1 to the last task
|
||||
if(currentMachine == m && index > i){
|
||||
lastTask++;
|
||||
}
|
||||
}
|
||||
// Add the machine to the checked machines list
|
||||
checkedMachines.add(currentMachine);
|
||||
// Create and add the new block to the list
|
||||
currentBlock = new Block(currentMachine, firstTask, lastTask);
|
||||
criticalBlockList.set(currentMachine, currentBlock);
|
||||
}
|
||||
}
|
||||
return criticalBlockList;
|
||||
}
|
||||
|
||||
|
||||
/** For a given block, return the possible swaps for the Nowicki and Smutnicki neighborhood */
|
||||
public List<Swap> neighbors(Block block) {
|
||||
List<Swap> swapList = new ArrayList<>();
|
||||
Swap currentSwap;
|
||||
|
||||
int machine = block.machine;
|
||||
int firstTask = block.firstTask;
|
||||
int lastTask = block.lastTask;
|
||||
|
||||
// Case when there is just one element in the block
|
||||
if(firstTask == lastTask) {
|
||||
swapList = null;
|
||||
}
|
||||
|
||||
for(int i = firstTask; i < lastTask; i++) {
|
||||
if(i == firstTask + 1) {
|
||||
currentSwap = new Swap(machine, firstTask, i);
|
||||
swapList.add(currentSwap);
|
||||
}
|
||||
if (i == lastTask - 1) {
|
||||
currentSwap = new Swap(machine, i, lastTask);
|
||||
swapList.add(currentSwap);
|
||||
}
|
||||
}
|
||||
return swapList;
|
||||
}
|
||||
|
||||
}
|
Laddar…
Referens i nytt ärende