Descent Solver: (blocksOfCriticalPath + neighbors + applyOn) completed

This commit is contained in:
AlexJavor 2020-05-02 22:15:43 +02:00
förälder 6f78309d10
incheckning f306a8c7f6
3 ändrade filer med 221 tillägg och 1 borttagningar

5
instances/aaa2 Normal file
Visa fil

@ -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

Visa fil

@ -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);

Visa fil

@ -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;
}
}