├── LICENSE ├── flowshop-test-10-student.txt ├── img ├── ACO.png ├── DP.png ├── HC.png ├── SA.png └── gantt.png ├── optimization.cpp ├── paper.pdf ├── plot.py ├── readme.md └── test.txt /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Rebabit 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 | -------------------------------------------------------------------------------- /flowshop-test-10-student.txt: -------------------------------------------------------------------------------- 1 | +++++++++++++++++++++++++++++ 2 | instance 0 3 | 11 5 4 | 0 375 1 12 2 142 3 245 4 412 5 | 0 632 1 452 2 758 3 278 4 398 6 | 0 12 1 876 2 124 3 534 4 765 7 | 0 460 1 542 2 523 3 120 4 499 8 | 0 528 1 101 2 789 3 124 4 999 9 | 0 796 1 245 2 632 3 375 4 123 10 | 0 532 1 230 2 543 3 896 4 452 11 | 0 14 1 124 2 214 3 543 4 785 12 | 0 257 1 527 2 753 3 210 4 463 13 | 0 896 1 896 2 214 3 258 4 259 14 | 0 532 1 302 2 501 3 765 4 988 15 | +++++++++++++++++++++++++++++ 16 | instance 1 17 | 8 8 18 | 0 456 1 654 2 852 3 145 4 632 5 425 6 214 7 654 19 | 0 789 1 123 2 369 3 678 4 581 5 396 6 123 7 789 20 | 0 654 1 123 2 632 3 965 4 475 5 325 6 456 7 654 21 | 0 321 1 456 2 581 3 421 4 32 5 147 6 789 7 123 22 | 0 456 1 789 2 472 3 365 4 536 5 852 6 654 7 123 23 | 0 789 1 654 2 586 3 824 4 325 5 12 6 321 7 456 24 | 0 654 1 321 2 320 3 758 4 863 5 452 6 456 7 789 25 | 0 789 1 147 2 120 3 639 4 21 5 863 6 789 7 654 26 | +++++++++++++++++++++++++++++ 27 | instance 2 28 | 13 4 29 | 0 654 1 147 2 345 3 447 30 | 0 321 1 520 2 789 3 702 31 | 0 12 1 147 2 630 3 255 32 | 0 345 1 586 2 214 3 866 33 | 0 678 1 532 2 275 3 332 34 | 0 963 1 145 2 302 3 225 35 | 0 25 1 24 2 142 3 589 36 | 0 874 1 517 2 24 3 996 37 | 0 114 1 896 2 520 3 541 38 | 0 785 1 543 2 336 3 234 39 | 0 203 1 210 2 699 3 784 40 | 0 696 1 784 2 855 3 512 41 | 0 302 1 512 2 221 3 345 42 | +++++++++++++++++++++++++++++ 43 | instance 3 44 | 12 5 45 | 0 456 1 537 2 123 3 214 4 234 46 | 0 789 1 854 2 225 3 528 4 123 47 | 0 876 1 632 2 588 3 896 4 456 48 | 0 543 1 145 2 669 3 325 4 789 49 | 0 210 1 785 2 966 3 147 4 876 50 | 0 123 1 214 2 332 3 856 4 543 51 | 0 456 1 752 2 144 3 321 4 210 52 | 0 789 1 143 2 755 3 427 4 123 53 | 0 876 1 698 2 322 3 546 4 456 54 | 0 543 1 532 2 100 3 321 4 789 55 | 0 210 1 145 2 114 3 401 4 876 56 | 0 124 1 247 2 753 3 214 4 543 57 | +++++++++++++++++++++++++++++ 58 | instance 4 59 | 14 4 60 | 0 456 1 856 2 963 3 696 61 | 0 789 1 930 2 21 3 320 62 | 0 630 1 214 2 475 3 142 63 | 0 214 1 257 2 320 3 753 64 | 0 573 1 896 2 124 3 214 65 | 0 218 1 532 2 752 3 528 66 | 0 653 1 142 2 147 3 653 67 | 0 214 1 547 2 532 3 214 68 | 0 204 1 865 2 145 3 527 69 | 0 785 1 321 2 763 3 536 70 | 0 696 1 124 2 214 3 214 71 | 0 532 1 12 2 257 3 528 72 | 0 12 1 345 2 854 3 888 73 | 0 457 1 678 2 123 3 999 74 | +++++++++++++++++++++++++++++ 75 | instance 5 76 | 10 6 77 | 0 333 1 991 2 996 3 123 4 145 5 234 78 | 0 333 1 111 2 663 3 456 4 785 5 532 79 | 0 252 1 222 2 222 3 789 4 214 5 586 80 | 0 222 1 204 2 114 3 876 4 752 5 532 81 | 0 255 1 477 2 123 3 543 4 143 5 142 82 | 0 555 1 566 2 456 3 210 4 698 5 573 83 | 0 558 1 899 2 789 3 124 4 532 5 12 84 | 0 888 1 965 2 876 3 537 4 145 5 14 85 | 0 889 1 588 2 543 3 854 4 247 5 527 86 | 0 999 1 889 2 210 3 632 4 451 5 856 87 | +++++++++++++++++++++++++++++ 88 | instance 6 89 | 20 10 90 | 0 96 1 80 2 56 3 48 4 14 5 88 6 50 7 15 8 67 9 65 91 | 0 25 1 44 2 10 3 41 4 64 5 52 6 19 7 28 8 72 9 27 92 | 0 76 1 62 2 48 3 54 4 47 5 35 6 72 7 54 8 27 9 56 93 | 0 41 1 6 2 3 3 33 4 77 5 44 6 43 7 50 8 19 9 43 94 | 0 65 1 91 2 75 3 30 4 47 5 55 6 51 7 1 8 36 9 73 95 | 0 81 1 69 2 65 3 93 4 61 5 3 6 44 7 17 8 6 9 14 96 | 0 49 1 9 2 12 3 54 4 75 5 66 6 34 7 12 8 32 9 6 97 | 0 93 1 89 2 31 3 14 4 37 5 57 6 33 7 96 8 32 9 45 98 | 0 39 1 83 2 55 3 32 4 18 5 9 6 93 7 65 8 75 9 73 99 | 0 52 1 46 2 64 3 13 4 54 5 62 6 45 7 80 8 19 9 65 100 | 0 72 1 4 2 29 3 94 4 85 5 51 6 29 7 65 8 50 9 16 101 | 0 55 1 43 2 47 3 32 4 87 5 97 6 41 7 86 8 17 9 30 102 | 0 8 1 91 2 81 3 93 4 14 5 86 6 64 7 42 8 70 9 3 103 | 0 27 1 11 2 94 3 38 4 33 5 67 6 8 7 55 8 99 9 18 104 | 0 34 1 86 2 87 3 10 4 64 5 30 6 47 7 51 8 69 9 26 105 | 0 15 1 5 2 39 3 23 4 16 5 1 6 57 7 55 8 62 9 35 106 | 0 59 1 55 2 43 3 49 4 23 5 25 6 51 7 72 8 9 9 1 107 | 0 93 1 4 2 43 3 5 4 84 5 55 6 22 7 78 8 31 9 11 108 | 0 20 1 91 2 73 3 41 4 100 5 38 6 75 7 9 8 76 9 71 109 | 0 59 1 13 2 93 3 26 4 11 5 7 6 66 7 42 8 54 9 99 110 | +++++++++++++++++++++++++++++ 111 | instance 7 112 | 20 15 113 | 0 60 1 70 2 51 3 74 4 6 5 4 6 27 7 5 8 30 9 79 10 58 11 49 12 91 13 20 14 63 114 | 0 79 1 53 2 74 3 87 4 18 5 16 6 44 7 95 8 41 9 3 10 20 11 59 12 74 13 33 14 42 115 | 0 94 1 57 2 19 3 77 4 70 5 90 6 36 7 73 8 37 9 24 10 28 11 23 12 16 13 97 14 75 116 | 0 23 1 3 2 82 3 87 4 45 5 54 6 76 7 60 8 61 9 98 10 68 11 14 12 10 13 17 14 9 117 | 0 38 1 32 2 68 3 7 4 49 5 49 6 72 7 31 8 70 9 8 10 26 11 81 12 86 13 60 14 74 118 | 0 27 1 14 2 77 3 20 4 92 5 74 6 33 7 44 8 43 9 52 10 10 11 81 12 30 13 93 14 71 119 | 0 23 1 55 2 67 3 6 4 64 5 68 6 19 7 73 8 92 9 96 10 3 11 21 12 51 13 3 14 25 120 | 0 41 1 91 2 90 3 43 4 37 5 96 6 99 7 46 8 41 9 51 10 33 11 49 12 17 13 64 14 68 121 | 0 92 1 44 2 12 3 37 4 75 5 20 6 14 7 43 8 26 9 64 10 85 11 14 12 54 13 54 14 97 122 | 0 69 1 69 2 71 3 54 4 36 5 96 6 3 7 27 8 16 9 61 10 94 11 96 12 85 13 34 14 34 123 | 0 16 1 38 2 36 3 48 4 92 5 20 6 55 7 89 8 75 9 57 10 89 11 62 12 36 13 36 14 69 124 | 0 37 1 19 2 55 3 2 4 96 5 10 6 81 7 29 8 2 9 34 10 83 11 1 12 45 13 23 14 64 125 | 0 4 1 57 2 26 3 29 4 91 5 94 6 21 7 30 8 30 9 51 10 31 11 62 12 53 13 29 14 51 126 | 0 55 1 65 2 21 3 99 4 27 5 53 6 42 7 78 8 63 9 25 10 86 11 60 12 64 13 76 14 69 127 | 0 17 1 70 2 33 3 81 4 24 5 35 6 77 7 21 8 83 9 19 10 44 11 70 12 90 13 34 14 90 128 | 0 76 1 94 2 54 3 34 4 12 5 28 6 24 7 5 8 59 9 4 10 46 11 93 12 32 13 78 14 48 129 | 0 81 1 49 2 83 3 72 4 31 5 72 6 91 7 8 8 40 9 93 10 84 11 63 12 67 13 36 14 84 130 | 0 63 1 70 2 14 3 85 4 66 5 41 6 64 7 54 8 10 9 65 10 26 11 58 12 20 13 64 14 41 131 | 0 98 1 39 2 91 3 5 4 55 5 28 6 43 7 97 8 35 9 23 10 50 11 99 12 59 13 63 14 95 132 | 0 47 1 48 2 89 3 33 4 99 5 10 6 54 7 94 8 52 9 44 10 73 11 67 12 44 13 36 14 98 133 | +++++++++++++++++++++++++++++ 134 | instance 8 135 | 20 5 136 | 0 34 1 6 2 63 3 85 4 60 137 | 0 11 1 65 2 4 3 1 4 73 138 | 0 63 1 67 2 3 3 73 4 100 139 | 0 22 1 46 2 88 3 1 4 66 140 | 0 76 1 4 2 34 3 9 4 76 141 | 0 20 1 22 2 7 3 3 4 28 142 | 0 44 1 30 2 55 3 68 4 92 143 | 0 29 1 89 2 12 3 96 4 71 144 | 0 54 1 12 2 21 3 74 4 2 145 | 0 62 1 96 2 61 3 79 4 53 146 | 0 50 1 13 2 48 3 40 4 37 147 | 0 89 1 69 2 57 3 1 4 70 148 | 0 50 1 56 2 8 3 67 4 46 149 | 0 32 1 24 2 23 3 87 4 62 150 | 0 12 1 88 2 64 3 14 4 13 151 | 0 59 1 78 2 95 3 59 4 48 152 | 0 41 1 20 2 83 3 65 4 20 153 | 0 94 1 48 2 26 3 93 4 3 154 | 0 28 1 59 2 10 3 81 4 20 155 | 0 66 1 33 2 34 3 8 4 5 156 | +++++++++++++++++++++++++++++ 157 | instance 9 158 | 20 15 159 | 0 59 1 11 2 4 3 79 4 94 5 31 6 74 7 82 8 53 9 51 10 19 11 31 12 46 13 47 14 10 160 | 0 72 1 54 2 36 3 3 4 59 5 23 6 40 7 59 8 89 9 37 10 85 11 67 12 39 13 65 14 60 161 | 0 92 1 26 2 15 3 81 4 86 5 56 6 92 7 47 8 93 9 21 10 40 11 77 12 84 13 10 14 91 162 | 0 49 1 27 2 99 3 64 4 30 5 51 6 26 7 89 8 40 9 64 10 60 11 67 12 67 13 100 14 3 163 | 0 42 1 12 2 55 3 62 4 37 5 24 6 24 7 42 8 41 9 88 10 14 11 33 12 85 13 4 14 20 164 | 0 21 1 61 2 52 3 49 4 44 5 98 6 26 7 68 8 61 9 25 10 6 11 46 12 75 13 37 14 5 165 | 0 80 1 99 2 88 3 83 4 11 5 93 6 47 7 80 8 100 9 87 10 84 11 17 12 43 13 93 14 58 166 | 0 4 1 54 2 43 3 63 4 44 5 78 6 44 7 39 8 76 9 99 10 29 11 38 12 14 13 75 14 25 167 | 0 46 1 23 2 54 3 77 4 60 5 53 6 42 7 72 8 90 9 11 10 22 11 68 12 94 13 24 14 14 168 | 0 23 1 84 2 92 3 94 4 8 5 10 6 77 7 58 8 64 9 95 10 55 11 15 12 19 13 62 14 67 169 | 0 53 1 91 2 80 3 8 4 41 5 89 6 3 7 87 8 57 9 75 10 37 11 8 12 23 13 88 14 65 170 | 0 72 1 17 2 53 3 36 4 9 5 24 6 80 7 9 8 28 9 60 10 94 11 99 12 67 13 10 14 44 171 | 0 5 1 44 2 96 3 37 4 21 5 44 6 49 7 13 8 86 9 74 10 89 11 3 12 82 13 85 14 61 172 | 0 80 1 19 2 73 3 95 4 78 5 78 6 31 7 13 8 50 9 93 10 98 11 80 12 46 13 9 14 37 173 | 0 7 1 16 2 46 3 82 4 97 5 82 6 41 7 21 8 11 9 50 10 5 11 28 12 95 13 84 14 45 174 | 0 68 1 73 2 57 3 4 4 66 5 71 6 87 7 43 8 60 9 56 10 30 11 21 12 14 13 37 14 61 175 | 0 77 1 2 2 1 3 82 4 2 5 49 6 89 7 27 8 34 9 52 10 85 11 26 12 80 13 87 14 58 176 | 0 17 1 86 2 32 3 35 4 6 5 50 6 53 7 39 8 94 9 89 10 22 11 75 12 59 13 74 14 27 177 | 0 61 1 14 2 70 3 58 4 24 5 36 6 70 7 57 8 31 9 100 10 21 11 76 12 54 13 94 14 57 178 | 0 29 1 6 2 6 3 12 4 78 5 28 6 40 7 13 8 61 9 19 10 39 11 98 12 69 13 14 14 3 179 | +++++++++++++++++++++++++++++ 180 | instance 10 181 | 50 10 182 | 0 100 1 72 2 76 3 100 4 16 5 9 6 5 7 87 8 34 9 15 183 | 0 19 1 3 2 19 3 68 4 29 5 22 6 16 7 13 8 87 9 70 184 | 0 70 1 56 2 39 3 71 4 29 5 91 6 100 7 86 8 88 9 99 185 | 0 50 1 93 2 100 3 71 4 84 5 64 6 67 7 29 8 28 9 81 186 | 0 80 1 97 2 3 3 10 4 14 5 32 6 92 7 67 8 72 9 68 187 | 0 47 1 59 2 29 3 3 4 26 5 20 6 50 7 26 8 1 9 70 188 | 0 40 1 63 2 69 3 21 4 56 5 73 6 56 7 10 8 46 9 40 189 | 0 84 1 80 2 68 3 82 4 4 5 45 6 100 7 96 8 29 9 67 190 | 0 85 1 46 2 59 3 35 4 68 5 84 6 89 7 18 8 97 9 58 191 | 0 60 1 60 2 2 3 50 4 90 5 20 6 78 7 56 8 62 9 27 192 | 0 78 1 64 2 21 3 5 4 85 5 55 6 15 7 23 8 36 9 87 193 | 0 98 1 31 2 42 3 73 4 83 5 48 6 71 7 49 8 72 9 30 194 | 0 4 1 57 2 30 3 11 4 67 5 4 6 82 7 77 8 98 9 21 195 | 0 45 1 45 2 25 3 45 4 7 5 59 6 88 7 42 8 57 9 81 196 | 0 73 1 94 2 83 3 59 4 1 5 72 6 65 7 62 8 45 9 76 197 | 0 77 1 84 2 11 3 82 4 10 5 9 6 67 7 27 8 43 9 8 198 | 0 22 1 66 2 5 3 77 4 97 5 28 6 61 7 82 8 62 9 96 199 | 0 90 1 51 2 87 3 27 4 65 5 76 6 67 7 20 8 75 9 67 200 | 0 12 1 92 2 43 3 21 4 92 5 64 6 94 7 67 8 60 9 46 201 | 0 9 1 76 2 62 3 46 4 71 5 65 6 76 7 65 8 30 9 38 202 | 0 29 1 12 2 71 3 70 4 46 5 96 6 12 7 70 8 76 9 19 203 | 0 83 1 15 2 73 3 32 4 51 5 6 6 3 7 29 8 3 9 24 204 | 0 83 1 95 2 87 3 29 4 46 5 67 6 89 7 73 8 69 9 33 205 | 0 83 1 46 2 82 3 2 4 55 5 54 6 85 7 3 8 20 9 57 206 | 0 11 1 32 2 15 3 27 4 2 5 43 6 23 7 79 8 28 9 29 207 | 0 10 1 74 2 73 3 99 4 54 5 89 6 83 7 5 8 28 9 90 208 | 0 73 1 40 2 4 3 20 4 51 5 18 6 37 7 18 8 61 9 75 209 | 0 85 1 30 2 58 3 89 4 48 5 15 6 82 7 77 8 2 9 3 210 | 0 56 1 63 2 26 3 87 4 53 5 8 6 80 7 46 8 5 9 62 211 | 0 59 1 67 2 73 3 65 4 60 5 61 6 94 7 86 8 38 9 1 212 | 0 70 1 66 2 80 3 32 4 93 5 56 6 26 7 41 8 21 9 9 213 | 0 4 1 66 2 79 3 43 4 39 5 83 6 55 7 25 8 62 9 13 214 | 0 51 1 42 2 90 3 85 4 84 5 29 6 73 7 8 8 95 9 57 215 | 0 18 1 30 2 61 3 67 4 57 5 60 6 25 7 10 8 20 9 95 216 | 0 61 1 9 2 3 3 2 4 61 5 18 6 44 7 78 8 38 9 74 217 | 0 25 1 91 2 31 3 2 4 14 5 97 6 91 7 84 8 88 9 26 218 | 0 84 1 8 2 95 3 61 4 85 5 41 6 88 7 4 8 86 9 51 219 | 0 74 1 2 2 24 3 42 4 33 5 24 6 62 7 13 8 62 9 10 220 | 0 33 1 7 2 62 3 68 4 42 5 41 6 78 7 67 8 99 9 6 221 | 0 38 1 43 2 2 3 4 4 62 5 95 6 76 7 91 8 67 9 78 222 | 0 43 1 98 2 28 3 51 4 43 5 84 6 13 7 71 8 64 9 81 223 | 0 15 1 19 2 50 3 30 4 75 5 90 6 94 7 35 8 51 9 83 224 | 0 75 1 98 2 42 3 67 4 24 5 63 6 15 7 45 8 92 9 44 225 | 0 29 1 60 2 80 3 86 4 70 5 13 6 100 7 86 8 88 9 6 226 | 0 14 1 49 2 78 3 93 4 45 5 94 6 35 7 46 8 18 9 85 227 | 0 29 1 20 2 27 3 66 4 70 5 95 6 7 7 11 8 75 9 52 228 | 0 73 1 19 2 33 3 36 4 93 5 21 6 44 7 51 8 4 9 24 229 | 0 87 1 79 2 52 3 85 4 24 5 89 6 50 7 4 8 37 9 50 230 | 0 86 1 99 2 31 3 25 4 78 5 10 6 41 7 66 8 35 9 1 231 | 0 2 1 41 2 41 3 88 4 6 5 77 6 89 7 80 8 21 9 54 232 | +++++++++++++++++++++++++++++ 233 | -------------------------------------------------------------------------------- /img/ACO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rebabit/Permutation-Flow-Shop-Scheduling-Problem-by-Heuristic-and-Metaheuristic-Algorithm/dcc577274e8bbf797a9eefba8d176958d3efe445/img/ACO.png -------------------------------------------------------------------------------- /img/DP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rebabit/Permutation-Flow-Shop-Scheduling-Problem-by-Heuristic-and-Metaheuristic-Algorithm/dcc577274e8bbf797a9eefba8d176958d3efe445/img/DP.png -------------------------------------------------------------------------------- /img/HC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rebabit/Permutation-Flow-Shop-Scheduling-Problem-by-Heuristic-and-Metaheuristic-Algorithm/dcc577274e8bbf797a9eefba8d176958d3efe445/img/HC.png -------------------------------------------------------------------------------- /img/SA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rebabit/Permutation-Flow-Shop-Scheduling-Problem-by-Heuristic-and-Metaheuristic-Algorithm/dcc577274e8bbf797a9eefba8d176958d3efe445/img/SA.png -------------------------------------------------------------------------------- /img/gantt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rebabit/Permutation-Flow-Shop-Scheduling-Problem-by-Heuristic-and-Metaheuristic-Algorithm/dcc577274e8bbf797a9eefba8d176958d3efe445/img/gantt.png -------------------------------------------------------------------------------- /optimization.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int max_workpiece = 60; 4 | const int max_machine = 20; 5 | const int inf = 0x3f3f3f3f; 6 | const int num_test_cases = 10; 7 | 8 | struct workpiece 9 | { 10 | // 基本信息存储 11 | int num_workpiece; //工件总数 12 | int num_machine; //机器总数 13 | // 解(加工顺序)的存储 14 | int order_temp[max_workpiece]; //邻域中新生成的解,可能接受也可能拒绝 15 | int order_temp_current[max_workpiece]; //遍历邻域时存储的当前解,防止解的更新破坏了当前解 16 | int order_current[max_workpiece]; //当前解 17 | int order_best[max_workpiece]; //全局最优解(用于输出) 18 | // 加工时间的存储 19 | int time_work[max_workpiece][max_machine]; //每个工件在每台机器上的加工时间 20 | int time_finish_current[max_workpiece][max_machine]; //当前方案下加工的结束时间 21 | int time_finish_best[max_workpiece][max_machine]; //最优方案下加工的结束时间(用于输出) 22 | int total_time_current; //当前的加工总时间 23 | int total_time_best; //最短的加工总时间(用于输出) 24 | // 蚁群算法参数的存储 25 | double pheromone[max_workpiece][max_workpiece]; //信息素量 26 | double eta[max_workpiece][max_workpiece]; //能见度eta 27 | // NEH算法参数的存储(辅助蚁群算法) 28 | int T[2][max_workpiece]; //每个工件在所有机器上的总加工时间,第一维存放时间,第二维存放对应的工件号(用于排序) 29 | int makespan; // NEH最优的加工总时间,用于蚁群算法中信息素的初始化 30 | int total_time_part[max_workpiece]; //前i工件最优的加工总时间,用于NEH中工件的插入 31 | }; 32 | 33 | workpiece w[11]; //模拟退火算法结果存储 34 | workpiece hc[11]; //爬山算法结果存储 35 | workpiece aco[11]; //蚁群算法结果存储 36 | workpiece neh[11]; // NEH算法结果存储 37 | 38 | // 读入文件,并进行初始化 39 | void input() 40 | { 41 | //为了在运行时生成随机数,设置种子 42 | unsigned seed = time(0); 43 | srand(seed); 44 | ifstream fin; 45 | fin.open("data/flowshop-test-10-student.txt", ios::in); 46 | char tmp[100]; 47 | for (int i = 0; i <= 10; i++) 48 | { 49 | fin.getline(tmp, sizeof(tmp)); 50 | fin.getline(tmp, sizeof(tmp)); 51 | fin >> w[i].num_workpiece >> w[i].num_machine; 52 | for (int j = 0; j < w[i].num_workpiece; j++) 53 | { 54 | w[i].order_current[j] = j; 55 | w[i].order_temp[j] = j; 56 | for (int k = 0; k < w[i].num_machine; k++) 57 | { 58 | w[i].time_finish_current[j][k] = 0; 59 | fin >> tmp >> w[i].time_work[j][k]; 60 | } 61 | } 62 | //随机初始化工件加工顺序 63 | random_shuffle(w[i].order_current, w[i].order_current + w[i].num_workpiece - 1); 64 | w[i].total_time_current = inf; 65 | w[i].total_time_best = inf; 66 | aco[i] = hc[i] = w[i]; 67 | //初始化蚁群算法特有参数 68 | for (int j = 0; j < aco[i].num_workpiece; j++) 69 | { 70 | aco[i].T[0][j] = 0; 71 | aco[i].T[1][j] = j; 72 | aco[i].total_time_part[j] = inf; 73 | for (int k = 0; k < aco[i].num_workpiece; k++) 74 | { 75 | aco[i].pheromone[j][k] = 1; 76 | aco[i].eta[j][k] = inf; 77 | } 78 | } 79 | aco[i].makespan = inf; 80 | neh[i] = aco[i]; 81 | fin.getline(tmp, sizeof(tmp)); 82 | } 83 | } 84 | 85 | // 通用模块 86 | 87 | // 计算当前加工顺序下工件的加工时间 88 | int calculate_time(workpiece w[11], int i, int num_workpiece) 89 | { 90 | int cur = w[i].order_temp[0]; //当前被加工的工件 91 | w[i].time_finish_current[0][0] = w[i].time_work[cur][0]; 92 | for (int k = 1; k < w[i].num_machine; k++) 93 | w[i].time_finish_current[0][k] = w[i].time_finish_current[0][k - 1] + w[i].time_work[cur][k]; 94 | for (int j = 1; j < num_workpiece; j++) 95 | { 96 | int cur = w[i].order_temp[j]; 97 | w[i].time_finish_current[j][0] = w[i].time_finish_current[j - 1][0] + w[i].time_work[cur][0]; 98 | // 当前工件可以被加工:1.上一个在此机器加工的工件已经完成加工 2.该工件前一道工序已经完成 99 | for (int k = 1; k < w[i].num_machine; k++) 100 | { 101 | w[i].time_finish_current[j][k] = max(w[i].time_finish_current[j - 1][k], w[i].time_finish_current[j][k - 1]) + w[i].time_work[cur][k]; 102 | } 103 | } 104 | return w[i].time_finish_current[num_workpiece - 1][w[i].num_machine - 1]; 105 | } 106 | // 更新当前方案 107 | void update(workpiece w[11], int i, int time_temp) 108 | { 109 | w[i].total_time_current = time_temp; 110 | for (int j = 0; j < w[i].num_workpiece; j++) 111 | { 112 | w[i].order_current[j] = w[i].order_temp[j]; 113 | } 114 | } 115 | // 记录最好的方案,用于后续对结果的输出(如果time_temp优于当前最优解则记录) 116 | void record_if_best(workpiece w[11], int i, int time_temp) 117 | { 118 | if (time_temp < w[i].total_time_best) 119 | { 120 | w[i].total_time_best = time_temp; 121 | for (int j = 0; j < w[i].num_workpiece; j++) 122 | { 123 | w[i].order_best[j] = w[i].order_temp[j]; 124 | } 125 | for (int j = 0; j < w[i].num_workpiece; j++) 126 | { 127 | for (int k = 0; k < w[i].num_machine; k++) 128 | { 129 | w[i].time_finish_best[j][k] = w[i].time_finish_current[j][k]; 130 | } 131 | } 132 | } 133 | } 134 | // 将最短时间及调度分配输出至文件,用于结果的保存和可视化 135 | void output_to_file(workpiece w[11]) 136 | { 137 | ofstream ofs; // 输出实现各个用例加工方案、每个工件在每台机器上的结束时间 138 | ofstream ofst; // 输出各个用例的最短完工时间 139 | ofs.open("data/result.txt", ios::out); 140 | ofst.open("data/minimum_time.txt", ios::out); 141 | for (int i = 0; i <= num_test_cases; i++) 142 | { 143 | ofs << i << endl; 144 | for (int j = 0; j < w[i].num_workpiece; j++) 145 | { 146 | ofs << w[i].order_best[j] << " "; 147 | for (int k = 0; k < w[i].num_machine; k++) 148 | { 149 | ofs << w[i].time_finish_best[j][k] << " "; 150 | } 151 | ofs << endl; 152 | } 153 | } 154 | for (int i = 0; i < 11; i++) 155 | { 156 | ofst << w[i].total_time_best << endl; 157 | } 158 | ofs.close(); 159 | ofst.close(); 160 | } 161 | 162 | // 优化模块 163 | 164 | // 模拟退火算法 165 | // 新解的生成——随机交换两个工件的加工顺序 166 | void switch_order(workpiece w[11], int i) 167 | { 168 | for (int j = 0; j < w[i].num_workpiece; j++) 169 | { 170 | w[i].order_temp[j] = w[i].order_current[j]; 171 | } 172 | int x1 = rand() % w[i].num_workpiece; 173 | int x2 = 0; 174 | while (x1 == x2) 175 | { 176 | x2 = rand() % w[i].num_workpiece; 177 | } 178 | int temp = w[i].order_temp[x1]; 179 | w[i].order_temp[x1] = w[i].order_temp[x2]; 180 | w[i].order_temp[x2] = temp; 181 | } 182 | void SA() 183 | { 184 | // 参数配置——初始温度 185 | double T[11] = {1000, 5000, 10000, 20000, 10000, 10000, 150000, 150000, 10000, 150000, 10000}; 186 | // 参数配置——温度下限 187 | double eps[11] = {1e-7, 1e-7, 1e-7, 1e-7, 1e-7, 1e-7, 1e-7, 1e-6, 1e-7, 1e-7, 1e-7}; 188 | // 参数配置——降温系数 189 | double dT[11] = {0.99, 0.95, 0.97, 0.99, 0.99, 0.99, 0.99, 0.998, 0.99, 0.997, 0.99}; 190 | // 参数配置——同一温度下的迭代次数 191 | int t[11] = {100, 1000, 1000, 3000, 1000, 1000, 3000, 3000, 1000, 3000, 1000}; 192 | cout << "===============Solution by Simulated Annealing===============" << endl; 193 | for (int i = 0; i <= num_test_cases; i++) 194 | { 195 | clock_t start, end; // 设计时钟,记录运行时间 196 | start = clock(); 197 | while (T[i] > eps[i]) 198 | { 199 | for (int k = 0; k < t[i]; k++) 200 | { 201 | // 生成新的方案,并计算时间 202 | switch_order(w, i); 203 | int time_temp = calculate_time(w, i, w[i].num_workpiece); 204 | record_if_best(w, i, time_temp); 205 | //接受当前方案:1.比最小值小 2.以一定概率接受更差的状态 并记录此时的最小值和方案内容 206 | if (time_temp < w[i].total_time_current || exp((-time_temp + w[i].total_time_current) / T[i]) * RAND_MAX > rand()) 207 | { 208 | update(w, i, time_temp); 209 | } 210 | } 211 | T[i] *= dT[i]; //降温 212 | } 213 | end = clock(); 214 | cout << "Minimum time of workpiece " << i << ": " << w[i].total_time_best << " Run time: " << double(end - start) / CLOCKS_PER_SEC << "s" << endl; 215 | } 216 | } 217 | 218 | // 爬山算法 219 | // 辅助爬山算法邻域的遍历——交换指定两个工件的加工顺序 220 | void switch_order_HC(workpiece w[11], int i, int m, int n) 221 | { 222 | for (int j = 0; j < w[i].num_workpiece; j++) 223 | { 224 | w[i].order_temp[j] = w[i].order_temp_current[j]; 225 | } 226 | w[i].order_temp[m] = w[i].order_temp_current[n]; 227 | w[i].order_temp[n] = w[i].order_temp_current[m]; 228 | } 229 | // 邻域的遍历 230 | bool traverse_neighborhood(workpiece hc[11], int i) 231 | { 232 | // 存储当前解,用于对邻域的遍历 233 | for (int j = 0; j < hc[i].num_workpiece; j++) 234 | { 235 | hc[i].order_temp_current[j] = hc[i].order_current[j]; 236 | } 237 | // 遍历登山算法所有邻域 238 | bool Update = false; // 记录是否对当前解进行更新 239 | for (int m = 0; m < hc[i].num_machine - 1; m++) 240 | { 241 | for (int n = m + 1; n < hc[i].num_machine; n++) 242 | { 243 | switch_order_HC(hc, i, m, n); // 交换当前解中m、n的顺序 244 | int time_temp = calculate_time(hc, i, hc[i].num_workpiece); 245 | if (time_temp < hc[i].total_time_current) // 如果交换后时间变短,则记录 246 | { 247 | // 虽然此处更新的是当前解order_current,但遍历时是根据order_temp_current交换解的顺序的,因此循环结束后,current内部存储的即为邻域的最优解 248 | update(hc, i, time_temp); 249 | Update = true; 250 | } 251 | } 252 | } 253 | return Update; 254 | } 255 | void HC() 256 | { 257 | cout << "===============Solution by Hill Climbing===============" << endl; 258 | for (int i = 0; i <= num_test_cases; i++) 259 | { 260 | clock_t start, end; 261 | start = clock(); 262 | for (int rep = 0; rep < 50000; rep++) 263 | { 264 | random_shuffle(hc[i].order_current, hc[i].order_current + hc[i].num_workpiece - 1); 265 | for (int k = 0; k < 1000; k++) 266 | { 267 | bool Update = traverse_neighborhood(hc, i); 268 | // 如果没有对当前解进行更新,则已登至山顶,跳出循环 269 | if (!Update) 270 | { 271 | break; 272 | } 273 | } 274 | record_if_best(hc, i, hc[i].total_time_current); 275 | } 276 | end = clock(); 277 | cout << "Minimum time of workpiece " << i << ": " << hc[i].total_time_best << " Run time: " << double(end - start) / CLOCKS_PER_SEC << "s" << endl; 278 | } 279 | } 280 | 281 | // NEH算法(本实验中,用于与蚁群算法结合,辅助蚁群算法) 282 | // 计算每个工件在所有机器上的总加工时间,用于算法步骤1 283 | void calculate_time_workpiece(workpiece aco[11]) 284 | { 285 | for (int i = 0; i <= num_test_cases; i++) 286 | { 287 | for (int j = 0; j < aco[i].num_workpiece; j++) 288 | { 289 | for (int k = 0; k < aco[i].num_machine; k++) 290 | { 291 | aco[i].T[0][j] += aco[i].time_work[j][k]; 292 | } 293 | } 294 | } 295 | } 296 | // 对每个工件在所有机器的总加工时间进行冒泡排序,用于算法步骤1 297 | void bubble_sort(workpiece aco[11]) 298 | { 299 | for (int i = 0; i <= num_test_cases; i++) 300 | { 301 | for (int j = 0; j < aco[i].num_workpiece - 1; j++) 302 | { 303 | for (int k = 0; k < aco[i].num_workpiece - 1 - j; k++) 304 | { 305 | if (aco[i].T[0][k] < aco[i].T[0][k + 1]) 306 | { 307 | swap(aco[i].T[0][k], aco[i].T[0][k + 1]); 308 | swap(aco[i].T[1][k], aco[i].T[1][k + 1]); 309 | } 310 | } 311 | } 312 | } 313 | } 314 | // 将工件插入指定位置,用于算法步骤3 315 | void insert_order(workpiece aco[11], int i, int cur_workpiece, int place, int insert_workpiece_num) 316 | { 317 | for (int j = cur_workpiece - 1; j >= place; j--) 318 | { 319 | aco[i].order_temp[j + 1] = aco[i].order_temp_current[j]; 320 | } 321 | aco[i].order_temp[place] = insert_workpiece_num; 322 | for (int j = 0; j < place; j++) 323 | { 324 | aco[i].order_temp[j] = aco[i].order_temp_current[j]; 325 | } 326 | } 327 | // 记录0~cur_workpiece的部分最短完工时间,用于算法步骤3 328 | void record_if_best_part(workpiece w[11], int i, int time_temp, int cur_workpiece) // cur_workpiece:当前要插入的工件的下标 329 | { 330 | if (time_temp < w[i].total_time_part[cur_workpiece]) // 如果更优,保存当前的完工时间、调度顺序等信息 331 | { 332 | w[i].total_time_part[cur_workpiece] = time_temp; 333 | for (int j = 0; j <= cur_workpiece; j++) 334 | { 335 | w[i].order_best[j] = w[i].order_temp[j]; 336 | } 337 | } 338 | } 339 | // NEH算法主体 340 | void NEH() 341 | { 342 | cout << "===============Solution by NEH===============" << endl; 343 | // NEH步骤1:计算每个工件的总加工时间,并按照非增顺序排列 344 | calculate_time_workpiece(neh); 345 | bubble_sort(neh); 346 | for (int i = 0; i <= num_test_cases; i++) 347 | { 348 | clock_t start, end; 349 | start = clock(); 350 | // NEH步骤2:取出步骤1排列好的前两个工件,选取时间较短的作为当前调度 351 | neh[i].order_temp[0] = neh[i].T[1][0]; 352 | neh[i].order_temp[1] = neh[i].T[1][1]; 353 | int time1 = calculate_time(neh, i, 2); 354 | swap(neh[i].order_temp[0], neh[i].order_temp[1]); 355 | int time2 = calculate_time(neh, i, 2); 356 | if (time1 < time2) 357 | { 358 | swap(neh[i].order_temp[0], neh[i].order_temp[1]); 359 | } 360 | // NEH步骤3:从第3个工件开始依次取出步骤1排列的好的工件,插入所有可能位置,将时间最短的排列作为当前调度 361 | for (int j = 2; j < neh[i].num_workpiece; j++) 362 | { 363 | int insert_num = neh[i].T[1][j]; 364 | // 记录插入前的解 365 | for (int k = 0; k < j; k++) 366 | { 367 | neh[i].order_temp_current[k] = neh[i].order_temp[k]; 368 | } 369 | // 进行所有可能的插入,记录时间最短的部分排列 370 | for (int k = 0; k <= j; k++) 371 | { 372 | insert_order(neh, i, j, k, insert_num); 373 | int time_temp = calculate_time(neh, i, j+1); 374 | record_if_best_part(neh, i, time_temp, j); 375 | } 376 | // 选取时间最短的部分排列作为新解,进行更新 377 | for (int k = 0; k <= j; k++) 378 | { 379 | neh[i].order_temp[k] = neh[i].order_best[k]; 380 | } 381 | } 382 | // 得到工件的启发式最短调度时间makespan,可用于蚁群算法信息素的初始化 383 | aco[i].makespan = neh[i].total_time_part[neh[i].num_workpiece - 1]; 384 | end = clock(); 385 | cout << "Minimum time of workpiece " << i << ": " << aco[i].makespan << " Run time: " << double(end - start) / CLOCKS_PER_SEC << "s" << endl; 386 | } 387 | } 388 | 389 | // 蚁群算法 390 | // 与NEH的结合:插入型局部寻优的思想 391 | bool insert_neighborhood(workpiece hc[11], int i) 392 | { 393 | // 存储当前解,用于对邻域的遍历 394 | for (int j = 0; j < hc[i].num_workpiece; j++) 395 | { 396 | hc[i].order_temp_current[j] = hc[i].order_current[j]; 397 | } 398 | bool Update = false; // 记录是否对当前解进行更新 399 | // 将第i(i=0~n-2)位置的工件依次插入第i+1~n-1位置,找到插入邻域中的最优解 400 | for (int m = 0; m < hc[i].num_machine - 1; m++) 401 | { 402 | for (int n = m + 1; n < hc[i].num_machine; n++) 403 | { 404 | for (int k = 0; k < hc[i].num_workpiece; k++) 405 | { 406 | // 将m位置的工件插入n 407 | if (k >= m && k < n) 408 | hc[i].order_temp[k] = hc[i].order_temp_current[k + 1]; // m~n间的工件左移 409 | else if (k == n) 410 | hc[i].order_temp[k] = hc[i].order_temp_current[m]; // n处插入m 411 | else 412 | hc[i].order_temp[k] = hc[i].order_temp_current[k]; // 其余工件不变 413 | } 414 | int time_temp = calculate_time(hc, i, hc[i].num_workpiece); 415 | if (time_temp < hc[i].total_time_current) 416 | { 417 | update(hc, i, time_temp); 418 | Update = true; 419 | } 420 | } 421 | } 422 | return Update; 423 | } 424 | void ACO() 425 | { 426 | // 参数设置 427 | int alpha = 1; 428 | int beta = 2; // alpha、beta用于概率的计算 429 | double rho = 0.3; // rho用于信息素的更新 430 | NEH(); 431 | cout << "===============Solution by Ant Colony Optimization===============" << endl; 432 | for (int i = 0; i <= num_test_cases; i++) 433 | { 434 | clock_t start, end; 435 | start = clock(); 436 | int num_ant = aco[i].num_workpiece * 1.5; 437 | // 二维数组,存放每个蚂蚁对应的排列顺序 438 | int ant_order[int(max_workpiece * 1.5)][max_workpiece]; 439 | memset(ant_order, inf, sizeof(ant_order)); 440 | // 信息素、能见度初始化 441 | for (int j = 0; j < aco[i].num_workpiece; j++) 442 | { 443 | for (int k = 0; k < aco[i].num_workpiece; k++) 444 | { 445 | aco[i].pheromone[j][k] = 1.0 / (aco[i].num_workpiece * aco[i].makespan); 446 | aco[i].eta[j][k] = neh[i].T[0][j]; 447 | } 448 | } 449 | int Ncmax[11] = {200,500,5000,5000,3000,5000,5000,5000,5000,5000,5000}; 450 | for (int rep = 0; rep < Ncmax[i]; rep++) 451 | { 452 | // 每个蚂蚁分别构造解 453 | for (int m = 0; m < num_ant; m++) 454 | { 455 | bool taboo[max_workpiece]; //记录已经被选择的城市 456 | memset(taboo, false, sizeof(taboo)); 457 | double probability[max_workpiece]; // 记录被选择的概率 458 | // 进行每个工件的选择,共需要选择n(工件总数)次,每次可以选择的个数不超过n个 459 | for (int n = 0; n < aco[i].num_workpiece; n++) 460 | { 461 | for (int k = 0; k < aco[i].num_workpiece; k++) 462 | { 463 | // 不能选择已经被选择过的工件 464 | if (taboo[k] == true) 465 | probability[k] = 0; 466 | // 按照概率计算公式,计算选择当前工件的可能性 467 | else 468 | probability[k] = pow(aco[i].pheromone[n][k], alpha) * pow(aco[i].eta[n][k], beta); 469 | } 470 | // 对概率进行归一化,得到0~1之间的概率 471 | int Sum = accumulate(probability, probability + aco[i].num_workpiece, 0); 472 | for (int k = 0; k < aco[i].num_workpiece; k++) 473 | { 474 | probability[k] /= (Sum * 1.0); 475 | } 476 | // 随机生成一个0~1之间的概率 477 | double pro = rand() * 1.0 / RAND_MAX; 478 | // 当前工件累计概率,用于工件的选取 479 | double acc = 0; 480 | int next; 481 | for (int k = 0; k < aco[i].num_workpiece; k++) 482 | { 483 | if (!taboo[k]) 484 | { 485 | acc += probability[k]; 486 | if (acc >= pro) 487 | { 488 | next = k; 489 | break; 490 | } 491 | } 492 | } 493 | // 更新已经选过的工件、更新蚂蚁选择的解 494 | taboo[next] = true; 495 | ant_order[m][n] = next; 496 | } 497 | } 498 | for (int m = 0; m < num_ant; m++) 499 | { 500 | // 对插入式寻优所需要的参数进行初始化 501 | for (int k = 0; k < aco[i].num_workpiece; k++) 502 | { 503 | aco[i].order_current[k] = aco[i].order_temp[k] = ant_order[m][k]; 504 | } 505 | int time_temp = aco[i].total_time_current = calculate_time(aco, i, aco[i].num_workpiece); 506 | // 进行插入式寻优,寻找插入邻域中的更优解,如果有更优的解,则进行更新 507 | if (insert_neighborhood(aco, i)) 508 | { 509 | time_temp = aco[i].total_time_current; 510 | for (int k = 0; k < aco[i].num_workpiece; k++) 511 | { 512 | ant_order[m][k] = aco[i].order_current[k]; 513 | } 514 | } 515 | record_if_best(aco, i, time_temp); 516 | // 对信息素进行更新 517 | double delta_tau = 1.0 / time_temp; 518 | for (int n = 0; n < aco[i].num_workpiece; n++) 519 | { 520 | int next = ant_order[m][n]; 521 | aco[i].pheromone[n][next] = (1 - rho) * aco[i].pheromone[n][next] + delta_tau; 522 | } 523 | } 524 | } 525 | end = clock(); 526 | cout << "Minimum time of workpiece " << i << ": " << aco[i].total_time_best << " Run time: " << double(end - start) / CLOCKS_PER_SEC << "s" << endl; 527 | } 528 | } 529 | 530 | int main() 531 | { 532 | input(); 533 | HC(); 534 | SA(); 535 | ACO(); 536 | return 0; 537 | } -------------------------------------------------------------------------------- /paper.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rebabit/Permutation-Flow-Shop-Scheduling-Problem-by-Heuristic-and-Metaheuristic-Algorithm/dcc577274e8bbf797a9eefba8d176958d3efe445/paper.pdf -------------------------------------------------------------------------------- /plot.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import numpy as np 3 | import matplotlib.patches as mpatches 4 | from colour import Color 5 | # 输入:finish_time,每个工件加工的结束时间,格式与程序输出的每个用例格式。每行第一个为加工的工件序号,其余依次为在每道工序上加工的结束时间。 6 | finish_time = np.genfromtxt("result2.txt", dtype=int) 7 | # 输入:time,工件加工时间,格式与每个用例相同。 8 | time = np.genfromtxt("time2.txt", dtype=int) 9 | # 局部变量:continue_time,处理后的工件加工时间,continue_time[i][j]为第i+1个工件在第j+1台机器上的加工时间。 10 | continue_time = [] 11 | # 局部变量:start_time,工件加工的开始时间,start_time[i][j]为第i+1个工件在第j+1台机器上开始加工的时间。 12 | start_time = [] 13 | # 局部变量:label,工件的加工顺序,label[i]为第i+1个加工的工件 14 | label = [] 15 | # 对输入进行处理,得到上述局部变量。 16 | for i in range(time.shape[0]): 17 | continue_time.append([]) 18 | for j in range(time.shape[1]): 19 | if j % 2 == 1: 20 | continue_time[i].append(time[i][j]) 21 | for i in range(finish_time.shape[0]): 22 | label.append(finish_time[i][0]) 23 | for i in range(finish_time.shape[0]): 24 | start_time.append([]) 25 | for j in range(finish_time.shape[1]): 26 | if j != 0: 27 | start_time[i].append(finish_time[i][j] - continue_time[label[i]][j - 1]) 28 | # 画图时正确显示中文 29 | plt.rcParams['font.sans-serif'] = ['SimHei'] 30 | # 设置甘特图的颜色 31 | red = Color("red") 32 | colors = list(red.range_to(Color("purple"), len(start_time))) 33 | colors = [color.rgb for color in colors] 34 | # 利用barh画出水平柱状图 35 | m = range(finish_time.shape[0]) 36 | n = range(finish_time.shape[1] - 1) 37 | for i in m: 38 | for j in n: 39 | plt.barh(y=n[j] + 1, width=continue_time[label[i]][j], left=start_time[i][j], color=colors[i]) 40 | # 设置图例文字 41 | labels = [''] * len(continue_time) 42 | for f in m: 43 | labels[f] = "工件%d" % (label[f] + 1) 44 | # 添加图例 45 | patches = [mpatches.Patch(color=colors[i], label="{:s}".format(labels[i])) for i in range(len(continue_time))] 46 | plt.legend(handles=patches, loc=4) 47 | # 添加XY轴标签 48 | plt.xlabel("加工时间/分钟", fontsize=15) 49 | plt.ylabel("加工机器", fontsize=15) 50 | plt.show() 51 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## **Permutation Flow Shop Scheduling Problem by Heuristic and Metaheuristic Algorithm** 2 | 3 | - `optimization.cpp`: main code 4 | - `plot.py`: main code for drawing the Gantt chart 5 | - `paper.pdf`: report for the project 6 | - `flowshop-test-10-students.txt`: given data for the problem 7 | - `test.txt`: best results for each of the case in `flowshop-test-10-students.txt` 8 | 9 | ### Project introduction 10 | 11 | - Solved the problem by Hill Climbing, Simulated Annealing (SA), NEH heuristic algorithm and Ant Clony Optimization (ACO); calculated the time cost of scheduling by Dynamic Programming. 12 | - Modified the model to achieve better performance of SA. 13 | - Improved the result of ACO based on the information of NEH heuristic algorithm. 14 | 15 | ### Methods 16 | 17 | #### Dynamic Programming 18 | 19 | DP 20 | 21 | #### Hill Climbing 22 | 23 | HC 24 | 25 | #### Simulated Annealing 26 | 27 | SA 28 | 29 | #### Ant Colony Optimization 30 | 31 | ACO 32 | 33 | ### Results 34 | 35 | #### Parameters 36 | 37 | | 序号 | 内循环次数 | 初始温度 | 降温系数 | 温度下限 | 运行时间(s) | 38 | | ---- | ---------- | -------- | -------- | -------- | ------------- | 39 | | 0 | 1000 | 10000 | 0.99 | 1E-07 | 1.523 | 40 | | 1 | 1000 | 10000 | 0.99 | 1E-07 | 1.648 | 41 | | 2 | 1000 | 10000 | 0.99 | 1E-07 | 1.433 | 42 | | 3 | 1000 | 10000 | 0.99 | 1E-07 | 1.676 | 43 | | 4 | 1000 | 10000 | 0.99 | 1E-07 | 1.488 | 44 | | 5 | 1000 | 10000 | 0.99 | 1E-07 | 1.54 | 45 | | 6 | 1000 | 150000 | 0.99 | 1E-07 | 6.017 | 46 | | 7 | 3000 | 150000 | 0.998 | 1E-06 | 126.944 | 47 | | 8 | 1000 | 10000 | 0.99 | 1E-07 | 2.546 | 48 | | 9 | 3000 | 150000 | 0.997 | 1E-07 | 102.665 | 49 | | 10 | 1000 | 10000 | 0.99 | 1E-07 | 14.058 | 50 | 51 | #### Gantt chart of the solution 52 | 53 | gantt 54 | -------------------------------------------------------------------------------- /test.txt: -------------------------------------------------------------------------------- 1 | 7038 2 | 8366 3 | 7166 4 | 7312 5 | 8003 6 | 7720 7 | 1431 8 | 1950 9 | 1109 10 | 1902 11 | 3277 --------------------------------------------------------------------------------