Descent Solver: Completed - Taboo Solver: Completed
This commit is contained in:
		
							parent
							
								
									f306a8c7f6
								
							
						
					
					
						commit
						5fe1352f2d
					
				
					 20 changed files with 1824 additions and 1306 deletions
				
			
		
							
								
								
									
										144
									
								
								Solvers-Results.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								Solvers-Results.txt
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,144 @@ | |||
|                          basic                         random                         | ||||
| instance size  best      runtime makespan ecart        runtime makespan ecart         | ||||
| aaa1     2x3     11            1       12   9.1            999       11   0.0         | ||||
| ft06     6x6     55            0       60   9.1            999       55   0.0         | ||||
| ft10     10x10  930            0     1319  41.8            999     1209  30.0         | ||||
| ft20     20x5  1165            0     1672  43.5            999     1529  31.2         | ||||
| la01     10x5   666            0      858  28.8            999      701   5.3         | ||||
| la02     10x5   655            0      904  38.0            999      729  11.3         | ||||
| la03     10x5   597            0      775  29.8            999      673  12.7         | ||||
| la04     10x5   590            0      854  44.7            999      667  13.1         | ||||
| la05     10x5   593            0      629   6.1            999      593   0.0         | ||||
| la06     15x5   926            0     1015   9.6            999      943   1.8         | ||||
| la07     15x5   890            0     1096  23.1            999      981  10.2         | ||||
| la08     15x5   863            0     1102  27.7            999      944   9.4         | ||||
| la09     15x5   951            0     1024   7.7            999      964   1.4         | ||||
| AVG      -        -          0.1        -  24.5          999.0        -   9.7 | ||||
| 
 | ||||
| 
 | ||||
|                          Greedy-SPT                    Greedy-LRPT                   Greedy-EST_SPT                Greedy-EST_LRPT                | ||||
| instance size  best      runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart         | ||||
| aaa1     2x3     11            6       16  45.5              0       11   0.0              0       11   0.0              1       11   0.0         | ||||
| ft06     6x6     55            2      108  96.4              2       74  34.5              1       88  60.0              1       61  10.9         | ||||
| ft10     10x10  930            3     2569 176.2              2     1289  38.6              2     1074  15.5              2     1108  19.1         | ||||
| ft20     20x5  1165            3     2765 137.3              3     1955  67.8              2     1267   8.8              1     1501  28.8         | ||||
| la01     10x5   666            1     1464 119.8              0      845  26.9              1      751  12.8              1      735  10.4         | ||||
| la02     10x5   655            1     1943 196.6              0      982  49.9              0      821  25.3              1      817  24.7         | ||||
| la03     10x5   597            1     1053  76.4              0      797  33.5              0      672  12.6              0      696  16.6         | ||||
| la04     10x5   590            1     1491 152.7              0     1000  69.5              1      711  20.5              0      758  28.5         | ||||
| la05     10x5   593            0     1521 156.5              0      666  12.3              0      610   2.9              0      593   0.0         | ||||
| la06     15x5   926            1     2372 156.2              1     1151  24.3              0     1200  29.6              0      926   0.0         | ||||
| la07     15x5   890            1     1823 104.8              1     1108  24.5              1     1034  16.2              1      970   9.0         | ||||
| la08     15x5   863            0     2309 167.6              0     1196  38.6              1      942   9.2              1      943   9.3         | ||||
| la09     15x5   951            0     2638 177.4              0     1233  29.7              0     1045   9.9              1     1015   6.7         | ||||
| AVG      -        -          1.5        - 135.6            0.7        -  34.6            0.7        -  17.2            0.8        -  12.6 | ||||
| 
 | ||||
| 
 | ||||
|                          Descent-SPT                   Descent-LRPT                  Descent-EST_SPT               Descent-EST_LRPT               | ||||
| instance size  best      runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart         | ||||
| aaa1     2x3     11           14       11   0.0              1       11   0.0              1       11   0.0              1       11   0.0         | ||||
| ft06     6x6     55           21       65  18.2              4       58   5.5              5       72  30.9              3       55   0.0         | ||||
| ft10     10x10  930           66     1379  48.3             23     1073  15.4              5     1017   9.4              2     1108  19.1         | ||||
| ft20     20x5  1165           79     1574  35.1             31     1513  29.9              1     1267   8.8              1     1501  28.8         | ||||
| la01     10x5   666           11      907  36.2              4      666   0.0              2      686   3.0              4      695   4.4         | ||||
| la02     10x5   655            8      869  32.7              2      806  23.1              3      685   4.6              1      782  19.4         | ||||
| la03     10x5   597            2      877  46.9              1      725  21.4              0      666  11.6              1      696  16.6         | ||||
| la04     10x5   590            6      852  44.4              2      794  34.6              1      702  19.0              0      747  26.6         | ||||
| la05     10x5   593           12      742  25.1              2      621   4.7              0      610   2.9              0      593   0.0         | ||||
| la06     15x5   926           11     1348  45.6              3      952   2.8              2      963   4.0              0      926   0.0         | ||||
| la07     15x5   890           14     1087  22.1              3      965   8.4              0     1034  16.2              5      923   3.7         | ||||
| la08     15x5   863           20     1320  53.0              2     1082  25.4              0      933   8.1              0      909   5.3         | ||||
| la09     15x5   951           29     1433  50.7              3     1084  14.0              1      975   2.5              1      985   3.6         | ||||
| AVG      -        -         22.5        -  35.2            6.2        -  14.2            1.6        -   9.3            1.5        -   9.8  | ||||
| 
 | ||||
| 
 | ||||
|                          Taboo-EST_LRPT(1,1)            | ||||
| instance size  best      runtime makespan ecart         | ||||
| aaa1     2x3     11           17       11   0.0         | ||||
| ft06     6x6     55           20       57   3.6         | ||||
| ft10     10x10  930           13     1108  19.1         | ||||
| ft20     20x5  1165            9     1501  28.8         | ||||
| la01     10x5   666            4      695   4.4         | ||||
| la02     10x5   655            3      803  22.6         | ||||
| la03     10x5   597            2      696  16.6         | ||||
| la04     10x5   590            2      747  26.6         | ||||
| la05     10x5   593            1      593   0.0         | ||||
| la06     15x5   926            2      926   0.0         | ||||
| la07     15x5   890            3      951   6.9         | ||||
| la08     15x5   863           12      909   5.3         | ||||
| la09     15x5   951            2      985   3.6         | ||||
| AVG      -        -          6.9        -  10.6 | ||||
| 
 | ||||
| 
 | ||||
|                          Taboo-EST_LRPT(1,10)          Taboo-EST_LRPT(2,10)          Taboo-EST_LRPT(3,10)          Taboo-EST_LRPT(4,10)          Taboo-EST_LRPT(5,10)          Taboo-EST_LRPT(6,10)          Taboo-EST_LRPT(7,10)          Taboo-EST_LRPT(8,10)          Taboo-EST_LRPT(9,10)          Taboo-EST_LRPT(10,10)          | ||||
| instance size  best      runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart         | ||||
| aaa1     2x3     11           25       11   0.0              4       11   0.0              4       11   0.0              2       11   0.0              2       11   0.0              2       11   0.0              2       11   0.0              1       11   0.0              2       11   0.0              3       11   0.0         | ||||
| ft06     6x6     55           14       55   0.0             11       55   0.0             11       55   0.0              7       55   0.0              8       55   0.0              7       55   0.0              6       55   0.0             16       55   0.0              4       55   0.0              4       55   0.0         | ||||
| ft10     10x10  930           21     1108  19.1             23     1108  19.1             19     1096  17.8             14     1108  19.1             19     1108  19.1             14     1108  19.1             12     1108  19.1             11     1108  19.1             11     1108  19.1             11     1108  19.1         | ||||
| ft20     20x5  1165            7     1501  28.8              7     1465  25.8              8     1465  25.8             15     1465  25.8              5     1465  25.8              4     1465  25.8              5     1465  25.8              5     1465  25.8              5     1465  25.8              5     1465  25.8         | ||||
| la01     10x5   666            4      695   4.4              2      692   3.9              3      692   3.9              2      692   3.9              3      692   3.9              2      692   3.9              2      692   3.9              2      692   3.9              2      692   3.9              2      692   3.9         | ||||
| la02     10x5   655            3      769  17.4              3      769  17.4              3      769  17.4              2      753  15.0              2      753  15.0              3      753  15.0              3      753  15.0              2      753  15.0              2      753  15.0              3      753  15.0         | ||||
| la03     10x5   597            2      692  15.9              2      692  15.9              6      689  15.4              2      689  15.4              2      692  15.9              4      692  15.9              3      692  15.9              2      692  15.9              3      692  15.9              2      692  15.9         | ||||
| la04     10x5   590            3      696  18.0              2      696  18.0              3      696  18.0              2      696  18.0              2      702  19.0              2      703  19.2              2      703  19.2              1      694  17.6              2      694  17.6              2      694  17.6         | ||||
| la05     10x5   593            3      593   0.0              2      593   0.0              1      593   0.0              1      593   0.0              1      593   0.0              1      593   0.0              1      593   0.0              1      593   0.0              1      593   0.0              1      593   0.0         | ||||
| la06     15x5   926            2      926   0.0              2      926   0.0              2      926   0.0              2      926   0.0              2      926   0.0              2      926   0.0              1      926   0.0              3      926   0.0              2      926   0.0              1      926   0.0         | ||||
| la07     15x5   890            7      912   2.5              5      912   2.5              4      912   2.5              8      912   2.5              4      912   2.5              4      912   2.5              5      912   2.5              4      912   2.5              4      912   2.5              4      912   2.5         | ||||
| la08     15x5   863            4      902   4.5              4      902   4.5              5      902   4.5              4      902   4.5              8      902   4.5              6      902   4.5              5      902   4.5              4      902   4.5              3      902   4.5              3      902   4.5         | ||||
| la09     15x5   951            3      951   0.0              2      951   0.0              3      951   0.0             15      985   3.6              6      985   3.6              5      951   0.0              4      951   0.0              4      951   0.0              4      951   0.0              6      951   0.0         | ||||
| AVG      -        -          7.5        -   8.5            5.3        -   8.2            5.5        -   8.1            5.8        -   8.3            4.9        -   8.4            4.3        -   8.1            3.9        -   8.1            4.3        -   8.0            3.5        -   8.0            3.6        -   8.0    | ||||
| 
 | ||||
| 
 | ||||
|                          Taboo-EST_LRPT(1,100)         Taboo-EST_LRPT(6,100)         Taboo-EST_LRPT(8,100)         Taboo-EST_LRPT(10,100)        Taboo-EST_LRPT(12,100)        Taboo-EST_LRPT(14,100)        Taboo-EST_LRPT(20,100)        Taboo-EST_LRPT(50,100)        Taboo-EST_LRPT(100,100)        | ||||
| instance size  best      runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart         | ||||
| aaa1     2x3     11           48       11   0.0             13       11   0.0              9       11   0.0              6       11   0.0              5       11   0.0              5       11   0.0              3       11   0.0              2       11   0.0              3       11   0.0         | ||||
| ft06     6x6     55           43       55   0.0             36       55   0.0             27       55   0.0             20       55   0.0             20       55   0.0             15       55   0.0             17       55   0.0             10       55   0.0              6       55   0.0         | ||||
| ft10     10x10  930           95     1108  19.1             63     1037  11.5             59     1041  11.9             52     1032  11.0             60     1048  12.7             82     1046  12.5             55     1054  13.3             48     1098  18.1             34     1098  18.1         | ||||
| ft20     20x5  1165           42     1501  28.8             40     1329  14.1             41     1329  14.1             46     1311  12.5             37     1325  13.7             43     1329  14.1             51     1352  16.1             23     1399  20.1             18     1400  20.2         | ||||
| la01     10x5   666           23      695   4.4              9      666   0.0              7      666   0.0             19      666   0.0             16      690   3.6             13      688   3.3             15      671   0.8              8      690   3.6              6      692   3.9         | ||||
| la02     10x5   655           34      737  12.5             17      722  10.2             22      694   6.0             15      706   7.8             16      732  11.8             13      736  12.4             11      736  12.4              9      736  12.4             11      745  13.7         | ||||
| la03     10x5   597           21      692  15.9             21      651   9.0             21      676  13.2             17      637   6.7             15      678  13.6             16      670  12.2             14      617   3.4             10      648   8.5              7      692  15.9         | ||||
| la04     10x5   590           21      696  18.0             22      638   8.1             26      646   9.5             23      648   9.8             14      639   8.3             14      651  10.3             12      647   9.7              9      674  14.2              5      674  14.2         | ||||
| la05     10x5   593           11      593   0.0              8      593   0.0              8      593   0.0              5      593   0.0              5      593   0.0              5      593   0.0              4      593   0.0              4      593   0.0              5      593   0.0         | ||||
| la06     15x5   926           31      926   0.0             11      926   0.0              8      926   0.0              8      926   0.0              8      926   0.0              8      926   0.0             11      926   0.0              7      926   0.0              7      926   0.0         | ||||
| la07     15x5   890           33      890   0.0             14      890   0.0             13      890   0.0             17      890   0.0             11      890   0.0             15      890   0.0             11      890   0.0             10      890   0.0             11      890   0.0         | ||||
| la08     15x5   863           30      902   4.5             22      863   0.0             25      866   0.3             23      863   0.0             24      863   0.0             21      863   0.0             14      863   0.0             13      878   1.7              8      902   4.5         | ||||
| la09     15x5   951           15      951   0.0             11      951   0.0             11      951   0.0              9      951   0.0              8      951   0.0              9      951   0.0             23      951   0.0             13      951   0.0             13      951   0.0         | ||||
| AVG      -        -         34.4        -   7.9           22.1        -   4.1           21.3        -   4.2           20.0        -   3.7           18.4        -   4.9           19.9        -   5.0           18.5        -   4.3           12.8        -   6.0           10.3        -   7.0  | ||||
| 
 | ||||
| 
 | ||||
|                          Taboo-EST_LRPT(1,1000)        Taboo-EST_LRPT(6,1000)        Taboo-EST_LRPT(8,1000)        Taboo-EST_LRPT(10,1000)       Taboo-EST_LRPT(12,1000)       Taboo-EST_LRPT(14,1000)       Taboo-EST_LRPT(20,1000)       Taboo-EST_LRPT(50,1000)       Taboo-EST_LRPT(100,1000)       | ||||
| instance size  best      runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart         | ||||
| aaa1     2x3     11           99       11   0.0             24       11   0.0             23       11   0.0             25       11   0.0             24       11   0.0             21       11   0.0             18       11   0.0             14       11   0.0             12       11   0.0         | ||||
| ft06     6x6     55          160       55   0.0            137       55   0.0            133       55   0.0             99       55   0.0            103       55   0.0             76       55   0.0             73       55   0.0             49       55   0.0             55       55   0.0         | ||||
| ft10     10x10  930          583     1108  19.1            622     1013   8.9            569      983   5.7            541      978   5.2            573      978   5.2            530     1007   8.3            535     1029  10.6            360     1045  12.4            251     1015   9.1         | ||||
| ft20     20x5  1165          383     1501  28.8            396     1217   4.5            438     1262   8.3            366     1243   6.7            294     1255   7.7            321     1218   4.5            302     1219   4.6            209     1246   7.0            168     1271   9.1         | ||||
| la01     10x5   666          196      695   4.4             61      666   0.0             52      666   0.0             64      666   0.0             65      666   0.0             76      666   0.0             68      666   0.0             52      666   0.0             54      666   0.0         | ||||
| la02     10x5   655          244      737  12.5            170      667   1.8            177      665   1.5            158      665   1.5            142      662   1.1            134      655   0.0            108      671   2.4             69      692   5.6             58      720   9.9         | ||||
| la03     10x5   597          165      692  15.9            133      628   5.2            152      620   3.9            143      603   1.0            140      603   1.0            130      603   1.0            108      603   1.0             76      615   3.0             56      615   3.0         | ||||
| la04     10x5   590          203      696  18.0            129      638   8.1            160      598   1.4            151      599   1.5            148      604   2.4             75      637   8.0            104      597   1.2             91      620   5.1             72      620   5.1         | ||||
| la05     10x5   593           93      593   0.0             56      593   0.0             59      593   0.0             49      593   0.0             49      593   0.0             45      593   0.0             45      593   0.0             45      593   0.0             40      593   0.0         | ||||
| la06     15x5   926          169      926   0.0             90      926   0.0             80      926   0.0             82      926   0.0             77      926   0.0             72      926   0.0             76      926   0.0             64      926   0.0             65      926   0.0         | ||||
| la07     15x5   890          164      890   0.0             92      890   0.0             94      890   0.0             84      890   0.0             82      890   0.0             79      890   0.0             81      890   0.0             69      890   0.0             72      890   0.0         | ||||
| la08     15x5   863          326      902   4.5            103      863   0.0            105      863   0.0             90      863   0.0             92      863   0.0             82      863   0.0             82      863   0.0             72      863   0.0             72      863   0.0         | ||||
| la09     15x5   951          151      951   0.0             85      951   0.0             81      951   0.0             80      951   0.0             79      951   0.0             78      951   0.0             78      951   0.0             78      951   0.0             62      951   0.0         | ||||
| AVG      -        -        225.8        -   7.9          161.4        -   2.2          163.3        -   1.6          148.6        -   1.2          143.7        -   1.3          132.2        -   1.7          129.1        -   1.5           96.0        -   2.5           79.8        -   2.8     | ||||
| 
 | ||||
| 
 | ||||
|                          Taboo-EST_LRPT(1,5000)        Taboo-EST_LRPT(6,5000)        Taboo-EST_LRPT(8,5000)        Taboo-EST_LRPT(10,5000)       Taboo-EST_LRPT(12,5000)       Taboo-EST_LRPT(14,5000)       Taboo-EST_LRPT(20,5000)       Taboo-EST_LRPT(50,5000)       Taboo-EST_LRPT(100,5000)       | ||||
| instance size  best      runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart        runtime makespan ecart         | ||||
| aaa1     2x3     11          265       11   0.0            101       11   0.0             40       11   0.0             34       11   0.0             35       11   0.0             27       11   0.0             38       11   0.0             25       11   0.0             30       11   0.0         | ||||
| ft06     6x6     55          675       55   0.0            665       55   0.0            405       55   0.0            504       55   0.0            489       55   0.0            329       55   0.0            286       55   0.0            267       55   0.0            222       55   0.0         | ||||
| ft10     10x10  930         1000     1108  19.1           1000     1002   7.7           1000      954   2.6           1000      978   5.2           1000      976   4.9           1000      995   7.0           1000     1007   8.3           1000     1036  11.4           1000     1015   9.1         | ||||
| ft20     20x5  1165         1000     1501  28.8           1000     1217   4.5           1000     1262   8.3           1000     1193   2.4           1000     1255   7.7           1000     1192   2.3           1000     1187   1.9           1000     1189   2.1            699     1240   6.4         | ||||
| la01     10x5   666          999      695   4.4            320      666   0.0            278      666   0.0            273      666   0.0            274      666   0.0            280      666   0.0            255      666   0.0            240      666   0.0            242      666   0.0         | ||||
| la02     10x5   655         1000      737  12.5            959      667   1.8            722      660   0.8            612      655   0.0            604      658   0.5            620      655   0.0            473      655   0.0            420      660   0.8            329      669   2.1         | ||||
| la03     10x5   597          891      692  15.9            510      628   5.2            690      605   1.3            380      603   1.0            690      603   1.0            329      603   1.0            440      603   1.0            414      615   3.0            278      615   3.0         | ||||
| la04     10x5   590         1000      696  18.0            710      638   8.1            677      598   1.4            382      599   1.5            477      602   2.0            339      637   8.0            381      597   1.2            446      598   1.4            332      616   4.4         | ||||
| la05     10x5   593          504      593   0.0            302      593   0.0            278      593   0.0            271      593   0.0            250      593   0.0            249      593   0.0            252      593   0.0            214      593   0.0            223      593   0.0         | ||||
| la06     15x5   926          794      926   0.0            471      926   0.0            412      926   0.0            417      926   0.0            406      926   0.0            391      926   0.0            367      926   0.0            360      926   0.0            338      926   0.0         | ||||
| la07     15x5   890          787      890   0.0            462      890   0.0            477      890   0.0            474      890   0.0            474      890   0.0            421      890   0.0            395      890   0.0            373      890   0.0            381      890   0.0         | ||||
| la08     15x5   863         1000      902   4.5            473      863   0.0            455      863   0.0            445      863   0.0            421      863   0.0            411      863   0.0            387      863   0.0            372      863   0.0            351      863   0.0         | ||||
| la09     15x5   951          786      951   0.0            482      951   0.0            453      951   0.0            426      951   0.0            406      951   0.0            392      951   0.0            388      951   0.0            367      951   0.0            357      951   0.0         | ||||
| AVG      -        -        823.2        -   7.9          573.5        -   2.1          529.8        -   1.1          478.3        -   0.8          502.0        -   1.2          445.2        -   1.4          435.5        -   1.0          422.9        -   1.4          367.8        -   1.9    | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1,5 +1,5 @@ | |||
| # Example instance | ||||
| 3 3 # num-jobs num-tasks | ||||
| 2  3  0  3  1  2 | ||||
| 2  4  0  3  1  2 | ||||
| 1  7  0  6  2  5 | ||||
| 0  2  1 10  2  4 | ||||
							
								
								
									
										5
									
								
								instances/aaa3
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								instances/aaa3
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | |||
| # Example instance | ||||
| 3 3 # num-jobs num-tasks | ||||
| 1  4  2  3  0  2 | ||||
| 1  7  0  6  2  5 | ||||
| 0  2  1 10  2  4 | ||||
|  | @ -1,180 +1,189 @@ | |||
| package jobshop; | ||||
| 
 | ||||
