├── .gitignore ├── README.md ├── images └── Example1.png ├── sga_example.py └── sga_minmax_example.py /.gitignore: -------------------------------------------------------------------------------- 1 | /.vscode/ 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sequential-Greedy-Algorithm 2 | sequential greedy algorithm (SGA) for multi robot task allocation 3 | 4 | ## Dependency 5 | - numpy 6 | - scipy 7 | - matplotlib 8 | 9 | ## Cost 10 | euclidean distance 11 | 12 | ## Objective 13 | 1. MinSum 14 | 2. MinMax 15 | 16 | referenced from [[1]](#1) 17 | 18 | 19 | ## Example of SGA 20 | ![Example1](https://user-images.githubusercontent.com/31655488/170826038-26ee16f9-e65f-4c57-92d9-fe8ba82ab6d4.png) 21 | 22 | 23 | ## Reference 24 | [1] 25 | Choi, Han-Lim, Luc Brunet, and Jonathan P. How. "Consensus-based decentralized auctions for robust task allocation." IEEE transactions on robotics 25.4 (2009): 912-926. 26 | -------------------------------------------------------------------------------- /images/Example1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keep9oing/Sequential-Greedy-Algorithm/36631feb8e7594332c9e9d2e4197057c5cf21b33/images/Example1.png -------------------------------------------------------------------------------- /sga_example.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import copy 3 | from scipy.spatial import distance_matrix 4 | 5 | from matplotlib import pyplot as plt 6 | 7 | robot_num = 5 8 | task_num = 50 9 | 10 | robot = np.random.uniform(0,1,(robot_num,2)) 11 | task = np.random.uniform(0,1,(task_num,2)) 12 | 13 | # Sequential Greedy Algorithm 14 | I = [i for i in range(len(robot))] 15 | J = [j for j in range(len(task))] 16 | 17 | bundle = [[] for i in range(len(robot))] 18 | path = [[] for i in range(len(robot))] 19 | Sp = [0 for i in range(len(robot))] 20 | 21 | L_t = len(task) 22 | N_min = min(len(task),len(robot)*L_t) 23 | alpha = 1 24 | 25 | eta = np.zeros(len(robot),dtype=np.int16) 26 | score = -distance_matrix(robot,task) 27 | 28 | for n in range(N_min): 29 | i_star,j_star = np.unravel_index(np.argmax(score, axis=None), score.shape) 30 | 31 | eta[i_star] += 1 32 | J.remove(j_star) 33 | 34 | # Construct Bundle 35 | bundle[i_star].append(j_star) 36 | 37 | # Construct Path 38 | if len(path[i_star]) > 0: 39 | c_list = [] 40 | for k in range(len(path[i_star])+1): 41 | p = copy.deepcopy(path[i_star]) 42 | p.insert(k,j_star) 43 | c = 0 44 | c += distance_matrix([robot[i_star]],[task[p[0]]]).squeeze() 45 | if len(p)>1: 46 | for loc in range(len(p)-1): 47 | c += distance_matrix([task[p[loc]]],[task[p[loc+1]]]).squeeze() 48 | c = -(c-Sp[i_star]) 49 | c_list.append(c) 50 | 51 | idx = np.argmax(c_list) 52 | c_max = c_list[idx] 53 | 54 | path[i_star].insert(idx,j_star) 55 | else: 56 | path[i_star].append(j_star) 57 | 58 | Sp[i_star] = 0 59 | Sp[i_star] += distance_matrix([robot[i_star]],[task[path[i_star][0]]]).squeeze() 60 | if len(path[i_star])>1: 61 | for loc in range(len(path[i_star])-1): 62 | Sp[i_star] += distance_matrix([task[path[i_star][loc]]],[task[path[i_star][loc+1]]]).squeeze() 63 | 64 | 65 | if eta[i_star] == L_t: 66 | I.remove(i_star) 67 | score[i_star,:] = -np.inf 68 | 69 | score[I,j_star] = -np.inf 70 | 71 | # Score Update 72 | for i in I: 73 | for j in J: 74 | c_list = [] 75 | for k in range(len(path[i])+1): 76 | p = copy.deepcopy(path[i]) 77 | p.insert(k,j) 78 | c = 0 79 | c += distance_matrix([robot[i]],[task[p[0]]]).squeeze() 80 | if len(p)>1: 81 | for loc in range(len(p)-1): 82 | c += distance_matrix([task[p[loc]]],[task[p[loc+1]]]).squeeze() 83 | c=-(c-Sp[i]) 84 | c_list.append(c) 85 | 86 | if c_list: 87 | if i == i_star: 88 | score[i,j] = (1/alpha) * max(c_list) 89 | else: 90 | score[i,j] = max(c_list) 91 | 92 | print("Bundle:",bundle) 93 | print("Path:",path) 94 | 95 | fig, ax = plt.subplots() 96 | ax.set_xlim((-0.1,1.2)) 97 | ax.set_ylim((-0.1,1.2)) 98 | ax.set_aspect("equal") 99 | 100 | ax.set_title("Sequential Greedy Algorithm (MinSum)") 101 | ax.plot(robot[:,0],robot[:,1],'r^',label="robot") 102 | ax.plot(task[:,0],task[:,1],'bo',label="task") 103 | 104 | for i in range(len(path)): 105 | p = copy.deepcopy(path[i]) 106 | if p: 107 | ax.plot([robot[i,0],task[p[0],0]],[robot[i,1],task[p[0],1]],'r-') 108 | ax.plot(task[p,0],task[p,1],'r-') 109 | 110 | ax.grid() 111 | ax.legend(loc="upper right") 112 | 113 | plt.show() 114 | -------------------------------------------------------------------------------- /sga_minmax_example.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import copy 3 | from scipy.spatial import distance_matrix 4 | 5 | from matplotlib import pyplot as plt 6 | 7 | 8 | robot_num = 5 9 | task_num = 50 10 | 11 | robot = np.random.uniform(0,1,(robot_num,2)) 12 | task = np.random.uniform(0,1,(task_num,2)) 13 | 14 | # Sequential Greedy Algorithm 15 | I = [i for i in range(len(robot))] 16 | J = [j for j in range(len(task))] 17 | 18 | bundle = [[] for i in range(len(robot))] 19 | path = [[] for i in range(len(robot))] 20 | Sp = [0 for i in range(len(robot))] 21 | 22 | L_t = len(task) 23 | N_min = min(len(task),len(robot)*L_t) 24 | alpha = 1 25 | penalty = 100 26 | 27 | eta = np.zeros(len(robot),dtype=np.int16) 28 | score = -distance_matrix(robot,task) 29 | 30 | for n in range(N_min): 31 | i_star,j_star = np.unravel_index(np.argmax(score, axis=None), score.shape) 32 | 33 | eta[i_star] += 1 34 | J.remove(j_star) 35 | 36 | # Construct Bundle 37 | bundle[i_star].append(j_star) 38 | 39 | # Construct Path 40 | if len(path[i_star]) > 0: 41 | c_list = [] 42 | for k in range(len(path[i_star])+1): 43 | p = copy.deepcopy(path[i_star]) 44 | p.insert(k,j_star) 45 | c = 0 46 | c += distance_matrix([robot[i_star]],[task[p[0]]]).squeeze() 47 | if len(p)>1: 48 | for loc in range(len(p)-1): 49 | c += distance_matrix([task[p[loc]]],[task[p[loc+1]]]).squeeze() 50 | c = -(c-Sp[i_star]) 51 | c_list.append(c) 52 | 53 | idx = np.argmax(c_list) 54 | c_max = c_list[idx] 55 | 56 | path[i_star].insert(idx,j_star) 57 | else: 58 | path[i_star].append(j_star) 59 | 60 | Sp[i_star] = 0 61 | Sp[i_star] += distance_matrix([robot[i_star]],[task[path[i_star][0]]]).squeeze() 62 | if len(path[i_star])>1: 63 | for loc in range(len(path[i_star])-1): 64 | Sp[i_star] += distance_matrix([task[path[i_star][loc]]],[task[path[i_star][loc+1]]]).squeeze() 65 | 66 | max_length = max(Sp) 67 | 68 | if eta[i_star] == L_t: 69 | I.remove(i_star) 70 | score[i_star,:] = -np.inf 71 | 72 | score[I,j_star] = -np.inf 73 | 74 | # Score Update 75 | for i in I: 76 | for j in J: 77 | c_list = [] 78 | for k in range(len(path[i])+1): 79 | p = copy.deepcopy(path[i]) 80 | p.insert(k,j) 81 | c = 0 82 | c += distance_matrix([robot[i]],[task[p[0]]]).squeeze() 83 | if len(p)>1: 84 | for loc in range(len(p)-1): 85 | c += distance_matrix([task[p[loc]]],[task[p[loc+1]]]).squeeze() 86 | 87 | if c > max_length: 88 | c = -(c-max_length)*penalty 89 | else: 90 | c=-(c-Sp[i]) 91 | c_list.append(c) 92 | 93 | if c_list: 94 | if i == i_star: 95 | score[i,j] = (1/alpha) * max(c_list) 96 | else: 97 | score[i,j] = max(c_list) 98 | 99 | print("Path",bundle) 100 | print("Bundle",path) 101 | print("Max Route:",max(Sp)) 102 | 103 | fig, ax = plt.subplots() 104 | ax.set_xlim((-0.1,1.2)) 105 | ax.set_ylim((-0.1,1.2)) 106 | ax.set_aspect("equal") 107 | 108 | ax.set_title("Sequential Greedy Algorithm (MinMax)") 109 | ax.plot(robot[:,0],robot[:,1],'r^',label="robot") 110 | ax.plot(task[:,0],task[:,1],'bo',label="task") 111 | 112 | for i in range(len(path)): 113 | p = copy.deepcopy(path[i]) 114 | if p: 115 | ax.plot([robot[i,0],task[p[0],0]],[robot[i,1],task[p[0],1]],'r-') 116 | ax.plot(task[p,0],task[p,1],'r-') 117 | 118 | ax.grid() 119 | ax.legend(loc="upper right") 120 | 121 | plt.show() 122 | --------------------------------------------------------------------------------