├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── img ├── 10_10_0.00.png ├── 10_10_2.75.png ├── 10_10_non_zero_velocity_task.png ├── 10_10_non_zero_velocity_task2.png ├── 20_20_1.08.png ├── 20_20_2.00.png ├── 4x4_TA.png ├── 50_50.png ├── diverse_tasks_loitering.png ├── lambda_1.7.png ├── lambda_2.5.png └── lambda_3.7.png ├── mov ├── Dynamic-Task-Agent-Allocation-CommLimit.gif ├── Dynamic-Task-Agent-Allocation-CommLimit.mp4 ├── Dynamic-Task-Agent-Allocation-noLimit.gif ├── Film_alloc_5_5.mp4 ├── Film_alloc_5_5_range.mp4 ├── Loitering_targets_simu_2_CommLimit_1_speedup_20.mp4 ├── Loitering_targets_simu_3_CommLimit_1.mp4 └── Loitering_targets_simu_3_CommLimit_1_range.mp4 ├── paper ├── Figures │ ├── Alloc_5_5_t_0_CommLimit_0.pdf │ ├── Alloc_5_5_t_0_CommLimit_1.pdf │ ├── Alloc_5_5_t_10_CommLimit_0.pdf │ ├── Alloc_5_5_t_10_CommLimit_1.pdf │ ├── Alloc_5_5_t_4_CommLimit_0.pdf │ ├── Alloc_5_5_t_4_CommLimit_1.pdf │ ├── CostReward.pdf │ ├── Figure-paper-auctions-2021.pdf │ ├── RangeLimitationUtility.pdf │ ├── RewardSuccessProbabilityUtility.pdf │ ├── RewardSuccessProbabilityUtility.tex │ ├── TotalUtility.pdf │ ├── nTnAComputationTime.pdf │ ├── nTnAUtility.pdf │ └── ntLoiterComputationTime.pdf ├── Greedy Decentralized Auction-based Task Allocation for Multi-Agent Systems - 6 pages.pdf ├── Greedy Decentralized Auction-based Task Allocation for Multi-Agent Systems.pdf ├── generatePDFFromTikz.tex ├── ieeeconf.cls ├── ifacconf.bst ├── ifacconf.cls ├── main.pdf ├── main.tex ├── ref.bib ├── remark.sty └── task_alloc_inkscape.pdf └── src ├── ComputeCommandParams.m ├── ComputeCommandParamsWithVelocity.m ├── Copy_of_OptimalControl.m ├── GenerateFiguresFixedTime.m ├── GenerateFiguresParamsAnalysis.m ├── GenerateMoviesFigures.m ├── GreedyCoalitionAuctionAlgorithm ├── CalcTaskUtility.m ├── CalcUtility.m ├── GCAASolution.m ├── GCAA_Bundle.m ├── GCAA_BundleAdd.m ├── GCAA_BundleRemove.m ├── GCAA_BundleRemoveSingleAssignment.m ├── GCAA_Communicate.m ├── GCAA_Communicate_Single_Assignment.m ├── GCAA_ComputeBids.m ├── GCAA_Init.m ├── GCAA_InsertInList.m ├── GCAA_Main.m ├── GCAA_RemoveFromList.m ├── MainTestScript.m ├── PlotAssignments.m ├── PlotAssignments2D.m ├── Scoring_CalcScore.m └── agents │ ├── agent1.mat │ ├── agent2.mat │ ├── agent3.mat │ ├── agent4.mat │ └── agent5.mat ├── ODE_test.m ├── ODE_test_loitering.m ├── ODE_test_loitering_1turn.m ├── OptimalControlSolution.m ├── OptimalControl_DTA.m ├── OptimalControl_OLTA.m ├── OptimalControl_lambda.m ├── OptimumSolution.m ├── PlotAgentRange.m ├── PlotAllocTime.m ├── PlotAnimation.m ├── PlotAnimationAndUtility.m ├── PlotTaskLoitering.m ├── PlotUtilitySimulation.m ├── PlotUtilitySimulationLaTeX.m ├── WinnerVectorToMatrix.m ├── legendUnq.m ├── optimalControlParametersAnalysis.m └── plotMapAllocation.m /.gitattributes: -------------------------------------------------------------------------------- 1 | paper/* linguist-vendored 2 | paper/* linguist-documentation 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.m~ 2 | *.avi* 3 | *.fig 4 | src/mat/* 5 | tex/* 6 | backup movies/* 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Martin Braquet 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Task Allocation using Auctions 2 | Dynamic decentralized task allocation algorithms for multi-agent systems using a greedy auction algorithm. 3 | 4 | Official GitHub repository: https://github.com/MartinBraquet/task-allocation-auctions. 5 | 6 | Master's research at The University of Texas at Austin in the research group of Efstathios Bakolas. 7 | 8 | The paper resulting from these simulations has been published at the Modeling, Estimation and Control Conference (MECC 2021). 9 | 10 | To cite this work: 11 | 12 | Braquet, M. and Bakolas E., "Greedy Decentralized Auction-based Task Allocation for Multi-Agent Systems", *Modeling, Estimation and Control Conference (MECC)*, 2021. 13 | 14 | * For the dynamic task allocation, run `OptimalControl_DTA.m`. 15 | * For the sensitivity analysis of the parameters, run `optimalControlParametersAnalysis.m`. 16 | 17 | To run the code in Matlab online: https://drive.matlab.com/sharing/f36a058f-99a4-4e38-a08e-0af800bd4ce8. 18 | 19 | Want a Python implementation as well? Please vote [here](https://github.com/MartinBraquet/task-allocation-auctions/discussions/5) and we'll do our best to accomodate the communities' needs! 20 | 21 | #### 2D map of the dynamic task allocation (10 agents and 10 tasks) with associated reward, cost and utility 22 | 23 | With communication limitation: 24 | 25 | ![Alt Text](https://martinbraquet.com/wp-content/uploads/Dynamic-Task-Agent-Allocation.gif) 26 | 27 | Without communication limitation: 28 | 29 | ![Alt Text](https://martinbraquet.com/wp-content/uploads/Dynamic-Task-Agent-Allocation-noLimit.gif) 30 | -------------------------------------------------------------------------------- /img/10_10_0.00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/img/10_10_0.00.png -------------------------------------------------------------------------------- /img/10_10_2.75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/img/10_10_2.75.png -------------------------------------------------------------------------------- /img/10_10_non_zero_velocity_task.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/img/10_10_non_zero_velocity_task.png -------------------------------------------------------------------------------- /img/10_10_non_zero_velocity_task2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/img/10_10_non_zero_velocity_task2.png -------------------------------------------------------------------------------- /img/20_20_1.08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/img/20_20_1.08.png -------------------------------------------------------------------------------- /img/20_20_2.00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/img/20_20_2.00.png -------------------------------------------------------------------------------- /img/4x4_TA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/img/4x4_TA.png -------------------------------------------------------------------------------- /img/50_50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/img/50_50.png -------------------------------------------------------------------------------- /img/diverse_tasks_loitering.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/img/diverse_tasks_loitering.png -------------------------------------------------------------------------------- /img/lambda_1.7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/img/lambda_1.7.png -------------------------------------------------------------------------------- /img/lambda_2.5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/img/lambda_2.5.png -------------------------------------------------------------------------------- /img/lambda_3.7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/img/lambda_3.7.png -------------------------------------------------------------------------------- /mov/Dynamic-Task-Agent-Allocation-CommLimit.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/mov/Dynamic-Task-Agent-Allocation-CommLimit.gif -------------------------------------------------------------------------------- /mov/Dynamic-Task-Agent-Allocation-CommLimit.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/mov/Dynamic-Task-Agent-Allocation-CommLimit.mp4 -------------------------------------------------------------------------------- /mov/Dynamic-Task-Agent-Allocation-noLimit.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/mov/Dynamic-Task-Agent-Allocation-noLimit.gif -------------------------------------------------------------------------------- /mov/Film_alloc_5_5.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/mov/Film_alloc_5_5.mp4 -------------------------------------------------------------------------------- /mov/Film_alloc_5_5_range.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/mov/Film_alloc_5_5_range.mp4 -------------------------------------------------------------------------------- /mov/Loitering_targets_simu_2_CommLimit_1_speedup_20.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/mov/Loitering_targets_simu_2_CommLimit_1_speedup_20.mp4 -------------------------------------------------------------------------------- /mov/Loitering_targets_simu_3_CommLimit_1.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/mov/Loitering_targets_simu_3_CommLimit_1.mp4 -------------------------------------------------------------------------------- /mov/Loitering_targets_simu_3_CommLimit_1_range.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/mov/Loitering_targets_simu_3_CommLimit_1_range.mp4 -------------------------------------------------------------------------------- /paper/Figures/Alloc_5_5_t_0_CommLimit_0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/paper/Figures/Alloc_5_5_t_0_CommLimit_0.pdf -------------------------------------------------------------------------------- /paper/Figures/Alloc_5_5_t_0_CommLimit_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/paper/Figures/Alloc_5_5_t_0_CommLimit_1.pdf -------------------------------------------------------------------------------- /paper/Figures/Alloc_5_5_t_10_CommLimit_0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/paper/Figures/Alloc_5_5_t_10_CommLimit_0.pdf -------------------------------------------------------------------------------- /paper/Figures/Alloc_5_5_t_10_CommLimit_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/paper/Figures/Alloc_5_5_t_10_CommLimit_1.pdf -------------------------------------------------------------------------------- /paper/Figures/Alloc_5_5_t_4_CommLimit_0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/paper/Figures/Alloc_5_5_t_4_CommLimit_0.pdf -------------------------------------------------------------------------------- /paper/Figures/Alloc_5_5_t_4_CommLimit_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/paper/Figures/Alloc_5_5_t_4_CommLimit_1.pdf -------------------------------------------------------------------------------- /paper/Figures/CostReward.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/paper/Figures/CostReward.pdf -------------------------------------------------------------------------------- /paper/Figures/Figure-paper-auctions-2021.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/paper/Figures/Figure-paper-auctions-2021.pdf -------------------------------------------------------------------------------- /paper/Figures/RangeLimitationUtility.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/paper/Figures/RangeLimitationUtility.pdf -------------------------------------------------------------------------------- /paper/Figures/RewardSuccessProbabilityUtility.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/paper/Figures/RewardSuccessProbabilityUtility.pdf -------------------------------------------------------------------------------- /paper/Figures/RewardSuccessProbabilityUtility.tex: -------------------------------------------------------------------------------- 1 | % This file was created by matlab2tikz. 2 | % 3 | %The latest updates can be retrieved from 4 | % http://www.mathworks.com/matlabcentral/fileexchange/22022-matlab2tikz-matlab2tikz 5 | %where you can also make suggestions and rate matlab2tikz. 6 | % 7 | \begin{tikzpicture}[scale=0.6] 8 | 9 | \begin{axis}[% 10 | width=4.521in, 11 | height=3.461in, 12 | at={(0.758in,0.586in)}, 13 | scale only axis, 14 | xmin=0, 15 | xmax=1, 16 | tick align=outside, 17 | xlabel style={font=\color{white!15!black}}, 18 | xlabel={Nominal reward}, 19 | ymin=0, 20 | ymax=1, 21 | ylabel style={font=\color{white!15!black}}, 22 | ylabel={Task success probability}, 23 | zmin=0, 24 | zmax=50, 25 | view={-37.5}{30}, 26 | axis background/.style={fill=white}, 27 | axis x line*=bottom, 28 | axis y line*=left, 29 | axis z line*=left, 30 | xmajorgrids, 31 | ymajorgrids, 32 | zmajorgrids 33 | ] 34 | 35 | \addplot3[% 36 | surf, 37 | shader=flat corner, draw=black, z buffer=sort, colormap={mymap}{[1pt] rgb(0pt)=(0.2422,0.1504,0.6603); rgb(1pt)=(0.25039,0.164995,0.707614); rgb(2pt)=(0.257771,0.181781,0.751138); rgb(3pt)=(0.264729,0.197757,0.795214); rgb(4pt)=(0.270648,0.214676,0.836371); rgb(5pt)=(0.275114,0.234238,0.870986); rgb(6pt)=(0.2783,0.255871,0.899071); rgb(7pt)=(0.280333,0.278233,0.9221); rgb(8pt)=(0.281338,0.300595,0.941376); rgb(9pt)=(0.281014,0.322757,0.957886); rgb(10pt)=(0.279467,0.344671,0.971676); rgb(11pt)=(0.275971,0.366681,0.982905); rgb(12pt)=(0.269914,0.3892,0.9906); rgb(13pt)=(0.260243,0.412329,0.995157); rgb(14pt)=(0.244033,0.435833,0.998833); rgb(15pt)=(0.220643,0.460257,0.997286); rgb(16pt)=(0.196333,0.484719,0.989152); rgb(17pt)=(0.183405,0.507371,0.979795); rgb(18pt)=(0.178643,0.528857,0.968157); rgb(19pt)=(0.176438,0.549905,0.952019); rgb(20pt)=(0.168743,0.570262,0.935871); rgb(21pt)=(0.154,0.5902,0.9218); rgb(22pt)=(0.146029,0.609119,0.907857); rgb(23pt)=(0.138024,0.627629,0.89729); rgb(24pt)=(0.124814,0.645929,0.888343); rgb(25pt)=(0.111252,0.6635,0.876314); rgb(26pt)=(0.0952095,0.679829,0.859781); rgb(27pt)=(0.0688714,0.694771,0.839357); rgb(28pt)=(0.0296667,0.708167,0.816333); rgb(29pt)=(0.00357143,0.720267,0.7917); rgb(30pt)=(0.00665714,0.731214,0.766014); rgb(31pt)=(0.0433286,0.741095,0.73941); rgb(32pt)=(0.0963952,0.75,0.712038); rgb(33pt)=(0.140771,0.7584,0.684157); rgb(34pt)=(0.1717,0.766962,0.655443); rgb(35pt)=(0.193767,0.775767,0.6251); rgb(36pt)=(0.216086,0.7843,0.5923); rgb(37pt)=(0.246957,0.791795,0.556743); rgb(38pt)=(0.290614,0.79729,0.518829); rgb(39pt)=(0.340643,0.8008,0.478857); rgb(40pt)=(0.3909,0.802871,0.435448); rgb(41pt)=(0.445629,0.802419,0.390919); rgb(42pt)=(0.5044,0.7993,0.348); rgb(43pt)=(0.561562,0.794233,0.304481); rgb(44pt)=(0.617395,0.787619,0.261238); rgb(45pt)=(0.671986,0.779271,0.2227); rgb(46pt)=(0.7242,0.769843,0.191029); rgb(47pt)=(0.773833,0.759805,0.16461); rgb(48pt)=(0.820314,0.749814,0.153529); rgb(49pt)=(0.863433,0.7406,0.159633); rgb(50pt)=(0.903543,0.733029,0.177414); rgb(51pt)=(0.939257,0.728786,0.209957); rgb(52pt)=(0.972757,0.729771,0.239443); rgb(53pt)=(0.995648,0.743371,0.237148); rgb(54pt)=(0.996986,0.765857,0.219943); rgb(55pt)=(0.995205,0.789252,0.202762); rgb(56pt)=(0.9892,0.813567,0.188533); rgb(57pt)=(0.978629,0.838629,0.176557); rgb(58pt)=(0.967648,0.8639,0.16429); rgb(59pt)=(0.96101,0.889019,0.153676); rgb(60pt)=(0.959671,0.913457,0.142257); rgb(61pt)=(0.962795,0.937338,0.12651); rgb(62pt)=(0.969114,0.960629,0.106362); rgb(63pt)=(0.9769,0.9839,0.0805)}, mesh/rows=11] 38 | table[row sep=crcr, point meta=\thisrow{c}] {% 39 | % 40 | x y z c\\ 41 | 0 0 0 0\\ 42 | 0 0.1 0 0\\ 43 | 0 0.2 0 0\\ 44 | 0 0.3 0 0\\ 45 | 0 0.4 0 0\\ 46 | 0 0.5 0 0\\ 47 | 0 0.6 0 0\\ 48 | 0 0.7 0 0\\ 49 | 0 0.8 0 0\\ 50 | 0 0.9 0 0\\ 51 | 0 1 0 0\\ 52 | 0.1 0 0 0\\ 53 | 0.1 0.1 0.490281064485351 0.490281064485351\\ 54 | 0.1 0.2 0.986382805086652 0.986382805086652\\ 55 | 0.1 0.3 1.48425168151501 1.48425168151501\\ 56 | 0.1 0.4 1.98375863974928 1.98375863974928\\ 57 | 0.1 0.5 2.48375863974928 2.48375863974928\\ 58 | 0.1 0.6 2.98375863974928 2.98375863974928\\ 59 | 0.1 0.7 3.48375863974928 3.48375863974928\\ 60 | 0.1 0.8 3.98375863974928 3.98375863974928\\ 61 | 0.1 0.9 4.48375863974928 4.48375863974928\\ 62 | 0.1 1 4.98375863974928 4.98375863974928\\ 63 | 0.2 0 0 0\\ 64 | 0.2 0.1 0.983758639749278 0.983758639749278\\ 65 | 0.2 0.2 1.98375863974928 1.98375863974928\\ 66 | 0.2 0.3 2.98375863974928 2.98375863974928\\ 67 | 0.2 0.4 3.98375863974928 3.98375863974928\\ 68 | 0.2 0.5 4.98375863974928 4.98375863974928\\ 69 | 0.2 0.6 5.98375863974928 5.98375863974928\\ 70 | 0.2 0.7 6.98375863974927 6.98375863974927\\ 71 | 0.2 0.8 7.98375863974928 7.98375863974928\\ 72 | 0.2 0.9 8.98375863974928 8.98375863974928\\ 73 | 0.2 1 9.98375863974927 9.98375863974927\\ 74 | 0.3 0 0 0\\ 75 | 0.3 0.1 1.48375863974928 1.48375863974928\\ 76 | 0.3 0.2 2.98375863974928 2.98375863974928\\ 77 | 0.3 0.3 4.48375863974928 4.48375863974928\\ 78 | 0.3 0.4 5.98375863974928 5.98375863974928\\ 79 | 0.3 0.5 7.48375863974928 7.48375863974928\\ 80 | 0.3 0.6 8.98375863974928 8.98375863974928\\ 81 | 0.3 0.7 10.4837586397493 10.4837586397493\\ 82 | 0.3 0.8 11.9837586397493 11.9837586397493\\ 83 | 0.3 0.9 13.4837586397493 13.4837586397493\\ 84 | 0.3 1 14.9837586397493 14.9837586397493\\ 85 | 0.4 0 0 0\\ 86 | 0.4 0.1 1.98375863974928 1.98375863974928\\ 87 | 0.4 0.2 3.98375863974928 3.98375863974928\\ 88 | 0.4 0.3 5.98375863974928 5.98375863974928\\ 89 | 0.4 0.4 7.98375863974928 7.98375863974928\\ 90 | 0.4 0.5 9.98375863974928 9.98375863974928\\ 91 | 0.4 0.6 11.9837586397493 11.9837586397493\\ 92 | 0.4 0.7 13.9837586397493 13.9837586397493\\ 93 | 0.4 0.8 15.9837586397493 15.9837586397493\\ 94 | 0.4 0.9 17.9837586397493 17.9837586397493\\ 95 | 0.4 1 19.9837586397493 19.9837586397493\\ 96 | 0.5 0 0 0\\ 97 | 0.5 0.1 2.48375863974928 2.48375863974928\\ 98 | 0.5 0.2 4.98375863974928 4.98375863974928\\ 99 | 0.5 0.3 7.48375863974928 7.48375863974928\\ 100 | 0.5 0.4 9.98375863974928 9.98375863974928\\ 101 | 0.5 0.5 12.4837586397493 12.4837586397493\\ 102 | 0.5 0.6 14.9837586397493 14.9837586397493\\ 103 | 0.5 0.7 17.4837586397493 17.4837586397493\\ 104 | 0.5 0.8 19.9837586397493 19.9837586397493\\ 105 | 0.5 0.9 22.4837586397493 22.4837586397493\\ 106 | 0.5 1 24.9837586397493 24.9837586397493\\ 107 | 0.6 0 0 0\\ 108 | 0.6 0.1 2.98375863974928 2.98375863974928\\ 109 | 0.6 0.2 5.98375863974928 5.98375863974928\\ 110 | 0.6 0.3 8.98375863974928 8.98375863974928\\ 111 | 0.6 0.4 11.9837586397493 11.9837586397493\\ 112 | 0.6 0.5 14.9837586397493 14.9837586397493\\ 113 | 0.6 0.6 17.9837586397493 17.9837586397493\\ 114 | 0.6 0.7 20.9837586397493 20.9837586397493\\ 115 | 0.6 0.8 23.9837586397493 23.9837586397493\\ 116 | 0.6 0.9 26.9837586397493 26.9837586397493\\ 117 | 0.6 1 29.9837586397493 29.9837586397493\\ 118 | 0.7 0 0 0\\ 119 | 0.7 0.1 3.48375863974928 3.48375863974928\\ 120 | 0.7 0.2 6.98375863974928 6.98375863974928\\ 121 | 0.7 0.3 10.4837586397493 10.4837586397493\\ 122 | 0.7 0.4 13.9837586397493 13.9837586397493\\ 123 | 0.7 0.5 17.4837586397493 17.4837586397493\\ 124 | 0.7 0.6 20.9837586397493 20.9837586397493\\ 125 | 0.7 0.7 24.4837586397493 24.4837586397493\\ 126 | 0.7 0.8 27.9837586397493 27.9837586397493\\ 127 | 0.7 0.9 31.4837586397493 31.4837586397493\\ 128 | 0.7 1 34.9837586397493 34.9837586397493\\ 129 | 0.8 0 0 0\\ 130 | 0.8 0.1 3.98375863974928 3.98375863974928\\ 131 | 0.8 0.2 7.98375863974928 7.98375863974928\\ 132 | 0.8 0.3 11.9837586397493 11.9837586397493\\ 133 | 0.8 0.4 15.9837586397493 15.9837586397493\\ 134 | 0.8 0.5 19.9837586397493 19.9837586397493\\ 135 | 0.8 0.6 23.9837586397493 23.9837586397493\\ 136 | 0.8 0.7 27.9837586397493 27.9837586397493\\ 137 | 0.8 0.8 31.9837586397493 31.9837586397493\\ 138 | 0.8 0.9 35.9837586397493 35.9837586397493\\ 139 | 0.8 1 39.9837586397493 39.9837586397493\\ 140 | 0.9 0 0 0\\ 141 | 0.9 0.1 4.48375863974928 4.48375863974928\\ 142 | 0.9 0.2 8.98375863974928 8.98375863974928\\ 143 | 0.9 0.3 13.4837586397493 13.4837586397493\\ 144 | 0.9 0.4 17.9837586397493 17.9837586397493\\ 145 | 0.9 0.5 22.4837586397493 22.4837586397493\\ 146 | 0.9 0.6 26.9837586397493 26.9837586397493\\ 147 | 0.9 0.7 31.4837586397493 31.4837586397493\\ 148 | 0.9 0.8 35.9837586397493 35.9837586397493\\ 149 | 0.9 0.9 40.4837586397493 40.4837586397493\\ 150 | 0.9 1 44.9837586397493 44.9837586397493\\ 151 | 1 0 0 0\\ 152 | 1 0.1 4.98375863974928 4.98375863974928\\ 153 | 1 0.2 9.98375863974928 9.98375863974928\\ 154 | 1 0.3 14.9837586397493 14.9837586397493\\ 155 | 1 0.4 19.9837586397493 19.9837586397493\\ 156 | 1 0.5 24.9837586397493 24.9837586397493\\ 157 | 1 0.6 29.9837586397493 29.9837586397493\\ 158 | 1 0.7 34.9837586397493 34.9837586397493\\ 159 | 1 0.8 39.9837586397493 39.9837586397493\\ 160 | 1 0.9 44.9837586397493 44.9837586397493\\ 161 | 1 1 49.9837586397493 49.9837586397493\\ 162 | }; 163 | \end{axis} 164 | \end{tikzpicture}% -------------------------------------------------------------------------------- /paper/Figures/TotalUtility.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/paper/Figures/TotalUtility.pdf -------------------------------------------------------------------------------- /paper/Figures/nTnAComputationTime.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/paper/Figures/nTnAComputationTime.pdf -------------------------------------------------------------------------------- /paper/Figures/nTnAUtility.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/paper/Figures/nTnAUtility.pdf -------------------------------------------------------------------------------- /paper/Figures/ntLoiterComputationTime.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/paper/Figures/ntLoiterComputationTime.pdf -------------------------------------------------------------------------------- /paper/Greedy Decentralized Auction-based Task Allocation for Multi-Agent Systems - 6 pages.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/paper/Greedy Decentralized Auction-based Task Allocation for Multi-Agent Systems - 6 pages.pdf -------------------------------------------------------------------------------- /paper/Greedy Decentralized Auction-based Task Allocation for Multi-Agent Systems.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/paper/Greedy Decentralized Auction-based Task Allocation for Multi-Agent Systems.pdf -------------------------------------------------------------------------------- /paper/generatePDFFromTikz.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | 3 | \usepackage{tikz,pgfplots} 4 | \usetikzlibrary{external} 5 | \tikzexternalize % activate! 6 | 7 | 8 | \begin{document} 9 | 10 | In Fig.~\ref{fig:RewardSuccessProbabilityUtility}, the global utility naturally increases with the nominal reward and the success probability of a task. 11 | 12 | \begin{figure} 13 | \centering 14 | \input{Figures/RewardSuccessProbabilityUtility.tex} 15 | \caption{Nominal reward and task success probability.} 16 | \label{fig:RewardSuccessProbabilityUtility} 17 | \end{figure} 18 | 19 | 20 | \end{document} 21 | -------------------------------------------------------------------------------- /paper/ifacconf.bst: -------------------------------------------------------------------------------- 1 | %% 2 | %% This is file `ifacconf.bst', 3 | %% generated with the docstrip utility. 4 | %% 5 | %% The original source files were: 6 | %% 7 | %% merlin.mbs (with options: `ay,nat,nm-rvvc,keyxyr,dt-beg,yr-par,note-yr,volp-com,num-xser,doi,edpar,ppx,ed,xedn,url,url-blk,nfss,') 8 | %% ---------------------------------------- 9 | %% *** Bibliography style for IFAC Proceedings *** 10 | %% 11 | %% Copyright 1994-2007 Patrick W Daly 12 | % =============================================================== 13 | % IMPORTANT NOTICE: 14 | % This bibliographic style (bst) file has been generated from one or 15 | % more master bibliographic style (mbs) files, listed above. 16 | % 17 | % This generated file can be redistributed and/or modified under the terms 18 | % of the LaTeX Project Public License Distributed from CTAN 19 | % archives in directory macros/latex/base/lppl.txt; either 20 | % version 1 of the License, or any later version. 21 | % =============================================================== 22 | % Name and version information of the main mbs file: 23 | % \ProvidesFile{merlin.mbs}[2007/04/24 4.20 (PWD, AO, DPC)] 24 | % For use with BibTeX version 0.99a or later 25 | %------------------------------------------------------------------- 26 | % This bibliography style file is intended for texts in ENGLISH 27 | % This is an author-year citation style bibliography. As such, it is 28 | % non-standard LaTeX, and requires a special package file to function properly. 29 | % Such a package is natbib.sty by Patrick W. Daly 30 | % The form of the \bibitem entries is 31 | % \bibitem[Jones et al.(1990)]{key}... 32 | % \bibitem[Jones et al.(1990)Jones, Baker, and Smith]{key}... 33 | % The essential feature is that the label (the part in brackets) consists 34 | % of the author names, as they should appear in the citation, with the year 35 | % in parentheses following. There must be no space before the opening 36 | % parenthesis! 37 | % With natbib v5.3, a full list of authors may also follow the year. 38 | % In natbib.sty, it is possible to define the type of enclosures that is 39 | % really wanted (brackets or parentheses), but in either case, there must 40 | % be parentheses in the label. 41 | % The \cite command functions as follows: 42 | % \citet{key} ==>> Jones et al. (1990) 43 | % \citet*{key} ==>> Jones, Baker, and Smith (1990) 44 | % \citep{key} ==>> (Jones et al., 1990) 45 | % \citep*{key} ==>> (Jones, Baker, and Smith, 1990) 46 | % \citep[chap. 2]{key} ==>> (Jones et al., 1990, chap. 2) 47 | % \citep[e.g.][]{key} ==>> (e.g. Jones et al., 1990) 48 | % \citep[e.g.][p. 32]{key} ==>> (e.g. Jones et al., p. 32) 49 | % \citeauthor{key} ==>> Jones et al. 50 | % \citeauthor*{key} ==>> Jones, Baker, and Smith 51 | % \citeyear{key} ==>> 1990 52 | %--------------------------------------------------------------------- 53 | 54 | ENTRY 55 | { address 56 | author 57 | booktitle 58 | chapter 59 | doi 60 | edition 61 | editor 62 | eid 63 | howpublished 64 | institution 65 | journal 66 | key 67 | month 68 | note 69 | number 70 | organization 71 | pages 72 | publisher 73 | school 74 | series 75 | title 76 | type 77 | url 78 | volume 79 | year 80 | } 81 | {} 82 | { label extra.label sort.label short.list } 83 | INTEGERS { output.state before.all mid.sentence after.sentence after.block } 84 | FUNCTION {init.state.consts} 85 | { #0 'before.all := 86 | #1 'mid.sentence := 87 | #2 'after.sentence := 88 | #3 'after.block := 89 | } 90 | STRINGS { s t} 91 | FUNCTION {output.nonnull} 92 | { 's := 93 | output.state mid.sentence = 94 | { ", " * write$ } 95 | { output.state after.block = 96 | { add.period$ write$ 97 | newline$ 98 | "\newblock " write$ 99 | } 100 | { output.state before.all = 101 | 'write$ 102 | { add.period$ " " * write$ } 103 | if$ 104 | } 105 | if$ 106 | mid.sentence 'output.state := 107 | } 108 | if$ 109 | s 110 | } 111 | FUNCTION {output} 112 | { duplicate$ empty$ 113 | 'pop$ 114 | 'output.nonnull 115 | if$ 116 | } 117 | FUNCTION {output.check} 118 | { 't := 119 | duplicate$ empty$ 120 | { pop$ "empty " t * " in " * cite$ * warning$ } 121 | 'output.nonnull 122 | if$ 123 | } 124 | FUNCTION {fin.entry} 125 | { add.period$ 126 | write$ 127 | newline$ 128 | } 129 | 130 | FUNCTION {new.block} 131 | { output.state before.all = 132 | 'skip$ 133 | { after.block 'output.state := } 134 | if$ 135 | } 136 | FUNCTION {new.sentence} 137 | { output.state after.block = 138 | 'skip$ 139 | { output.state before.all = 140 | 'skip$ 141 | { after.sentence 'output.state := } 142 | if$ 143 | } 144 | if$ 145 | } 146 | FUNCTION {add.blank} 147 | { " " * before.all 'output.state := 148 | } 149 | 150 | FUNCTION {date.block} 151 | { 152 | new.block 153 | } 154 | 155 | FUNCTION {not} 156 | { { #0 } 157 | { #1 } 158 | if$ 159 | } 160 | FUNCTION {and} 161 | { 'skip$ 162 | { pop$ #0 } 163 | if$ 164 | } 165 | FUNCTION {or} 166 | { { pop$ #1 } 167 | 'skip$ 168 | if$ 169 | } 170 | FUNCTION {new.block.checkb} 171 | { empty$ 172 | swap$ empty$ 173 | and 174 | 'skip$ 175 | 'new.block 176 | if$ 177 | } 178 | FUNCTION {field.or.null} 179 | { duplicate$ empty$ 180 | { pop$ "" } 181 | 'skip$ 182 | if$ 183 | } 184 | FUNCTION {emphasize} 185 | { duplicate$ empty$ 186 | { pop$ "" } 187 | { "\emph{" swap$ * "}" * } 188 | if$ 189 | } 190 | FUNCTION {tie.or.space.prefix} 191 | { duplicate$ text.length$ #3 < 192 | { "~" } 193 | { " " } 194 | if$ 195 | swap$ 196 | } 197 | 198 | FUNCTION {capitalize} 199 | { "u" change.case$ "t" change.case$ } 200 | 201 | FUNCTION {space.word} 202 | { " " swap$ * " " * } 203 | % Here are the language-specific definitions for explicit words. 204 | % Each function has a name bbl.xxx where xxx is the English word. 205 | % The language selected here is ENGLISH 206 | FUNCTION {bbl.and} 207 | { "and"} 208 | 209 | FUNCTION {bbl.etal} 210 | { "et~al." } 211 | 212 | FUNCTION {bbl.editors} 213 | { "eds." } 214 | 215 | FUNCTION {bbl.editor} 216 | { "ed." } 217 | 218 | FUNCTION {bbl.edby} 219 | { "edited by" } 220 | 221 | FUNCTION {bbl.edition} 222 | { "edition" } 223 | 224 | FUNCTION {bbl.volume} 225 | { "volume" } 226 | 227 | FUNCTION {bbl.of} 228 | { "of" } 229 | 230 | FUNCTION {bbl.number} 231 | { "number" } 232 | 233 | FUNCTION {bbl.nr} 234 | { "no." } 235 | 236 | FUNCTION {bbl.in} 237 | { "in" } 238 | 239 | FUNCTION {bbl.pages} 240 | { "" } 241 | 242 | FUNCTION {bbl.page} 243 | { "" } 244 | 245 | FUNCTION {bbl.chapter} 246 | { "chapter" } 247 | 248 | FUNCTION {bbl.techrep} 249 | { "Technical Report" } 250 | 251 | FUNCTION {bbl.mthesis} 252 | { "Master's thesis" } 253 | 254 | FUNCTION {bbl.phdthesis} 255 | { "Ph.D. thesis" } 256 | 257 | MACRO {jan} {"January"} 258 | 259 | MACRO {feb} {"February"} 260 | 261 | MACRO {mar} {"March"} 262 | 263 | MACRO {apr} {"April"} 264 | 265 | MACRO {may} {"May"} 266 | 267 | MACRO {jun} {"June"} 268 | 269 | MACRO {jul} {"July"} 270 | 271 | MACRO {aug} {"August"} 272 | 273 | MACRO {sep} {"September"} 274 | 275 | MACRO {oct} {"October"} 276 | 277 | MACRO {nov} {"November"} 278 | 279 | MACRO {dec} {"December"} 280 | 281 | MACRO {acmcs} {"ACM Computing Surveys"} 282 | 283 | MACRO {acta} {"Acta Informatica"} 284 | 285 | MACRO {cacm} {"Communications of the ACM"} 286 | 287 | MACRO {ibmjrd} {"IBM Journal of Research and Development"} 288 | 289 | MACRO {ibmsj} {"IBM Systems Journal"} 290 | 291 | MACRO {ieeese} {"IEEE Transactions on Software Engineering"} 292 | 293 | MACRO {ieeetc} {"IEEE Transactions on Computers"} 294 | 295 | MACRO {ieeetcad} 296 | {"IEEE Transactions on Computer-Aided Design of Integrated Circuits"} 297 | 298 | MACRO {ipl} {"Information Processing Letters"} 299 | 300 | MACRO {jacm} {"Journal of the ACM"} 301 | 302 | MACRO {jcss} {"Journal of Computer and System Sciences"} 303 | 304 | MACRO {scp} {"Science of Computer Programming"} 305 | 306 | MACRO {sicomp} {"SIAM Journal on Computing"} 307 | 308 | MACRO {tocs} {"ACM Transactions on Computer Systems"} 309 | 310 | MACRO {tods} {"ACM Transactions on Database Systems"} 311 | 312 | MACRO {tog} {"ACM Transactions on Graphics"} 313 | 314 | MACRO {toms} {"ACM Transactions on Mathematical Software"} 315 | 316 | MACRO {toois} {"ACM Transactions on Office Information Systems"} 317 | 318 | MACRO {toplas} {"ACM Transactions on Programming Languages and Systems"} 319 | 320 | MACRO {tcs} {"Theoretical Computer Science"} 321 | FUNCTION {bibinfo.check} 322 | { swap$ 323 | duplicate$ missing$ 324 | { 325 | pop$ pop$ 326 | "" 327 | } 328 | { duplicate$ empty$ 329 | { 330 | swap$ pop$ 331 | } 332 | { swap$ 333 | pop$ 334 | } 335 | if$ 336 | } 337 | if$ 338 | } 339 | FUNCTION {bibinfo.warn} 340 | { swap$ 341 | duplicate$ missing$ 342 | { 343 | swap$ "missing " swap$ * " in " * cite$ * warning$ pop$ 344 | "" 345 | } 346 | { duplicate$ empty$ 347 | { 348 | swap$ "empty " swap$ * " in " * cite$ * warning$ 349 | } 350 | { swap$ 351 | pop$ 352 | } 353 | if$ 354 | } 355 | if$ 356 | } 357 | FUNCTION {format.url} 358 | { url empty$ 359 | { "" } 360 | { "\urlprefix\url{" url * "}" * } 361 | if$ 362 | } 363 | 364 | INTEGERS { nameptr namesleft numnames } 365 | 366 | 367 | STRINGS { bibinfo} 368 | 369 | FUNCTION {format.names} 370 | { 'bibinfo := 371 | duplicate$ empty$ 'skip$ { 372 | 's := 373 | "" 't := 374 | #1 'nameptr := 375 | s num.names$ 'numnames := 376 | numnames 'namesleft := 377 | { namesleft #0 > } 378 | { s nameptr 379 | "{vv~}{ll}{, jj}{, f{.}.}" 380 | format.name$ 381 | bibinfo bibinfo.check 382 | 't := 383 | nameptr #1 > 384 | { 385 | namesleft #1 > 386 | { ", " * t * } 387 | { 388 | s nameptr "{ll}" format.name$ duplicate$ "others" = 389 | { 't := } 390 | { pop$ } 391 | if$ 392 | numnames #2 > 393 | { "," * } 394 | 'skip$ 395 | if$ 396 | t "others" = 397 | { 398 | " " * bbl.etal * 399 | } 400 | { 401 | bbl.and 402 | space.word * t * 403 | } 404 | if$ 405 | } 406 | if$ 407 | } 408 | 't 409 | if$ 410 | nameptr #1 + 'nameptr := 411 | namesleft #1 - 'namesleft := 412 | } 413 | while$ 414 | } if$ 415 | } 416 | FUNCTION {format.names.ed} 417 | { 418 | 'bibinfo := 419 | duplicate$ empty$ 'skip$ { 420 | 's := 421 | "" 't := 422 | #1 'nameptr := 423 | s num.names$ 'numnames := 424 | numnames 'namesleft := 425 | { namesleft #0 > } 426 | { s nameptr 427 | "{f{.}.~}{vv~}{ll}{ jj}" 428 | format.name$ 429 | bibinfo bibinfo.check 430 | 't := 431 | nameptr #1 > 432 | { 433 | namesleft #1 > 434 | { ", " * t * } 435 | { 436 | s nameptr "{ll}" format.name$ duplicate$ "others" = 437 | { 't := } 438 | { pop$ } 439 | if$ 440 | numnames #2 > 441 | { "," * } 442 | 'skip$ 443 | if$ 444 | t "others" = 445 | { 446 | 447 | " " * bbl.etal * 448 | } 449 | { 450 | bbl.and 451 | space.word * t * 452 | } 453 | if$ 454 | } 455 | if$ 456 | } 457 | 't 458 | if$ 459 | nameptr #1 + 'nameptr := 460 | namesleft #1 - 'namesleft := 461 | } 462 | while$ 463 | } if$ 464 | } 465 | FUNCTION {format.key} 466 | { empty$ 467 | { key field.or.null } 468 | { "" } 469 | if$ 470 | } 471 | 472 | FUNCTION {format.authors} 473 | { author "author" format.names 474 | } 475 | FUNCTION {get.bbl.editor} 476 | { editor num.names$ #1 > 'bbl.editors 'bbl.editor if$ } 477 | 478 | FUNCTION {format.editors} 479 | { editor "editor" format.names duplicate$ empty$ 'skip$ 480 | { 481 | " " * 482 | get.bbl.editor 483 | "(" swap$ * ")" * 484 | * 485 | } 486 | if$ 487 | } 488 | FUNCTION {format.doi} 489 | { doi "doi" bibinfo.check 490 | duplicate$ empty$ 'skip$ 491 | { 492 | new.block 493 | "\doi{" swap$ * "}" * 494 | } 495 | if$ 496 | } 497 | FUNCTION {format.note} 498 | { 499 | note empty$ 500 | { "" } 501 | { note #1 #1 substring$ 502 | duplicate$ "{" = 503 | 'skip$ 504 | { output.state mid.sentence = 505 | { "l" } 506 | { "u" } 507 | if$ 508 | change.case$ 509 | } 510 | if$ 511 | note #2 global.max$ substring$ * "note" bibinfo.check 512 | } 513 | if$ 514 | } 515 | 516 | FUNCTION {format.title} 517 | { title 518 | duplicate$ empty$ 'skip$ 519 | { "t" change.case$ } 520 | if$ 521 | "title" bibinfo.check 522 | } 523 | FUNCTION {format.full.names} 524 | {'s := 525 | "" 't := 526 | #1 'nameptr := 527 | s num.names$ 'numnames := 528 | numnames 'namesleft := 529 | { namesleft #0 > } 530 | { s nameptr 531 | "{vv~}{ll}" format.name$ 532 | 't := 533 | nameptr #1 > 534 | { 535 | namesleft #1 > 536 | { ", " * t * } 537 | { 538 | s nameptr "{ll}" format.name$ duplicate$ "others" = 539 | { 't := } 540 | { pop$ } 541 | if$ 542 | t "others" = 543 | { 544 | " " * bbl.etal * 545 | } 546 | { 547 | numnames #2 > 548 | { "," * } 549 | 'skip$ 550 | if$ 551 | bbl.and 552 | space.word * t * 553 | } 554 | if$ 555 | } 556 | if$ 557 | } 558 | 't 559 | if$ 560 | nameptr #1 + 'nameptr := 561 | namesleft #1 - 'namesleft := 562 | } 563 | while$ 564 | } 565 | 566 | FUNCTION {author.editor.key.full} 567 | { author empty$ 568 | { editor empty$ 569 | { key empty$ 570 | { cite$ #1 #3 substring$ } 571 | 'key 572 | if$ 573 | } 574 | { editor format.full.names } 575 | if$ 576 | } 577 | { author format.full.names } 578 | if$ 579 | } 580 | 581 | FUNCTION {author.key.full} 582 | { author empty$ 583 | { key empty$ 584 | { cite$ #1 #3 substring$ } 585 | 'key 586 | if$ 587 | } 588 | { author format.full.names } 589 | if$ 590 | } 591 | 592 | FUNCTION {editor.key.full} 593 | { editor empty$ 594 | { key empty$ 595 | { cite$ #1 #3 substring$ } 596 | 'key 597 | if$ 598 | } 599 | { editor format.full.names } 600 | if$ 601 | } 602 | 603 | FUNCTION {make.full.names} 604 | { type$ "book" = 605 | type$ "inbook" = 606 | or 607 | 'author.editor.key.full 608 | { type$ "proceedings" = 609 | 'editor.key.full 610 | 'author.key.full 611 | if$ 612 | } 613 | if$ 614 | } 615 | 616 | FUNCTION {output.bibitem} 617 | { newline$ 618 | "\bibitem[{" write$ 619 | label write$ 620 | ")" make.full.names duplicate$ short.list = 621 | { pop$ } 622 | { * } 623 | if$ 624 | "}]{" * write$ 625 | cite$ write$ 626 | "}" write$ 627 | newline$ 628 | "" 629 | before.all 'output.state := 630 | } 631 | 632 | FUNCTION {n.dashify} 633 | { 634 | 't := 635 | "" 636 | { t empty$ not } 637 | { t #1 #1 substring$ "-" = 638 | { t #1 #2 substring$ "--" = not 639 | { "--" * 640 | t #2 global.max$ substring$ 't := 641 | } 642 | { { t #1 #1 substring$ "-" = } 643 | { "-" * 644 | t #2 global.max$ substring$ 't := 645 | } 646 | while$ 647 | } 648 | if$ 649 | } 650 | { t #1 #1 substring$ * 651 | t #2 global.max$ substring$ 't := 652 | } 653 | if$ 654 | } 655 | while$ 656 | } 657 | 658 | FUNCTION {word.in} 659 | { bbl.in capitalize 660 | " " * } 661 | 662 | FUNCTION {format.date} 663 | { year "year" bibinfo.check duplicate$ empty$ 664 | { 665 | "empty year in " cite$ * "; set to ????" * warning$ 666 | pop$ "????" 667 | } 668 | 'skip$ 669 | if$ 670 | extra.label * 671 | before.all 'output.state := 672 | " (" swap$ * ")" * 673 | } 674 | FUNCTION {format.btitle} 675 | { title "title" bibinfo.check 676 | duplicate$ empty$ 'skip$ 677 | { 678 | emphasize 679 | } 680 | if$ 681 | } 682 | FUNCTION {either.or.check} 683 | { empty$ 684 | 'pop$ 685 | { "can't use both " swap$ * " fields in " * cite$ * warning$ } 686 | if$ 687 | } 688 | FUNCTION {format.bvolume} 689 | { volume empty$ 690 | { "" } 691 | { bbl.volume volume tie.or.space.prefix 692 | "volume" bibinfo.check * * 693 | series "series" bibinfo.check 694 | duplicate$ empty$ 'pop$ 695 | { swap$ bbl.of space.word * swap$ 696 | emphasize * } 697 | if$ 698 | "volume and number" number either.or.check 699 | } 700 | if$ 701 | } 702 | FUNCTION {format.number.series} 703 | { volume empty$ 704 | { number empty$ 705 | { series field.or.null } 706 | { series empty$ 707 | { number "number" bibinfo.check } 708 | { output.state mid.sentence = 709 | { bbl.number } 710 | { bbl.number capitalize } 711 | if$ 712 | number tie.or.space.prefix "number" bibinfo.check * * 713 | bbl.in space.word * 714 | series "series" bibinfo.check * 715 | } 716 | if$ 717 | } 718 | if$ 719 | } 720 | { "" } 721 | if$ 722 | } 723 | 724 | FUNCTION {format.edition} 725 | { edition duplicate$ empty$ 'skip$ 726 | { 727 | output.state mid.sentence = 728 | { "l" } 729 | { "t" } 730 | if$ change.case$ 731 | "edition" bibinfo.check 732 | " " * bbl.edition * 733 | } 734 | if$ 735 | } 736 | INTEGERS { multiresult } 737 | FUNCTION {multi.page.check} 738 | { 't := 739 | #0 'multiresult := 740 | { multiresult not 741 | t empty$ not 742 | and 743 | } 744 | { t #1 #1 substring$ 745 | duplicate$ "-" = 746 | swap$ duplicate$ "," = 747 | swap$ "+" = 748 | or or 749 | { #1 'multiresult := } 750 | { t #2 global.max$ substring$ 't := } 751 | if$ 752 | } 753 | while$ 754 | multiresult 755 | } 756 | FUNCTION {format.pages} 757 | { pages duplicate$ empty$ 'skip$ 758 | { duplicate$ multi.page.check 759 | { 760 | n.dashify 761 | } 762 | { 763 | } 764 | if$ 765 | "pages" bibinfo.check 766 | } 767 | if$ 768 | } 769 | FUNCTION {format.journal.pages} 770 | { pages duplicate$ empty$ 'pop$ 771 | { swap$ duplicate$ empty$ 772 | { pop$ pop$ format.pages } 773 | { 774 | ", " * 775 | swap$ 776 | n.dashify 777 | "pages" bibinfo.check 778 | * 779 | } 780 | if$ 781 | } 782 | if$ 783 | } 784 | FUNCTION {format.journal.eid} 785 | { eid "eid" bibinfo.check 786 | duplicate$ empty$ 'pop$ 787 | { swap$ duplicate$ empty$ 'skip$ 788 | { 789 | ", " * 790 | } 791 | if$ 792 | swap$ * 793 | } 794 | if$ 795 | } 796 | FUNCTION {format.vol.num.pages} 797 | { volume field.or.null 798 | duplicate$ empty$ 'skip$ 799 | { 800 | "volume" bibinfo.check 801 | } 802 | if$ 803 | number "number" bibinfo.check duplicate$ empty$ 'skip$ 804 | { 805 | swap$ duplicate$ empty$ 806 | { "there's a number but no volume in " cite$ * warning$ } 807 | 'skip$ 808 | if$ 809 | swap$ 810 | "(" swap$ * ")" * 811 | } 812 | if$ * 813 | eid empty$ 814 | { format.journal.pages } 815 | { format.journal.eid } 816 | if$ 817 | } 818 | 819 | FUNCTION {format.chapter.pages} 820 | { chapter empty$ 821 | 'format.pages 822 | { type empty$ 823 | { bbl.chapter } 824 | { type "l" change.case$ 825 | "type" bibinfo.check 826 | } 827 | if$ 828 | chapter tie.or.space.prefix 829 | "chapter" bibinfo.check 830 | * * 831 | pages empty$ 832 | 'skip$ 833 | { ", " * format.pages * } 834 | if$ 835 | } 836 | if$ 837 | } 838 | 839 | FUNCTION {format.booktitle} 840 | { 841 | booktitle "booktitle" bibinfo.check 842 | emphasize 843 | } 844 | FUNCTION {format.in.ed.booktitle} 845 | { format.booktitle duplicate$ empty$ 'skip$ 846 | { 847 | editor "editor" format.names.ed duplicate$ empty$ 'pop$ 848 | { 849 | " " * 850 | get.bbl.editor 851 | "(" swap$ * "), " * 852 | * swap$ 853 | * } 854 | if$ 855 | word.in swap$ * 856 | } 857 | if$ 858 | } 859 | FUNCTION {format.thesis.type} 860 | { type duplicate$ empty$ 861 | 'pop$ 862 | { swap$ pop$ 863 | "t" change.case$ "type" bibinfo.check 864 | } 865 | if$ 866 | } 867 | FUNCTION {format.tr.number} 868 | { number "number" bibinfo.check 869 | type duplicate$ empty$ 870 | { pop$ bbl.techrep } 871 | 'skip$ 872 | if$ 873 | "type" bibinfo.check 874 | swap$ duplicate$ empty$ 875 | { pop$ "t" change.case$ } 876 | { tie.or.space.prefix * * } 877 | if$ 878 | } 879 | FUNCTION {format.article.crossref} 880 | { 881 | word.in 882 | " \cite{" * crossref * "}" * 883 | } 884 | FUNCTION {format.book.crossref} 885 | { volume duplicate$ empty$ 886 | { "empty volume in " cite$ * "'s crossref of " * crossref * warning$ 887 | pop$ word.in 888 | } 889 | { bbl.volume 890 | capitalize 891 | swap$ tie.or.space.prefix "volume" bibinfo.check * * bbl.of space.word * 892 | } 893 | if$ 894 | " \cite{" * crossref * "}" * 895 | } 896 | FUNCTION {format.incoll.inproc.crossref} 897 | { 898 | word.in 899 | " \cite{" * crossref * "}" * 900 | } 901 | FUNCTION {format.org.or.pub} 902 | { 't := 903 | "" 904 | address empty$ t empty$ and 905 | 'skip$ 906 | { 907 | t empty$ 908 | { address "address" bibinfo.check * 909 | } 910 | { t * 911 | address empty$ 912 | 'skip$ 913 | { ", " * address "address" bibinfo.check * } 914 | if$ 915 | } 916 | if$ 917 | } 918 | if$ 919 | } 920 | FUNCTION {format.publisher.address} 921 | { publisher "publisher" bibinfo.warn format.org.or.pub 922 | } 923 | 924 | FUNCTION {format.organization.address} 925 | { organization "organization" bibinfo.check format.org.or.pub 926 | } 927 | 928 | FUNCTION {article} 929 | { output.bibitem 930 | format.authors "author" output.check 931 | author format.key output 932 | format.date "year" output.check 933 | date.block 934 | format.title "title" output.check 935 | new.block 936 | crossref missing$ 937 | { 938 | journal 939 | "journal" bibinfo.check 940 | emphasize 941 | "journal" output.check 942 | format.vol.num.pages output 943 | } 944 | { format.article.crossref output.nonnull 945 | format.pages output 946 | } 947 | if$ 948 | format.doi output 949 | new.block 950 | format.url output 951 | new.block 952 | format.note output 953 | fin.entry 954 | } 955 | FUNCTION {book} 956 | { output.bibitem 957 | author empty$ 958 | { format.editors "author and editor" output.check 959 | editor format.key output 960 | } 961 | { format.authors output.nonnull 962 | crossref missing$ 963 | { "author and editor" editor either.or.check } 964 | 'skip$ 965 | if$ 966 | } 967 | if$ 968 | format.date "year" output.check 969 | date.block 970 | format.btitle "title" output.check 971 | crossref missing$ 972 | { format.bvolume output 973 | new.block 974 | format.number.series output 975 | new.sentence 976 | format.publisher.address output 977 | } 978 | { 979 | new.block 980 | format.book.crossref output.nonnull 981 | } 982 | if$ 983 | format.edition output 984 | format.doi output 985 | new.block 986 | format.url output 987 | new.block 988 | format.note output 989 | fin.entry 990 | } 991 | FUNCTION {booklet} 992 | { output.bibitem 993 | format.authors output 994 | author format.key output 995 | format.date "year" output.check 996 | date.block 997 | format.title "title" output.check 998 | new.block 999 | howpublished "howpublished" bibinfo.check output 1000 | address "address" bibinfo.check output 1001 | format.doi output 1002 | new.block 1003 | format.url output 1004 | new.block 1005 | format.note output 1006 | fin.entry 1007 | } 1008 | 1009 | FUNCTION {inbook} 1010 | { output.bibitem 1011 | author empty$ 1012 | { format.editors "author and editor" output.check 1013 | editor format.key output 1014 | } 1015 | { format.authors output.nonnull 1016 | crossref missing$ 1017 | { "author and editor" editor either.or.check } 1018 | 'skip$ 1019 | if$ 1020 | } 1021 | if$ 1022 | format.date "year" output.check 1023 | date.block 1024 | format.btitle "title" output.check 1025 | crossref missing$ 1026 | { 1027 | format.bvolume output 1028 | format.chapter.pages "chapter and pages" output.check 1029 | new.block 1030 | format.number.series output 1031 | new.sentence 1032 | format.publisher.address output 1033 | } 1034 | { 1035 | format.chapter.pages "chapter and pages" output.check 1036 | new.block 1037 | format.book.crossref output.nonnull 1038 | } 1039 | if$ 1040 | format.edition output 1041 | format.doi output 1042 | new.block 1043 | format.url output 1044 | new.block 1045 | format.note output 1046 | fin.entry 1047 | } 1048 | 1049 | FUNCTION {incollection} 1050 | { output.bibitem 1051 | format.authors "author" output.check 1052 | author format.key output 1053 | format.date "year" output.check 1054 | date.block 1055 | format.title "title" output.check 1056 | new.block 1057 | crossref missing$ 1058 | { format.in.ed.booktitle "booktitle" output.check 1059 | format.bvolume output 1060 | format.number.series output 1061 | format.chapter.pages output 1062 | new.sentence 1063 | format.publisher.address output 1064 | format.edition output 1065 | } 1066 | { format.incoll.inproc.crossref output.nonnull 1067 | format.chapter.pages output 1068 | } 1069 | if$ 1070 | format.doi output 1071 | new.block 1072 | format.url output 1073 | new.block 1074 | format.note output 1075 | fin.entry 1076 | } 1077 | FUNCTION {inproceedings} 1078 | { output.bibitem 1079 | format.authors "author" output.check 1080 | author format.key output 1081 | format.date "year" output.check 1082 | date.block 1083 | format.title "title" output.check 1084 | new.block 1085 | crossref missing$ 1086 | { format.in.ed.booktitle "booktitle" output.check 1087 | format.bvolume output 1088 | format.number.series output 1089 | format.pages output 1090 | new.sentence 1091 | publisher empty$ 1092 | { format.organization.address output } 1093 | { organization "organization" bibinfo.check output 1094 | format.publisher.address output 1095 | } 1096 | if$ 1097 | } 1098 | { format.incoll.inproc.crossref output.nonnull 1099 | format.pages output 1100 | } 1101 | if$ 1102 | format.doi output 1103 | new.block 1104 | format.url output 1105 | new.block 1106 | format.note output 1107 | fin.entry 1108 | } 1109 | FUNCTION {conference} { inproceedings } 1110 | FUNCTION {manual} 1111 | { output.bibitem 1112 | format.authors output 1113 | author format.key output 1114 | format.date "year" output.check 1115 | date.block 1116 | format.btitle "title" output.check 1117 | organization address new.block.checkb 1118 | organization "organization" bibinfo.check output 1119 | address "address" bibinfo.check output 1120 | format.edition output 1121 | format.doi output 1122 | new.block 1123 | format.url output 1124 | new.block 1125 | format.note output 1126 | fin.entry 1127 | } 1128 | 1129 | FUNCTION {mastersthesis} 1130 | { output.bibitem 1131 | format.authors "author" output.check 1132 | author format.key output 1133 | format.date "year" output.check 1134 | date.block 1135 | format.btitle 1136 | "title" output.check 1137 | new.block 1138 | bbl.mthesis format.thesis.type output.nonnull 1139 | school "school" bibinfo.warn output 1140 | address "address" bibinfo.check output 1141 | format.doi output 1142 | new.block 1143 | format.url output 1144 | new.block 1145 | format.note output 1146 | fin.entry 1147 | } 1148 | 1149 | FUNCTION {misc} 1150 | { output.bibitem 1151 | format.authors output 1152 | author format.key output 1153 | format.date "year" output.check 1154 | date.block 1155 | format.title output 1156 | new.block 1157 | howpublished "howpublished" bibinfo.check output 1158 | format.doi output 1159 | new.block 1160 | format.url output 1161 | new.block 1162 | format.note output 1163 | fin.entry 1164 | } 1165 | FUNCTION {phdthesis} 1166 | { output.bibitem 1167 | format.authors "author" output.check 1168 | author format.key output 1169 | format.date "year" output.check 1170 | date.block 1171 | format.btitle 1172 | "title" output.check 1173 | new.block 1174 | bbl.phdthesis format.thesis.type output.nonnull 1175 | school "school" bibinfo.warn output 1176 | address "address" bibinfo.check output 1177 | format.doi output 1178 | new.block 1179 | format.url output 1180 | new.block 1181 | format.note output 1182 | fin.entry 1183 | } 1184 | 1185 | FUNCTION {proceedings} 1186 | { output.bibitem 1187 | format.editors output 1188 | editor format.key output 1189 | format.date "year" output.check 1190 | date.block 1191 | format.btitle "title" output.check 1192 | format.bvolume output 1193 | format.number.series output 1194 | new.sentence 1195 | publisher empty$ 1196 | { format.organization.address output } 1197 | { organization "organization" bibinfo.check output 1198 | format.publisher.address output 1199 | } 1200 | if$ 1201 | format.doi output 1202 | new.block 1203 | format.url output 1204 | new.block 1205 | format.note output 1206 | fin.entry 1207 | } 1208 | 1209 | FUNCTION {techreport} 1210 | { output.bibitem 1211 | format.authors "author" output.check 1212 | author format.key output 1213 | format.date "year" output.check 1214 | date.block 1215 | format.title 1216 | "title" output.check 1217 | new.block 1218 | format.tr.number output.nonnull 1219 | institution "institution" bibinfo.warn output 1220 | address "address" bibinfo.check output 1221 | format.doi output 1222 | new.block 1223 | format.url output 1224 | new.block 1225 | format.note output 1226 | fin.entry 1227 | } 1228 | 1229 | FUNCTION {unpublished} 1230 | { output.bibitem 1231 | format.authors "author" output.check 1232 | author format.key output 1233 | format.date "year" output.check 1234 | date.block 1235 | format.title "title" output.check 1236 | format.doi output 1237 | new.block 1238 | format.url output 1239 | new.block 1240 | format.note "note" output.check 1241 | fin.entry 1242 | } 1243 | 1244 | FUNCTION {default.type} { misc } 1245 | READ 1246 | FUNCTION {sortify} 1247 | { purify$ 1248 | "l" change.case$ 1249 | } 1250 | INTEGERS { len } 1251 | FUNCTION {chop.word} 1252 | { 's := 1253 | 'len := 1254 | s #1 len substring$ = 1255 | { s len #1 + global.max$ substring$ } 1256 | 's 1257 | if$ 1258 | } 1259 | FUNCTION {format.lab.names} 1260 | { 's := 1261 | "" 't := 1262 | s #1 "{vv~}{ll}" format.name$ 1263 | s num.names$ duplicate$ 1264 | #2 > 1265 | { pop$ 1266 | " " * bbl.etal * 1267 | } 1268 | { #2 < 1269 | 'skip$ 1270 | { s #2 "{ff }{vv }{ll}{ jj}" format.name$ "others" = 1271 | { 1272 | " " * bbl.etal * 1273 | } 1274 | { bbl.and space.word * s #2 "{vv~}{ll}" format.name$ 1275 | * } 1276 | if$ 1277 | } 1278 | if$ 1279 | } 1280 | if$ 1281 | } 1282 | 1283 | FUNCTION {author.key.label} 1284 | { author empty$ 1285 | { key empty$ 1286 | { cite$ #1 #3 substring$ } 1287 | 'key 1288 | if$ 1289 | } 1290 | { author format.lab.names } 1291 | if$ 1292 | } 1293 | 1294 | FUNCTION {author.editor.key.label} 1295 | { author empty$ 1296 | { editor empty$ 1297 | { key empty$ 1298 | { cite$ #1 #3 substring$ } 1299 | 'key 1300 | if$ 1301 | } 1302 | { editor format.lab.names } 1303 | if$ 1304 | } 1305 | { author format.lab.names } 1306 | if$ 1307 | } 1308 | 1309 | FUNCTION {editor.key.label} 1310 | { editor empty$ 1311 | { key empty$ 1312 | { cite$ #1 #3 substring$ } 1313 | 'key 1314 | if$ 1315 | } 1316 | { editor format.lab.names } 1317 | if$ 1318 | } 1319 | 1320 | FUNCTION {calc.short.authors} 1321 | { type$ "book" = 1322 | type$ "inbook" = 1323 | or 1324 | 'author.editor.key.label 1325 | { type$ "proceedings" = 1326 | 'editor.key.label 1327 | 'author.key.label 1328 | if$ 1329 | } 1330 | if$ 1331 | 'short.list := 1332 | } 1333 | 1334 | FUNCTION {calc.label} 1335 | { calc.short.authors 1336 | short.list 1337 | "(" 1338 | * 1339 | year duplicate$ empty$ 1340 | short.list key field.or.null = or 1341 | { pop$ "" } 1342 | 'skip$ 1343 | if$ 1344 | * 1345 | 'label := 1346 | } 1347 | 1348 | FUNCTION {sort.format.names} 1349 | { 's := 1350 | #1 'nameptr := 1351 | "" 1352 | s num.names$ 'numnames := 1353 | numnames 'namesleft := 1354 | { namesleft #0 > } 1355 | { s nameptr 1356 | "{vv{ } }{ll{ }}{ ff{ }}{ jj{ }}" 1357 | format.name$ 't := 1358 | nameptr #1 > 1359 | { 1360 | " " * 1361 | namesleft #1 = t "others" = and 1362 | { "zzzzz" * } 1363 | { t sortify * } 1364 | if$ 1365 | } 1366 | { t sortify * } 1367 | if$ 1368 | nameptr #1 + 'nameptr := 1369 | namesleft #1 - 'namesleft := 1370 | } 1371 | while$ 1372 | } 1373 | 1374 | FUNCTION {sort.format.title} 1375 | { 't := 1376 | "A " #2 1377 | "An " #3 1378 | "The " #4 t chop.word 1379 | chop.word 1380 | chop.word 1381 | sortify 1382 | #1 global.max$ substring$ 1383 | } 1384 | FUNCTION {author.sort} 1385 | { author empty$ 1386 | { key empty$ 1387 | { "to sort, need author or key in " cite$ * warning$ 1388 | "" 1389 | } 1390 | { key sortify } 1391 | if$ 1392 | } 1393 | { author sort.format.names } 1394 | if$ 1395 | } 1396 | FUNCTION {author.editor.sort} 1397 | { author empty$ 1398 | { editor empty$ 1399 | { key empty$ 1400 | { "to sort, need author, editor, or key in " cite$ * warning$ 1401 | "" 1402 | } 1403 | { key sortify } 1404 | if$ 1405 | } 1406 | { editor sort.format.names } 1407 | if$ 1408 | } 1409 | { author sort.format.names } 1410 | if$ 1411 | } 1412 | FUNCTION {editor.sort} 1413 | { editor empty$ 1414 | { key empty$ 1415 | { "to sort, need editor or key in " cite$ * warning$ 1416 | "" 1417 | } 1418 | { key sortify } 1419 | if$ 1420 | } 1421 | { editor sort.format.names } 1422 | if$ 1423 | } 1424 | FUNCTION {presort} 1425 | { calc.label 1426 | label sortify 1427 | " " 1428 | * 1429 | type$ "book" = 1430 | type$ "inbook" = 1431 | or 1432 | 'author.editor.sort 1433 | { type$ "proceedings" = 1434 | 'editor.sort 1435 | 'author.sort 1436 | if$ 1437 | } 1438 | if$ 1439 | #1 entry.max$ substring$ 1440 | 'sort.label := 1441 | sort.label 1442 | * 1443 | " " 1444 | * 1445 | title field.or.null 1446 | sort.format.title 1447 | * 1448 | #1 entry.max$ substring$ 1449 | 'sort.key$ := 1450 | } 1451 | 1452 | ITERATE {presort} 1453 | SORT 1454 | STRINGS { last.label next.extra } 1455 | INTEGERS { last.extra.num number.label } 1456 | FUNCTION {initialize.extra.label.stuff} 1457 | { #0 int.to.chr$ 'last.label := 1458 | "" 'next.extra := 1459 | #0 'last.extra.num := 1460 | #0 'number.label := 1461 | } 1462 | FUNCTION {forward.pass} 1463 | { last.label label = 1464 | { last.extra.num #1 + 'last.extra.num := 1465 | last.extra.num int.to.chr$ 'extra.label := 1466 | } 1467 | { "a" chr.to.int$ 'last.extra.num := 1468 | "" 'extra.label := 1469 | label 'last.label := 1470 | } 1471 | if$ 1472 | number.label #1 + 'number.label := 1473 | } 1474 | FUNCTION {reverse.pass} 1475 | { next.extra "b" = 1476 | { "a" 'extra.label := } 1477 | 'skip$ 1478 | if$ 1479 | extra.label 'next.extra := 1480 | extra.label 1481 | duplicate$ empty$ 1482 | 'skip$ 1483 | { "{\natexlab{" swap$ * "}}" * } 1484 | if$ 1485 | 'extra.label := 1486 | label extra.label * 'label := 1487 | } 1488 | EXECUTE {initialize.extra.label.stuff} 1489 | ITERATE {forward.pass} 1490 | REVERSE {reverse.pass} 1491 | FUNCTION {bib.sort.order} 1492 | { sort.label 1493 | " " 1494 | * 1495 | year field.or.null sortify 1496 | * 1497 | " " 1498 | * 1499 | title field.or.null 1500 | sort.format.title 1501 | * 1502 | #1 entry.max$ substring$ 1503 | 'sort.key$ := 1504 | } 1505 | ITERATE {bib.sort.order} 1506 | SORT 1507 | FUNCTION {begin.bib} 1508 | { preamble$ empty$ 1509 | 'skip$ 1510 | { preamble$ write$ newline$ } 1511 | if$ 1512 | "\begin{thebibliography}{" number.label int.to.str$ * "}" * 1513 | write$ newline$ 1514 | "\providecommand{\natexlab}[1]{#1}" 1515 | write$ newline$ 1516 | "\providecommand{\url}[1]{\texttt{#1}}" 1517 | write$ newline$ 1518 | "\providecommand{\urlprefix}{URL }" 1519 | write$ newline$ 1520 | "\expandafter\ifx\csname urlstyle\endcsname\relax" 1521 | write$ newline$ 1522 | " \providecommand{\doi}[1]{doi:\discretionary{}{}{}#1}\else" 1523 | write$ newline$ 1524 | " \providecommand{\doi}{doi:\discretionary{}{}{}\begingroup \urlstyle{rm}\Url}\fi" 1525 | write$ newline$ 1526 | } 1527 | EXECUTE {begin.bib} 1528 | EXECUTE {init.state.consts} 1529 | ITERATE {call.type$} 1530 | FUNCTION {end.bib} 1531 | { newline$ 1532 | "\end{thebibliography}" write$ newline$ 1533 | } 1534 | EXECUTE {end.bib} 1535 | %% End of customized bst file 1536 | %% 1537 | %% End of file `ifacconf.bst'. 1538 | -------------------------------------------------------------------------------- /paper/main.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/paper/main.pdf -------------------------------------------------------------------------------- /paper/ref.bib: -------------------------------------------------------------------------------- 1 | @article{p:shamma2007, 2 | author = {Arslan, Gürdal and Marden, Jason R. and Shamma, Jeff S.}, 3 | title = "{Autonomous Vehicle-Target Assignment: A Game-Theoretical Formulation}", 4 | journal = {J. Dyn. Syst. Meas. Control}, 5 | volume = {129}, 6 | number = {5}, 7 | pages = {584-596}, 8 | year = {2007}, 9 | month = {04} 10 | } 11 | 12 | @article{p:chapman2010, 13 | title={Decentralized dynamic task allocation using overlapping potential games}, 14 | author={Chapman, Archie C and Micillo, Rosa Anna and Kota, Ramachandra and Jennings, Nicholas R}, 15 | journal={The Computer Journal}, 16 | volume={53}, 17 | number={9}, 18 | pages={1462--1477}, 19 | year={2010} 20 | } 21 | 22 | @article{p:potgames2016, 23 | title={A survey of static and dynamic potential games}, 24 | author={Gonz{\'a}lez-S{\'a}nchez, David and Hern{\'a}ndez-Lerma, On{\'e}simo}, 25 | journal={Science China Mathematics}, 26 | volume={59}, 27 | number={11}, 28 | pages={2075--2102}, 29 | year={2016} 30 | } 31 | 32 | @article{p:monderer1996potential, 33 | title={Potential games}, 34 | author={Monderer, Dov and Shapley, Lloyd S}, 35 | journal={Games and economic behavior}, 36 | volume={14}, 37 | number={1}, 38 | pages={124--143}, 39 | year={1996} 40 | } 41 | 42 | 43 | @inproceedings{p:chasparis2011, 44 | title={Perturbed learning automata in potential games}, 45 | author={Chasparis, G.~C. and Shamma,~J.~S. and Rantzer,~A.}, 46 | booktitle={CDC (2011)}, 47 | pages={2453--2458}, 48 | year={2011} 49 | } 50 | 51 | 52 | @inproceedings{p:WANG2014, 53 | title = "A Modified Q-Learning Algorithm for Potential Games", 54 | pages = "8710 - 8718", 55 | year = "2014", 56 | booktitle = "19th IFAC World Congress", 57 | author = "Yatao Wang and Lacra Pavel", 58 | } 59 | 60 | 61 | @article{b:MARDEN2012, 62 | title = "State based potential games", 63 | journal = "Automatica", 64 | volume = "48", 65 | number = "12", 66 | pages = "3075--3088", 67 | year = "2012", 68 | author = "Jason R. Marden", 69 | } 70 | 71 | 72 | @inproceedings{p:distrmaxsum, 73 | title={A distributed anytime algorithm for dynamic task allocation in multi-agent systems}, 74 | author={Macarthur, Kathryn Sarah and Stranders, Ruben and Ramchurn, Sarvapali and Jennings, Nicholas}, 75 | booktitle={25th AAAI Conf. on Artificial Intelligence}, 76 | year={2011} 77 | } 78 | 79 | @article{p:tolmidis2013, 80 | title={Multi-objective optimization for dynamic task allocation in a multi-robot system}, 81 | author={Tolmidis, Avraam Th and Petrou, Loukas}, 82 | journal={Eng. Appl. Artif. Intell.}, 83 | volume={26}, 84 | number={5-6}, 85 | pages={1458--1468}, 86 | year={2013} 87 | } 88 | 89 | @ARTICLE{p:howauction2009, 90 | author={H. {Choi} and L. {Brunet} and J. P. {How}}, journal={IEEE Transactions on Robotics}, 91 | title={Consensus-Based Decentralized Auctions for Robust Task Allocation}, 92 | year={2009}, 93 | volume={25}, 94 | number={4}, 95 | pages={912-926},} 96 | 97 | @inproceedings{p:wolpert1999, 98 | title={General principles of learning-based multi-agent systems}, 99 | author={Wolpert, David H and Wheeler, Kevin R and Tumer, Kagan}, 100 | booktitle={Proceedings of the third annual conference on Autonomous Agents}, 101 | pages={77--83}, 102 | year={1999} 103 | } 104 | 105 | 106 | @book{b:young2020, 107 | title={Individual strategy and social structure: An evolutionary theory of institutions}, 108 | author={Young, H Peyton}, 109 | year={2020}, 110 | publisher={Princeton University Press} 111 | } 112 | 113 | @article{p:marden2009, 114 | title={Joint strategy fictitious play with inertia for potential games}, 115 | author={Marden, J.~R. and Arslan, G. and Shamma,~J.~S.}, 116 | journal={IEEE Transactions on Automatic Control}, 117 | volume={54}, 118 | number={2}, 119 | pages={208--220}, 120 | year={2009}, 121 | publisher={IEEE} 122 | } 123 | 124 | @article{p:fudenberg1998, 125 | title={Learning in games}, 126 | author={Fudenberg, Drew and Levine, David}, 127 | journal={European economic review}, 128 | volume={42}, 129 | number={3-5}, 130 | pages={631--639}, 131 | year={1998}, 132 | publisher={Elsevier} 133 | } 134 | 135 | @inproceedings{p:qpotential2014, 136 | title = "A Modified \textsc{Q}-Learning Algorithm for Potential Games", 137 | pages = "8710 - 8718", 138 | year = "2014", 139 | booktitle = "19th IFAC World Congress", 140 | author = "Yatao Wang and Lacra Pavel", 141 | } 142 | 143 | 144 | @article{p:capitan2013, 145 | title={Decentralized multi-robot cooperation with auctioned \textsc{POMDP}s}, 146 | author={Capitan, Jesus and Spaan, Matthijs TJ and Merino, Luis and Ollero, Anibal}, 147 | journal={The International Journal of Robotics Research}, 148 | volume={32}, 149 | number={6}, 150 | pages={650--671}, 151 | year={2013} 152 | } 153 | 154 | 155 | @article{p:NANJANATH2010, 156 | title = "Repeated auctions for robust task execution by a robot team", 157 | journal = "Robotics and Autonomous Systems", 158 | volume = "58", 159 | number = "7", 160 | pages = "900 - 909", 161 | year = "2010", 162 | author = "Maitreyi Nanjanath and Maria Gini", 163 | } 164 | 165 | @article{p:gerkey2002, 166 | title={Sold!: Auction methods for multirobot coordination}, 167 | author={Gerkey, Brian P and Mataric, Maja J}, 168 | journal={IEEE Transactions on Robotics and Automation}, 169 | volume={18}, 170 | number={5}, 171 | pages={758--768}, 172 | year={2002}, 173 | publisher={IEEE} 174 | } 175 | 176 | @article{p:zivan2015, 177 | title={Distributed constraint optimization for teams of mobile sensing agents}, 178 | author={Zivan, Roie and Yedidsion, Harel and Okamoto, Steven and Glinton, Robin and Sycara, Katia}, 179 | journal={Auton. Agent Multi. Agent Syst.}, 180 | volume={29}, 181 | number={3}, 182 | pages={495--536}, 183 | year={2015} 184 | } 185 | 186 | @article{p:gerkey2004, 187 | author = {Brian P. Gerkey and Maja J. Matarić}, 188 | title ={A Formal Analysis and Taxonomy of Task Allocation in Multi-Robot Systems}, 189 | journal = {The International Journal of Robotics Research}, 190 | volume = {23}, 191 | number = {9}, 192 | pages = {939--954}, 193 | year = {2004}, 194 | } 195 | 196 | @article{p:battin1987, 197 | author = {Richard Battin}, 198 | title = {An Introduction to the Mathematics and Methods of Astrodynamics}, 199 | year = {1987}, 200 | pages = {559--561}, 201 | publisher = {AIAA Education} 202 | } 203 | 204 | @article{p:ravichandar2019, 205 | author = {Ravichandar, Harish and Shaw, Kenneth and Chernova, Sonia}, 206 | year = {2019}, 207 | month = {03}, 208 | journal = {Autonomous Agents and Multi-Agent Systems}, 209 | volume = {34}, 210 | pages = {38}, 211 | title = {STRATA: A Unified Framework for Task Assignments in Large Teams of Heterogeneous Robots} 212 | } 213 | 214 | @article{p:johnson2011, 215 | title={Asynchronous Decentralized Task Allocation for Dynamic Environments}, 216 | author={Luke B. Johnson and Sameera S. Ponda and H. Choi and J. How}, 217 | journal = {Infotech@Aerospace 2011}, 218 | year={2011} 219 | } 220 | 221 | @article{p:lee2018, 222 | title = {Resource-based task allocation for multi-robot systems}, 223 | journal = {Robotics and Autonomous Systems}, 224 | volume = {103}, 225 | pages = {151-161}, 226 | year = {2018}, 227 | issn = {0921-8890}, 228 | author = "Dong-Hyun Lee" 229 | } 230 | 231 | 232 | @inproceedings{p:bakolas2020, 233 | title = "Decentralized Game-Theoretic Control for Dynamic Task Allocation Problems for Multi-Agent Systems", 234 | pages = "", 235 | year = "2021", 236 | booktitle = "2021 American Control Conference (ACC)", 237 | author = "Efstathios Bakolas and Yoonjae Lee", 238 | } 239 | 240 | @article{p:keum2019, 241 | author = {Kim, Keum-Seong and Kim, Ho-Yeon and Choi, Han-Lim}, 242 | year = {2019}, 243 | month = {06}, 244 | pages = {1-6}, 245 | title = {Minimizing Communications in Decentralized Greedy Task Allocation}, 246 | volume = {16}, 247 | journal = {Journal of Aerospace Information Systems} 248 | } 249 | 250 | @article{p:shin2019, 251 | title={Sample Greedy Based Task Allocation for Multiple Robot Systems}, 252 | author={Hyo-Sang Shin and Teng Li and Pau Segui-Gasco}, 253 | year={2019}, 254 | journal={arXiv preprint arXiv:1901.03258} 255 | } 256 | 257 | @article{p:guannan2019, 258 | title = "Distributed greedy algorithm for multi-agent task assignment problem with submodular utility functions", 259 | journal = "Automatica", 260 | volume = "105", 261 | pages = "206 - 215", 262 | year = "2019", 263 | issn = "0005-1098", 264 | author = "Guannan Qu and Dave Brown and Na Li" 265 | } 266 | 267 | @article{p:whitbrook2019, 268 | issn = {0924-669X}, 269 | journal = {Applied intelligence}, 270 | pages = {1--15}, 271 | volume = {49}, 272 | publisher = {Kluwer Academic Publishers}, 273 | number = {1}, 274 | year = {2019}, 275 | title = {Addressing robustness in time-critical, distributed, task allocation algorithms}, 276 | address = {[Dordrecht] :}, 277 | author = {Whitbrook, Amanda and Meng, Qinggang and Chung, Paul W H}, 278 | } 279 | 280 | @article{p:gautier2020, 281 | TITLE = {{Comparison of Market-based and DQN methods for Multi-Robot processing Task Allocation (MRpTA)}}, 282 | AUTHOR = {Gautier, Paul and Johann, Laurent D. and Diguet, Jean-Philippe}, 283 | journal = {{IEEE International Conference on Robotic Computing (IRC)}}, 284 | ADDRESS = {Taichung, Taiwan}, 285 | YEAR = {2020}, 286 | MONTH = Nov, 287 | } 288 | 289 | @article{p:phillips2021, 290 | author = {Sean Phillips and Fernando Parra}, 291 | title = {A Case Study on Auction-Based Task Allocation Algorithms in Multi-Satellite Systems}, 292 | journal = {AIAA Scitech 2021 Forum}, 293 | chapter = {}, 294 | pages = {}, 295 | year={2021} 296 | } 297 | 298 | @article{p:otte2020, 299 | title={Auctions for multi-robot task allocation in communication limited environments}, 300 | author={Otte, Michael and Kuhlman, Michael J and Sofge, Donald}, 301 | journal={Autonomous Robots}, 302 | volume={44}, 303 | number={3}, 304 | pages={547--584}, 305 | year={2020}, 306 | publisher={Springer} 307 | } 308 | 309 | @article{p:hayat2020, 310 | title={Multi-objective drone path planning for search and rescue with quality-of-service requirements}, 311 | author={Hayat, Samira and Yanmaz, Ev{\c{s}}en and Bettstetter, Christian and Brown, Timothy X}, 312 | journal={Autonomous Robots}, 313 | volume={44}, 314 | number={7}, 315 | pages={1183--1198}, 316 | year={2020}, 317 | publisher={Springer} 318 | } 319 | 320 | @article{p:rahili2020, 321 | title={Distributed Adaptive Reinforcement Learning: A Method for Optimal Routing}, 322 | author={Rahili, Salar and Riviere, Benjamin and Chung, Soon-Jo}, 323 | journal={arXiv preprint arXiv:2005.01976}, 324 | year={2020} 325 | } 326 | 327 | @article{p:bakshi2019, 328 | title={Fast Scheduling of Autonomous Mobile Robots Under Task Space Constraints With Priorities}, 329 | author={Bakshi, S. and Feng, T. and Yan, Z. and Chen, D.}, 330 | journal={ASME. J. Dyn. Sys., Meas., Control.}, 331 | year={2019} 332 | } 333 | 334 | @article{p:bakshi2019quad, 335 | author={S. {Bakshi} and T. {Feng} and Z. {Yan} and D. {Chen}}, 336 | journal={2019 American Control Conference (ACC)}, 337 | title={A Regularized Quadratic Programming Approach to Real-Time Scheduling of Autonomous Mobile Robots in a Prioritized Task Space}, 338 | year={2019}, 339 | pages={1361-1366} 340 | } 341 | 342 | @article{p:bakolas2014, 343 | author={E. {Bakolas}}, 344 | journal={2014 American Control Conference}, 345 | title={A decentralized spatial partitioning algorithm based on the minimum control effort metric}, 346 | year={2014}, 347 | volume={}, 348 | number={}, 349 | pages={5264-5269} 350 | } 351 | 352 | @INPROCEEDINGS{p:luo2012, 353 | author={L. {Luo} and N. {Chakraborty} and K. {Sycara}}, 354 | booktitle={2012 IEEE International Conference on Robotics and Automation}, 355 | title={Competitive analysis of repeated greedy auction algorithm for online multi-robot task assignment}, 356 | year={2012}, 357 | volume={}, 358 | number={}, 359 | pages={4792-4799}, 360 | month={May} 361 | } -------------------------------------------------------------------------------- /paper/remark.sty: -------------------------------------------------------------------------------- 1 | %% 2 | %% This file name is ``remark.sty'' 3 | %% 4 | % **************************************** 5 | % * REMARK ENVIRONMENTS * 6 | % **************************************** 7 | % 8 | % The user creates his own remark-like environments with the command 9 | % \newremark{NAME}{TEXT}[COUNTER] or 10 | % \newremark{NAME}[OLDNAME]{TEXT} 11 | % This defines the environment NAME to be just as one would expect a 12 | % remark environment to be, except that it prints ``TEXT'' instead of 13 | % ``Remark''. 14 | % 15 | % If OLDNAME is given, then environments NAME and OLDNAME use the same 16 | % counter, so using a NAME environment advances the number of the next 17 | % NAME environment, and vice-versa. 18 | % 19 | % If COUNTER is given, then environment NAME is numbered within COUNTER. 20 | % E.g., if COUNTER = subsection, then the first NAME in subsection 7.2 21 | % is numbered TEXT 7.2.1. 22 | % 23 | % The way NAME environments are numbered can be changed by redefining 24 | % \theNAME. 25 | % 26 | % DOCUMENT STYLE PARAMETERS 27 | % 28 | % \@rmkcounter{COUNTER} : A command such that 29 | % \edef\theCOUNTER{\@rmkcounter{COUNTER}} 30 | % defines \theCOUNTER to produce a number for a remark environment. 31 | % The default is: 32 | % BEGIN \noexpand\arabic{COUNTER} END 33 | % 34 | % \@rmkcountersep : A separator placed between a remark number and 35 | % the number of the counter within which it is numbered. 36 | % E.g., to make the third remark of section 7.2 be numbered 37 | % 7.2-3, \@rmkcountersep should be \def'ed to '-'. Its 38 | % default is '.'. 39 | % 40 | % \@beginremark{NAME}{NUMBER} : A command that begins a remark 41 | % environment for a 'remark' named 'NAME NUMBER' -- 42 | % e.g., \@beginremark{Lemma}{3.7} starts Lemma 3.7. 43 | % 44 | % \@opargbeginremark{NAME}{NUMBER}{OPARG} : A command that begins a remark 45 | % environment for a 'remark' named 'NAME NUMBER' with optional 46 | % argument OPARG -- e.g., \@beginremark{Lemma}{3.7}{Jones} 47 | % starts `Lemma 3.7 (Jones):'. 48 | % 49 | % \@endremark : A command that ends a remark environment. 50 | % 51 | % \newremark{NAME}{TEXT}[COUNTER] == 52 | % BEGIN 53 | % if \NAME is definable 54 | % then \@definecounter{NAME} 55 | % if COUNTER present 56 | % then \@addtoreset{NAME}{COUNTER} fi 57 | % \theNAME == BEGIN \theCOUNTER \@rmkcountersep 58 | % eval\@rmkcounter{NAME} END 59 | % else \theNAME == BEGIN eval\@rmkcounter{NAME} END 60 | % \NAME == \@rmk{NAME}{TEXT} 61 | % \endNAME == \@endremark 62 | % else error 63 | % fi 64 | % END 65 | % 66 | % \newremark{NAME}[OLDNAME]{TEXT}== 67 | % BEGIN 68 | % if \NAME is definable 69 | % then \theNAME == \theOLDNAME 70 | % \NAME == \@rmk{OLDNAME}{TEXT} 71 | % \endNAME == \@endremark 72 | % else error 73 | % fi 74 | % END 75 | % 76 | % \@rmk{NAME}{TEXT} == 77 | % BEGIN 78 | % \refstepcounter{NAME} 79 | % if next char = [ 80 | % then \@yrmk{NAME}{TEXT} 81 | % else \@xrmk{NAME}{TEXT} 82 | % fi 83 | % END 84 | % 85 | % \@xrmk{NAME}{TEXT} == 86 | % BEGIN 87 | % \@beginremark{TEXT}{\theNAME} 88 | % \ignorespaces 89 | % END 90 | % 91 | % \@yrmk{NAME}{TEXT}[OPARG] == 92 | % BEGIN 93 | % \@opargbeginremark{TEXT}{\theNAME}{OPARG} 94 | % \ignorespaces 95 | % END 96 | % 97 | \def\newremark#1{\@ifnextchar[{\@ormk{#1}}{\@nrmk{#1}}} 98 | 99 | \def\@nrmk#1#2{% 100 | \@ifnextchar[{\@xnrmk{#1}{#2}}{\@ynrmk{#1}{#2}}} 101 | 102 | \def\@xnrmk#1#2[#3]{\expandafter\@ifdefinable\csname #1\endcsname 103 | {\@definecounter{#1}\@addtoreset{#1}{#3}% 104 | \expandafter\xdef\csname the#1\endcsname{\expandafter\noexpand 105 | \csname the#3\endcsname \@rmkcountersep \@rmkcounter{#1}}% 106 | \global\@namedef{#1}{\@rmk{#1}{#2}}\global\@namedef{end#1}{\@endremark}}} 107 | 108 | \def\@ynrmk#1#2{\expandafter\@ifdefinable\csname #1\endcsname 109 | {\@definecounter{#1}% 110 | \expandafter\xdef\csname the#1\endcsname{\@rmkcounter{#1}}% 111 | \global\@namedef{#1}{\@rmk{#1}{#2}}\global\@namedef{end#1}{\@endremark}}} 112 | 113 | \def\@ormk#1[#2]#3{\expandafter\@ifdefinable\csname #1\endcsname 114 | {\global\@namedef{the#1}{\@nameuse{the#2}}% 115 | \global\@namedef{#1}{\@rmk{#2}{#3}}% 116 | \global\@namedef{end#1}{\@endremark}}} 117 | 118 | \def\@rmk#1#2{\refstepcounter 119 | {#1}\@ifnextchar[{\@yrmk{#1}{#2}}{\@xrmk{#1}{#2}}} 120 | 121 | \def\@xrmk#1#2{\@beginremark{#2}{\csname the#1\endcsname}\ignorespaces} 122 | \def\@yrmk#1#2[#3]{\@opargbeginremark{#2}{\csname 123 | the#1\endcsname}{#3}\ignorespaces} 124 | 125 | %DEFAULT VALUES 126 | \def\@rmkcounter#1{\noexpand\arabic{#1}} 127 | \def\@rmkcountersep{.} 128 | %deleted September 2, 1986 MDK 129 | %\def\@makermknumber#1#2{\bf #1 #2:} 130 | \def\@beginremark#1#2{\trivlist \item[\hskip \labelsep{\bf #1\ #2}]} 131 | \def\@opargbeginremark#1#2#3{\trivlist 132 | \item[\hskip \labelsep{\bf #1\ #2\ (#3)}]} 133 | \def\@endremark{\endtrivlist} 134 | 135 | 136 | -------------------------------------------------------------------------------- /paper/task_alloc_inkscape.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/paper/task_alloc_inkscape.pdf -------------------------------------------------------------------------------- /src/ComputeCommandParams.m: -------------------------------------------------------------------------------- 1 | function [a, b, rho] = ComputeCommandParams(pos_a_curr, v_a_curr, pos_t_curr, tf) 2 | % 3 | a = 6/tf^2 * (pos_t_curr - pos_a_curr) - 4/tf * v_a_curr; 4 | b = -12/tf^3 * (pos_t_curr - pos_a_curr) + 6/tf^2 * v_a_curr; 5 | rho = 1/2 * (tf * norm(a)^2 + tf^2 * a*b' + (1/3) * tf^3 * norm(b)^2); 6 | 7 | end 8 | 9 | -------------------------------------------------------------------------------- /src/ComputeCommandParamsWithVelocity.m: -------------------------------------------------------------------------------- 1 | function [u, r, v, t, rho] = ComputeCommandParamsWithVelocity(pos_a_curr, v_a_curr, pos_t_curr, v_t, tf, t, kdrag) 2 | 3 | t0 = 0; 4 | t1 = tf; 5 | r0 = pos_a_curr; 6 | r1 = pos_t_curr; 7 | v0 = v_a_curr; 8 | v1 = v_t; 9 | 10 | %if norm(pos_a_curr - pos_t_curr) / norm(pos_a_curr) < 1e-2 11 | 12 | if isempty(t) 13 | t = [t0 t1]; 14 | end 15 | 16 | dydt = @(t,y) [y(3:4); 4/(t1-t) * (v1 - y(3:4)) + 6/(t1-t)^2 * (r1 - (y(1:2) + v1*(t1 - t)))]; 17 | 18 | 19 | %options = odeset('RelTol',1e-4); 20 | %[t,y] = ode23s(dydt, t, [r0; v0], options); 21 | [t,y] = ode45(dydt, t, [r0; v0]); %, options); 22 | 23 | r = y(:,1:2); 24 | v = y(:,3:4); 25 | a = zeros(size(v)); 26 | norm2_a = zeros(length(t),1); 27 | 28 | for i = 1:length(t) 29 | a(i,:) = 4/(t1-t(i)) .* (v1' - v(i,:)) + 6/(t1-t(i)).^2 .* (r1' - (r(i,:) + v1'.*(t1 - t(i)))); 30 | norm2_a(i) = norm(a(i,:)).^2; 31 | end 32 | 33 | a(isnan(a) | isinf(a)) = 0; 34 | norm2_a(isnan(norm2_a) | isinf(norm2_a)) = 0; 35 | 36 | rho = 1/2 * trapz(t,norm2_a); 37 | u = a; 38 | 39 | end -------------------------------------------------------------------------------- /src/Copy_of_OptimalControl.m: -------------------------------------------------------------------------------- 1 | %% Decentralized Control for Dynamic Task Allocation Problems for Multi-Agent Systems with Auctions 2 | % Author: Martin Braquet 3 | % Date: September 2020 4 | 5 | addpath('GreedyCoalitionAuctionAlgorithm/'); 6 | close all; clear all; 7 | rng('default'); 8 | rng(9); 9 | 10 | [ComputeOpt ComputeSGA ComputeGCAA] = deal(0,0,1); 11 | CommLimit = 1; 12 | use_GCAA = 1; 13 | use_OPT = 0; 14 | 15 | na = 50; 16 | nt = 50; 17 | Lt = nt; 18 | 19 | map_width = 1; 20 | comm_distance = 2 * map_width; 21 | 22 | simu_time = 10; 23 | n_rounds = 1000; 24 | time_step = simu_time / n_rounds; 25 | 26 | pos_a = rand(na,2) * map_width; 27 | pos_t = rand(nt,2) * map_width; 28 | %tf_t = rand(nt,1) * simu_time; 29 | %tf_t = [5*ones(1,3) 10*ones(1,1)]; 30 | tf_t = 2 * (1 + 0.05 * rand(nt,2)); 31 | %tf_t = 10*ones(1,nt); 32 | 33 | [tf_t, idx] = sort(tf_t); 34 | pos_t = pos_t(idx,:); 35 | 36 | %velocity = 1:na; 37 | %velocity = 1 * ones(1,nt); 38 | max_speed = 0.1; 39 | v_a = (2 * rand(na,2) - 1) * max_speed; 40 | 41 | % Reward after task completion 42 | r_bar = rand(nt,1); 43 | %r_bar = ones(nt,1); 44 | 45 | % Probability that agent i successfully completes task j 46 | prob_a_t = rand(na,nt); 47 | %prob_a_t = 1*ones(na,nt); 48 | 49 | Tasks.r_bar = r_bar; 50 | Tasks.prob_a_t = prob_a_t; 51 | 52 | Agents.N = na; 53 | Agents.Lt = Lt * ones(1,na); 54 | Agents.v_a = v_a; 55 | 56 | costs = zeros(na, nt); 57 | utility = zeros(na, nt); 58 | rewards = zeros(na, nt); 59 | for i = 1:na 60 | for j = 1:nt 61 | [~, ~, costs(i,j)] = ComputeCommandParams(pos_a(i,:), v_a(i,:), pos_t(j,:), tf_t(j)); 62 | rewards(i,j) = r_bar(j) * prob_a_t(i,j); 63 | winners = zeros(na,nt); 64 | winners(i,j) = 1; 65 | utility(i,j) = CalcTaskUtility(pos_a, v_a, pos_t(j,:), tf_t(j), r_bar(j), j, prob_a_t, winners); 66 | end 67 | end 68 | 69 | % Fully connected graph 70 | G = ~eye(Agents.N); 71 | 72 | figure; hold on; 73 | colors = lines(na); 74 | 75 | %while 1 76 | 77 | clf; hold on; 78 | xlim([0 map_width]); 79 | ylim([0 map_width]); 80 | xlabel('x [m]'); 81 | ylabel('y [m]'); 82 | title('Task-Agent allocation'); 83 | for i = 1:na 84 | plot(pos_a(i,1), pos_a(i,2), '*', 'Color', colors(i,:), 'MarkerSize', 10, 'DisplayName', 'Agents'); 85 | end 86 | plot(pos_t(:,1), pos_t(:,2),'rs', 'MarkerSize', 10, 'DisplayName', 'Targets', 'MarkerFaceColor',[1 .6 .6]); 87 | PlotAgentRange(pos_a, comm_distance, colors, 'Comm Range') 88 | 89 | Agents.Pos = pos_a; 90 | 91 | Tasks.Pos = pos_t; 92 | Tasks.N = nt; 93 | Tasks.tf = tf_t; 94 | 95 | if CommLimit 96 | for i = 1:na 97 | for j = (i+1):na 98 | G(i,j) = norm(pos_a(i,:) - pos_a(j,:)) < comm_distance; 99 | G(j,i) = G(i,j); 100 | end 101 | end 102 | end 103 | 104 | if use_GCAA 105 | % GCAA solution 106 | tic; [S_GCAA, p_GCAA, S_GCAA_ALL] = GCAASolution(Agents, G, Tasks) 107 | toc; 108 | else 109 | % Test of fixed solution 110 | p_GCAA = {[1 4], [2 4], [3 4]}; S_GCAA = 1; 111 | end 112 | 113 | if use_OPT 114 | tic; [S_OPT, p_OPT, S_OPT_ALL] = OptimumSolution(Agents, G, Tasks) 115 | toc; 116 | end 117 | 118 | % Find the optimal control solution for the given allocation p_GCAA 119 | X = OptimalControlSolution(pos_a, v_a, pos_t, p_GCAA, tf_t, time_step, n_rounds, na); 120 | PlotAlloc(X, n_rounds, na, colors, 'GCAA solution'); 121 | 122 | legend(legendUnq(gca)); 123 | drawnow; 124 | 125 | % [p_GCAA, pos_a, ind_completed_tasks, nt, Agents] = UpdatePath(p_GCAA, pos_a, pos_t, time_step, Agents, nt); 126 | % 127 | % stop = 1; 128 | % for i = 1:na 129 | % if ~isempty(p_GCAA{i}) 130 | % stop = 0; 131 | % break; 132 | % end 133 | % end 134 | 135 | 136 | % if (stop) 137 | % break; 138 | % end 139 | 140 | % pos_t = RemoveCompletedTasks(pos_t, ind_completed_tasks); 141 | %end 142 | 143 | 144 | function PlotAlloc(X, n_rounds, na, color, name) 145 | 146 | for i = 1:na 147 | xx = reshape(X(:,i,:),[4,n_rounds+1]); 148 | plot(xx(1,:),xx(2,:), ':', 'Color', color(i,:), 'LineWidth', 2, 'DisplayName', name); 149 | end 150 | 151 | end 152 | 153 | function PlotAgentRange(pos_a, comm_distance, color, name) 154 | n = 20; 155 | theta = linspace(0, 2*pi, n)'; 156 | for i = 1:size(pos_a,1) 157 | pos = repmat(pos_a(i,:), n, 1) + comm_distance * [cos(theta) sin(theta)]; 158 | plot(pos(:,1), pos(:,2), '--', 'Color', color(i,:), 'LineWidth', 1, 'DisplayName', name); 159 | end 160 | end 161 | 162 | function pos_t_new = RemoveCompletedTasks(pos_t, ind) 163 | 164 | pos_t_new = zeros(size(pos_t,1)-length(ind),2); 165 | k = 1; 166 | for t = 1:size(pos_t,1) 167 | if ~sum(ind == t) 168 | pos_t_new(k,:) = pos_t(t,:); 169 | k = k + 1; 170 | end 171 | end 172 | 173 | end 174 | 175 | function [p, pos_a, ind_completed_tasks, nt, Agents] = UpdatePath(p, pos_a, pos_t, time_step, Agents, nt) 176 | ind_completed_tasks = []; 177 | 178 | for i = 1:size(pos_a,1) 179 | if ~isempty(p{i}) 180 | d_a_t = pos_t(p{i}(1),:) - pos_a(i,:); 181 | if (norm(d_a_t) < time_step * Agents.Speed(i)) 182 | pos_a(i,:) = pos_t(p{i}(1),:); 183 | nt = nt - 1; 184 | Agents.Lt(i) = Agents.Lt(i) - 1; 185 | ind_completed_tasks = [ind_completed_tasks p{i}(1)]; 186 | %if (nt == 0) 187 | % break; 188 | %end 189 | p{i} = p{i}(2:end); 190 | % if ~isempty(p{i}) 191 | % time_step_remaining = time_step - norm(d_a_t) / Agents.Speed(i); 192 | % d_a_next_t = pos_t(p{i}(1),:) - pos_a(i,:); 193 | % pos_a(i,:) = pos_a(i,:) + d_a_next_t / norm(d_a_next_t) * time_step_remaining * Agents.Speed(i); 194 | % end 195 | else 196 | pos_a(i,:) = pos_a(i,:) + d_a_t / norm(d_a_t) * time_step * Agents.Speed(i); 197 | end 198 | end 199 | end 200 | end 201 | 202 | %% Optimal control solution 203 | % for a double integrator dynamics and minimizing the square of the input command along the path 204 | % Params: p_GCAA: task allocation 205 | % Output: X: (n_rounds x na x 4) matrix corresponding to the (x,y) position and velocity of 206 | % each agents for each round (n_rounds = tf/time_step) 207 | function [X] = OptimalControlSolution(pos_a, v_a, pos_t, p_GCAA, tf_t, time_step, n_rounds, na) 208 | X = zeros(4, na, n_rounds+1); 209 | A = [zeros(2,2) eye(2,2); zeros(2,2) zeros(2,2)]; 210 | B = [zeros(2,2); eye(2,2)]; 211 | for i = 1:na 212 | k = 0; 213 | for j = 1:size(p_GCAA{i},2) 214 | ind_task = p_GCAA{i}(j); 215 | tf = tf_t(ind_task); 216 | if j > 1 217 | tf = tf - tf_t(p_GCAA{i}(j-1)); 218 | end 219 | if j == 1 220 | X(:, i, 1) = [pos_a(i,:) v_a(i,:)]; 221 | end 222 | pos_t_curr = pos_t(ind_task,:)'; 223 | pos_a_curr = X(1:2, i, k+1); 224 | v_a_curr = X(3:4, i, k+1); 225 | 226 | [a, b,] = ComputeCommandParams(pos_a_curr, v_a_curr, pos_t_curr, tf); 227 | 228 | t = 0; 229 | while t + time_step <= tf 230 | u = a + b*t; 231 | X(:, i, k+2) = X(:, i, k+1) + time_step * (A * X(:, i, k+1) + B * u); 232 | t = t + time_step; 233 | k = k + 1; 234 | end 235 | end 236 | for k2 = k+2:n_rounds+1 237 | X(:,i,k2) = X(:,i,k+1); 238 | end 239 | end 240 | end 241 | -------------------------------------------------------------------------------- /src/GenerateFiguresFixedTime.m: -------------------------------------------------------------------------------- 1 | close all; clear all; 2 | 3 | simu_number = 6; 4 | PlotCommLimit = 0; 5 | saveMovie = 0; 6 | 7 | nRatioPointsFigure = 10; 8 | lineWidthFigure = 2; 9 | markerSizeFigure = 12; 10 | 11 | load(sprintf('mat/Dynamics/simu_%d/SimuParamsCell.mat', simu_number)); 12 | 13 | for t_plot = [0 4 10] 14 | for CommLimit = [0 1] 15 | load(sprintf('mat/Dynamics/simu_%d/X_just_saved_CommLimit_%d.mat', simu_number, CommLimit)); 16 | load(sprintf('mat/Dynamics/simu_%d/J_to_completion_target_CommLimit_%d.mat', simu_number, CommLimit)); 17 | load(sprintf('mat/Dynamics/simu_%d/J_CommLimit_%d.mat', simu_number, CommLimit)); 18 | load(sprintf('mat/Dynamics/simu_%d/p_GCAA_just_saved_CommLimit_%d.mat', simu_number, CommLimit)); 19 | load(sprintf('mat/Dynamics/simu_%d/S_GCAA_ALL_just_saved_CommLimit_%d.mat', simu_number, CommLimit)); 20 | load(sprintf('mat/Dynamics/simu_%d/rt_just_saved_CommLimit_%d.mat', simu_number, CommLimit)); 21 | 22 | figure; hold on; PlotAllocTime(X_full_simu, t_plot, SimuParamsCell.time_step, SimuParamsCell.pos_t, SimuParamsCell.map_width, SimuParamsCell.colors, SimuParamsCell.radius_t, SimuParamsCell.task_type, nRatioPointsFigure, lineWidthFigure, markerSizeFigure); 23 | sprintf('Alloc_5_5_t_%1.0f_CommLimit_%d.tex',t_plot, CommLimit) 24 | matlab2tikz(sprintf('mat/Dynamics/simu_%d/Alloc_5_5_t_%1.0f_CommLimit_%d.tex',simu_number,t_plot, CommLimit)); 25 | end 26 | end -------------------------------------------------------------------------------- /src/GenerateFiguresParamsAnalysis.m: -------------------------------------------------------------------------------- 1 | close all; clear all; 2 | 3 | simuName = 'Variation of parameters'; 4 | lineWidth = 3; 5 | 6 | AllParamsToAnalyze = {'RangeLimitation', 'RewardSuccessProbability', 'NumberAgentsTasks', 'TimeRatioLoiteringTasks'}; 7 | 8 | %% 9 | 10 | paramToAnalyze = AllParamsToAnalyze{1}; 11 | simuNumber = 1; 12 | load(sprintf('mat/%s/%s/simu_%d/ratioRangeMapWidth-%d.mat', simuName, paramToAnalyze, simuNumber)); 13 | load(sprintf('mat/%s/%s/simu_%d/totalUtilityAllocation-%d.mat', simuName, paramToAnalyze, simuNumber)); 14 | load(sprintf('mat/%s/%s/simu_%d/SimuParamsCell.mat', simuName, paramToAnalyze, simuNumber)); 15 | 16 | figure; 17 | plot(ratioRangeMapWidth, totalUtilityAllocation, 'LineWidth', lineWidth); 18 | ylim([0 max(totalUtilityAllocation)*1.1]); 19 | xlabel('Communication range'); 20 | ylabel('Utility'); 21 | matlab2tikz(sprintf('mat/%s/%s/simu_%d/RangeLimitationUtility.tex', simuName, paramToAnalyze, simuNumber)); 22 | 23 | %% 24 | 25 | paramToAnalyze = AllParamsToAnalyze{2}; 26 | simuNumber = 1; 27 | 28 | load(sprintf('mat/%s/%s/simu_%d/nomReward-%d.mat', simuName, paramToAnalyze, simuNumber)); 29 | load(sprintf('mat/%s/%s/simu_%d/nomProbAT-%d.mat', simuName, paramToAnalyze, simuNumber)); 30 | load(sprintf('mat/%s/%s/simu_%d/totalUtilityAllocation-%d.mat', simuName, paramToAnalyze, simuNumber)); 31 | load(sprintf('mat/%s/%s/simu_%d/SimuParamsCell.mat', simuName, paramToAnalyze, simuNumber)); 32 | 33 | figure; 34 | [mechNomReward, meshNomProbAT] = meshgrid(nomReward, nomProbAT); 35 | surf(mechNomReward, meshNomProbAT, totalUtilityAllocation); 36 | xlabel('Nominal reward'); 37 | ylabel('Task success probability'); 38 | zlabel('Utility'); 39 | matlab2tikz(sprintf('mat/%s/%s/simu_%d/RewardSuccessProbabilityUtility.tex', simuName, paramToAnalyze, simuNumber)); 40 | 41 | %% 42 | 43 | paramToAnalyze = AllParamsToAnalyze{3}; 44 | simuNumber = 3; 45 | 46 | load(sprintf('mat/%s/%s/simu_%d/nAVect-%d.mat', simuName, paramToAnalyze, simuNumber)); 47 | load(sprintf('mat/%s/%s/simu_%d/nTVect-%d.mat', simuName, paramToAnalyze, simuNumber)); 48 | load(sprintf('mat/%s/%s/simu_%d/totalUtilityAllocation-%d.mat', simuName, paramToAnalyze, simuNumber)); 49 | load(sprintf('mat/%s/%s/simu_%d/totalComputationTime-%d.mat', simuName, paramToAnalyze, simuNumber)); 50 | load(sprintf('mat/%s/%s/simu_%d/SimuParamsCell.mat', simuName, paramToAnalyze, simuNumber)); 51 | 52 | [mechnAVect, meshnTVect] = meshgrid(nAVect, nTVect); 53 | 54 | figure; 55 | surf(mechnAVect, meshnTVect, totalUtilityAllocation); 56 | xlabel('Number of agents'); 57 | ylabel('Number of tasks'); 58 | zlabel('Utility'); 59 | matlab2tikz(sprintf('mat/%s/%s/simu_%d/nTnAUtility.tex', simuName, paramToAnalyze, simuNumber)); 60 | 61 | figure; 62 | surf(mechnAVect, meshnTVect, totalComputationTime); 63 | xlabel('Number of agents'); 64 | ylabel('Number of tasks'); 65 | zlabel('Computation time'); 66 | matlab2tikz(sprintf('mat/%s/%s/simu_%d/nTnAComputationTime.tex', simuName, paramToAnalyze, simuNumber)); 67 | 68 | %% 69 | 70 | paramToAnalyze = AllParamsToAnalyze{4}; 71 | simuNumber = 1; 72 | 73 | load(sprintf('mat/%s/%s/simu_%d/ntLoiterVect-%d.mat', simuName, paramToAnalyze, simuNumber)); 74 | load(sprintf('mat/%s/%s/simu_%d/totalUtilityAllocation-%d.mat', simuName, paramToAnalyze, simuNumber)); 75 | load(sprintf('mat/%s/%s/simu_%d/totalComputationTime-%d.mat', simuName, paramToAnalyze, simuNumber)); 76 | load(sprintf('mat/%s/%s/simu_%d/SimuParamsCell.mat', simuName, paramToAnalyze, simuNumber)); 77 | 78 | % figure; 79 | % plot(ntLoiterVect, totalUtilityAllocation, 'LineWidth', lineWidth); 80 | % ylim([0 max(totalUtilityAllocation)*1.1]); 81 | % xlabel('Ratio of loitering tasks'); 82 | % ylabel('Utility'); 83 | % matlab2tikz(sprintf('mat/%s/%s/simu_%d/ntLoiterUtility.tex', simuName, paramToAnalyze, simuNumber)); 84 | 85 | figure; 86 | plot(ntLoiterVect, totalComputationTime, 'LineWidth', lineWidth); 87 | ylim([0 max(totalComputationTime)*1.1]); 88 | xlabel('Ratio of loitering tasks'); 89 | ylabel('Computation time'); 90 | matlab2tikz(sprintf('mat/%s/%s/simu_%d/ntLoiterComputationTime.tex', simuName, paramToAnalyze, simuNumber)); 91 | 92 | % figure; 93 | % yyaxis left 94 | % plot(ntLoiterVect, totalUtilityAllocation, 'LineWidth', lineWidth); hold on; 95 | % ylim([0 max(totalUtilityAllocation)*1.1]); 96 | % xlabel('Ratio of loitering tasks'); 97 | % ylabel('Utility'); 98 | % yyaxis right 99 | % plot(ntLoiterVect, totalComputationTime, 'LineWidth', lineWidth); 100 | % %grid; 101 | % ylabel('Computation time'); 102 | % matlab2tikz(sprintf('mat/%s/%s/simu_%d/ntLoiterUtilityComputationTime.tex', simuName, paramToAnalyze, simuNumber)); -------------------------------------------------------------------------------- /src/GenerateMoviesFigures.m: -------------------------------------------------------------------------------- 1 | close all; clear all; 2 | 3 | simu_number = 7; 4 | CommLimit = 1; 5 | PlotCommLimit = 0; 6 | saveMovie = 0; 7 | 8 | load(sprintf('mat/Dynamics/simu_%d/X_just_saved_CommLimit_%d.mat', simu_number, CommLimit)); 9 | load(sprintf('mat/Dynamics/simu_%d/J_to_completion_target_CommLimit_%d.mat', simu_number, CommLimit)); 10 | load(sprintf('mat/Dynamics/simu_%d/J_CommLimit_%d.mat', simu_number, CommLimit)); 11 | load(sprintf('mat/Dynamics/simu_%d/p_GCAA_just_saved_CommLimit_%d.mat', simu_number, CommLimit)); 12 | load(sprintf('mat/Dynamics/simu_%d/S_GCAA_ALL_just_saved_CommLimit_%d.mat', simu_number, CommLimit)); 13 | load(sprintf('mat/Dynamics/simu_%d/rt_just_saved_CommLimit_%d.mat', simu_number, CommLimit)); 14 | load(sprintf('mat/Dynamics/simu_%d/SimuParamsCell.mat', simu_number)); 15 | 16 | filename = sprintf('mat/Dynamics/MAllocUtil_%d.mat', CommLimit); 17 | MAllocUtil = PlotAnimationAndUtility(X_full_simu, SimuParamsCell, J, J_to_completion_target, rt_full_simu, PlotCommLimit, saveMovie, filename); 18 | if saveMovie 19 | save(sprintf('mat/Dynamics/MAllocUtil_%d.mat', CommLimit), 'MAllocUtil'); 20 | end 21 | 22 | %MAlloc = PlotAnimation(X_full_simu, n_rounds, time_step, pos_t_initial, map_width, colors, radius_t, task_type); 23 | % save(sprintf('mat/MAlloc_%d.mat', k), 'MAllocUtil'); 24 | 25 | % v = VideoWriter('Film_alloc_5_5.avi'); 26 | % v.Quality = 100; 27 | % open(v); 28 | % writeVideo(v,MAllocUtil); 29 | % close(v); 30 | 31 | 32 | 33 | % for t_plot = [0 3 9.9] 34 | % figure; hold on; PlotAllocTime(X_full_simu, t_plot, time_step, pos_t_initial, map_width, colors, radius_t, task_type); 35 | % sprintf('Alloc_5_5_t_%d.tex',t_plot) 36 | % matlab2tikz(sprintf('Alloc_5_5_t_%d.tex',t_plot)); 37 | % figure; hold on; PlotAllocTime(X_full_simu_range, t_plot, time_step, pos_t_initial, map_width, colors, radius_t, task_type); 38 | % matlab2tikz(sprintf('Alloc_range_5_5_t_%d.tex',t_plot)); 39 | % end -------------------------------------------------------------------------------- /src/GreedyCoalitionAuctionAlgorithm/CalcTaskUtility.m: -------------------------------------------------------------------------------- 1 | function [U] = CalcTaskUtility(agent_pos, agent_va, task_pos, task_vt, task_tf, task_value, j, prob_a_t, winners, lambda, kdrag) 2 | prod_all = prod(1 - winners(:,j).*prob_a_t(:,j)); 3 | 4 | rt = task_value * (1 - prod_all); 5 | 6 | Rt = 0; 7 | 8 | assigned_agents = find(winners(:,j) == 1)'; 9 | if isempty(assigned_agents) 10 | U = 0; 11 | else 12 | for i = assigned_agents 13 | [~, ~, ~, ~, rho] = ComputeCommandParamsWithVelocity(agent_pos(i,:)', agent_va(i,:)', task_pos', task_vt', task_tf, [], kdrag); 14 | Rt = Rt + rho; 15 | end 16 | U = rt - lambda * Rt; 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /src/GreedyCoalitionAuctionAlgorithm/CalcUtility.m: -------------------------------------------------------------------------------- 1 | function [rin, vt, U] = CalcUtility(agent_pos, agent_va, task_pos, task_v, task_type, task_radius, task_tloiter, task_tf, task_value, b, i, prob_a_t, N, winners, lambda, kdrag) 2 | U = 0; 3 | old_tf = 0; 4 | 5 | % No assignment if same end time for two tasks in the sequence 6 | for j = 1:length(b) 7 | if j ~= 1 && task_tf(b(j)) == task_tf(b(j-1)) 8 | return; 9 | end 10 | end 11 | 12 | 13 | for j = b 14 | [rin, vt, dU] = compute_dU(winners, j, agent_pos, agent_va, task_pos, task_v, task_type, task_radius, task_tloiter, task_tf, task_value, i, prob_a_t, N, lambda, old_tf, kdrag); 15 | 16 | U = U + dU; 17 | end 18 | end 19 | 20 | function [rin, vt, dU] = compute_dU(allocations, j, agent_pos, agent_va, task_pos, task_v, task_type, task_radius, task_tloiter, task_tf, task_value, i, prob_a_t, N, lambda, old_tf, kdrag) 21 | prod_others = prod(1 - allocations([1:(i-1) (i+1):N],j).*prob_a_t([1:(i-1) (i+1):N],j)); 22 | r_without_a = task_value(j) * (1 - prod_others); 23 | r_with_a = task_value(j) * (1 - prod_others * (1 - prob_a_t(i,j))); 24 | 25 | tf = task_tf(j) - old_tf; 26 | old_tf = old_tf + tf; 27 | if task_type(j) == 0 28 | [~, ~, ~, ~, rho] = ComputeCommandParamsWithVelocity(agent_pos', agent_va', task_pos(j,:)', task_v(j,:)', tf, [], kdrag); 29 | rin = task_pos(j,:)'; 30 | vt = task_v(j,:)'; 31 | else 32 | [rin, vt, rho] = MinimumCostAlongLoitering(agent_pos, agent_va, task_pos, task_radius, task_tloiter, task_tf, j, kdrag); 33 | end 34 | 35 | dU = (r_with_a - r_without_a) - lambda * rho; 36 | end 37 | 38 | function [rin, vt, rho] = MinimumCostAlongLoitering(agent_pos, agent_va, task_pos, task_radius, task_tloiter, task_tf, j, kdrag) 39 | norm_vt = 2*pi * task_radius(j) / task_tloiter(j); 40 | rho = 1e16; 41 | for theta = linspace(0.05, 2*pi*0.9, 10) 42 | rin_new = task_pos(j,:)' + task_radius(j) * [cos(theta); sin(theta)]; 43 | for rot_turn = [-1 1] 44 | vt_new = rot_turn * [0 1; -1 0] * (rin_new - task_pos(j,:)') * norm_vt / norm(rin_new - task_pos(j,:)'); 45 | [u, ~, ~, ~, rho_new] = ComputeCommandParamsWithVelocity(agent_pos', agent_va', rin_new, vt_new, task_tf(j) - task_tloiter(j), [], kdrag); 46 | if rho_new < rho 47 | rho = rho_new; 48 | rin = rin_new; 49 | vt = vt_new; 50 | u_opt = u; 51 | end 52 | end 53 | end 54 | norm_a = norm(vt)^2 / task_radius(j); 55 | rho = rho + 1/2 * (norm_a)^2 * task_tloiter(j); 56 | end 57 | -------------------------------------------------------------------------------- /src/GreedyCoalitionAuctionAlgorithm/GCAASolution.m: -------------------------------------------------------------------------------- 1 | %% Computes the solution of the GCAA for the task-assignment problem 2 | % Main part of the code comes from MAS Project - Distributed Tasking Algorithm 3 | % Control Science Group, Temasek Laboratory 4 | % Author: Martin Braquet 5 | % Date: August 31, 2020 6 | 7 | function [S_GCAA, p, S_GCAA_ALL, rt, Agents] = GCAASolution(Agents, G, TasksCells) 8 | 9 | na = Agents.N; 10 | pos_a = Agents.Pos; 11 | 12 | nt = TasksCells.N; 13 | pos_t = TasksCells.Pos; 14 | 15 | %---------------------------------------------------------------------% 16 | % Initialize global variables 17 | %---------------------------------------------------------------------% 18 | 19 | %WORLD.CLR = rand(100,3); 20 | 21 | %---------------------------------------------------------------------% 22 | % Define agents and tasks 23 | %---------------------------------------------------------------------% 24 | % Grab agent and task types from GCAA Parameter definitions 25 | GCAA_Params = GCAA_Init(0,0,TasksCells.prob_a_t,TasksCells.lambda); 26 | 27 | % Initialize possible agent fields 28 | agent_default.id = 0; % agent id 29 | agent_default.type = 0; % agent type 30 | agent_default.avail = 0; % agent availability (expected time in sec) 31 | agent_default.clr = []; % for plotting 32 | 33 | agent_default.x = 0; % agent position (meters) 34 | agent_default.y = 0; % agent position (meters) 35 | agent_default.z = 0; % agent position (meters) 36 | agent_default.nom_vel = 0; % agent cruise velocity (m/s) 37 | agent_default.fuel = 0; % agent fuel penalty (per meter) 38 | agent_default.Lt = 0; % agent max number of tasks 39 | agent_default.v_a = [0 0]; % 40 | agent_default.rin_task = []; 41 | agent_default.vin_task = []; 42 | agent_default.previous_task = []; 43 | agent_default.previous_winnerBids = []; 44 | agent_default.kdrag = 0; 45 | 46 | % FOR USER TO DO: Set agent fields for specialized agents, for example: 47 | % agent_default.util = 0; 48 | 49 | % Initialize possible task fields 50 | task_default.id = 0; % task id 51 | task_default.type = 0; % task type 52 | task_default.value = 0; % task reward 53 | task_default.start = 0; % task start time (sec) 54 | task_default.end = 0; % task expiry time (sec) 55 | task_default.duration = 0; % task default duration (sec) 56 | task_default.tf = 0; % task default duration (sec) 57 | %task_default.lambda = 0.95; % task exponential discount 58 | 59 | task_default.x = 0; % task position (meters) 60 | task_default.y = 0; % task position (meters) 61 | task_default.z = 0; % task position (meters) 62 | task_default.Speed = 0; % 63 | task_default.type = 0; % 64 | task_default.radius = 0; % 65 | task_default.tloiter = 0; % 66 | 67 | % FOR USER TO DO: Set task fields for specialized tasks 68 | 69 | %---------------------------% 70 | 71 | % Create some default agents 72 | 73 | % QUAD 74 | agent_quad = agent_default; 75 | agent_quad.type = GCAA_Params.AGENT_TYPES.QUAD; % agent type 76 | agent_quad.nom_vel = 0; % agent cruise velocity (m/s) 77 | agent_quad.fuel = 1; % agent fuel penalty (per meter) 78 | 79 | % Create some default tasks 80 | 81 | % Track 82 | task_track = task_default; 83 | task_track.type = GCAA_Params.TASK_TYPES.TRACK; % task type 84 | task_track.value = 0; % task reward 85 | task_track.duration = 0; %600; % task default duration (sec) 86 | 87 | 88 | %---------------------------------------------------------------------% 89 | % Define sample scenario 90 | %---------------------------------------------------------------------% 91 | 92 | % Create random agents 93 | for n=1:na 94 | agents(n) = agent_quad; 95 | 96 | % Init remaining agent params 97 | agents(n).id = n; 98 | agents(n).x = pos_a(n,1); 99 | agents(n).y = pos_a(n,2); 100 | agents(n).z = 0; 101 | agents(n).v_a = Agents.v_a(n,:); 102 | agents(n).Lt = Agents.Lt(n); 103 | agents(n).rin_task = []; 104 | agents(n).vin_task = []; 105 | agents(n).previous_task = Agents.previous_task(n); 106 | agents(n).previous_winnerBids = Agents.previous_winnerBids(n); 107 | agents(n).kdrag = Agents.kdrag; 108 | %agents(n).clr = WORLD.CLR(n,:); 109 | end 110 | 111 | % Create random tasks 112 | for m=1:nt 113 | tasks(m) = task_track; 114 | tasks(m).id = m; 115 | tasks(m).start = 0; % task start time (sec) 116 | tasks(m).end = 1e20; %tasks(m).start + 1*tasks(m).duration; % task expiry time (sec) 117 | tasks(m).x = pos_t(m,1); 118 | tasks(m).y = pos_t(m,2); 119 | tasks(m).z = 0; 120 | tasks(m).tf = TasksCells.tf(m); 121 | tasks(m).value = TasksCells.r_bar(m); 122 | tasks(m).Speed = TasksCells.Speed(m); 123 | tasks(m).type = TasksCells.task_type(m); 124 | tasks(m).radius = TasksCells.radius(m); 125 | tasks(m).tloiter = TasksCells.tloiter(m); 126 | end 127 | 128 | %---------------------------------------------------------------------% 129 | % Run GCAA 130 | %---------------------------------------------------------------------% 131 | %tic 132 | [GCAA_Assignments, S_GCAA_agents, S_GCAA_ALL_agents, agents] = GCAA_Main(agents, tasks, G, TasksCells.prob_a_t, TasksCells.lambda); 133 | %toc 134 | %PlotAssignments(WORLD, GCAA_Assignments, agents, tasks, 1); 135 | %PlotAssignments2D(WORLD, GCAA_Assignments, agents, tasks, 3); 136 | 137 | p{na} = []; 138 | 139 | for i = 1:na 140 | p{i} = GCAA_Assignments(i).path; 141 | 142 | ind = find(p{i} == -1); 143 | if ~isempty(ind) 144 | p{i} = p{i}(1:(ind(1)-1)); 145 | end 146 | end 147 | 148 | 149 | winners = zeros(na,1); 150 | for i = 1:na 151 | if ~isempty(p{i}) 152 | winners(i) = p{i}; 153 | end 154 | end 155 | winners_matrix = WinnerVectorToMatrix(na, nt, winners); 156 | 157 | S_GCAA_ALL = zeros(1,nt); 158 | rt = zeros(1,nt); 159 | for j = 1:nt 160 | S_GCAA_ALL(j) = CalcTaskUtility(Agents.Pos, Agents.v_a, TasksCells.Pos(j,:), TasksCells.Speed(j,:), TasksCells.tf(j), TasksCells.r_bar(j), j, TasksCells.prob_a_t, winners_matrix, TasksCells.lambda, Agents.kdrag); 161 | rt(j) = TasksCells.r_bar(j) * (1 - prod(1 - winners_matrix(:,j).*TasksCells.prob_a_t(:,j))); 162 | end 163 | S_GCAA = sum(S_GCAA_ALL); 164 | 165 | % Fix the tasks if the completion is close 166 | for i=1:na 167 | task_idx = p{i}; 168 | if isempty(task_idx) 169 | Agents.previous_task(i) = 0; 170 | Agents.previous_winnerBids(i) = 0; 171 | else 172 | if tasks(task_idx).tloiter > 0 && (tasks(task_idx).tf - tasks(task_idx).tloiter) / tasks(task_idx).tloiter < 1 173 | p{i} = Agents.previous_task(i); 174 | agents(i).rin_task = []; 175 | else 176 | Agents.previous_task(i) = task_idx; 177 | Agents.previous_winnerBids(i) = S_GCAA_ALL_agents(i); 178 | end 179 | if i==2 180 | a = Agents.previous_task(i); 181 | a 182 | task_idx 183 | end 184 | end 185 | end 186 | 187 | for i = 1:na 188 | if ~isempty(agents(i).rin_task') 189 | Agents.rin_task(i,:) = agents(i).rin_task'; 190 | Agents.vin_task(i,:) = agents(i).vin_task'; 191 | end 192 | end 193 | 194 | end -------------------------------------------------------------------------------- /src/GreedyCoalitionAuctionAlgorithm/GCAA_Bundle.m: -------------------------------------------------------------------------------- 1 | 2 | % Main GCAA bundle building/updating (runs on each individual agent) 3 | %---------------------------------------------------------------------% 4 | 5 | function [GCAA_Data, newBid, agent] = GCAA_Bundle(GCAA_Params, GCAA_Data, agent, tasks, agent_idx) 6 | 7 | % Update bundles after messaging to drop tasks that are outbid 8 | GCAA_Data = GCAA_BundleRemoveSingleAssignment(GCAA_Params, GCAA_Data, agent_idx); 9 | 10 | % Bid on new tasks and add them to the bundle 11 | [GCAA_Data agent] = GCAA_BundleAdd(GCAA_Params, GCAA_Data, agent, tasks, agent_idx); 12 | 13 | newBid = 0; 14 | 15 | end 16 | -------------------------------------------------------------------------------- /src/GreedyCoalitionAuctionAlgorithm/GCAA_BundleAdd.m: -------------------------------------------------------------------------------- 1 | 2 | % Create bundles for each agent 3 | %---------------------------------------------------------------------% 4 | 5 | function [GCAA_Data, agent] = GCAA_BundleAdd(GCAA_Params, GCAA_Data, agent, tasks, agent_idx) 6 | 7 | if GCAA_Data.fixedAgents(agent_idx) == 1 8 | return; 9 | end 10 | 11 | M = size(tasks,2); 12 | task_pos = zeros(M,2); 13 | task_v = zeros(M,2); 14 | task_tf = zeros(M,1); 15 | task_tloiter = zeros(M,1); 16 | task_radius = zeros(M,1); 17 | task_type = zeros(M,1); 18 | task_value = zeros(M,1); 19 | 20 | for j = 1:M 21 | task_pos(j,:) = [tasks(j).x tasks(j).y]; 22 | task_v(j,:) = tasks(j).Speed; 23 | task_tf(j) = tasks(j).tf; 24 | task_tloiter(j) = tasks(j).tloiter; 25 | task_radius(j) = tasks(j).radius; 26 | task_type(j) = tasks(j).type; 27 | task_value(j) = tasks(j).value; 28 | end 29 | 30 | U = -1e14; 31 | b = []; 32 | 33 | winners_matrix = zeros(GCAA_Params.N, GCAA_Params.M); 34 | for i = 1:GCAA_Params.N 35 | if GCAA_Data.winners(i) > 0 36 | winners_matrix(i,GCAA_Data.winners(i)) = 1; 37 | end 38 | end 39 | 40 | % Only pick a task that is not assigned yet 41 | availTasks = []; 42 | for j = 1:GCAA_Params.M 43 | if ~any(GCAA_Data.winners == j) 44 | availTasks = [availTasks, j]; 45 | end 46 | end 47 | 48 | % If all tasks are assigned, pick any task with positive utility 49 | if isempty(availTasks) 50 | availTasks = 1:M; 51 | allTasksAssigned = true; 52 | U = 0; 53 | end 54 | 55 | newRin = false; 56 | for j = availTasks 57 | if task_tf(j) > task_tloiter(j) 58 | b_new = j; 59 | 60 | winners_matrix(agent_idx, :) = zeros(1,GCAA_Params.M); 61 | winners_matrix(agent_idx, j) = 1; 62 | [rin_t_new, vin_t_new, U_new] = CalcUtility([agent.x, agent.y], agent.v_a, task_pos, task_v, task_type, task_radius, task_tloiter, task_tf, task_value, b_new, agent_idx, GCAA_Params.prob_a_t, GCAA_Params.N, winners_matrix, GCAA_Params.lambda, agent.kdrag); 63 | 64 | if U_new > U 65 | U = U_new; 66 | b = b_new; 67 | rin_t = rin_t_new; 68 | vin_t = vin_t_new; 69 | newRin = true; 70 | end 71 | end 72 | 73 | end 74 | 75 | 76 | GCAA_Data.path = b; %GCAA_InsertInList(GCAA_Data.path, bestTask, bestIdxs(1,bestTask)); 77 | GCAA_Data.winnerBids(agent_idx) = U; %GCAA_InsertInList(GCAA_Data.scores, GCAA_Data.bids(bestTask), bestIdxs(1,bestTask)); 78 | 79 | if isempty(b) 80 | b = 0; 81 | end 82 | 83 | GCAA_Data.winners(agent_idx) = b; 84 | 85 | if newRin 86 | agent.rin_task = rin_t; 87 | agent.vin_task = vin_t; 88 | end 89 | 90 | return 91 | -------------------------------------------------------------------------------- /src/GreedyCoalitionAuctionAlgorithm/GCAA_BundleRemove.m: -------------------------------------------------------------------------------- 1 | 2 | % Update bundles after communication 3 | % For outbid agents, releases tasks from bundles 4 | %---------------------------------------------------------------------% 5 | 6 | function GCAA_Data = GCAA_BundleRemove(GCAA_Params, GCAA_Data) 7 | 8 | outbidForTask = 0; 9 | 10 | for j=1:GCAA_Data.Lt 11 | % If bundle(j) < 0, it means that all tasks up to task j are 12 | % still valid and in paths, the rest (j to MAX_DEPTH) are 13 | % released 14 | if( GCAA_Data.bundle(j) < 0 ) 15 | %disp('Order is negative, breaking'); 16 | break; 17 | else 18 | % Test if agent has been outbid for a task. If it has, 19 | % release it and all subsequent tasks in its path. 20 | if( GCAA_Data.winners(GCAA_Data.bundle(j)) ~= GCAA_Data.agentIndex ) 21 | outbidForTask = 1; 22 | end 23 | 24 | if( outbidForTask ) 25 | % The agent has lost a previous task, release this one too 26 | if( GCAA_Data.winners(GCAA_Data.bundle(j)) == GCAA_Data.agentIndex ) 27 | % Remove from winner list if in there 28 | GCAA_Data.winners(GCAA_Data.bundle(j)) = 0; 29 | GCAA_Data.winnerBids(GCAA_Data.bundle(j)) = 0; 30 | end 31 | % Clear from path and times vectors and remove from bundle 32 | idx = find(GCAA_Data.path == GCAA_Data.bundle(j)); 33 | 34 | GCAA_Data.path = GCAA_RemoveFromList(GCAA_Data.path, idx); 35 | GCAA_Data.times = GCAA_RemoveFromList(GCAA_Data.times, idx); 36 | GCAA_Data.scores = GCAA_RemoveFromList(GCAA_Data.scores, idx); 37 | 38 | GCAA_Data.bundle(j) = -1; 39 | end 40 | end 41 | end 42 | 43 | end 44 | -------------------------------------------------------------------------------- /src/GreedyCoalitionAuctionAlgorithm/GCAA_BundleRemoveSingleAssignment.m: -------------------------------------------------------------------------------- 1 | 2 | % Update bundles after communication 3 | % For outbid agents, releases tasks from bundles 4 | %---------------------------------------------------------------------% 5 | 6 | function GCAA_Data = GCAA_BundleRemoveSingleAssignment(GCAA_Params, GCAA_Data, agent_idx) 7 | 8 | if sum(GCAA_Data.winnerBids) == 0 9 | return; 10 | end 11 | 12 | %for agent_idx = 1:GCAA_Params.N 13 | if GCAA_Data.winners(agent_idx) > 0 14 | All_winners = (GCAA_Data.winners == GCAA_Data.winners(agent_idx)) .* (GCAA_Data.fixedAgents == 0); 15 | if sum(All_winners) > 0 16 | All_winnerBids = GCAA_Data.winnerBids .* All_winners; 17 | All_winnerBids(All_winnerBids == 0) = -1e16; 18 | [maxBid, idxMaxBid] = max(All_winnerBids); 19 | All_losers = All_winners; All_losers(idxMaxBid) = 0; 20 | GCAA_Data.winners = (~All_losers) .* GCAA_Data.winners; 21 | GCAA_Data.winnerBids = (~All_losers) .* GCAA_Data.winnerBids; 22 | GCAA_Data.fixedAgents(idxMaxBid) = 1; 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /src/GreedyCoalitionAuctionAlgorithm/GCAA_Communicate.m: -------------------------------------------------------------------------------- 1 | 2 | % Runs consensus between neighbors 3 | % Checks for conflicts and resolves among agents 4 | 5 | %---------------------------------------------------------------------% 6 | 7 | function [GCAA_Data t] = GCAA_Communicate(GCAA_Params, GCAA_Data, Graph, old_t, T, agent_idx) 8 | 9 | % Copy data 10 | for n = 1:GCAA_Params.N 11 | old_z(:,:,n) = GCAA_Data(n).winners; 12 | old_y(n,:) = GCAA_Data(n).winnerBids; 13 | end 14 | 15 | z = old_z; 16 | y = old_y; 17 | t = old_t; 18 | 19 | epsilon = 10e-6; 20 | 21 | 22 | % Start communication between agents 23 | 24 | % sender = k 25 | % receiver = i 26 | % task = j 27 | 28 | i = agent_idx; 29 | %for i=1:GCAA_Params.N 30 | for k=1:GCAA_Params.N 31 | if( Graph(k,i) == 1 ) 32 | for j=1:GCAA_Params.M 33 | z(k,:,i) = old_z(k,:,k); 34 | end 35 | 36 | % Update timestamps for all agents based on latest comm 37 | for n=1:GCAA_Params.N 38 | if( n ~= i && t(i,n) < old_t(k,n) ) 39 | t(i,n) = old_t(k,n); 40 | end 41 | end 42 | t(i,k) = T; 43 | 44 | end 45 | end 46 | %end 47 | 48 | % Copy data 49 | for n = 1:GCAA_Params.N 50 | GCAA_Data(n).winners = z(:,:,n); 51 | %GCAA_Data(n).winnerBids = y(n,:); 52 | t(n,n) = T; 53 | end 54 | 55 | end 56 | 57 | -------------------------------------------------------------------------------- /src/GreedyCoalitionAuctionAlgorithm/GCAA_Communicate_Single_Assignment.m: -------------------------------------------------------------------------------- 1 | 2 | % Runs consensus between neighbors 3 | % Checks for conflicts and resolves among agents 4 | 5 | %---------------------------------------------------------------------% 6 | 7 | function [GCAA_Data t] = GCAA_Communicate_Single_Assignment(GCAA_Params, GCAA_Data, Graph, old_t, T) 8 | % Copy data 9 | for n = 1:GCAA_Params.N 10 | old_z(n,:) = GCAA_Data(n).winners; 11 | old_y(n,:) = GCAA_Data(n).winnerBids; 12 | old_f(n,:) = GCAA_Data(n).fixedAgents; 13 | end 14 | 15 | z = old_z; 16 | y = old_y; 17 | f = old_f; 18 | t = old_t; 19 | 20 | epsilon = 10e-6; 21 | 22 | 23 | % Start communication between agents 24 | 25 | for i=1:GCAA_Params.N 26 | for k=1:GCAA_Params.N 27 | if( Graph(k,i) == 1 ) 28 | z(i,k) = old_z(k,k); 29 | y(i,k) = old_y(k,k); 30 | f(i,k) = old_f(k,k); 31 | 32 | % Update timestamps for all agents based on latest comm 33 | for n=1:GCAA_Params.N 34 | if( n ~= i && t(i,n) < old_t(k,n) ) 35 | t(i,n) = old_t(k,n); 36 | end 37 | end 38 | t(i,k) = T; 39 | 40 | end 41 | end 42 | end 43 | 44 | % Copy data 45 | for n = 1:GCAA_Params.N 46 | GCAA_Data(n).winners = z(n,:); 47 | GCAA_Data(n).winnerBids = y(n,:); 48 | GCAA_Data(n).fixedAgents = f(n,:); 49 | t(n,n) = T; 50 | end 51 | 52 | end 53 | 54 | -------------------------------------------------------------------------------- /src/GreedyCoalitionAuctionAlgorithm/GCAA_ComputeBids.m: -------------------------------------------------------------------------------- 1 | 2 | % Computes bids for each task. Returns bids, best index for task in 3 | % the path, and times for the new path 4 | %---------------------------------------------------------------------% 5 | 6 | function [GCAA_Data bestIdxs taskTimes feasibility] = GCAA_ComputeBids(GCAA_Params, GCAA_Data, agent, tasks, feasibility) 7 | 8 | 9 | % If the path is full then we cannot add any tasks to it 10 | L = find(GCAA_Data.path == -1); 11 | if( isempty(L) ) 12 | return; 13 | end 14 | 15 | % Reset bids, best positions in path, and best times 16 | GCAA_Data.bids = zeros(1, GCAA_Params.M); 17 | bestIdxs = zeros(1, GCAA_Params.M); 18 | taskTimes = zeros(1, GCAA_Params.M); 19 | 20 | % For each task 21 | for m=1:GCAA_Params.M 22 | 23 | % Check for compatibility between agent and task 24 | if(GCAA_Params.CM(agent.type, tasks(m).type) > 0), 25 | 26 | % Check to make sure the path doesn't already contain task m 27 | if( isempty(find(GCAA_Data.path(1,1:L(1,1)-1) == m)) ) 28 | 29 | % Find the best score attainable by inserting the score into the 30 | % current path 31 | bestBid = 0; 32 | bestIndex = 0; 33 | bestTime = -1; 34 | 35 | % Try inserting task m in location j among other tasks and see if 36 | % it generates a better new_path. 37 | for j=1:L(1,1) 38 | if( feasibility(m,j) == 1 ) 39 | % Check new path feasibility 40 | skip = 0; 41 | 42 | if(j == 1) % insert at the beginning 43 | taskPrev = []; 44 | timePrev = []; 45 | else 46 | taskPrev = tasks(GCAA_Data.path(j-1)); 47 | timePrev = GCAA_Data.times(j-1); 48 | end 49 | 50 | if(j == L(1,1)) %insert at the end 51 | taskNext = []; 52 | timeNext = []; 53 | else 54 | taskNext = tasks(GCAA_Data.path(j)); 55 | timeNext = GCAA_Data.times(j); 56 | end 57 | 58 | % Compute min and max start times and score 59 | [score minStart maxStart] = Scoring_CalcScore(GCAA_Params,agent,tasks(m),taskPrev,timePrev,taskNext,timeNext); 60 | 61 | if(minStart > maxStart) 62 | % Infeasible path 63 | skip = 1; 64 | feasibility(m,j) = 0; 65 | end 66 | 67 | if(~skip), 68 | 69 | % Save the best score and task position 70 | if(score > bestBid ) 71 | bestBid = score; 72 | bestIndex = j; 73 | bestTime = minStart; % Select min start time as optimal 74 | end 75 | end 76 | end 77 | end 78 | 79 | % Save best bid information 80 | if( bestBid > 0 ) 81 | GCAA_Data.bids(1,m) = bestBid; 82 | bestIdxs(1,m) = bestIndex; 83 | taskTimes(1,m) = bestTime; 84 | end 85 | end % this task is already in my bundle 86 | end % this task is incompatible with my type 87 | end % end loop through tasks 88 | -------------------------------------------------------------------------------- /src/GreedyCoalitionAuctionAlgorithm/GCAA_Init.m: -------------------------------------------------------------------------------- 1 | 2 | % Initialize GCAA Parameters 3 | %---------------------------------------------------------------------% 4 | 5 | function GCAA_Params = GCAA_Init(N,M, prob_a_t,lambda) 6 | 7 | % Define GCAA Constants 8 | GCAA_Params.N = N; % number of agents 9 | GCAA_Params.M = M; % number of tasks 10 | GCAA_Params.prob_a_t = prob_a_t; 11 | GCAA_Params.lambda = lambda; 12 | 13 | GCAA_Params.MAX_STEPS = 10000000; 14 | 15 | % FOR USER TO DO: Add specialized agent types and task types 16 | 17 | % List agent types 18 | GCAA_Params.AGENT_TYPES.QUAD = 1; 19 | GCAA_Params.AGENT_TYPES.CAR = 2; 20 | 21 | % List task types 22 | GCAA_Params.TASK_TYPES.TRACK = 1; 23 | GCAA_Params.TASK_TYPES.RESCUE = 2; 24 | 25 | % Initialize Compatibility Matrix 26 | GCAA_Params.CM = zeros(length(fieldnames(GCAA_Params.AGENT_TYPES)), ... 27 | length(fieldnames(GCAA_Params.TASK_TYPES))); 28 | 29 | % FOR USER TO DO: Set agent-task pairs (which types of agents can do which types of tasks) 30 | GCAA_Params.CM(GCAA_Params.AGENT_TYPES.QUAD, GCAA_Params.TASK_TYPES.TRACK) = 1; 31 | GCAA_Params.CM(GCAA_Params.AGENT_TYPES.CAR, GCAA_Params.TASK_TYPES.RESCUE) = 1; 32 | 33 | return -------------------------------------------------------------------------------- /src/GreedyCoalitionAuctionAlgorithm/GCAA_InsertInList.m: -------------------------------------------------------------------------------- 1 | 2 | % Insert value into list at location specified by index 3 | %---------------------------------------------------------------------% 4 | 5 | function newList = GCAA_InsertInList(oldList, value, index) 6 | 7 | newList = -ones(1,length(oldList)); 8 | 9 | newList(1,1:index-1) = oldList(1,1:index-1); 10 | 11 | newList(1,index) = value; 12 | 13 | newList(1,index+1:end) = oldList(1,index:end-1); 14 | 15 | end -------------------------------------------------------------------------------- /src/GreedyCoalitionAuctionAlgorithm/GCAA_Main.m: -------------------------------------------------------------------------------- 1 | 2 | % Main GCAA Function 3 | %---------------------------------------------------------------------% 4 | 5 | function [GCAA_Data Total_Score, All_scores, agents] = GCAA_Main(agents, tasks, Graph, prob_a_t, lambda) 6 | 7 | % Initialize GCAA parameters 8 | GCAA_Params = GCAA_Init(length(agents),length(tasks), prob_a_t, lambda); 9 | 10 | for n=1:GCAA_Params.N 11 | GCAA_Data(n).agentID = agents(n).id; 12 | GCAA_Data(n).agentIndex = n; 13 | %GCAA_Data(n).bundle = -ones(1, agents(n).Lt); 14 | GCAA_Data(n).path = -ones(1, agents(n).Lt); 15 | GCAA_Data(n).times = -ones(1, agents(n).Lt); 16 | %GCAA_Data(n).scores = 0; 17 | %GCAA_Data(n).bids = zeros(1, GCAA_Params.M); 18 | GCAA_Data(n).winners = zeros(1, GCAA_Params.N);%zeros(GCAA_Params.N, GCAA_Params.M); 19 | GCAA_Data(n).winnerBids = zeros(1, GCAA_Params.N); 20 | GCAA_Data(n).fixedAgents = zeros(1, GCAA_Params.N); 21 | GCAA_Data(n).Lt = agents(n).Lt; 22 | end 23 | 24 | % Fix the tasks if the completion is close 25 | for i=1:GCAA_Params.N 26 | task_idx = agents(i).previous_task; 27 | if task_idx ~= 0 && (tasks(task_idx).tf - tasks(task_idx).tloiter) / tasks(task_idx).tloiter < 1 28 | GCAA_Data(i).fixedAgents(i) = 1; 29 | GCAA_Data(i).path = agents(i).previous_task; 30 | GCAA_Data(i).winners(i) = task_idx; 31 | GCAA_Data(i).winnerBids(i) = agents(i).previous_winnerBids; 32 | end 33 | end 34 | 35 | 36 | 37 | % Initialize working variables 38 | T = 0; % Current iteration 39 | t = zeros(GCAA_Params.N, GCAA_Params.N); % Matrix of time of updates from the current winners 40 | lastTime = T-1; 41 | doneFlag = 0; 42 | 43 | % Main GCAA loop (runs until convergence) 44 | while(doneFlag == 0) 45 | 46 | %---------------------------------------% 47 | % 1. Communicate 48 | %---------------------------------------% 49 | [GCAA_Data, t] = GCAA_Communicate_Single_Assignment(GCAA_Params, GCAA_Data, Graph, t, T); 50 | 51 | %---------------------------------------% 52 | % 2. Run GCAA bundle building/updating 53 | %---------------------------------------% 54 | % Run GCAA on each agent 55 | for n = 1:GCAA_Params.N 56 | 57 | % Perform consensus on winning agents and bid values 58 | %[GCAA_Data, t] = GCAA_Communicate(GCAA_Params, GCAA_Data, Graph, t, T, n); 59 | 60 | if GCAA_Data(n).fixedAgents(n) == 0 61 | [GCAA_Data(n), newBid, agents(n)] = GCAA_Bundle(GCAA_Params, GCAA_Data(n), agents(n), tasks, n); 62 | end 63 | 64 | % Update last time things changed 65 | % if(newBid) 66 | % lastTime = T; 67 | % end 68 | end 69 | 70 | doneFlag = 1; 71 | for n = 1:GCAA_Params.N 72 | if GCAA_Data(n).fixedAgents(n) == 0 73 | doneFlag = 0; 74 | break; 75 | end 76 | end 77 | 78 | %---------------------------------------% 79 | % 3. Convergence Check 80 | %---------------------------------------% 81 | % Determine if the assignment is over (implemented for now, but later 82 | % this loop will just run forever) 83 | if(T-lastTime > GCAA_Params.N) 84 | doneFlag = 1; 85 | elseif(T-lastTime > 2*GCAA_Params.N) 86 | disp('Algorithm did not converge due to communication trouble'); 87 | doneFlag = 1; 88 | else 89 | % Maintain loop 90 | T = T + 1; 91 | %display(T); 92 | %display(agents(n).x) 93 | end 94 | end 95 | 96 | 97 | 98 | % Compute the total score of the GCAA assignment 99 | Total_Score = 0; 100 | All_scores = zeros(1,GCAA_Params.N); 101 | for n=1:GCAA_Params.N 102 | All_scores(n) = GCAA_Data(n).winnerBids(n); 103 | Total_Score = Total_Score + All_scores(n); 104 | end 105 | -------------------------------------------------------------------------------- /src/GreedyCoalitionAuctionAlgorithm/GCAA_RemoveFromList.m: -------------------------------------------------------------------------------- 1 | 2 | % Remove item from list at location specified by index 3 | %---------------------------------------------------------------------% 4 | 5 | function newList = GCAA_RemoveFromList(oldList, index) 6 | 7 | newList = -ones(1,length(oldList)); 8 | 9 | newList(1,1:index-1) = oldList(1,1:index-1); 10 | 11 | newList(1,index:end-1) = oldList(1,index+1:end); 12 | 13 | end -------------------------------------------------------------------------------- /src/GreedyCoalitionAuctionAlgorithm/MainTestScript.m: -------------------------------------------------------------------------------- 1 | %% Computes the solution of the GCAA for the task-assignment problem 2 | % Main part of the code comes from MAS Project - Distributed Tasking Algorithm 3 | % Control Science Group, Temasek Laboratory 4 | % Author: Martin Braquet 5 | % Date: August 31, 2020 6 | 7 | rng('default'); 8 | rng(1); 9 | 10 | N = 3; 11 | M = 8; 12 | Lt = 3; 13 | 14 | WORLD.XMAX = 100; 15 | WORLD.YMAX = WORLD.XMAX; 16 | WORLD.XMIN = 0; 17 | WORLD.YMIN = WORLD.XMIN; 18 | pos_a = rand(N,2) * WORLD.XMAX; 19 | pos_t = rand(M,2) * WORLD.XMAX; 20 | 21 | %---------------------------------------------------------------------% 22 | % Initialize global variables 23 | %---------------------------------------------------------------------% 24 | 25 | WORLD.CLR = rand(100,3); 26 | 27 | %---------------------------------------------------------------------% 28 | % Define agents and tasks 29 | %---------------------------------------------------------------------% 30 | % Grab agent and task types from GCAA Parameter definitions 31 | GCAA_Params = GCAA_Init(0,0); 32 | GCAA_Params.MAX_DEPTH = Lt; % maximum bundle depth 33 | 34 | % Initialize possible agent fields 35 | agent_default.id = 0; % agent id 36 | agent_default.type = 0; % agent type 37 | agent_default.avail = 0; % agent availability (expected time in sec) 38 | agent_default.clr = []; % for plotting 39 | 40 | agent_default.x = 0; % agent position (meters) 41 | agent_default.y = 0; % agent position (meters) 42 | agent_default.z = 0; % agent position (meters) 43 | agent_default.nom_vel = 0; % agent cruise velocity (m/s) 44 | agent_default.fuel = 0; % agent fuel penalty (per meter) 45 | 46 | % FOR USER TO DO: Set agent fields for specialized agents, for example: 47 | % agent_default.util = 0; 48 | 49 | % Initialize possible task fields 50 | task_default.id = 0; % task id 51 | task_default.type = 0; % task type 52 | task_default.value = 0; % task reward 53 | task_default.start = 0; % task start time (sec) 54 | task_default.end = 0; % task expiry time (sec) 55 | task_default.duration = 0; % task default duration (sec) 56 | task_default.lambda = 0.95; % task exponential discount 57 | 58 | task_default.x = 0; % task position (meters) 59 | task_default.y = 0; % task position (meters) 60 | task_default.z = 0; % task position (meters) 61 | 62 | % FOR USER TO DO: Set task fields for specialized tasks 63 | 64 | %---------------------------% 65 | 66 | % Create some default agents 67 | 68 | % QUAD 69 | agent_quad = agent_default; 70 | agent_quad.type = GCAA_Params.AGENT_TYPES.QUAD; % agent type 71 | agent_quad.nom_vel = 1; % agent cruise velocity (m/s) 72 | agent_quad.fuel = 1; % agent fuel penalty (per meter) 73 | 74 | % Create some default tasks 75 | 76 | % Track 77 | task_track = task_default; 78 | task_track.type = GCAA_Params.TASK_TYPES.TRACK; % task type 79 | task_track.value = 1; % task reward 80 | task_track.duration = 0; %600; % task default duration (sec) 81 | 82 | 83 | %---------------------------------------------------------------------% 84 | % Define sample scenario 85 | %---------------------------------------------------------------------% 86 | 87 | % Create random agents 88 | for n=1:N 89 | agents(n) = agent_quad; 90 | 91 | % Init remaining agent params 92 | agents(n).id = n; 93 | agents(n).x = pos_a(n,1); 94 | agents(n).y = pos_a(n,2); 95 | agents(n).z = 0; 96 | agents(n).clr = WORLD.CLR(n,:); 97 | end 98 | 99 | % Create random tasks 100 | for m=1:M 101 | tasks(m) = task_track; 102 | tasks(m).id = m; 103 | tasks(m).start = 0; % task start time (sec) 104 | tasks(m).end = 1e20; %tasks(m).start + 1*tasks(m).duration; % task expiry time (sec) 105 | tasks(m).x = pos_t(m,1); 106 | tasks(m).y = pos_t(m,2); 107 | tasks(m).z = 0; 108 | end 109 | %---------------------------------------------------------------------% 110 | % Initialize communication graph and diameter 111 | %---------------------------------------------------------------------% 112 | 113 | % Fully connected graph 114 | Graph = ~eye(N); 115 | 116 | %---------------------------------------------------------------------% 117 | % Run GCAA 118 | %---------------------------------------------------------------------% 119 | tic 120 | [GCAA_Assignments, Total_Score] = GCAA_Main(agents, tasks, Graph) 121 | toc 122 | %PlotAssignments(WORLD, GCAA_Assignments, agents, tasks, 1); 123 | PlotAssignments2D(WORLD, GCAA_Assignments, agents, tasks, 3); 124 | 125 | 126 | % profile off 127 | % profile report -------------------------------------------------------------------------------- /src/GreedyCoalitionAuctionAlgorithm/PlotAssignments.m: -------------------------------------------------------------------------------- 1 | 2 | % Plots GCAA outputs 3 | %---------------------------------------------------------------------% 4 | 5 | function fig = PlotAssignments(WORLD, GCAA_Assignments, agents, tasks, figureID) 6 | 7 | %---------------------------------------------------------------------% 8 | % Set plotting parameters 9 | 10 | set(0, 'DefaultAxesFontSize', 12) 11 | set(0, 'DefaultTextFontSize', 10, 'DefaultTextFontWeight','demi') 12 | set(0,'DefaultAxesFontName','arial') 13 | set(0,'DefaultTextFontName','arial') 14 | set(0,'DefaultLineLineWidth',2); % < == very important 15 | set(0,'DefaultlineMarkerSize',10) 16 | 17 | %---------------------------------------------------------------------% 18 | % Plot X and Y agent and task positions vs. time 19 | 20 | offset = (WORLD.XMAX - WORLD.XMIN)/100; 21 | fig = figure(figureID); 22 | Cmap = colormap('lines'); 23 | 24 | % Plot tasks 25 | for m=1:length(tasks) 26 | plot3(tasks(m).x + [0 0], tasks(m).y + [0 0], [tasks(m).start tasks(m).end],'x:','color',Cmap(tasks(m).type,:),'LineWidth',3); 27 | hold on; 28 | text(tasks(m).x+offset, tasks(m).y+offset, tasks(m).start, ['T' num2str(m)]); 29 | end 30 | % Plot agents 31 | for n=1:length(agents) 32 | plot3(agents(n).x, agents(n).y, 0,'o','color',Cmap(agents(n).type,:)); 33 | text(agents(n).x+offset, agents(n).y+offset, 0.1, ['A' num2str(n)]); 34 | % Check if path has something in it 35 | if( GCAA_Assignments(n).path(1) > -1 ) 36 | taskPrev = lookupTask(tasks, GCAA_Assignments(n).path(1)); 37 | X = [agents(n).x, taskPrev.x]; 38 | Y = [agents(n).y, taskPrev.y]; 39 | T = [0, GCAA_Assignments(n).times(1)]; 40 | plot3(X,Y,T,'-','color',Cmap(agents(n).type,:)); 41 | plot3(X(end)+[0 0], Y(end)+[0 0], [T(2) T(2)+taskPrev.duration],'-^','color',Cmap(agents(n).type,:)); 42 | % Add time and path to agents(n) 43 | agents(n).time = round(GCAA_Assignments(n).times(1)/100); 44 | agents(n).path = [taskPrev.x, taskPrev.y, agents(n).z, taskPrev.duration/100, taskPrev.id]; 45 | 46 | for m = 2:length(GCAA_Assignments(n).path); 47 | if( GCAA_Assignments(n).path(m) > -1 ) 48 | taskNext = lookupTask(tasks, GCAA_Assignments(n).path(m)); 49 | X = [taskPrev.x, taskNext.x]; 50 | Y = [taskPrev.y, taskNext.y]; 51 | T = [GCAA_Assignments(n).times(m-1)+taskPrev.duration, GCAA_Assignments(n).times(m)]; 52 | plot3(X,Y,T,'-^','color',Cmap(agents(n).type,:)); 53 | plot3(X(end)+[0 0], Y(end)+[0 0], [T(2) T(2)+taskNext.duration],'-^','color',Cmap(agents(n).type,:)); 54 | % Add path to agents(n) 55 | agents(n).path = [agents(n).path; taskNext.x, taskNext.y, agents(n).z, taskNext.duration/100, taskNext.id]; 56 | 57 | taskPrev = taskNext; 58 | else 59 | break; 60 | end 61 | end 62 | end 63 | end 64 | hold off; 65 | title(['Agent Paths with Time Windows']) 66 | xlabel('X'); 67 | ylabel('Y'); 68 | zlabel('Time'); 69 | grid on 70 | 71 | % Plot agent schedules 72 | 73 | fig = figure(figureID+1); 74 | subplot(length(agents),1,1); 75 | title(['Agent Schedules']) 76 | 77 | for n=1:length(agents), 78 | subplot(length(agents),1,n); 79 | ylabel(['A' num2str(n)]) 80 | hold on; 81 | grid on; 82 | axis([0 1600 0 2]) 83 | for m = 1:length(GCAA_Assignments(n).path), 84 | if (GCAA_Assignments(n).path(m) > -1) 85 | taskCurr = lookupTask(tasks, GCAA_Assignments(n).path(m)); 86 | plot([GCAA_Assignments(n).times(m) GCAA_Assignments(n).times(m)+taskCurr.duration],[1 1],'-','color',Cmap(agents(n).type,:), 'Linewidth',10) 87 | plot([taskCurr.start taskCurr.end],[1 1],'--','color',Cmap(agents(n).type,:)) 88 | else 89 | break; 90 | end 91 | end 92 | end 93 | xlabel('Time'); 94 | 95 | % cicle create file path for all agents 96 | for n=1:length(agents), 97 | UAV = agents(n); 98 | File = strcat('agents\agent',int2str(UAV.id)); 99 | save(File, 'UAV'); 100 | end 101 | 102 | return 103 | 104 | function task = lookupTask(tasks, taskID) 105 | 106 | for m=1:length(tasks), 107 | if(tasks(m).id == taskID) 108 | task = tasks(m); 109 | return; 110 | end 111 | end 112 | 113 | task = []; 114 | disp(['Task with index=' num2str(taskID) ' not found']) 115 | 116 | return 117 | 118 | -------------------------------------------------------------------------------- /src/GreedyCoalitionAuctionAlgorithm/PlotAssignments2D.m: -------------------------------------------------------------------------------- 1 | 2 | % Plots GCAA outputs 3 | %---------------------------------------------------------------------% 4 | 5 | function fig = PlotAssignments2D(WORLD, GCAA_Assignments, agents, tasks, figureID) 6 | 7 | %---------------------------------------------------------------------% 8 | % Set plotting parameters 9 | 10 | set(0, 'DefaultAxesFontSize', 12) 11 | set(0, 'DefaultTextFontSize', 10, 'DefaultTextFontWeight','demi') 12 | set(0,'DefaultAxesFontName','arial') 13 | set(0,'DefaultTextFontName','arial') 14 | set(0,'DefaultLineLineWidth',2); % < == very important 15 | set(0,'DefaultlineMarkerSize',10) 16 | 17 | %---------------------------------------------------------------------% 18 | % Plot X and Y agent and task positions vs. time 19 | 20 | offset = (WORLD.XMAX - WORLD.XMIN)/100; 21 | fig = figure(figureID); 22 | Cmap = colormap('lines'); 23 | 24 | % Plot tasks 25 | for m=1:length(tasks) 26 | plot(tasks(m).x + [0 0], tasks(m).y + [0 0],'x:','color',Cmap(tasks(m).type,:),'LineWidth',3); 27 | hold on; 28 | text(tasks(m).x+offset, tasks(m).y+offset, tasks(m).start, ['T' num2str(m)]); 29 | end 30 | % Plot agents 31 | for n=1:length(agents) 32 | plot(agents(n).x, agents(n).y,'o','color',Cmap(agents(n).type,:)); 33 | text(agents(n).x+offset, agents(n).y+offset, 0.1, ['A' num2str(n)]); 34 | % Check if path has something in it 35 | if( GCAA_Assignments(n).path(1) > -1 ) 36 | taskPrev = lookupTask(tasks, GCAA_Assignments(n).path(1)); 37 | X = [agents(n).x, taskPrev.x]; 38 | Y = [agents(n).y, taskPrev.y]; 39 | T = [0, GCAA_Assignments(n).times(1)]; 40 | plot(X,Y,'-','color',Cmap(agents(n).type,:)); 41 | plot(X(end)+[0 0], Y(end)+[0 0], '-^','color',Cmap(agents(n).type,:)); 42 | % Add time and path to agents(n) 43 | agents(n).time = round(GCAA_Assignments(n).times(1)/100); 44 | agents(n).path = [taskPrev.x, taskPrev.y, agents(n).z, taskPrev.duration/100, taskPrev.id]; 45 | 46 | for m = 2:length(GCAA_Assignments(n).path); 47 | if( GCAA_Assignments(n).path(m) > -1 ) 48 | taskNext = lookupTask(tasks, GCAA_Assignments(n).path(m)); 49 | X = [taskPrev.x, taskNext.x]; 50 | Y = [taskPrev.y, taskNext.y]; 51 | T = [GCAA_Assignments(n).times(m-1)+taskPrev.duration, GCAA_Assignments(n).times(m)]; 52 | plot(X,Y,'-^','color',Cmap(agents(n).type,:)); 53 | plot(X(end)+[0 0], Y(end)+[0 0], '-^','color',Cmap(agents(n).type,:)); 54 | % Add path to agents(n) 55 | agents(n).path = [agents(n).path; taskNext.x, taskNext.y, agents(n).z, taskNext.duration/100, taskNext.id]; 56 | 57 | taskPrev = taskNext; 58 | else 59 | break; 60 | end 61 | end 62 | end 63 | end 64 | hold off; 65 | title(['Agent Paths with Time Windows']) 66 | xlabel('X'); 67 | ylabel('Y'); 68 | grid on 69 | 70 | return 71 | 72 | function task = lookupTask(tasks, taskID) 73 | 74 | for m=1:length(tasks), 75 | if(tasks(m).id == taskID) 76 | task = tasks(m); 77 | return; 78 | end 79 | end 80 | 81 | task = []; 82 | disp(['Task with index=' num2str(taskID) ' not found']) 83 | 84 | return 85 | 86 | -------------------------------------------------------------------------------- /src/GreedyCoalitionAuctionAlgorithm/Scoring_CalcScore.m: -------------------------------------------------------------------------------- 1 | 2 | % Calculates marginal score of doing a task and returns the expected 3 | % start time for the task. 4 | %---------------------------------------------------------------------% 5 | function [score minStart maxStart] = Scoring_CalcScore(GCAA_Params,agent,taskCurr,taskPrev,timePrev,taskNext,timeNext) 6 | 7 | if((agent.type == GCAA_Params.AGENT_TYPES.QUAD) || ... 8 | (agent.type == GCAA_Params.AGENT_TYPES.CAR)) 9 | 10 | 11 | if(isempty(taskPrev)) % First task in path 12 | % Compute start time of task 13 | dt = sqrt((agent.x-taskCurr.x)^2 + (agent.y-taskCurr.y)^2 + (agent.z-taskCurr.z)^2)/agent.nom_vel; 14 | minStart = max(taskCurr.start, agent.avail + dt); 15 | else % Not first task in path 16 | dt = sqrt((taskPrev.x-taskCurr.x)^2 + (taskPrev.y-taskCurr.y)^2 + (taskPrev.z-taskCurr.z)^2)/agent.nom_vel; 17 | minStart = max(taskCurr.start, timePrev + taskPrev.duration + dt); %i have to have time to do task at j-1 and go to task m 18 | end 19 | 20 | if(isempty(taskNext)) % Last task in path 21 | maxStart = taskCurr.end; 22 | else % Not last task, check if we can still make promised task 23 | dt = sqrt((taskNext.x-taskCurr.x)^2 + (taskNext.y-taskCurr.y)^2 + (taskNext.z-taskCurr.z)^2)/agent.nom_vel; 24 | maxStart = min(taskCurr.end, timeNext - taskCurr.duration - dt); %i have to have time to do task m and fly to task at j+1 25 | end 26 | 27 | % Compute score 28 | reward = taskCurr.value * taskCurr.lambda.^(minStart-taskCurr.start); 29 | 30 | % Subtract fuel cost. Implement constant fuel to ensure 31 | %that resulting scoring scheme satisfies a property called 32 | %diminishing marginal gain (DMG). 33 | % NOTE: This is a fake score since it double counts fuel. Should 34 | % not be used when comparing to optimal score. Need to compute 35 | % real score of GCAA paths once GCAA algorithm has finished 36 | % running. 37 | %penalty = agent.fuel*sqrt((agent.x-taskCurr.x)^2 + (agent.y-taskCurr.y)^2 + (agent.z-taskCurr.z)^2); 38 | penalty = 0; 39 | 40 | score = reward - penalty; 41 | 42 | % FOR USER TO DO: Define score function for specialized agents, for example: 43 | % elseif(agent.type == GCAA_Params.AGENT_TYPES.NEW_AGENT), ... 44 | 45 | % Need to define score, minStart and maxStart 46 | 47 | else 48 | disp('Unknown agent type') 49 | end 50 | 51 | return 52 | -------------------------------------------------------------------------------- /src/GreedyCoalitionAuctionAlgorithm/agents/agent1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/src/GreedyCoalitionAuctionAlgorithm/agents/agent1.mat -------------------------------------------------------------------------------- /src/GreedyCoalitionAuctionAlgorithm/agents/agent2.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/src/GreedyCoalitionAuctionAlgorithm/agents/agent2.mat -------------------------------------------------------------------------------- /src/GreedyCoalitionAuctionAlgorithm/agents/agent3.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/src/GreedyCoalitionAuctionAlgorithm/agents/agent3.mat -------------------------------------------------------------------------------- /src/GreedyCoalitionAuctionAlgorithm/agents/agent4.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/src/GreedyCoalitionAuctionAlgorithm/agents/agent4.mat -------------------------------------------------------------------------------- /src/GreedyCoalitionAuctionAlgorithm/agents/agent5.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartinBraquet/task-allocation-auctions/b6fa44bbfc331169c52c0d5ab0b074abbf463c61/src/GreedyCoalitionAuctionAlgorithm/agents/agent5.mat -------------------------------------------------------------------------------- /src/ODE_test.m: -------------------------------------------------------------------------------- 1 | close all; 2 | 3 | t0 = 0; 4 | t1 = 1; 5 | r0 = [0; 0]; 6 | r1 = [1; 0]; 7 | v0 = [0; -1]; 8 | v1 = [1; 1]; 9 | 10 | dydt = @(t,y) [y(3:4); 4/(t1-t) * (v1 - y(3:4)) + 6/(t1-t)^2 * (r1 - (y(1:2) + v1*(t1 - t)))]; 11 | 12 | options = odeset('RelTol',1e-5,'Stats','on','OutputFcn',@odeplot); 13 | [t,y] = ode45(dydt, [t0 t1], [r0; v0], options); 14 | 15 | r = y(:,1:2); 16 | v = y(:,3:4); 17 | a = zeros(size(v)); 18 | norm_a = zeros(length(t),1); 19 | 20 | for i = 1:length(t) 21 | a(i,:) = 4/(t1-t(i)) .* (v1' - v(i,:)) + 6/(t1-t(i)).^2 .* (r1' - (r(i,:) + v1'.*(t1 - t(i)))); 22 | norm_a(i) = norm(a(i,:)); 23 | end 24 | 25 | a(isnan(a)) = 0; 26 | norm_a(isnan(norm_a)) = 0; 27 | 28 | J = trapz(t,norm_a) 29 | 30 | figure; 31 | plot(y(:,1), y(:,2)); 32 | 33 | figure; 34 | plot(t, norm_a); -------------------------------------------------------------------------------- /src/ODE_test_loitering.m: -------------------------------------------------------------------------------- 1 | close all; 2 | 3 | t0 = 0; 4 | tin = 1; 5 | tT = 4; 6 | ra = [0; 0]; 7 | rt = [1; 0]; 8 | R = 0.2; 9 | va = [0; -1]; 10 | rout = rt - [0; R]; 11 | nturns_loitering = 1; 12 | 13 | [xa, ya] = deal(ra(1),ra(2)); 14 | [xt, yt] = deal(rt(1),rt(2)); 15 | syms x y 16 | eqns = [(x - xa)^2 + (y - ya)^2 == norm(ra-rt)^2 - R^2, (x - xt)^2 + (y - yt)^2 == R^2]; 17 | [solx, soly] = solve(eqns,[x y]); 18 | 19 | rin1 = [double(solx(1)); double(soly(1))]; 20 | rin2 = [double(solx(2)); double(soly(2))]; 21 | 22 | rot_direction = cross([rin1-ra; 0], [rin1-rt; 0]); 23 | 24 | if rot_direction(3) > 0 % For clockwise 25 | rin = rin1; 26 | else 27 | rin = rin2; 28 | end 29 | 30 | theta = atan2(rin(2)-rt(2),rin(1)-rt(1)) - atan2(rout(2)-rt(2),rout(1)-rt(1)); % For clockwise 31 | norm_vt = (theta + nturns_loitering * 2*pi) / tT; 32 | vt = (rin - ra) * norm_vt / norm(rin - ra); 33 | 34 | 35 | dydt = @(t,y) [y(3:4); 4/(tin-t) * (vt - y(3:4)) + 6/(tin-t)^2 * (rin - (y(1:2) + vt*(tin - t)))]; 36 | 37 | options = odeset('RelTol',1e-5,'Stats','on','OutputFcn',@odeplot); 38 | [t,y] = ode45(dydt, [t0 tin], [ra; va], options); 39 | 40 | r = y(:,1:2); 41 | v = y(:,3:4); 42 | a = zeros(size(v)); 43 | norm_a = zeros(length(t),1); 44 | 45 | for i = 1:length(t) 46 | a(i,:) = 4/(tin-t(i)) .* (vt' - v(i,:)) + 6/(tin-t(i)).^2 .* (rt' - (r(i,:) + vt'.*(tin - t(i)))); 47 | norm_a(i) = norm(a(i,:)); 48 | end 49 | 50 | a(isnan(a)) = 0; 51 | norm_a(isnan(norm_a)) = 0; 52 | 53 | J = trapz(t,norm_a) 54 | 55 | figure; hold on; 56 | plot(y(:,1), y(:,2)); 57 | 58 | n = 20; 59 | theta = linspace(0, 2*pi, n)'; 60 | pos = repmat(rt', n, 1) + R * [cos(theta) sin(theta)]; 61 | plot(pos(:,1), pos(:,2), '--', 'LineWidth', 1); 62 | xlim([0 1.5]); 63 | ylim([-0.75 0.75]); 64 | 65 | 66 | figure; 67 | plot(t, norm_a); -------------------------------------------------------------------------------- /src/ODE_test_loitering_1turn.m: -------------------------------------------------------------------------------- 1 | close all; 2 | 3 | t0 = 0; 4 | tin = 1; 5 | tT = 4; 6 | tf = 10; 7 | ra = [0; 0]; 8 | rt = [1; 0]; 9 | R = 0.2; 10 | va = [0; 0.6]; 11 | nturns_loitering = 1; 12 | 13 | norm_vt = nturns_loitering * 2*pi * R / tT; 14 | 15 | time_step = tf / 1000; 16 | t_circle = 0:time_step:(tf-tT); 17 | t = (0:time_step:tf)'; 18 | 19 | rho = 1e16; 20 | for theta = linspace(0, 2*pi, 10) 21 | rin_new = rt + R * [cos(theta); sin(theta)]; 22 | for i = [-1 1] 23 | vt_new = i * [0 1; -1 0] * (rin_new - rt) * norm_vt / norm(rin_new - rt); 24 | [a_new, r_new, v_new, rho_new] = ComputeCommandParamsWithVelocity(ra, va, rin_new, vt_new, tf - tT, t_circle); 25 | if rho_new < rho 26 | rho = rho_new; 27 | rin = rin_new; 28 | vt = vt_new; 29 | a_to_target = a_new; 30 | r_to_target = r_new; 31 | v_to_target = v_new; 32 | end 33 | end 34 | end 35 | 36 | norm_a = norm_vt^2 / R; 37 | 38 | r = zeros(length(t),2); 39 | r(1:length(t_circle),:) = r_to_target; 40 | v = zeros(length(t),2); 41 | v(1:length(t_circle),:) = v_to_target; 42 | a = zeros(length(t),2); 43 | a(1:length(t_circle),:) = a_to_target; 44 | 45 | for i = length(t_circle)+1:length(t) 46 | a(i,:) = (rt' - r(i-1,:)) * norm_a / norm(rt' - r(i-1,:)); 47 | v(i,:) = v(i-1,:) + time_step * a(i,:); 48 | r(i,:) = r(i-1,:) + time_step * v(i,:); 49 | end 50 | 51 | J = rho + 1/2 * (norm_a)^2 * tT; 52 | 53 | figure; hold on; 54 | plot(r(:,1), r(:,2), 'LineWidth', 2); 55 | 56 | n = 20; 57 | theta = linspace(0, 2*pi, n)'; 58 | pos = repmat(rt', n, 1) + R * [cos(theta) sin(theta)]; 59 | plot(pos(:,1), pos(:,2), 'r--', 'LineWidth', 2); 60 | xlim([-0.5 1.75]); 61 | ylim([-1 1]); 62 | 63 | 64 | % figure; 65 | % plot(t, norm_a); -------------------------------------------------------------------------------- /src/OptimalControlSolution.m: -------------------------------------------------------------------------------- 1 | %% Optimal control solution 2 | % for a double integrator dynamics and minimizing the square of the input command along the path 3 | % Params: p_GCAA: task allocation 4 | % Output: X: (n_rounds x na x 4) matrix corresponding to the (x,y) position and velocity of 5 | % each agents for each round (n_rounds = tf/time_step) 6 | function [X, completed_tasks, J, J_to_completion_target] = OptimalControlSolution(pos_a, v_a, pos_t, v_t, radius_t, p_GCAA, Agents, tf_t, tloiter_t, time_step, n_rounds, na, kdrag) 7 | X = zeros(4, na, n_rounds+1); 8 | J = [zeros(1,na)]; 9 | J_to_completion_target = [zeros(1,na)]; 10 | A = [zeros(2,2) eye(2,2); zeros(2,2) zeros(2,2)]; 11 | B = [zeros(2,2); eye(2,2)]; 12 | completed_tasks = []; 13 | for i = 1:na 14 | X(:, i, 1) = [pos_a(i,:) v_a(i,:)]; 15 | if (isempty(p_GCAA{i}) || p_GCAA{i} == 0) 16 | p_GCAA{i} = []; 17 | for k = 1:size(X,3)-1 18 | if k == 1 19 | u = - kdrag * X(3:4, i, k); 20 | X(:, i, k+1) = X(:, i, k) + time_step * (A * X(:, i, k) + B * u); 21 | else 22 | X(:, i, k+1) = X(:, i, k); 23 | end 24 | end 25 | end 26 | for j = 1:size(p_GCAA{i},2) 27 | k = 0; 28 | ind_task = p_GCAA{i}(j); 29 | tf = tf_t(ind_task); 30 | if j > 1 31 | tf = tf - tf_t(p_GCAA{i}(j-1)); 32 | end 33 | pos_t_curr = pos_t(ind_task,:)'; 34 | v_t_curr = v_t(ind_task,:)'; 35 | pos_a_curr = X(1:2, i, k+1); 36 | v_a_curr = X(3:4, i, k+1); 37 | 38 | J_to_completion_target_curr = 0; 39 | if tf > tloiter_t(ind_task) + time_step 40 | t_to_target = 0:time_step:(tf-tloiter_t(ind_task)); 41 | [uparams, rparams, vparams, tparams, J_to_completion_target_curr] = ComputeCommandParamsWithVelocity(pos_a_curr, v_a_curr, Agents.rin_task(i,:)', Agents.vin_task(i,:)', tf - tloiter_t(ind_task), t_to_target, Agents.kdrag); 42 | end 43 | J_to_completion_target(i) = J_to_completion_target_curr; 44 | R = radius_t(ind_task); 45 | norm_vt = 2*pi * R / tloiter_t(ind_task); 46 | norm_a = norm_vt^2 / R; 47 | 48 | if tloiter_t(ind_task) > 0 && tf > 0 49 | J_to_completion_target(i) = J_to_completion_target(i) + 1/2 * norm_a^2 * min(tloiter_t(ind_task), tf); 50 | end 51 | 52 | t = 0; 53 | while t + time_step <= tf 54 | %diff_t = tparams-t; 55 | %diff_t(diff_t <= 0) = 1e16; 56 | %[~, idx] = min(diff_t); idx = idx - 1; 57 | %u = uparams(idx,:) + (uparams(idx+1,:) - uparams(idx,:)) * (t - tparams(idx)) / (tparams(idx+1) - tparams(idx)); 58 | u = 0; 59 | if tf > tloiter_t(ind_task) + time_step 60 | if k + 1 <= length(t_to_target) 61 | u = uparams(k+1,:)'; 62 | X(:, i, k+2) = X(:, i, k+1) + time_step * (A * X(:, i, k+1) + B * u); 63 | else 64 | X(:, i, k+2) = X(:, i, k+1); 65 | end 66 | else 67 | r_target_circle = pos_t_curr - X(1:2, i, k+1); 68 | d = norm(r_target_circle); 69 | alpha = 0; % 0.4 * (d - R) / R; 70 | u = (1 + alpha) * norm_a * r_target_circle / d; 71 | X(:, i, k+2) = X(:, i, k+1) + time_step * (A * X(:, i, k+1) + B * u); 72 | end 73 | 74 | if k == 0 75 | J(i) = 1/2 * norm(u)^2 * time_step; 76 | end 77 | 78 | t = t + time_step; 79 | k = k + 1; 80 | end 81 | end 82 | % If it reaches the target 83 | if k == 1 && sum(completed_tasks == p_GCAA{i}) == 0 84 | completed_tasks = [completed_tasks p_GCAA{i}]; 85 | end 86 | for k2 = k+2:n_rounds+1 87 | X(:,i,k2) = X(:,i,k+1); 88 | end 89 | end 90 | end -------------------------------------------------------------------------------- /src/OptimalControl_DTA.m: -------------------------------------------------------------------------------- 1 | %% Decentralized Control for Dynamic Task Allocation Problems for Multi-Agent Systems with Auctions 2 | % Analysis in dynamics 3 | % 4 | % Author: Martin Braquet 5 | % Date: September 2020 6 | 7 | addpath('GreedyCoalitionAuctionAlgorithm/'); 8 | close all; clear all; 9 | rng('default'); 10 | rng(5); 11 | 12 | simu_number = 7; 13 | simu_name = 'Dynamics'; 14 | 15 | [ComputeOpt ComputeSGA ComputeGCAA] = deal(0,0,1); 16 | 17 | use_GCAA = 1; 18 | use_OPT = 0; 19 | uniform_agents = 0; 20 | uniform_tasks = 0; 21 | plot_range = 0; 22 | 23 | na = 5; 24 | nt = 4; 25 | n_rounds = 200; 26 | 27 | Lt = 1; 28 | nt_loiter = ceil(0.5*nt); 29 | task_type = zeros(nt,1); 30 | task_type(1:nt_loiter) = 1; 31 | lambda = 1; 32 | 33 | map_width = 1; 34 | comm_distance = 0.5 * map_width; 35 | 36 | simu_time = 10; 37 | time_step = simu_time / n_rounds; 38 | time_start = 0; 39 | 40 | pos_a = (0.1 + 0.8 * rand(na,2)) * map_width; 41 | pos_t = (0.1 + 0.8 * rand(nt,2)) * map_width; 42 | %tf_t = rand(nt,1) * simu_time; 43 | %tf_t = [5*ones(1,3) 10*ones(1,1)]; 44 | tf_t = simu_time * (0.95 + 0.05 * rand(nt,1)); 45 | tloiter_t = simu_time * (0.2 + 0.05 * rand(nt,1)); 46 | tloiter_t(task_type == 0) = 0; 47 | %tf_t = 10*ones(1,nt); 48 | 49 | [tf_t, idx] = sort(tf_t); 50 | pos_t = pos_t(idx,:); 51 | pos_t_initial = pos_t; 52 | 53 | kdrag = 3 / simu_time; 54 | 55 | %velocity = 1:na; 56 | %velocity = 1 * ones(1,nt); 57 | max_speed = 0.1; 58 | if uniform_agents 59 | v_a = zeros(na,2); 60 | else 61 | v_a = (2 * rand(na,2) - 1) * max_speed; 62 | end 63 | 64 | max_speed_task = 0.1; 65 | if uniform_tasks 66 | v_t = zeros(nt,2); 67 | else 68 | v_t = (2 * rand(nt,2) - 1) * max_speed_task; 69 | end 70 | 71 | R = 0.04 * map_width; 72 | if uniform_tasks 73 | radius_t = R * ones(nt,1); 74 | else 75 | radius_t = (0.2 * rand(nt,1) + 1) * R; 76 | end 77 | 78 | % 79 | % pos_a = [0.1 0.5]; 80 | % v_a = [0 0]; 81 | % pos_t = [0 0.8]; 82 | 83 | 84 | % Reward after task completion 85 | r_nom = 0.2; 86 | if uniform_tasks 87 | r_bar = r_nom * ones(nt,1); 88 | else 89 | r_bar = r_nom * rand(nt,1); 90 | end 91 | r_bar(task_type == 1) = 5 * r_bar(task_type == 1); 92 | 93 | % Probability that agent i successfully completes task j 94 | if uniform_agents 95 | prob_a_t = 0.7 * ones(na,nt); 96 | else 97 | prob_a_t = rand(na,nt); 98 | end 99 | 100 | Tasks.r_bar = r_bar; 101 | Tasks.prob_a_t = prob_a_t; 102 | Tasks.tast_type = task_type; 103 | 104 | Agents.N = na; 105 | Agents.Lt = Lt * ones(1,na); 106 | Agents.v_a = v_a; 107 | Agents.previous_task = zeros(na,1); 108 | Agents.previous_winnerBids = zeros(na,1); 109 | Agents.rin_task = zeros(na,2); 110 | Agents.vin_task = zeros(na,2); 111 | Agents.kdrag = kdrag; 112 | 113 | costs = zeros(na, nt); 114 | utility = zeros(na, nt); 115 | rewards = zeros(na, nt); 116 | 117 | % Fully connected graph 118 | G = ~eye(Agents.N); 119 | 120 | figure; hold on; 121 | colors = lines(na); 122 | 123 | SimuParamsCell.n_rounds = n_rounds; 124 | SimuParamsCell.time_step = time_step; 125 | SimuParamsCell.map_width = map_width; 126 | SimuParamsCell.comm_distance = comm_distance; 127 | SimuParamsCell.simu_time = simu_time; 128 | SimuParamsCell.time_step = time_step; 129 | SimuParamsCell.colors = colors; 130 | SimuParamsCell.pos_a_init = pos_a; 131 | SimuParamsCell.max_speed = max_speed; 132 | SimuParamsCell.v_a = v_a; 133 | SimuParamsCell.pos_t = pos_t; 134 | SimuParamsCell.max_speed_task = max_speed_task; 135 | SimuParamsCell.v_t = v_t; 136 | SimuParamsCell.radius_t = radius_t; 137 | SimuParamsCell.task_type = task_type; 138 | SimuParamsCell.nt_loiter = nt_loiter; 139 | SimuParamsCell.task_type = task_type; 140 | SimuParamsCell.na = na; 141 | SimuParamsCell.nt = nt; 142 | SimuParamsCell.tf_t = tf_t; 143 | SimuParamsCell.tloiter_t = tf_t; 144 | SimuParamsCell.R = R; 145 | SimuParamsCell.radius_t = radius_t; 146 | SimuParamsCell.r_nom = r_nom; 147 | SimuParamsCell.r_bar = r_bar; 148 | SimuParamsCell.lambda = lambda; 149 | SimuParamsCell.prob_a_t = prob_a_t; 150 | SimuParamsCell.kdrag = kdrag; 151 | 152 | 153 | for CommLimit = [0 1] 154 | 155 | clear J J_to_completion_target X_full_simu p_GCAA_full_simu S_GCAA_ALL X; 156 | 157 | n_rounds_loop = n_rounds; 158 | simu_time_loop = simu_time; 159 | time_start_loop = time_start; 160 | tf_t_loop = tf_t; 161 | pos_a_loop = pos_a; 162 | v_a_loop = v_a; 163 | 164 | U_next_tot = zeros(n_rounds,1); 165 | U_tot = zeros(n_rounds,1); 166 | U_completed_tot = 0; 167 | 168 | completed_tasks_round = []; 169 | completed_tasks = []; 170 | rt_completed = 0; 171 | 172 | X_full_simu{n_rounds} = 0; 173 | p_GCAA_full_simu{n_rounds} = 0; 174 | S_GCAA_ALL_full_simu = zeros(n_rounds,nt); 175 | rt_full_simu = zeros(n_rounds,nt); 176 | J = zeros(n_rounds,na); % Cost for each agent from start to current step 177 | J_to_completion_target = zeros(n_rounds,na); % Estimated cost for each agent from step to end 178 | 179 | for i_round = 1:n_rounds 180 | 181 | clf; hold on; 182 | xlim([0 map_width]); 183 | ylim([0 map_width]); 184 | xlabel('x [m]'); 185 | ylabel('y [m]'); 186 | title('Task-Agent allocation'); 187 | for i = 1:na 188 | plot(pos_a_loop(i,1), pos_a_loop(i,2), '*', 'Color', colors(i,:), 'MarkerSize', 10, 'DisplayName', 'Agents'); 189 | end 190 | plot(pos_t(:,1), pos_t(:,2),'rs', 'MarkerSize', 10, 'DisplayName', 'Targets', 'MarkerFaceColor',[1 .6 .6]); 191 | if plot_range 192 | PlotAgentRange(pos_a_loop, comm_distance, colors, 'Comm Range'); 193 | end 194 | 195 | PlotTaskLoitering(pos_t, radius_t, task_type, 'r--', 'Task loitering'); 196 | 197 | Agents.Pos = pos_a_loop; 198 | Agents.v_a = v_a_loop; 199 | 200 | Tasks.Pos = pos_t; 201 | Tasks.Speed = v_t; 202 | Tasks.N = nt; 203 | Tasks.tf = tf_t_loop; 204 | Tasks.lambda = lambda; 205 | Tasks.task_type = task_type; 206 | Tasks.tloiter = tloiter_t; 207 | Tasks.radius = radius_t; 208 | 209 | for j = 1:nt 210 | if tf_t_loop(j) > 0 211 | for i = 1:na 212 | [~, ~, ~, ~, costs(i,j)] = ComputeCommandParamsWithVelocity(pos_a_loop(i,:)', v_a_loop(i,:)', pos_t(j,:)', v_t(j,:)', tf_t_loop(j), [], kdrag); 213 | %mycost(i_round) = costs(i,j) 214 | rewards(i,j) = r_bar(j) * prob_a_t(i,j); 215 | winners = zeros(na,nt); 216 | winners(i,j) = 1; 217 | utility(i,j) = CalcTaskUtility(pos_a_loop, v_a_loop, pos_t(j,:), v_t(j,:), tf_t_loop(j), r_bar(j), j, prob_a_t, winners, lambda, kdrag); 218 | %myutility(i_round) = utility(i,j) 219 | end 220 | end 221 | end 222 | 223 | if CommLimit 224 | for i = 1:na 225 | for j = (i+1):na 226 | G(i,j) = norm(pos_a_loop(i,:) - pos_a_loop(j,:)) < comm_distance; 227 | G(j,i) = G(i,j); 228 | end 229 | end 230 | end 231 | 232 | if use_GCAA 233 | % GCAA solution 234 | tic; [S_GCAA, p_GCAA, S_GCAA_ALL, rt_curr, Agents] = GCAASolution(Agents, G, Tasks) 235 | rt_full_simu(i_round,:) = rt_curr; 236 | toc; 237 | else 238 | % Test of fixed solution 239 | p_GCAA = {[1 4], [2 4], [3 4]}; S_GCAA = 1; 240 | end 241 | 242 | if use_OPT 243 | tic; [S_OPT, p_OPT, S_OPT_ALL] = OptimumSolution(Agents, G, Tasks); 244 | toc; 245 | [S_GCAA S_OPT] 246 | end 247 | 248 | U_next_tot(i_round) = S_GCAA; 249 | U_tot(i_round) = U_next_tot(i_round) + U_completed_tot; 250 | 251 | % Find the optimal control solution for the given allocation p_GCAA 252 | [X, completed_tasks_round, J_curr, J_to_completion_target(i_round+1,:)] = OptimalControlSolution(pos_a_loop, v_a_loop, pos_t, v_t, radius_t, p_GCAA, Agents, tf_t_loop, tloiter_t, time_step, n_rounds_loop, na, kdrag); 253 | X_full_simu{i_round} = X; 254 | p_GCAA_full_simu{i_round} = p_GCAA; 255 | S_GCAA_ALL_full_simu(i_round,:) = S_GCAA_ALL; 256 | J(i_round+1,:) = J(i_round,:) + J_curr; 257 | plotMapAllocation(X, n_rounds_loop, na, colors, 'GCAA solution'); 258 | 259 | for j = completed_tasks_round 260 | rt_completed = rt_completed + rt_curr(j); 261 | %pos_t(j,:) = [1 1] * 1e16; 262 | %U_completed_tot = U_completed_tot + S_GCAA_ALL(j); 263 | end 264 | 265 | completed_tasks_round = []; 266 | 267 | 268 | legend(legendUnq(gca)); 269 | drawnow; 270 | 271 | % Update position and velocity of each agent 272 | pos_a_loop = X(1:2,:,2)'; 273 | v_a_loop = X(3:4,:,2)'; 274 | 275 | % stop = 1; 276 | % for i = 1:na 277 | % if ~isempty(p_GCAA{i}) 278 | % stop = 0; 279 | % break; 280 | % end 281 | % end 282 | % 283 | % 284 | % if (stop) 285 | % break; 286 | % end 287 | 288 | %pos_t = RemoveCompletedTasks(pos_t, ind_completed_tasks); 289 | 290 | simu_time_loop = simu_time_loop - time_step; 291 | time_start_loop = time_start_loop + time_step; 292 | n_rounds_loop = n_rounds_loop - 1; 293 | tf_t_loop = tf_t_loop - time_step; 294 | end 295 | 296 | U_tot = rt_completed - sum(J(end,:)); 297 | 298 | mkdir(sprintf('mat/%s/simu_%d', simu_name, simu_number)); 299 | save(sprintf('mat/%s/simu_%d/J_CommLimit_%d.mat', simu_name, simu_number, CommLimit), 'J'); 300 | save(sprintf('mat/%s/simu_%d/J_to_completion_target_CommLimit_%d.mat', simu_name, simu_number, CommLimit), 'J_to_completion_target'); 301 | save(sprintf('mat/%s/simu_%d/X_just_saved_CommLimit_%d.mat', simu_name, simu_number, CommLimit), 'X_full_simu'); 302 | save(sprintf('mat/%s/simu_%d/p_GCAA_just_saved_CommLimit_%d.mat', simu_name, simu_number, CommLimit), 'p_GCAA_full_simu'); 303 | save(sprintf('mat/%s/simu_%d/S_GCAA_ALL_just_saved_CommLimit_%d.mat', simu_name, simu_number, CommLimit), 'S_GCAA_ALL_full_simu'); 304 | save(sprintf('mat/%s/simu_%d/rt_just_saved_CommLimit_%d.mat', simu_name, simu_number, CommLimit), 'rt_full_simu'); 305 | 306 | save(sprintf('mat/%s/simu_%d/SimuParamsCell.mat', simu_name, simu_number), 'SimuParamsCell'); 307 | 308 | end 309 | 310 | 311 | 312 | 313 | %% 314 | 315 | 316 | function pos_t_new = RemoveCompletedTasks(pos_t, ind) 317 | 318 | pos_t_new = zeros(size(pos_t,1)-length(ind),2); 319 | k = 1; 320 | for t = 1:size(pos_t,1) 321 | if ~sum(ind == t) 322 | pos_t_new(k,:) = pos_t(t,:); 323 | k = k + 1; 324 | end 325 | end 326 | 327 | end 328 | 329 | function [p, pos_a, ind_completed_tasks, nt, Agents] = UpdatePath(p, pos_a, pos_t, time_step, Agents, nt) 330 | ind_completed_tasks = []; 331 | 332 | for i = 1:size(pos_a,1) 333 | if ~isempty(p{i}) 334 | d_a_t = pos_t(p{i}(1),:) - pos_a(i,:); 335 | if (norm(d_a_t) < time_step * Agents.Speed(i)) 336 | pos_a(i,:) = pos_t(p{i}(1),:); 337 | nt = nt - 1; 338 | Agents.Lt(i) = Agents.Lt(i) - 1; 339 | ind_completed_tasks = [ind_completed_tasks p{i}(1)]; 340 | %if (nt == 0) 341 | % break; 342 | %end 343 | p{i} = p{i}(2:end); 344 | % if ~isempty(p{i}) 345 | % time_step_remaining = time_step - norm(d_a_t) / Agents.Speed(i); 346 | % d_a_next_t = pos_t(p{i}(1),:) - pos_a(i,:); 347 | % pos_a(i,:) = pos_a(i,:) + d_a_next_t / norm(d_a_next_t) * time_step_remaining * Agents.Speed(i); 348 | % end 349 | else 350 | pos_a(i,:) = pos_a(i,:) + d_a_t / norm(d_a_t) * time_step * Agents.Speed(i); 351 | end 352 | end 353 | end 354 | end 355 | 356 | -------------------------------------------------------------------------------- /src/OptimalControl_OLTA.m: -------------------------------------------------------------------------------- 1 | %% Decentralized Control for Dynamic Task Allocation Problems for Multi-Agent Systems with Auctions 2 | % Analysis in static (Open Loop) 3 | % 4 | % Author: Martin Braquet 5 | % Date: September 2020 6 | 7 | addpath('GreedyCoalitionAuctionAlgorithm/'); 8 | close all; clear all; 9 | rng('default'); 10 | rng(8); 11 | 12 | [ComputeOpt ComputeSGA ComputeGCAA] = deal(0,0,1); 13 | CommLimit = 1; 14 | use_GCAA = 1; 15 | use_OPT = 0; 16 | 17 | na = 3; 18 | nt = 3; 19 | Lt = 1; 20 | 21 | lambda = 1; 22 | 23 | map_width = 1; 24 | comm_distance = 2 * map_width; 25 | 26 | simu_time = 5; 27 | n_rounds = 40; 28 | time_step = simu_time / n_rounds; 29 | time_start = 0; 30 | 31 | pos_a = (0.1 + 0.8 * rand(na,2)) * map_width; 32 | pos_t = (0.1 + 0.8 * rand(na,2)) * map_width; 33 | %tf_t = rand(nt,1) * simu_time; 34 | %tf_t = [5*ones(1,3) 10*ones(1,1)]; 35 | tf_t = simu_time / 1.05 * (1 + 0.05 * rand(nt,1)); 36 | %tf_t = 10*ones(1,nt); 37 | 38 | [tf_t, idx] = sort(tf_t); 39 | pos_t = pos_t(idx,:); 40 | 41 | %velocity = 1:na; 42 | %velocity = 1 * ones(1,nt); 43 | max_speed = 0.1; 44 | v_a = (2 * rand(na,2) - 1) * max_speed; 45 | 46 | % Reward after task completion 47 | r_bar = rand(nt,1); 48 | %r_bar = ones(nt,1); 49 | 50 | % Probability that agent i successfully completes task j 51 | prob_a_t = rand(na,nt); 52 | %prob_a_t = 1*ones(na,nt); 53 | 54 | Tasks.r_bar = r_bar; 55 | Tasks.prob_a_t = prob_a_t; 56 | 57 | Agents.N = na; 58 | Agents.Lt = Lt * ones(1,na); 59 | Agents.v_a = v_a; 60 | 61 | costs = zeros(na, nt); 62 | utility = zeros(na, nt); 63 | rewards = zeros(na, nt); 64 | 65 | % Fully connected graph 66 | G = ~eye(Agents.N); 67 | 68 | Agents.Pos = pos_a; 69 | 70 | Tasks.Pos = pos_t; 71 | Tasks.N = nt; 72 | Tasks.tf = tf_t; 73 | Tasks.lambda = lambda; 74 | 75 | if use_GCAA 76 | % GCAA solution 77 | tic; [S_GCAA, p_GCAA, S_GCAA_ALL] = GCAASolution(Agents, G, Tasks) 78 | toc; 79 | else 80 | % Test of fixed solution 81 | p_GCAA = {[1 4], [2 4], [3 4]}; S_GCAA = 1; 82 | end 83 | 84 | if use_OPT 85 | tic; [S_OPT, p_OPT, S_OPT_ALL] = OptimumSolution(Agents, G, Tasks); 86 | toc; 87 | [S_GCAA S_OPT] 88 | end 89 | 90 | 91 | figure; hold on; 92 | colors = lines(na); 93 | 94 | clf; hold on; 95 | xlim([0 map_width]); 96 | ylim([0 map_width]); 97 | xlabel('x [m]'); 98 | ylabel('y [m]'); 99 | title('Task-Agent allocation'); 100 | for i = 1:na 101 | plot(pos_a(i,1), pos_a(i,2), '*', 'Color', colors(i,:), 'MarkerSize', 10, 'DisplayName', 'Agents'); 102 | end 103 | plot(pos_t(:,1), pos_t(:,2),'rs', 'MarkerSize', 10, 'DisplayName', 'Targets', 'MarkerFaceColor',[1 .6 .6]); 104 | PlotAgentRange(pos_a, comm_distance, colors, 'Comm Range') 105 | 106 | for i = 1:na 107 | for j = 1:nt 108 | [~, ~, costs(i,j)] = ComputeCommandParams(pos_a(i,:), v_a(i,:), pos_t(j,:), tf_t(j)); 109 | rewards(i,j) = r_bar(j) * prob_a_t(i,j); 110 | winners = zeros(na,nt); 111 | winners(i,j) = 1; 112 | utility(i,j) = CalcTaskUtility(pos_a, v_a, pos_t(j,:), tf_t(j), r_bar(j), j, prob_a_t, winners, lambda); 113 | end 114 | end 115 | 116 | if CommLimit 117 | for i = 1:na 118 | for j = (i+1):na 119 | G(i,j) = norm(pos_a(i,:) - pos_a(j,:)) < comm_distance; 120 | G(j,i) = G(i,j); 121 | end 122 | end 123 | end 124 | 125 | U_tot = S_GCAA 126 | 127 | % Find the optimal control solution for the given allocation p_GCAA 128 | [X, ~] = OptimalControlSolution(pos_a, v_a, pos_t, p_GCAA, tf_t, time_step, n_rounds, na); 129 | PlotAlloc(X, n_rounds, na, colors, 'GCAA solution'); 130 | 131 | legend(legendUnq(gca)); 132 | drawnow; 133 | 134 | %% 135 | 136 | function pos_t_new = RemoveCompletedTasks(pos_t, ind) 137 | 138 | pos_t_new = zeros(size(pos_t,1)-length(ind),2); 139 | k = 1; 140 | for t = 1:size(pos_t,1) 141 | if ~sum(ind == t) 142 | pos_t_new(k,:) = pos_t(t,:); 143 | k = k + 1; 144 | end 145 | end 146 | 147 | end 148 | 149 | function [p, pos_a, ind_completed_tasks, nt, Agents] = UpdatePath(p, pos_a, pos_t, time_step, Agents, nt) 150 | ind_completed_tasks = []; 151 | 152 | for i = 1:size(pos_a,1) 153 | if ~isempty(p{i}) 154 | d_a_t = pos_t(p{i}(1),:) - pos_a(i,:); 155 | if (norm(d_a_t) < time_step * Agents.Speed(i)) 156 | pos_a(i,:) = pos_t(p{i}(1),:); 157 | nt = nt - 1; 158 | Agents.Lt(i) = Agents.Lt(i) - 1; 159 | ind_completed_tasks = [ind_completed_tasks p{i}(1)]; 160 | %if (nt == 0) 161 | % break; 162 | %end 163 | p{i} = p{i}(2:end); 164 | % if ~isempty(p{i}) 165 | % time_step_remaining = time_step - norm(d_a_t) / Agents.Speed(i); 166 | % d_a_next_t = pos_t(p{i}(1),:) - pos_a(i,:); 167 | % pos_a(i,:) = pos_a(i,:) + d_a_next_t / norm(d_a_next_t) * time_step_remaining * Agents.Speed(i); 168 | % end 169 | else 170 | pos_a(i,:) = pos_a(i,:) + d_a_t / norm(d_a_t) * time_step * Agents.Speed(i); 171 | end 172 | end 173 | end 174 | end 175 | 176 | -------------------------------------------------------------------------------- /src/OptimalControl_lambda.m: -------------------------------------------------------------------------------- 1 | %% Decentralized Control for Dynamic Task Allocation Problems for Multi-Agent Systems with Auctions 2 | % Analysis of the weight variation (lambda) between the reward and the cost of the tasks 3 | % 4 | % Author: Martin Braquet 5 | % Date: September 2020 6 | 7 | addpath('GreedyCoalitionAuctionAlgorithm/'); 8 | close all; clear all; 9 | rng('default'); 10 | rng(8); 11 | 12 | CommLimit = 1; 13 | use_GCAA = 1; 14 | use_OPT = 0; 15 | 16 | na = 10; 17 | nt = 10; 18 | Lt = 1; 19 | 20 | map_width = 1; 21 | comm_distance = 2 * map_width; 22 | 23 | %velocity = 1:na; 24 | %velocity = 1 * ones(1,nt); 25 | max_speed = 0.1; 26 | v_a = (2 * rand(na,2) - 1) * max_speed; 27 | 28 | lambda = 1; 29 | simu_time = 5; 30 | 31 | % Reward after task completion 32 | r_bar = rand(nt,1); 33 | %r_bar = ones(nt,1); 34 | 35 | % Probability that agent i successfully completes task j 36 | prob_a_t = rand(na,nt); 37 | %prob_a_t = 1*ones(na,nt); 38 | 39 | Tasks.r_bar = r_bar; 40 | Tasks.prob_a_t = prob_a_t; 41 | 42 | Agents.N = na; 43 | Agents.Lt = Lt * ones(1,na); 44 | Agents.v_a = v_a; 45 | 46 | costs = zeros(na, nt); 47 | utility = zeros(na, nt); 48 | rewards = zeros(na, nt); 49 | 50 | % Fully connected graph 51 | G = ~eye(Agents.N); 52 | 53 | lambda_vector = 0:10:200; 54 | n_lambda = length(lambda_vector); 55 | simu_time_vector = 3; %1:1:6; 56 | n_simu_time = length(simu_time_vector); 57 | i_simu_time = 0; 58 | 59 | for simu_time = simu_time_vector 60 | i_simu_time = i_simu_time + 1; 61 | i_lambda = 0; 62 | 63 | pos_a = (0.1 + 0.8 * rand(na,2)) * map_width; 64 | pos_t = (0.1 + 0.8 * rand(na,2)) * map_width; 65 | %tf_t = rand(nt,1) * simu_time; 66 | %tf_t = [5*ones(1,3) 10*ones(1,1)]; 67 | tf_t = simu_time / 1.05 * (1 + 0.05 * rand(nt,1)); 68 | %tf_t = 10*ones(1,nt); 69 | 70 | [tf_t, idx] = sort(tf_t); 71 | pos_t = pos_t(idx,:); 72 | 73 | for lambda = lambda_vector 74 | i_lambda = i_lambda + 1; 75 | n_rounds = 40; 76 | time_step = simu_time / n_rounds; 77 | time_start = 0; 78 | 79 | figure; hold on; 80 | colors = lines(na); 81 | %subplot(n_lambda, n_simu_time, (i_lambda - 1) * n_lambda + i_simu_time); 82 | clf; hold on; 83 | xlim([0 map_width]); 84 | ylim([0 map_width]); 85 | xlabel('x [m]'); 86 | ylabel('y [m]'); 87 | title(sprintf('Task-Agent allocation (lambda = %5.2f, tf = %d)', lambda, simu_time)); 88 | for i = 1:na 89 | plot(pos_a(i,1), pos_a(i,2), '*', 'Color', colors(i,:), 'MarkerSize', 10, 'DisplayName', 'Agents'); 90 | end 91 | plot(pos_t(:,1), pos_t(:,2),'rs', 'MarkerSize', 10, 'DisplayName', 'Targets', 'MarkerFaceColor',[1 .6 .6]); 92 | PlotAgentRange(pos_a, comm_distance, colors, 'Comm Range') 93 | 94 | Agents.Pos = pos_a; 95 | Agents.v_a = v_a; 96 | 97 | Tasks.Pos = pos_t; 98 | Tasks.N = nt; 99 | Tasks.tf = tf_t; 100 | Tasks.lambda = lambda; 101 | 102 | for i = 1:na 103 | for j = 1:nt 104 | [~, ~, costs(i,j)] = ComputeCommandParams(pos_a(i,:), v_a(i,:), pos_t(j,:), tf_t(j)); 105 | rewards(i,j) = r_bar(j) * prob_a_t(i,j); 106 | winners = zeros(na,nt); 107 | winners(i,j) = 1; 108 | utility(i,j) = CalcTaskUtility(pos_a, v_a, pos_t(j,:), tf_t(j), r_bar(j), j, prob_a_t, winners, lambda); 109 | end 110 | end 111 | 112 | if CommLimit 113 | for i = 1:na 114 | for j = (i+1):na 115 | G(i,j) = norm(pos_a(i,:) - pos_a(j,:)) < comm_distance; 116 | G(j,i) = G(i,j); 117 | end 118 | end 119 | end 120 | 121 | % GCAA solution 122 | tic; [S_GCAA, p_GCAA, S_GCAA_ALL] = GCAASolution(Agents, G, Tasks) 123 | toc; 124 | 125 | if use_OPT 126 | % Optimal solution 127 | tic; [S_OPT, p_OPT, S_OPT_ALL] = OptimumSolution(Agents, G, Tasks); 128 | toc; 129 | [S_GCAA S_OPT] 130 | end 131 | 132 | % Find the optimal control solution for the given allocation p_GCAA 133 | X = OptimalControlSolution(pos_a, v_a, pos_t, p_GCAA, tf_t, time_step, n_rounds, na); 134 | PlotAlloc(X, n_rounds, na, colors, 'GCAA solution'); 135 | 136 | legend(legendUnq(gca)); 137 | drawnow; 138 | end 139 | end 140 | -------------------------------------------------------------------------------- /src/OptimumSolution.m: -------------------------------------------------------------------------------- 1 | %% Computes the optimum solution of the task-assignment problem 2 | % Author: Martin Braquet 3 | % Date: August 23, 2020 4 | 5 | function [S_opt, p_opt, S_opt_all] = OptimumSolution(Agents, G, Tasks) 6 | 7 | na = Agents.N; 8 | Lt = Agents.Lt(1); 9 | pos_a = Agents.Pos; 10 | 11 | nt = Tasks.N; 12 | pos_t = Tasks.Pos; 13 | 14 | b{na} = []; 15 | 16 | Nmin = min(nt, Lt*na); 17 | 18 | I = 1:na; 19 | J = 1:nt; 20 | 21 | S_opt = 0; 22 | 23 | if Nmin == nt 24 | list_b = AllAllocComb_Nt(1, J, [], b); % Sufficient number of agents to allocate all the targets 25 | else 26 | list_b = AllAllocComb_NuLt(1, J, [], b); 27 | end 28 | 29 | all_S{size(list_b,2)} = []; 30 | all_p{size(list_b,2)} = []; 31 | % % Enumerates all combinations of tasks to agents (without order) 32 | % perms_tasks = perms(1:nj); % All permutations of tasks: [1 2 3], [1 3 2], 33 | % % [2 1 3], [2 3 1], [3 1 2] and [3 2 1] (if nj = 3) 34 | % task_list = perms_tasks(t,:); % 1 of the 6 task lists 35 | % % Enumerates all the possibilities to split the task list among all agents 36 | 37 | for l = 1:size(list_b,2) 38 | b_curr = list_b{l}; 39 | 40 | stop = 0; 41 | for i = 1:na 42 | if length(b_curr{i}) > 1 43 | stop = 1; % Consider only one task per agent 44 | end 45 | end 46 | if stop 47 | continue; 48 | end 49 | 50 | winners = zeros(na,nt); 51 | for i = 1:na 52 | for j = 1:nt 53 | winners(i,j) = (sum(b_curr{i} == j) > 0); 54 | end 55 | end 56 | [S, all_scores] = ComputeScore(na, b_curr, winners); 57 | all_S{l} = S; 58 | all_p{l} = b_curr; 59 | if S > S_opt 60 | S_opt = S; 61 | p_opt = b_curr; 62 | S_opt_all = all_scores; 63 | end 64 | end 65 | 66 | 67 | %% 68 | function list_b = AllAllocComb_Nt(i, J, list_b, b) 69 | if i == na+1 70 | list_b{size(list_b,2)+1} = b; 71 | else 72 | for k = 0:Lt 73 | allcombs = combnk(J,k); 74 | for l = 1:size(allcombs,1) 75 | b{i} = allcombs(l,:); 76 | J_new = J; %J_new(ismember(J_new,allcombs(l,:))) = 0; J_new = J_new(J_new~=0); 77 | list_b = AllAllocComb_Nt(i+1, J_new, list_b, b); 78 | end 79 | end 80 | end 81 | end 82 | 83 | function list_b = AllAllocComb_NuLt(i, J, list_b, b) 84 | if i > na 85 | list_b{size(list_b,2)+1} = b; 86 | else 87 | allcombs = combnk(J,Lt); 88 | for l = 1:size(allcombs,1) 89 | b{i} = allcombs(l,:); 90 | J_new = J; %J_new(ismember(J_new,allcombs(l,:))) = 0; J_new = J_new(J_new~=0); 91 | list_b = AllAllocComb_NuLt(i+1, J_new, list_b, b); 92 | end 93 | end 94 | end 95 | 96 | function [S_new, S_j] = ComputeScore(nt, b, winners) 97 | S_j = zeros(1,nt); 98 | for j = 1:nt 99 | % % No assignment if same end time for two tasks in the sequence 100 | % stop = 0; 101 | % for j = 1:length(b{i}) 102 | % if j ~= 1 && task_tf(b(j)) == task_tf(b(j-1)) 103 | % stop = 1; 104 | % break; 105 | % end 106 | % end 107 | % if ~stop 108 | S_j(j) = CalcTaskUtility(Agents.Pos, Agents.v_a, Tasks.Pos(j,:), Tasks.tf(j), Tasks.r_bar(j), j, Tasks.prob_a_t, winners); 109 | p{i} = b{i}; 110 | % end 111 | end 112 | 113 | S_new = sum(S_j); 114 | end 115 | end 116 | -------------------------------------------------------------------------------- /src/PlotAgentRange.m: -------------------------------------------------------------------------------- 1 | function PlotAgentRange(pos_a, comm_distance, color, name) 2 | n = 20; 3 | theta = linspace(0, 2*pi, n)'; 4 | for i = 1:size(pos_a,1) 5 | pos = repmat(pos_a(i,:), n, 1) + comm_distance * [cos(theta) sin(theta)]; 6 | plot(pos(:,1), pos(:,2), '--', 'Color', color(i,:), 'LineWidth', 1, 'DisplayName', name); 7 | end 8 | end -------------------------------------------------------------------------------- /src/PlotAllocTime.m: -------------------------------------------------------------------------------- 1 | function [] = PlotAllocTime(X_full_simu, t_plot, time_step, pos_t, map_width, colors, radius_t, task_type, nRatioPointsFigure, lineWidthFigure, markerSizeFigure) 2 | xlim([0 map_width]); 3 | ylim([0 map_width]); 4 | xlabel('x [m]'); 5 | ylabel('y [m]'); 6 | na = size(X_full_simu{1}, 2); 7 | n_round = size(X_full_simu{1}, 3); 8 | plot(pos_t(:,1), pos_t(:,2),'ks', 'MarkerSize', markerSizeFigure/2.5, 'MarkerFaceColor',[0 0 0]); 9 | PlotTaskLoitering(pos_t, radius_t, task_type, 'k--', 'Task loitering'); 10 | 11 | round_plot = floor(t_plot / time_step) + 1; 12 | if round_plot >= n_round 13 | round_plot = n_round-1; 14 | end 15 | X_prev = zeros(4, na, round_plot); 16 | for k = 1:round_plot 17 | X_prev(:,:,k) = X_full_simu{k}(:,:,1); 18 | end 19 | 20 | X_next = zeros(4, na, n_round - round_plot); 21 | for i = 1:na 22 | X_next(:,i,:) = X_full_simu{round_plot}(:,i,2:end); 23 | end 24 | 25 | for i = 1:na 26 | xX_prev = reshape(X_prev(:,i,:),[4, size(X_prev, 3)]); 27 | xX_next = reshape(X_next(:,i,:),[4, size(X_next, 3)]); 28 | plot(xX_prev(1,1:nRatioPointsFigure:end), xX_prev(2,1:nRatioPointsFigure:end), 'Color', colors(i,:), 'LineWidth', lineWidthFigure); 29 | plot(xX_next(1,1:nRatioPointsFigure:end), xX_next(2,1:nRatioPointsFigure:end), '--', 'Color', colors(i,:), 'LineWidth', lineWidthFigure-1); 30 | plot(xX_next(1), xX_next(2), 'h', 'Color', colors(i,:), 'MarkerSize', markerSizeFigure, 'MarkerFaceColor', colors(i,:)); 31 | end 32 | end -------------------------------------------------------------------------------- /src/PlotAnimation.m: -------------------------------------------------------------------------------- 1 | function M = PlotAnimation(X_full_simu, n_rounds, time_step, pos_t, map_width, colors, radius_t, task_type) 2 | figure; 3 | clear M; 4 | for k = 1:n_rounds-1 5 | t_plot = time_step * (k-1); 6 | clf; hold on; 7 | PlotAllocTime(X_full_simu, t_plot, time_step, pos_t, map_width, colors, radius_t, task_type); 8 | %drawnow; 9 | M(k) = getframe(gcf,[74 47 450 350]); 10 | end 11 | figure; 12 | fps = floor(1 / time_step); 13 | movie(M,1,fps); 14 | end -------------------------------------------------------------------------------- /src/PlotAnimationAndUtility.m: -------------------------------------------------------------------------------- 1 | function M = PlotAnimationAndUtility(X_full_simu, SimuParamsCell, J, J_to_completion_target, rt_full_simu, PlotCommLimit, saveMovie, filename) 2 | clear M; 3 | 4 | n_rounds = SimuParamsCell.n_rounds; 5 | time_step = SimuParamsCell.time_step; 6 | pos_t = SimuParamsCell.pos_t; 7 | map_width = SimuParamsCell.map_width; 8 | colors = SimuParamsCell.colors; 9 | radius_t = SimuParamsCell.radius_t; 10 | task_type = SimuParamsCell.task_type; 11 | comm_distance = SimuParamsCell.comm_distance; 12 | 13 | nRatioPointsFigure = 1; 14 | lineWidthFigure = 4; 15 | markerSizeFigure = 20; 16 | 17 | na = size(J,2); 18 | J_tot = J + J_to_completion_target; 19 | 20 | win = figure(1); hold on; 21 | win(1) = subplot(2, 3, 1); 22 | xlim([0 n_rounds*time_step]); 23 | ylim([0 max(max(J_tot))*1.1]); 24 | title('Cost'); 25 | xlabel('t [s]'); 26 | win(2) = subplot(2, 3, 4); 27 | xlim([0 n_rounds*time_step]); 28 | ylim([0 max(sum(rt_full_simu,2))*1.1]); 29 | xlabel('t [s]'); 30 | win(3) = subplot(2, 3, [2 3 5 6]); 31 | xlim([0 1]); ylim([0 1]); 32 | t = (0:n_rounds) * time_step; 33 | set(win,'Nextplot','add'); set(gcf,'color','w'); 34 | set(win,'fontsize', 25); 35 | for k = 2:n_rounds-1 36 | cla(win(1)); 37 | t_plot = time_step * (k-1); 38 | for i = 1:na 39 | plot(win(1), t(1:k), J_tot(1:k,i), 'LineWidth', 2); 40 | end 41 | cla(win(2)); 42 | plot(win(2), t(1:k), sum(rt_full_simu(1:k,:),2), 'k--', 'LineWidth', 3); 43 | U_tot = sum(rt_full_simu(1:k-1,:),2) - sum(J_tot(2:k,:),2); 44 | U_tot(1,:) = 0; 45 | plot(win(2), t(1:k-1), U_tot, 'k', 'LineWidth', 3); 46 | legend(win(2), 'Reward', 'Utility', 'Location', 'SouthEast'); 47 | cla(win(3)); 48 | PlotAllocTime(X_full_simu, t_plot, time_step, pos_t, map_width, colors, radius_t, task_type, nRatioPointsFigure, lineWidthFigure, markerSizeFigure); 49 | if PlotCommLimit 50 | pos_a = zeros(na,2); 51 | for i = 1:na 52 | pos_a(i,:) = X_full_simu{k}(1:2,i,1)'; 53 | end 54 | PlotAgentRange(pos_a, comm_distance, colors, '') 55 | end 56 | drawnow; 57 | if saveMovie 58 | M(k-1) = getframe(gcf,[74 47 450 350]); 59 | end 60 | end 61 | if saveMovie 62 | figure; 63 | fps = floor(1 / time_step); 64 | movie(M,1,fps); 65 | else 66 | M = []; 67 | end 68 | frame = getframe(win); 69 | im = frame2im(frame); 70 | [imind,cm] = rgb2ind(im,256); 71 | imwrite(imind,cm,filename,'gif','WriteMode','append','DelayTime',obj.t_hist(step)); 72 | end -------------------------------------------------------------------------------- /src/PlotTaskLoitering.m: -------------------------------------------------------------------------------- 1 | function PlotTaskLoitering(pos_t, radius_t, type_t, color, name) 2 | n = 20; 3 | theta = linspace(0, 2*pi, n)'; 4 | for i = 1:size(pos_t,1) 5 | if type_t(i) == 1 6 | pos = repmat(pos_t(i,:), n, 1) + radius_t(i) * [cos(theta) sin(theta)]; 7 | plot(pos(:,1), pos(:,2), color, 'LineWidth', 2, 'DisplayName', name); 8 | end 9 | end 10 | end -------------------------------------------------------------------------------- /src/PlotUtilitySimulation.m: -------------------------------------------------------------------------------- 1 | close all; clear all; 2 | 3 | simu_number = 7; 4 | CommLimit = 0; 5 | load(sprintf('mat/Dynamics/simu_%d/SimuParamsCell.mat', simu_number)); 6 | load(sprintf('mat/Dynamics/simu_%d/X_just_saved_CommLimit_%d.mat', simu_number, CommLimit)); 7 | load(sprintf('mat/Dynamics/simu_%d/J_to_completion_target_CommLimit_%d.mat', simu_number, CommLimit)); 8 | load(sprintf('mat/Dynamics/simu_%d/J_CommLimit_%d.mat', simu_number, CommLimit)); 9 | load(sprintf('mat/Dynamics/simu_%d/p_GCAA_just_saved_CommLimit_%d.mat', simu_number, CommLimit)); 10 | load(sprintf('mat/Dynamics/simu_%d/S_GCAA_ALL_just_saved_CommLimit_%d.mat', simu_number, CommLimit)); 11 | load(sprintf('mat/Dynamics/simu_%d/rt_just_saved_CommLimit_%d.mat', simu_number, CommLimit)); 12 | 13 | na = size(J,2); 14 | 15 | J(isnan(J)) = 0; 16 | 17 | J_to_completion_target(isnan(J_to_completion_target)) = 0; 18 | 19 | %rt = p_GCAA_full_simu ... 20 | 21 | figure; hold on; 22 | for i = 1:na 23 | plot(J(:,i)); 24 | end 25 | plot(sum(J,2), 'LineWidth', 3); 26 | title('Cost up to t'); 27 | 28 | figure; hold on; 29 | for i = 1:na 30 | plot(J_to_completion_target(:,i)); 31 | end 32 | plot(sum(J_to_completion_target,2), 'LineWidth', 3); 33 | title('Estimated cost from t to end'); 34 | 35 | figure; hold on; 36 | ylim([0 max(sum(J(1:end-1,:),2) + sum(J_to_completion_target(2:end,:),2)) * 1.1]); 37 | for i = 1:na 38 | plot(sum(J(1:end-1,i),2) + sum(J_to_completion_target(2:end,i),2)); 39 | end 40 | plot(sum(J(1:end-1,:),2) + sum(J_to_completion_target(2:end,:),2), 'LineWidth', 3); 41 | title('Estimated cost from start to end'); 42 | 43 | 44 | figure; hold on; 45 | plot(sum(rt_full_simu(1:end-2,:),2)); 46 | title('Reward for the assignement at time t'); 47 | 48 | figure; hold on; 49 | plot(sum(rt_full_simu(1:end-2,:),2) - (sum(J(1:end-3,:),2) + sum(J_to_completion_target(2:end-2,:),2))); 50 | title('Utility for the assignement at time t'); 51 | -------------------------------------------------------------------------------- /src/PlotUtilitySimulationLaTeX.m: -------------------------------------------------------------------------------- 1 | close all; clear all; 2 | 3 | % Figure 1: cost and reward with/without commlimit 4 | % Figure 2: utility with/without commlimit 5 | 6 | simu_number = 6; 7 | figure(1); hold on; 8 | figure(2); hold on; 9 | 10 | colors = lines(2); 11 | maxYUtility = 0; 12 | maxYReward = 0 13 | 14 | for CommLimit = [0 1] 15 | 16 | load(sprintf('mat/Dynamics/simu_%d/SimuParamsCell.mat', simu_number)); 17 | load(sprintf('mat/Dynamics/simu_%d/X_just_saved_CommLimit_%d.mat', simu_number, CommLimit)); 18 | load(sprintf('mat/Dynamics/simu_%d/J_to_completion_target_CommLimit_%d.mat', simu_number, CommLimit)); 19 | load(sprintf('mat/Dynamics/simu_%d/J_CommLimit_%d.mat', simu_number, CommLimit)); 20 | load(sprintf('mat/Dynamics/simu_%d/p_GCAA_just_saved_CommLimit_%d.mat', simu_number, CommLimit)); 21 | load(sprintf('mat/Dynamics/simu_%d/S_GCAA_ALL_just_saved_CommLimit_%d.mat', simu_number, CommLimit)); 22 | load(sprintf('mat/Dynamics/simu_%d/rt_just_saved_CommLimit_%d.mat', simu_number, CommLimit)); 23 | 24 | na = size(J,2); 25 | 26 | t = (0:SimuParamsCell.n_rounds) * SimuParamsCell.time_step; 27 | 28 | J(isnan(J)) = 0; 29 | J_to_completion_target(isnan(J_to_completion_target)) = 0; 30 | 31 | figure(1) 32 | plot(t(1:end-1),sum(J(1:end-1,:),2) + sum(J_to_completion_target(2:end,:),2), 'color', colors(CommLimit+1,:), 'LineWidth', 3); 33 | plot(t(1:end-1),sum(rt_full_simu(1:end,:),2), '--', 'color', colors(CommLimit+1,:), 'LineWidth', 3); 34 | %ylim([0 max(sum(J(1:end-1,:),2) + sum(J_to_completion_target(2:end,:),2)) * 1.1]); 35 | maxYReward = max(maxYReward,max(sum(rt_full_simu(1:end,:),2))); 36 | 37 | figure(2); hold on; 38 | plot(t(1:end-3),sum(rt_full_simu(1:end-2,:),2) - (sum(J(1:end-3,:),2) + sum(J_to_completion_target(2:end-2,:),2)), 'color', colors(CommLimit+1,:), 'LineWidth', 3); 39 | 40 | maxYUtility = max(maxYUtility, max(sum(rt_full_simu(1:end-2,:),2) - (sum(J(1:end-3,:),2) + sum(J_to_completion_target(2:end-2,:),2)))); 41 | 42 | end 43 | 44 | figure(1); 45 | legend('Cost (unconstrained)', 'Reward (unconstrained)', 'Cost (constrained)', 'Reward (constrained)', 'Location', 'SouthEast'); 46 | ylim([0 maxYReward * 1.1]); 47 | matlab2tikz(sprintf('mat/Dynamics/simu_%d/CostReward.tex',simu_number)); 48 | 49 | figure(2); 50 | legend('Utility (unconstrained)', 'Utility (constrained)', 'Location', 'SouthEast'); 51 | ylim([0 maxYUtility * 1.1]); 52 | matlab2tikz(sprintf('mat/Dynamics/simu_%d/TotalUtility.tex',simu_number)); -------------------------------------------------------------------------------- /src/WinnerVectorToMatrix.m: -------------------------------------------------------------------------------- 1 | function [ winners_matrix ] = WinnerVectorToMatrix(N, M, winners) 2 | 3 | winners_matrix = zeros(N, M); 4 | for i = 1:N 5 | if winners(i) > 0 6 | winners_matrix(i,winners(i)) = 1; 7 | end 8 | end 9 | 10 | end 11 | 12 | -------------------------------------------------------------------------------- /src/legendUnq.m: -------------------------------------------------------------------------------- 1 | function unqLegHands = legendUnq(h, sortType) 2 | % unqLegHands = legendUnq(h, sortType) 3 | % Run this function just before running 'legend()' to avoid representing duplicate or missing 4 | % DisplayNames within the legend. This solves the problem of having a cluttered legend with 5 | % duplicate or generic values such as "data1" assigned by matalab's legend() function. This 6 | % also makes is incredibly easy to assign one legend to a figure with multiple subplots. 7 | % Use the 'DisplayName' property in your plots and input the axis handle or the figure handle 8 | % so this code can search for all potential legend elements, find duplicate DisplayName strings, 9 | % and remove redundent components by setting their IconDisplayStyle to 'off'. Then call 10 | % legend(unqLegHands) to display unique legend components. 11 | % INTPUT 12 | % h: (optional) either a handle to a figure, an axis, or a vector of axis handles. The code 13 | % will search for plot elements in all axes belonging to h. If h is missing, gca is used. 14 | % sort: (optional) can be one of the following strings that will sort the unqLeghands. 15 | % 'alpha': alphabetical order. 16 | % OUTPUT 17 | % unqLegHands: a list of handles that have unique DisplayNames; class 'matlab.graphics.chart.primitive.Line'. 18 | % ie: unqLegHands = legendUnq(figHandle); legend(unqLegHands) 19 | % EXAMPLE 1: 20 | % figure; axis; hold on 21 | % for i=1:10 22 | % plot(i,rand(), 'ko', 'DisplayName', 'randVal1'); % included in legend 23 | % plot(i+.33, rand(), 'ro', 'DisplayName', 'randVal2'); % included in legend 24 | % end 25 | % plot(rand(1,10), 'b-'); % no DisplayName so it is absent from legend 26 | % legend(legendUnq()) 27 | % EXAMPLE 2: 28 | % fh = figure; subplot(2,2,1); hold on 29 | % plot(1:10, rand(1,10), 'b-o', 'DisplayName', 'plot1 val1') 30 | % plot(1:2:10, rand(1,5), 'r-*', 'DisplayName', 'plot1 val2') 31 | % subplot(2,2,2); hold on 32 | % plot(1:10, rand(1,10), 'm-o', 'DisplayName', 'plot2 val1') 33 | % plot(1:2:10, rand(1,5), 'g-*', 'DisplayName', 'plot2 val2') 34 | % subplot(2,2,3); hold on 35 | % plot(1:10, rand(1,10), 'c-o', 'DisplayName', 'plot3 val1') 36 | % plot(1:2:10, rand(1,5), 'k-*', 'DisplayName', 'plot3 val2') 37 | % lh = legend(legendUnq(fh)); 38 | % lh.Position = [.6 .2 .17 .21]; 39 | % 40 | % Danz 180515 41 | 42 | % Change history 43 | % 180912 fixed error when plot is empty 44 | % 180913 adapted use of undocumented function for matlab 2018b 45 | 46 | persistent useOldMethod 47 | 48 | % If handle isn't specified, choose current axes 49 | if nargin == 0 50 | h = gca; 51 | end 52 | 53 | % If user entered a figure handle, replace with a list of children axes; preserve order of axes 54 | if strcmp(get(h, 'type'), 'figure') 55 | h = flipud(findall(h, 'type', 'Axes')); 56 | end 57 | 58 | % set flag to use old method of obtaining legend children 59 | % In 2018b matlab changed an undocumented function that obtains legend handles. 60 | useOldMethod = verLessThan('matlab', '9.5.0'); 61 | 62 | % Set the correct undocumented function 63 | if useOldMethod 64 | getLegendChildren = @(x) graph2dhelper('get_legendable_children', x); 65 | else 66 | getLegendChildren = @(x) matlab.graphics.illustration.internal.getLegendableChildren(x); 67 | end 68 | 69 | % Get all objects that will be assigned to legend. 70 | % This uses an undocumented function that the legend() func uses to get legend componenets. 71 | legChildren = matlab.graphics.chart.primitive.Line; %initializing class (unsure of a better way) 72 | for i = 1:length(h) 73 | temp = getLegendChildren(h(i)); 74 | if ~isempty(temp) 75 | legChildren(end+1:end+length(temp),1) = temp; 76 | end 77 | end 78 | legChildren(1) = []; 79 | % Get display names 80 | dispNames = get(legChildren, 'DisplayName'); 81 | if isempty(dispNames) 82 | dispNames = {''}; 83 | end 84 | if ~iscell(dispNames) 85 | dispNames = {dispNames}; 86 | end 87 | % Find the first occurance of each name 88 | [~, firstIdx] = unique(dispNames, 'first'); 89 | % Create an index of legend items that will be hidden from legend 90 | legRmIdx = true(size(legChildren)); 91 | legRmIdx(firstIdx) = false; 92 | % Add any elements that have no displayName to removal index (legend would assign them 'dataX') 93 | legRmIdx = legRmIdx | cellfun(@isempty,dispNames); 94 | % get all annotations 95 | annot = get(legChildren, 'Annotation'); 96 | % Loop through all items to be hidden and turn off IconDisplayStyle 97 | for i = 1:length(annot) 98 | if legRmIdx(i) 99 | set(get(annot{i}, 'LegendInformation'), 'IconDisplayStyle', 'off'); 100 | end 101 | end 102 | % Output remaining, handles to unique legend entries 103 | unqLegHands = legChildren(~legRmIdx); 104 | 105 | % Sort, if user requested 106 | if nargin > 1 && ~isempty(sortType) && length(unqLegHands)>1 107 | [~, sortIdx] = sort(get(unqLegHands, 'DisplayName')); 108 | unqLegHands = unqLegHands(sortIdx); 109 | end 110 | -------------------------------------------------------------------------------- /src/optimalControlParametersAnalysis.m: -------------------------------------------------------------------------------- 1 | %% Decentralized Control for Dynamic Task Allocation Problems for Multi-Agent Systems with Auctions 2 | % Analysis of the variation of the parameters 3 | % 4 | % Author: Martin Braquet 5 | % Date: November 2020 6 | 7 | function [] = optimalControlParametersAnalysis() 8 | 9 | addpath('GreedyCoalitionAuctionAlgorithm/'); 10 | close all; clear all; 11 | rng('default'); 12 | rng(6); 13 | 14 | simuNumber = 3; 15 | simuName = 'Variation of parameters'; 16 | 17 | %% Setting of the manual parameters 18 | 19 | AllParamsToAnalyze = {'RangeLimitation', 'RewardSuccessProbability', 'NumberAgentsTasks', 'TimeRatioLoiteringTasks'}; 20 | paramToAnalyze = AllParamsToAnalyze{3}; 21 | 22 | isUniformAgents = 0; 23 | isUniformTasks = 1; 24 | isPlotAlloc = 0; 25 | isPlotRange = 0; 26 | isCommLimit = 0; 27 | 28 | nA = 10; 29 | nT = 20; 30 | ntLoiter = 0; %ceil(0.5*nt); 31 | ratioRangeMapWidth = 0.3; 32 | nRounds = 50; 33 | maxInitSpeedAgents = 0.1; 34 | nomReward = 1; 35 | nomProbAT = 0.5; 36 | 37 | 38 | %% Setting of the fixed parameters 39 | 40 | lambda = 1; 41 | Lt = 1; 42 | 43 | mapWidth = 1; 44 | commDistance = ratioRangeMapWidth * mapWidth; 45 | 46 | simuTime = 10; 47 | timeStep = simuTime / nRounds; 48 | 49 | posA = (0.1 + 0.8 * rand(nA,2)) * mapWidth; 50 | posT = (0.1 + 0.8 * rand(nT,2)) * mapWidth; 51 | 52 | tfT = simuTime * ones(nT,1); 53 | tlT = 0.2 * simuTime * ones(nT,1); 54 | taskType = zeros(nT,1); 55 | taskType(1:ntLoiter) = 1; 56 | tlT(taskType == 0) = 0; 57 | [tlT, idx] = sort(tlT); 58 | posT = posT(idx,:); 59 | 60 | % Drag force to slow down the agents, final speed set to exp(-3) * vA0 61 | kdrag = 3 / simuTime; 62 | 63 | if isUniformAgents 64 | vA = zeros(nA,2); 65 | else 66 | vA = (2 * rand(nA,2) - 1) * maxInitSpeedAgents; 67 | end 68 | 69 | maxInitSpeedTasks = 0.1; 70 | if isUniformTasks 71 | vT = zeros(nT,2); 72 | else 73 | vT = (2 * rand(nT,2) - 1) * maxInitSpeedTasks; 74 | end 75 | 76 | R = 0.04 * mapWidth; 77 | if isUniformTasks 78 | radiusT = R * ones(nT,1); 79 | else 80 | radiusT = (0.2 * rand(nT,1) + 1) * R; 81 | end 82 | 83 | % Reward after task completion 84 | if isUniformTasks 85 | rBar = nomReward * ones(nT,1); 86 | else 87 | rBar = nomReward * rand(nT,1); 88 | end 89 | rBar(taskType == 1) = 2 * rBar(taskType == 1); 90 | 91 | % Probability that agent i successfully completes task j 92 | if isUniformAgents 93 | probAT = nomProbAT * ones(nA,nT); 94 | else 95 | probAT = rand(nA,nT); 96 | end 97 | 98 | Tasks.Pos = posT; 99 | Tasks.Speed = vT; 100 | Tasks.N = nT; 101 | Tasks.tf = tfT; 102 | Tasks.lambda = lambda; 103 | Tasks.task_type = taskType; 104 | Tasks.tloiter = tlT; 105 | Tasks.radius = radiusT; 106 | Tasks.r_bar = rBar; 107 | Tasks.prob_a_t = probAT; 108 | Tasks.task_type = taskType; 109 | 110 | Agents.N = nA; 111 | Agents.Lt = Lt * ones(1,nA); 112 | Agents.Pos = posA; 113 | Agents.v_a = vA; 114 | Agents.previous_task = zeros(nA,1); 115 | Agents.previous_winnerBids = zeros(nA,1); 116 | Agents.rin_task = zeros(nA,2); 117 | Agents.vin_task = zeros(nA,2); 118 | Agents.kdrag = kdrag; 119 | 120 | % Fully connected graph 121 | G = ~eye(Agents.N); 122 | 123 | if isPlotAlloc 124 | figure; hold on; 125 | colors = lines(nA); 126 | SimuParamsCell.colors = colors; 127 | end 128 | 129 | SimuParamsCell.n_rounds = nRounds; 130 | SimuParamsCell.timeStep = timeStep; 131 | SimuParamsCell.mapWidth = mapWidth; 132 | SimuParamsCell.commDistance = commDistance; 133 | SimuParamsCell.simuTime = simuTime; 134 | SimuParamsCell.timeStep = timeStep; 135 | SimuParamsCell.posA = posA; 136 | SimuParamsCell.maxInitSpeedAgents = maxInitSpeedAgents; 137 | SimuParamsCell.vA = vA; 138 | SimuParamsCell.posT = posT; 139 | SimuParamsCell.maxInitSpeedTasks = maxInitSpeedTasks; 140 | SimuParamsCell.vT = vT; 141 | SimuParamsCell.radiusT = radiusT; 142 | SimuParamsCell.taskType = taskType; 143 | SimuParamsCell.ntLoiter = ntLoiter; 144 | SimuParamsCell.taskType = taskType; 145 | SimuParamsCell.na = nA; 146 | SimuParamsCell.nt = nT; 147 | SimuParamsCell.tfT = tfT; 148 | SimuParamsCell.tlT = tlT; 149 | SimuParamsCell.R = R; 150 | SimuParamsCell.radiusT = radiusT; 151 | SimuParamsCell.nomReward = nomReward; 152 | SimuParamsCell.rBar = rBar; 153 | SimuParamsCell.lambda = lambda; 154 | SimuParamsCell.probAT = probAT; 155 | SimuParamsCell.kdrag = kdrag; 156 | 157 | %% 158 | 159 | switch paramToAnalyze 160 | case 'RangeLimitation' 161 | analyzeUtilityRangeLimitation(); 162 | case 'RewardSuccessProbability' 163 | analyzeUtilityRewardSuccessProbability(); 164 | case 'NumberAgentsTasks' 165 | analyzeTimeNumberAgentsTasks(); 166 | case 'TimeRatioLoiteringTasks' 167 | analyzeTimeRatioLoiteringTasks(); 168 | end 169 | 170 | %% Main subfunctions 171 | 172 | function [] = analyzeUtilityRangeLimitation() 173 | 174 | % Setting of the varying parameters 175 | ratioRangeMapWidth = 0:0.01:1; 176 | commDistance = ratioRangeMapWidth * mapWidth; 177 | totalUtilityAllocation = zeros(length(ratioRangeMapWidth), 1); 178 | 179 | for k = 1:length(ratioRangeMapWidth) 180 | if isPlotAlloc 181 | plotMapAgentsTasks(); 182 | end 183 | 184 | for i = 1:nA 185 | for j = (i+1):nA 186 | G(i,j) = norm(posA(i,:) - posA(j,:)) < commDistance(k); 187 | G(j,i) = G(i,j); 188 | end 189 | end 190 | 191 | % GCAA solution 192 | tic; 193 | [S_GCAA, pGCAA, ~, ~, Agents] = GCAASolution(Agents, G, Tasks); 194 | pGCAA 195 | toc; 196 | 197 | totalUtilityAllocation(k) = S_GCAA; 198 | 199 | if isPlotAlloc 200 | setPlotAllocation(pGCAA); 201 | end 202 | end 203 | 204 | mkdir(sprintf('mat/%s/%s/simu_%d', simuName, paramToAnalyze, simuNumber)); 205 | save(sprintf('mat/%s/%s/simu_%d/ratioRangeMapWidth-%d.mat', simuName, paramToAnalyze, simuNumber), 'ratioRangeMapWidth'); 206 | save(sprintf('mat/%s/%s/simu_%d/totalUtilityAllocation-%d.mat', simuName, paramToAnalyze, simuNumber), 'totalUtilityAllocation'); 207 | save(sprintf('mat/%s/%s/simu_%d/SimuParamsCell.mat', simuName, paramToAnalyze, simuNumber), 'SimuParamsCell'); 208 | 209 | figure; 210 | plot(ratioRangeMapWidth, totalUtilityAllocation); 211 | title('Total utility'); 212 | 213 | end 214 | 215 | function [] = analyzeUtilityRewardSuccessProbability() 216 | 217 | % Setting of the varying parameters 218 | nomReward = 0:0.1:1; 219 | nomProbAT = 0:0.1:1; 220 | totalUtilityAllocation = zeros(length(nomReward), length(nomProbAT)); 221 | 222 | for k = 2:length(nomReward) 223 | for l = 2:length(nomProbAT) 224 | 225 | rBar = nomReward(k) * ones(nT,1); 226 | Tasks.r_bar = rBar; 227 | probAT = nomProbAT(l) * ones(nA,nT); 228 | Tasks.prob_a_t = probAT; 229 | 230 | if isPlotAlloc 231 | plotMapAgentsTasks(); 232 | end 233 | 234 | if isCommLimit 235 | setCommunicationLimitation(); 236 | end 237 | 238 | % GCAA solution 239 | tic; 240 | [S_GCAA, pGCAA, ~, ~, Agents] = GCAASolution(Agents, G, Tasks); 241 | pGCAA 242 | toc; 243 | 244 | totalUtilityAllocation(k,l) = S_GCAA; 245 | 246 | if isPlotAlloc 247 | setPlotAllocation(pGCAA); 248 | end 249 | end 250 | end 251 | 252 | mkdir(sprintf('mat/%s/%s/simu_%d', simuName, paramToAnalyze, simuNumber)); 253 | save(sprintf('mat/%s/%s/simu_%d/nomReward-%d.mat', simuName, paramToAnalyze, simuNumber), 'nomReward'); 254 | save(sprintf('mat/%s/%s/simu_%d/nomProbAT-%d.mat', simuName, paramToAnalyze, simuNumber), 'nomProbAT'); 255 | save(sprintf('mat/%s/%s/simu_%d/totalUtilityAllocation-%d.mat', simuName, paramToAnalyze, simuNumber), 'totalUtilityAllocation'); 256 | save(sprintf('mat/%s/%s/simu_%d/SimuParamsCell.mat', simuName, paramToAnalyze, simuNumber), 'SimuParamsCell'); 257 | 258 | figure; 259 | [mechNomReward, meshNomProbAT] = meshgrid(nomReward, nomProbAT); 260 | surf(mechNomReward, meshNomProbAT, totalUtilityAllocation); 261 | xlabel('nomReward'); 262 | ylabel('nomProbAT'); 263 | title('Total utility'); 264 | 265 | end 266 | 267 | function [] = analyzeTimeNumberAgentsTasks() 268 | 269 | % Setting of the varying parameters 270 | nAVect = 1:2:80; 271 | nTVect = 1:2:80; 272 | totalUtilityAllocation = zeros(length(nAVect), length(nTVect)); 273 | totalComputationTime = zeros(length(nAVect), length(nTVect)); 274 | 275 | for k = 1:length(nAVect) 276 | for l = 1:length(nTVect) 277 | 278 | nA = nAVect(k); 279 | nT = nTVect(l); 280 | 281 | posA = (0.1 + 0.8 * rand(nA,2)) * mapWidth; 282 | posT = (0.1 + 0.8 * rand(nT,2)) * mapWidth; 283 | tfT = simuTime * ones(nT,1); 284 | tlT = 0.2 * simuTime * ones(nT,1); 285 | taskType = zeros(nT,1); 286 | taskType(1:ntLoiter) = 1; 287 | tlT(taskType == 0) = 0; 288 | [tlT, idx] = sort(tlT); 289 | posT = posT(idx,:); 290 | vA = zeros(nA,2); 291 | vT = zeros(nT,2); 292 | R = 0.04 * mapWidth; 293 | radiusT = R * ones(nT,1); 294 | rBar = nomReward * ones(nT,1); 295 | probAT = nomProbAT * ones(nA,nT); 296 | G = ~eye(nA); 297 | 298 | Tasks.Pos = posT; 299 | Tasks.Speed = vT; 300 | Tasks.N = nT; 301 | Tasks.tf = tfT; 302 | Tasks.lambda = lambda; 303 | Tasks.task_type = taskType; 304 | Tasks.tloiter = tlT; 305 | Tasks.radius = radiusT; 306 | Tasks.r_bar = rBar; 307 | Tasks.prob_a_t = probAT; 308 | Tasks.task_type = taskType; 309 | 310 | Agents.N = nA; 311 | Agents.Lt = Lt * ones(1,nA); 312 | Agents.Pos = posA; 313 | Agents.v_a = vA; 314 | Agents.previous_task = zeros(nA,1); 315 | Agents.previous_winnerBids = zeros(nA,1); 316 | Agents.rin_task = zeros(nA,2); 317 | Agents.vin_task = zeros(nA,2); 318 | 319 | if isPlotAlloc 320 | plotMapAgentsTasks(); 321 | end 322 | 323 | if isCommLimit 324 | setCommunicationLimitation(); 325 | end 326 | 327 | % GCAA solution 328 | tic; 329 | [S_GCAA, pGCAA, ~, ~, Agents] = GCAASolution(Agents, G, Tasks); 330 | %pGCAA 331 | totalComputationTime(k,l) = toc; 332 | [k l] 333 | 334 | totalUtilityAllocation(k,l) = S_GCAA; 335 | 336 | if isPlotAlloc 337 | setPlotAllocation(pGCAA); 338 | end 339 | end 340 | end 341 | 342 | mkdir(sprintf('mat/%s/%s/simu_%d', simuName, paramToAnalyze, simuNumber)); 343 | save(sprintf('mat/%s/%s/simu_%d/nAVect-%d.mat', simuName, paramToAnalyze, simuNumber), 'nAVect'); 344 | save(sprintf('mat/%s/%s/simu_%d/nTVect-%d.mat', simuName, paramToAnalyze, simuNumber), 'nTVect'); 345 | save(sprintf('mat/%s/%s/simu_%d/totalUtilityAllocation-%d.mat', simuName, paramToAnalyze, simuNumber), 'totalUtilityAllocation'); 346 | save(sprintf('mat/%s/%s/simu_%d/totalComputationTime-%d.mat', simuName, paramToAnalyze, simuNumber), 'totalComputationTime'); 347 | save(sprintf('mat/%s/%s/simu_%d/SimuParamsCell.mat', simuName, paramToAnalyze, simuNumber), 'SimuParamsCell'); 348 | 349 | [mechnAVect, meshnTVect] = meshgrid(nAVect, nTVect); 350 | 351 | figure; 352 | surf(mechnAVect, meshnTVect, totalUtilityAllocation); 353 | xlabel('nA'); 354 | ylabel('nT'); 355 | title('Total utility'); 356 | 357 | figure; 358 | surf(mechnAVect, meshnTVect, totalComputationTime); 359 | xlabel('nA'); 360 | ylabel('nT'); 361 | title('Computation time'); 362 | 363 | end 364 | 365 | function [] = analyzeTimeRatioLoiteringTasks() 366 | 367 | % Setting of the varying parameters 368 | ntLoiterVect = 0:nT; 369 | totalUtilityAllocation = zeros(length(ntLoiterVect+1), 1); 370 | totalComputationTime = zeros(length(ntLoiterVect+1), 1); 371 | 372 | for k = 1:length(ntLoiterVect)+1 373 | 374 | ntLoiter = ntLoiterVect(k); 375 | 376 | taskType(1:ntLoiter) = 1; 377 | tlT(taskType == 0) = 0; 378 | tlT(taskType == 1) = 2; 379 | Tasks.tloiter = tlT; 380 | Tasks.task_type = taskType; 381 | 382 | Agents.previous_task = zeros(nA,1); 383 | Agents.previous_winnerBids = zeros(nA,1); 384 | Agents.rin_task = zeros(nA,2); 385 | Agents.vin_task = zeros(nA,2); 386 | 387 | if isPlotAlloc 388 | plotMapAgentsTasks(); 389 | end 390 | 391 | if isCommLimit 392 | setCommunicationLimitation(); 393 | end 394 | 395 | % GCAA solution 396 | tic; 397 | [S_GCAA, pGCAA, ~, ~, Agents] = GCAASolution(Agents, G, Tasks); 398 | %pGCAA 399 | totalComputationTime(k) = toc; 400 | ntLoiter 401 | 402 | totalUtilityAllocation(k) = S_GCAA; 403 | 404 | if isPlotAlloc 405 | setPlotAllocation(pGCAA); 406 | end 407 | end 408 | 409 | mkdir(sprintf('mat/%s/%s/simu_%d', simuName, paramToAnalyze, simuNumber)); 410 | save(sprintf('mat/%s/%s/simu_%d/ntLoiterVect-%d.mat', simuName, paramToAnalyze, simuNumber), 'ntLoiterVect'); 411 | save(sprintf('mat/%s/%s/simu_%d/totalUtilityAllocation-%d.mat', simuName, paramToAnalyze, simuNumber), 'totalUtilityAllocation'); 412 | save(sprintf('mat/%s/%s/simu_%d/totalComputationTime-%d.mat', simuName, paramToAnalyze, simuNumber), 'totalComputationTime'); 413 | save(sprintf('mat/%s/%s/simu_%d/SimuParamsCell.mat', simuName, paramToAnalyze, simuNumber), 'SimuParamsCell'); 414 | 415 | figure; 416 | plot(ntLoiterVect, totalUtilityAllocation); 417 | title('Total utility'); 418 | 419 | figure; 420 | plot(ntLoiterVect, totalComputationTime); 421 | title('Computation time'); 422 | 423 | end 424 | 425 | %% Other subfunctions 426 | 427 | function [] = setCommunicationLimitation() 428 | 429 | for i = 1:nA 430 | for j = (i+1):nA 431 | G(i,j) = norm(posA(i,:) - posA(j,:)) < commDistance; 432 | G(j,i) = G(i,j); 433 | end 434 | end 435 | 436 | end 437 | 438 | function [] = setPlotAllocation(pGCAA) 439 | 440 | % Find the optimal control solution for the given allocation p_GCAA 441 | [X, ~, ~, ~] = OptimalControlSolution(posA, vA, posT, vT, radiusT, pGCAA, Agents, tfT, Tasks.tloiter, timeStep, nRounds, nA, kdrag); 442 | plotMapAllocation(X, nRounds, nA, colors, 'GCAA solution'); 443 | legend(legendUnq(gca)); 444 | drawnow; 445 | 446 | end 447 | 448 | 449 | function [] = plotMapAgentsTasks() 450 | 451 | clf; hold on; 452 | xlim([0 mapWidth]); 453 | ylim([0 mapWidth]); 454 | xlabel('x [m]'); 455 | ylabel('y [m]'); 456 | title('Task-Agent allocation'); 457 | for i = 1:nA 458 | plot(posA(i,1), posA(i,2), '*', 'Color', colors(i,:), 'MarkerSize', 10, 'DisplayName', 'Agents'); 459 | end 460 | plot(posT(:,1), posT(:,2),'rs', 'MarkerSize', 10, 'DisplayName', 'Targets', 'MarkerFaceColor',[1 .6 .6]); 461 | if isPlotRange 462 | PlotAgentRange(posA, commDistance, colors, 'Comm Range'); 463 | end 464 | 465 | PlotTaskLoitering(posT, radiusT, taskType, 'r--', 'Task loitering'); 466 | 467 | end 468 | 469 | end 470 | -------------------------------------------------------------------------------- /src/plotMapAllocation.m: -------------------------------------------------------------------------------- 1 | function plotMapAllocation(X, n_rounds, na, color, name) 2 | 3 | for i = 1:na 4 | xx = reshape(X(:,i,:),[4,n_rounds+1]); 5 | plot(xx(1,:),xx(2,:), ':', 'Color', color(i,:), 'LineWidth', 2, 'DisplayName', name); 6 | end 7 | 8 | end --------------------------------------------------------------------------------