| import java.util.Arrays; | ||||
| import java.util.HashMap; | ||||
| 
 | ||||
| public class BestKnownResult { | ||||
| 
 | ||||
|     public static boolean isKnown(String instanceName) { | ||||
|         return bests.containsKey(instanceName); | ||||
|     } | ||||
| 
 | ||||
|     public static int of(String instanceName) { | ||||
|         if(!bests.containsKey(instanceName)) { | ||||
|             throw new RuntimeException("Unknown best result for "+instanceName); | ||||
|         } | ||||
|         return bests.get(instanceName); | ||||
|     } | ||||
| 
 | ||||
|     static private HashMap<String, Integer> bests; | ||||
|     static String[] instances; | ||||
|     static { | ||||
|         bests = new HashMap<>(); | ||||
|         bests.put("aaa1", 11); | ||||
|         bests.put("abz5", 1234); | ||||
|         bests.put("abz6", 943); | ||||
|         bests.put("abz7", 656); | ||||
|         bests.put("abz8", 665); | ||||
|         bests.put("abz9", 679); | ||||
|         bests.put("ft06", 55); | ||||
|         bests.put("ft10", 930); | ||||
|         bests.put("ft20", 1165); | ||||
|         bests.put("la01", 666); | ||||
|         bests.put("la02", 655); | ||||
|         bests.put("la03", 597); | ||||
|         bests.put("la04", 590); | ||||
|         bests.put("la05", 593); | ||||
|         bests.put("la06", 926); | ||||
|         bests.put("la07", 890); | ||||
|         bests.put("la08", 863); | ||||
|         bests.put("la09", 951); | ||||
|         bests.put("la10", 958); | ||||
|         bests.put("la11", 1222); | ||||
|         bests.put("la12", 1039); | ||||
|         bests.put("la13", 1150); | ||||
|         bests.put("la14", 1292); | ||||
|         bests.put("la15", 1207); | ||||
|         bests.put("la16", 945); | ||||
|         bests.put("la17", 784); | ||||
|         bests.put("la18", 848); | ||||
|         bests.put("la19", 842); | ||||
|         bests.put("la20", 902); | ||||
|         bests.put("la21", 1046); | ||||
|         bests.put("la22", 927); | ||||
|         bests.put("la23", 1032); | ||||
|         bests.put("la24", 935); | ||||
|         bests.put("la25", 977); | ||||
|         bests.put("la26", 1218); | ||||
|         bests.put("la27", 1235); | ||||
|         bests.put("la28", 1216); | ||||
|         bests.put("la29", 1152); | ||||
|         bests.put("la30", 1355); | ||||
|         bests.put("la31", 1784); | ||||
|         bests.put("la32", 1850); | ||||
|         bests.put("la33", 1719); | ||||
|         bests.put("la34", 1721); | ||||
|         bests.put("la35", 1888); | ||||
|         bests.put("la36", 1268); | ||||
|         bests.put("la37", 1397); | ||||
|         bests.put("la38", 1196); | ||||
|         bests.put("la39", 1233); | ||||
|         bests.put("la40", 1222); | ||||
|         bests.put("orb01", 1059); | ||||
|         bests.put("orb02", 888); | ||||
|         bests.put("orb03", 1005); | ||||
|         bests.put("orb04", 1005); | ||||
|         bests.put("orb05", 887); | ||||
|         bests.put("orb06", 1010); | ||||
|         bests.put("orb07", 397); | ||||
|         bests.put("orb08", 899); | ||||
|         bests.put("orb09", 934); | ||||
|         bests.put("orb10", 944); | ||||
|         bests.put("swv01", 1407); | ||||
|         bests.put("swv02", 1475); | ||||
|         bests.put("swv03", 1398); | ||||
|         bests.put("swv04", 1474); | ||||
|         bests.put("swv05", 1424); | ||||
|         bests.put("swv06", 1678); | ||||
|         bests.put("swv07", 1600); | ||||
|         bests.put("swv08", 1763); | ||||
|         bests.put("swv09", 1661); | ||||
|         bests.put("swv10", 1767); | ||||
|         bests.put("swv11", 2991); | ||||
|         bests.put("swv12", 3003); | ||||
|         bests.put("swv13", 3104); | ||||
|         bests.put("swv14", 2968); | ||||
|         bests.put("swv15", 2904); | ||||
|         bests.put("swv16", 2924); | ||||
|         bests.put("swv17", 2794); | ||||
|         bests.put("swv18", 2852); | ||||
|         bests.put("swv19", 2843); | ||||
|         bests.put("swv20", 2823); | ||||
|         bests.put("yn1", 885); | ||||
|         bests.put("yn2", 909); | ||||
|         bests.put("yn3", 892); | ||||
|         bests.put("yn4", 968); | ||||
|         bests.put("ta01", 1231); | ||||
|         bests.put("ta02", 1244); | ||||
|         bests.put("ta03", 1218); | ||||
|         bests.put("ta04", 1175); | ||||
|         bests.put("ta05", 1224); | ||||
|         bests.put("ta06", 1238); | ||||
|         bests.put("ta07", 1227); | ||||
|         bests.put("ta08", 1217); | ||||
|         bests.put("ta09", 1274); | ||||
|         bests.put("ta10", 1241); | ||||
|         bests.put("ta11", 1361); | ||||
|         bests.put("ta12", 1367); | ||||
|         bests.put("ta13", 1342); | ||||
|         bests.put("ta14", 1345); | ||||
|         bests.put("ta15", 1340); | ||||
|         bests.put("ta16", 1360); | ||||
|         bests.put("ta17", 1462); | ||||
|         bests.put("ta18", 1396); | ||||
|         bests.put("ta19", 1335); | ||||
|         bests.put("ta20", 1351); | ||||
|         bests.put("ta21", 1644); | ||||
|         bests.put("ta22", 1600); | ||||
|         bests.put("ta23", 1557); | ||||
|         bests.put("ta24", 1647); | ||||
|         bests.put("ta25", 1595); | ||||
|         bests.put("ta26", 1645); | ||||
|         bests.put("ta27", 1680); | ||||
|         bests.put("ta28", 1614); | ||||
|         bests.put("ta29", 1635); | ||||
|         bests.put("ta30", 1584); | ||||
|         bests.put("ta31", 1764); | ||||
|         bests.put("ta32", 1796); | ||||
|         bests.put("ta33", 1793); | ||||
|         bests.put("ta34", 1829); | ||||
|         bests.put("ta35", 2007); | ||||
|         bests.put("ta36", 1819); | ||||
|         bests.put("ta37", 1778); | ||||
|         bests.put("ta38", 1673); | ||||
|         bests.put("ta39", 1795); | ||||
|         bests.put("ta40", 1674); | ||||
|         bests.put("ta41", 2018); | ||||
|         bests.put("ta42", 1956); | ||||
|         bests.put("ta43", 1859); | ||||
|         bests.put("ta44", 1984); | ||||
|         bests.put("ta45", 2000); | ||||
|         bests.put("ta46", 2021); | ||||
|         bests.put("ta47", 1903); | ||||
|         bests.put("ta48", 1952); | ||||
|         bests.put("ta49", 1968); | ||||
|         bests.put("ta50", 1926); | ||||
|         bests.put("ta51", 2760); | ||||
|         bests.put("ta52", 2756); | ||||
|         bests.put("ta53", 2717); | ||||
|         bests.put("ta54", 2839); | ||||
|         bests.put("ta55", 2679); | ||||
|         bests.put("ta56", 2781); | ||||
|         bests.put("ta57", 2943); | ||||
|         bests.put("ta58", 2885); | ||||
|         bests.put("ta59", 2655); | ||||
|         bests.put("ta60", 2723); | ||||
|         bests.put("ta61", 2868); | ||||
|         bests.put("ta62", 2869); | ||||
|         bests.put("ta63", 2755); | ||||
|         bests.put("ta64", 2702); | ||||
|         bests.put("ta65", 2725); | ||||
|         bests.put("ta66", 2845); | ||||
|         bests.put("ta67", 2825); | ||||
|         bests.put("ta68", 2784); | ||||
|         bests.put("ta69", 3071); | ||||
|         bests.put("ta70", 2995); | ||||
|         instances = bests.keySet().toArray(new String[0]); | ||||
|         Arrays.sort(instances); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| package jobshop; | ||||
| 
 | ||||
| import java.util.Arrays; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.stream.Collectors; | ||||
| 
 | ||||
| public class BestKnownResult { | ||||
| 
 | ||||
|     public static boolean isKnown(String instanceName) { | ||||
|         return bests.containsKey(instanceName); | ||||
|     } | ||||
| 
 | ||||
|     public static List<String> instancesMatching(String namePrefix) { | ||||
|         return Arrays.stream(instances) | ||||
|                 .filter(i -> i.startsWith(namePrefix)) | ||||
|                 .sorted() | ||||
|                 .collect(Collectors.toList()); | ||||
|     } | ||||
| 
 | ||||
|     public static int of(String instanceName) { | ||||
|         if(!bests.containsKey(instanceName)) { | ||||
|             throw new RuntimeException("Unknown best result for "+instanceName); | ||||
|         } | ||||
|         return bests.get(instanceName); | ||||
|     } | ||||
| 
 | ||||
|     static private HashMap<String, Integer> bests; | ||||
|     static String[] instances; | ||||
|     static { | ||||
|         bests = new HashMap<>(); | ||||
|         bests.put("aaa1", 11); | ||||
|         bests.put("abz5", 1234); | ||||
|         bests.put("abz6", 943); | ||||
|         bests.put("abz7", 656); | ||||
|         bests.put("abz8", 665); | ||||
|         bests.put("abz9", 679); | ||||
|         bests.put("ft06", 55); | ||||
|         bests.put("ft10", 930); | ||||
|         bests.put("ft20", 1165); | ||||
|         bests.put("la01", 666); | ||||
|         bests.put("la02", 655); | ||||
|         bests.put("la03", 597); | ||||
|         bests.put("la04", 590); | ||||
|         bests.put("la05", 593); | ||||
|         bests.put("la06", 926); | ||||
|         bests.put("la07", 890); | ||||
|         bests.put("la08", 863); | ||||
|         bests.put("la09", 951); | ||||
|         bests.put("la10", 958); | ||||
|         bests.put("la11", 1222); | ||||
|         bests.put("la12", 1039); | ||||
|         bests.put("la13", 1150); | ||||
|         bests.put("la14", 1292); | ||||
|         bests.put("la15", 1207); | ||||
|         bests.put("la16", 945); | ||||
|         bests.put("la17", 784); | ||||
|         bests.put("la18", 848); | ||||
|         bests.put("la19", 842); | ||||
|         bests.put("la20", 902); | ||||
|         bests.put("la21", 1046); | ||||
|         bests.put("la22", 927); | ||||
|         bests.put("la23", 1032); | ||||
|         bests.put("la24", 935); | ||||
|         bests.put("la25", 977); | ||||
|         bests.put("la26", 1218); | ||||
|         bests.put("la27", 1235); | ||||
|         bests.put("la28", 1216); | ||||
|         bests.put("la29", 1152); | ||||
|         bests.put("la30", 1355); | ||||
|         bests.put("la31", 1784); | ||||
|         bests.put("la32", 1850); | ||||
|         bests.put("la33", 1719); | ||||
|         bests.put("la34", 1721); | ||||
|         bests.put("la35", 1888); | ||||
|         bests.put("la36", 1268); | ||||
|         bests.put("la37", 1397); | ||||
|         bests.put("la38", 1196); | ||||
|         bests.put("la39", 1233); | ||||
|         bests.put("la40", 1222); | ||||
|         bests.put("orb01", 1059); | ||||
|         bests.put("orb02", 888); | ||||
|         bests.put("orb03", 1005); | ||||
|         bests.put("orb04", 1005); | ||||
|         bests.put("orb05", 887); | ||||
|         bests.put("orb06", 1010); | ||||
|         bests.put("orb07", 397); | ||||
|         bests.put("orb08", 899); | ||||
|         bests.put("orb09", 934); | ||||
|         bests.put("orb10", 944); | ||||
|         bests.put("swv01", 1407); | ||||
|         bests.put("swv02", 1475); | ||||
|         bests.put("swv03", 1398); | ||||
|         bests.put("swv04", 1474); | ||||
|         bests.put("swv05", 1424); | ||||
|         bests.put("swv06", 1678); | ||||
|         bests.put("swv07", 1600); | ||||
|         bests.put("swv08", 1763); | ||||
|         bests.put("swv09", 1661); | ||||
|         bests.put("swv10", 1767); | ||||
|         bests.put("swv11", 2991); | ||||
|         bests.put("swv12", 3003); | ||||
|         bests.put("swv13", 3104); | ||||
|         bests.put("swv14", 2968); | ||||
|         bests.put("swv15", 2904); | ||||
|         bests.put("swv16", 2924); | ||||
|         bests.put("swv17", 2794); | ||||
|         bests.put("swv18", 2852); | ||||
|         bests.put("swv19", 2843); | ||||
|         bests.put("swv20", 2823); | ||||
|         bests.put("yn1", 885); | ||||
|         bests.put("yn2", 909); | ||||
|         bests.put("yn3", 892); | ||||
|         bests.put("yn4", 968); | ||||
|         bests.put("ta01", 1231); | ||||
|         bests.put("ta02", 1244); | ||||
|         bests.put("ta03", 1218); | ||||
|         bests.put("ta04", 1175); | ||||
|         bests.put("ta05", 1224); | ||||
|         bests.put("ta06", 1238); | ||||
|         bests.put("ta07", 1227); | ||||
|         bests.put("ta08", 1217); | ||||
|         bests.put("ta09", 1274); | ||||
|         bests.put("ta10", 1241); | ||||
|         bests.put("ta11", 1361); | ||||
|         bests.put("ta12", 1367); | ||||
|         bests.put("ta13", 1342); | ||||
|         bests.put("ta14", 1345); | ||||
|         bests.put("ta15", 1340); | ||||
|         bests.put("ta16", 1360); | ||||
|         bests.put("ta17", 1462); | ||||
|         bests.put("ta18", 1396); | ||||
|         bests.put("ta19", 1335); | ||||
|         bests.put("ta20", 1351); | ||||
|         bests.put("ta21", 1644); | ||||
|         bests.put("ta22", 1600); | ||||
|         bests.put("ta23", 1557); | ||||
|         bests.put("ta24", 1647); | ||||
|         bests.put("ta25", 1595); | ||||
|         bests.put("ta26", 1645); | ||||
|         bests.put("ta27", 1680); | ||||
|         bests.put("ta28", 1614); | ||||
|         bests.put("ta29", 1635); | ||||
|         bests.put("ta30", 1584); | ||||
|         bests.put("ta31", 1764); | ||||
|         bests.put("ta32", 1796); | ||||
|         bests.put("ta33", 1793); | ||||
|         bests.put("ta34", 1829); | ||||
|         bests.put("ta35", 2007); | ||||
|         bests.put("ta36", 1819); | ||||
|         bests.put("ta37", 1778); | ||||
|         bests.put("ta38", 1673); | ||||
|         bests.put("ta39", 1795); | ||||
|         bests.put("ta40", 1674); | ||||
|         bests.put("ta41", 2018); | ||||
|         bests.put("ta42", 1956); | ||||
|         bests.put("ta43", 1859); | ||||
|         bests.put("ta44", 1984); | ||||
|         bests.put("ta45", 2000); | ||||
|         bests.put("ta46", 2021); | ||||
|         bests.put("ta47", 1903); | ||||
|         bests.put("ta48", 1952); | ||||
|         bests.put("ta49", 1968); | ||||
|         bests.put("ta50", 1926); | ||||
|         bests.put("ta51", 2760); | ||||
|         bests.put("ta52", 2756); | ||||
|         bests.put("ta53", 2717); | ||||
|         bests.put("ta54", 2839); | ||||
|         bests.put("ta55", 2679); | ||||
|         bests.put("ta56", 2781); | ||||
|         bests.put("ta57", 2943); | ||||
|         bests.put("ta58", 2885); | ||||
|         bests.put("ta59", 2655); | ||||
|         bests.put("ta60", 2723); | ||||
|         bests.put("ta61", 2868); | ||||
|         bests.put("ta62", 2869); | ||||
|         bests.put("ta63", 2755); | ||||
|         bests.put("ta64", 2702); | ||||
|         bests.put("ta65", 2725); | ||||
|         bests.put("ta66", 2845); | ||||
|         bests.put("ta67", 2825); | ||||
|         bests.put("ta68", 2784); | ||||
|         bests.put("ta69", 3071); | ||||
|         bests.put("ta70", 2995); | ||||
|         instances = bests.keySet().toArray(new String[0]); | ||||
|         Arrays.sort(instances); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -1,153 +1,189 @@ | |||
| package jobshop; | ||||
| 
 | ||||
| import jobshop.encodings.JobNumbers; | ||||
| import jobshop.encodings.ResourceOrder; | ||||
| import jobshop.encodings.Task; | ||||
| import jobshop.solvers.DescentSolver; | ||||
| import jobshop.solvers.GreedySolver; | ||||
| import jobshop.solvers.DescentSolver.Block; | ||||
| import jobshop.solvers.GreedySolver.PriorityESTRule; | ||||
| import jobshop.solvers.GreedySolver.PriorityRule; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.nio.file.Paths; | ||||
| import java.util.List; | ||||
| 
 | ||||
| public class DebuggingMain { | ||||
| 
 | ||||
|     public static void main(String[] args) { | ||||
|         try { | ||||
|             // load the aaa1 instance | ||||
|             Instance instance = Instance.fromFile(Paths.get("instances/aaa1")); | ||||
| 
 | ||||
|             // construit une solution dans la représentation par | ||||
|             // numéro de jobs : [0 1 1 0 0 1] | ||||
|             // Note : cette solution a aussi été vue dans les exercices (section 3.3) | ||||
|             //        mais on commençait à compter à 1 ce qui donnait [1 2 2 1 1 2] | ||||
|             JobNumbers enc = new JobNumbers(instance); | ||||
|             enc.jobs[enc.nextToSet++] = 0; | ||||
|             enc.jobs[enc.nextToSet++] = 0; | ||||
|             enc.jobs[enc.nextToSet++] = 1; | ||||
|             enc.jobs[enc.nextToSet++] = 1; | ||||
|             enc.jobs[enc.nextToSet++] = 0; | ||||
|             enc.jobs[enc.nextToSet++] = 1; | ||||
| 
 | ||||
|             System.out.println("\nJOB NUMBER ENCODING: " + enc + "\n"); | ||||
| 
 | ||||
|             Schedule sched = enc.toSchedule(); | ||||
|              | ||||
|             System.out.println("SCHEDULE:\n" + sched); | ||||
|             System.out.println("VALID: " + sched.isValid() + "\n"); | ||||
|             System.out.println("MAKESPAN: " + sched.makespan() + "\n"); | ||||
|              | ||||
|             System.out.println("---------------------------------------------\n"); | ||||
|          | ||||
|             ResourceOrder ro = new ResourceOrder(instance); | ||||
|             ro.tasksByMachine[0][0] = new Task(0,0); | ||||
|             ro.tasksByMachine[0][1] = new Task(1,1); | ||||
|             ro.tasksByMachine[1][0] = new Task(1,0); | ||||
|             ro.tasksByMachine[1][1] = new Task(0,1); | ||||
|             ro.tasksByMachine[2][0] = new Task(0,2); | ||||
|             ro.tasksByMachine[2][1] = new Task(1,2); | ||||
|              | ||||
|             System.out.println("RESOURCE ORDER ENCODING:\n" + ro + "\n"); | ||||
|              | ||||
|             System.out.println("---------------------------------------------\n"); | ||||
|              | ||||
|             // load the aaa2 instance | ||||
|             Instance instance2 = Instance.fromFile(Paths.get("instances/aaa2")); | ||||
|              | ||||
|             ResourceOrder ro2 = new ResourceOrder(instance2); | ||||
|             ro2.tasksByMachine[0][0] = new Task(2,0); //O7: Job 2, Task 0 (Machine 0) | ||||
|             ro2.tasksByMachine[0][1] = new Task(1,1); //O5: Job 1, Task 1 (Machine 0) | ||||
|             ro2.tasksByMachine[0][2] = new Task(0,1); //O2: Job 0, Task 1 (Machine 0) | ||||
|             ro2.tasksByMachine[1][0] = new Task(1,0); //O4: Job 1, Task 0 (Machine 1) | ||||
|             ro2.tasksByMachine[1][1] = new Task(2,1); //O8: Job 2, Task 1 (Machine 1) | ||||
|             ro2.tasksByMachine[1][2] = new Task(0,2); //O3: Job 0, Task 2 (Machine 1) | ||||
|             ro2.tasksByMachine[2][0] = new Task(2,2); //O9: Job 2, Task 2 (Machine 2) | ||||
|             ro2.tasksByMachine[2][1] = new Task(0,0); //O1: Job 0, Task 0 (Machine 2) | ||||
|             ro2.tasksByMachine[2][2] = new Task(1,2); //O6: Job 1, Task 2 (Machine 2) | ||||
|              | ||||
|             System.out.println("RESOURCE ORDER ENCODING:\n" + ro2 + "\n"); | ||||
|              | ||||
|             System.out.println("---------------------------------------------\n"); | ||||
|              | ||||
|             System.out.println("Default Solver\n"); | ||||
|             sched = ro.toSchedule(); | ||||
|              | ||||
|             System.out.println("SCHEDULE:\n" + sched); | ||||
|             System.out.println("VALID: " + sched.isValid()); | ||||
|             System.out.println("MAKESPAN: " + sched.makespan()); | ||||
|              | ||||
|             System.out.println("---------------------------------------------\n"); | ||||
|              | ||||
|             JobNumbers jo = JobNumbers.fromSchedule(sched); | ||||
|             System.out.println("JOB NUMBER ENCODING (FROM_SCHEDULE): " + jo + "\n"); | ||||
|              | ||||
|             System.out.println("---------------------------------------------\n"); | ||||
|             System.out.println("Greedy Solver: STP"); | ||||
|             PriorityRule SPT = PriorityRule.SPT; | ||||
|             Solver solverSPT = new GreedySolver(SPT); | ||||
|             Result resultSPT = solverSPT.solve(instance, System.currentTimeMillis() + 10); | ||||
|             sched = resultSPT.schedule; | ||||
|              | ||||
|             System.out.println("SCHEDULE:\n" + sched); | ||||
|             System.out.println("VALID: " + sched.isValid()); | ||||
|             System.out.println("MAKESPAN: " + sched.makespan()); | ||||
|              | ||||
|             System.out.println("---------------------------------------------\n"); | ||||
|             System.out.println("Greedy Solver: LRPT\n"); | ||||
|             PriorityRule LRPT = PriorityRule.LRPT; | ||||
|             Solver solverLRPT = new GreedySolver(LRPT); | ||||
|             Result resultLRPT = solverLRPT.solve(instance, System.currentTimeMillis() + 10); | ||||
|             sched = resultLRPT.schedule; | ||||
|              | ||||
|             System.out.println("SCHEDULE:\n" + sched); | ||||
|             System.out.println("VALID: " + sched.isValid()); | ||||
|             System.out.println("MAKESPAN: " + sched.makespan()); | ||||
|              | ||||
|             System.out.println("---------------------------------------------\n"); | ||||
|             System.out.println("Greedy Solver: EST_SPT\n"); | ||||
|             PriorityESTRule EST_SPT = PriorityESTRule.EST_SPT; | ||||
|             Solver solverEST_SPT = new GreedySolver(EST_SPT); | ||||
|             Result resultEST_SPT = solverEST_SPT.solve(instance, System.currentTimeMillis() + 10); | ||||
|             sched = resultEST_SPT.schedule; | ||||
|              | ||||
|             System.out.println("SCHEDULE:\n" + sched); | ||||
|             System.out.println("VALID: " + sched.isValid()); | ||||
|             System.out.println("MAKESPAN: " + sched.makespan()); | ||||
|              | ||||
|             System.out.println("---------------------------------------------\n"); | ||||
|             System.out.println("Greedy Solver: ic void applyOn(ResourceOrder order) {\r\n" +  | ||||
|             		"            throw new UnsupportedOperationException();EST_SPT\n"); | ||||
|             PriorityESTRule EST_LRPT = PriorityESTRule.EST_LRPT; | ||||
|             Solver solverEST_LRPT = new GreedySolver(EST_SPT); | ||||
|             Result resultEST_LRPT = solverEST_LRPT.solve(instance, System.currentTimeMillis() + 10); | ||||
|             sched = resultEST_LRPT.schedule; | ||||
|              | ||||
|             System.out.println("SCHEDULE:\n" + sched); | ||||
|             System.out.println("VALID: " + sched.isValid()); | ||||
|             System.out.println("MAKESPAN: " + sched.makespan()); | ||||
|              | ||||
|             System.out.println("---------------------------------------------\n"); | ||||
|             System.out.println("Descent Solver: \n"); | ||||
|             DescentSolver solverDescent = new DescentSolver(); | ||||
|             List<Block> criticalBlockList = solverDescent.blocksOfCriticalPath(ro2); | ||||
|             for(Block b : criticalBlockList) { | ||||
|             	System.out.println(b); | ||||
|             	//System.out.println(solverDescent.neighbors(b)); | ||||
|             } | ||||
|             /* | ||||
|             sched = ro2.toSchedule(); | ||||
|              | ||||
|             System.out.println("SCHEDULE:\n" + sched); | ||||
|             System.out.println("VALID: " + sched.isValid()); | ||||
|             System.out.println("MAKESPAN: " + sched.makespan());*/ | ||||
|              | ||||
|         } catch (IOException e) { | ||||
|             e.printStackTrace(); | ||||
|             System.exit(1); | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| } | ||||
| package jobshop; | ||||
| 
 | ||||
| import jobshop.encodings.JobNumbers; | ||||
| import jobshop.encodings.ResourceOrder; | ||||
| import jobshop.encodings.Task; | ||||
| import jobshop.solvers.DescentSolver; | ||||
| import jobshop.solvers.DescentSolver.Block; | ||||
| import jobshop.solvers.DescentSolver.Swap; | ||||
| import jobshop.solvers.GreedySolver; | ||||
| import jobshop.solvers.GreedySolver.PriorityESTRule; | ||||
| import jobshop.solvers.GreedySolver.PriorityRule; | ||||
| import jobshop.solvers.TabooSolver; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.nio.file.Paths; | ||||
| import java.util.List; | ||||
| 
 | ||||
| public class DebuggingMain { | ||||
| 
 | ||||
|     public static void main(String[] args) { | ||||
|         try { | ||||
|             // load the aaa1 instance | ||||
|             Instance instance = Instance.fromFile(Paths.get("instances/aaa1")); | ||||
| 
 | ||||
|             // construit une solution dans la représentation par | ||||
|             // numéro de jobs : [0 1 1 0 0 1] | ||||
|             // Note : cette solution a aussi été vue dans les exercices (section 3.3) | ||||
|             //        mais on commençait à compter à 1 ce qui donnait [1 2 2 1 1 2] | ||||
|             JobNumbers enc = new JobNumbers(instance); | ||||
|             enc.jobs[enc.nextToSet++] = 0; | ||||
|             enc.jobs[enc.nextToSet++] = 1; | ||||
|             enc.jobs[enc.nextToSet++] = 1; | ||||
|             enc.jobs[enc.nextToSet++] = 0; | ||||
|             enc.jobs[enc.nextToSet++] = 0; | ||||
|             enc.jobs[enc.nextToSet++] = 1; | ||||
| 
 | ||||
|             System.out.println("\nENCODING: " + enc); | ||||
| 
 | ||||
|             Schedule sched = enc.toSchedule(); | ||||
|             // TODO: make it print something meaningful | ||||
|             // by implementing the toString() method | ||||
|             System.out.println("SCHEDULE: " + sched); | ||||
|             System.out.println("VALID: " + sched.isValid()); | ||||
|             System.out.println("MAKESPAN: " + sched.makespan()); | ||||
|              | ||||
|             System.out.println("---------------------------------------------\n"); | ||||
|              | ||||
|             ResourceOrder ro = new ResourceOrder(instance); | ||||
|             ro.tasksByMachine[0][0] = new Task(0,0); | ||||
|             ro.tasksByMachine[0][1] = new Task(1,1); | ||||
|             ro.tasksByMachine[1][0] = new Task(1,0); | ||||
|             ro.tasksByMachine[1][1] = new Task(0,1); | ||||
|             ro.tasksByMachine[2][0] = new Task(0,2); | ||||
|             ro.tasksByMachine[2][1] = new Task(1,2); | ||||
|              | ||||
|             System.out.println("RESOURCE ORDER ENCODING:\n" + ro + "\n"); | ||||
|              | ||||
|             System.out.println("---------------------------------------------\n"); | ||||
|              | ||||
|             // load the aaa2 instance | ||||
|             Instance instance2 = Instance.fromFile(Paths.get("instances/aaa2")); | ||||
|              | ||||
|             ResourceOrder ro2 = new ResourceOrder(instance2); | ||||
|             ro2.tasksByMachine[0][0] = new Task(2,0); //O7: Job 2, Task 0 (Machine 0) | ||||
|             ro2.tasksByMachine[0][1] = new Task(1,1); //O5: Job 1, Task 1 (Machine 0) | ||||
|             ro2.tasksByMachine[0][2] = new Task(0,1); //O2: Job 0, Task 1 (Machine 0) | ||||
|             ro2.tasksByMachine[1][0] = new Task(1,0); //O4: Job 1, Task 0 (Machine 1) | ||||
|             ro2.tasksByMachine[1][1] = new Task(2,1); //O8: Job 2, Task 1 (Machine 1) | ||||
|             ro2.tasksByMachine[1][2] = new Task(0,2); //O3: Job 0, Task 2 (Machine 1) | ||||
|             ro2.tasksByMachine[2][0] = new Task(2,2); //O9: Job 2, Task 2 (Machine 2) | ||||
|             ro2.tasksByMachine[2][1] = new Task(0,0); //O1: Job 0, Task 0 (Machine 2) | ||||
|             ro2.tasksByMachine[2][2] = new Task(1,2); //O6: Job 1, Task 2 (Machine 2) | ||||
|              | ||||
|             System.out.println("RESOURCE ORDER ENCODING:\n" + ro2 + "\n"); | ||||
|              | ||||
|             System.out.println("---------------------------------------------\n"); | ||||
|              | ||||
|             System.out.println("Default Solver\n"); | ||||
|             sched = ro.toSchedule(); | ||||
|              | ||||
|             System.out.println("SCHEDULE:\n" + sched); | ||||
|             System.out.println("VALID: " + sched.isValid()); | ||||
|             System.out.println("MAKESPAN: " + sched.makespan()); | ||||
|              | ||||
|             System.out.println("---------------------------------------------\n"); | ||||
|              | ||||
|             /*JobNumbers jo = JobNumbers.fromSchedule(sched); | ||||
|             System.out.println("JOB NUMBER ENCODING (FROM_SCHEDULE): " + jo + "\n");*/ | ||||
|              | ||||
|             System.out.println("---------------------------------------------\n"); | ||||
|             System.out.println("Greedy Solver: STP"); | ||||
|             PriorityRule SPT = PriorityRule.SPT; | ||||
|             Solver solverSPT = new GreedySolver(SPT); | ||||
|             Result resultSPT = solverSPT.solve(instance, System.currentTimeMillis() + 10); | ||||
|             sched = resultSPT.schedule; | ||||
|              | ||||
|             System.out.println("SCHEDULE:\n" + sched); | ||||
|             System.out.println("VALID: " + sched.isValid()); | ||||
|             System.out.println("MAKESPAN: " + sched.makespan()); | ||||
|              | ||||
|             System.out.println("---------------------------------------------\n"); | ||||
|             System.out.println("Greedy Solver: LRPT\n"); | ||||
|             PriorityRule LRPT = PriorityRule.LRPT; | ||||
|             Solver solverLRPT = new GreedySolver(LRPT); | ||||
|             Result resultLRPT = solverLRPT.solve(instance, System.currentTimeMillis() + 10); | ||||
|             sched = resultLRPT.schedule; | ||||
|              | ||||
|             System.out.println("SCHEDULE:\n" + sched); | ||||
|             System.out.println("VALID: " + sched.isValid()); | ||||
|             System.out.println("MAKESPAN: " + sched.makespan()); | ||||
|              | ||||
|             System.out.println("---------------------------------------------\n"); | ||||
|             System.out.println("Greedy Solver: EST_SPT\n"); | ||||
|             PriorityESTRule EST_SPT = PriorityESTRule.EST_SPT; | ||||
|             Solver solverEST_SPT = new GreedySolver(EST_SPT); | ||||
|             Result resultEST_SPT = solverEST_SPT.solve(instance, System.currentTimeMillis() + 10); | ||||
|             sched = resultEST_SPT.schedule; | ||||
|              | ||||
|             System.out.println("SCHEDULE:\n" + sched); | ||||
|             System.out.println("VALID: " + sched.isValid()); | ||||
|             System.out.println("MAKESPAN: " + sched.makespan()); | ||||
|              | ||||
|             System.out.println("---------------------------------------------\n"); | ||||
|             System.out.println("Greedy Solver: EST_LRPT\n"); | ||||
|             PriorityESTRule EST_LRPT = PriorityESTRule.EST_LRPT; | ||||
|             Solver solverEST_LRPT = new GreedySolver(EST_LRPT); | ||||
|             Result resultEST_LRPT = solverEST_LRPT.solve(instance, System.currentTimeMillis() + 10); | ||||
|             sched = resultEST_LRPT.schedule; | ||||
|              | ||||
|             System.out.println("SCHEDULE:\n" + sched); | ||||
|             System.out.println("VALID: " + sched.isValid()); | ||||
|             System.out.println("MAKESPAN: " + sched.makespan()); | ||||
|              | ||||
|             System.out.println("---------------------------------------------\n"); | ||||
|             System.out.println("Descent Solver: [Executed with EST_LRPT]\n"); | ||||
|              | ||||
|             DescentSolver solverDescent = new DescentSolver(EST_LRPT); | ||||
|              | ||||
|              | ||||
|             System.out.print("****** TEST: blocksOfCriticalPath() ******\n"); | ||||
|             System.out.print("Number of Jobs     : " + instance2.numJobs + "\n"); | ||||
|             System.out.print("Number of Tasks    : " + instance2.numTasks + "\n"); | ||||
|             System.out.print("Number of Machines : " + instance2.numMachines + "\n\n"); | ||||
|              | ||||
|              | ||||
|              | ||||
|             List<Block> criticalBlockList = solverDescent.blocksOfCriticalPath(ro2); | ||||
|             for(Block b : criticalBlockList) { | ||||
|             	System.out.println(b); | ||||
|             	for(Swap s : solverDescent.neighbors(b)) { | ||||
|             		System.out.println(s); | ||||
|             	} | ||||
|             } | ||||
|             System.out.print("******************************************\n"); | ||||
|              | ||||
|              | ||||
|             Result resultDescent = solverDescent.solve(instance2, System.currentTimeMillis() + 10); | ||||
|             sched = resultDescent.schedule; | ||||
|              | ||||
|             System.out.println("SCHEDULE:\n" + sched); | ||||
|             System.out.println("VALID: " + sched.isValid()); | ||||
|             System.out.println("MAKESPAN: " + sched.makespan()); | ||||
|              | ||||
|             System.out.println("---------------------------------------------\n"); | ||||
|             System.out.println("Taboo Solver: [Executed with EST_LRPT]\n"); | ||||
|              | ||||
|             TabooSolver solverTaboo = new TabooSolver(EST_LRPT, 50, 1000);             | ||||
|             Result resultTaboo = solverTaboo.solve(instance2, System.currentTimeMillis() + 10); | ||||
|             sched = resultTaboo.schedule; | ||||
|             /* | ||||
|             List<Block>criticalBlockList2 = solverTaboo.blocksOfCriticalPath(ro2); | ||||
|             for(Block b : criticalBlockList2) { | ||||
|             	System.out.println(b); | ||||
|             	for(Swap s : solverTaboo.neighbors(b)) { | ||||
|             		System.out.println(s); | ||||
|             	} | ||||
|             } | ||||
|             */ | ||||
|             System.out.println("SCHEDULE:\n" + sched); | ||||
|             System.out.println("VALID: " + sched.isValid()); | ||||
|             System.out.println("MAKESPAN: " + sched.makespan()); | ||||
| 
 | ||||
|         } catch (IOException e) { | ||||
|             e.printStackTrace(); | ||||
|             System.exit(1); | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -1,12 +1,12 @@ | |||
| package jobshop; | ||||
| 
 | ||||
| public abstract class Encoding { | ||||
| 
 | ||||
|     public final Instance instance; | ||||
| 
 | ||||
|     public Encoding(Instance instance) { | ||||
|         this.instance = instance; | ||||
|     } | ||||
| 
 | ||||
|     public abstract Schedule toSchedule(); | ||||
| } | ||||
| package jobshop; | ||||
| 
 | ||||
| public abstract class Encoding { | ||||
| 
 | ||||
|     public final Instance instance; | ||||
| 
 | ||||
|     public Encoding(Instance instance) { | ||||
|         this.instance = instance; | ||||
|     } | ||||
| 
 | ||||
|     public abstract Schedule toSchedule(); | ||||
| } | ||||
|  |  | |||
|  | @ -1,73 +1,79 @@ | |||
| package jobshop; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.util.Iterator; | ||||
| import java.util.Scanner; | ||||
| import java.util.stream.Collectors; | ||||
| 
 | ||||
| public class Instance { | ||||
| 
 | ||||
|     /** Number of jobs in the instance */ | ||||
|     public final int numJobs; | ||||
| 
 | ||||
|     /** Number of tasks per job */ | ||||
|     public final int numTasks; | ||||
| 
 | ||||
|     /** Number of machines, assumed to be same as number of tasks. */ | ||||
|     public final int numMachines; | ||||
| 
 | ||||
|     final int[][] durations; | ||||
|     final int[][] machines; | ||||
| 
 | ||||
|     public int duration(int job, int task) { | ||||
|         return durations[job][task]; | ||||
|     } | ||||
|     public int machine(int job, int task) { | ||||
|         return machines[job][task]; | ||||
|     } | ||||
| 
 | ||||
|     /** among the tasks of the given job, returns the task index that uses the given machine. */ | ||||
|     public int task_with_machine(int job, int wanted_machine) { | ||||
|         for(int task = 0 ; task < numTasks ; task++) { | ||||
|             if(machine(job, task) == wanted_machine) | ||||
|                 return task; | ||||
|         } | ||||
|         throw new RuntimeException("No task targeting machine "+wanted_machine+" on job "+job); | ||||
|     } | ||||
| 
 | ||||
|     Instance(int numJobs, int numTasks) { | ||||
|         this.numJobs = numJobs; | ||||
|         this.numTasks = numTasks; | ||||
|         this.numMachines = numTasks; | ||||
| 
 | ||||
|         durations = new int[numJobs][numTasks]; | ||||
|         machines = new int[numJobs][numTasks]; | ||||
|     } | ||||
| 
 | ||||
|     public static Instance fromFile(Path path) throws IOException { | ||||
|         Iterator<String> lines = Files.readAllLines(path).stream() | ||||
|                 .filter(l -> !l.startsWith("#")) | ||||
|                 .collect(Collectors.toList()) | ||||
|                 .iterator(); | ||||
| 
 | ||||
|         Scanner header = new Scanner(lines.next()); | ||||
|         int num_jobs = header.nextInt(); | ||||
|         int num_tasks = header.nextInt(); | ||||
|         Instance pb = new Instance(num_jobs, num_tasks); | ||||
| 
 | ||||
|         for(int job = 0 ; job<num_jobs ; job++) { | ||||
|             Scanner line = new Scanner(lines.next()); | ||||
|             for(int task = 0 ; task < num_tasks ; task++) { | ||||
|                 pb.machines[job][task] = line.nextInt(); | ||||
|                 pb.durations[job][task] = line.nextInt(); | ||||
|             } | ||||
|             line.close(); | ||||
|         } | ||||
| 
 | ||||
|         header.close(); | ||||
|   | ||||
|         return pb; | ||||
|     } | ||||
| } | ||||
| package jobshop; | ||||
| 
 | ||||
| import jobshop.encodings.Task; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.util.Iterator; | ||||
| import java.util.Scanner; | ||||
| import java.util.stream.Collectors; | ||||
| 
 | ||||
| public class Instance { | ||||
| 
 | ||||
|     /** Number of jobs in the instance */ | ||||
|     public final int numJobs; | ||||
| 
 | ||||
|     /** Number of tasks per job */ | ||||
|     public final int numTasks; | ||||
| 
 | ||||
|     /** Number of machines, assumed to be same as number of tasks. */ | ||||
|     public final int numMachines; | ||||
| 
 | ||||
|     final int[][] durations; | ||||
|     final int[][] machines; | ||||
| 
 | ||||
|     public int duration(int job, int task) { | ||||
|         return durations[job][task]; | ||||
|     } | ||||
|     public int duration(Task t) { | ||||
|         return duration(t.job, t.task); | ||||
|     } | ||||
|     public int machine(int job, int task) { | ||||
|         return machines[job][task]; | ||||
|     } | ||||
|     public int machine(Task t) { | ||||
|         return this.machine(t.job, t.task); | ||||
|     } | ||||
| 
 | ||||
|     /** among the tasks of the given job, returns the task index that uses the given machine. */ | ||||
|     public int task_with_machine(int job, int wanted_machine) { | ||||
|         for(int task = 0 ; task < numTasks ; task++) { | ||||
|             if(machine(job, task) == wanted_machine) | ||||
|                 return task; | ||||
|         } | ||||
|         throw new RuntimeException("No task targeting machine "+wanted_machine+" on job "+job); | ||||
|     } | ||||
| 
 | ||||
|     Instance(int numJobs, int numTasks) { | ||||
|         this.numJobs = numJobs; | ||||
|         this.numTasks = numTasks; | ||||
|         this.numMachines = numTasks; | ||||
| 
 | ||||
|         durations = new int[numJobs][numTasks]; | ||||
|         machines = new int[numJobs][numTasks]; | ||||
|     } | ||||
| 
 | ||||
|     /** Parses a instance from a file. */ | ||||
|     public static Instance fromFile(Path path) throws IOException { | ||||
|         Iterator<String> lines = Files.readAllLines(path).stream() | ||||
|                 .filter(l -> !l.startsWith("#")) | ||||
|                 .collect(Collectors.toList()) | ||||
|                 .iterator(); | ||||
| 
 | ||||
|         Scanner header = new Scanner(lines.next()); | ||||
|         int num_jobs = header.nextInt(); | ||||
|         int num_tasks = header.nextInt(); | ||||
|         Instance pb = new Instance(num_jobs, num_tasks); | ||||
| 
 | ||||
|         for(int job = 0 ; job<num_jobs ; job++) { | ||||
|             Scanner line = new Scanner(lines.next()); | ||||
|             for(int task = 0 ; task < num_tasks ; task++) { | ||||
|                 pb.machines[job][task] = line.nextInt(); | ||||
|                 pb.durations[job][task] = line.nextInt(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return pb; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -1,154 +1,223 @@ | |||
| package jobshop; | ||||
| 
 | ||||
| import java.io.PrintStream; | ||||
| import java.nio.file.Path; | ||||
| import java.nio.file.Paths; | ||||
| import java.util.Arrays; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| 
 | ||||
| 
 | ||||
| import jobshop.solvers.BasicSolver; | ||||
| import jobshop.solvers.RandomSolver; | ||||
| import jobshop.solvers.GreedySolver.PriorityESTRule; | ||||
| import jobshop.solvers.GreedySolver.PriorityRule; | ||||
| import jobshop.solvers.GreedySolver; | ||||
| import net.sourceforge.argparse4j.ArgumentParsers; | ||||
| import net.sourceforge.argparse4j.inf.ArgumentParser; | ||||
| import net.sourceforge.argparse4j.inf.ArgumentParserException; | ||||
| import net.sourceforge.argparse4j.inf.Namespace; | ||||
| 
 | ||||
| 
 | ||||
| public class Main { | ||||
| 
 | ||||
|     /** All solvers available in this program */ | ||||
|     private static HashMap<String, Solver> solvers; | ||||
|     static { | ||||
|         solvers = new HashMap<>(); | ||||
|         solvers.put("basic", new BasicSolver()); | ||||
|         solvers.put("random", new RandomSolver()); | ||||
|         // add new solvers here | ||||
|         PriorityRule SPT = PriorityRule.SPT; | ||||
|         solvers.put("greedySPT", new GreedySolver(SPT)); | ||||
|         PriorityRule LRPT = PriorityRule.LRPT; | ||||
|         solvers.put("greedyLRPT", new GreedySolver(LRPT)); | ||||
|         PriorityESTRule EST_SPT = PriorityESTRule.EST_SPT; | ||||
|         solvers.put("greedyEST_SPT", new GreedySolver(EST_SPT)); | ||||
|         PriorityESTRule EST_LRPT = PriorityESTRule.EST_LRPT; | ||||
|         solvers.put("greedyEST_LRPT", new GreedySolver(EST_LRPT)); | ||||
|     } | ||||
| 
 | ||||
|     @SuppressWarnings("unused") | ||||
| 	public static void main(String[] args) { | ||||
|         ArgumentParser parser = ArgumentParsers.newFor("jsp-solver").build() | ||||
|                 .defaultHelp(true) | ||||
|                 .description("Solves jobshop problems."); | ||||
| 
 | ||||
|         parser.addArgument("-t", "--timeout") | ||||
|                 .setDefault(1L) | ||||
|                 .type(Long.class) | ||||
|                 .help("Solver timeout in seconds for each instance"); | ||||
|         parser.addArgument("--solver") | ||||
|                 .nargs("+") | ||||
|                 .required(true) | ||||
|                 .help("Solver(s) to use (space separated if more than one)"); | ||||
| 
 | ||||
|         parser.addArgument("--instance") | ||||
|                 .nargs("+") | ||||
|                 .required(true) | ||||
|                 .help("Instance(s) to solve (space separated if more than one)"); | ||||
| 
 | ||||
|         Namespace ns = null; | ||||
|         try { | ||||
|             ns = parser.parseArgs(args); | ||||
|         } catch (ArgumentParserException e) { | ||||
|             parser.handleError(e); | ||||
|             System.exit(1); | ||||
|         } | ||||
| 
 | ||||
|         PrintStream output = System.out; | ||||
| 
 | ||||
|         long solveTimeMs = ns.getLong("timeout") * 1000; | ||||
| 
 | ||||
|         List<String> solversToTest = ns.getList("solver"); | ||||
|         for(String solverName : solversToTest) { | ||||
|             if(!solvers.containsKey(solverName)) { | ||||
|                 System.err.println("ERROR: Solver \"" + solverName + "\" is not avalaible."); | ||||
|                 System.err.println("       Available solvers: " + solvers.keySet().toString()); | ||||
|                 System.err.println("       You can provide your own solvers by adding them to the `Main.solvers` HashMap."); | ||||
|                 System.exit(1); | ||||
|             } | ||||
|         } | ||||
|         List<String> instances = ns.<String>getList("instance"); | ||||
|         for(String instanceName : instances) { | ||||
|             if(!BestKnownResult.isKnown(instanceName)) { | ||||
|                 System.err.println("ERROR: instance \"" + instanceName + "\" is not avalaible."); | ||||
|                 System.err.println("       available instances: " + Arrays.toString(BestKnownResult.instances)); | ||||
|                 System.exit(1); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         float[] runtimes = new float[solversToTest.size()]; | ||||
|         float[] distances = new float[solversToTest.size()]; | ||||
| 
 | ||||
|         try { | ||||
|             output.print(  "                         ");; | ||||
|             for(String s : solversToTest) | ||||
|                 output.printf("%-30s", s); | ||||
|             output.println(); | ||||
|             output.print("instance size  best      "); | ||||
|             for(String s : solversToTest) { | ||||
|                 output.print("runtime makespan ecart        "); | ||||
|             } | ||||
|             output.println(); | ||||
| 
 | ||||
| 
 | ||||
|         for(String instanceName : instances) { | ||||
|             int bestKnown = BestKnownResult.of(instanceName); | ||||
| 
 | ||||
| 
 | ||||
|             Path path = Paths.get("instances/", instanceName); | ||||
|             Instance instance = Instance.fromFile(path); | ||||
| 
 | ||||
|             output.printf("%-8s %-5s %4d      ",instanceName, instance.numJobs +"x"+instance.numTasks, bestKnown); | ||||
| 
 | ||||
|             for(int solverId = 0 ; solverId < solversToTest.size() ; solverId++) { | ||||
|                 String solverName = solversToTest.get(solverId); | ||||
|                 Solver solver = solvers.get(solverName); | ||||
|                 long start = System.currentTimeMillis(); | ||||
|                 long deadline = System.currentTimeMillis() + solveTimeMs; | ||||
|                 Result result = solver.solve(instance, deadline); | ||||
|                 long runtime = System.currentTimeMillis() - start; | ||||
| 
 | ||||
|                 if(!result.schedule.isValid()) { | ||||
|                     System.err.println("ERROR: solver returned an invalid schedule"); | ||||
|                     System.exit(1); | ||||
|                 } | ||||
| 
 | ||||
|                 assert result.schedule.isValid(); | ||||
|                 int makespan = result.schedule.makespan(); | ||||
|                 float dist = 100f * (makespan - bestKnown) / (float) bestKnown; | ||||
|                 runtimes[solverId] += (float) runtime / (float) instances.size(); | ||||
|                 distances[solverId] += dist / (float) instances.size(); | ||||
| 
 | ||||
|                 output.printf("%7d %8s %5.1f        ", runtime, makespan, dist); | ||||
|                 output.flush(); | ||||
|             } | ||||
|             output.println(); | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         output.printf("%-8s %-5s %4s      ", "AVG", "-", "-"); | ||||
|         for(int solverId = 0 ; solverId < solversToTest.size() ; solverId++) { | ||||
|             output.printf("%7.1f %8s %5.1f        ", runtimes[solverId], "-", distances[solverId]); | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         } catch (Exception e) { | ||||
|             e.printStackTrace(); | ||||
|             System.exit(1); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| package jobshop; | ||||
| 
 | ||||
| import java.io.PrintStream; | ||||
| import java.nio.file.Path; | ||||
| import java.nio.file.Paths; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Arrays; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| 
 | ||||
| 
 | ||||
| import jobshop.solvers.*; | ||||
| import jobshop.solvers.GreedySolver.PriorityESTRule; | ||||
| import jobshop.solvers.GreedySolver.PriorityRule; | ||||
| import net.sourceforge.argparse4j.ArgumentParsers; | ||||
| import net.sourceforge.argparse4j.inf.ArgumentParser; | ||||
| import net.sourceforge.argparse4j.inf.ArgumentParserException; | ||||
| import net.sourceforge.argparse4j.inf.Namespace; | ||||
| 
 | ||||
| 
 | ||||
| public class Main { | ||||
| 	// ******************************************** Main - Arguments ************************************************ // | ||||
| 	// *** Basic + Random *** // | ||||
| 	// --solver basic random --instance aaa1 ft06 ft10 ft20 la01 la02 la03 la04 la05 la06 la07 la08 la09 | ||||
| 	 | ||||
| 	// *** Greedy Solvers *** //  | ||||
| 	// --solver Greedy-SPT Greedy-LRPT Greedy-EST_SPT Greedy-EST_LRPT --instance aaa1 ft06 ft10 ft20 la01 la02 la03 la04 la05 la06 la07 la08 la09 | ||||
| 	 | ||||
| 	// *** Descent Solvers *** // | ||||
| 	// --solver Descent-SPT Descent-LRPT Descent-EST_SPT Descent-EST_LRPT --instance aaa1 ft06 ft10 ft20 la01 la02 la03 la04 la05 la06 la07 la08 la09 | ||||
| 	 | ||||
| 	// *** Taboo Solvers *** // | ||||
| 	// --solver Taboo-EST_LRPT(1,1) --instance aaa1 ft06 ft10 ft20 la01 la02 la03 la04 la05 la06 la07 la08 la09 | ||||
| 	// --solver Taboo-EST_LRPT(1,10) Taboo-EST_LRPT(2,10) Taboo-EST_LRPT(3,10) Taboo-EST_LRPT(4,10) Taboo-EST_LRPT(5,10) Taboo-EST_LRPT(6,10) Taboo-EST_LRPT(7,10) Taboo-EST_LRPT(8,10) Taboo-EST_LRPT(9,10) Taboo-EST_LRPT(10,10) --instance aaa1 ft06 ft10 ft20 la01 la02 la03 la04 la05 la06 la07 la08 la09 | ||||
| 	// --solver Taboo-EST_LRPT(1,100) Taboo-EST_LRPT(6,100) Taboo-EST_LRPT(8,100) Taboo-EST_LRPT(10,100) Taboo-EST_LRPT(12,100) Taboo-EST_LRPT(14,100) Taboo-EST_LRPT(20,100) Taboo-EST_LRPT(50,100) Taboo-EST_LRPT(100,100) --instance aaa1 ft06 ft10 ft20 la01 la02 la03 la04 la05 la06 la07 la08 la09 | ||||
| 	// --solver Taboo-EST_LRPT(1,1000) Taboo-EST_LRPT(6,1000) Taboo-EST_LRPT(8,1000) Taboo-EST_LRPT(10,1000) Taboo-EST_LRPT(12,1000) Taboo-EST_LRPT(14,1000) Taboo-EST_LRPT(20,1000) Taboo-EST_LRPT(50,1000) Taboo-EST_LRPT(100,1000) --instance aaa1 ft06 ft10 ft20 la01 la02 la03 la04 la05 la06 la07 la08 la09 | ||||
| 	// --solver Taboo-EST_LRPT(1,5000) Taboo-EST_LRPT(6,5000) Taboo-EST_LRPT(8,5000) Taboo-EST_LRPT(10,5000) Taboo-EST_LRPT(12,5000) Taboo-EST_LRPT(14,5000) Taboo-EST_LRPT(20,5000) Taboo-EST_LRPT(50,5000) Taboo-EST_LRPT(100,5000) --instance aaa1 ft06 ft10 ft20 la01 la02 la03 la04 la05 la06 la07 la08 la09 | ||||
| 	 | ||||
| 	/** All solvers available in this program */ | ||||
|     private static HashMap<String, Solver> solvers; | ||||
|     static { | ||||
|         solvers = new HashMap<>(); | ||||
|         solvers.put("basic", new BasicSolver()); | ||||
|         solvers.put("random", new RandomSolver()); | ||||
|         // Add new solvers here | ||||
|         // ******************** Greedy Solver ******************** // | ||||
|         PriorityRule SPT = PriorityRule.SPT; | ||||
|         solvers.put("Greedy-SPT", new GreedySolver(SPT)); | ||||
|         PriorityRule LRPT = PriorityRule.LRPT; | ||||
|         solvers.put("Greedy-LRPT", new GreedySolver(LRPT)); | ||||
|         PriorityESTRule EST_SPT = PriorityESTRule.EST_SPT; | ||||
|         solvers.put("Greedy-EST_SPT", new GreedySolver(EST_SPT)); | ||||
|         PriorityESTRule EST_LRPT = PriorityESTRule.EST_LRPT; | ||||
|         solvers.put("Greedy-EST_LRPT", new GreedySolver(EST_LRPT)); | ||||
|          | ||||
|         // ******************* Descent Solver ******************** // | ||||
|         solvers.put("Descent-SPT",      new DescentSolver(SPT)); | ||||
|         solvers.put("Descent-LRPT",     new DescentSolver(LRPT)); | ||||
|         solvers.put("Descent-EST_SPT",  new DescentSolver(EST_SPT)); | ||||
|         solvers.put("Descent-EST_LRPT", new DescentSolver(EST_LRPT)); | ||||
|          | ||||
|         // ******************** Taboo Solver ********************* // | ||||
|         solvers.put("Taboo-EST_LRPT(1,1)",   new TabooSolver(EST_LRPT, 1, 1)); | ||||
|          | ||||
|         solvers.put("Taboo-EST_LRPT(1,10)",  new TabooSolver(EST_LRPT, 1, 10)); | ||||
|         solvers.put("Taboo-EST_LRPT(2,10)",  new TabooSolver(EST_LRPT, 2, 10)); | ||||
|         solvers.put("Taboo-EST_LRPT(3,10)",  new TabooSolver(EST_LRPT, 3, 10)); | ||||
|         solvers.put("Taboo-EST_LRPT(4,10)",  new TabooSolver(EST_LRPT, 4, 10)); | ||||
|         solvers.put("Taboo-EST_LRPT(5,10)",  new TabooSolver(EST_LRPT, 5, 10)); | ||||
|         solvers.put("Taboo-EST_LRPT(6,10)",  new TabooSolver(EST_LRPT, 6, 10)); | ||||
|         solvers.put("Taboo-EST_LRPT(7,10)",  new TabooSolver(EST_LRPT, 7, 10)); | ||||
|         solvers.put("Taboo-EST_LRPT(8,10)",  new TabooSolver(EST_LRPT, 8, 10)); | ||||
|         solvers.put("Taboo-EST_LRPT(9,10)",  new TabooSolver(EST_LRPT, 9, 10)); | ||||
|         solvers.put("Taboo-EST_LRPT(10,10)", new TabooSolver(EST_LRPT, 10, 10)); | ||||
|          | ||||
|         solvers.put("Taboo-EST_LRPT(1,100)",   new TabooSolver(EST_LRPT, 1, 100)); | ||||
|         solvers.put("Taboo-EST_LRPT(6,100)",   new TabooSolver(EST_LRPT, 6, 100)); | ||||
|         solvers.put("Taboo-EST_LRPT(8,100)",   new TabooSolver(EST_LRPT, 8, 100)); | ||||
|         solvers.put("Taboo-EST_LRPT(10,100)",  new TabooSolver(EST_LRPT, 10, 100)); | ||||
|         solvers.put("Taboo-EST_LRPT(12,100)",  new TabooSolver(EST_LRPT, 12, 100)); | ||||
|         solvers.put("Taboo-EST_LRPT(14,100)",  new TabooSolver(EST_LRPT, 14, 100)); | ||||
|         solvers.put("Taboo-EST_LRPT(20,100)",  new TabooSolver(EST_LRPT, 20, 100)); | ||||
|         solvers.put("Taboo-EST_LRPT(50,100)",  new TabooSolver(EST_LRPT, 50, 100)); | ||||
|         solvers.put("Taboo-EST_LRPT(100,100)", new TabooSolver(EST_LRPT, 100, 100)); | ||||
|          | ||||
|         solvers.put("Taboo-EST_LRPT(1,1000)",   new TabooSolver(EST_LRPT, 1, 1000)); | ||||
|         solvers.put("Taboo-EST_LRPT(6,1000)",   new TabooSolver(EST_LRPT, 6, 1000)); | ||||
|         solvers.put("Taboo-EST_LRPT(8,1000)",   new TabooSolver(EST_LRPT, 8, 1000)); | ||||
|         solvers.put("Taboo-EST_LRPT(10,1000)",  new TabooSolver(EST_LRPT, 10, 1000)); | ||||
|         solvers.put("Taboo-EST_LRPT(12,1000)",  new TabooSolver(EST_LRPT, 12, 1000)); | ||||
|         solvers.put("Taboo-EST_LRPT(14,1000)",  new TabooSolver(EST_LRPT, 14, 1000)); | ||||
|         solvers.put("Taboo-EST_LRPT(20,1000)",  new TabooSolver(EST_LRPT, 20, 1000)); | ||||
|         solvers.put("Taboo-EST_LRPT(50,1000)",  new TabooSolver(EST_LRPT, 50, 1000)); | ||||
|         solvers.put("Taboo-EST_LRPT(100,1000)", new TabooSolver(EST_LRPT, 100, 1000)); | ||||
|          | ||||
|         solvers.put("Taboo-EST_LRPT(1,5000)",   new TabooSolver(EST_LRPT, 1, 5000)); | ||||
|         solvers.put("Taboo-EST_LRPT(6,5000)",   new TabooSolver(EST_LRPT, 6, 5000)); | ||||
|         solvers.put("Taboo-EST_LRPT(8,5000)",   new TabooSolver(EST_LRPT, 8, 5000)); | ||||
|         solvers.put("Taboo-EST_LRPT(10,5000)",  new TabooSolver(EST_LRPT, 10, 5000)); | ||||
|         solvers.put("Taboo-EST_LRPT(12,5000)",  new TabooSolver(EST_LRPT, 12, 5000)); | ||||
|         solvers.put("Taboo-EST_LRPT(14,5000)",  new TabooSolver(EST_LRPT, 14, 5000)); | ||||
|         solvers.put("Taboo-EST_LRPT(20,5000)",  new TabooSolver(EST_LRPT, 20, 5000)); | ||||
|         solvers.put("Taboo-EST_LRPT(50,5000)",  new TabooSolver(EST_LRPT, 50, 5000)); | ||||
|         solvers.put("Taboo-EST_LRPT(100,5000)", new TabooSolver(EST_LRPT, 100, 5000));      | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     public static void main(String[] args) { | ||||
|         ArgumentParser parser = ArgumentParsers.newFor("jsp-solver").build() | ||||
|                 .defaultHelp(true) | ||||
|                 .description("Solves jobshop problems."); | ||||
| 
 | ||||
|         parser.addArgument("-t", "--timeout") | ||||
|                 .setDefault(1L) | ||||
|                 .type(Long.class) | ||||
|                 .help("Solver timeout in seconds for each instance"); | ||||
|         parser.addArgument("--solver") | ||||
|                 .nargs("+") | ||||
|                 .required(true) | ||||
|                 .help("Solver(s) to use (space separated if more than one)"); | ||||
| 
 | ||||
|         parser.addArgument("--instance") | ||||
|                 .nargs("+") | ||||
|                 .required(true) | ||||
|                 .help("Instance(s) to solve (space separated if more than one)"); | ||||
| 
 | ||||
|         Namespace ns = null; | ||||
|         try { | ||||
|             ns = parser.parseArgs(args); | ||||
|         } catch (ArgumentParserException e) { | ||||
|             parser.handleError(e); | ||||
|             System.exit(1); | ||||
|         } | ||||
| 
 | ||||
|         PrintStream output = System.out; | ||||
| 
 | ||||
|         long solveTimeMs = ns.getLong("timeout") * 1000; | ||||
| 
 | ||||
|         List<String> solversToTest = ns.getList("solver"); | ||||
|         for(String solverName : solversToTest) { | ||||
|             if(!solvers.containsKey(solverName)) { | ||||
|                 System.err.println("ERROR: Solver \"" + solverName + "\" is not avalaible."); | ||||
|                 System.err.println("       Available solvers: " + solvers.keySet().toString()); | ||||
|                 System.err.println("       You can provide your own solvers by adding them to the `Main.solvers` HashMap."); | ||||
|                 System.exit(1); | ||||
|             } | ||||
|         } | ||||
|         List<String> instancePrefixes = ns.getList("instance"); | ||||
|         List<String> instances = new ArrayList<>(); | ||||
|         for(String instancePrefix : instancePrefixes) { | ||||
|             List<String> matches = BestKnownResult.instancesMatching(instancePrefix); | ||||
|             if(matches.isEmpty()) { | ||||
|                 System.err.println("ERROR: instance prefix \"" + instancePrefix + "\" does not match any instance."); | ||||
|                 System.err.println("       available instances: " + Arrays.toString(BestKnownResult.instances)); | ||||
|                 System.exit(1); | ||||
|             } | ||||
|             instances.addAll(matches); | ||||
|         } | ||||
| 
 | ||||
|         float[] runtimes = new float[solversToTest.size()]; | ||||
|         float[] distances = new float[solversToTest.size()]; | ||||
| 
 | ||||
|         try { | ||||
|             output.print(  "                         "); | ||||
|             for(String s : solversToTest) | ||||
|                 output.printf("%-30s", s); | ||||
|             output.println(); | ||||
|             output.print("instance size  best      "); | ||||
|             for(String s : solversToTest) { | ||||
|                 output.print("runtime makespan ecart        "); | ||||
|             } | ||||
|             output.println(); | ||||
| 
 | ||||
| 
 | ||||
|             for(String instanceName : instances) { | ||||
|                 int bestKnown = BestKnownResult.of(instanceName); | ||||
| 
 | ||||
| 
 | ||||
|                 Path path = Paths.get("instances/", instanceName); | ||||
|                 Instance instance = Instance.fromFile(path); | ||||
| 
 | ||||
|                 output.printf("%-8s %-5s %4d      ",instanceName, instance.numJobs +"x"+instance.numTasks, bestKnown); | ||||
| 
 | ||||
|                 for(int solverId = 0 ; solverId < solversToTest.size() ; solverId++) { | ||||
|                     String solverName = solversToTest.get(solverId); | ||||
|                     Solver solver = solvers.get(solverName); | ||||
|                     long start = System.currentTimeMillis(); | ||||
|                     long deadline = System.currentTimeMillis() + solveTimeMs; | ||||
|                     Result result = solver.solve(instance, deadline); | ||||
|                     long runtime = System.currentTimeMillis() - start; | ||||
| 
 | ||||
|                     if(!result.schedule.isValid()) { | ||||
|                         System.err.println("ERROR: solver returned an invalid schedule"); | ||||
|                         System.exit(1); | ||||
|                     } | ||||
| 
 | ||||
|                     assert result.schedule.isValid(); | ||||
|                     int makespan = result.schedule.makespan(); | ||||
|                     float dist = 100f * (makespan - bestKnown) / (float) bestKnown; | ||||
|                     runtimes[solverId] += (float) runtime / (float) instances.size(); | ||||
|                     distances[solverId] += dist / (float) instances.size(); | ||||
| 
 | ||||
|                     output.printf("%7d %8s %5.1f        ", runtime, makespan, dist); | ||||
|                     output.flush(); | ||||
|                 } | ||||
|                 output.println(); | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
| 
 | ||||
|             output.printf("%-8s %-5s %4s      ", "AVG", "-", "-"); | ||||
|             for(int solverId = 0 ; solverId < solversToTest.size() ; solverId++) { | ||||
|                 output.printf("%7.1f %8s %5.1f        ", runtimes[solverId], "-", distances[solverId]); | ||||
|             } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         } catch (Exception e) { | ||||
|             e.printStackTrace(); | ||||
|             System.exit(1); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -1,23 +1,20 @@ | |||
| package jobshop; | ||||
| 
 | ||||
| import java.util.Optional; | ||||
| 
 | ||||
| @SuppressWarnings("unused") | ||||
| public class Result { | ||||
| 
 | ||||
|     public Result(Instance instance, Schedule schedule, ExitCause cause) { | ||||
|         this.instance = instance; | ||||
|         this.schedule = schedule; | ||||
|         this.cause = cause; | ||||
|     } | ||||
| 
 | ||||
|     public enum ExitCause { | ||||
|         Timeout, ProvedOptimal, Blocked | ||||
|     } | ||||
| 
 | ||||
|     public final Instance instance; | ||||
|     public final Schedule schedule; | ||||
|     public final ExitCause cause; | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| package jobshop; | ||||
| 
 | ||||
| public class Result { | ||||
| 
 | ||||
|     public Result(Instance instance, Schedule schedule, ExitCause cause) { | ||||
|         this.instance = instance; | ||||
|         this.schedule = schedule; | ||||
|         this.cause = cause; | ||||
|     } | ||||
| 
 | ||||
|     public enum ExitCause { | ||||
|         Timeout, ProvedOptimal, Blocked | ||||
|     } | ||||
| 
 | ||||
|     public final Instance instance; | ||||
|     public final Schedule schedule; | ||||
|     public final ExitCause cause; | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -1,157 +1,153 @@ | |||
| package jobshop; | ||||
| 
 | ||||
| 
 | ||||
| import java.util.Arrays; | ||||
| import java.util.Comparator; | ||||
| import java.util.LinkedList; | ||||
| import java.util.List; | ||||
| import java.util.Optional; | ||||
| import java.util.stream.IntStream; | ||||
| 
 | ||||
| import jobshop.encodings.Task; | ||||
| 
 | ||||
| public class Schedule { | ||||
|     public final Instance pb; | ||||
|     // start times of each job and task | ||||
|     // times[j][i] is the start time of task (j,i) : i^th task of the j^th job | ||||
|     final int[][] times; | ||||
| 
 | ||||
|     public Schedule(Instance pb, int[][] times) { | ||||
|         this.pb = pb; | ||||
|         this.times = new int[pb.numJobs][]; | ||||
|         for(int j = 0 ; j < pb.numJobs ; j++) { | ||||
|             this.times[j] = Arrays.copyOf(times[j], pb.numTasks); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public int startTime(int job, int task) { | ||||
|         return times[job][task]; | ||||
|     } | ||||
| 
 | ||||
|     /** Returns true if this schedule is valid (no constraint is violated) */ | ||||
|     public boolean isValid() { | ||||
|         for(int j = 0 ; j<pb.numJobs ; j++) { | ||||
|             for(int t = 1 ; t<pb.numTasks ; t++) { | ||||
|                 if(startTime(j, t-1) + pb.duration(j, t-1) > startTime(j, t)) | ||||
|                     return false; | ||||
|             } | ||||
|             for(int t = 0 ; t<pb.numTasks ; t++) { | ||||
|                 if(startTime(j, t) < 0) | ||||
|                     return false; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         for (int machine = 0 ; machine < pb.numMachines ; machine++) { | ||||
|             for(int j1=0 ; j1<pb.numJobs ; j1++) { | ||||
|                 int t1 = pb.task_with_machine(j1, machine); | ||||
|                 for(int j2=j1+1 ; j2<pb.numJobs ; j2++) { | ||||
|                     int t2 = pb.task_with_machine(j2, machine); | ||||
| 
 | ||||
|                     boolean t1_first = startTime(j1, t1) + pb.duration(j1, t1) <= startTime(j2, t2); | ||||
|                     boolean t2_first = startTime(j2, t2) + pb.duration(j2, t2) <= startTime(j1, t1); | ||||
| 
 | ||||
|                     if(!t1_first && !t2_first) | ||||
|                         return false; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     public int makespan() { | ||||
|         int max = -1; | ||||
|         for(int j = 0 ; j<pb.numJobs ; j++) { | ||||
|             max = Math.max(max, startTime(j, pb.numTasks-1) + pb.duration(j, pb.numTasks -1)); | ||||
|         } | ||||
|         return max; | ||||
|     } | ||||
|      | ||||
|     public int startTime(Task task) { | ||||
|         return startTime(task.job, task.task); | ||||
|     } | ||||
| 
 | ||||
|     public int endTime(Task task) { | ||||
|         return startTime(task) + pb.duration(task.job, task.task); | ||||
|     } | ||||
|      | ||||
|     public boolean isCriticalPath(List<Task> path) { | ||||
|         if(startTime(path.get(0)) != 0) { | ||||
|             return false; | ||||
|         } | ||||
|         if(endTime(path.get(path.size()-1)) != makespan()) { | ||||
|             return false; | ||||
|         } | ||||
|         for(int i=0 ; i<path.size()-1 ; i++) { | ||||
|             if(endTime(path.get(i)) != startTime(path.get(i+1))) | ||||
|                 return false; | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     public List<Task> criticalPath() { | ||||
|         // select task with greatest end time | ||||
|         Task ldd = IntStream.range(0, pb.numJobs) | ||||
|                 .mapToObj(j -> new Task(j, pb.numTasks-1)) | ||||
|                 .max(Comparator.comparing(this::endTime)) | ||||
|                 .get(); | ||||
|         assert endTime(ldd) == makespan(); | ||||
| 
 | ||||
|         // list that will contain the critical path. | ||||
|         // we construct it from the end, starting with the | ||||
|         // task that finishes last | ||||
|         LinkedList<Task> path = new LinkedList<>(); | ||||
|         path.add(0,ldd); | ||||
| 
 | ||||
|         // keep adding tasks to the path until the first task in the path | ||||
|         // starts a time 0 | ||||
|         while(startTime(path.getFirst()) != 0) { | ||||
|             Task cur = path.getFirst(); | ||||
|             int machine = pb.machine(cur.job, cur.task); | ||||
| 
 | ||||
|             // will contain the task that was delaying the start | ||||
|             // of our current task | ||||
|             Optional<Task> latestPredecessor = Optional.empty(); | ||||
| 
 | ||||
|             if(cur.task > 0) { | ||||
|                 // our current task has a predecessor on the job | ||||
|                 Task predOnJob = new Task(cur.job, cur.task -1); | ||||
| 
 | ||||
|                 // if it was the delaying task, save it to predecessor | ||||
|                 if(endTime(predOnJob) == startTime(cur)) | ||||
|                     latestPredecessor = Optional.of(predOnJob); | ||||
|             } | ||||
|             if(!latestPredecessor.isPresent()) { | ||||
|                 // no latest predecessor found yet, look among tasks executing on the same machine | ||||
|                 latestPredecessor = IntStream.range(0, pb.numJobs) | ||||
|                         .mapToObj(j -> new Task(j, pb.task_with_machine(j, machine))) | ||||
|                         .filter(t -> endTime(t) == startTime(cur)) | ||||
|                         .findFirst(); | ||||
|             } | ||||
|             // at this point we should have identified a latest predecessor, either on the job or on the machine | ||||
|             assert latestPredecessor.isPresent() && endTime(latestPredecessor.get()) == startTime(cur); | ||||
|             // insert predecessor at the beginning of the path | ||||
|             path.add(0, latestPredecessor.get()); | ||||
|         } | ||||
|         assert isCriticalPath(path); | ||||
|         return path; | ||||
|     } | ||||
| 
 | ||||
|     public Schedule copy() { | ||||
|         return new Schedule(this.pb, this.times); | ||||
|     } | ||||
|      | ||||
|     /****************************************************************/ | ||||
|     /* Implémentation de la méthode toString() de la classe Schedule*/ | ||||
|     /****************************************************************/ | ||||
|     public String toString() { | ||||
|     	String res = ""; | ||||
|     	for (int i = 0; i < this.times.length; i++) { | ||||
|     		res += "Job " + Integer.toString(i + 1) + " starting times : \n"; | ||||
|     		for (int j = 0; j < this.times[i].length; j++) { | ||||
|     			res += "\tTask " + Integer.toString(j + 1) + " starts at time : " + Integer.toString(this.times[i][j]) + "\n"; | ||||
|     		} | ||||
|     	} | ||||
|     	return res; | ||||
|     } | ||||
| } | ||||
| package jobshop; | ||||
| 
 | ||||
| 
 | ||||
| import jobshop.encodings.Task; | ||||
| 
 | ||||
| import java.util.*; | ||||
| import java.util.stream.IntStream; | ||||
| 
 | ||||
| public class Schedule { | ||||
|     public final Instance pb; | ||||
|     // start times of each job and task | ||||
|     // times[j][i] is the start time of task (j,i) : i^th task of the j^th job | ||||
|     final int[][] times; | ||||
| 
 | ||||
|     public Schedule(Instance pb, int[][] times) { | ||||
|         this.pb = pb; | ||||
|         this.times = new int[pb.numJobs][]; | ||||
|         for(int j = 0 ; j < pb.numJobs ; j++) { | ||||
|             this.times[j] = Arrays.copyOf(times[j], pb.numTasks); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public int startTime(int job, int task) { | ||||
|         return times[job][task]; | ||||
|     } | ||||
| 
 | ||||
|     /** Returns true if this schedule is valid (no constraint is violated) */ | ||||
|     public boolean isValid() { | ||||
|         for(int j = 0 ; j<pb.numJobs ; j++) { | ||||
|             for(int t = 1 ; t<pb.numTasks ; t++) { | ||||
|                 if(startTime(j, t-1) + pb.duration(j, t-1) > startTime(j, t)) | ||||
|                     return false; | ||||
|             } | ||||
|             for(int t = 0 ; t<pb.numTasks ; t++) { | ||||
|                 if(startTime(j, t) < 0) | ||||
|                     return false; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         for (int machine = 0 ; machine < pb.numMachines ; machine++) { | ||||
|             for(int j1=0 ; j1<pb.numJobs ; j1++) { | ||||
|                 int t1 = pb.task_with_machine(j1, machine); | ||||
|                 for(int j2=j1+1 ; j2<pb.numJobs ; j2++) { | ||||
|                     int t2 = pb.task_with_machine(j2, machine); | ||||
| 
 | ||||
|                     boolean t1_first = startTime(j1, t1) + pb.duration(j1, t1) <= startTime(j2, t2); | ||||
|                     boolean t2_first = startTime(j2, t2) + pb.duration(j2, t2) <= startTime(j1, t1); | ||||
| 
 | ||||
|                     if(!t1_first && !t2_first) | ||||
|                         return false; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     public int makespan() { | ||||
|         int max = -1; | ||||
|         for(int j = 0 ; j<pb.numJobs ; j++) { | ||||
|             max = Math.max(max, startTime(j, pb.numTasks-1) + pb.duration(j, pb.numTasks -1)); | ||||
|         } | ||||
|         return max; | ||||
|     } | ||||
| 
 | ||||
|     public int startTime(Task task) { | ||||
|         return startTime(task.job, task.task); | ||||
|     } | ||||
| 
 | ||||
|     public int endTime(Task task) { | ||||
|         return startTime(task) + pb.duration(task.job, task.task); | ||||
|     } | ||||
| 
 | ||||
|     public boolean isCriticalPath(List<Task> path) { | ||||
|         if(startTime(path.get(0)) != 0) { | ||||
|             return false; | ||||
|         } | ||||
|         if(endTime(path.get(path.size()-1)) != makespan()) { | ||||
|             return false; | ||||
|         } | ||||
|         for(int i=0 ; i<path.size()-1 ; i++) { | ||||
|             if(endTime(path.get(i)) != startTime(path.get(i+1))) | ||||
|                 return false; | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     public List<Task> criticalPath() { | ||||
|         // select task with greatest end time | ||||
|         Task ldd = IntStream.range(0, pb.numJobs) | ||||
|                 .mapToObj(j -> new Task(j, pb.numTasks-1)) | ||||
|                 .max(Comparator.comparing(this::endTime)) | ||||
|                 .get(); | ||||
|         assert endTime(ldd) == makespan(); | ||||
| 
 | ||||
|         // list that will contain the critical path. | ||||
|         // we construct it from the end, starting with the | ||||
|         // task that finishes last | ||||
|         LinkedList<Task> path = new LinkedList<>(); | ||||
|         path.add(0,ldd); | ||||
| 
 | ||||
|         // keep adding tasks to the path until the first task in the path | ||||
|         // starts a time 0 | ||||
|         while(startTime(path.getFirst()) != 0) { | ||||
|             Task cur = path.getFirst(); | ||||
|             int machine = pb.machine(cur.job, cur.task); | ||||
| 
 | ||||
|             // will contain the task that was delaying the start | ||||
|             // of our current task | ||||
|             Optional<Task> latestPredecessor = Optional.empty(); | ||||
| 
 | ||||
|             if(cur.task > 0) { | ||||
|                 // our current task has a predecessor on the job | ||||
|                 Task predOnJob = new Task(cur.job, cur.task -1); | ||||
| 
 | ||||
|                 // if it was the delaying task, save it to predecessor | ||||
|                 if(endTime(predOnJob) == startTime(cur)) | ||||
|                     latestPredecessor = Optional.of(predOnJob); | ||||
|             } | ||||
|             if(!latestPredecessor.isPresent()) { | ||||
|                 // no latest predecessor found yet, look among tasks executing on the same machine | ||||
|                 latestPredecessor = IntStream.range(0, pb.numJobs) | ||||
|                         .mapToObj(j -> new Task(j, pb.task_with_machine(j, machine))) | ||||
|                         .filter(t -> endTime(t) == startTime(cur)) | ||||
|                         .findFirst(); | ||||
|             } | ||||
|             // at this point we should have identified a latest predecessor, either on the job or on the machine | ||||
|             assert latestPredecessor.isPresent() && endTime(latestPredecessor.get()) == startTime(cur); | ||||
|             // insert predecessor at the beginning of the path | ||||
|             path.add(0, latestPredecessor.get()); | ||||
|         } | ||||
|         assert isCriticalPath(path); | ||||
|         return path; | ||||
|     } | ||||
|      | ||||
|     public Schedule copy() { | ||||
|         return new Schedule(this.pb, this.times); | ||||
|     } | ||||
|      | ||||
|     /****************************************************************/ | ||||
|     /* Implémentation de la méthode toString() de la classe Schedule*/ | ||||
|     /****************************************************************/ | ||||
|     public String toString() { | ||||
|     	String res = ""; | ||||
|     	for (int i = 0; i < this.times.length; i++) { | ||||
|     		res += "Job " + Integer.toString(i + 1) + " starting times : \n"; | ||||
|     		for (int j = 0; j < this.times[i].length; j++) { | ||||
|     			res += "\tTask " + Integer.toString(j + 1) + " starts at time : " + Integer.toString(this.times[i][j]) + "\n"; | ||||
|     		} | ||||
|     	} | ||||
|     	return res; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| package jobshop; | ||||
| 
 | ||||
| public interface Solver { | ||||
| 
 | ||||
|     Result solve(Instance instance, long deadline); | ||||
| 
 | ||||
| } | ||||
| package jobshop; | ||||
| 
 | ||||
| public interface Solver { | ||||
| 
 | ||||
|     Result solve(Instance instance, long deadline); | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -1,116 +1,84 @@ | |||
| package jobshop.encodings; | ||||
| 
 | ||||
| import jobshop.Encoding; | ||||
| import jobshop.Instance; | ||||
| import jobshop.Schedule; | ||||
| 
 | ||||
| import java.util.Arrays; | ||||
| import java.util.Comparator; | ||||
| import java.util.stream.IntStream; | ||||
| 
 | ||||
| /** Représentation par numéro de job. */ | ||||
| public class JobNumbers extends Encoding { | ||||
| 
 | ||||
|     /** A numJobs * numTasks array containing the representation by job numbers. */ | ||||
|     public final int[] jobs; | ||||
| 
 | ||||
|     /** In case the encoding is only partially filled, indicates the index of first | ||||
|      * element of `jobs` that has not been set yet. */ | ||||
|     public int nextToSet = 0; | ||||
| 
 | ||||
|     public JobNumbers(Instance instance) { | ||||
|         super(instance); | ||||
| 
 | ||||
|         jobs = new int[instance.numJobs * instance.numMachines]; | ||||
|         Arrays.fill(jobs, -1); | ||||
|     } | ||||
|      | ||||
|     public JobNumbers(Schedule schedule) { | ||||
|         super(schedule.pb); | ||||
| 
 | ||||
|         this.jobs = new int[instance.numJobs * instance.numTasks]; | ||||
| 
 | ||||
|         // for each job indicates which is the next task to be scheduled | ||||
|         int[] nextOnJob = new int[instance.numJobs]; | ||||
| 
 | ||||
|         while(Arrays.stream(nextOnJob).anyMatch(t -> t < instance.numTasks)) { | ||||
|             Task next = IntStream | ||||
|                     // for all jobs numbers | ||||
|                     .range(0, instance.numJobs) | ||||
|                     // build the next task for this job | ||||
|                     .mapToObj(j -> new Task(j, nextOnJob[j])) | ||||
|                     // only keep valid tasks (some jobs have no task left to be executed) | ||||
|                     .filter(t -> t.task < instance.numTasks) | ||||
|                     // select the task with the earliest execution time | ||||
|                     .min(Comparator.comparing(t -> schedule.startTime(t.job, t.task))) | ||||
|                     .get(); | ||||
| 
 | ||||
|             this.jobs[nextToSet++] = next.job; | ||||
|             nextOnJob[next.job] += 1; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public Schedule toSchedule() { | ||||
|         // time at which each machine is going to be freed | ||||
|         int[] nextFreeTimeResource = new int[instance.numMachines]; | ||||
| 
 | ||||
|         // for each job, the first task that has not yet been scheduled | ||||
|         int[] nextTask = new int[instance.numJobs]; | ||||
| 
 | ||||
|         // for each task, its start time | ||||
|         int[][] startTimes = new int[instance.numJobs][instance.numTasks]; | ||||
| 
 | ||||
|         // compute the earliest start time for every task of every job | ||||
|         for(int job : jobs) { | ||||
|             int task = nextTask[job]; | ||||
|             int machine = instance.machine(job, task); | ||||
|             // earliest start time for this task | ||||
|             int est = task == 0 ? 0 : startTimes[job][task-1] + instance.duration(job, task-1); | ||||
|             est = Math.max(est, nextFreeTimeResource[machine]); | ||||
| 
 | ||||
|             startTimes[job][task] = est; | ||||
|             nextFreeTimeResource[machine] = est + instance.duration(job, task); | ||||
|             nextTask[job] = task + 1; | ||||
|         } | ||||
| 
 | ||||
|         return new Schedule(instance, startTimes); | ||||
|     } | ||||
|      | ||||
|     public static JobNumbers fromSchedule(Schedule sched) { | ||||
| 		JobNumbers jo = new JobNumbers(sched.pb); | ||||
| 		 | ||||
| 		int current_time = 0; | ||||
| 		Task current_task = new Task(-1,-1); | ||||
| 		Task [] done_tasks = new Task[sched.pb.numJobs*sched.pb.numTasks]; | ||||
| 		Arrays.fill(done_tasks, current_task); | ||||
| 		 | ||||
| 		int min; | ||||
| 		 | ||||
| 		for (int i = 0; i < sched.pb.numJobs*sched.pb.numTasks; i++) { | ||||
| 			// Il faut faire le code ci-dessous autant de fois que l'on a de taches | ||||
| 			// On trouve le minimum parmis les restants | ||||
| 			min = Integer.MAX_VALUE; | ||||
| 			for (int job = 0; job < sched.pb.numJobs; job++) { | ||||
| 				for (int task = 0; task < sched.pb.numTasks; task++) { | ||||
| 					int task_start_time = sched.startTime(job, task); | ||||
| 					Task this_task = new Task(job, task); | ||||
| 					if (task_start_time < min && task_start_time >= current_time && !(Arrays.asList(done_tasks).contains(this_task))) { | ||||
| 						min = task_start_time; | ||||
| 						current_task = this_task; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			// Une fois on a trouvé la suivante tache a realiser on introduit le numero du job dans jobs | ||||
| 			jo.jobs[jo.nextToSet++] = current_task.job; | ||||
| 			done_tasks[i] = current_task; | ||||
| 		} | ||||
|     	 | ||||
|     	return jo; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return Arrays.toString(Arrays.copyOfRange(jobs,0, nextToSet)); | ||||
|     } | ||||
| } | ||||
| package jobshop.encodings; | ||||
| 
 | ||||
| import jobshop.Encoding; | ||||
| import jobshop.Instance; | ||||
| import jobshop.Schedule; | ||||
| 
 | ||||
| import java.util.Arrays; | ||||
| import java.util.Comparator; | ||||
| import java.util.stream.IntStream; | ||||
| 
 | ||||
| /** Représentation par numéro de job. */ | ||||
| public class JobNumbers extends Encoding { | ||||
| 
 | ||||
|     /** A numJobs * numTasks array containing the representation by job numbers. */ | ||||
|     public final int[] jobs; | ||||
| 
 | ||||
|     /** In case the encoding is only partially filled, indicates the index of the first | ||||
|      * element of `jobs` that has not been set yet. */ | ||||
|     public int nextToSet = 0; | ||||
| 
 | ||||
|     public JobNumbers(Instance instance) { | ||||
|         super(instance); | ||||
| 
 | ||||
|         jobs = new int[instance.numJobs * instance.numMachines]; | ||||
|         Arrays.fill(jobs, -1); | ||||
|     } | ||||
| 
 | ||||
|     public JobNumbers(Schedule schedule) { | ||||
|         super(schedule.pb); | ||||
| 
 | ||||
|         this.jobs = new int[instance.numJobs * instance.numTasks]; | ||||
| 
 | ||||
|         // for each job indicates which is the next task to be scheduled | ||||
|         int[] nextOnJob = new int[instance.numJobs]; | ||||
| 
 | ||||
|         while(Arrays.stream(nextOnJob).anyMatch(t -> t < instance.numTasks)) { | ||||
|             Task next = IntStream | ||||
|                     // for all jobs numbers | ||||
|                     .range(0, instance.numJobs) | ||||
|                     // build the next task for this job | ||||
|                     .mapToObj(j -> new Task(j, nextOnJob[j])) | ||||
|                     // only keep valid tasks (some jobs have no task left to be executed) | ||||
|                     .filter(t -> t.task < instance.numTasks) | ||||
|                     // select the task with the earliest execution time | ||||
|                     .min(Comparator.comparing(t -> schedule.startTime(t.job, t.task))) | ||||
|                     .get(); | ||||
| 
 | ||||
|             this.jobs[nextToSet++] = next.job; | ||||
|             nextOnJob[next.job] += 1; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public Schedule toSchedule() { | ||||
|         // time at which each machine is going to be freed | ||||
|         int[] nextFreeTimeResource = new int[instance.numMachines]; | ||||
| 
 | ||||
|         // for each job, the first task that has not yet been scheduled | ||||
|         int[] nextTask = new int[instance.numJobs]; | ||||
| 
 | ||||
|         // for each task, its start time | ||||
|         int[][] startTimes = new int[instance.numJobs][instance.numTasks]; | ||||
| 
 | ||||
|         // compute the earliest start time for every task of every job | ||||
|         for(int job : jobs) { | ||||
|             int task = nextTask[job]; | ||||
|             int machine = instance.machine(job, task); | ||||
|             // earliest start time for this task | ||||
|             int est = task == 0 ? 0 : startTimes[job][task-1] + instance.duration(job, task-1); | ||||
|             est = Math.max(est, nextFreeTimeResource[machine]); | ||||
| 
 | ||||
|             startTimes[job][task] = est; | ||||
|             nextFreeTimeResource[machine] = est + instance.duration(job, task); | ||||
|             nextTask[job] = task + 1; | ||||
|         } | ||||
| 
 | ||||
|         return new Schedule(instance, startTimes); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return Arrays.toString(Arrays.copyOfRange(jobs,0, nextToSet)); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -1,120 +1,126 @@ | |||
| package jobshop.encodings; | ||||
| 
 | ||||
| import java.util.Comparator; | ||||
| import java.util.Optional; | ||||
| import java.util.stream.IntStream; | ||||
| 
 | ||||
| import jobshop.Encoding; | ||||
| import jobshop.Instance; | ||||
| import jobshop.Schedule; | ||||
| 
 | ||||
| 
 | ||||
| public class ResourceOrder extends Encoding { | ||||
| 	 | ||||
| 	public final Task[][] tasksByMachine; | ||||
| 	 | ||||
| 	public final int[] nextFreeSlot; | ||||
| 	 | ||||
| 	public ResourceOrder(Instance instance) { | ||||
| 		super(instance); | ||||
| 		 | ||||
| 		this.tasksByMachine = new Task[instance.numMachines][instance.numJobs]; | ||||
| 		for (int i = 0; i < instance.numMachines; i++) { | ||||
| 			for (int j = 0; j < instance.numJobs; j++) { | ||||
| 				this.tasksByMachine[i][j] = new Task(-1,-1); | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		// no task scheduled on any machine (0 is the default value) | ||||
|         nextFreeSlot = new int[instance.numMachines]; | ||||
| 	} | ||||
| 	 | ||||
| 	public ResourceOrder(Schedule schedule) { | ||||
|         super(schedule.pb); | ||||
|         Instance pb = schedule.pb; | ||||
| 
 | ||||
|         this.tasksByMachine = new Task[pb.numMachines][]; | ||||
|         this.nextFreeSlot = new int[instance.numMachines]; | ||||
| 
 | ||||
|         for(int m = 0 ; m<schedule.pb.numMachines ; m++) { | ||||
|             final int machine = m; | ||||
| 
 | ||||
|             // for thi machine, find all tasks that are executed on it and sort them by their start time | ||||
|             tasksByMachine[m] = | ||||
|                     IntStream.range(0, pb.numJobs) // all job numbers | ||||
|                             .mapToObj(j -> new Task(j, pb.task_with_machine(j, machine))) // all tasks on this machine (one per job) | ||||
|                             .sorted(Comparator.comparing(t -> schedule.startTime(t.job, t.task))) // sorted by start time | ||||
|                             .toArray(Task[]::new); // as new array and store in tasksByMachine | ||||
| 
 | ||||
|             // indicate that all tasks have been initialized for machine m | ||||
|             nextFreeSlot[m] = instance.numJobs; | ||||
|         } | ||||
| 	 } | ||||
| 	 | ||||
| 	 | ||||
| 	@Override | ||||
|     public Schedule toSchedule() { | ||||
|         // indicate for each task that have been scheduled, its start time | ||||
|         int [][] startTimes = new int [instance.numJobs][instance.numTasks]; | ||||
| 
 | ||||
|         // for each job, how many tasks have been scheduled (0 initially) | ||||
|         int[] nextToScheduleByJob = new int[instance.numJobs]; | ||||
| 
 | ||||
|         // for each machine, how many tasks have been scheduled (0 initially) | ||||
|         int[] nextToScheduleByMachine = new int[instance.numMachines]; | ||||
| 
 | ||||
|         // for each machine, earliest time at which the machine can be used | ||||
|         int[] releaseTimeOfMachine = new int[instance.numMachines]; | ||||
| 
 | ||||
| 
 | ||||
|         // loop while there remains a job that has unscheduled tasks | ||||
|         while(IntStream.range(0, instance.numJobs).anyMatch(m -> nextToScheduleByJob[m] < instance.numTasks)) { | ||||
| 
 | ||||
|             // selects a task that has noun scheduled predecessor on its job and machine : | ||||
|             //  - it is the next to be schedule on a machine | ||||
|             //  - it is the next to be scheduled on its job | ||||
|             // if there is no such task, we have cyclic dependency and the solution is invalid | ||||
|             Optional<Task> schedulable = | ||||
|                     IntStream.range(0, instance.numMachines) // all machines ... | ||||
|                     .filter(m -> nextToScheduleByMachine[m] < instance.numJobs) // ... with unscheduled jobs | ||||
|                     .mapToObj(m -> this.tasksByMachine[m][nextToScheduleByMachine[m]]) // tasks that are next to schedule on a machine ... | ||||
|                     .filter(task -> task.task == nextToScheduleByJob[task.job])  // ... and on their job | ||||
|                     .findFirst(); // select the first one if any | ||||
| 
 | ||||
|             if(schedulable.isPresent()) { | ||||
|                 // we found a schedulable task, lets call it t | ||||
|                 Task t = schedulable.get(); | ||||
|                 int machine = instance.machine(t.job, t.task); | ||||
| 
 | ||||
|                 // compute the earliest start time (est) of the task | ||||
|                 int est = t.task == 0 ? 0 : startTimes[t.job][t.task-1] + instance.duration(t.job, t.task-1); | ||||
|                 est = Math.max(est, releaseTimeOfMachine[instance.machine(t.job, t.task)]); | ||||
|                 startTimes[t.job][t.task] = est; | ||||
| 
 | ||||
|                 // mark the task as scheduled | ||||
|                 nextToScheduleByJob[t.job]++; | ||||
|                 nextToScheduleByMachine[machine]++; | ||||
|                 // increase the release time of the machine | ||||
|                 releaseTimeOfMachine[machine] = est + instance.duration(t.job, t.task); | ||||
|             } else { | ||||
|                 // no tasks are schedulable, there is no solution for this resource ordering | ||||
|                 return null; | ||||
|             } | ||||
|         } | ||||
|         // we exited the loop : all tasks have been scheduled successfully | ||||
|         return new Schedule(instance, startTimes); | ||||
|     } | ||||
| 	 | ||||
| 	@Override | ||||
|     public String toString() { | ||||
| 		String res = ""; | ||||
| 		for (int i = 0; i < this.tasksByMachine.length; i++) { | ||||
| 			res += "Machine number : " + Integer.toString(i+1) + "\n"; | ||||
| 			for (int j = 0; j < this.tasksByMachine[i].length; j++) { | ||||
| 				res += "\tUse number " + Integer.toString(j+1) + " : " + this.tasksByMachine[i][j].add_one() + "\n"; | ||||
| 			} | ||||
| 		} | ||||
|         return res; | ||||
|     } | ||||
| 	 | ||||
| } | ||||
| package jobshop.encodings; | ||||
| 
 | ||||
| import jobshop.Encoding; | ||||
| import jobshop.Instance; | ||||
| import jobshop.Schedule; | ||||
| 
 | ||||
| import java.util.Comparator; | ||||
| import java.util.Optional; | ||||
| import java.util.stream.IntStream; | ||||
| 
 | ||||
| public class ResourceOrder extends Encoding { | ||||
| 
 | ||||
|     // for each machine m, taskByMachine[m] is an array of tasks to be | ||||
|     // executed on this machine in the same order | ||||
|     public final Task[][] tasksByMachine; | ||||
| 
 | ||||
|     // for each machine, indicate on many tasks have been initialized | ||||
|     public final int[] nextFreeSlot; | ||||
| 
 | ||||
|     /** Creates a new empty resource order. */ | ||||
|     public ResourceOrder(Instance instance) | ||||
|     { | ||||
|         super(instance); | ||||
| 
 | ||||
|         // matrix of null elements (null is the default value of objects) | ||||
|         tasksByMachine = new Task[instance.numMachines][instance.numJobs]; | ||||
| 
 | ||||
|         // no task scheduled on any machine (0 is the default value) | ||||
|         nextFreeSlot = new int[instance.numMachines]; | ||||
|     } | ||||
| 
 | ||||
|     /** Creates a resource order from a schedule. */ | ||||
|     public ResourceOrder(Schedule schedule) | ||||
|     { | ||||
|         super(schedule.pb); | ||||
|         Instance pb = schedule.pb; | ||||
| 
 | ||||
|         this.tasksByMachine = new Task[pb.numMachines][]; | ||||
|         this.nextFreeSlot = new int[instance.numMachines]; | ||||
| 
 | ||||
|         for(int m = 0 ; m<schedule.pb.numMachines ; m++) { | ||||
|             final int machine = m; | ||||
| 
 | ||||
|             // for thi machine, find all tasks that are executed on it and sort them by their start time | ||||
|             tasksByMachine[m] = | ||||
|                     IntStream.range(0, pb.numJobs) // all job numbers | ||||
|                             .mapToObj(j -> new Task(j, pb.task_with_machine(j, machine))) // all tasks on this machine (one per job) | ||||
|                             .sorted(Comparator.comparing(t -> schedule.startTime(t.job, t.task))) // sorted by start time | ||||
|                             .toArray(Task[]::new); // as new array and store in tasksByMachine | ||||
| 
 | ||||
|             // indicate that all tasks have been initialized for machine m | ||||
|             nextFreeSlot[m] = instance.numJobs; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public Schedule toSchedule() { | ||||
|         // indicate for each task that have been scheduled, its start time | ||||
|         int [][] startTimes = new int [instance.numJobs][instance.numTasks]; | ||||
| 
 | ||||
|         // for each job, how many tasks have been scheduled (0 initially) | ||||
|         int[] nextToScheduleByJob = new int[instance.numJobs]; | ||||
| 
 | ||||
|         // for each machine, how many tasks have been scheduled (0 initially) | ||||
|         int[] nextToScheduleByMachine = new int[instance.numMachines]; | ||||
| 
 | ||||
|         // for each machine, earliest time at which the machine can be used | ||||
|         int[] releaseTimeOfMachine = new int[instance.numMachines]; | ||||
| 
 | ||||
| 
 | ||||
|         // loop while there remains a job that has unscheduled tasks | ||||
|         while(IntStream.range(0, instance.numJobs).anyMatch(m -> nextToScheduleByJob[m] < instance.numTasks)) { | ||||
| 
 | ||||
|             // selects a task that has noun scheduled predecessor on its job and machine : | ||||
|             //  - it is the next to be schedule on a machine | ||||
|             //  - it is the next to be scheduled on its job | ||||
|             // if there is no such task, we have cyclic dependency and the solution is invalid | ||||
|             Optional<Task> schedulable = | ||||
|                     IntStream.range(0, instance.numMachines) // all machines ... | ||||
|                     .filter(m -> nextToScheduleByMachine[m] < instance.numJobs) // ... with unscheduled jobs | ||||
|                     .mapToObj(m -> this.tasksByMachine[m][nextToScheduleByMachine[m]]) // tasks that are next to schedule on a machine ... | ||||
|                     .filter(task -> task.task == nextToScheduleByJob[task.job])  // ... and on their job | ||||
|                     .findFirst(); // select the first one if any | ||||
| 
 | ||||
|             if(schedulable.isPresent()) { | ||||
|                 // we found a schedulable task, lets call it t | ||||
|                 Task t = schedulable.get(); | ||||
|                 int machine = instance.machine(t.job, t.task); | ||||
| 
 | ||||
|                 // compute the earliest start time (est) of the task | ||||
|                 int est = t.task == 0 ? 0 : startTimes[t.job][t.task-1] + instance.duration(t.job, t.task-1); | ||||
|                 est = Math.max(est, releaseTimeOfMachine[instance.machine(t)]); | ||||
|                 startTimes[t.job][t.task] = est; | ||||
| 
 | ||||
|                 // mark the task as scheduled | ||||
|                 nextToScheduleByJob[t.job]++; | ||||
|                 nextToScheduleByMachine[machine]++; | ||||
|                 // increase the release time of the machine | ||||
|                 releaseTimeOfMachine[machine] = est + instance.duration(t.job, t.task); | ||||
|             } else { | ||||
|                 // no tasks are schedulable, there is no solution for this resource ordering | ||||
|                 return null; | ||||
|             } | ||||
|         } | ||||
|         // we exited the loop : all tasks have been scheduled successfully | ||||
|         return new Schedule(instance, startTimes); | ||||
|     } | ||||
| 
 | ||||
|     /** Creates an exact copy of this resource order. */ | ||||
|     public ResourceOrder copy() { | ||||
|         return new ResourceOrder(this.toSchedule()); | ||||
|     } | ||||
| 	 | ||||
| 	@Override | ||||
|     public String toString() { | ||||
| 		String res = ""; | ||||
| 		for (int i = 0; i < this.tasksByMachine.length; i++) { | ||||
| 			res += "Machine number : " + Integer.toString(i+1) + "\n"; | ||||
| 			for (int j = 0; j < this.tasksByMachine[i].length; j++) { | ||||
| 				res += "\tUse number " + Integer.toString(j+1) + " : " + this.tasksByMachine[i][j].add_one() + "\n"; | ||||
| 			} | ||||
| 		} | ||||
|         return res; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -1,45 +1,45 @@ | |||
| package jobshop.encodings; | ||||
| 
 | ||||
| import java.util.Objects; | ||||
| 
 | ||||
| /** Represents a task (job,task) of an jobshop problem. | ||||
|  * | ||||
|  * Example : (2, 3) repesents the fourth task of the third job. (remeber that we tart counting at 0) | ||||
|  * */ | ||||
| public final class Task { | ||||
| 
 | ||||
|     /** Identifier of the job */ | ||||
|     public final int job; | ||||
| 
 | ||||
|     /** Index of the task inside the job. */ | ||||
|     public final int task; | ||||
| 
 | ||||
| 
 | ||||
|     public Task(int job, int task) { | ||||
|         this.job = job; | ||||
|         this.task = task; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean equals(Object o) { | ||||
|         if (this == o) return true; | ||||
|         if (o == null || getClass() != o.getClass()) return false; | ||||
|         Task task1 = (Task) o; | ||||
|         return job == task1.job && | ||||
|                 task == task1.task; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public int hashCode() { | ||||
|         return Objects.hash(job, task); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return "Job " + this.job + " Task " + this.task; | ||||
|     } | ||||
|      | ||||
|     public Task add_one() { | ||||
|     	return new Task(this.job + 1, this.task + 1); | ||||
|     } | ||||
| } | ||||
| package jobshop.encodings; | ||||
| 
 | ||||
| import java.util.Objects; | ||||
| 
 | ||||
| /** Represents a task (job,task) of an jobshop problem. | ||||
|  * | ||||
|  * Example : (2, 3) repesents the fourth task of the third job. (remeber that we tart counting at 0) | ||||
|  * */ | ||||
| public final class Task { | ||||
| 
 | ||||
|     /** Identifier of the job */ | ||||
|     public final int job; | ||||
| 
 | ||||
|     /** Index of the task inside the job. */ | ||||
|     public final int task; | ||||
| 
 | ||||
| 
 | ||||
|     public Task(int job, int task) { | ||||
|         this.job = job; | ||||
|         this.task = task; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean equals(Object o) { | ||||
|         if (this == o) return true; | ||||
|         if (o == null || getClass() != o.getClass()) return false; | ||||
|         Task task1 = (Task) o; | ||||
|         return job == task1.job && | ||||
|                 task == task1.task; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public int hashCode() { | ||||
|         return Objects.hash(job, task); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return "(" + job +", " + task + '}'; | ||||
|     } | ||||
|      | ||||
|     public Task add_one() { | ||||
|     	return new Task(this.job + 1, this.task + 1); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -1,21 +1,21 @@ | |||
| package jobshop.solvers; | ||||
| 
 | ||||
| import jobshop.Instance; | ||||
| import jobshop.Result; | ||||
| import jobshop.Solver; | ||||
| import jobshop.encodings.JobNumbers; | ||||
| 
 | ||||
| public class BasicSolver implements Solver { | ||||
|     @Override | ||||
|     public Result solve(Instance instance, long deadline) { | ||||
| 
 | ||||
|         JobNumbers sol = new JobNumbers(instance); | ||||
|         for(int t = 0 ; t<instance.numTasks ; t++) { | ||||
|             for(int j = 0 ; j<instance.numJobs ; j++) { | ||||
|                 sol.jobs[sol.nextToSet++] = j; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return new Result(instance, sol.toSchedule(), Result.ExitCause.Blocked); | ||||
|     } | ||||
| } | ||||
| package jobshop.solvers; | ||||
| 
 | ||||
| import jobshop.Instance; | ||||
| import jobshop.Result; | ||||
| import jobshop.Solver; | ||||
| import jobshop.encodings.JobNumbers; | ||||
| 
 | ||||
| public class BasicSolver implements Solver { | ||||
|     @Override | ||||
|     public Result solve(Instance instance, long deadline) { | ||||
| 
 | ||||
|         JobNumbers sol = new JobNumbers(instance); | ||||
|         for(int t = 0 ; t<instance.numTasks ; t++) { | ||||
|             for(int j = 0 ; j<instance.numJobs ; j++) { | ||||
|                 sol.jobs[sol.nextToSet++] = j; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return new Result(instance, sol.toSchedule(), Result.ExitCause.Blocked); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -2,15 +2,34 @@ package jobshop.solvers; | |||
| 
 | ||||
| import jobshop.Instance; | ||||
| import jobshop.Result; | ||||
| import jobshop.Result.ExitCause; | ||||
| import jobshop.Schedule; | ||||
| import jobshop.Solver; | ||||
| import jobshop.encodings.ResourceOrder; | ||||
| import jobshop.encodings.Task; | ||||
| import jobshop.solvers.GreedySolver.PriorityESTRule; | ||||
| import jobshop.solvers.GreedySolver.PriorityRule; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| public class DescentSolver implements Solver { | ||||
| 	 | ||||
| 	private PriorityRule priorityRule; | ||||
| 	private PriorityESTRule priorityESTRule; | ||||
| 	 | ||||
| 	// 2 constructors: the default and one with the EST restriction | ||||
| 	public DescentSolver(PriorityRule rule) { | ||||
| 		super(); | ||||
| 		this.priorityRule = rule; | ||||
| 		this.priorityESTRule = null; | ||||
| 	} | ||||
| 	 | ||||
| 	public DescentSolver(PriorityESTRule ruleEST) { | ||||
| 		super(); | ||||
| 		this.priorityESTRule = ruleEST; | ||||
| 		this.priorityRule = null; | ||||
| 	} | ||||
| 
 | ||||
|     /** A block represents a subsequence of the critical path such that all tasks in it execute on the same machine. | ||||
|      * This class identifies a block in a ResourceOrder representation. | ||||
|  | @ -24,7 +43,7 @@ public class DescentSolver implements Solver { | |||
|      * Represent the task sequence : [(0,2) (2,1)] | ||||
|      * | ||||
|      * */ | ||||
|     public static class Block { | ||||
| 	public static class Block { | ||||
|         /** machine on which the block is identified */ | ||||
|         final int machine; | ||||
|         /** index of the first task of the block */ | ||||
|  | @ -78,7 +97,7 @@ public class DescentSolver implements Solver { | |||
|             // Retrieve the tasks to be swap | ||||
|         	Task task1 = order.tasksByMachine[this.machine][this.t1]; | ||||
|             Task task2 = order.tasksByMachine[this.machine][this.t2]; | ||||
|             // Make the swap | ||||
|             // Make the swap (default in/out) | ||||
|             order.tasksByMachine[this.machine][this.t1] = task2; | ||||
|             order.tasksByMachine[this.machine][this.t2] = task1; | ||||
|         } | ||||
|  | @ -87,90 +106,142 @@ public class DescentSolver implements Solver { | |||
|         	return "Swap: {M" + this.machine + " | t1 = " + this.t1 + " | t2 = " + this.t2 + "}"; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     // ************************************************************************************************************* // | ||||
|     // *************************************** DescentSolver: solve Method ***************************************** // | ||||
|     // ************************************************************************************************************* // | ||||
|     @Override | ||||
|     public Result solve(Instance instance, long deadline) { | ||||
|         throw new UnsupportedOperationException(); | ||||
|     	// Choosing rule (SPT / LRPT / EST_SPT / EST_LRPT) | ||||
|     	GreedySolver greedy = null; | ||||
|     	if(priorityESTRule == null) { | ||||
|     		PriorityRule currentRule = this.priorityRule; | ||||
|     		greedy = new GreedySolver(currentRule); | ||||
|     	} else if(priorityRule == null) { | ||||
|     		PriorityESTRule currentESTRule = this.priorityESTRule; | ||||
|     		greedy = new GreedySolver(currentESTRule); | ||||
|     	} else { | ||||
|     		System.out.printf("Error priorityRule and priorityRuleEST are null. You must give a value to one of them."); | ||||
|     	} | ||||
|     	 | ||||
|         // Start: Sinit <- GreedySolver(instance) | ||||
|     	Result resultLRPT = greedy.solve(instance, deadline); | ||||
|     	Schedule initialSolution = resultLRPT.schedule; | ||||
|     	 | ||||
|     	// Record the best solution | ||||
|     	Schedule bestSolution = initialSolution; | ||||
|     	ResourceOrder bestResourceOrder = new ResourceOrder(bestSolution); | ||||
|     	 | ||||
|     	// Repeat: Explore the concurrent neighbors | ||||
|     	Boolean optimizable = true; | ||||
|     	Schedule currentSolution; | ||||
|     	ResourceOrder currentResourceOrder; | ||||
|     	List<Block> criticalBlockList; | ||||
|     	 | ||||
|     	while(optimizable && deadline > System.currentTimeMillis()) { | ||||
|     		// We first take the critical path from the bestSolution | ||||
|         	bestResourceOrder = new ResourceOrder(bestSolution); | ||||
|         	criticalBlockList = this.blocksOfCriticalPath(bestResourceOrder); | ||||
|         	// By default we suppose there will be no optimization possible. If there is, this value will be later changed | ||||
|         	optimizable = false; | ||||
|         	// We search for the best solution by checking all neighbors | ||||
|         	for(Block b : criticalBlockList) { | ||||
|         		for(Swap s : this.neighbors(b)) { | ||||
|                 	// We copy to a variable the bestResourceOrder in order to modified freely while searching for the best solution | ||||
|                 	currentResourceOrder = bestResourceOrder.copy(); | ||||
|         			// We apply the swap on the current Resource Order and we schedule it | ||||
|         			s.applyOn(currentResourceOrder); | ||||
|         			currentSolution = currentResourceOrder.toSchedule(); | ||||
|         			// If the currentSolution duration is smaller than the bestSolution one, save the currentSolution | ||||
|         			if(currentSolution != null) { | ||||
| 	        			if(currentSolution.makespan() < bestSolution.makespan()) { | ||||
| 	        				bestSolution = currentSolution; | ||||
| 	        				// While we find better solutions keep running the solve method | ||||
| 	        				optimizable = true; | ||||
| 	        			} | ||||
|         			} | ||||
|         		} | ||||
|         	} | ||||
|     	} | ||||
|     	// We find the exit cause in order to create the result we will return | ||||
|     	ExitCause exitCause = null; | ||||
|     	if(deadline <= System.currentTimeMillis()) { | ||||
|     		exitCause = ExitCause.Timeout; | ||||
|     	} else { | ||||
|     		exitCause = ExitCause.ProvedOptimal; | ||||
|     	} | ||||
|     	 | ||||
|     	return new Result(instance, bestSolution, exitCause); | ||||
|     } | ||||
| 
 | ||||
|      | ||||
|     // ************************************************************************************************************* // | ||||
|      | ||||
|      | ||||
|     // ************************************************************************************************************* // | ||||
|     // ***************************** blocksOfCriticalPath and neighbors Methods ************************************ // | ||||
|     // ************************************************************************************************************* // | ||||
|     /** Returns a list of all blocks of the critical path. */ | ||||
|     public List<Block> blocksOfCriticalPath(ResourceOrder order) { | ||||
|     	List<Block> criticalBlockList = new ArrayList<>(); | ||||
|     	List<Integer> checkedMachines = new ArrayList<>(); | ||||
|     	 | ||||
|     	Block currentBlock; | ||||
|     	// Obtain the critical task list from the resource order instance | ||||
|         Schedule criticalSchedule = order.toSchedule(); | ||||
|         List<Task> criticalTaskList = criticalSchedule.criticalPath(); | ||||
|          | ||||
|         Block currentBlock; | ||||
|         int currentMachine, m; | ||||
|         int firstTask = 0, lastTask = 0; | ||||
|         Task currentTask; | ||||
|         int totalNumMachines = criticalSchedule.pb.numMachines; | ||||
|         int totalNumJobs     = criticalSchedule.pb.numJobs; | ||||
|          | ||||
|         System.out.print("Number of Jobs     : " + order.instance.numJobs + "\n"); | ||||
|         System.out.print("Number of Tasks    : " + order.instance.numTasks + "\n"); | ||||
|         System.out.print("Number of Machines : " + order.instance.numMachines + "\n"); | ||||
|         System.out.print("Critical path      : " + criticalTaskList + "\n"); | ||||
|         Task currentTaskRO; | ||||
|         int currentTaskIndexRO, currentCriticalTaskIndex, firstTask, lastTask; | ||||
|          | ||||
|         // Initialize the block list | ||||
|         for(int i = 0; i < order.instance.numMachines; i++) { | ||||
|         	currentBlock = new Block(i, -1, -1); | ||||
|         	criticalBlockList.add(i, currentBlock); | ||||
|         } | ||||
|          | ||||
|         for(int i = 0; i < criticalTaskList.size(); i++) { | ||||
|         	currentTask = criticalTaskList.get(i); | ||||
|         	currentMachine = order.instance.machine(currentTask.job, currentTask.task); | ||||
|         	 | ||||
|         	// When we find a machine we have not explored, we start searching for all its appearances in the critical path  | ||||
|         	// and we safe the first and last occurrence of the machine.   | ||||
|         	if(!checkedMachines.contains(currentMachine)) { | ||||
|         		firstTask = 0; | ||||
|                 lastTask = 0; | ||||
|         		for(int index = i; index < criticalTaskList.size(); index++) { | ||||
| 	        		m = order.instance.machine(criticalTaskList.get(index).job, criticalTaskList.get(index).task); | ||||
| 	        		// If we find a task running in the same machine and it is not the first task, add 1 to the last task | ||||
| 	        		if(currentMachine == m && index > i){ | ||||
| 	    				lastTask++; | ||||
| 	        		} | ||||
|         		} | ||||
|             	// Add the machine to the checked machines list | ||||
|             	checkedMachines.add(currentMachine); | ||||
|             	// Create and add the new block to the list | ||||
|             	currentBlock = new Block(currentMachine, firstTask, lastTask); | ||||
|             	criticalBlockList.set(currentMachine, currentBlock); | ||||
|         	} | ||||
|         // We check for all machines | ||||
|         for(int currentMachine = 0; currentMachine < totalNumMachines; currentMachine++) { | ||||
|         	currentTaskIndexRO = 0; | ||||
|             while(currentTaskIndexRO < (totalNumJobs-1)){ | ||||
|                 currentTaskRO = order.tasksByMachine[currentMachine][currentTaskIndexRO]; | ||||
|                 if (criticalTaskList.contains(currentTaskRO)) { | ||||
|                     currentCriticalTaskIndex = criticalTaskList.indexOf(currentTaskRO); | ||||
|                     //If the next task in the critical path is running in the same machine try find the last task index | ||||
|                     if(currentMachine == criticalSchedule.pb.machine(criticalTaskList.get(currentCriticalTaskIndex+1))) { | ||||
|                         firstTask = currentTaskIndexRO; | ||||
|                         while(currentCriticalTaskIndex < (criticalTaskList.size()-1) && currentMachine == criticalSchedule.pb.machine(criticalTaskList.get(currentCriticalTaskIndex+1))){ | ||||
|                         	// We advance in the list | ||||
|                             currentCriticalTaskIndex++; | ||||
|                             // We have to also advance in the resource order | ||||
|                             currentTaskIndexRO++; | ||||
|                         } | ||||
|                         // Create and add the new block to the list | ||||
|                         lastTask = currentTaskIndexRO; | ||||
|                 	    currentBlock = new Block(currentMachine, firstTask, lastTask); | ||||
|                         criticalBlockList.add(currentBlock); | ||||
|                     } | ||||
|                 } | ||||
|                 // We move on to the next task in the resource order | ||||
|                 currentTaskIndexRO++; | ||||
|             } | ||||
|         } | ||||
|         return criticalBlockList; | ||||
|     } | ||||
|      | ||||
|      } | ||||
| 
 | ||||
|     /** For a given block, return the possible swaps for the Nowicki and Smutnicki neighborhood */ | ||||
|     public List<Swap> neighbors(Block block) { | ||||
|      /** For a given block, return the possible swaps for the Nowicki and Smutnicki neighborhood */ | ||||
|      public List<Swap> neighbors(Block block) { | ||||
|     	List<Swap> swapList = new ArrayList<>(); | ||||
|     	Swap currentSwap; | ||||
|     	Swap swap1, swap2; | ||||
|     	 | ||||
|     	int machine   = block.machine; | ||||
|     	int firstTask = block.firstTask; | ||||
|     	int lastTask  = block.lastTask; | ||||
|     	 | ||||
|     	// Case when there is just one element in the block | ||||
|     	if(firstTask == lastTask) { | ||||
|     		swapList = null; | ||||
|     	} | ||||
|     	 | ||||
|      	for(int i = firstTask; i < lastTask; i++) { | ||||
|      		if(i == firstTask + 1) { | ||||
|      			currentSwap = new Swap(machine, firstTask, i); | ||||
|      			swapList.add(currentSwap); | ||||
|      		} | ||||
|      		if (i == lastTask - 1) { | ||||
|      			currentSwap = new Swap(machine, i, lastTask); | ||||
|      			swapList.add(currentSwap); | ||||
|      		} | ||||
|     	} | ||||
|     	// One single swap if there are just 2 elements in the block, two swaps if there are more than 2. | ||||
|  		if(firstTask + 1 == lastTask) { | ||||
|  			swap1 = new Swap(machine, firstTask, lastTask); | ||||
|  			swapList.add(swap1); | ||||
|  		} else { | ||||
|  			swap1 = new Swap(machine, firstTask, firstTask+1); | ||||
|  			swap2 = new Swap(machine, lastTask-1 , lastTask); | ||||
|  			swapList.add(swap1); | ||||
|  			swapList.add(swap2); | ||||
|  		} | ||||
|         return swapList; | ||||
|     } | ||||
| 
 | ||||
|      }    | ||||
|      // ************************************************************************************************************* // | ||||
| } | ||||
|  |  | |||
|  | @ -3,9 +3,9 @@ package jobshop.solvers; | |||
| import java.util.ArrayList; | ||||
| 
 | ||||
| import jobshop.*; | ||||
| import jobshop.Result.ExitCause; | ||||
| import jobshop.encodings.ResourceOrder; | ||||
| import jobshop.encodings.Task; | ||||
| import jobshop.solvers.GreedySolver.PriorityESTRule; | ||||
| 
 | ||||
| public class GreedySolver implements Solver { | ||||
| 	 | ||||
|  | @ -100,12 +100,12 @@ public class GreedySolver implements Solver { | |||
| 			// Search for the date or dates which start sooner | ||||
| 			ArrayList<Task> priorityTasks = new ArrayList<>(); | ||||
| 			int minStartDate = Integer.MAX_VALUE; | ||||
| 
 | ||||
| 			 | ||||
| 			Task currentTask; | ||||
| 			int currentMachine, currentStartDate; | ||||
| 			for(int i = 0; i < achievableTasks.size(); i++) { | ||||
| 				Task currentTask = achievableTasks.get(i); | ||||
| 				int currentMachine = instance.machine(currentTask.job, currentTask.task); | ||||
| 				int currentStartDate = Integer.max(nextStartDateJobs[currentTask.job], nextStartDateMachines[currentMachine]); | ||||
| 				currentTask = achievableTasks.get(i); | ||||
| 				currentMachine = instance.machine(currentTask); | ||||
| 				currentStartDate = Integer.max(nextStartDateJobs[currentTask.job], nextStartDateMachines[currentMachine]); | ||||
| 						 | ||||
| 				if(currentStartDate < minStartDate) { | ||||
| 					minStartDate = currentStartDate; | ||||
|  | @ -124,16 +124,18 @@ public class GreedySolver implements Solver { | |||
| 	/********************** Greedy Solver: Constructors + Solve function *************************/ | ||||
| 	/*********************************************************************************************/ | ||||
| 	 | ||||
| 	public PriorityRule priorityRule; | ||||
| 	public PriorityESTRule priorityESTRule; | ||||
| 	private PriorityRule priorityRule; | ||||
| 	private PriorityESTRule priorityESTRule; | ||||
| 	 | ||||
| 	// 2 constructors: the default and one with the EST restriction | ||||
| 	public GreedySolver(PriorityRule rule) { | ||||
| 		super(); | ||||
| 		this.priorityRule = rule; | ||||
| 		this.priorityESTRule = null; | ||||
| 	} | ||||
| 	 | ||||
| 	public GreedySolver(PriorityESTRule ruleEST) { | ||||
| 		super(); | ||||
| 		this.priorityESTRule = ruleEST; | ||||
| 		this.priorityRule = null; | ||||
| 	} | ||||
|  | @ -143,7 +145,7 @@ public class GreedySolver implements Solver { | |||
| 	@Override | ||||
|     public Result solve(Instance instance, long deadline) { | ||||
| 		 | ||||
| 		int currentMachine, currentDuration; | ||||
| 		int currentMachine, currentDuration, currentStartDate, nextFreeSlot; | ||||
| 		// We declare 2 arrays containing the updated moment the next task will start in a job and a machine respectively | ||||
| 		int[] nextStartDateJobs = new int[instance.numJobs]; | ||||
| 		int[] nextStartDateMachines = new int[instance.numMachines]; | ||||
|  | @ -152,14 +154,13 @@ public class GreedySolver implements Solver { | |||
| 		ResourceOrder solution = new ResourceOrder(instance); | ||||
| 		// Array list with all the achievable current tasks | ||||
|         ArrayList<Task> achievableTasks = new ArrayList<>(); | ||||
|          | ||||
|        | ||||
|         // Initialize the array list with all the first task achievable | ||||
| 		for(int i = 0 ; i < instance.numJobs ; i++) { | ||||
| 			Task currentTask = new Task(i, 0); | ||||
| 			achievableTasks.add(currentTask); | ||||
| 			achievableTasks.add(new Task(i, 0)); | ||||
|         } | ||||
| 		 | ||||
|         while(!achievableTasks.isEmpty()) { | ||||
|         while(!achievableTasks.isEmpty() && deadline > System.currentTimeMillis()) { | ||||
|             // We take the task we should do now in function of the priority rule used | ||||
|         	Task currentTask = null; | ||||
|         	if(priorityESTRule == null) { | ||||
|  | @ -170,14 +171,16 @@ public class GreedySolver implements Solver { | |||
|         		System.out.printf("Error priorityRule and priorityRuleEST are null. You must give a value to one of them."); | ||||
|         	} | ||||
|         	 | ||||
|         	// Updating starting dates | ||||
| 			currentMachine = instance.machine(currentTask.job, currentTask.task); | ||||
| 			currentDuration = instance.duration(currentTask.job, currentTask.task); | ||||
| 			nextStartDateJobs[currentTask.job] += currentDuration; | ||||
| 			nextStartDateMachines[currentMachine] += currentDuration; | ||||
|              | ||||
|             // We remove the current task from the achievable tasks list | ||||
|             achievableTasks.remove(currentTask); | ||||
|         	 | ||||
|         	// Updating starting dates | ||||
| 			currentMachine   = instance.machine(currentTask); | ||||
| 			currentDuration  = instance.duration(currentTask); | ||||
|             currentStartDate = Integer.max(nextStartDateJobs[currentTask.job], nextStartDateMachines[currentMachine]); | ||||
| 
 | ||||
| 			nextStartDateJobs[currentTask.job]    = currentStartDate + currentDuration; | ||||
| 			nextStartDateMachines[currentMachine] = currentStartDate + currentDuration; | ||||
|              | ||||
|             // If it's not the last task of the job, we update the array list with the new task | ||||
|             if (currentTask.task < (instance.numTasks - 1)) { | ||||
|  | @ -185,10 +188,16 @@ public class GreedySolver implements Solver { | |||
|             } | ||||
|              | ||||
|             // We add the current task to the solution | ||||
|             int nextFreeSlot = solution.nextFreeSlot[currentMachine]++; | ||||
|             nextFreeSlot = solution.nextFreeSlot[currentMachine]++; | ||||
|             solution.tasksByMachine[currentMachine][nextFreeSlot] = currentTask; | ||||
|         } | ||||
| 
 | ||||
|         return new Result(instance, solution.toSchedule(), Result.ExitCause.Blocked); | ||||
|     	// We find the exit cause in order to create the result we will return | ||||
|     	ExitCause exitCause = null; | ||||
|     	if(deadline <= System.currentTimeMillis()) { | ||||
|     		exitCause = ExitCause.Timeout; | ||||
|     	} else { | ||||
|     		exitCause = ExitCause.ProvedOptimal; | ||||
|     	} | ||||
|         return new Result(instance, solution.toSchedule(), exitCause); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -1,53 +1,52 @@ | |||
| package jobshop.solvers; | ||||
| 
 | ||||
| import jobshop.*; | ||||
| import jobshop.encodings.JobNumbers; | ||||
| 
 | ||||
| import java.util.Optional; | ||||
| import java.util.Random; | ||||
| 
 | ||||
| @SuppressWarnings("unused") | ||||
| public class RandomSolver implements Solver { | ||||
| 
 | ||||
|     @Override | ||||
|     public Result solve(Instance instance, long deadline) { | ||||
|         Random generator = new Random(0); | ||||
| 
 | ||||
|         JobNumbers sol = new JobNumbers(instance); | ||||
| 
 | ||||
|         for(int j = 0 ; j<instance.numJobs ; j++) { | ||||
|             for(int t = 0 ; t<instance.numTasks ; t++) { | ||||
|                 sol.jobs[sol.nextToSet++] = j; | ||||
|             } | ||||
|         } | ||||
|         Schedule best = sol.toSchedule(); | ||||
|         while(deadline - System.currentTimeMillis() > 1) { | ||||
|             shuffleArray(sol.jobs, generator); | ||||
|             Schedule s = sol.toSchedule(); | ||||
|             if(s.makespan() < best.makespan()) { | ||||
|                 best = s; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         return new Result(instance, best, Result.ExitCause.Timeout); | ||||
|     } | ||||
| 
 | ||||
|     /** Simple Fisher–Yates array shuffling */ | ||||
|     private static void shuffleArray(int[] array, Random random) | ||||
|     { | ||||
|         int index; | ||||
|         for (int i = array.length - 1; i > 0; i--) | ||||
|         { | ||||
|             index = random.nextInt(i + 1); | ||||
|             if (index != i) | ||||
|             { | ||||
|                 array[index] ^= array[i]; | ||||
|                 array[i] ^= array[index]; | ||||
|                 array[index] ^= array[i]; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| package jobshop.solvers; | ||||
| 
 | ||||
| import jobshop.*; | ||||
| import jobshop.encodings.JobNumbers; | ||||
| 
 | ||||
| import java.util.Optional; | ||||
| import java.util.Random; | ||||
| 
 | ||||
| public class RandomSolver implements Solver { | ||||
| 
 | ||||
|     @Override | ||||
|     public Result solve(Instance instance, long deadline) { | ||||
|         Random generator = new Random(0); | ||||
| 
 | ||||
|         JobNumbers sol = new JobNumbers(instance); | ||||
| 
 | ||||
|         for(int j = 0 ; j<instance.numJobs ; j++) { | ||||
|             for(int t = 0 ; t<instance.numTasks ; t++) { | ||||
|                 sol.jobs[sol.nextToSet++] = j; | ||||
|             } | ||||
|         } | ||||
|         Schedule best = sol.toSchedule(); | ||||
|         while(deadline - System.currentTimeMillis() > 1) { | ||||
|             shuffleArray(sol.jobs, generator); | ||||
|             Schedule s = sol.toSchedule(); | ||||
|             if(s.makespan() < best.makespan()) { | ||||
|                 best = s; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         return new Result(instance, best, Result.ExitCause.Timeout); | ||||
|     } | ||||
| 
 | ||||
|     /** Simple Fisher–Yates array shuffling */ | ||||
|     private static void shuffleArray(int[] array, Random random) | ||||
|     { | ||||
|         int index; | ||||
|         for (int i = array.length - 1; i > 0; i--) | ||||
|         { | ||||
|             index = random.nextInt(i + 1); | ||||
|             if (index != i) | ||||
|             { | ||||
|                 array[index] ^= array[i]; | ||||
|                 array[i] ^= array[index]; | ||||
|                 array[index] ^= array[i]; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										231
									
								
								src/main/java/jobshop/solvers/TabooSolver.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								src/main/java/jobshop/solvers/TabooSolver.java
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,231 @@ | |||
| package jobshop.solvers; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.Arrays; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import jobshop.Instance; | ||||
| import jobshop.Result; | ||||
| import jobshop.Schedule; | ||||
| import jobshop.Solver; | ||||
| import jobshop.Result.ExitCause; | ||||
| import jobshop.encodings.ResourceOrder; | ||||
| import jobshop.encodings.Task; | ||||
| import jobshop.solvers.GreedySolver.PriorityESTRule; | ||||
| import jobshop.solvers.GreedySolver.PriorityRule; | ||||
| import jobshop.solvers.DescentSolver.*; | ||||
| 
 | ||||
| 
 | ||||
| public class TabooSolver implements Solver { | ||||
| 	 | ||||
| 	private PriorityRule priorityRule; | ||||
| 	private PriorityESTRule priorityESTRule; | ||||
| 	private int dureeTaboo; | ||||
| 	private int maxIter; | ||||
| 	 | ||||
| 	// 2 constructors: the default and one with the EST restriction | ||||
| 	public TabooSolver(PriorityRule rule, int dureeTaboo, int maxIter) { | ||||
| 		super(); | ||||
| 		this.priorityRule = rule; | ||||
| 		this.priorityESTRule = null; | ||||
| 		this.dureeTaboo = dureeTaboo; | ||||
| 		this.maxIter = maxIter; | ||||
| 	} | ||||
| 	 | ||||
| 	public TabooSolver(PriorityESTRule ruleEST, int dureeTaboo, int maxIter) { | ||||
| 		super(); | ||||
| 		this.priorityESTRule = ruleEST; | ||||
| 		this.priorityRule = null; | ||||
| 		this.dureeTaboo = dureeTaboo; | ||||
| 		this.maxIter = maxIter; | ||||
| 	} | ||||
| 	 | ||||
| 	 | ||||
| 	// ************************************************************************************************************* // | ||||
| 	// *************************************** TabooSolver: solve Method ******************************************* // | ||||
| 	// ************************************************************************************************************* // | ||||
| 	 | ||||
|     @Override | ||||
|     public Result solve(Instance instance, long deadline) { | ||||
|     	// Choosing rule (SPT / LRPT / EST_SPT / EST_LRPT) | ||||
|     	GreedySolver greedy = null; | ||||
|     	if(priorityESTRule == null) { | ||||
|     		PriorityRule currentRule = this.priorityRule; | ||||
|     		greedy = new GreedySolver(currentRule); | ||||
|     	} else if(priorityRule == null) { | ||||
|     		PriorityESTRule currentESTRule = this.priorityESTRule; | ||||
|     		greedy = new GreedySolver(currentESTRule); | ||||
|     	} else { | ||||
|     		System.out.printf("Error priorityRule and priorityRuleEST are null. You must give a value to one of them."); | ||||
|     	} | ||||
|     	 | ||||
|         // Generating a viable solution | ||||
|     	Result result = greedy.solve(instance, deadline); | ||||
|     	Schedule initialSolution = result.schedule; | ||||
|     	ResourceOrder initialResourceOrder = new ResourceOrder(initialSolution); | ||||
|          | ||||
|     	// Declaring all solution types | ||||
|     	ResourceOrder bestRO         = initialResourceOrder; // s* | ||||
|     	ResourceOrder currentRO      = bestRO.copy();		 // s | ||||
|     	ResourceOrder bestNeighborRO = bestRO.copy();		 // s'  | ||||
|     	ResourceOrder neighborRO;							 // s'' | ||||
|     	 | ||||
| 		// Defining the sTaboo variables | ||||
|     	int totalTasks = instance.numJobs * instance.numTasks; | ||||
| 		int[][] sTaboo = new int[totalTasks][totalTasks]; | ||||
| 		// Initializing sTaboo with all 0 | ||||
| 		for (int[] row : sTaboo) { | ||||
| 			Arrays.fill(row, 0); | ||||
| 		} | ||||
| 		 | ||||
|     	// Declaring other variables | ||||
| 		List<Block> criticalBlockList; | ||||
|     	int TASK_PER_JOB, j1, i1, j2, i2, taskID1, taskID2, forbiddenTaskID1, forbiddenTaskID2; | ||||
|     	int bestMakespan = initialSolution.makespan(); | ||||
|     	int bestNeighborMakespan, neighborMakespan; | ||||
|     	boolean updated; | ||||
|     	 | ||||
|     	// Iteration Counter | ||||
|     	int k = 0; | ||||
| 
 | ||||
|         while (deadline > System.currentTimeMillis() && k <= this.maxIter) { | ||||
|         	// ***************** 1. k <- k + 1 ******************************************************** // | ||||
|             k++; | ||||
|              | ||||
|             // ***************** 2. Choose the best neighbor s' that is not in sTaboo ***************** // | ||||
|             bestNeighborMakespan = Integer.MAX_VALUE; | ||||
|             forbiddenTaskID1 = -1;  | ||||
|             forbiddenTaskID2 = -1; | ||||
|             updated = false; | ||||
|     		 | ||||
|             // We first take the critical path from the currentRO (s) | ||||
|     		currentRO = bestNeighborRO.copy(); // (s <- s') | ||||
|         	criticalBlockList = this.blocksOfCriticalPath(currentRO); | ||||
|         	 | ||||
|             for(Block b : criticalBlockList) { | ||||
|                 for(Swap s : neighbors(b)) { | ||||
|                 	// Extract the current index values for sTaboo | ||||
|         			TASK_PER_JOB = currentRO.instance.numTasks; | ||||
|         			j1 = currentRO.tasksByMachine[s.machine][s.t1].job; | ||||
|          			j2 = currentRO.tasksByMachine[s.machine][s.t2].job; | ||||
|         			i1 = currentRO.tasksByMachine[s.machine][s.t1].task; | ||||
|         			i2 = currentRO.tasksByMachine[s.machine][s.t2].task; | ||||
|         			taskID1 = j1 * TASK_PER_JOB + i1; | ||||
|         			taskID2 = j2 * TASK_PER_JOB + i2; | ||||
|         			 | ||||
|                     // Check if it is a forbidden swap | ||||
|                     if(sTaboo[taskID1][taskID2] < k) { | ||||
|                     	updated= true; | ||||
|                         neighborRO = currentRO.copy(); | ||||
|                         // We apply the swap on the current Resource Order and we schedule it to find its makespan | ||||
|                         s.applyOn(neighborRO); | ||||
|                         neighborMakespan = neighborRO.toSchedule().makespan();                         | ||||
|                          | ||||
|                         if(neighborMakespan < bestNeighborMakespan) { | ||||
|                         	// We forbid the opposite permutation of the given tasks (in index taskID1 and taskID2) | ||||
|                         	forbiddenTaskID1 = taskID1; | ||||
|                         	forbiddenTaskID2 = taskID2; | ||||
|                             // We have checked all neighbors and we have chosen the best one: bestNeighborRO | ||||
|                         	bestNeighborMakespan = neighborMakespan; | ||||
|                             bestNeighborRO = neighborRO.copy(); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             // ************************ 3. Add bestNeighborSolution (s') to sTaboo *************************** // | ||||
|             // If it is not updated it means all solutions are forbidden | ||||
|             if(updated) { | ||||
|             	sTaboo[forbiddenTaskID2][forbiddenTaskID1] = this.dureeTaboo + k; | ||||
|             	// ******************** 4. If s' is better than s* then s* <- s' ************************** // | ||||
|                 if(bestNeighborMakespan < bestMakespan) { | ||||
|                 	bestMakespan = bestNeighborMakespan; | ||||
|                 	bestRO = bestNeighborRO.copy(); | ||||
|                 } | ||||
|             }  | ||||
|         } | ||||
|     	// We find the exit cause in order to create the result we will return | ||||
|     	ExitCause exitCause = null; | ||||
|     	if(deadline <= System.currentTimeMillis()) { | ||||
|     		exitCause = ExitCause.Timeout; | ||||
|     	} else if(k >= this.maxIter) { | ||||
|     		exitCause = ExitCause.Blocked; | ||||
|     	} else { | ||||
|     		exitCause = ExitCause.ProvedOptimal; | ||||
|     	} | ||||
|     	return new Result(instance, bestRO.toSchedule(), exitCause); | ||||
|     } | ||||
|     // ************************************************************************************************************* // | ||||
|      | ||||
|      | ||||
|     // ************************************************************************************************************* // | ||||
|     // ********************************** Copied functions from DescentSolver ************************************** // | ||||
|     // ************************************************************************************************************* // | ||||
|      | ||||
|     /** Returns a list of all blocks of the critical path. */ | ||||
|     private List<Block> blocksOfCriticalPath(ResourceOrder order) { | ||||
|      	List<Block> criticalBlockList = new ArrayList<>(); | ||||
|      	Block currentBlock; | ||||
|      	// Obtain the critical task list from the resource order instance | ||||
|          Schedule criticalSchedule = order.toSchedule(); | ||||
|          List<Task> criticalTaskList = criticalSchedule.criticalPath(); | ||||
|           | ||||
|          int totalNumMachines = criticalSchedule.pb.numMachines; | ||||
|          int totalNumJobs     = criticalSchedule.pb.numJobs; | ||||
|           | ||||
|          Task currentTaskRO; | ||||
|          int currentTaskIndexRO, currentCriticalTaskIndex, firstTask, lastTask; | ||||
|           | ||||
|          // We check for all machines | ||||
|          for(int currentMachine = 0; currentMachine < totalNumMachines; currentMachine++) { | ||||
|          	currentTaskIndexRO = 0; | ||||
|              while(currentTaskIndexRO < (totalNumJobs-1)){ | ||||
|                  currentTaskRO = order.tasksByMachine[currentMachine][currentTaskIndexRO]; | ||||
|                  if (criticalTaskList.contains(currentTaskRO)) { | ||||
|                      currentCriticalTaskIndex = criticalTaskList.indexOf(currentTaskRO); | ||||
|                      //If the next task in the critical path is running in the same machine try find the last task index | ||||
|                      if(currentMachine == criticalSchedule.pb.machine(criticalTaskList.get(currentCriticalTaskIndex+1))) { | ||||
|                          firstTask = currentTaskIndexRO; | ||||
|                          while(currentCriticalTaskIndex < (criticalTaskList.size()-1) && currentMachine == criticalSchedule.pb.machine(criticalTaskList.get(currentCriticalTaskIndex+1))){ | ||||
|                          	// We advance in the list | ||||
|                              currentCriticalTaskIndex++; | ||||
|                              // We have to also advance in the resource order | ||||
|                              currentTaskIndexRO++; | ||||
|                          } | ||||
|                          // Create and add the new block to the list | ||||
|                          lastTask = currentTaskIndexRO; | ||||
|                  	    currentBlock = new Block(currentMachine, firstTask, lastTask); | ||||
|                          criticalBlockList.add(currentBlock); | ||||
|                      } | ||||
|                  } | ||||
|                  // We move on to the next task in the resource order | ||||
|                  currentTaskIndexRO++; | ||||
|              } | ||||
|          } | ||||
|          return criticalBlockList; | ||||
|      } | ||||
| 
 | ||||
|     /** For a given block, return the possible swaps for the Nowicki and Smutnicki neighborhood */ | ||||
|     private List<Swap> neighbors(Block block) { | ||||
|     	List<Swap> swapList = new ArrayList<>(); | ||||
|     	Swap swap1; | ||||
|     	Swap swap2; | ||||
|     	 | ||||
|     	int machine   = block.machine; | ||||
|     	int firstTask = block.firstTask; | ||||
|     	int lastTask  = block.lastTask; | ||||
|     	 | ||||
|     	// One single swap if there are just 2 elements in the block, two swaps if there are more than 2. | ||||
|  		if(firstTask + 1 == lastTask) { | ||||
|  			swap1 = new Swap(machine, firstTask, lastTask); | ||||
|  			swapList.add(swap1); | ||||
|  		} else { | ||||
|  			swap1 = new Swap(machine, firstTask, firstTask+1); | ||||
|  			swap2 = new Swap(machine, lastTask-1 , lastTask); | ||||
|  			swapList.add(swap1); | ||||
|  			swapList.add(swap2); | ||||
|  		} | ||||
|         return swapList; | ||||
|     } | ||||
| 		 | ||||
|     // ************************************************************************************************************* // | ||||
| } | ||||
|  | @ -1,103 +1,75 @@ | |||
| package jobshop.encodings; | ||||
| 
 | ||||
| import jobshop.Instance; | ||||
| import jobshop.Result; | ||||
| import jobshop.Schedule; | ||||
| import jobshop.Solver; | ||||
| import jobshop.solvers.BasicSolver; | ||||
| import jobshop.solvers.GreedySolver; | ||||
| import jobshop.solvers.GreedySolver.PriorityRule; | ||||
| 
 | ||||
| import org.junit.Test; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.nio.file.Paths; | ||||
| 
 | ||||
| public class EncodingTests { | ||||
| 
 | ||||
|     @Test | ||||
|     public void testJobNumbers() throws IOException { | ||||
|         Instance instance = Instance.fromFile(Paths.get("instances/aaa1")); | ||||
| 
 | ||||
|         // numéro de jobs : 1 2 2 1 1 2 (cf exercices) | ||||
|         JobNumbers enc = new JobNumbers(instance); | ||||
|         enc.jobs[enc.nextToSet++] = 0; | ||||
|         enc.jobs[enc.nextToSet++] = 1; | ||||
|         enc.jobs[enc.nextToSet++] = 1; | ||||
|         enc.jobs[enc.nextToSet++] = 0; | ||||
|         enc.jobs[enc.nextToSet++] = 0; | ||||
|         enc.jobs[enc.nextToSet++] = 1; | ||||
| 
 | ||||
|         Schedule sched = enc.toSchedule(); | ||||
|         // TODO: make it print something meaningful | ||||
|         // by implementing the toString() method | ||||
|         System.out.println(sched); | ||||
|         assert sched.isValid(); | ||||
|         assert sched.makespan() == 12; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         // numéro de jobs : 1 1 2 2 1 2 | ||||
|         enc = new JobNumbers(instance); | ||||
|         enc.jobs[enc.nextToSet++] = 0; | ||||
|         enc.jobs[enc.nextToSet++] = 0; | ||||
|         enc.jobs[enc.nextToSet++] = 1; | ||||
|         enc.jobs[enc.nextToSet++] = 1; | ||||
|         enc.jobs[enc.nextToSet++] = 0; | ||||
|         enc.jobs[enc.nextToSet++] = 1; | ||||
| 
 | ||||
|         sched = enc.toSchedule(); | ||||
|         assert sched.isValid(); | ||||
|         assert sched.makespan() == 14; | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testBasicSolver() throws IOException { | ||||
|         Instance instance = Instance.fromFile(Paths.get("instances/aaa1")); | ||||
| 
 | ||||
|         // build a solution that should be equal to the result of BasicSolver | ||||
|         JobNumbers enc = new JobNumbers(instance); | ||||
|         enc.jobs[enc.nextToSet++] = 0; | ||||
|         enc.jobs[enc.nextToSet++] = 1; | ||||
|         enc.jobs[enc.nextToSet++] = 0; | ||||
|         enc.jobs[enc.nextToSet++] = 1; | ||||
|         enc.jobs[enc.nextToSet++] = 0; | ||||
|         enc.jobs[enc.nextToSet++] = 1; | ||||
| 
 | ||||
|         Schedule sched = enc.toSchedule(); | ||||
|         assert sched.isValid(); | ||||
|         assert sched.makespan() == 12; | ||||
| 
 | ||||
|         Solver solver = new BasicSolver(); | ||||
|         Result result = solver.solve(instance, System.currentTimeMillis() + 10); | ||||
| 
 | ||||
|         assert result.schedule.isValid(); | ||||
|         assert result.schedule.makespan() == sched.makespan(); // should have the same makespan | ||||
|     } | ||||
|      | ||||
|     @Test | ||||
|     public void testGreedySolver() throws IOException { | ||||
|         Instance instance = Instance.fromFile(Paths.get("instances/aaa1")); | ||||
| 
 | ||||
|         // build a solution that should be equal to the result of BasicSolver | ||||
|         JobNumbers enc = new JobNumbers(instance); | ||||
|         enc.jobs[enc.nextToSet++] = 0; | ||||
|         enc.jobs[enc.nextToSet++] = 1; | ||||
|         enc.jobs[enc.nextToSet++] = 0; | ||||
|         enc.jobs[enc.nextToSet++] = 1; | ||||
|         enc.jobs[enc.nextToSet++] = 0; | ||||
|         enc.jobs[enc.nextToSet++] = 1; | ||||
| 
 | ||||
|         Schedule sched = enc.toSchedule(); | ||||
|         assert sched.isValid(); | ||||
|         assert sched.makespan() == 12; | ||||
|          | ||||
|         PriorityRule priorityRule = PriorityRule.SPT; | ||||
|         Solver solver = new GreedySolver(priorityRule); | ||||
|         Result result = solver.solve(instance, System.currentTimeMillis() + 10); | ||||
| 
 | ||||
|         assert result.schedule.isValid(); | ||||
|         assert result.schedule.makespan() == sched.makespan(); // should have the same makespan | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| package jobshop.encodings; | ||||
| 
 | ||||
| import jobshop.Instance; | ||||
| import jobshop.Result; | ||||
| import jobshop.Schedule; | ||||
| import jobshop.Solver; | ||||
| import jobshop.solvers.BasicSolver; | ||||
| import org.junit.Test; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.nio.file.Paths; | ||||
| 
 | ||||
| public class EncodingTests { | ||||
| 
 | ||||
|     @Test | ||||
|     public void testJobNumbers() throws IOException { | ||||
|         Instance instance = Instance.fromFile(Paths.get("instances/aaa1")); | ||||
| 
 | ||||
|         // numéro de jobs : 1 2 2 1 1 2 (cf exercices) | ||||
|         JobNumbers enc = new JobNumbers(instance); | ||||
|         enc.jobs[enc.nextToSet++] = 0; | ||||
|         enc.jobs[enc.nextToSet++] = 1; | ||||
|         enc.jobs[enc.nextToSet++] = 1; | ||||
|         enc.jobs[enc.nextToSet++] = 0; | ||||
|         enc.jobs[enc.nextToSet++] = 0; | ||||
|         enc.jobs[enc.nextToSet++] = 1; | ||||
| 
 | ||||
|         Schedule sched = enc.toSchedule(); | ||||
|         // TODO: make it print something meaningful | ||||
|         // by implementing the toString() method | ||||
|         System.out.println(sched); | ||||
|         assert sched.isValid(); | ||||
|         assert sched.makespan() == 12; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         // numéro de jobs : 1 1 2 2 1 2 | ||||
|         enc = new JobNumbers(instance); | ||||
|         enc.jobs[enc.nextToSet++] = 0; | ||||
|         enc.jobs[enc.nextToSet++] = 0; | ||||
|         enc.jobs[enc.nextToSet++] = 1; | ||||
|         enc.jobs[enc.nextToSet++] = 1; | ||||
|         enc.jobs[enc.nextToSet++] = 0; | ||||
|         enc.jobs[enc.nextToSet++] = 1; | ||||
| 
 | ||||
|         sched = enc.toSchedule(); | ||||
|         assert sched.isValid(); | ||||
|         assert sched.makespan() == 14; | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testBasicSolver() throws IOException { | ||||
|         Instance instance = Instance.fromFile(Paths.get("instances/aaa1")); | ||||
| 
 | ||||
|         // build a solution that should be equal to the result of BasicSolver | ||||
|         JobNumbers enc = new JobNumbers(instance); | ||||
|         enc.jobs[enc.nextToSet++] = 0; | ||||
|         enc.jobs[enc.nextToSet++] = 1; | ||||
|         enc.jobs[enc.nextToSet++] = 0; | ||||
|         enc.jobs[enc.nextToSet++] = 1; | ||||
|         enc.jobs[enc.nextToSet++] = 0; | ||||
|         enc.jobs[enc.nextToSet++] = 1; | ||||
| 
 | ||||
|         Schedule sched = enc.toSchedule(); | ||||
|         assert sched.isValid(); | ||||
|         assert sched.makespan() == 12; | ||||
| 
 | ||||
|         Solver solver = new BasicSolver(); | ||||
|         Result result = solver.solve(instance, System.currentTimeMillis() + 10); | ||||
| 
 | ||||
|         assert result.schedule.isValid(); | ||||
|         assert result.schedule.makespan() == sched.makespan(); // should have the same makespan | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue