├── GA ├── H2TS_create.m ├── H2TS_crossover.m ├── H2TS_fitness.m ├── H2TS_main.m ├── H2TS_mutate.m ├── cell2vec.m ├── completeTimeCell.mat ├── feasibleValidation.m ├── getDistance.m ├── plotGantt.m ├── plotSolutionGA.m ├── rank2sequence.m ├── sequence2rank.m ├── testMutationFasible.m ├── testSeq2Rank.m └── vec2cell.m ├── MILP ├── MILP.m ├── Untitled.m ├── getDistance.m ├── plotGantt.m ├── plotSolutionMILP.m └── solutionMILP.mat ├── README.md ├── SCP ├── SCP.m ├── getDistance.m ├── linear2rcd.m ├── plotGantt.m ├── plotSolutionSCP.m ├── rcd2linear.m └── taskSelection.m ├── generateInstance.m ├── linear2rcd.m ├── plotInstance.m └── rcd2linear.m /GA/H2TS_create.m: -------------------------------------------------------------------------------- 1 | function pop = H2TS_create(NVARS,~,options) 2 | % POP = H2TS_CREATE(NVARS,FITNESSFCN,OPTIONS) creates a population 3 | % each with a length of NVARS. 4 | % The arguments to the function are 5 | % NVARS: Number of variables 6 | % FITNESSFCN: Fitness function 7 | % OPTIONS: Options structure used by the GA 8 | global TaskNumMat; 9 | totalTaskNum = sum(sum(TaskNumMat)); 10 | totalPopulationSize = sum(options.PopulationSize); 11 | pop = cell(totalPopulationSize,1); 12 | for pop_id = 1:totalPopulationSize 13 | individualCell = vec2cell((randperm(totalTaskNum))',TaskNumMat); 14 | individualCell = feasibleValidation(individualCell,TaskNumMat,[1 1 1]); 15 | pop{pop_id} = cell2vec(individualCell,TaskNumMat)'; 16 | end 17 | -------------------------------------------------------------------------------- /GA/H2TS_crossover.m: -------------------------------------------------------------------------------- 1 | function xoverKids = H2TS_crossover(parents,~,~,~,~,thisPopulation) 2 | % FITNESSFCN,THISSCORE,THISPOPULATION) crossovers PARENTS to produce 3 | % the children XOVERKIDS. 4 | % 5 | % The arguments to the function are 6 | % PARENTS: Parents chosen by the selection function. index 7 | % OPTIONS: Options created from OPTIMOPTIONS 8 | % NVARS: Number of variables 9 | % FITNESSFCN: Fitness function 10 | % STATE: State structure used by the GA solver 11 | % THISSCORE: Vector of scores of the current population 12 | % THISPOPULATION: Matrix of individuals in the current population 13 | global TaskNumMat; 14 | [m,n]=size(TaskNumMat); 15 | %Crossover combines two individuals, or parents, to form a newchild, for the next generation 16 | nKids = length(parents)/2; 17 | %fprintf("Total crossover is %d",nKids); 18 | xoverKids = cell(nKids,1); 19 | index = 1; 20 | totalTaskSum=sum(sum(TaskNumMat)); 21 | 22 | for id=1:nKids 23 | parent1 = thisPopulation{parents(index)}; 24 | parent2 = thisPopulation{parents(index+1)}; 25 | index = index + 2; 26 | 27 | crossProb = rand; 28 | crossNum = int32(totalTaskSum*crossProb); 29 | if crossNum==0 30 | crossNum =1; 31 | end 32 | crossLinearIndices = randperm(totalTaskSum); 33 | crossLinearIndices = crossLinearIndices(1:crossNum); 34 | 35 | % generate subtask index matrix. 36 | taskIndexMat = zeros(totalTaskSum,3); 37 | temp = 1; 38 | for i=1:m 39 | for j=1:n 40 | if TaskNumMat(i,j)~=0 41 | for k=1:TaskNumMat(i,j) 42 | taskIndexMat(temp,:)=[i j k]; 43 | temp = temp+1; 44 | end 45 | end 46 | end 47 | end 48 | crossLocations = taskIndexMat(crossLinearIndices,:); 49 | 50 | %crossover 51 | child = parent1; 52 | child(crossLinearIndices) = parent2(crossLinearIndices); 53 | 54 | childCell = vec2cell(child',TaskNumMat); 55 | childCell = feasibleValidation(childCell,TaskNumMat,crossLocations); 56 | xoverKids{id} = cell2vec(childCell,TaskNumMat)'; 57 | end 58 | -------------------------------------------------------------------------------- /GA/H2TS_fitness.m: -------------------------------------------------------------------------------- 1 | function scores = H2TS_fitness(x,TaskCell,RobotMat,AgentMat,depot,alpha) 2 | %x is cell matrix, its element is a row vector 3 | global TaskNumMat; 4 | [m,n]=size(TaskNumMat); 5 | scores = zeros(size(x,1),1); 6 | for id = 1:size(x,1) 7 | %recover from row vector to cell matrix,p->pp 8 | p = x{id}; 9 | pCell = vec2cell(p',TaskNumMat); 10 | 11 | robotLatestTime = zeros(m,1); 12 | agentLatestTime = zeros(n,1); 13 | robotLatestLoc = RobotMat(:,1:2); 14 | agentLatestLoc = AgentMat(:,1:2); 15 | 16 | largestRankMat = zeros(m,n); 17 | completeTimeCell = cell(m,n); 18 | for i=1:m 19 | for j=1:n 20 | if TaskNumMat(i,j)~=0 21 | largestRankMat(i,j)=max(pCell{i,j}); 22 | completeTimeCell{i,j}=zeros(TaskNumMat(i,j),1); 23 | end 24 | end 25 | end 26 | maxRank=max(max(largestRankMat)); 27 | 28 | for sb=1:maxRank 29 | for i=1:m 30 | for j=1:n 31 | vec=pCell{i,j}; 32 | index=find(vec==sb, 1); 33 | if ~isempty(index) 34 | Tasks=TaskCell{i,j}; 35 | task=Tasks(index,:); 36 | time1=robotLatestTime(i,1)+getDistance(robotLatestLoc(i,1),robotLatestLoc(i,2),task(1,4),task(1,5)); 37 | time2=agentLatestTime(j,1)+alpha*getDistance(agentLatestLoc(j,1),agentLatestLoc(j,2),task(1,4),task(1,5)); 38 | tempVec=completeTimeCell{i,j}; 39 | tempVec(index,1)=max(time1,time2)+task(1,6); 40 | completeTimeCell{i,j}=tempVec; 41 | robotLatestTime(i,1)=tempVec(index,1); 42 | agentLatestTime(j,1)=tempVec(index,1); 43 | robotLatestLoc(i,:)=task(1,4:5); 44 | agentLatestLoc(j,:)=task(1,4:5); 45 | end 46 | end 47 | end 48 | end 49 | save('completeTimeCell.mat','completeTimeCell'); 50 | 51 | for i=1:m 52 | robotLatestTime(i,1)=robotLatestTime(i,1)+getDistance(depot(1,1),depot(1,2),robotLatestLoc(i,1),robotLatestLoc(i,2)); 53 | end 54 | scores(id,1) = max(robotLatestTime(:,1)); 55 | end -------------------------------------------------------------------------------- /GA/H2TS_main.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/labimage/Multi-robot-Task-Allocation/2a4dd4da5fb3fc46c69608abfcb6b60bdc5c837e/GA/H2TS_main.m -------------------------------------------------------------------------------- /GA/H2TS_mutate.m: -------------------------------------------------------------------------------- 1 | function children = H2TS_mutate(parentsIndex,~,~,~, ~, ~,thisPopulation,~) 2 | global TaskNumMat; 3 | [m,n]=size(TaskNumMat); 4 | totalTaskSum=sum(sum(TaskNumMat)); 5 | % The arguments to the function are 6 | % PARENTS: Parents chosen by the selection function. index 7 | % OPTIONS: Options created from OPTIMOPTIONS 8 | % NVARS: Number of variables 9 | % FITNESSFCN: Fitness function 10 | % STATE: State structure used by the GA solver 11 | % THISSCORE: Vector of scores of the current population 12 | % THISPOPULATION: Matrix of individuals in the current population 13 | % MUTATIONRATE: Rate of mutation 14 | 15 | children = cell(length(parentsIndex),1); %output children number = parent number 16 | for id=1:length(parentsIndex) 17 | parent = thisPopulation{parentsIndex(id)}; 18 | parentCell = vec2cell(parent',TaskNumMat); 19 | largestRankMat=zeros(m,n); 20 | for i=1:m 21 | for j=1:n 22 | if TaskNumMat(i,j)~=0 23 | largestRankMat(i,j)=max(parentCell{i,j}); 24 | end 25 | end 26 | end 27 | 28 | taskIndexMat = zeros(totalTaskSum,3); 29 | temp = 1; 30 | for i=1:m 31 | for j=1:n 32 | if TaskNumMat(i,j)~=0 33 | for k=1:TaskNumMat(i,j) 34 | taskIndexMat(temp,:)=[i j k]; 35 | temp = temp+1; 36 | end 37 | end 38 | end 39 | end 40 | mutateLinearLocation = randi([1 totalTaskSum]); 41 | mutateLocation = taskIndexMat(mutateLinearLocation,:); 42 | 43 | r = mutateLocation(1,1); 44 | c = mutateLocation(1,2); 45 | d = mutateLocation(1,3); 46 | mutatedValue = parent(mutateLinearLocation); 47 | maxRowAndColumnRank = max(max(largestRankMat(r,:)),max(largestRankMat(:,c))); 48 | %mutateSpace:{1,2,...,maxRank,maxRank+1}\{rrc} 49 | mutateSpace = 1:maxRowAndColumnRank+1; 50 | mutateSpace = mutateSpace(mutateSpace~=mutatedValue); 51 | parent(mutateLinearLocation) = mutateSpace(randi([1 length(mutateSpace)])); 52 | %verification 53 | childCell = vec2cell(parent',TaskNumMat); 54 | childCell = feasibleValidation(childCell,TaskNumMat,mutateLocation); 55 | children{id}=cell2vec(childCell,TaskNumMat)'; %row vector 56 | end 57 | -------------------------------------------------------------------------------- /GA/cell2vec.m: -------------------------------------------------------------------------------- 1 | function colVec = cell2vec(inputCell,taskNumMat) 2 | [m,n]=size(inputCell); 3 | totalTaskNum = sum(sum(taskNumMat)); 4 | colVec = zeros(totalTaskNum,1); 5 | temp=1; 6 | for i=1:m 7 | for j=1:n 8 | if taskNumMat(i,j)~=0 9 | colVec(temp:temp+taskNumMat(i,j)-1,1)=inputCell{i,j}; 10 | temp=temp+taskNumMat(i,j); 11 | end 12 | end 13 | end 14 | 15 | end 16 | 17 | -------------------------------------------------------------------------------- /GA/completeTimeCell.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/labimage/Multi-robot-Task-Allocation/2a4dd4da5fb3fc46c69608abfcb6b60bdc5c837e/GA/completeTimeCell.mat -------------------------------------------------------------------------------- /GA/feasibleValidation.m: -------------------------------------------------------------------------------- 1 | function rankCell = feasibleValidation(inputCell,taskNumMat,Locations) 2 | %Locations: many rows means many mutated subtasks. 3 | [m,n]=size(inputCell); 4 | totalTaskNum=sum(sum(taskNumMat)); 5 | %linear order of all subtasks. 6 | LinearTaskRankVec=cell2vec(inputCell,taskNumMat); 7 | LinearMutatedIndices=zeros(size(Locations,1),1); 8 | 9 | for i=1:size(Locations,1) 10 | if Locations(i,1)==1 11 | if Locations(i,2)==1 12 | LinearMutatedIndices(i,1)=Locations(i,3); 13 | else 14 | LinearMutatedIndices(i,1)=sum(taskNumMat(Locations(i,1),1:Locations(i,2)-1))+Locations(i,3); 15 | end 16 | else 17 | temp = sum(sum(taskNumMat(1:Locations(i,1)-1,:))); 18 | if Locations(i,2)==1 19 | LinearMutatedIndices(i,1)=temp+Locations(i,3); 20 | else 21 | LinearMutatedIndices(i,1)=temp+sum(taskNumMat(Locations(i,1),1:Locations(i,2)-1))+Locations(i,3); 22 | end 23 | end 24 | end 25 | 26 | largestRankMat=zeros(m,n); 27 | for i=1:m 28 | for j=1:n 29 | if taskNumMat(i,j)~=0 30 | largestRankMat(i,j)=max(inputCell{i,j}); 31 | end 32 | end 33 | end 34 | maxRank=max(max(largestRankMat)); 35 | 36 | temp=1; 37 | tempIndices=1:totalTaskNum; 38 | newLinear = zeros(totalTaskNum,1); 39 | for i=1:maxRank 40 | rowIndices=find(LinearTaskRankVec==i); 41 | if ~isempty(rowIndices) 42 | repeated = find(LinearTaskRankVec(LinearMutatedIndices',1)==i, 1); 43 | if ~isempty(repeated) 44 | nRepeated=size(repeated); 45 | for k=1:nRepeated 46 | newLinear(LinearMutatedIndices(repeated(k,1),1),1)=temp; 47 | rowIndices=rowIndices(rowIndices~=LinearMutatedIndices(repeated(k,1),1)); 48 | temp=temp+1; 49 | end 50 | if ~isempty(rowIndices) 51 | newLinear(rowIndices,1)=tempIndices(temp:temp+size(rowIndices,1)-1)'; 52 | temp=temp+length(rowIndices); 53 | end 54 | else 55 | newLinear(rowIndices,1)=tempIndices(temp:temp+size(rowIndices,1)-1)'; 56 | temp=temp+length(rowIndices); 57 | end 58 | end 59 | end 60 | 61 | tempRankCell=vec2cell(newLinear,taskNumMat); 62 | [RSeq,CSeq]=rank2sequence(tempRankCell); 63 | rankCell=sequence2rank(RSeq,CSeq); 64 | end 65 | 66 | -------------------------------------------------------------------------------- /GA/getDistance.m: -------------------------------------------------------------------------------- 1 | function distance = getDistance(r1,c1,r2,c2) 2 | distance = abs(r1-r2)+abs(c1-c2); 3 | end -------------------------------------------------------------------------------- /GA/plotGantt.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/labimage/Multi-robot-Task-Allocation/2a4dd4da5fb3fc46c69608abfcb6b60bdc5c837e/GA/plotGantt.m -------------------------------------------------------------------------------- /GA/plotSolutionGA.m: -------------------------------------------------------------------------------- 1 | clear; 2 | clc; 3 | load("../Instance.mat"); 4 | 5 | figure('position',[400,10,1000,1000]); 6 | axis([0 80 0 80]); 7 | axis equal; 8 | axis manual; 9 | 10 | robotNum=size(RobotMat,1); 11 | agentNum=size(AgentMat,1); 12 | subtaskNum=size(TaskMat,1); 13 | 14 | ColorMat=zeros(robotNum,3); 15 | ColorMat(1,:)=[1 0 0]; 16 | ColorMat(1,:)=[0 1 0]; 17 | ColorMat(1,:)=[0 0 1]; 18 | 19 | %% plot depot and stations 20 | plot(StationMat(:,1),StationMat(:,2),'LineStyle','none','Color',[0.7 0.7 0.7],'marker','.','markersize',20); 21 | hold on; 22 | plot(depot(1,1),depot(1,2),'LineStyle','none','Color',[0 0 0],'marker','.','markersize',20); 23 | hold on; 24 | 25 | % plot(100,100,'LineStyle','none','Color',[1 1 1],'marker','.','markersize',1); 26 | %pause(5); 27 | 28 | %% plot cliques 29 | for i=1:agentNum 30 | Clique = CliqueCell{i,1}; 31 | x=Clique(:,1); 32 | y=Clique(:,2); 33 | dt = delaunayTriangulation(x,y); 34 | k = convexHull(dt); 35 | plot(x,y,'LineStyle','none', 'Color',[0.7 0.7 0.7],'marker','.','markersize',20); 36 | hold on; 37 | plot(x(k), y(k), 'Color',[0.9 0.9 0.9]); 38 | hold on; 39 | end 40 | 41 | %pause(5); 42 | 43 | %% plot robots 44 | plot(RobotMat(:,1), RobotMat(:,2),'LineStyle','none','marker','o', 'Color',[0 0 0],'markersize',13,'MarkerFaceColor','k'); 45 | text(RobotMat(:,1)+1,RobotMat(:,2),'TR1,TR2,TR3'); 46 | hold on; 47 | plot(AgentMat(:,1), AgentMat(:,2),'LineStyle','none','marker','s', 'Color',[0 0 0],'markersize',10,'MarkerFaceColor','k'); 48 | for i=1:agentNum 49 | txt=sprintf('SR%d',i); 50 | text(AgentMat(i,1)+1,AgentMat(i,2),txt); 51 | end 52 | hold on; 53 | 54 | %pause(5); 55 | 56 | %% plot tasks 57 | ColorMat = [1 0 0;0 1 0;0 0 1;1 1 0;1 0 1;1 1 0]; 58 | 59 | for i=1:subtaskNum 60 | subtask=TaskMat(i,:); 61 | plot(subtask(1,4),subtask(1,5),'LineStyle','none','Color',ColorMat(subtask(1,1),:),'marker','.','MarkerFaceColor',ColorMat(subtask(1,1),:),'markersize',20); 62 | hold on; 63 | text(subtask(1,4)-0.7,subtask(1,5)-1,num2str(subtask(1,6))); 64 | end 65 | 66 | %pause(5); 67 | 68 | %% plot optimal solutions 69 | load('solutionGA.mat'); 70 | %% Reorganize all tasks. 71 | RobotTaskCell = cell(robotNum,1); 72 | RobotTaskNumVec = zeros(robotNum,1); 73 | for i=1:robotNum 74 | task = TaskMat(TaskMat(:,1)==i,:); 75 | robot=RobotMat(i,:); 76 | dummyTask = [i 0 0 robot(1,1) robot(1,2) 0 0 0 0];%dummy task comes first 77 | RobotTaskCell{i,1}=[dummyTask;task]; 78 | RobotTaskNumVec(i,1) = size(task,1)+1; 79 | end 80 | 81 | AgentTaskCell = cell(agentNum,1); 82 | AgentTaskNumVec = zeros(agentNum,1); 83 | for i=1:agentNum 84 | task = TaskMat(TaskMat(:,2)==i,:); 85 | agent=AgentMat(i,:); 86 | dummyTask = [0 i 0 agent(1,1) agent(1,2) 0 0 0 0];%dummy task comes first 87 | AgentTaskCell{i,1}=[dummyTask;task]; 88 | AgentTaskNumVec(i,1)=size(task,1)+1; 89 | end 90 | 91 | taskNumVec = zeros(robotNum,1); 92 | taskNumVec(:,1) = sum(BlockNumMat,2); 93 | 94 | %% plot routes. 95 | hold on; 96 | for i=1:robotNum 97 | robot = RobotMat(i,:); 98 | seq = RobotTaskSequence{i,1}; 99 | task = RobotTaskCell{i,1}; 100 | num = RobotTaskNumVec(i,1); 101 | for j=0:num 102 | if j==0 103 | priorLocation = robot(1,1:2); 104 | else 105 | priorLocation = task(seq(j,1),4:5); 106 | end 107 | if j~=num 108 | latterLocation = task(seq(j+1,1),4:5); 109 | else 110 | latterLocation = depot; 111 | end 112 | line([priorLocation(1,1),latterLocation(1,1)],[priorLocation(1,2),latterLocation(1,2)],'color',ColorMat(i,:),'linestyle','-'); 113 | %pause(0.5); 114 | end 115 | %pause(1); 116 | end 117 | 118 | hold on; 119 | %pause(5); 120 | 121 | for i=1:agentNum 122 | agent = AgentMat(i,:); 123 | seq = AgentTaskSequence{i,1}; 124 | task = AgentTaskCell{i,1}; 125 | num = AgentTaskNumVec(i,1); 126 | for j=0:num-1 127 | if j==0 128 | priorLocation = agent(1,1:2); 129 | else 130 | priorLocation = task(seq(j,1),4:5); 131 | end 132 | latterLocation = task(seq(j+1,1),4:5); 133 | line([priorLocation(1,1),latterLocation(1,1)],[priorLocation(1,2),latterLocation(1,2)],'color',[0 0 0],'linestyle','--'); 134 | %pause(0.5); 135 | end 136 | %pause(1); 137 | end 138 | 139 | %pause(3); 140 | 141 | %% plot Gantt chart and statistics 142 | totalRobotTravelTime = 0; 143 | totalRobotWaitTime = 0; 144 | totalAgentTravelTime = 0; 145 | totalAgentWaitTime = 0; 146 | 147 | solution=[0;StartTimeVec]; 148 | 149 | figure(2); 150 | TimeCell=cell(robotNum+agentNum,1); 151 | TaskIndexSequenceCell=cell(robotNum+agentNum,1); 152 | priorTotalNum = 0; 153 | for i=1:robotNum 154 | seq = RobotTaskSequence{i,1}; 155 | task = RobotTaskCell{i,1}; 156 | num = RobotTaskNumVec(i,1); 157 | timeMat = zeros(num,6); 158 | tempTime = 0; 159 | for j=1:num 160 | colIndex = 1+priorTotalNum; 161 | if j==num 162 | currentTask = task(1,:); 163 | else 164 | currentTask = task(seq(j+1,1),:); 165 | end 166 | priorTask = task(seq(j,1),:); 167 | travelTime = getDistance(priorTask(1,4),priorTask(1,5),currentTask(1,4),currentTask(1,5)); 168 | 169 | if j==num 170 | startTime = 0; 171 | else 172 | index=find(ismember(TaskMat,currentTask,'rows')',1); 173 | startTime = solution(1+index,1); 174 | end 175 | processTime = currentTask(1,6); 176 | time1 = tempTime; 177 | time2 = time1+travelTime; 178 | time3 = time2; 179 | time4 = startTime; 180 | time5 = time4; 181 | time6 = time5+processTime; 182 | tempTime = time6; 183 | 184 | if startTime == 0 185 | time4 = time3; 186 | time5 = time4; 187 | time6 = time5; 188 | end 189 | 190 | timeMat(j,:) = [time1 time2 time3 time4 time5 time6]; 191 | taskIndexMat(j,:) = currentTask(1,1:3); 192 | 193 | %statistics 194 | totalRobotTravelTime = totalRobotTravelTime+travelTime; 195 | totalRobotWaitTime = totalRobotWaitTime+time4-time3; 196 | end 197 | 198 | TimeCell{i,1}=timeMat; 199 | TaskIndexSequenceCell{i,1}=taskIndexMat; 200 | priorTotalNum = priorTotalNum + num-1; 201 | end 202 | 203 | for i=1:agentNum 204 | seq = AgentTaskSequence{i,1}; 205 | task = AgentTaskCell{i,1}; 206 | num = AgentTaskNumVec(i,1); 207 | 208 | timeMat = zeros(num-1,6); 209 | taskIndexMat = zeros(num-1,3); 210 | 211 | tempTime = 0; 212 | for j=1:num-1 213 | currentTask = task(seq(j+1,1),:); 214 | priorTask = task(seq(j,1),:); 215 | travelTime = alpha*getDistance(priorTask(1,4),priorTask(1,5),currentTask(1,4),currentTask(1,5)); 216 | index=find(ismember(TaskMat,currentTask,'rows')',1); 217 | startTime = solution(1+index,1); 218 | 219 | processTime = currentTask(1,6); 220 | time1 = tempTime; 221 | time2 = time1+travelTime; 222 | time3 = time2; 223 | time4 = startTime; 224 | time5 = time4; 225 | time6 = time5+processTime; 226 | tempTime = time6; 227 | 228 | if startTime == 0 229 | time4 = time3; 230 | time5 = time4; 231 | time6 = time5; 232 | end 233 | 234 | timeMat(j,:) = [time1 time2 time3 time4 time5 time6]; 235 | taskIndexMat(j,:) = currentTask(1,1:3); 236 | 237 | %statistics 238 | totalAgentTravelTime = totalAgentTravelTime+travelTime; 239 | totalAgentWaitTime = totalAgentWaitTime+time4-time3; 240 | end 241 | 242 | TimeCell{robotNum+i,1}=timeMat; 243 | TaskIndexSequenceCell{robotNum+i,1}=taskIndexMat; 244 | end 245 | 246 | plotGantt(TimeCell,TaskIndexSequenceCell); 247 | 248 | %pause(5); 249 | 250 | %% plot Graph 251 | figure(3); 252 | G=digraph; 253 | 254 | nodeName = cell(1,sum(RobotTaskNumVec)+agentNum); 255 | 256 | for i=1:subtaskNum 257 | subtask=TaskMat(i,:); 258 | nodeName{1,i}=strcat('t(',num2str(subtask(1,1)),',',num2str(subtask(1,2)),',',num2str(subtask(1,3)),')'); 259 | end 260 | 261 | for i=1:robotNum+agentNum 262 | nodeName{1,subtaskNum+i}=strcat('t(',num2str(i),',',num2str(0),')'); 263 | end 264 | 265 | G = addnode(G,nodeName'); 266 | 267 | for i=1:robotNum 268 | seq=RobotTaskSequence{i,1}; 269 | task=RobotTaskCell{i,1}; 270 | num=RobotTaskNumVec(i,1); 271 | for j=1:num-1 272 | priorTask=task(seq(j,1),:); 273 | latterTask=task(seq(j+1,1),:); 274 | s=find(ismember(TaskMat,priorTask,'rows')',1); 275 | t=find(ismember(TaskMat,latterTask,'rows')',1); 276 | G=addedge(G,s,t); 277 | end 278 | end 279 | 280 | for i=1:agentNum 281 | seq=AgentTaskSequence{i,1}; 282 | task=AgentTaskCell{i,1}; 283 | num=AgentTaskNumVec(i,1); 284 | for j=1:num-1 285 | priorTask=task(seq(j,1),:); 286 | latterTask=task(seq(j+1,1),:); 287 | s=find(ismember(TaskMat,priorTask,'rows')',1); 288 | t=find(ismember(TaskMat,latterTask,'rows')',1); 289 | G=addedge(G,s,t); 290 | end 291 | end 292 | 293 | %plot(G); 294 | 295 | % remove all dummy tasks. 296 | H = rmnode(G,subtaskNum+1:subtaskNum+robotNum+agentNum); 297 | plot(H); 298 | 299 | [n,I] = toposort(H); 300 | 301 | 302 | %analysis this DAG 303 | deg = indegree(H); 304 | sourceNum=size(find(deg==0),1); 305 | 306 | criticalLength=0; 307 | while (numnodes(H)~=0) 308 | deg = indegree(H); 309 | indices = find(deg==0); 310 | H=rmnode(H,indices); 311 | criticalLength=criticalLength+1; 312 | end 313 | 314 | makespan=0; 315 | for i=1:robotNum 316 | mat=TimeCell{i,1}; 317 | sb=mat(end,6); 318 | makespan=max(makespan,sb); 319 | end 320 | disp(makespan); 321 | disp(totalRobotTravelTime); 322 | disp(totalAgentTravelTime); 323 | disp(totalRobotWaitTime); 324 | disp(totalAgentWaitTime); 325 | disp(sourceNum); 326 | disp(criticalLength); -------------------------------------------------------------------------------- /GA/rank2sequence.m: -------------------------------------------------------------------------------- 1 | function [RSeqCell,CSeqCell]= rank2sequence(RankCell) 2 | [m,n]=size(RankCell); 3 | RSeqCell=cell(m,n); 4 | CSeqCell=cell(m,n); 5 | TaskNumMat=zeros(m,n); 6 | for i=1:m 7 | for j=1:n 8 | TaskNumMat(i,j)=length(RankCell{i,j}); 9 | RSeqCell{i,j}=zeros(TaskNumMat(i,j),1); 10 | CSeqCell{i,j}=ones(TaskNumMat(i,j),1); 11 | end 12 | end 13 | 14 | for i=1:m 15 | len=sum(TaskNumMat(i,:)); 16 | row=zeros(1,len); 17 | temp = 1; 18 | for j=1:n 19 | row(1,temp:temp+TaskNumMat(i,j)-1)=RankCell{i,j}'; 20 | temp=temp+TaskNumMat(i,j); 21 | end 22 | [~,index]=sort(row); 23 | vector=1:len; 24 | vector(index)=vector; 25 | temp = 1; 26 | for j=1:n 27 | RSeqCell{i,j}=vector(1,temp:temp+TaskNumMat(i,j)-1)'; 28 | temp=temp+TaskNumMat(i,j); 29 | end 30 | end 31 | 32 | for j=1:n 33 | len=sum(TaskNumMat(:,j)); 34 | column=zeros(len,1); 35 | temp = 1; 36 | for i=1:m 37 | column(temp:temp+TaskNumMat(i,j)-1,1)=RankCell{i,j}; 38 | temp=temp+TaskNumMat(i,j); 39 | end 40 | [~,index]=sort(column); 41 | vector=(1:len)'; 42 | vector(index)=vector; 43 | temp = 1; 44 | for i=1:m 45 | CSeqCell{i,j}=vector(temp:temp+TaskNumMat(i,j)-1,1); 46 | temp=temp+TaskNumMat(i,j); 47 | end 48 | end 49 | 50 | 51 | end 52 | -------------------------------------------------------------------------------- /GA/sequence2rank.m: -------------------------------------------------------------------------------- 1 | function RankCell = sequence2rank(RSeqCell,CSeqCell) 2 | % prerequisites: Rseq and Cseq should be acyclic. 3 | [m,n]=size(RSeqCell); 4 | RankCell=cell(m,n); 5 | TaskCell=cell(m,n); 6 | TaskNumMat=zeros(m,n); 7 | totalTaskSum = 0; 8 | for i=1:m 9 | for j=1:n 10 | TaskNumMat(i,j)=length(RSeqCell{i,j}); 11 | RankCell{i,j}=zeros(TaskNumMat(i,j),1); 12 | TaskCell{i,j}=ones(TaskNumMat(i,j),1); 13 | end 14 | end 15 | totalTaskSum=sum(sum(TaskNumMat)); 16 | k=0; 17 | while (totalTaskSum>0) 18 | k=k+1; 19 | temp = 1; 20 | taskIndex = zeros(totalTaskSum,3); 21 | for i=1:m 22 | for j=1:n 23 | [r,~]=find(and(RSeqCell{i,j}==CSeqCell{i,j},RSeqCell{i,j}==1)==1); 24 | if size(r,1)~=0 25 | taskIndex(temp,:)=[i,j,r]; 26 | temp=temp+1; 27 | end 28 | end 29 | end 30 | sourceNum = sum(taskIndex(:,1)~=0); 31 | taskIndex=int32(taskIndex(1:sourceNum,:)); 32 | if sourceNum==0 33 | break; 34 | else 35 | for i=1:sourceNum 36 | tempVec = RankCell{taskIndex(i,1),taskIndex(i,2)}; 37 | tempVec(taskIndex(i,3),1)=k; 38 | RankCell{taskIndex(i,1),taskIndex(i,2)}=tempVec; 39 | end 40 | r=unique(taskIndex(:,1)); 41 | c=unique(taskIndex(:,2)); 42 | for i=1:length(r) 43 | for j=1:n 44 | RSeqCell{r(i,1),j}=RSeqCell{r(i,1),j}-1; 45 | end 46 | end 47 | for i=1:length(c) 48 | for j=1:m 49 | CSeqCell{j,c(i,1)}=CSeqCell{j,c(i,1)}-1; 50 | end 51 | end 52 | totalTaskSum=totalTaskSum-sourceNum; 53 | end 54 | end 55 | end %end of function -------------------------------------------------------------------------------- /GA/testMutationFasible.m: -------------------------------------------------------------------------------- 1 | A=cell(3,3); 2 | A{1,1}=2; 3 | A{1,2}=2; 4 | A{1,3}=4; 5 | A{2,1}=1; 6 | A{2,2}=1; 7 | A{2,3}=3; 8 | A{3,1}=4; 9 | A{3,2}=2; 10 | A{3,3}=3; 11 | B=ones(3); 12 | feasibleValidation(A,B,[1 2 1;2 2 1;2 3 1]); -------------------------------------------------------------------------------- /GA/testSeq2Rank.m: -------------------------------------------------------------------------------- 1 | clc; 2 | clear; 3 | 4 | %% test sequence2rank function 5 | A=cell(4,3); 6 | A{1,1}=[1,3,4]'; 7 | A{1,2}=5; 8 | A{1,3}=[2,6,7]'; 9 | A{2,1}=1; 10 | A{2,2}=[2,4,5]'; 11 | A{2,3}=3; 12 | A{3,1}=6; 13 | A{3,2}=1; 14 | A{3,3}=[2,3,4,5]'; 15 | A{4,1}=[2,4]'; 16 | A{4,2}=3; 17 | A{4,3}=1; 18 | 19 | B=cell(4,3); 20 | B{1,1}=[3,5,6]'; 21 | B{1,2}=6; 22 | B{1,3}=[4,8,9]'; 23 | B{2,1}=1; 24 | B{2,2}=[2,4,5]'; 25 | B{2,3}=3; 26 | B{3,1}=7; 27 | B{3,2}=1; 28 | B{3,3}=[2,5,6,7]'; 29 | B{4,1}=[2,4]'; 30 | B{4,2}=3; 31 | B{4,3}=1; 32 | 33 | %% test sequence2rank function 34 | C=sequence2rank(A,B); 35 | 36 | %% test rank2sequence function 37 | [D,E]=rank2sequence(C); 38 | 39 | %% test objective function 40 | P=cell(4,3); 41 | P{1,1}=[10,1,1]'; 42 | P{1,2}=9; 43 | P{1,3}=[1,3,4]'; 44 | P{2,1}=5; 45 | P{2,2}=[5,1,1]'; 46 | P{2,3}=10; 47 | P{3,1}=3; 48 | P{3,2}=5; 49 | P{3,3}=[5,1,1,9]'; 50 | P{4,1}=[5,1]'; 51 | P{4,2}=10; 52 | P{4,3}=5; 53 | 54 | global robotNum 55 | global agentNum 56 | global TaskNumMat 57 | robotNum=4; 58 | agentNum=3; 59 | TaskNumMat=[3 1 3;1 3 1;1 1 4;2 1 1]; 60 | 61 | CVec=[C{1,1};C{1,2};C{1,3};C{2,1};C{2,2};C{2,3};C{3,1};C{3,2};C{3,3};C{4,1};C{4,2};C{4,3}]; 62 | Cmax=H2TS_fitness2(CVec,P) 63 | 64 | -------------------------------------------------------------------------------- /GA/vec2cell.m: -------------------------------------------------------------------------------- 1 | function outputCell = vec2cell(colVec,taskNumMat) 2 | [m,n]=size(taskNumMat); 3 | outputCell=cell(m,n); 4 | if length(colVec)~=sum(sum(taskNumMat)) 5 | disp("dimension error!"); 6 | return; 7 | end 8 | 9 | temp=1; 10 | for i=1:m 11 | for j=1:n 12 | if taskNumMat(i,j)~=0 13 | outputCell{i,j}=colVec(temp:temp+taskNumMat(i,j)-1,1); 14 | temp=temp+taskNumMat(i,j); 15 | end 16 | end 17 | end 18 | 19 | end 20 | 21 | -------------------------------------------------------------------------------- /MILP/MILP.m: -------------------------------------------------------------------------------- 1 | clear; 2 | clc; 3 | load("../Instance.mat"); 4 | 5 | robotNum=size(RobotMat,1); 6 | agentNum=size(AgentMat,1); 7 | subtaskNum=size(TaskMat,1); 8 | 9 | %% Reorganize all tasks. 10 | RobotTaskCell = cell(robotNum,1); 11 | RobotTaskNumVec = zeros(robotNum,1); 12 | for i=1:robotNum 13 | task = TaskMat(TaskMat(:,1)==i,:); 14 | robot=RobotMat(i,:); 15 | dummyTask = [i 0 0 robot(1,1) robot(1,2) 0 0 0 0];%dummy task comes first 16 | RobotTaskCell{i,1}=[dummyTask;task]; 17 | RobotTaskNumVec(i,1) = size(task,1)+1; 18 | end 19 | 20 | AgentTaskCell = cell(agentNum,1); 21 | AgentTaskNumVec = zeros(agentNum,1); 22 | for i=1:agentNum 23 | task = TaskMat(TaskMat(:,2)==i,:); 24 | agent=AgentMat(i,:); 25 | dummyTask = [0 i 0 agent(1,1) agent(1,2) 0 0 0 0];%dummy task comes first 26 | AgentTaskCell{i,1}=[dummyTask;task]; 27 | AgentTaskNumVec(i,1)=size(task,1)+1; 28 | end 29 | 30 | %% Variable Definition and counting. 31 | %Cmax,S_ijk,X,Y,U_ijk,V_ijk 32 | % count tasks, continuous variables and binary variables. 33 | 34 | XNumVec = RobotTaskNumVec.^2; 35 | YNumVec = AgentTaskNumVec.^2; 36 | 37 | taskNumVec = zeros(robotNum,1); 38 | taskNumVec(:,1) = sum(BlockNumMat,2); 39 | 40 | vecLen = 1+3*subtaskNum+sum(XNumVec)+sum(YNumVec); 41 | M=10000; 42 | 43 | %% constraints 44 | Aineq=[]; 45 | bineq=[]; 46 | Aeq=[]; 47 | beq=[]; 48 | 49 | %constraint (1) 50 | A=zeros(subtaskNum,vecLen); 51 | b=zeros(subtaskNum,1); 52 | A(:,1)=-1; 53 | A(:,2:subtaskNum+1)=eye(subtaskNum); 54 | b(:,1)=-TaskMat(:,6)-getDistance(TaskMat(:,4),TaskMat(:,5),depot(1,1)*ones(subtaskNum,1),depot(1,2)*ones(subtaskNum,1)); 55 | Aineq=[Aineq;A]; 56 | bineq=[bineq;b]; 57 | 58 | %constraint (2). 59 | A=zeros(robotNum,vecLen); 60 | b=ones(robotNum,1); 61 | for i=1:robotNum 62 | indices=find(TaskMat(:,1)==i); 63 | for j=1:length(indices) 64 | idx = indices(j,1); 65 | A(i,1+subtaskNum+idx)=1; 66 | end 67 | end 68 | Aeq=[Aeq;A]; 69 | beq=[beq;b]; 70 | 71 | %constraint (3) 72 | A=zeros(agentNum,vecLen); 73 | b=ones(agentNum,1); 74 | for i=1:agentNum 75 | indices=find(TaskMat(:,2)==i); 76 | for j=1:length(indices) 77 | idx = indices(j,1); 78 | A(i,1+2*subtaskNum+idx)=1; 79 | end 80 | end 81 | Aeq=[Aeq;A]; 82 | beq=[beq;b]; 83 | 84 | %constraint (4)(5) 85 | for i=1:robotNum 86 | task = RobotTaskCell{i,1}; 87 | num = RobotTaskNumVec(i,1); 88 | %regard as a transportation problem. 89 | %each constraint is a [2*taskNum * taskNum^2] matrix 90 | A=zeros(2*num,vecLen); 91 | b=ones(2*num,1); 92 | 93 | if i==1 94 | tempXNum=0; 95 | else 96 | tempXNum=sum(XNumVec(1:i-1,1)); 97 | end 98 | 99 | for j=1:num 100 | colIndex = 1+3*subtaskNum+tempXNum+(j-1)*num; 101 | A(j,colIndex +1:colIndex+num)=ones(1,num); 102 | A(j,colIndex + j)=0; % delete self-loop 103 | A(j,colIndex + 1)=0; % delete dummy task 104 | 105 | % last task 106 | if j>1 107 | finalIndex = find(ismember(TaskMat,task(j,:),'rows')',1); 108 | finalIndex = 1+subtaskNum+finalIndex; 109 | A(j,finalIndex)=1; 110 | end 111 | 112 | A(num+1:2*num,colIndex +1:colIndex+num)=eye(num); 113 | A(num+j,colIndex+j)=0; % delete self-loop 114 | 115 | end 116 | 117 | A(num+1,:)=0; % delete dummy task 118 | b(num+1,:)=0; % delete dummy task 119 | Aeq=[Aeq;A]; 120 | beq=[beq;b]; 121 | 122 | end 123 | 124 | %constraint (6)(7) 125 | for i=1:agentNum 126 | task = AgentTaskCell{i,1}; 127 | num = AgentTaskNumVec(i,1); 128 | %regard as a transportation problem. 129 | %each constraint is a [2*taskNum * taskNum^2] mRobotix 130 | A=zeros(2*num,vecLen); 131 | b=ones(2*num,1); 132 | 133 | if i==1 134 | tempYNum=0; 135 | else 136 | tempYNum=sum(YNumVec(1:i-1,1)); 137 | end 138 | 139 | for j=1:num 140 | colIndex = 1+3*subtaskNum+sum(XNumVec)+tempYNum+(j-1)*num; 141 | A(j,colIndex +1:colIndex+num)=ones(1,num); 142 | A(j,colIndex + j)=0; % delete self-loop 143 | A(j,colIndex + 1)=0; % delete dummy task 144 | 145 | % last task 146 | if j>1 147 | finalIndex = find(ismember(TaskMat,task(j,:),'rows')',1); 148 | finalIndex = 1+2*subtaskNum+finalIndex; 149 | A(j,finalIndex)=1; 150 | end 151 | 152 | A(num+1:2*num,colIndex +1:colIndex+num)=eye(num); 153 | A(num+j,colIndex+j)=0; % delete self-loop 154 | end 155 | A(num+1,:)=0; % delete dummy task 156 | b(num+1,:)=0; % delete dummy task 157 | 158 | Aeq=[Aeq;A]; 159 | beq=[beq;b]; 160 | end 161 | 162 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 163 | 164 | % constraint (8) 165 | for i=1:robotNum 166 | task = RobotTaskCell{i,1}; 167 | num = RobotTaskNumVec(i,1); 168 | 169 | if i==1 170 | tempXNum=0; 171 | else 172 | tempXNum=sum(XNumVec(1:i-1,1)); 173 | end 174 | 175 | for j=1:num 176 | colIndex = 1+3*subtaskNum+tempXNum+(j-1)*num; 177 | A=zeros(num,vecLen); 178 | b=zeros(num,1); 179 | priorTask = task(j,:); 180 | 181 | if j==1 %dummy task 182 | index1=0; 183 | else 184 | index1=find(ismember(TaskMat,priorTask,'rows')',1); 185 | end 186 | 187 | for k=1:num 188 | %skip self loop and dummy task.k cannot be a dummy task. 189 | if k~=j && k~=1 190 | latterTask = task(k,:); 191 | index2=find(ismember(TaskMat,latterTask,'rows')',1); 192 | tempRow = zeros(1,vecLen); 193 | if index1~=0 194 | tempRow(1,1+index1) = 1; 195 | end 196 | tempRow(1,1+index2) = -1; 197 | tempRow(1,colIndex +k) = M; 198 | %fprintf("%d,%d\n",index1,index2); 199 | A(k,:) = tempRow; 200 | b(k,1) = M-priorTask(1,6)-getDistance(priorTask(1,4),priorTask(1,5),latterTask(1,4),latterTask(1,5)); 201 | end 202 | end 203 | Aineq=[Aineq;A]; 204 | bineq=[bineq;b]; 205 | end 206 | end 207 | 208 | % constraint (9) 209 | for i=1:agentNum 210 | task = AgentTaskCell{i,1}; 211 | num = AgentTaskNumVec(i,1); 212 | 213 | if i==1 214 | tempYNum=0; 215 | else 216 | tempYNum=sum(YNumVec(1:i-1,1)); 217 | end 218 | 219 | for j=1:num 220 | colIndex = 1+3*subtaskNum+sum(XNumVec)+tempYNum+(j-1)*num; 221 | A=zeros(num,vecLen); 222 | b=zeros(num,1); 223 | priorTask = task(j,:); 224 | 225 | if j==1 226 | index1=0; 227 | else 228 | index1=find(ismember(TaskMat,priorTask,'rows')',1); 229 | end 230 | 231 | for k=1:num 232 | %skip self loop and dummy task 233 | if k~=j && k~=1 234 | latterTask = task(k,:); 235 | index2=find(ismember(TaskMat,latterTask,'rows')',1); 236 | %fprintf("%d,%d\n",index1,index2); 237 | tempRow = zeros(1,vecLen); 238 | if index1~=0 239 | tempRow(1,1+index1) = 1; 240 | end 241 | tempRow(1,1+index2) = -1; 242 | tempRow(1,colIndex +k) = M; 243 | A(k,:) = tempRow; 244 | b(k,1) = M-priorTask(1,6)-alpha*getDistance(priorTask(1,4),priorTask(1,5),latterTask(1,4),latterTask(1,5)); 245 | end 246 | end 247 | Aineq=[Aineq;A]; 248 | bineq=[bineq;b]; 249 | end 250 | end 251 | 252 | %% Bounds 253 | intcon=1+subtaskNum+1:vecLen; 254 | lb = zeros(vecLen,1); 255 | ub = inf(vecLen,1); 256 | ub(1+subtaskNum+1:vecLen,1)=1; 257 | 258 | %% Objective 259 | f=zeros(vecLen,1); 260 | f(1,1)=1; 261 | %% MILP 262 | opts = optimoptions('intlinprog','Display','iter','Heuristics','round-diving','IPPreprocess','none'); 263 | tic; 264 | [solutionMILP,fval,exitflag,output] = intlinprog(f,intcon,Aineq,bineq,Aeq,beq,lb,ub,opts); 265 | toc; 266 | solutionMILP=int32(solutionMILP); 267 | disp(solutionMILP); 268 | fprintf('optimal makespan:%f\n',fval); 269 | fprintf('robot number:%d,agent number:%d,task number:%f\n',robotNum,agentNum,subtaskNum); 270 | fprintf('varible size:%d, continuous variable: %d, binary variable:%d\n',vecLen,1+subtaskNum,vecLen-1-subtaskNum); 271 | fprintf('equality constraint size:%d\n',size(Aeq,1)); 272 | fprintf('inequality constraint size:%d\n',size(Aineq,1)); 273 | 274 | save('solutionMILP.mat','solutionMILP'); 275 | 276 | -------------------------------------------------------------------------------- /MILP/Untitled.m: -------------------------------------------------------------------------------- 1 | 2 | solutionMILP=double(solutionMILP); 3 | Aeq2=Aeq(8:end,:); 4 | Aeq2=Aeq2(11:22,:) 5 | sb=size(Aeq2,1); 6 | out=zeros(sb,1); 7 | for i=1:sb 8 | sb(i,1)=Aeq2(i,:)*solutionMILP; 9 | end 10 | -------------------------------------------------------------------------------- /MILP/getDistance.m: -------------------------------------------------------------------------------- 1 | function distance = getDistance(r1,c1,r2,c2) 2 | distance = abs(r1-r2)+abs(c1-c2); 3 | end -------------------------------------------------------------------------------- /MILP/plotGantt.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/labimage/Multi-robot-Task-Allocation/2a4dd4da5fb3fc46c69608abfcb6b60bdc5c837e/MILP/plotGantt.m -------------------------------------------------------------------------------- /MILP/plotSolutionMILP.m: -------------------------------------------------------------------------------- 1 | clear; 2 | clc; 3 | load("../Instance.mat"); 4 | 5 | figure('position',[400,10,1000,1000]); 6 | axis([0 80 0 80]); 7 | axis equal; 8 | axis manual; 9 | 10 | robotNum=size(RobotMat,1); 11 | agentNum=size(AgentMat,1); 12 | subtaskNum=size(TaskMat,1); 13 | 14 | ColorMat=zeros(robotNum,3); 15 | ColorMat(1,:)=[1 0 0]; 16 | ColorMat(1,:)=[0 1 0]; 17 | ColorMat(1,:)=[0 0 1]; 18 | 19 | 20 | 21 | %% plot depot and stations 22 | plot(StationMat(:,1),StationMat(:,2),'LineStyle','none','Color',[0.7 0.7 0.7],'marker','.','markersize',20); 23 | hold on; 24 | plot(depot(1,1),depot(1,2),'LineStyle','none','Color',[0 0 0],'marker','.','markersize',20); 25 | hold on; 26 | 27 | % plot(100,100,'LineStyle','none','Color',[1 1 1],'marker','.','markersize',1); 28 | %pause(5); 29 | 30 | %% plot cliques 31 | for i=1:agentNum 32 | Clique = CliqueCell{i,1}; 33 | x=Clique(:,1); 34 | y=Clique(:,2); 35 | dt = delaunayTriangulation(x,y); 36 | k = convexHull(dt); 37 | plot(x,y,'LineStyle','none', 'Color',[0.7 0.7 0.7],'marker','.','markersize',20); 38 | hold on; 39 | plot(x(k), y(k), 'Color',[0.9 0.9 0.9]); 40 | hold on; 41 | end 42 | 43 | %pause(5); 44 | 45 | %% plot robots 46 | plot(RobotMat(:,1), RobotMat(:,2),'LineStyle','none','marker','o', 'Color',[0 0 0],'markersize',13,'MarkerFaceColor','k'); 47 | text(RobotMat(:,1)+1,RobotMat(:,2),'TR1,TR2,TR3'); 48 | hold on; 49 | plot(AgentMat(:,1), AgentMat(:,2),'LineStyle','none','marker','s', 'Color',[0 0 0],'markersize',10,'MarkerFaceColor','k'); 50 | for i=1:agentNum 51 | txt=sprintf('SR%d',i); 52 | text(AgentMat(i,1)+1,AgentMat(i,2),txt); 53 | end 54 | hold on; 55 | 56 | %pause(5); 57 | 58 | %% plot tasks 59 | ColorMat = [1 0 0;0 1 0;0 0 1;1 1 0;1 0 1;1 1 0]; 60 | 61 | for i=1:subtaskNum 62 | subtask=TaskMat(i,:); 63 | plot(subtask(1,4),subtask(1,5),'LineStyle','none','Color',ColorMat(subtask(1,1),:),'marker','.','MarkerFaceColor',ColorMat(subtask(1,1),:),'markersize',20); 64 | hold on; 65 | text(subtask(1,4)-0.7,subtask(1,5)-1,num2str(subtask(1,6))); 66 | end 67 | 68 | %pause(5); 69 | 70 | %% plot optimal solutions 71 | load('solutionMILP.mat'); 72 | solution=solutionMILP; 73 | %% Reorganize all tasks. 74 | RobotTaskCell = cell(robotNum,1); 75 | RobotTaskNumVec = zeros(robotNum,1); 76 | for i=1:robotNum 77 | task = TaskMat(TaskMat(:,1)==i,:); 78 | robot=RobotMat(i,:); 79 | dummyTask = [i 0 0 robot(1,1) robot(1,2) 0 0 0 0];%dummy task comes first 80 | RobotTaskCell{i,1}=[dummyTask;task]; 81 | RobotTaskNumVec(i,1) = size(task,1)+1; 82 | end 83 | 84 | AgentTaskCell = cell(agentNum,1); 85 | AgentTaskNumVec = zeros(agentNum,1); 86 | for i=1:agentNum 87 | task = TaskMat(TaskMat(:,2)==i,:); 88 | agent=AgentMat(i,:); 89 | dummyTask = [0 i 0 agent(1,1) agent(1,2) 0 0 0 0];%dummy task comes first 90 | AgentTaskCell{i,1}=[dummyTask;task]; 91 | AgentTaskNumVec(i,1)=size(task,1)+1; 92 | end 93 | 94 | XNumVec = RobotTaskNumVec.^2; 95 | YNumVec = AgentTaskNumVec.^2; 96 | 97 | taskNumVec = zeros(robotNum,1); 98 | taskNumVec(:,1) = sum(BlockNumMat,2); 99 | 100 | vecLen = 1+3*subtaskNum+sum(XNumVec)+sum(YNumVec); 101 | M=10000; 102 | 103 | %% Construct task sequence. 104 | RobotTaskSequence = cell(robotNum,1); 105 | for i=1:robotNum 106 | task = RobotTaskCell{i,1}; 107 | num = RobotTaskNumVec(i,1); 108 | seq = zeros(num,1); 109 | 110 | if i==1 111 | tempXNum=0; 112 | else 113 | tempXNum=sum(XNumVec(1:i-1,1)); 114 | end 115 | 116 | for j=1:num 117 | colIndex = 1+3*subtaskNum+tempXNum+(j-1)*num; 118 | tempVec = solution(colIndex+1:colIndex+num,1); 119 | if ~isempty(find(tempVec == 1, 1)) 120 | rowIndex = find(tempVec == 1); 121 | else 122 | rowIndex = 0; 123 | end 124 | seq(j,1) = rowIndex; 125 | end 126 | seq2 = zeros(num,1); 127 | seq2(1,1) = 1; 128 | 129 | for j=1:num-1 130 | seq2(j+1,1) = seq(seq2(j,1),1); 131 | end 132 | 133 | RobotTaskSequence{i,1}=seq2; 134 | end 135 | 136 | AgentTaskSequence = cell(agentNum,1); 137 | for i=1:agentNum 138 | task = AgentTaskCell{i,1}; 139 | num = AgentTaskNumVec(i,1); 140 | seq = zeros(num,1); 141 | 142 | if i==1 143 | tempYNum=0; 144 | else 145 | tempYNum=sum(YNumVec(1:i-1,1)); 146 | end 147 | 148 | for j=1:num 149 | colIndex = 1+3*subtaskNum+sum(XNumVec)+tempYNum+(j-1)*num; 150 | tempVec = solution(colIndex+1:colIndex+num,1); 151 | if ~isempty(find(tempVec == 1, 1)) 152 | rowIndex = find(tempVec == 1); 153 | else 154 | rowIndex = 0; 155 | end 156 | seq(j,1) = rowIndex; 157 | end 158 | 159 | seq2 = zeros(num,1); 160 | seq2(1,1) = 1; 161 | for j=1:num-1 162 | seq2(j+1,1) = seq(seq2(j,1),1); 163 | end 164 | 165 | AgentTaskSequence{i,1}=seq2; 166 | end 167 | 168 | %% plot routes. 169 | hold on; 170 | for i=1:robotNum 171 | robot = RobotMat(i,:); 172 | seq = RobotTaskSequence{i,1}; 173 | task = RobotTaskCell{i,1}; 174 | num = RobotTaskNumVec(i,1); 175 | for j=0:num 176 | if j==0 177 | priorLocation = robot(1,1:2); 178 | else 179 | priorLocation = task(seq(j,1),4:5); 180 | end 181 | if j~=num 182 | latterLocation = task(seq(j+1,1),4:5); 183 | else 184 | latterLocation = depot; 185 | end 186 | line([priorLocation(1,1),latterLocation(1,1)],[priorLocation(1,2),latterLocation(1,2)],'color',ColorMat(i,:),'linestyle','-'); 187 | %pause(0.5); 188 | end 189 | %pause(1); 190 | end 191 | 192 | hold on; 193 | %pause(5); 194 | 195 | for i=1:agentNum 196 | agent = AgentMat(i,:); 197 | seq = AgentTaskSequence{i,1}; 198 | task = AgentTaskCell{i,1}; 199 | num = AgentTaskNumVec(i,1); 200 | for j=0:num-1 201 | if j==0 202 | priorLocation = agent(1,1:2); 203 | else 204 | priorLocation = task(seq(j,1),4:5); 205 | end 206 | latterLocation = task(seq(j+1,1),4:5); 207 | line([priorLocation(1,1),latterLocation(1,1)],[priorLocation(1,2),latterLocation(1,2)],'color',[0 0 0],'linestyle','--'); 208 | %pause(0.5); 209 | end 210 | %pause(1); 211 | end 212 | 213 | %pause(3); 214 | 215 | %% plot Gantt chart and statistics 216 | totalRobotTravelTime = 0; 217 | totalRobotWaitTime = 0; 218 | totalAgentTravelTime = 0; 219 | totalAgentWaitTime = 0; 220 | 221 | figure(2); 222 | TimeCell=cell(robotNum+agentNum,1); 223 | TaskIndexSequenceCell=cell(robotNum+agentNum,1); 224 | priorTotalNum = 0; 225 | for i=1:robotNum 226 | seq = RobotTaskSequence{i,1}; 227 | task = RobotTaskCell{i,1}; 228 | num = RobotTaskNumVec(i,1); 229 | timeMat = zeros(num,6); 230 | tempTime = 0; 231 | for j=1:num 232 | colIndex = 1+priorTotalNum; 233 | if j==num 234 | currentTask = task(1,:); 235 | else 236 | currentTask = task(seq(j+1,1),:); 237 | end 238 | priorTask = task(seq(j,1),:); 239 | travelTime = getDistance(priorTask(1,4),priorTask(1,5),currentTask(1,4),currentTask(1,5)); 240 | 241 | if j==num 242 | startTime = 0; 243 | else 244 | index=find(ismember(TaskMat,currentTask,'rows')',1); 245 | startTime = solution(1+index,1); 246 | end 247 | processTime = currentTask(1,6); 248 | time1 = tempTime; 249 | time2 = time1+travelTime; 250 | time3 = time2; 251 | time4 = startTime; 252 | time5 = time4; 253 | time6 = time5+processTime; 254 | tempTime = time6; 255 | 256 | if startTime == 0 257 | time4 = time3; 258 | time5 = time4; 259 | time6 = time5; 260 | end 261 | 262 | timeMat(j,:) = [time1 time2 time3 time4 time5 time6]; 263 | taskIndexMat(j,:) = currentTask(1,1:3); 264 | 265 | %statistics 266 | totalRobotTravelTime = totalRobotTravelTime+travelTime; 267 | totalRobotWaitTime = totalRobotWaitTime+time4-time3; 268 | end 269 | 270 | TimeCell{i,1}=timeMat; 271 | TaskIndexSequenceCell{i,1}=taskIndexMat; 272 | priorTotalNum = priorTotalNum + num-1; 273 | end 274 | 275 | for i=1:agentNum 276 | seq = AgentTaskSequence{i,1}; 277 | task = AgentTaskCell{i,1}; 278 | num = AgentTaskNumVec(i,1); 279 | 280 | timeMat = zeros(num-1,6); 281 | taskIndexMat = zeros(num-1,3); 282 | 283 | tempTime = 0; 284 | for j=1:num-1 285 | currentTask = task(seq(j+1,1),:); 286 | priorTask = task(seq(j,1),:); 287 | travelTime = alpha*getDistance(priorTask(1,4),priorTask(1,5),currentTask(1,4),currentTask(1,5)); 288 | index=find(ismember(TaskMat,currentTask,'rows')',1); 289 | startTime = solution(1+index,1); 290 | 291 | processTime = currentTask(1,6); 292 | time1 = tempTime; 293 | time2 = time1+travelTime; 294 | time3 = time2; 295 | time4 = startTime; 296 | time5 = time4; 297 | time6 = time5+processTime; 298 | tempTime = time6; 299 | 300 | if startTime == 0 301 | time4 = time3; 302 | time5 = time4; 303 | time6 = time5; 304 | end 305 | 306 | timeMat(j,:) = [time1 time2 time3 time4 time5 time6]; 307 | taskIndexMat(j,:) = currentTask(1,1:3); 308 | 309 | %statistics 310 | totalAgentTravelTime = totalAgentTravelTime+travelTime; 311 | totalAgentWaitTime = totalAgentWaitTime+time4-time3; 312 | end 313 | 314 | TimeCell{robotNum+i,1}=timeMat; 315 | TaskIndexSequenceCell{robotNum+i,1}=taskIndexMat; 316 | end 317 | 318 | plotGantt(TimeCell,TaskIndexSequenceCell); 319 | 320 | %pause(5); 321 | 322 | %% plot Graph 323 | figure(3); 324 | G=digraph; 325 | 326 | nodeName = cell(1,sum(RobotTaskNumVec)+agentNum); 327 | 328 | for i=1:subtaskNum 329 | subtask=TaskMat(i,:); 330 | nodeName{1,i}=strcat('t(',num2str(subtask(1,1)),',',num2str(subtask(1,2)),',',num2str(subtask(1,3)),')'); 331 | end 332 | 333 | for i=1:robotNum+agentNum 334 | nodeName{1,subtaskNum+i}=strcat('t(',num2str(i),',',num2str(0),')'); 335 | end 336 | 337 | G = addnode(G,nodeName'); 338 | 339 | for i=1:robotNum 340 | seq=RobotTaskSequence{i,1}; 341 | task=RobotTaskCell{i,1}; 342 | num=RobotTaskNumVec(i,1); 343 | for j=1:num-1 344 | priorTask=task(seq(j,1),:); 345 | latterTask=task(seq(j+1,1),:); 346 | s=find(ismember(TaskMat,priorTask,'rows')',1); 347 | t=find(ismember(TaskMat,latterTask,'rows')',1); 348 | G=addedge(G,s,t); 349 | end 350 | end 351 | 352 | for i=1:agentNum 353 | seq=AgentTaskSequence{i,1}; 354 | task=AgentTaskCell{i,1}; 355 | num=AgentTaskNumVec(i,1); 356 | for j=1:num-1 357 | priorTask=task(seq(j,1),:); 358 | latterTask=task(seq(j+1,1),:); 359 | s=find(ismember(TaskMat,priorTask,'rows')',1); 360 | t=find(ismember(TaskMat,latterTask,'rows')',1); 361 | G=addedge(G,s,t); 362 | end 363 | end 364 | 365 | %plot(G); 366 | 367 | % remove all dummy tasks. 368 | H = rmnode(G,subtaskNum+1:subtaskNum+robotNum+agentNum); 369 | plot(H); 370 | 371 | %analysis this DAG 372 | deg = indegree(H); 373 | sourceNum=size(find(deg==0),1); 374 | 375 | criticalLength=0; 376 | while (numnodes(H)~=0) 377 | deg = indegree(H); 378 | indices = find(deg==0); 379 | H=rmnode(H,indices); 380 | criticalLength=criticalLength+1; 381 | end 382 | 383 | 384 | 385 | -------------------------------------------------------------------------------- /MILP/solutionMILP.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/labimage/Multi-robot-Task-Allocation/2a4dd4da5fb3fc46c69608abfcb6b60bdc5c837e/MILP/solutionMILP.mat -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Multi-robot-Task-Allocation 2 | Multi-robot Task Allocation for Heterogeneous Teams of Two Types with Complex-schedule Constraints. 3 | Three centralized methods, mixed linear programming, genetic algorithm and a heuristic are used. 4 | Results are shown by Gantt Charts(time domain),routes(space domain) and directed acyclic graphs(logical domain). 5 | -------------------------------------------------------------------------------- /SCP/SCP.m: -------------------------------------------------------------------------------- 1 | clear; 2 | clc; 3 | 4 | load('../Instance.mat'); 5 | 6 | totalTaskNum = sum(sum(BlockNumMat)); 7 | robotNum=size(RobotMat,1); 8 | agentNum=size(AgentMat,1); 9 | %% generate TaskCell TaskIndexCell TaskNumMat 10 | 11 | BlockTaskCell=cell(robotNum,agentNum); 12 | for i=1:robotNum 13 | for j=1:agentNum 14 | index = find(and(TaskMat(:,1)==i,TaskMat(:,2)==j)); 15 | if ~isempty(index) 16 | BlockTaskCell{i,j} = TaskMat(index,:); 17 | else 18 | BlockTaskCell{i,j}=[]; 19 | end 20 | end 21 | end 22 | 23 | RobotTaskCell = cell(robotNum,1); 24 | RobotTaskNumVec = zeros(robotNum,1); 25 | for i=1:robotNum 26 | task = TaskMat(TaskMat(:,1)==i,:); 27 | robot=RobotMat(i,:); 28 | dummyTask = [i 0 0 robot(1,1) robot(1,2) 0 0 0 0];%dummy task comes first 29 | RobotTaskCell{i,1}=[dummyTask;task]; 30 | RobotTaskNumVec(i,1) = size(task,1)+1; 31 | end 32 | 33 | AgentTaskCell = cell(agentNum,1); 34 | AgentTaskNumVec = zeros(agentNum,1); 35 | for i=1:agentNum 36 | task = TaskMat(TaskMat(:,2)==i,:); 37 | agent=AgentMat(i,:); 38 | dummyTask = [0 i 0 agent(1,1) agent(1,2) 0 0 0 0];%dummy task comes first 39 | AgentTaskCell{i,1}=[dummyTask;task]; 40 | AgentTaskNumVec(i,1)=size(task,1)+1; 41 | end 42 | 43 | %% 44 | RobotTaskSequence = cell(robotNum,1); 45 | AgentTaskSequence = cell(agentNum,1); 46 | 47 | %% initialization 48 | for i=1:robotNum 49 | RobotTaskSequence{i,1}=[1]; 50 | end 51 | for j=1:agentNum 52 | AgentTaskSequence{j,1}=[1]; 53 | end 54 | tic; 55 | StartTimeVec=zeros(totalTaskNum); 56 | iteration = 1; 57 | scheduledTaskVec=TaskMat(:,9); 58 | while(~isempty(find(scheduledTaskVec==0, 1))) 59 | %% MILP 60 | %variable: 61 | %1-totalTaskNum:task selection binary variable 62 | %totalTaskNum+1:makespan 63 | selectVec=taskSelection(BlockNumMat,TaskMat,RobotMat,AgentMat,alpha); 64 | indices = find(selectVec==1); 65 | 66 | tasks = TaskMat(indices,:); 67 | for i=1:size(tasks,1) 68 | task = tasks(i,:); 69 | robotId = task(1,1); 70 | agentId = task(1,2); 71 | robot = RobotMat(robotId,:); 72 | agent = AgentMat(agentId,:); 73 | index1 = find(ismember(RobotTaskCell{robotId,1},task,'rows')',1); 74 | index2 = find(ismember(AgentTaskCell{agentId,1},task,'rows')',1); 75 | RobotTaskSequence{robotId,1}=[RobotTaskSequence{robotId,1};index1]; 76 | AgentTaskSequence{agentId,1}=[AgentTaskSequence{agentId,1};index2]; 77 | time1=robot(1,3)+getDistance(robot(1,1),robot(1,2),task(1,4),task(1,5)); 78 | time2=agent(1,3)+alpha*getDistance(agent(1,1),agent(1,2),task(1,4),task(1,5)); 79 | ctime=max(time1,time2); 80 | %update robots' status 81 | robot = [task(1,4) task(1,5) ctime+task(1,6) 0]; 82 | agent = [task(1,4) task(1,5) ctime+task(1,6) 0]; 83 | RobotMat(robotId,:) = robot; 84 | AgentMat(agentId,:) = agent; 85 | %update task start times. 86 | TaskMat(indices(i,1),8)=ctime; 87 | end 88 | 89 | %mark finished tasks. 90 | TaskMat(indices,9)=1; 91 | 92 | %update robot finish flag. 93 | for i=1:robotNum 94 | tasks=TaskMat(TaskMat(:,1)==i,:); 95 | vec = tasks(:,9); 96 | if isempty(find(vec==0, 1)) 97 | RobotMat(i,4)=1; 98 | end 99 | end 100 | 101 | %update agent finish flag. 102 | for i=1:agentNum 103 | tasks=TaskMat(TaskMat(:,2)==i,:); 104 | vec = tasks(:,9); 105 | if isempty(find(vec==0, 1)) 106 | AgentMat(i,4)=1; 107 | end 108 | end 109 | 110 | iteration = iteration+1; 111 | scheduledTaskVec=TaskMat(:,9); 112 | end 113 | toc; 114 | StartTimeVec=TaskMat(:,8); 115 | 116 | save('solutionSCP.mat','RobotTaskSequence','AgentTaskSequence','StartTimeVec'); -------------------------------------------------------------------------------- /SCP/getDistance.m: -------------------------------------------------------------------------------- 1 | function distance = getDistance(r1,c1,r2,c2) 2 | distance = abs(r1-r2)+abs(c1-c2); 3 | end -------------------------------------------------------------------------------- /SCP/linear2rcd.m: -------------------------------------------------------------------------------- 1 | function [r, c, d] = linear2rcd(taskNumMat,linearLoc) 2 | [robotNum,agentNum]=size(taskNumMat); 3 | sum=0; 4 | for i=1:robotNum 5 | for j=1:agentNum 6 | if ~isempty(taskNumMat(i,j)) 7 | for k=1:taskNumMat(i,j) 8 | sum=sum+1; 9 | if sum==linearLoc 10 | r=i; 11 | c=j; 12 | d=k; 13 | return; 14 | end 15 | 16 | end 17 | end 18 | 19 | end 20 | end 21 | 22 | 23 | end 24 | 25 | -------------------------------------------------------------------------------- /SCP/plotGantt.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/labimage/Multi-robot-Task-Allocation/2a4dd4da5fb3fc46c69608abfcb6b60bdc5c837e/SCP/plotGantt.m -------------------------------------------------------------------------------- /SCP/plotSolutionSCP.m: -------------------------------------------------------------------------------- 1 | clear; 2 | clc; 3 | load("../Instance.mat"); 4 | 5 | figure('position',[400,10,1000,1000]); 6 | axis([0 80 0 80]); 7 | axis equal; 8 | axis manual; 9 | 10 | robotNum=size(RobotMat,1); 11 | agentNum=size(AgentMat,1); 12 | subtaskNum=size(TaskMat,1); 13 | 14 | ColorMat=zeros(robotNum,3); 15 | ColorMat(1,:)=[1 0 0]; 16 | ColorMat(1,:)=[0 1 0]; 17 | ColorMat(1,:)=[0 0 1]; 18 | 19 | %% plot depot and stations 20 | plot(StationMat(:,1),StationMat(:,2),'LineStyle','none','Color',[0.7 0.7 0.7],'marker','.','markersize',20); 21 | hold on; 22 | plot(depot(1,1),depot(1,2),'LineStyle','none','Color',[0 0 0],'marker','.','markersize',20); 23 | hold on; 24 | 25 | % plot(100,100,'LineStyle','none','Color',[1 1 1],'marker','.','markersize',1); 26 | %pause(5); 27 | 28 | %% plot cliques 29 | for i=1:agentNum 30 | Clique = CliqueCell{i,1}; 31 | x=Clique(:,1); 32 | y=Clique(:,2); 33 | dt = delaunayTriangulation(x,y); 34 | k = convexHull(dt); 35 | plot(x,y,'LineStyle','none', 'Color',[0.7 0.7 0.7],'marker','.','markersize',20); 36 | hold on; 37 | plot(x(k), y(k), 'Color',[0.9 0.9 0.9]); 38 | hold on; 39 | end 40 | 41 | %pause(5); 42 | 43 | %% plot robots 44 | plot(RobotMat(:,1), RobotMat(:,2),'LineStyle','none','marker','o', 'Color',[0 0 0],'markersize',13,'MarkerFaceColor','k'); 45 | text(RobotMat(:,1)+1,RobotMat(:,2),'TR1,TR2,TR3'); 46 | hold on; 47 | plot(AgentMat(:,1), AgentMat(:,2),'LineStyle','none','marker','s', 'Color',[0 0 0],'markersize',10,'MarkerFaceColor','k'); 48 | for i=1:agentNum 49 | txt=sprintf('SR%d',i); 50 | text(AgentMat(i,1)+1,AgentMat(i,2),txt); 51 | end 52 | hold on; 53 | 54 | %pause(5); 55 | 56 | %% plot tasks 57 | ColorMat = [1 0 0;0 1 0;0 0 1;1 1 0;1 0 1;1 1 0]; 58 | 59 | for i=1:subtaskNum 60 | subtask=TaskMat(i,:); 61 | plot(subtask(1,4),subtask(1,5),'LineStyle','none','Color',ColorMat(subtask(1,1),:),'marker','.','MarkerFaceColor',ColorMat(subtask(1,1),:),'markersize',20); 62 | hold on; 63 | text(subtask(1,4)-0.7,subtask(1,5)-1,num2str(subtask(1,6))); 64 | end 65 | 66 | %pause(5); 67 | 68 | %% plot optimal solutions 69 | load('solutionSCP.mat'); 70 | %% Reorganize all tasks. 71 | RobotTaskCell = cell(robotNum,1); 72 | RobotTaskNumVec = zeros(robotNum,1); 73 | for i=1:robotNum 74 | task = TaskMat(TaskMat(:,1)==i,:); 75 | robot=RobotMat(i,:); 76 | dummyTask = [i 0 0 robot(1,1) robot(1,2) 0 0 0 0];%dummy task comes first 77 | RobotTaskCell{i,1}=[dummyTask;task]; 78 | RobotTaskNumVec(i,1) = size(task,1)+1; 79 | end 80 | 81 | AgentTaskCell = cell(agentNum,1); 82 | AgentTaskNumVec = zeros(agentNum,1); 83 | for i=1:agentNum 84 | task = TaskMat(TaskMat(:,2)==i,:); 85 | agent=AgentMat(i,:); 86 | dummyTask = [0 i 0 agent(1,1) agent(1,2) 0 0 0 0];%dummy task comes first 87 | AgentTaskCell{i,1}=[dummyTask;task]; 88 | AgentTaskNumVec(i,1)=size(task,1)+1; 89 | end 90 | 91 | taskNumVec = zeros(robotNum,1); 92 | taskNumVec(:,1) = sum(BlockNumMat,2); 93 | 94 | %% plot routes. 95 | hold on; 96 | for i=1:robotNum 97 | robot = RobotMat(i,:); 98 | seq = RobotTaskSequence{i,1}; 99 | task = RobotTaskCell{i,1}; 100 | num = RobotTaskNumVec(i,1); 101 | for j=0:num 102 | if j==0 103 | priorLocation = robot(1,1:2); 104 | else 105 | priorLocation = task(seq(j,1),4:5); 106 | end 107 | if j~=num 108 | latterLocation = task(seq(j+1,1),4:5); 109 | else 110 | latterLocation = depot; 111 | end 112 | line([priorLocation(1,1),latterLocation(1,1)],[priorLocation(1,2),latterLocation(1,2)],'color',ColorMat(i,:),'linestyle','-'); 113 | %pause(0.5); 114 | end 115 | %pause(1); 116 | end 117 | 118 | hold on; 119 | %pause(5); 120 | 121 | for i=1:agentNum 122 | agent = AgentMat(i,:); 123 | seq = AgentTaskSequence{i,1}; 124 | task = AgentTaskCell{i,1}; 125 | num = AgentTaskNumVec(i,1); 126 | for j=0:num-1 127 | if j==0 128 | priorLocation = agent(1,1:2); 129 | else 130 | priorLocation = task(seq(j,1),4:5); 131 | end 132 | latterLocation = task(seq(j+1,1),4:5); 133 | line([priorLocation(1,1),latterLocation(1,1)],[priorLocation(1,2),latterLocation(1,2)],'color',[0 0 0],'linestyle','--'); 134 | %pause(0.5); 135 | end 136 | %pause(1); 137 | end 138 | 139 | %pause(3); 140 | 141 | %% plot Gantt chart and statistics 142 | totalRobotTravelTime = 0; 143 | totalRobotWaitTime = 0; 144 | totalAgentTravelTime = 0; 145 | totalAgentWaitTime = 0; 146 | 147 | solution=[0;StartTimeVec]; 148 | 149 | figure(2); 150 | TimeCell=cell(robotNum+agentNum,1); 151 | TaskIndexSequenceCell=cell(robotNum+agentNum,1); 152 | priorTotalNum = 0; 153 | for i=1:robotNum 154 | seq = RobotTaskSequence{i,1}; 155 | task = RobotTaskCell{i,1}; 156 | num = RobotTaskNumVec(i,1); 157 | timeMat = zeros(num,6); 158 | tempTime = 0; 159 | for j=1:num 160 | colIndex = 1+priorTotalNum; 161 | if j==num 162 | currentTask = task(1,:); 163 | else 164 | currentTask = task(seq(j+1,1),:); 165 | end 166 | priorTask = task(seq(j,1),:); 167 | travelTime = getDistance(priorTask(1,4),priorTask(1,5),currentTask(1,4),currentTask(1,5)); 168 | 169 | if j==num 170 | startTime = 0; 171 | else 172 | index=find(ismember(TaskMat,currentTask,'rows')',1); 173 | startTime = solution(1+index,1); 174 | end 175 | processTime = currentTask(1,6); 176 | time1 = tempTime; 177 | time2 = time1+travelTime; 178 | time3 = time2; 179 | time4 = startTime; 180 | time5 = time4; 181 | time6 = time5+processTime; 182 | tempTime = time6; 183 | 184 | if startTime == 0 185 | time4 = time3; 186 | time5 = time4; 187 | time6 = time5; 188 | end 189 | 190 | timeMat(j,:) = [time1 time2 time3 time4 time5 time6]; 191 | taskIndexMat(j,:) = currentTask(1,1:3); 192 | 193 | %statistics 194 | totalRobotTravelTime = totalRobotTravelTime+travelTime; 195 | totalRobotWaitTime = totalRobotWaitTime+time4-time3; 196 | end 197 | 198 | TimeCell{i,1}=timeMat; 199 | TaskIndexSequenceCell{i,1}=taskIndexMat; 200 | priorTotalNum = priorTotalNum + num-1; 201 | end 202 | 203 | for i=1:agentNum 204 | seq = AgentTaskSequence{i,1}; 205 | task = AgentTaskCell{i,1}; 206 | num = AgentTaskNumVec(i,1); 207 | 208 | timeMat = zeros(num-1,6); 209 | taskIndexMat = zeros(num-1,3); 210 | 211 | tempTime = 0; 212 | for j=1:num-1 213 | currentTask = task(seq(j+1,1),:); 214 | priorTask = task(seq(j,1),:); 215 | travelTime = alpha*getDistance(priorTask(1,4),priorTask(1,5),currentTask(1,4),currentTask(1,5)); 216 | index=find(ismember(TaskMat,currentTask,'rows')',1); 217 | startTime = solution(1+index,1); 218 | 219 | processTime = currentTask(1,6); 220 | time1 = tempTime; 221 | time2 = time1+travelTime; 222 | time3 = time2; 223 | time4 = startTime; 224 | time5 = time4; 225 | time6 = time5+processTime; 226 | tempTime = time6; 227 | 228 | if startTime == 0 229 | time4 = time3; 230 | time5 = time4; 231 | time6 = time5; 232 | end 233 | 234 | timeMat(j,:) = [time1 time2 time3 time4 time5 time6]; 235 | taskIndexMat(j,:) = currentTask(1,1:3); 236 | 237 | %statistics 238 | totalAgentTravelTime = totalAgentTravelTime+travelTime; 239 | totalAgentWaitTime = totalAgentWaitTime+time4-time3; 240 | end 241 | 242 | TimeCell{robotNum+i,1}=timeMat; 243 | TaskIndexSequenceCell{robotNum+i,1}=taskIndexMat; 244 | end 245 | 246 | plotGantt(TimeCell,TaskIndexSequenceCell); 247 | 248 | %pause(5); 249 | 250 | %% plot Graph 251 | figure(3); 252 | G=digraph; 253 | 254 | nodeName = cell(1,sum(RobotTaskNumVec)+agentNum); 255 | 256 | for i=1:subtaskNum 257 | subtask=TaskMat(i,:); 258 | nodeName{1,i}=strcat('t(',num2str(subtask(1,1)),',',num2str(subtask(1,2)),',',num2str(subtask(1,3)),')'); 259 | end 260 | 261 | for i=1:robotNum+agentNum 262 | nodeName{1,subtaskNum+i}=strcat('t(',num2str(i),',',num2str(0),')'); 263 | end 264 | 265 | G = addnode(G,nodeName'); 266 | 267 | for i=1:robotNum 268 | seq=RobotTaskSequence{i,1}; 269 | task=RobotTaskCell{i,1}; 270 | num=RobotTaskNumVec(i,1); 271 | for j=1:num-1 272 | priorTask=task(seq(j,1),:); 273 | latterTask=task(seq(j+1,1),:); 274 | s=find(ismember(TaskMat,priorTask,'rows')',1); 275 | t=find(ismember(TaskMat,latterTask,'rows')',1); 276 | G=addedge(G,s,t); 277 | end 278 | end 279 | 280 | for i=1:agentNum 281 | seq=AgentTaskSequence{i,1}; 282 | task=AgentTaskCell{i,1}; 283 | num=AgentTaskNumVec(i,1); 284 | for j=1:num-1 285 | priorTask=task(seq(j,1),:); 286 | latterTask=task(seq(j+1,1),:); 287 | s=find(ismember(TaskMat,priorTask,'rows')',1); 288 | t=find(ismember(TaskMat,latterTask,'rows')',1); 289 | G=addedge(G,s,t); 290 | end 291 | end 292 | 293 | %plot(G); 294 | 295 | % remove all dummy tasks. 296 | H = rmnode(G,subtaskNum+1:subtaskNum+robotNum+agentNum); 297 | plot(H); 298 | 299 | [n,I] = toposort(H); 300 | 301 | %analysis this DAG 302 | deg = indegree(H); 303 | sourceNum=size(find(deg==0),1); 304 | 305 | criticalLength=0; 306 | while (numnodes(H)~=0) 307 | deg = indegree(H); 308 | indices = find(deg==0); 309 | H=rmnode(H,indices); 310 | criticalLength=criticalLength+1; 311 | end 312 | 313 | makespan=0; 314 | for i=1:robotNum 315 | mat=TimeCell{i,1}; 316 | sb=mat(end,6); 317 | makespan=max(makespan,sb); 318 | end 319 | disp(makespan); 320 | disp(totalRobotTravelTime); 321 | disp(totalAgentTravelTime); 322 | disp(totalRobotWaitTime); 323 | disp(totalAgentWaitTime); 324 | disp(sourceNum); 325 | disp(criticalLength); -------------------------------------------------------------------------------- /SCP/rcd2linear.m: -------------------------------------------------------------------------------- 1 | function linearLoc = rcd2linear(taskNumMat,r,c,d) 2 | if r==1 3 | if c==1 4 | linearLoc=d; 5 | else 6 | vec=taskNumMat(r,:); 7 | linearLoc=sum(1:c-1)+d; 8 | end 9 | else 10 | temp=sum(sum(taskNumMat(1:r-1,:))); 11 | if c==1 12 | linearLoc=temp+d; 13 | else 14 | vec=taskNumMat(r,:); 15 | linearLoc=temp+sum(1:c-1)+d; 16 | end 17 | 18 | end 19 | 20 | 21 | end 22 | 23 | -------------------------------------------------------------------------------- /SCP/taskSelection.m: -------------------------------------------------------------------------------- 1 | function outputSelect = taskSelection(BlockNumMat,TaskMat,RobotMat,AgentMat,alpha) 2 | totalTaskNum=sum(sum(BlockNumMat)); 3 | robotNum=size(RobotMat,1); 4 | agentNum=size(AgentMat,1); 5 | varlen=totalTaskNum+1; 6 | M=10000; 7 | Aineq=[]; 8 | bineq=[]; 9 | %constraint (1) 10 | A=[M*eye(totalTaskNum),-1*ones(totalTaskNum,1)]; 11 | b=zeros(totalTaskNum,1); 12 | for i=1:totalTaskNum 13 | task=TaskMat(i,:); 14 | robotId=task(1,1); 15 | robot=RobotMat(robotId,:); 16 | b(i,1)=-robot(1,3)-getDistance(robot(1,1),robot(1,2),task(1,4),task(1,5))-task(1,6)+M; 17 | end 18 | 19 | indices = find(TaskMat(:,9)==1); 20 | A(indices,:)=0; 21 | b(indices,:)=0; 22 | 23 | Aineq=[Aineq;A]; 24 | bineq=[bineq;b]; 25 | 26 | %constraint (2) 27 | A=[M*eye(totalTaskNum),-1*ones(totalTaskNum,1)]; 28 | b=zeros(totalTaskNum,1); 29 | for i=1:totalTaskNum 30 | task=TaskMat(i,:); 31 | agentId=task(1,2); 32 | agent=AgentMat(agentId,:); 33 | b(i,1)=-agent(1,3)-alpha*getDistance(agent(1,1),agent(1,2),task(1,4),task(1,5))-task(1,6)+M; 34 | end 35 | 36 | indices = find(TaskMat(:,9)==1); 37 | A(indices,:)=0; 38 | b(indices,:)=0; 39 | 40 | Aineq=[Aineq;A]; 41 | bineq=[bineq;b]; 42 | 43 | %constraint (3) 44 | A=zeros(robotNum,varlen); 45 | b=zeros(robotNum,1); 46 | for i=1:robotNum 47 | indices=and(TaskMat(:,1)==i,TaskMat(:,9)==0); 48 | indices=find(indices==1); 49 | if ~isempty(indices) 50 | vec=zeros(1,varlen); 51 | vec(1,indices)=1; 52 | A(i,:)=vec; 53 | b(i,1)=1; 54 | end 55 | end 56 | 57 | Aineq=[Aineq;A]; 58 | bineq=[bineq;b]; 59 | 60 | %constraint (4) 61 | A=zeros(agentNum,varlen); 62 | b=zeros(agentNum,1); 63 | for i=1:agentNum 64 | indices=and(TaskMat(:,2)==i,TaskMat(:,9)==0); 65 | indices=find(indices==1); 66 | if ~isempty(indices) 67 | vec=zeros(1,varlen); 68 | vec(1,indices)=1; 69 | A(i,:)=vec; 70 | b(i,1)=1; 71 | end 72 | end 73 | 74 | Aineq=[Aineq;A]; 75 | bineq=[bineq;b]; 76 | 77 | %constraint (5) 78 | indices = find(TaskMat(:,9)==0); 79 | A=zeros(1,varlen); 80 | A(1,indices)=1; 81 | b=0; 82 | UnfinishedRobotNum = find(RobotMat(:,4)==0); 83 | UnfinishedAgentNum = find(AgentMat(:,4)==0); 84 | b=min(size(UnfinishedRobotNum,1),size(UnfinishedAgentNum,1)); 85 | 86 | Aeq=A; 87 | beq=b; 88 | 89 | intcon=1:varlen-1; 90 | lb = zeros(varlen,1); 91 | ub = inf(varlen,1); 92 | ub(1:varlen-1,1)=1; 93 | %% Objective 94 | f=zeros(varlen,1); 95 | f(end,1)=1; 96 | %% MILP 97 | opts = optimoptions('intlinprog','Display','iter','Heuristics','round-diving','IPPreprocess','none'); 98 | [bestSolution,fval,exitflag,output] = intlinprog(f,intcon,Aineq,bineq,Aeq,beq,lb,ub,opts); 99 | outputSelect=bestSolution(1:varlen-1,1); 100 | outputSelect=int32(outputSelect); 101 | end 102 | 103 | -------------------------------------------------------------------------------- /generateInstance.m: -------------------------------------------------------------------------------- 1 | clear; 2 | clc; 3 | 4 | robotNum=4; 5 | agentNum=3; 6 | taskNum = robotNum; 7 | %velocity ratio 8 | alpha = 2; 9 | 10 | %% X-n110-k13 map 11 | % VertexMat=zeros(101,3); 12 | % VertexMat(1,:)=[1 50 50]; 13 | % for i=2:101 14 | % VertexMat(i,:)=[i randi([1 100]) randi([1 100])]; 15 | % end 16 | VertexMat=[1 35 35 17 | 2 41 49 18 | 3 35 17 19 | 4 55 45 20 | 5 55 20 21 | 6 15 30 22 | 7 25 30 23 | 8 20 50 24 | 9 10 43 25 | 10 55 60 26 | 11 30 60 27 | 12 20 65 28 | 13 50 35 29 | 14 30 25 30 | 15 15 10 31 | 16 30 5 32 | 17 10 20 33 | 18 5 30 34 | 19 20 40 35 | 20 15 60 36 | 21 45 65 37 | 22 45 20 38 | 23 45 10 39 | 24 55 5 40 | 25 65 35 41 | 26 65 20 42 | 27 45 30 43 | 28 35 40 44 | 29 41 37 45 | 30 64 42 46 | 31 40 60 47 | 32 31 52 48 | 33 35 69 49 | 34 53 52 50 | 35 65 55 51 | 36 63 65 52 | 37 2 60 53 | 38 20 20 54 | 39 5 5 55 | 40 60 12 56 | 41 40 25 57 | 42 42 7 58 | 43 24 12 59 | 44 23 3 60 | 45 11 14 61 | 46 6 38 62 | 47 2 48 63 | 48 8 56 64 | 49 13 52 65 | 50 6 68 66 | 51 47 47 67 | 52 49 58 68 | 53 27 43 69 | 54 37 31 70 | 55 57 29 71 | 56 63 23 72 | 57 53 12 73 | 58 32 12 74 | 59 36 26 75 | 60 21 24 76 | 61 17 34 77 | 62 12 24 78 | 63 24 58 79 | 64 27 69 80 | 65 15 77 81 | 66 62 77 82 | 67 49 73 83 | 68 67 5 84 | 69 56 39 85 | 70 37 47 86 | 71 37 56 87 | 72 57 68 88 | 73 47 16 89 | 74 44 17 90 | 75 46 13 91 | 76 49 11 92 | 77 49 42 93 | 78 53 43 94 | 79 61 52 95 | 80 57 48 96 | 81 56 37 97 | 82 55 54 98 | 83 15 47 99 | 84 14 37 100 | 85 11 31 101 | 86 16 22 102 | 87 4 18 103 | 88 28 18 104 | 89 26 52 105 | 90 26 35 106 | 91 31 67 107 | 92 15 19 108 | 93 22 22 109 | 94 18 24 110 | 95 26 27 111 | 96 25 24 112 | 97 22 27 113 | 98 25 21 114 | 99 19 21 115 | 100 20 26 116 | 101 18 18]; 117 | 118 | VertexMat=VertexMat(:,2:3); 119 | %the first vertex is depot 120 | depot=VertexMat(1,:); 121 | StationMat = VertexMat(2:end,:); 122 | stationNum = size(StationMat,1); 123 | 124 | %% Robots and Agents 125 | %Station Allocation by K-means clustering 126 | [idx,C] = kmeans(StationMat,agentNum); 127 | %[idx,C] = kmeans(StationMat,agentNum,'Distance','cityblock'); 128 | CliqueCell = cell(agentNum,1); 129 | %[x y time finished] 130 | RobotMat = zeros(robotNum,4); 131 | RobotMat(:,1:2) = repmat(depot,robotNum,1); 132 | AgentMat = zeros(agentNum,4); 133 | for i=1:agentNum 134 | CliqueCell{i,1} = StationMat(idx==i,:); 135 | temp = CliqueCell{i,1}; 136 | n=randi(size(temp,1)); 137 | AgentMat(i,1:2) = temp(n,:); 138 | end 139 | 140 | %% Generate Logistic Tasks. 141 | % Each subtask is denoted by [x y processTime] 142 | processTimeLB = 10; 143 | processTimeUB = 20; 144 | stationIndices = 1:stationNum; 145 | TaskCell = cell(taskNum,1); 146 | subtaskNum=0; 147 | for i=1:taskNum 148 | taskLength = round(normrnd(agentNum,0.8))+2; 149 | %taskLength = agentNum; 150 | %task = zeros(taskLength,3); 151 | c=randperm(numel(stationIndices)); 152 | tempIndex=stationIndices(c(1:taskLength)); 153 | %avoid repeated locations. 154 | stationIndices = stationIndices(c(taskLength+1:end)); 155 | for j=1:taskLength 156 | %uniform distribution 157 | tempTime = processTimeLB + int32((processTimeUB-processTimeLB)*rand()); 158 | task(j,:) = [StationMat(tempIndex(j),:),tempTime]; 159 | end 160 | TaskCell{i,1}=task; 161 | subtaskNum=subtaskNum+taskLength; 162 | end 163 | 164 | %% Reorganize Tasks into a matrix including index and temporal-spatial information. 165 | BlockTaskCell=cell(robotNum,agentNum); 166 | BlockNumMat=zeros(robotNum,agentNum); 167 | 168 | for i=1:robotNum 169 | task = TaskCell{i,1}; 170 | for j=1:size(task,1) 171 | subtaskStation = task(j,1:2); 172 | rowIndex = and(StationMat(:,1)==subtaskStation(1,1),StationMat(:,2)==subtaskStation(1,2)); 173 | rowIndex = find(rowIndex~=0); 174 | index = idx(rowIndex,1); %find which cliques this task belongs to 175 | BlockTaskCell{i,index} = [BlockTaskCell{i,index};task(j,:)]; 176 | BlockNumMat(i,index)=BlockNumMat(i,index)+1; 177 | end 178 | end 179 | 180 | % [robotId,agentId,depthId,x,y,processTime,robotStartTime,agentStartTime,finished] linear order. 181 | TaskMat = zeros(subtaskNum,9); 182 | index=1; 183 | for i=1:robotNum 184 | for j=1:agentNum 185 | temp=BlockNumMat(i,j); 186 | task=BlockTaskCell{i,j}; 187 | if ~isempty(temp) 188 | for k=1:temp 189 | TaskMat(index,:)=[i j k task(k,1) task(k,2) task(k,3) 0 0 0]; 190 | index=index+1; 191 | end 192 | end 193 | end 194 | end 195 | 196 | 197 | save('Instance.mat','StationMat','depot','CliqueCell','TaskMat','BlockNumMat','RobotMat','AgentMat','alpha'); 198 | 199 | -------------------------------------------------------------------------------- /linear2rcd.m: -------------------------------------------------------------------------------- 1 | function [r, c, d] = linear2rcd(TaskNumMat,linearLoc) 2 | [robotNum,agentNum]=size(TaskNumMat); 3 | sum=0; 4 | for i=1:robotNum 5 | for j=1:agentNum 6 | if ~isempty(TaskNumMat(i,j)) 7 | for k=1:TaskNumMat(i,j) 8 | sum=sum+1; 9 | if sum==linearLoc 10 | r=i; 11 | c=j; 12 | d=k; 13 | return; 14 | end 15 | 16 | end 17 | end 18 | 19 | end 20 | end 21 | 22 | 23 | end 24 | 25 | -------------------------------------------------------------------------------- /plotInstance.m: -------------------------------------------------------------------------------- 1 | clear; 2 | clc; 3 | load("Instance.mat"); 4 | 5 | figure('position',[400,10,1000,1000]); 6 | axis([0 80 0 80]); 7 | axis equal; 8 | axis manual; 9 | robotNum=size(RobotMat,1); 10 | agentNum=size(AgentMat,1); 11 | subtaskNum=size(TaskMat,1); 12 | 13 | %% plot depot and stations 14 | plot(StationMat(:,1),StationMat(:,2),'LineStyle','none','Color',[0.7 0.7 0.7],'marker','.','markersize',20); 15 | hold on; 16 | plot(depot(1,1),depot(1,2),'LineStyle','none','Color',[0 0 0],'marker','.','markersize',20); 17 | hold on; 18 | 19 | % plot(100,100,'LineStyle','none','Color',[1 1 1],'marker','.','markersize',1); 20 | %pause(5); 21 | 22 | %% plot cliques 23 | for i=1:agentNum 24 | Clique = CliqueCell{i,1}; 25 | x=Clique(:,1); 26 | y=Clique(:,2); 27 | dt = delaunayTriangulation(x,y); 28 | k = convexHull(dt); 29 | plot(x,y,'LineStyle','none', 'Color',[0.7 0.7 0.7],'marker','.','markersize',20); 30 | hold on; 31 | plot(x(k), y(k), 'Color',[0.9 0.9 0.9]); 32 | hold on; 33 | end 34 | 35 | %pause(5); 36 | 37 | %% plot robots 38 | plot(RobotMat(:,1), RobotMat(:,2),'LineStyle','none','marker','o', 'Color',[0 0 0],'markersize',13,'MarkerFaceColor','k'); 39 | text(RobotMat(:,1)+1,RobotMat(:,2),'TR1,TR2,TR3'); 40 | hold on; 41 | plot(AgentMat(:,1), AgentMat(:,2),'LineStyle','none','marker','s', 'Color',[0 0 0],'markersize',10,'MarkerFaceColor','k'); 42 | for i=1:agentNum 43 | txt=sprintf('SR%d',i); 44 | text(AgentMat(i,1)+1,AgentMat(i,2),txt); 45 | end 46 | hold on; 47 | 48 | %pause(5); 49 | 50 | %% plot tasks 51 | ColorMat = [1 0 0;0 1 0;0 0 1;1 1 0;1 0 1;1 1 0]; 52 | 53 | for i=1:subtaskNum 54 | subtask=TaskMat(i,:); 55 | plot(subtask(1,4),subtask(1,5),'LineStyle','none','Color',ColorMat(subtask(1,1),:),'marker','.','MarkerFaceColor',ColorMat(subtask(1,1),:),'markersize',20); 56 | hold on; 57 | text(subtask(1,4)-0.7,subtask(1,5)-1,num2str(subtask(1,6))); 58 | end 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /rcd2linear.m: -------------------------------------------------------------------------------- 1 | function linearLoc = rcd2linear(TaskNumMat,r,c,d) 2 | if r==1 3 | if c==1 4 | linearLoc=d; 5 | else 6 | vec=TaskNumMat(r,:); 7 | linearLoc=sum(1:c-1)+d; 8 | end 9 | else 10 | temp=sum(sum(TaskNumMat(1:r-1,:))); 11 | if c==1 12 | linearLoc=temp+d; 13 | else 14 | vec=TaskNumMat(r,:); 15 | linearLoc=temp+sum(1:c-1)+d; 16 | end 17 | 18 | end 19 | 20 | 21 | end 22 | 23 | --------------------------------------------------------------------------------