├── .gitignore ├── plot ├── 16t6m.png └── 17t5m.png ├── poster └── Poster.pptx ├── testpoints ├── 15t4m.test ├── 16t6m.test ├── 17t5m.test ├── 20t4m.test ├── Makefile └── jssp_bf.c ├── initSolution.m ├── findStartTemp.m ├── cost_test.m ├── cost.m ├── gen_neighbor.m ├── gen_neighbor_test.m ├── GA_16t6m_test.m ├── GA_17t5m_test.m ├── GA_test.m ├── PSO_16t6m_test.m ├── PSO_17t5m_test.m ├── TS_16t6m_test.m ├── TS_17t5m_test.m ├── ACO_16t6m_test.m ├── ACO_17t5m_test.m ├── PSO_test.m ├── TS_test.m ├── ACO_test.m ├── SA_16t6m_test.m ├── SA_17t5m_test.m ├── SA_test.m ├── ALL_test_16t6m.m ├── ALL_test_17t5m.m ├── TS_readme.txt ├── TS.m ├── getBestNeighbor.m ├── PSO.m ├── SA.m ├── PSO_lbest.m ├── ACO.m ├── GA.m ├── README.org └── README.html /.gitignore: -------------------------------------------------------------------------------- 1 | *.asv 2 | .DS_Store 3 | octave-workspace 4 | -------------------------------------------------------------------------------- /plot/16t6m.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oahziur/animated-archer/HEAD/plot/16t6m.png -------------------------------------------------------------------------------- /plot/17t5m.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oahziur/animated-archer/HEAD/plot/17t5m.png -------------------------------------------------------------------------------- /poster/Poster.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oahziur/animated-archer/HEAD/poster/Poster.pptx -------------------------------------------------------------------------------- /testpoints/15t4m.test: -------------------------------------------------------------------------------- 1 | 91,36,65,82,51,6,12,96,26,96,54,4,54,47,6 2 | 182 3 | 0, 0, 1, 2, 1, 0, 1, 2, 3, 3, 1, 2, 3, 0, 3 4 | -------------------------------------------------------------------------------- /testpoints/16t6m.test: -------------------------------------------------------------------------------- 1 | 58,72,79,43,16,37,7,74,97,44,39,80,65,65,39,96 2 | 154 3 | 0, 1, 1, 2, 3, 2, 2, 4, 3, 5, 3, 4, 2, 5, 5, 0 4 | -------------------------------------------------------------------------------- /initSolution.m: -------------------------------------------------------------------------------- 1 | function [S] = initSolution(m, n) 2 | S = []; 3 | for i = 1:n 4 | S(i) = mod(i, m) + 1; 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /testpoints/17t5m.test: -------------------------------------------------------------------------------- 1 | 50,22,13,64,43,70,53,55,95,83,54,56,60,77,28,24,25 2 | 175 3 | 0, 0, 1, 2, 0, 3, 1, 1, 4, 2, 1, 3, 0, 4, 2, 3, 3 4 | -------------------------------------------------------------------------------- /testpoints/20t4m.test: -------------------------------------------------------------------------------- 1 | 32,96,4,32,97,29,35,97,6,74,77,78,33,4,92,69,64,51,58,91 2 | 280 3 | 0, 0, 0, 0, 1, 0, 0, 2, 3, 3, 1, 3, 1, 1, 2, 1, 3, 0, 3, 2 4 | -------------------------------------------------------------------------------- /testpoints/Makefile: -------------------------------------------------------------------------------- 1 | CC=clang 2 | CFLAGS= -Wall -O3 3 | 4 | jssp_bf: jssp_bf.o 5 | ${CC} ${CFLAGS} -o jssp_bf jssp_bf.o 6 | 7 | %.o:%.c 8 | ${CC} ${CFLAGS} -c $< 9 | 10 | clean: 11 | rm -f *.o *.a jssp_bf 12 | -------------------------------------------------------------------------------- /findStartTemp.m: -------------------------------------------------------------------------------- 1 | function [sT] = findStartTemp(jobs, m) 2 | sT = 0; 3 | maxChange = max(jobs); 4 | avgExeTime = sum(jobs) / m; 5 | if (avgExeTime > maxChange) 6 | maxChange = avgExeTime; 7 | end 8 | sT = -1* maxChange / log(0.85); 9 | end 10 | -------------------------------------------------------------------------------- /cost_test.m: -------------------------------------------------------------------------------- 1 | function [] = cost_test() 2 | S = [1, 2, 2, 3, 1, 1]; 3 | J = [2, 3, 4, 6, 2, 2]; 4 | result = cost(S, J, 3, 6); 5 | if result == 7 6 | disp("cost function test PASSED!"); 7 | else 8 | disp("cost function test FAILED!"); 9 | end 10 | -------------------------------------------------------------------------------- /cost.m: -------------------------------------------------------------------------------- 1 | function [result] = cost(schedule, jobs, m, n) 2 | results = zeros(1, m); 3 | if n == 0 4 | result = 0; 5 | else 6 | for i = 1:n 7 | results(schedule(i)) = results(schedule(i)) + jobs(i); 8 | end 9 | result = max(results); 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /gen_neighbor.m: -------------------------------------------------------------------------------- 1 | function [neighbor] = gen_neighbor(schedule, m, n) 2 | neighbor = schedule; 3 | job_to_mutate = randi([1, n], 1); 4 | new_machine = randi([1, m], 1); 5 | while new_machine == schedule(job_to_mutate) 6 | new_machine = randi([1, m], 1); 7 | end 8 | neighbor(job_to_mutate) = new_machine; 9 | end 10 | -------------------------------------------------------------------------------- /gen_neighbor_test.m: -------------------------------------------------------------------------------- 1 | function [] = gen_neighbor_test() 2 | S = [1, 1, 2, 2, 3, 3]; 3 | N = gen_neighbor(S, 3, 6); 4 | diff = 0; 5 | for i = 1:6 6 | if S(i) != N(i) 7 | diff = diff + 1; 8 | end 9 | end 10 | if diff == 1 11 | disp("gen_neighbor function PASSED!"); 12 | else 13 | disp("gen_neighbor function FAILED!"); 14 | end 15 | -------------------------------------------------------------------------------- /GA_16t6m_test.m: -------------------------------------------------------------------------------- 1 | function [costs] = GA_16t6m_test(iterations) 2 | m = 6; 3 | n = 16; 4 | J = [58,72,79,43,16,37,7,74,97,44,39,80,65,65,39,96]; 5 | [costs, bestSol] = GA(J, m, iterations); 6 | bestSolCost = cost(bestSol, J, 6, 16); 7 | if bestSolCost == 154 8 | disp('16t6m global best found!'); 9 | else 10 | disp('16t6m local best found!'); 11 | disp(bestSolCost); 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /GA_17t5m_test.m: -------------------------------------------------------------------------------- 1 | function [costs] = GA_17t5m_test(iterations) 2 | m = 5; 3 | n = 17; 4 | J = [50,22,13,64,43,70,53,55,95,83,54,56,60,77,28,24,25]; 5 | [costs, bestSol] = GA(J, m, iterations); 6 | bestSolCost = cost(bestSol, J, 6, 16); 7 | if bestSolCost == 175 8 | disp('17t5m global best found!'); 9 | else 10 | disp('17t5m local best found!'); 11 | disp(bestSolCost); 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /GA_test.m: -------------------------------------------------------------------------------- 1 | function [] = GA_test() 2 | GA_small_test(150); 3 | GA_16t6m_test(500); 4 | GA_17t5m_test(500); 5 | end 6 | 7 | function [costs] = GA_small_test(iterations) 8 | m = 3; 9 | n = 6; 10 | J = [2, 3, 4, 6, 2, 2]; 11 | [costs, bestSol] = GA(J, m, iterations); 12 | if cost(bestSol, J, 3, 6) == 7 13 | disp('small global best found!'); 14 | else 15 | disp('small local best found!'); 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /PSO_16t6m_test.m: -------------------------------------------------------------------------------- 1 | function [costs] = PSO_16t6m_test(iterations) 2 | m = 6; 3 | n = 16; 4 | J = [58,72,79,43,16,37,7,74,97,44,39,80,65,65,39,96]; 5 | [costs, bestSol] = PSO_lbest(J, m, n, 500, iterations, @cost); 6 | bestSolCost = cost(bestSol, J, 6, 16); 7 | if bestSolCost == 154 8 | disp('16t6m global best found!'); 9 | else 10 | disp('16t6m local best found!'); 11 | disp(bestSolCost); 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /PSO_17t5m_test.m: -------------------------------------------------------------------------------- 1 | function [costs] = PSO_17t5m_test(iterations) 2 | m = 5; 3 | n = 17; 4 | J = [50,22,13,64,43,70,53,55,95,83,54,56,60,77,28,24,25]; 5 | [costs, bestSol] = PSO_lbest(J, m, n, 500, iterations, @cost); 6 | bestSolCost = cost(bestSol, J, 6, 16); 7 | if bestSolCost == 175 8 | disp('17t5m global best found!'); 9 | else 10 | disp('17t5m local best found!'); 11 | disp(bestSolCost); 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /TS_16t6m_test.m: -------------------------------------------------------------------------------- 1 | function [costs] = TS_16t6m_test(iterations) 2 | m = 6; 3 | n = 16; 4 | J = [58,72,79,43,16,37,7,74,97,44,39,80,65,65,39,96]; 5 | [costs, bestSol] = TS(J, m, n, 15, iterations, @cost, @getBestNeighbor); 6 | bestSolCost = cost(bestSol, J, m, n); 7 | if bestSolCost == 154 8 | disp('16t6m global best found!'); 9 | else 10 | disp('16t6m local best found!'); 11 | disp(bestSolCost); 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /TS_17t5m_test.m: -------------------------------------------------------------------------------- 1 | function [costs] = TS_17t5m_test(iterations) 2 | m = 5; 3 | n = 17; 4 | J = [50,22,13,64,43,70,53,55,95,83,54,56,60,77,28,24,25]; 5 | [costs, bestSol] = TS(J, m, n, 15, iterations, @cost, @getBestNeighbor); 6 | bestSolCost = cost(bestSol, J, 6, 16); 7 | if bestSolCost == 175 8 | disp('17t5m global best found!'); 9 | else 10 | disp('17t5m local best found!'); 11 | disp(bestSolCost); 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /ACO_16t6m_test.m: -------------------------------------------------------------------------------- 1 | function [costs] = ACO_16t6m_test(iterations) 2 | m = 6; 3 | n = 16; 4 | J = [58,72,79,43,16,37,7,74,97,44,39,80,65,65,39,96]; 5 | ants = 20; 6 | [costs, bestSol] = ACO(J, m, n, ants, iterations, 0.2, @cost); 7 | bestSolCost = cost(bestSol, J, m, n); 8 | if bestSolCost == 154 9 | disp('16t6m global best found!'); 10 | else 11 | disp('16t6m local best found!'); 12 | disp(bestSolCost); 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /ACO_17t5m_test.m: -------------------------------------------------------------------------------- 1 | function [costs] = ACO_17t5m_test(iterations) 2 | m = 5; 3 | n = 17; 4 | J = [50,22,13,64,43,70,53,55,95,83,54,56,60,77,28,24,25]; 5 | ants = 20; 6 | [costs, bestSol] = ACO(J, m, n, ants, iterations, 0.2, @cost); 7 | bestSolCost = cost(bestSol, J, 6, 16); 8 | if bestSolCost == 175 9 | disp('17t5m global best found!'); 10 | else 11 | disp('17t5m local best found!'); 12 | disp(bestSolCost); 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /PSO_test.m: -------------------------------------------------------------------------------- 1 | function [] = PSO_test() 2 | PSO_samll_test(150); 3 | PSO_16t6m_test(500); 4 | PSO_17t5m_test(500); 5 | end 6 | 7 | function [costs] = PSO_samll_test(iterations) 8 | m = 3; 9 | n = 6; 10 | J = [2, 3, 4, 6, 2, 2]; 11 | [costs, bestSol] = PSO_lbest(J, m, n, 1500, iterations, @cost); 12 | if cost(bestSol, J, 3, 6) == 7 13 | disp('small global best found!'); 14 | else 15 | disp('small local best found!'); 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /TS_test.m: -------------------------------------------------------------------------------- 1 | function [] = TS_test() 2 | TS_small_test(100); 3 | TS_16t6m_test(100); 4 | TS_17t5m_test(100); 5 | end 6 | 7 | function [costs] = TS_small_test(iterations) 8 | m = 3; 9 | n = 6; 10 | J = [2, 3, 4, 6, 2, 2]; 11 | [costs, bestSol] = TS(J, m, n, 10, iterations, @cost, @getBestNeighbor); 12 | if cost(bestSol, J, 3, 6) == 7 13 | disp('small global best found!'); 14 | else 15 | disp('small local best found!'); 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /ACO_test.m: -------------------------------------------------------------------------------- 1 | function [] = ACO_test() 2 | ACO_small_test(100); 3 | ACO_16t6m_test(100); 4 | ACO_17t5m_test(100); 5 | end 6 | 7 | function [costs] = ACO_small_test(iterations) 8 | m = 3; 9 | n = 6; 10 | J = [2, 3, 4, 6, 2, 2]; 11 | ants = 5; 12 | [costs, bestSol] = ACO(J, m, n, ants, iterations, 0.2, @cost); 13 | if cost(bestSol, J, 3, 6) == 7 14 | disp('small global best found!'); 15 | else 16 | disp('small local best found!'); 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /SA_16t6m_test.m: -------------------------------------------------------------------------------- 1 | function [costs] = SA_16t6m_test(iterations) 2 | m = 6; 3 | n = 16; 4 | S = initSolution(m,n); 5 | J = [58,72,79,43,16,37,7,74,97,44,39,80,65,65,39,96]; 6 | sT = findStartTemp(J, m); 7 | alpha = 0.85; 8 | iterationsAtTemp = 5; 9 | [costs, bestSol] = SA(S, J, m, n, iterationsAtTemp, sT, iterations, ... 10 | alpha, @cost, @gen_neighbor); 11 | bestSolCost = cost(bestSol, J, 6, 16); 12 | if bestSolCost == 154 13 | disp('16t6m global best found!'); 14 | else 15 | disp('16t6m local best found!'); 16 | disp(bestSolCost); 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /SA_17t5m_test.m: -------------------------------------------------------------------------------- 1 | function [costs] = SA_17t5m_test(iterations) 2 | m = 5; 3 | n = 17; 4 | S = initSolution(m,n); 5 | J = [50,22,13,64,43,70,53,55,95,83,54,56,60,77,28,24,25]; 6 | sT = findStartTemp(J, m); 7 | alpha = 0.85; 8 | iterationsAtTemp = 5; 9 | [costs, bestSol] = SA(S, J, m, n, iterationsAtTemp, sT, iterations, ... 10 | alpha, @cost, @gen_neighbor); 11 | bestSolCost = cost(bestSol, J, 6, 16); 12 | if bestSolCost == 175 13 | disp('17t5m global best found!'); 14 | else 15 | disp('17t5m local best found!'); 16 | disp(bestSolCost); 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /SA_test.m: -------------------------------------------------------------------------------- 1 | function [] = SA_test() 2 | SA_samll_test(100); 3 | SA_16t6m_test(10000); 4 | SA_17t5m_test(10000); 5 | end 6 | 7 | function [costs] = SA_samll_test(iterations) 8 | m = 3; 9 | n = 6; 10 | S = initSolution(m,n); 11 | J = [2, 3, 4, 6, 2, 2]; 12 | sT = findStartTemp(J, m); 13 | alpha = 0.85; 14 | iterationsAtTemp = 2; 15 | fT = sT*(alpha^(iterations/iterationsAtTemp)); 16 | [costs, bestSol] = SA(S, J, m, n, iterationsAtTemp, sT, fT, alpha, @cost, @gen_neighbor); 17 | if cost(bestSol, J, 3, 6) == 7 18 | disp('small global best found!'); 19 | else 20 | disp('small local best found!'); 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /ALL_test_16t6m.m: -------------------------------------------------------------------------------- 1 | function [] = ALL_test_16t6m() 2 | n = 1000; 3 | t(1) = cputime; 4 | GACost = GA_16t6m_test(n); 5 | t(2) = cputime; 6 | PSOCost = PSO_16t6m_test(n); 7 | t(3) = cputime; 8 | TSCost = TS_16t6m_test(n); 9 | t(4) = cputime; 10 | SACost = SA_16t6m_test(n); 11 | t(5) = cputime; 12 | ACOCost = ACO_16t6m_test(n); 13 | t(6) = cputime; 14 | diff(t) 15 | 16 | % SAVE COST TO DISK 17 | 18 | 19 | hold on; 20 | plot(GACost, 'b'); 21 | plot(PSOCost, 'k'); 22 | plot(SACost, 'c'); 23 | plot(ACOCost, 'r'); 24 | plot(TSCost, 'g'); 25 | legend(' GA ', ' PSO ', ' SA ', ' ACO ', ' TS '); 26 | title(' Iteration plot for 16 task on 6 machine '); 27 | hold off; 28 | end 29 | -------------------------------------------------------------------------------- /ALL_test_17t5m.m: -------------------------------------------------------------------------------- 1 | function [] = ALL_test_17t5m() 2 | n = 1000; 3 | t(1) = cputime; 4 | GACost = GA_17t5m_test(n); 5 | t(2) = cputime; 6 | PSOCost = PSO_17t5m_test(n); 7 | t(3) = cputime; 8 | TSCost = TS_17t5m_test(n); 9 | t(4) = cputime; 10 | SACost = SA_17t5m_test(n); 11 | t(5) = cputime; 12 | ACOCost = ACO_17t5m_test(n); 13 | t(6) = cputime; 14 | diff(t) 15 | 16 | % SAVE COST TO DISK 17 | 18 | 19 | hold on; 20 | plot(GACost, 'b'); 21 | plot(PSOCost, 'k'); 22 | plot(SACost, 'c'); 23 | plot(ACOCost, 'r'); 24 | plot(TSCost, 'g'); 25 | legend(' GA ', ' PSO ', ' SA ', ' ACO ', ' TS '); 26 | title(' Iteration plot for 17 task on 5 machine '); 27 | hold off; 28 | end 29 | -------------------------------------------------------------------------------- /TS_readme.txt: -------------------------------------------------------------------------------- 1 | *Initial Solution 2 | 3 | The initial solution is randomly generated. 4 | 5 | *Neighbors of each schedule 6 | 7 | Each schedule will have (m-1)*n neighbors, where m is the number of machines, and n is the number of jobs. Neighbors will only have one job scheduled on a different machine. 8 | 9 | *Finding the best neighbor 10 | 11 | In order the find the neighbor with the lowest cost, the algorithm will loop through every valid neighbor and evaluate its cost. The neighbor with the lowest cost will be selected as the best neighbor. 12 | 13 | *Tabulist 14 | 15 | The list length of the tabulist is user-defined. The tabulist acts like a queque (first in first out) in which the oldest move will be deleted when a new move is appended. A new move is appended every time after finding a best neighbor. 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /TS.m: -------------------------------------------------------------------------------- 1 | function [costs, bestSol] = TS(jobs, m, n, listLength, iterations, costFunc, getBestNeighbor) 2 | % This function implements the tabu search algorithm for Hybird Job Shop Sceduling 3 | 4 | costs = []; 5 | tabuList = zeros(listLength, 2); 6 | 7 | % Firstly, randomly generate an initial solution given m and n 8 | % Set the best solution to the initial solution 9 | bestSol = ones(1, n); 10 | for i = 1 : m 11 | bestSol(i) = randi([1,m],1); 12 | end 13 | bestSolCost = costFunc(bestSol, jobs, m, n); 14 | costs(1)=bestSolCost; 15 | 16 | sol = bestSol; 17 | for i = 2 : iterations 18 | % Get the best solution in the neighbourhood of the current solution 19 | % avoiding Tabu moves 20 | [sol, solCost, tabuList] = getBestNeighbor(sol, jobs, m, n, tabuList, ... 21 | bestSolCost, costFunc); 22 | %disp(tabuList); 23 | costs(i)=solCost; 24 | 25 | %Update the best solution 26 | if (solCost 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define TASK 20 9 | #define MACHINE 4 10 | 11 | int s[TASK]; 12 | int d[TASK] = {32,96,4,32,97,29,35,97,6,74,77,78,33,4,92,69,64,51,58,91}; 13 | int m[MACHINE]; 14 | int bests[TASK]; 15 | int best = INT_MAX; 16 | uint64_t trial = 0; 17 | 18 | int finds(int tid) 19 | { 20 | int i; 21 | if (tid == TASK) 22 | { 23 | int max = 0; 24 | for (i = 0; i < MACHINE; i++) 25 | { 26 | if (m[i] > max) 27 | max = m[i]; 28 | } 29 | if (max < best) 30 | { 31 | best = max; 32 | memcpy(bests, s, sizeof(s)); 33 | } 34 | if((trial++ % 100000000) == 0) 35 | printf("trial: %" PRIu64 "00M, best:%d\n", trial/100000000, best); 36 | return 0; 37 | } 38 | for (i = 0; i < MACHINE; i++) 39 | { 40 | m[i] += d[tid]; 41 | s[tid] = i; 42 | finds(tid + 1); 43 | m[i] -= d[tid]; 44 | } 45 | return 0; 46 | } 47 | 48 | int main(int argc, char * argv[]) 49 | { 50 | int i; 51 | for (i = 0; i < MACHINE; i++) 52 | { 53 | m[i] = 0; 54 | } 55 | finds(0); 56 | printf("best solution: %d \n", best); 57 | for (i = 0; i < TASK; i++) 58 | { 59 | printf("%d, ", bests[i]); 60 | } 61 | printf("\n"); 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /getBestNeighbor.m: -------------------------------------------------------------------------------- 1 | function [bestNeighbour, bestNeighbourCost, newTabuList] = ... 2 | getBestNeighbor(schedule, jobs, m, n, tabuList, knownBestCost, costFunc) 3 | total_move_number = (m-1)*n; 4 | all_valid_moves = zeros(total_move_number,3); 5 | neighbor = schedule; 6 | newTabuList = tabuList; 7 | row = 1; 8 | 9 | for i = 1 : n 10 | for j = 1 : m 11 | neighbor = schedule; 12 | if(j ~= schedule(i)) 13 | neighbor(i)=j; 14 | all_valid_moves(row,:) = [i,j,costFunc(neighbor, jobs, m, n)]; 15 | row = row+1; 16 | end 17 | end 18 | end 19 | all_valid_moves = sortrows(all_valid_moves,3); 20 | 21 | for i = 1 : total_move_number 22 | neighbor = schedule; 23 | job = all_valid_moves(i,1); 24 | machine = all_valid_moves(i,2); 25 | cost = all_valid_moves(i,3); 26 | neighbor(job)=machine; 27 | 28 | % if in tabu list 29 | if(ismember([job,machine],tabuList,'rows')) 30 | if(cost < knownBestCost) 31 | bestNeighbour = neighbor; 32 | bestNeighbourCost = cost; 33 | break; 34 | end 35 | % not in tabu list 36 | else 37 | bestNeighbour = neighbor; 38 | bestNeighbourCost = cost; 39 | break; 40 | end 41 | end 42 | 43 | %updating tabu list 44 | newTabuList(1,:)=[]; 45 | newTabuList(end+1,:)=[job,machine]; 46 | end 47 | -------------------------------------------------------------------------------- /PSO.m: -------------------------------------------------------------------------------- 1 | function [costs, bestSol] = PSO(jobs, m, n, particals, iterations, costFunc) 2 | c1 = 1.4944; 3 | c2 = 1.4944; 4 | w = 0.79; 5 | gbests = ones(1, n); 6 | gbest = costFunc(gbests, jobs, m, n); 7 | lbests = randi(m, particals, n); 8 | lbest = ones(1, particals); 9 | costs = ones(iterations, 1); 10 | costsEnd = 0; 11 | for i = 1:particals 12 | lbest(i) = costFunc(lbests(i, :), jobs, m, n); 13 | if lbest(i) < gbest 14 | gbest = lbest(i); 15 | gbests = lbests(i, :); 16 | end 17 | end 18 | x = lbests; 19 | v = zeros(particals, n); 20 | 21 | for i = 1:iterations 22 | ibest = costFunc(ones(particals, n), jobs, m, n); 23 | r1 = rand(particals, 1); 24 | r2 = rand(particals, 1); 25 | v = w*v + c1 * bsxfun(@times, r1, lbests - x) + ... 26 | c2 * bsxfun(@times, r2, (bsxfun(@minus, gbests, x))); 27 | x = round(x + v); 28 | %x = bsxfun(@mod, x, m) + 1; 29 | x(x < 1) = 1; 30 | x(x > m) = m; 31 | for j = 1:particals 32 | c = costFunc(x(j, :), jobs, m, n); 33 | if c < ibest 34 | ibest = c; 35 | end 36 | if c < lbest(j) 37 | lbest(j) = c; 38 | lbests(j, :) = x(j, :); 39 | end 40 | end 41 | costsEnd = costsEnd + 1; 42 | costs(costsEnd) = ibest; 43 | [ilbest, idx] = min(lbest); 44 | %ibest 45 | ilbests = lbests(idx, :); 46 | if ilbest < gbest 47 | gbest = ilbest; 48 | gbests = ilbests; 49 | end 50 | end 51 | bestSol = gbests; 52 | end -------------------------------------------------------------------------------- /SA.m: -------------------------------------------------------------------------------- 1 | % Simulated Annealing Algorithm for Hybrid Job Shop Scheduling 2 | % Problem. 3 | % 4 | % costs: history of cost for each iteration's schedule. 5 | % bestSol: best solution for the given sT and fT. 6 | % 7 | % iterations: number of iteration for each T. 8 | % sT: start T. 9 | % fT: final T. 10 | % alpha: alpha in geometric cooling schedule. 11 | 12 | function [costs, bestSol] = SA(schedule, jobs, m, n, iterations, sT, ... 13 | minTotalIteration, alpha, costFunc, ... 14 | genNeighborFunc) 15 | costsEnd = 0; 16 | costs = []; 17 | bestSol = schedule; 18 | bestSolCost = costFunc(schedule, jobs, m, n); 19 | acceptedSol = schedule; 20 | acceptedSolCost = costFunc(schedule, jobs, m, n); 21 | T = sT; 22 | counter = 0; 23 | while counter < minTotalIteration 24 | for i=1:iterations 25 | counter = counter + 1; 26 | newSol = genNeighborFunc(acceptedSol, m, n); 27 | newSolCost = costFunc(newSol, jobs, m, n); 28 | deltaCost = newSolCost - acceptedSolCost; 29 | if deltaCost < 0 30 | acceptedSol = newSol; 31 | acceptedSolCost = newSolCost; 32 | else 33 | randVal = rand(1); 34 | p = exp(-1*deltaCost / T); 35 | if p > randVal 36 | acceptedSol = newSol; 37 | acceptedSolCost = newSolCost; 38 | end 39 | end 40 | 41 | % record the cost value in to history 42 | costsEnd = costsEnd + 1; 43 | costs(costsEnd) = acceptedSolCost; 44 | 45 | % Update current best value 46 | if acceptedSolCost < bestSolCost 47 | bestSol = acceptedSol; 48 | bestSolCost = acceptedSolCost; 49 | end 50 | end 51 | T = T * alpha; % cooling 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /PSO_lbest.m: -------------------------------------------------------------------------------- 1 | function [costs, bestSol] = PSO_lbest(jobs, m, n, particals, iterations, costFunc) 2 | c1 = 1.4944; 3 | c2 = 1.4944; 4 | w = 0.9; 5 | gbests = ones(1, n); 6 | gbest = costFunc(gbests, jobs, m, n); 7 | lbests = randi(m, particals, n); 8 | lbest = ones(1, particals); 9 | nbests = lbests; 10 | nbest = lbest; 11 | nsize = 2; 12 | costs = ones(iterations, 1); 13 | costsEnd = 0; 14 | for i = 1:particals 15 | lbest(i) = costFunc(lbests(i, :), jobs, m, n); 16 | %if lbest(i) < gbest 17 | % gbest = lbest(i); 18 | % gbests = lbests(i, :); 19 | %end 20 | nbest(i) = lbest(i); 21 | end 22 | for i = 1:particals 23 | for k = (i-nsize-1):(i+nsize-1) 24 | if lbest(i) < nbest(mod(k, particals) + 1) 25 | nbest(mod(k, particals) + 1) = lbest(i); 26 | nbests(mod(k, particals) + 1, :) = lbests(i, :); 27 | end 28 | end 29 | end 30 | x = lbests; 31 | v = zeros(particals, n); 32 | 33 | for i = 1:iterations 34 | ibest = costFunc(ones(particals, n), jobs, m, n); 35 | r1 = rand(particals, 1); 36 | r2 = rand(particals, 1); 37 | %v = w*v + c1 * bsxfun(@times, r1, lbests - x) + ... 38 | % c2 * bsxfun(@times, r2, (bsxfun(@minus, gbests, x))); 39 | v = w*v + c1 * bsxfun(@times, r1, lbests - x) + ... 40 | c2 * bsxfun(@times, r2, nbests - x); 41 | x = round(x + v); 42 | %x = bsxfun(@mod, x-1, m) + 1; 43 | x(x < 1) = 1; 44 | x(x > m) = m; 45 | for j = 1:particals 46 | c = costFunc(x(j, :), jobs, m, n); 47 | if c < ibest 48 | ibest = c; 49 | end 50 | if c < lbest(j) 51 | lbest(j) = c; 52 | lbests(j, :) = x(j, :); 53 | for k = (j-nsize-1):(j+nsize-1) 54 | if lbest(j) < nbest(mod(k, particals) + 1) 55 | nbest(mod(k, particals) + 1) = lbest(j); 56 | nbests(mod(k, particals) + 1, :) = lbests(j, :); 57 | end 58 | end 59 | end 60 | end 61 | costsEnd = costsEnd + 1; 62 | costs(costsEnd) = ibest; 63 | [ilbest, idx] = min(lbest); 64 | %ibest 65 | ilbests = lbests(idx, :); 66 | if ilbest < gbest 67 | gbest = ilbest; 68 | gbests = ilbests; 69 | end 70 | end 71 | %v 72 | bestSol = gbests; 73 | end -------------------------------------------------------------------------------- /ACO.m: -------------------------------------------------------------------------------- 1 | % Ant Colony Opimization - Ant Colony System for Hybird Job Shop Sceduling 2 | % Problem. 3 | 4 | function [costs, bestSol] = ACO(jobs, m, n, ants, iterations, ... 5 | rzero, costFunc) 6 | 7 | costEnd = 0; 8 | costs = []; 9 | bestSol = ones(1, n); 10 | bestSolCost = costFunc(bestSol, jobs, m, n); 11 | 12 | phermone = ones(n, m*m); % track phermone value on each path. 13 | 14 | for i = 1:iterations 15 | 16 | antPaths = []; % stores all antPaths 17 | for a = 1:ants; 18 | 19 | antPath = []; % current ants path 20 | 21 | for l = 1:n % going down n layers in total 22 | 23 | phermoneToNextLevel = []; 24 | 25 | if l == 1 % layer 1 to n mapping 26 | for j = 1:m 27 | phermoneToNextLevel(j) = phermone(1, j); 28 | end 29 | 30 | else % rest layers are n to n mapping 31 | lastNode = antPath(l-1); 32 | 33 | phermoneRow = l; 34 | phermoneColS = (lastNode - 1) * m + 1; 35 | phermoneColF = lastNode * m; 36 | phermoneToNextLevel = phermone(phermoneRow, ... 37 | phermoneColS:phermoneColF); 38 | end 39 | 40 | randVal = rand(1); 41 | weights = phermoneToNextLevel; 42 | testPath = antPath; % copy current ant path to calculate distance 43 | for mi = 1:m 44 | testPath(l) = mi; 45 | % Construct a matrix to memorize this for better performance 46 | distance = costFunc(testPath, jobs, m, l) - costFunc(antPath, ... 47 | jobs, m, l-1); 48 | weights(mi) = weights(mi) / (distance+1); 49 | end 50 | totalWeight = sum(weights); 51 | weightAcc = 0; 52 | nextIndex = 0; 53 | 54 | if rand(1) < rzero % experience vs exploration 55 | nextIndexs = find(weights == max(weights)); 56 | nextIndex = nextIndexs(randi(numel(nextIndexs))); 57 | else 58 | while randVal > (weightAcc / totalWeight) 59 | nextIndex = nextIndex + 1; 60 | weightAcc = weightAcc + weights(nextIndex); 61 | end 62 | end 63 | antPath(l) = nextIndex; 64 | end 65 | 66 | antPaths(a, :) = antPath; 67 | 68 | end 69 | 70 | antCosts = []; 71 | 72 | % Find costs for all ant paths. Consider to use a vectoralization 73 | % version of cost function for this process in matlab. 74 | for a = 1:ants 75 | antCosts(a) = costFunc(antPaths(a,:), jobs, m, n); 76 | end 77 | 78 | bestAntCost = min(antCosts); 79 | worstAntCost = max(antCosts); 80 | bestAntPaths = antPaths(find(antCosts==bestAntCost), :); 81 | 82 | % Update phermone 83 | phermone = phermone .* 0.4; 84 | 85 | if bestAntCost <= bestSolCost 86 | % ONLY THE GLOBAL BEST ALLOW TO UPDATE 87 | deltaPhermone = 1 / bestAntCost; 88 | 89 | for s = 1:size(bestAntPaths, 1) 90 | bestAntPath = bestAntPaths(s,:); 91 | for ji = 1:n 92 | pcol = 0; 93 | if ji == 1 % first job 94 | pcol = bestAntPath(ji); 95 | else 96 | lastNode = bestAntPath(ji - 1); 97 | pcol = (lastNode - 1) * m + bestAntPath(ji); 98 | end 99 | phermone(ji, pcol) = phermone(ji, pcol) + deltaPhermone; 100 | end 101 | end 102 | end 103 | 104 | costEnd = costEnd + 1; 105 | costs(costEnd) = bestAntCost; 106 | 107 | if bestAntCost < bestSolCost 108 | bestSol = bestAntPaths(1,:); 109 | bestSolCost = bestAntCost; 110 | end 111 | end 112 | end 113 | -------------------------------------------------------------------------------- /GA.m: -------------------------------------------------------------------------------- 1 | % Genetic Algorithm (Simple Demo) Matlab/Octave Program 2 | % Written by X S Yang (Cambridge University) 3 | % Modified by Gary Li (University of Waterloo) 2014 4 | % Usage: gasimple or gasimple('x*exp(-x)'); 5 | 6 | %This program is modified to satify the Job Scheduling problem 7 | %For ECE457A, Unitersity of Waterloo, Summer, 2014 8 | 9 | %costs, Best Solution 10 | function [costs, schedule]=GA(jobs, numberOfMachines, maxGen) 11 | global solnew sol pop popnew fitness fitold range userdefinedn chromesomesize jobList NumberOfMachines limitedRange; 12 | range=[1 numberOfMachines]; % Range/Domain 13 | % Initializing the parameters 14 | rand('state' ,0'); % Reset the random generator 15 | popsize=100; % Population size 16 | MaxGen=100; % Max number of generations 17 | count=0; % counter 18 | nsite=2; % number of mutation sites 19 | pc=0.95; % Crossover probability 20 | pm=0.05; % Mutation probability 21 | 22 | % Update the max generation number if max generation is given 23 | if nargin>1, 24 | MaxGen=maxGen; 25 | jobList=jobs; 26 | NumberOfMachines=numberOfMachines; 27 | end 28 | 29 | chromesomesize=length(dec2bin(numberOfMachines)); 30 | nsbit=length(jobs)*chromesomesize; % String length (bits) 31 | userdefinedn=length(jobs); %user defined n 32 | % Generating the initial population 33 | popnew=init_gen(popsize,nsbit); 34 | fitness=zeros(1,popsize); % fitness array 35 | % Display the shape of the function 36 | %x=range(1):0.1:range(2); 37 | %plot(x,felement(x,userdefinedn)); 38 | fitold=fitness; 39 | 40 | % Initialize solution <- initial population 41 | solnew=zeros(popsize, userdefinedn); 42 | 43 | limitedRange=max(abs(range)); 44 | 45 | costs=zeros(maxGen,1); 46 | 47 | %TODO:populate row 48 | for i=1:popsize, 49 | solnew(i,:)=bintodec(popnew(i,:)); 50 | end 51 | 52 | bestfun=zeros(MaxGen,1); 53 | bestsol=zeros(MaxGen,length(jobs)); 54 | 55 | %Record as the history 56 | fitold=fitness; 57 | pop=popnew; 58 | sol=solnew; 59 | 60 | % Start the evolution loop 61 | for i=1:MaxGen, 62 | % Record as the history 63 | for k=1:popsize, 64 | if(fitness(k)>=fitold(k)) 65 | pop(k,:)=popnew(k,:); 66 | sol(k,:)=solnew(k,:); 67 | fitold(k)=fitness(k); 68 | else 69 | popnew(k,:)=pop(k,:); 70 | solnew(k,:)=sol(k,:); 71 | end 72 | end 73 | for j=1:popsize, 74 | % Crossover pair 75 | ii=floor(popsize*rand)+1; 76 | jj=floor(popsize*rand)+1; 77 | % Cross over 78 | if pc>rand, 79 | [popnew(ii,:),popnew(jj,:)]=crossover(pop(ii,:),pop(jj,:)); 80 | % Evaluate the new pairs 81 | count=count+2; 82 | evolve(ii); 83 | evolve(jj); 84 | end 85 | 86 | % Mutation at n sites 87 | if pm>rand, 88 | kk=floor(popsize*rand)+1; count=count+1; 89 | popnew(kk,:)=mutate(pop(kk,:),nsite); 90 | evolve(kk); 91 | end 92 | end % end for j 93 | % Record the current best 94 | bestfun(i)=max(fitness); 95 | bestsols=sol(bestfun(i)==fitness,:); 96 | bestsol(i,:)=bestsols(1,:); 97 | costs(i,:)=cost(bestsol(i,:), jobs, numberOfMachines); 98 | end % end for i 99 | 100 | % Display results 101 | %set(gcf,'color','w'); 102 | %subplot (2,1,1); 103 | %plot(bestsol); 104 | %title('Plot of best solution of each generation'); 105 | %subplot(2,1,2); 106 | %plot(bestfun); 107 | %title('Fitness'); 108 | 109 | %output 110 | schedule=bestsol(size(bestsol, 1),:); 111 | %costOutput=cost(schedule, jobs, numberOfMachines); 112 | end % end for gasimple 113 | 114 | % All the sub functions 115 | % generation of the initial population 116 | function pop=init_gen(np,nsbit) 117 | % String length=nsbit+l with pop(:,l) for the Sign 118 | %pop=rand(np,nsbit)>0.5; 119 | pop=randi([0 1],np,nsbit); 120 | end % end for init_gen 121 | 122 | % Evolving the new generation 123 | function evolve(j) 124 | global solnew popnew fitness fitold pop sol jobList NumberOfMachines; 125 | solnew(j,:)=bintodec(popnew(j,:)); 126 | %TODO: cost(schedule, Jobs, numberOfMachine) 127 | fitness(j)= 1 / (1 + cost( solnew(j,:),jobList,NumberOfMachines)); 128 | if fitness(j)>fitold(j), 129 | pop(j,:)=popnew(j,:); 130 | sol(j)=solnew(j); 131 | % else 132 | % popnew(j,:)= pop(j,:); 133 | % solnew(j)=sol(j); 134 | end 135 | % Convert a binary string into a decimal number 136 | end % end for evolve 137 | 138 | 139 | function [decs]=bintodec(bins) 140 | global chromesomesize userdefinedn limitedRange; 141 | decs=zeros(1, userdefinedn); 142 | index=1; 143 | divisor=((2^chromesomesize)-1); 144 | for deci=1:userdefinedn, 145 | nindex=index+chromesomesize; 146 | bin=bins(index:nindex-1); 147 | num=bin(1:end); % get the binary 148 | generated=0; 149 | for i=1:length(bin), 150 | generated=generated+num(i)*2^(length(bin)-i); 151 | end 152 | dec=round((generated/divisor)*(limitedRange-1))+1; 153 | index=nindex; 154 | decs(deci)=dec; 155 | end 156 | end % end for bintodec 157 | 158 | % Crossover operator 159 | function [c,d]=crossover(a,b) 160 | nn=length(a)-1; 161 | % generating a random crossover point 162 | cpoint=floor(nn*rand)+1; 163 | c=[a(1:cpoint) b(cpoint+1:end)]; 164 | d=[b(1:cpoint) a(cpoint+1:end)]; 165 | end % end for crossover 166 | 167 | % Mutatation operator 168 | function anew=mutate(a,nsite) 169 | nn=length(a); 170 | anew=a; 171 | for i=1:nsite, 172 | j=floor(rand*nn)+1; 173 | anew(j)=mod(a(j)+1,2); 174 | end 175 | end % end for mutation operation 176 | 177 | % function for question 3, assume every value in vector x is same 178 | % value 179 | % x is the input of each value in vector x, assume each vector is same 180 | % n is the user defined variable, which implies the size of the input 181 | function [result]=felement(x, n) 182 | result=zeros(1,size(x,2)); 183 | for i=1:size(x,2), 184 | absx = abs(x(i)); 185 | absxn(1:n) = absx; 186 | iexp = linspace(2, n+1, n); 187 | result(i) = sum(absxn .^ iexp); 188 | end 189 | end 190 | 191 | 192 | function [result]=cost(schedule, jobs, numberOfMachines) 193 | results=zeros(1,numberOfMachines); 194 | for i=1:length(jobs) 195 | results(schedule(i)) = results(schedule(i)) + jobs(i); 196 | end 197 | result=max(results); 198 | end 199 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | ** Running 2 | - All tests 3 | #+BEGIN_SRC octave 4 | ALL_test_16t6m(); 5 | ALL_test_17t5m(); 6 | #+END_SRC 7 | - TS 8 | - source code file: TS.m 9 | - All test files match TS_* 10 | - example 11 | #+BEGIN_SRC octave 12 | iterations = 50; 13 | m = 3; 14 | n = 6; 15 | J = [2, 3, 4, 6, 2, 2]; 16 | [costs, bestSol] = TS(J, m, n, 10, iterations, @cost, @getBestNeighbor); 17 | #+END_SRC 18 | - SA 19 | - source code file: SA.m 20 | - All test files match SA_* 21 | - example 22 | #+BEGIN_SRC octave 23 | iterations = 50; 24 | m = 3; 25 | n = 6; 26 | S = initSolution(m,n); 27 | J = [2, 3, 4, 6, 2, 2]; 28 | sT = findStartTemp(J, m); 29 | alpha = 0.85; 30 | iterationsAtTemp = 2; 31 | fT = sT*(alpha^(iterations/iterationsAtTemp)); 32 | [costs, bestSol] = SA(S, J, m, n, iterationsAtTemp, sT, fT, alpha, @cost, @gen_neighbor); 33 | #+END_SRC 34 | - GA 35 | - source code file: GA.m 36 | - All test files match GA_* 37 | - example 38 | #+BEGIN_SRC octave 39 | iterations = 50; 40 | m = 3; 41 | n = 6; 42 | J = [2, 3, 4, 6, 2, 2]; 43 | [costs, bestSol] = GA(J, m, iterations); 44 | #+END_SRC 45 | - PSO 46 | - source code file: PSO.m PSO_lbest.m (better performance) 47 | - All test files match PSO_* 48 | - example 49 | #+BEGIN_SRC octave 50 | iterations = 50; 51 | m = 3; 52 | n = 6; 53 | J = [2, 3, 4, 6, 2, 2]; 54 | [costs, bestSol] = PSO_lbest(J, m, n, 1500, iterations, @cost); 55 | #+END_SRC 56 | - ACO 57 | - source code file: ACO.m 58 | - All test files match ACO_* 59 | - example 60 | #+BEGIN_SRC octave 61 | iterations = 50; 62 | m = 3; 63 | n = 6; 64 | J = [2, 3, 4, 6, 2, 2]; 65 | ants = 5; 66 | [costs, bestSol] = ACO(J, m, n, ants, iterations, 0.2, @cost); 67 | #+END_SRC 68 | ** Problem Description 69 | 70 | Job shop scheduling is an optimization problem in which n jobs J1, 71 | J2, ..., Jn of varying sizes are given. These jobs need to be 72 | scheduled on m identical machines, while trying to minimize the 73 | makespan. The makespan is the total length of the schedule (that 74 | is, when all the jobs have finished processing). 75 | 76 | ** Problem Formulation 77 | *** Variables 78 | - n, number of Jobs 79 | - m, number of identical Machine 80 | - J, an array of each Jobs' weight 81 | - S, an array of each Jobs' Schedule 82 | *** Constraints 83 | - m > 1 84 | - n > m 85 | - \forall s \in S, 1 <= s <= m 86 | *** Cost Function 87 | 88 | Time takes the longest scheduled machine to finish. See cost.m 89 | 90 | *** Goals 91 | - Minimize cost function 92 | - Minimize number of iterations for each algorithm 93 | - Find the best algorithm for the problem 94 | *** Simple Example 95 | - J = (2,3,4,6,2,2) 96 | - S = (1,2,2,3,1,1) 97 | - Cost = 7 98 | - This setup is optimal 99 | ** Tabu Search 100 | *** Neighbors of each schedule 101 | 102 | Each schedule will have (m-1)*n neighbors, where m is the number 103 | of machines, and n is the number of jobs. Neighbors will only have 104 | one job scheduled on a different machine. 105 | *** Finding the best neighbor 106 | 107 | In order the find the neighbor with the lowest cost, the algorithm 108 | will loop through every valid neighbor and evaluate its cost. The 109 | neighbor with the lowest cost will be selected as the best neighbor. 110 | 111 | *** Tabulist 112 | - The list length of the tabulist is user-defined. 113 | - The tabulist acts like a queque (first in first out) 114 | - The oldest move will be deleted when a new move is appended. 115 | - A new move is appended every time after finding a best neighbor. 116 | 117 | ** Simulated Annealing 118 | *** Neighbors of each schedule 119 | 120 | Each schedule will have (m-1)*n neighbors, where m is the number 121 | of machines, and n is the number of jobs. Neighbors will only have 122 | one job scheduled on a different machine. 123 | 124 | *** Finding a suitable start temperature 125 | - Assume the max change is the MAX of 126 | - total time of all job divide by number of machines. 127 | - max time of a single job. 128 | - Formula to find the max 129 | - Temp_start = -1 * max_change / ln(p_0), where p_0 is 0.85 130 | - Start temperature is not calculated within SA, need to be 131 | calculated before execute the SA. 132 | - see "findStartTemp" in "SA_test.m". 133 | *** Cooling Schedule 134 | - Using geometric cooling schedule. 135 | - Final temperature should close to zero but not equal to zero. 136 | - alpha = 0.75 ~ 0.9 is commonly used. 137 | - iteration 138 | - a constant. 139 | - number of iteration for each temperature. 140 | 141 | ** Genetic Algorithm 142 | *** Overview 143 | 144 | This part uses Genetic Algorithm to find the optimal solution for the job 145 | scheduling problem. The process was inspired by the evolution of organisms 146 | in natural. It employs random crossover, mutation and evolution to achieve 147 | the goal of finding the optimal scheduling for a set of given jobs. This 148 | process is based on the stock Genetic Algorithm given by the professor. 149 | 150 | *** Initial state 151 | - The population size is set to 100 152 | - Chromosome length depends on the range of the possible output 153 | - Crossover Probability was set to 95% 154 | - Mutation probability was set to 5% 155 | - There will be 2 sites of mutation, when the mutation event occurs 156 | *** Crossover 157 | - The crossover will exchange chromosome information at a specified 158 | crossover site, which is generated randomly. 159 | - After each crossover, evolve will be called, and the fittest of the older 160 | population, or its offspring will survive. 161 | *** Evolve 162 | - The evolve function will maximize the model function, 1/(1+cost), which is 163 | the same as to minimize the cost 164 | - The old and the new population will be compared, and the fitter of the two 165 | will get passed to the next generation 166 | *** Mutate 167 | - A given number mutation sites were generated, and the binary bits at the 168 | generated mutation sites will be flipped 169 | - Evolve function will be called, and the older generation and the newer 170 | generation will be compared, the fittest of the two will get passed on to 171 | the next generation 172 | ** Particle Swarm Optimization 173 | *** Overview 174 | 175 | This part uses the Ring Topology or lbest Particle Swarm Algorithm to find 176 | optimal solution for job scheduling problem. Each particle is communicating 177 | with four of its adjecent neighour. In each iteration, each particle 178 | calculates its speed based on the best solution in its neighbour and its 179 | personal best. Speed and location is defined in n dimensions. 180 | 181 | *** Initial state 182 | - All particals starts with 0 speed at all n directions. 183 | - All particals starts at location randomly assigned between 1 ~ m in all 184 | dimensions. 185 | - Local best solution is the same as partical's location 186 | - Neighbor best solution in each particle is the best solution in four of 187 | its neighours based on neighbor index. 188 | *** Local search criteria 189 | - Speed is calculated based on each particle's personal best solution and 190 | the best solution of its neighbor. c1 = 1.4944, c2 = 1.4944, w = 0.9, 191 | v_{t+1}^{i} = w\times v_{t}^{i}+c_{1}r_{1}^{i}(pbest_{t}^{i}-x_{t}^{i})+ 192 | c_{2}r_{2}^{i}(Nbest_{t}^{i}-x_{t}^{i}) 193 | - The new solution is calculated by adding its previous location and its 194 | new speed, 195 | x_{t+1}^{i} = x_{t}^{i}+v_{t+1}^{i} 196 | - When the new cost of the new location is smaller than a particle's local 197 | best, it updates its local best and update its neighbour's neibour best 198 | when applicable. 199 | - Asynchronous update method is used to reduce run time load requirement, 200 | neighbor best is updated when all partical finishes its calculation for 201 | its current round. 202 | *** Termination Criteria 203 | - The algorithm is terminated when set number of particals completes set 204 | number of iterations. 205 | - The number of particals determines the amount of exploration and the 206 | amount of iterations determines the amount of exploitation. 207 | ** Ant Colony Optimization 208 | *** Overview 209 | 210 | This part uses Ant Colony System to find the optimal solution for the job 211 | scheduling problem. The process is similar to find a shortest path between 212 | two nodes on an weighted tree graph. 213 | 214 | *** Initial state 215 | - All ants starts at layer 0 of the tree, which means no job has been 216 | scheduled. 217 | - All routes has initial pheromone of 1. 218 | - pheromone will decrease 40% after each round. 219 | *** Local search criteria 220 | - Local search depends on the number of pheromone, and the cost to move the 221 | next level. 222 | - The cost is calculate by the the extra number of time required for 223 | including the next job in certain machine. The cost can be zero. 224 | - Using experience vs Explore the new scheduling 225 | 1. a rand value is generate to compare with r_0 226 | 2. if the rand value is smaller than r_0, the local search will select the 227 | route with max amount of pheromone 228 | 3. otherwise, it will do a roulette wheel selection based on ( pheromone / 229 | (route-cost + 1)) 230 | *** Pheromone deposit 231 | - only the best ants in each round can deposit pheromone on its path. 232 | - the number of pheromone deposited equals to ( 1 / best-ant-total-cost). 233 | ** CPU Time Usage Data 234 | *** Total time for 1000 iterations 235 | |----------+-------+-------+-------+-------+-------| 236 | | data set | GA | PSO | TS | SA | ACO | 237 | |----------+-------+-------+-------+-------+-------| 238 | | 16t6m | 23.15 | 6.490 | 6.677 | 0.062 | 49.23 | 239 | | 17t5m | 22.62 | 6.209 | 5.600 | 0.047 | 44.15 | 240 | |----------+-------+-------+-------+-------+-------| 241 | *** Time of Convergence 242 | |----------+-------+-------+-------+-------+-------| 243 | | data set | GA | PSO | TS | SA | ACO | 244 | |----------+-------+-------+-------+-------+-------| 245 | | 16t6m | 16.97 | 2.726 | 0.133 | 0.012 | 0.985 | 246 | | 17t5m | 9.048 | 5.588 | 0.168 | 0.011 | 0.883 | 247 | |----------+-------+-------+-------+-------+-------| 248 | -------------------------------------------------------------------------------- /README.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | README 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 63 | 109 | 110 | 111 | 112 | 113 |
114 | 115 |
116 | 117 |
118 |

README

119 | 120 | 121 | 184 | 185 |
186 |

1 Running

187 |
188 | 189 |
    190 |
  • All tests 191 | 192 | 193 | 194 |
    ALL_test_16t6m();
    195 | ALL_test_17t5m();
    196 | 
    197 | 198 |
  • 199 |
  • TS 200 |
      201 |
    • source code file: TS.m 202 |
    • 203 |
    • All test files match TS* 204 |
    • 205 |
    • example 206 | 207 | 208 | 209 |
      iterations = 50;
      210 | m = 3;
      211 | n = 6;
      212 | J = [2, 3, 4, 6, 2, 2];
      213 | [costs, bestSol] = TS(J, m, n, 10, iterations, @cost, @getBestNeighbor);
      214 | 
      215 | 216 |
    • 217 |
    218 | 219 |
  • 220 |
  • SA 221 |
      222 |
    • source code file: SA.m 223 |
    • 224 |
    • All test files match SA* 225 |
    • 226 |
    • example 227 | 228 | 229 | 230 |
      iterations = 50;
      231 | m = 3;
      232 | n = 6;
      233 | S = initSolution(m,n);
      234 | J = [2, 3, 4, 6, 2, 2];
      235 | sT = findStartTemp(J, m);
      236 | alpha = 0.85;
      237 | iterationsAtTemp = 2;
      238 | fT = sT*(alpha^(iterations/iterationsAtTemp));
      239 | [costs, bestSol] = SA(S, J, m, n, iterationsAtTemp, sT, fT, alpha, @cost, @gen_neighbor);
      240 | 
      241 | 242 |
    • 243 |
    244 | 245 |
  • 246 |
  • GA 247 |
      248 |
    • source code file: GA.m 249 |
    • 250 |
    • All test files match GA* 251 |
    • 252 |
    • example 253 | 254 | 255 | 256 |
      iterations = 50;
      257 | m = 3;
      258 | n = 6;
      259 | J = [2, 3, 4, 6, 2, 2];
      260 | [costs, bestSol] = GA(J, m, iterations);
      261 | 
      262 | 263 |
    • 264 |
    265 | 266 |
  • 267 |
  • PSO 268 |
      269 |
    • source code file: PSO.m PSOlbest.m (better performance) 270 |
    • 271 |
    • All test files match PSO* 272 |
    • 273 |
    • example 274 | 275 | 276 | 277 |
      iterations = 50;
      278 | m = 3;
      279 | n = 6;
      280 | J = [2, 3, 4, 6, 2, 2];
      281 | [costs, bestSol] = PSO_lbest(J, m, n, 1500, iterations, @cost);
      282 | 
      283 | 284 |
    • 285 |
    286 | 287 |
  • 288 |
  • ACO 289 |
      290 |
    • source code file: ACO.m 291 |
    • 292 |
    • All test files match ACO* 293 |
    • 294 |
    • example 295 | 296 | 297 | 298 |
      iterations = 50;
      299 | m = 3;
      300 | n = 6;
      301 | J = [2, 3, 4, 6, 2, 2];
      302 | ants = 5;
      303 | [costs, bestSol] = ACO(J, m, n, ants, iterations, 0.2, @cost);
      304 | 
      305 | 306 |
    • 307 |
    308 | 309 |
  • 310 |
311 | 312 |
313 | 314 |
315 | 316 |
317 |

2 Problem Description

318 |
319 | 320 | 321 |

322 | Job shop scheduling is an optimization problem in which n jobs J1, 323 | J2, …, Jn of varying sizes are given. These jobs need to be 324 | scheduled on m identical machines, while trying to minimize the 325 | makespan. The makespan is the total length of the schedule (that 326 | is, when all the jobs have finished processing). 327 |

328 |
329 | 330 |
331 | 332 |
333 |

3 Problem Formulation

334 |
335 | 336 | 337 |
338 | 339 |
340 |

3.1 Variables

341 |
342 | 343 |
    344 |
  • n, number of Jobs 345 |
  • 346 |
  • m, number of identical Machine 347 |
  • 348 |
  • J, an array of each Jobs' weight 349 |
  • 350 |
  • S, an array of each Jobs' Schedule 351 |
  • 352 |
353 | 354 |
355 | 356 |
357 | 358 |
359 |

3.2 Constraints

360 |
361 | 362 |
    363 |
  • m > 1 364 |
  • 365 |
  • n > m 366 |
  • 367 |
  • ∀ s ∈ S, 1 <= s <= m 368 |
  • 369 |
370 | 371 |
372 | 373 |
374 | 375 |
376 |

3.3 Cost Function

377 |
378 | 379 | 380 |

381 | Time takes the longest scheduled machine to finish. See cost.m 382 |

383 |
384 | 385 |
386 | 387 |
388 |

3.4 Goals

389 |
390 | 391 |
    392 |
  • Minimize cost function 393 |
  • 394 |
  • Minimize number of iterations for each algorithm 395 |
  • 396 |
  • Find the best algorithm for the problem 397 |
  • 398 |
399 | 400 |
401 | 402 |
403 | 404 |
405 |

3.5 Simple Example

406 |
407 | 408 |
    409 |
  • J = (2,3,4,6,2,2) 410 |
  • 411 |
  • S = (1,2,2,3,1,1) 412 |
  • 413 |
  • Cost = 7 414 |
  • 415 |
  • This setup is optimal 416 |
  • 417 |
418 | 419 |
420 |
421 | 422 |
423 | 424 |
425 |

4 Tabu Search

426 |
427 | 428 | 429 |
430 | 431 |
432 |

4.1 Neighbors of each schedule

433 |
434 | 435 | 436 |

437 | Each schedule will have (m-1)*n neighbors, where m is the number 438 | of machines, and n is the number of jobs. Neighbors will only have 439 | one job scheduled on a different machine. 440 |

441 | 442 |
443 | 444 |
445 |

4.2 Finding the best neighbor

446 |
447 | 448 | 449 |

450 | In order the find the neighbor with the lowest cost, the algorithm 451 | will loop through every valid neighbor and evaluate its cost. The 452 | neighbor with the lowest cost will be selected as the best neighbor. 453 |

454 |
455 | 456 |
457 | 458 |
459 |

4.3 Tabulist

460 |
461 | 462 |
    463 |
  • The list length of the tabulist is user-defined. 464 |
  • 465 |
  • The tabulist acts like a queque (first in first out) 466 |
  • 467 |
  • The oldest move will be deleted when a new move is appended. 468 |
  • 469 |
  • A new move is appended every time after finding a best neighbor. 470 |
  • 471 |
472 | 473 | 474 |
475 |
476 | 477 |
478 | 479 |
480 |

5 Simulated Annealing

481 |
482 | 483 | 484 |
485 | 486 |
487 |

5.1 Neighbors of each schedule

488 |
489 | 490 | 491 |

492 | Each schedule will have (m-1)*n neighbors, where m is the number 493 | of machines, and n is the number of jobs. Neighbors will only have 494 | one job scheduled on a different machine. 495 |

496 |
497 | 498 |
499 | 500 |
501 |

5.2 Finding a suitable start temperature

502 |
503 | 504 |
    505 |
  • Assume the max change is the MAX of 506 |
      507 |
    • total time of all job divide by number of machines. 508 |
    • 509 |
    • max time of a single job. 510 |
    • 511 |
    512 | 513 |
  • 514 |
  • Formula to find the max 515 |
      516 |
    • Tempstart = -1 * maxchange / ln(p0), where p0 is 0.85 517 |
    • 518 |
    519 | 520 |
  • 521 |
  • Start temperature is not calculated within SA, need to be 522 | calculated before execute the SA. 523 |
      524 |
    • see "findStartTemp" in "SAtest.m". 525 |
    • 526 |
    527 | 528 |
  • 529 |
530 | 531 |
532 | 533 |
534 | 535 |
536 |

5.3 Cooling Schedule

537 |
538 | 539 |
    540 |
  • Using geometric cooling schedule. 541 |
  • 542 |
  • Final temperature should close to zero but not equal to zero. 543 |
  • 544 |
  • alpha = 0.75 ~ 0.9 is commonly used. 545 |
  • 546 |
  • iteration 547 |
      548 |
    • a constant. 549 |
    • 550 |
    • number of iteration for each temperature. 551 |
    • 552 |
    553 | 554 |
  • 555 |
556 | 557 | 558 |
559 |
560 | 561 |
562 | 563 |
564 |

6 Genetic Algorithm

565 |
566 | 567 | 568 |
569 | 570 |
571 |

6.1 Overview

572 |
573 | 574 | 575 |

576 | This part uses Genetic Algorithm to find the optimal solution for the job 577 | scheduling problem. The process was inspired by the evolution of organisms 578 | in natural. It employs random crossover, mutation and evolution to achieve 579 | the goal of finding the optimal scheduling for a set of given jobs. This 580 | process is based on the stock Genetic Algorithm given by the professor. 581 |

582 |
583 | 584 |
585 | 586 |
587 |

6.2 Initial state

588 |
589 | 590 |
    591 |
  • The population size is set to 100 592 |
  • 593 |
  • Chromosome length depends on the range of the possible output 594 |
  • 595 |
  • Crossover Probability was set to 95% 596 |
  • 597 |
  • Mutation probability was set to 5% 598 |
  • 599 |
  • There will be 2 sites of mutation, when the mutation event occurs 600 |
  • 601 |
602 | 603 |
604 | 605 |
606 | 607 |
608 |

6.3 Crossover

609 |
610 | 611 |
    612 |
  • The crossover will exchange chromosome information at a specified 613 | crossover site, which is generated randomly. 614 |
  • 615 |
  • After each crossover, evolve will be called, and the fittest of the older 616 | population, or its offspring will survive. 617 |
  • 618 |
619 | 620 |
621 | 622 |
623 | 624 |
625 |

6.4 Evolve

626 |
627 | 628 |
    629 |
  • The evolve function will maximize the model function, 1/(1+cost), which is 630 | the same as to minimize the cost 631 |
  • 632 |
  • The old and the new population will be compared, and the fitter of the two 633 | will get passed to the next generation 634 |
  • 635 |
636 | 637 |
638 | 639 |
640 | 641 |
642 |

6.5 Mutate

643 |
644 | 645 |
    646 |
  • A given number mutation sites were generated, and the binary bits at the 647 | generated mutation sites will be flipped 648 |
  • 649 |
  • Evolve function will be called, and the older generation and the newer 650 | generation will be compared, the fittest of the two will get passed on to 651 | the next generation 652 |
  • 653 |
654 | 655 |
656 |
657 | 658 |
659 | 660 |
661 |

7 Particle Swarm Optimization

662 |
663 | 664 | 665 |
666 | 667 |
668 |

7.1 Overview

669 |
670 | 671 | 672 |

673 | This part uses the Ring Topology or lbest Particle Swarm Algorithm to find 674 | optimal solution for job scheduling problem. Each particle is communicating 675 | with four of its adjecent neighour. In each iteration, each particle 676 | calculates its speed based on the best solution in its neighbour and its 677 | personal best. Speed and location is defined in n dimensions. 678 |

679 |
680 | 681 |
682 | 683 |
684 |

7.2 Initial state

685 |
686 | 687 |
    688 |
  • All particals starts with 0 speed at all n directions. 689 |
  • 690 |
  • All particals starts at location randomly assigned between 1 ~ m in all 691 | dimensions. 692 |
  • 693 |
  • Local best solution is the same as partical's location 694 |
  • 695 |
  • Neighbor best solution in each particle is the best solution in four of 696 | its neighours based on neighbor index. 697 |
  • 698 |
699 | 700 |
701 | 702 |
703 | 704 |
705 |

7.3 Local search criteria

706 |
707 | 708 |
    709 |
  • Speed is calculated based on each particle's personal best solution and 710 | the best solution of its neighbor. c1 = 1.4944, c2 = 1.4944, w = 0.9, 711 | vt+1i = w× vti+c1r1i(pbestti-xti)+ 712 | c2r2i(Nbestti-xti) 713 |
  • 714 |
  • The new solution is calculated by adding its previous location and its 715 | new speed, 716 | xt+1i = xti+vt+1i 717 |
  • 718 |
  • When the new cost of the new location is smaller than a particle's local 719 | best, it updates its local best and update its neighbour's neibour best 720 | when applicable. 721 |
  • 722 |
  • Asynchronous update method is used to reduce run time load requirement, 723 | neighbor best is updated when all partical finishes its calculation for 724 | its current round. 725 |
  • 726 |
727 | 728 |
729 | 730 |
731 | 732 |
733 |

7.4 Termination Criteria

734 |
735 | 736 |
    737 |
  • The algorithm is terminated when set number of particals completes set 738 | number of iterations. 739 |
  • 740 |
  • The number of particals determines the amount of exploration and the 741 | amount of iterations determines the amount of exploitation. 742 |
  • 743 |
744 | 745 |
746 |
747 | 748 |
749 | 750 |
751 |

8 Ant Colony Optimization

752 |
753 | 754 | 755 |
756 | 757 |
758 |

8.1 Overview

759 |
760 | 761 | 762 |

763 | This part uses Ant Colony System to find the optimal solution for the job 764 | scheduling problem. The process is similar to find a shortest path between 765 | two nodes on an weighted tree graph. 766 |

767 |
768 | 769 |
770 | 771 |
772 |

8.2 Initial state

773 |
774 | 775 |
    776 |
  • All ants starts at layer 0 of the tree, which means no job has been 777 | scheduled. 778 |
  • 779 |
  • All routes has initial pheromone of 1. 780 |
  • 781 |
  • pheromone will decrease 40% after each round. 782 |
  • 783 |
784 | 785 |
786 | 787 |
788 | 789 |
790 |

8.3 Local search criteria

791 |
792 | 793 |
    794 |
  • Local search depends on the number of pheromone, and the cost to move the 795 | next level. 796 |
  • 797 |
  • The cost is calculate by the the extra number of time required for 798 | including the next job in certain machine. The cost can be zero. 799 |
  • 800 |
  • Using experience vs Explore the new scheduling 801 |
      802 |
    1. a rand value is generate to compare with r0 803 |
    2. 804 |
    3. if the rand value is smaller than r0, the local search will select the 805 | route with max amount of pheromone 806 |
    4. 807 |
    5. otherwise, it will do a roulette wheel selection based on ( pheromone / 808 | (route-cost + 1)) 809 |
    6. 810 |
    811 | 812 |
  • 813 |
814 | 815 |
816 | 817 |
818 | 819 |
820 |

8.4 Pheromone deposit

821 |
822 | 823 |
    824 |
  • only the best ants in each round can deposit pheromone on its path. 825 |
  • 826 |
  • the number of pheromone deposited equals to ( 1 / best-ant-total-cost). 827 |
  • 828 |
829 | 830 |
831 |
832 | 833 |
834 | 835 |
836 |

9 CPU Time Usage Data

837 |
838 | 839 | 840 |
841 | 842 |
843 |

9.1 Total time for 1000 iterations

844 |
845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | 854 | 855 | 856 |
data setGAPSOTSSAACO
16t6m23.156.4906.6770.06249.23
17t5m22.626.2095.6000.04744.15
857 | 858 |
859 | 860 |
861 | 862 |
863 |

9.2 Time of Convergence

864 |
865 | 866 | 867 | 868 | 869 | 870 | 871 | 872 | 873 | 874 | 875 | 876 |
data setGAPSOTSSAACO
16t6m16.972.7260.1330.0120.985
17t5m9.0485.5880.1680.0110.883
877 | 878 |
879 |
880 |
881 |
882 | 883 |
884 |

Date: 2014-07-29T20:00-0400

885 |

Author: Rui Zhao

886 |

Org version 7.9.3f with Emacs version 24

887 | Validate XHTML 1.0 888 | 889 |
890 | 891 | 892 | --------------------------------------------------------------------------------