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 | # Example instance | ||||||
| 3 3 # num-jobs num-tasks | 3 3 # num-jobs num-tasks | ||||||
| 2  3  0  3  1  2 | 2  4  0  3  1  2 | ||||||
| 1  7  0  6  2  5 | 1  7  0  6  2  5 | ||||||
| 0  2  1 10  2  4 | 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; | package jobshop; | ||||||
| 
 | 
 | ||||||
| import java.util.Arrays; | import java.util.Arrays; | ||||||
| import java.util.HashMap; | import java.util.HashMap; | ||||||
| 
 | import java.util.List; | ||||||
| public class BestKnownResult { | import java.util.stream.Collectors; | ||||||
| 
 | 
 | ||||||
|     public static boolean isKnown(String instanceName) { | public class BestKnownResult { | ||||||
|         return bests.containsKey(instanceName); | 
 | ||||||
|     } |     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); |     public static List<String> instancesMatching(String namePrefix) { | ||||||
|         } |         return Arrays.stream(instances) | ||||||
|         return bests.get(instanceName); |                 .filter(i -> i.startsWith(namePrefix)) | ||||||
|     } |                 .sorted() | ||||||
| 
 |                 .collect(Collectors.toList()); | ||||||
|     static private HashMap<String, Integer> bests; |     } | ||||||
|     static String[] instances; | 
 | ||||||
|     static { |     public static int of(String instanceName) { | ||||||
|         bests = new HashMap<>(); |         if(!bests.containsKey(instanceName)) { | ||||||
|         bests.put("aaa1", 11); |             throw new RuntimeException("Unknown best result for "+instanceName); | ||||||
|         bests.put("abz5", 1234); |         } | ||||||
|         bests.put("abz6", 943); |         return bests.get(instanceName); | ||||||
|         bests.put("abz7", 656); |     } | ||||||
|         bests.put("abz8", 665); | 
 | ||||||
|         bests.put("abz9", 679); |     static private HashMap<String, Integer> bests; | ||||||
|         bests.put("ft06", 55); |     static String[] instances; | ||||||
|         bests.put("ft10", 930); |     static { | ||||||
|         bests.put("ft20", 1165); |         bests = new HashMap<>(); | ||||||
|         bests.put("la01", 666); |         bests.put("aaa1", 11); | ||||||
|         bests.put("la02", 655); |         bests.put("abz5", 1234); | ||||||
|         bests.put("la03", 597); |         bests.put("abz6", 943); | ||||||
|         bests.put("la04", 590); |         bests.put("abz7", 656); | ||||||
|         bests.put("la05", 593); |         bests.put("abz8", 665); | ||||||
|         bests.put("la06", 926); |         bests.put("abz9", 679); | ||||||
|         bests.put("la07", 890); |         bests.put("ft06", 55); | ||||||
|         bests.put("la08", 863); |         bests.put("ft10", 930); | ||||||
|         bests.put("la09", 951); |         bests.put("ft20", 1165); | ||||||
|         bests.put("la10", 958); |         bests.put("la01", 666); | ||||||
|         bests.put("la11", 1222); |         bests.put("la02", 655); | ||||||
|         bests.put("la12", 1039); |         bests.put("la03", 597); | ||||||
|         bests.put("la13", 1150); |         bests.put("la04", 590); | ||||||
|         bests.put("la14", 1292); |         bests.put("la05", 593); | ||||||
|         bests.put("la15", 1207); |         bests.put("la06", 926); | ||||||
|         bests.put("la16", 945); |         bests.put("la07", 890); | ||||||
|         bests.put("la17", 784); |         bests.put("la08", 863); | ||||||
|         bests.put("la18", 848); |         bests.put("la09", 951); | ||||||
|         bests.put("la19", 842); |         bests.put("la10", 958); | ||||||
|         bests.put("la20", 902); |         bests.put("la11", 1222); | ||||||
|         bests.put("la21", 1046); |         bests.put("la12", 1039); | ||||||
|         bests.put("la22", 927); |         bests.put("la13", 1150); | ||||||
|         bests.put("la23", 1032); |         bests.put("la14", 1292); | ||||||
|         bests.put("la24", 935); |         bests.put("la15", 1207); | ||||||
|         bests.put("la25", 977); |         bests.put("la16", 945); | ||||||
|         bests.put("la26", 1218); |         bests.put("la17", 784); | ||||||
|         bests.put("la27", 1235); |         bests.put("la18", 848); | ||||||
|         bests.put("la28", 1216); |         bests.put("la19", 842); | ||||||
|         bests.put("la29", 1152); |         bests.put("la20", 902); | ||||||
|         bests.put("la30", 1355); |         bests.put("la21", 1046); | ||||||
|         bests.put("la31", 1784); |         bests.put("la22", 927); | ||||||
|         bests.put("la32", 1850); |         bests.put("la23", 1032); | ||||||
|         bests.put("la33", 1719); |         bests.put("la24", 935); | ||||||
|         bests.put("la34", 1721); |         bests.put("la25", 977); | ||||||
|         bests.put("la35", 1888); |         bests.put("la26", 1218); | ||||||
|         bests.put("la36", 1268); |         bests.put("la27", 1235); | ||||||
|         bests.put("la37", 1397); |         bests.put("la28", 1216); | ||||||
|         bests.put("la38", 1196); |         bests.put("la29", 1152); | ||||||
|         bests.put("la39", 1233); |         bests.put("la30", 1355); | ||||||
|         bests.put("la40", 1222); |         bests.put("la31", 1784); | ||||||
|         bests.put("orb01", 1059); |         bests.put("la32", 1850); | ||||||
|         bests.put("orb02", 888); |         bests.put("la33", 1719); | ||||||
|         bests.put("orb03", 1005); |         bests.put("la34", 1721); | ||||||
|         bests.put("orb04", 1005); |         bests.put("la35", 1888); | ||||||
|         bests.put("orb05", 887); |         bests.put("la36", 1268); | ||||||
|         bests.put("orb06", 1010); |         bests.put("la37", 1397); | ||||||
|         bests.put("orb07", 397); |         bests.put("la38", 1196); | ||||||
|         bests.put("orb08", 899); |         bests.put("la39", 1233); | ||||||
|         bests.put("orb09", 934); |         bests.put("la40", 1222); | ||||||
|         bests.put("orb10", 944); |         bests.put("orb01", 1059); | ||||||
|         bests.put("swv01", 1407); |         bests.put("orb02", 888); | ||||||
|         bests.put("swv02", 1475); |         bests.put("orb03", 1005); | ||||||
|         bests.put("swv03", 1398); |         bests.put("orb04", 1005); | ||||||
|         bests.put("swv04", 1474); |         bests.put("orb05", 887); | ||||||
|         bests.put("swv05", 1424); |         bests.put("orb06", 1010); | ||||||
|         bests.put("swv06", 1678); |         bests.put("orb07", 397); | ||||||
|         bests.put("swv07", 1600); |         bests.put("orb08", 899); | ||||||
|         bests.put("swv08", 1763); |         bests.put("orb09", 934); | ||||||
|         bests.put("swv09", 1661); |         bests.put("orb10", 944); | ||||||
|         bests.put("swv10", 1767); |         bests.put("swv01", 1407); | ||||||
|         bests.put("swv11", 2991); |         bests.put("swv02", 1475); | ||||||
|         bests.put("swv12", 3003); |         bests.put("swv03", 1398); | ||||||
|         bests.put("swv13", 3104); |         bests.put("swv04", 1474); | ||||||
|         bests.put("swv14", 2968); |         bests.put("swv05", 1424); | ||||||
|         bests.put("swv15", 2904); |         bests.put("swv06", 1678); | ||||||
|         bests.put("swv16", 2924); |         bests.put("swv07", 1600); | ||||||
|         bests.put("swv17", 2794); |         bests.put("swv08", 1763); | ||||||
|         bests.put("swv18", 2852); |         bests.put("swv09", 1661); | ||||||
|         bests.put("swv19", 2843); |         bests.put("swv10", 1767); | ||||||
|         bests.put("swv20", 2823); |         bests.put("swv11", 2991); | ||||||
|         bests.put("yn1", 885); |         bests.put("swv12", 3003); | ||||||
|         bests.put("yn2", 909); |         bests.put("swv13", 3104); | ||||||
|         bests.put("yn3", 892); |         bests.put("swv14", 2968); | ||||||
|         bests.put("yn4", 968); |         bests.put("swv15", 2904); | ||||||
|         bests.put("ta01", 1231); |         bests.put("swv16", 2924); | ||||||
|         bests.put("ta02", 1244); |         bests.put("swv17", 2794); | ||||||
|         bests.put("ta03", 1218); |         bests.put("swv18", 2852); | ||||||
|         bests.put("ta04", 1175); |         bests.put("swv19", 2843); | ||||||
|         bests.put("ta05", 1224); |         bests.put("swv20", 2823); | ||||||
|         bests.put("ta06", 1238); |         bests.put("yn1", 885); | ||||||
|         bests.put("ta07", 1227); |         bests.put("yn2", 909); | ||||||
|         bests.put("ta08", 1217); |         bests.put("yn3", 892); | ||||||
|         bests.put("ta09", 1274); |         bests.put("yn4", 968); | ||||||
|         bests.put("ta10", 1241); |         bests.put("ta01", 1231); | ||||||
|         bests.put("ta11", 1361); |         bests.put("ta02", 1244); | ||||||
|         bests.put("ta12", 1367); |         bests.put("ta03", 1218); | ||||||
|         bests.put("ta13", 1342); |         bests.put("ta04", 1175); | ||||||
|         bests.put("ta14", 1345); |         bests.put("ta05", 1224); | ||||||
|         bests.put("ta15", 1340); |         bests.put("ta06", 1238); | ||||||
|         bests.put("ta16", 1360); |         bests.put("ta07", 1227); | ||||||
|         bests.put("ta17", 1462); |         bests.put("ta08", 1217); | ||||||
|         bests.put("ta18", 1396); |         bests.put("ta09", 1274); | ||||||
|         bests.put("ta19", 1335); |         bests.put("ta10", 1241); | ||||||
|         bests.put("ta20", 1351); |         bests.put("ta11", 1361); | ||||||
|         bests.put("ta21", 1644); |         bests.put("ta12", 1367); | ||||||
|         bests.put("ta22", 1600); |         bests.put("ta13", 1342); | ||||||
|         bests.put("ta23", 1557); |         bests.put("ta14", 1345); | ||||||
|         bests.put("ta24", 1647); |         bests.put("ta15", 1340); | ||||||
|         bests.put("ta25", 1595); |         bests.put("ta16", 1360); | ||||||
|         bests.put("ta26", 1645); |         bests.put("ta17", 1462); | ||||||
|         bests.put("ta27", 1680); |         bests.put("ta18", 1396); | ||||||
|         bests.put("ta28", 1614); |         bests.put("ta19", 1335); | ||||||
|         bests.put("ta29", 1635); |         bests.put("ta20", 1351); | ||||||
|         bests.put("ta30", 1584); |         bests.put("ta21", 1644); | ||||||
|         bests.put("ta31", 1764); |         bests.put("ta22", 1600); | ||||||
|         bests.put("ta32", 1796); |         bests.put("ta23", 1557); | ||||||
|         bests.put("ta33", 1793); |         bests.put("ta24", 1647); | ||||||
|         bests.put("ta34", 1829); |         bests.put("ta25", 1595); | ||||||
|         bests.put("ta35", 2007); |         bests.put("ta26", 1645); | ||||||
|         bests.put("ta36", 1819); |         bests.put("ta27", 1680); | ||||||
|         bests.put("ta37", 1778); |         bests.put("ta28", 1614); | ||||||
|         bests.put("ta38", 1673); |         bests.put("ta29", 1635); | ||||||
|         bests.put("ta39", 1795); |         bests.put("ta30", 1584); | ||||||
|         bests.put("ta40", 1674); |         bests.put("ta31", 1764); | ||||||
|         bests.put("ta41", 2018); |         bests.put("ta32", 1796); | ||||||
|         bests.put("ta42", 1956); |         bests.put("ta33", 1793); | ||||||
|         bests.put("ta43", 1859); |         bests.put("ta34", 1829); | ||||||
|         bests.put("ta44", 1984); |         bests.put("ta35", 2007); | ||||||
|         bests.put("ta45", 2000); |         bests.put("ta36", 1819); | ||||||
|         bests.put("ta46", 2021); |         bests.put("ta37", 1778); | ||||||
|         bests.put("ta47", 1903); |         bests.put("ta38", 1673); | ||||||
|         bests.put("ta48", 1952); |         bests.put("ta39", 1795); | ||||||
|         bests.put("ta49", 1968); |         bests.put("ta40", 1674); | ||||||
|         bests.put("ta50", 1926); |         bests.put("ta41", 2018); | ||||||
|         bests.put("ta51", 2760); |         bests.put("ta42", 1956); | ||||||
|         bests.put("ta52", 2756); |         bests.put("ta43", 1859); | ||||||
|         bests.put("ta53", 2717); |         bests.put("ta44", 1984); | ||||||
|         bests.put("ta54", 2839); |         bests.put("ta45", 2000); | ||||||
|         bests.put("ta55", 2679); |         bests.put("ta46", 2021); | ||||||
|         bests.put("ta56", 2781); |         bests.put("ta47", 1903); | ||||||
|         bests.put("ta57", 2943); |         bests.put("ta48", 1952); | ||||||
|         bests.put("ta58", 2885); |         bests.put("ta49", 1968); | ||||||
|         bests.put("ta59", 2655); |         bests.put("ta50", 1926); | ||||||
|         bests.put("ta60", 2723); |         bests.put("ta51", 2760); | ||||||
|         bests.put("ta61", 2868); |         bests.put("ta52", 2756); | ||||||
|         bests.put("ta62", 2869); |         bests.put("ta53", 2717); | ||||||
|         bests.put("ta63", 2755); |         bests.put("ta54", 2839); | ||||||
|         bests.put("ta64", 2702); |         bests.put("ta55", 2679); | ||||||
|         bests.put("ta65", 2725); |         bests.put("ta56", 2781); | ||||||
|         bests.put("ta66", 2845); |         bests.put("ta57", 2943); | ||||||
|         bests.put("ta67", 2825); |         bests.put("ta58", 2885); | ||||||
|         bests.put("ta68", 2784); |         bests.put("ta59", 2655); | ||||||
|         bests.put("ta69", 3071); |         bests.put("ta60", 2723); | ||||||
|         bests.put("ta70", 2995); |         bests.put("ta61", 2868); | ||||||
|         instances = bests.keySet().toArray(new String[0]); |         bests.put("ta62", 2869); | ||||||
|         Arrays.sort(instances); |         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; | package jobshop; | ||||||
| 
 | 
 | ||||||
| import jobshop.encodings.JobNumbers; | import jobshop.encodings.JobNumbers; | ||||||
| import jobshop.encodings.ResourceOrder; | import jobshop.encodings.ResourceOrder; | ||||||
| import jobshop.encodings.Task; | import jobshop.encodings.Task; | ||||||
| import jobshop.solvers.DescentSolver; | import jobshop.solvers.DescentSolver; | ||||||
| import jobshop.solvers.GreedySolver; | import jobshop.solvers.DescentSolver.Block; | ||||||
| import jobshop.solvers.DescentSolver.Block; | import jobshop.solvers.DescentSolver.Swap; | ||||||
| import jobshop.solvers.GreedySolver.PriorityESTRule; | import jobshop.solvers.GreedySolver; | ||||||
| import jobshop.solvers.GreedySolver.PriorityRule; | import jobshop.solvers.GreedySolver.PriorityESTRule; | ||||||
| 
 | import jobshop.solvers.GreedySolver.PriorityRule; | ||||||
| import java.io.IOException; | import jobshop.solvers.TabooSolver; | ||||||
| import java.nio.file.Paths; | 
 | ||||||
| import java.util.List; | import java.io.IOException; | ||||||
| 
 | import java.nio.file.Paths; | ||||||
| public class DebuggingMain { | import java.util.List; | ||||||
| 
 | 
 | ||||||
|     public static void main(String[] args) { | public class DebuggingMain { | ||||||
|         try { | 
 | ||||||
|             // load the aaa1 instance |     public static void main(String[] args) { | ||||||
|             Instance instance = Instance.fromFile(Paths.get("instances/aaa1")); |         try { | ||||||
| 
 |             // load the aaa1 instance | ||||||
|             // construit une solution dans la représentation par |             Instance instance = Instance.fromFile(Paths.get("instances/aaa1")); | ||||||
|             // numéro de jobs : [0 1 1 0 0 1] | 
 | ||||||
|             // Note : cette solution a aussi été vue dans les exercices (section 3.3) |             // construit une solution dans la représentation par | ||||||
|             //        mais on commençait à compter à 1 ce qui donnait [1 2 2 1 1 2] |             // numéro de jobs : [0 1 1 0 0 1] | ||||||
|             JobNumbers enc = new JobNumbers(instance); |             // Note : cette solution a aussi été vue dans les exercices (section 3.3) | ||||||
|             enc.jobs[enc.nextToSet++] = 0; |             //        mais on commençait à compter à 1 ce qui donnait [1 2 2 1 1 2] | ||||||
|             enc.jobs[enc.nextToSet++] = 0; |             JobNumbers enc = new JobNumbers(instance); | ||||||
|             enc.jobs[enc.nextToSet++] = 1; |             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; | ||||||
|             enc.jobs[enc.nextToSet++] = 1; |             enc.jobs[enc.nextToSet++] = 0; | ||||||
| 
 |             enc.jobs[enc.nextToSet++] = 0; | ||||||
|             System.out.println("\nJOB NUMBER ENCODING: " + enc + "\n"); |             enc.jobs[enc.nextToSet++] = 1; | ||||||
| 
 | 
 | ||||||
|             Schedule sched = enc.toSchedule(); |             System.out.println("\nENCODING: " + enc); | ||||||
|              | 
 | ||||||
|             System.out.println("SCHEDULE:\n" + sched); |             Schedule sched = enc.toSchedule(); | ||||||
|             System.out.println("VALID: " + sched.isValid() + "\n"); |             // TODO: make it print something meaningful | ||||||
|             System.out.println("MAKESPAN: " + sched.makespan() + "\n"); |             // by implementing the toString() method | ||||||
|              |             System.out.println("SCHEDULE: " + sched); | ||||||
|             System.out.println("---------------------------------------------\n"); |             System.out.println("VALID: " + sched.isValid()); | ||||||
|          |             System.out.println("MAKESPAN: " + sched.makespan()); | ||||||
|             ResourceOrder ro = new ResourceOrder(instance); |              | ||||||
|             ro.tasksByMachine[0][0] = new Task(0,0); |             System.out.println("---------------------------------------------\n"); | ||||||
|             ro.tasksByMachine[0][1] = new Task(1,1); |              | ||||||
|             ro.tasksByMachine[1][0] = new Task(1,0); |             ResourceOrder ro = new ResourceOrder(instance); | ||||||
|             ro.tasksByMachine[1][1] = new Task(0,1); |             ro.tasksByMachine[0][0] = new Task(0,0); | ||||||
|             ro.tasksByMachine[2][0] = new Task(0,2); |             ro.tasksByMachine[0][1] = new Task(1,1); | ||||||
|             ro.tasksByMachine[2][1] = new Task(1,2); |             ro.tasksByMachine[1][0] = new Task(1,0); | ||||||
|              |             ro.tasksByMachine[1][1] = new Task(0,1); | ||||||
|             System.out.println("RESOURCE ORDER ENCODING:\n" + ro + "\n"); |             ro.tasksByMachine[2][0] = new Task(0,2); | ||||||
|              |             ro.tasksByMachine[2][1] = new Task(1,2); | ||||||
|             System.out.println("---------------------------------------------\n"); |              | ||||||
|              |             System.out.println("RESOURCE ORDER ENCODING:\n" + ro + "\n"); | ||||||
|             // load the aaa2 instance |              | ||||||
|             Instance instance2 = Instance.fromFile(Paths.get("instances/aaa2")); |             System.out.println("---------------------------------------------\n"); | ||||||
|              |              | ||||||
|             ResourceOrder ro2 = new ResourceOrder(instance2); |             // load the aaa2 instance | ||||||
|             ro2.tasksByMachine[0][0] = new Task(2,0); //O7: Job 2, Task 0 (Machine 0) |             Instance instance2 = Instance.fromFile(Paths.get("instances/aaa2")); | ||||||
|             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) |             ResourceOrder ro2 = new ResourceOrder(instance2); | ||||||
|             ro2.tasksByMachine[1][0] = new Task(1,0); //O4: Job 1, Task 0 (Machine 1) |             ro2.tasksByMachine[0][0] = new Task(2,0); //O7: Job 2, Task 0 (Machine 0) | ||||||
|             ro2.tasksByMachine[1][1] = new Task(2,1); //O8: Job 2, Task 1 (Machine 1) |             ro2.tasksByMachine[0][1] = new Task(1,1); //O5: Job 1, Task 1 (Machine 0) | ||||||
|             ro2.tasksByMachine[1][2] = new Task(0,2); //O3: Job 0, Task 2 (Machine 1) |             ro2.tasksByMachine[0][2] = new Task(0,1); //O2: Job 0, Task 1 (Machine 0) | ||||||
|             ro2.tasksByMachine[2][0] = new Task(2,2); //O9: Job 2, Task 2 (Machine 2) |             ro2.tasksByMachine[1][0] = new Task(1,0); //O4: Job 1, Task 0 (Machine 1) | ||||||
|             ro2.tasksByMachine[2][1] = new Task(0,0); //O1: Job 0, Task 0 (Machine 2) |             ro2.tasksByMachine[1][1] = new Task(2,1); //O8: Job 2, Task 1 (Machine 1) | ||||||
|             ro2.tasksByMachine[2][2] = new Task(1,2); //O6: Job 1, Task 2 (Machine 2) |             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) | ||||||
|             System.out.println("RESOURCE ORDER ENCODING:\n" + ro2 + "\n"); |             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("---------------------------------------------\n"); |              | ||||||
|              |             System.out.println("RESOURCE ORDER ENCODING:\n" + ro2 + "\n"); | ||||||
|             System.out.println("Default Solver\n"); |              | ||||||
|             sched = ro.toSchedule(); |             System.out.println("---------------------------------------------\n"); | ||||||
|              |              | ||||||
|             System.out.println("SCHEDULE:\n" + sched); |             System.out.println("Default Solver\n"); | ||||||
|             System.out.println("VALID: " + sched.isValid()); |             sched = ro.toSchedule(); | ||||||
|             System.out.println("MAKESPAN: " + sched.makespan()); |              | ||||||
|              |             System.out.println("SCHEDULE:\n" + sched); | ||||||
|             System.out.println("---------------------------------------------\n"); |             System.out.println("VALID: " + sched.isValid()); | ||||||
|              |             System.out.println("MAKESPAN: " + sched.makespan()); | ||||||
|             JobNumbers jo = JobNumbers.fromSchedule(sched); |              | ||||||
|             System.out.println("JOB NUMBER ENCODING (FROM_SCHEDULE): " + jo + "\n"); |             System.out.println("---------------------------------------------\n"); | ||||||
|              |              | ||||||
|             System.out.println("---------------------------------------------\n"); |             /*JobNumbers jo = JobNumbers.fromSchedule(sched); | ||||||
|             System.out.println("Greedy Solver: STP"); |             System.out.println("JOB NUMBER ENCODING (FROM_SCHEDULE): " + jo + "\n");*/ | ||||||
|             PriorityRule SPT = PriorityRule.SPT; |              | ||||||
|             Solver solverSPT = new GreedySolver(SPT); |             System.out.println("---------------------------------------------\n"); | ||||||
|             Result resultSPT = solverSPT.solve(instance, System.currentTimeMillis() + 10); |             System.out.println("Greedy Solver: STP"); | ||||||
|             sched = resultSPT.schedule; |             PriorityRule SPT = PriorityRule.SPT; | ||||||
|              |             Solver solverSPT = new GreedySolver(SPT); | ||||||
|             System.out.println("SCHEDULE:\n" + sched); |             Result resultSPT = solverSPT.solve(instance, System.currentTimeMillis() + 10); | ||||||
|             System.out.println("VALID: " + sched.isValid()); |             sched = resultSPT.schedule; | ||||||
|             System.out.println("MAKESPAN: " + sched.makespan()); |              | ||||||
|              |             System.out.println("SCHEDULE:\n" + sched); | ||||||
|             System.out.println("---------------------------------------------\n"); |             System.out.println("VALID: " + sched.isValid()); | ||||||
|             System.out.println("Greedy Solver: LRPT\n"); |             System.out.println("MAKESPAN: " + sched.makespan()); | ||||||
|             PriorityRule LRPT = PriorityRule.LRPT; |              | ||||||
|             Solver solverLRPT = new GreedySolver(LRPT); |             System.out.println("---------------------------------------------\n"); | ||||||
|             Result resultLRPT = solverLRPT.solve(instance, System.currentTimeMillis() + 10); |             System.out.println("Greedy Solver: LRPT\n"); | ||||||
|             sched = resultLRPT.schedule; |             PriorityRule LRPT = PriorityRule.LRPT; | ||||||
|              |             Solver solverLRPT = new GreedySolver(LRPT); | ||||||
|             System.out.println("SCHEDULE:\n" + sched); |             Result resultLRPT = solverLRPT.solve(instance, System.currentTimeMillis() + 10); | ||||||
|             System.out.println("VALID: " + sched.isValid()); |             sched = resultLRPT.schedule; | ||||||
|             System.out.println("MAKESPAN: " + sched.makespan()); |              | ||||||
|              |             System.out.println("SCHEDULE:\n" + sched); | ||||||
|             System.out.println("---------------------------------------------\n"); |             System.out.println("VALID: " + sched.isValid()); | ||||||
|             System.out.println("Greedy Solver: EST_SPT\n"); |             System.out.println("MAKESPAN: " + sched.makespan()); | ||||||
|             PriorityESTRule EST_SPT = PriorityESTRule.EST_SPT; |              | ||||||
|             Solver solverEST_SPT = new GreedySolver(EST_SPT); |             System.out.println("---------------------------------------------\n"); | ||||||
|             Result resultEST_SPT = solverEST_SPT.solve(instance, System.currentTimeMillis() + 10); |             System.out.println("Greedy Solver: EST_SPT\n"); | ||||||
|             sched = resultEST_SPT.schedule; |             PriorityESTRule EST_SPT = PriorityESTRule.EST_SPT; | ||||||
|              |             Solver solverEST_SPT = new GreedySolver(EST_SPT); | ||||||
|             System.out.println("SCHEDULE:\n" + sched); |             Result resultEST_SPT = solverEST_SPT.solve(instance, System.currentTimeMillis() + 10); | ||||||
|             System.out.println("VALID: " + sched.isValid()); |             sched = resultEST_SPT.schedule; | ||||||
|             System.out.println("MAKESPAN: " + sched.makespan()); |              | ||||||
|              |             System.out.println("SCHEDULE:\n" + sched); | ||||||
|             System.out.println("---------------------------------------------\n"); |             System.out.println("VALID: " + sched.isValid()); | ||||||
|             System.out.println("Greedy Solver: ic void applyOn(ResourceOrder order) {\r\n" +  |             System.out.println("MAKESPAN: " + sched.makespan()); | ||||||
|             		"            throw new UnsupportedOperationException();EST_SPT\n"); |              | ||||||
|             PriorityESTRule EST_LRPT = PriorityESTRule.EST_LRPT; |             System.out.println("---------------------------------------------\n"); | ||||||
|             Solver solverEST_LRPT = new GreedySolver(EST_SPT); |             System.out.println("Greedy Solver: EST_LRPT\n"); | ||||||
|             Result resultEST_LRPT = solverEST_LRPT.solve(instance, System.currentTimeMillis() + 10); |             PriorityESTRule EST_LRPT = PriorityESTRule.EST_LRPT; | ||||||
|             sched = resultEST_LRPT.schedule; |             Solver solverEST_LRPT = new GreedySolver(EST_LRPT); | ||||||
|              |             Result resultEST_LRPT = solverEST_LRPT.solve(instance, System.currentTimeMillis() + 10); | ||||||
|             System.out.println("SCHEDULE:\n" + sched); |             sched = resultEST_LRPT.schedule; | ||||||
|             System.out.println("VALID: " + sched.isValid()); |              | ||||||
|             System.out.println("MAKESPAN: " + sched.makespan()); |             System.out.println("SCHEDULE:\n" + sched); | ||||||
|              |             System.out.println("VALID: " + sched.isValid()); | ||||||
|             System.out.println("---------------------------------------------\n"); |             System.out.println("MAKESPAN: " + sched.makespan()); | ||||||
|             System.out.println("Descent Solver: \n"); |              | ||||||
|             DescentSolver solverDescent = new DescentSolver(); |             System.out.println("---------------------------------------------\n"); | ||||||
|             List<Block> criticalBlockList = solverDescent.blocksOfCriticalPath(ro2); |             System.out.println("Descent Solver: [Executed with EST_LRPT]\n"); | ||||||
|             for(Block b : criticalBlockList) { |              | ||||||
|             	System.out.println(b); |             DescentSolver solverDescent = new DescentSolver(EST_LRPT); | ||||||
|             	//System.out.println(solverDescent.neighbors(b)); |              | ||||||
|             } |              | ||||||
|             /* |             System.out.print("****** TEST: blocksOfCriticalPath() ******\n"); | ||||||
|             sched = ro2.toSchedule(); |             System.out.print("Number of Jobs     : " + instance2.numJobs + "\n"); | ||||||
|              |             System.out.print("Number of Tasks    : " + instance2.numTasks + "\n"); | ||||||
|             System.out.println("SCHEDULE:\n" + sched); |             System.out.print("Number of Machines : " + instance2.numMachines + "\n\n"); | ||||||
|             System.out.println("VALID: " + sched.isValid()); |              | ||||||
|             System.out.println("MAKESPAN: " + sched.makespan());*/ |              | ||||||
|              |              | ||||||
|         } catch (IOException e) { |             List<Block> criticalBlockList = solverDescent.blocksOfCriticalPath(ro2); | ||||||
|             e.printStackTrace(); |             for(Block b : criticalBlockList) { | ||||||
|             System.exit(1); |             	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; | package jobshop; | ||||||
| 
 | 
 | ||||||
| public abstract class Encoding { | public abstract class Encoding { | ||||||
| 
 | 
 | ||||||
|     public final Instance instance; |     public final Instance instance; | ||||||
| 
 | 
 | ||||||
|     public Encoding(Instance instance) { |     public Encoding(Instance instance) { | ||||||
|         this.instance = instance; |         this.instance = instance; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public abstract Schedule toSchedule(); |     public abstract Schedule toSchedule(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,73 +1,79 @@ | ||||||
| package jobshop; | package jobshop; | ||||||
| 
 | 
 | ||||||
| import java.io.IOException; | import jobshop.encodings.Task; | ||||||
| import java.nio.file.Files; | 
 | ||||||
| import java.nio.file.Path; | import java.io.IOException; | ||||||
| import java.util.Iterator; | import java.nio.file.Files; | ||||||
| import java.util.Scanner; | import java.nio.file.Path; | ||||||
| import java.util.stream.Collectors; | import java.util.Iterator; | ||||||
| 
 | import java.util.Scanner; | ||||||
| public class Instance { | import java.util.stream.Collectors; | ||||||
| 
 | 
 | ||||||
|     /** Number of jobs in the instance */ | public class Instance { | ||||||
|     public final int numJobs; | 
 | ||||||
| 
 |     /** Number of jobs in the instance */ | ||||||
|     /** Number of tasks per job */ |     public final int numJobs; | ||||||
|     public final int numTasks; | 
 | ||||||
| 
 |     /** Number of tasks per job */ | ||||||
|     /** Number of machines, assumed to be same as number of tasks. */ |     public final int numTasks; | ||||||
|     public final int numMachines; | 
 | ||||||
| 
 |     /** Number of machines, assumed to be same as number of tasks. */ | ||||||
|     final int[][] durations; |     public final int numMachines; | ||||||
|     final int[][] machines; | 
 | ||||||
| 
 |     final int[][] durations; | ||||||
|     public int duration(int job, int task) { |     final int[][] machines; | ||||||
|         return durations[job][task]; | 
 | ||||||
|     } |     public int duration(int job, int task) { | ||||||
|     public int machine(int job, int task) { |         return durations[job][task]; | ||||||
|         return machines[job][task]; |     } | ||||||
|     } |     public int duration(Task t) { | ||||||
| 
 |         return duration(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) { |     public int machine(int job, int task) { | ||||||
|         for(int task = 0 ; task < numTasks ; task++) { |         return machines[job][task]; | ||||||
|             if(machine(job, task) == wanted_machine) |     } | ||||||
|                 return task; |     public int machine(Task t) { | ||||||
|         } |         return this.machine(t.job, t.task); | ||||||
|         throw new RuntimeException("No task targeting machine "+wanted_machine+" on job "+job); |     } | ||||||
|     } | 
 | ||||||
| 
 |     /** among the tasks of the given job, returns the task index that uses the given machine. */ | ||||||
|     Instance(int numJobs, int numTasks) { |     public int task_with_machine(int job, int wanted_machine) { | ||||||
|         this.numJobs = numJobs; |         for(int task = 0 ; task < numTasks ; task++) { | ||||||
|         this.numTasks = numTasks; |             if(machine(job, task) == wanted_machine) | ||||||
|         this.numMachines = numTasks; |                 return task; | ||||||
| 
 |         } | ||||||
|         durations = new int[numJobs][numTasks]; |         throw new RuntimeException("No task targeting machine "+wanted_machine+" on job "+job); | ||||||
|         machines = new int[numJobs][numTasks]; |     } | ||||||
|     } | 
 | ||||||
| 
 |     Instance(int numJobs, int numTasks) { | ||||||
|     public static Instance fromFile(Path path) throws IOException { |         this.numJobs = numJobs; | ||||||
|         Iterator<String> lines = Files.readAllLines(path).stream() |         this.numTasks = numTasks; | ||||||
|                 .filter(l -> !l.startsWith("#")) |         this.numMachines = numTasks; | ||||||
|                 .collect(Collectors.toList()) | 
 | ||||||
|                 .iterator(); |         durations = new int[numJobs][numTasks]; | ||||||
| 
 |         machines = new int[numJobs][numTasks]; | ||||||
|         Scanner header = new Scanner(lines.next()); |     } | ||||||
|         int num_jobs = header.nextInt(); | 
 | ||||||
|         int num_tasks = header.nextInt(); |     /** Parses a instance from a file. */ | ||||||
|         Instance pb = new Instance(num_jobs, num_tasks); |     public static Instance fromFile(Path path) throws IOException { | ||||||
| 
 |         Iterator<String> lines = Files.readAllLines(path).stream() | ||||||
|         for(int job = 0 ; job<num_jobs ; job++) { |                 .filter(l -> !l.startsWith("#")) | ||||||
|             Scanner line = new Scanner(lines.next()); |                 .collect(Collectors.toList()) | ||||||
|             for(int task = 0 ; task < num_tasks ; task++) { |                 .iterator(); | ||||||
|                 pb.machines[job][task] = line.nextInt(); | 
 | ||||||
|                 pb.durations[job][task] = line.nextInt(); |         Scanner header = new Scanner(lines.next()); | ||||||
|             } |         int num_jobs = header.nextInt(); | ||||||
|             line.close(); |         int num_tasks = header.nextInt(); | ||||||
|         } |         Instance pb = new Instance(num_jobs, num_tasks); | ||||||
| 
 | 
 | ||||||
|         header.close(); |         for(int job = 0 ; job<num_jobs ; job++) { | ||||||
|   |             Scanner line = new Scanner(lines.next()); | ||||||
|         return pb; |             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; | package jobshop; | ||||||
| 
 | 
 | ||||||
| import java.io.PrintStream; | import java.io.PrintStream; | ||||||
| import java.nio.file.Path; | import java.nio.file.Path; | ||||||
| import java.nio.file.Paths; | import java.nio.file.Paths; | ||||||
| import java.util.Arrays; | import java.util.ArrayList; | ||||||
| import java.util.HashMap; | import java.util.Arrays; | ||||||
| import java.util.List; | import java.util.HashMap; | ||||||
| 
 | import java.util.List; | ||||||
| 
 | 
 | ||||||
| import jobshop.solvers.BasicSolver; | 
 | ||||||
| import jobshop.solvers.RandomSolver; | import jobshop.solvers.*; | ||||||
| import jobshop.solvers.GreedySolver.PriorityESTRule; | import jobshop.solvers.GreedySolver.PriorityESTRule; | ||||||
| import jobshop.solvers.GreedySolver.PriorityRule; | import jobshop.solvers.GreedySolver.PriorityRule; | ||||||
| import jobshop.solvers.GreedySolver; | import net.sourceforge.argparse4j.ArgumentParsers; | ||||||
| import net.sourceforge.argparse4j.ArgumentParsers; | import net.sourceforge.argparse4j.inf.ArgumentParser; | ||||||
| import net.sourceforge.argparse4j.inf.ArgumentParser; | import net.sourceforge.argparse4j.inf.ArgumentParserException; | ||||||
| import net.sourceforge.argparse4j.inf.ArgumentParserException; | import net.sourceforge.argparse4j.inf.Namespace; | ||||||
| import net.sourceforge.argparse4j.inf.Namespace; | 
 | ||||||
| 
 | 
 | ||||||
| 
 | public class Main { | ||||||
| public class Main { | 	// ******************************************** Main - Arguments ************************************************ // | ||||||
| 
 | 	// *** Basic + Random *** // | ||||||
|     /** All solvers available in this program */ | 	// --solver basic random --instance aaa1 ft06 ft10 ft20 la01 la02 la03 la04 la05 la06 la07 la08 la09 | ||||||
|     private static HashMap<String, Solver> solvers; | 	 | ||||||
|     static { | 	// *** Greedy Solvers *** //  | ||||||
|         solvers = new HashMap<>(); | 	// --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 | ||||||
|         solvers.put("basic", new BasicSolver()); | 	 | ||||||
|         solvers.put("random", new RandomSolver()); | 	// *** Descent Solvers *** // | ||||||
|         // add new solvers here | 	// --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 | ||||||
|         PriorityRule SPT = PriorityRule.SPT; | 	 | ||||||
|         solvers.put("greedySPT", new GreedySolver(SPT)); | 	// *** Taboo Solvers *** // | ||||||
|         PriorityRule LRPT = PriorityRule.LRPT; | 	// --solver Taboo-EST_LRPT(1,1) --instance aaa1 ft06 ft10 ft20 la01 la02 la03 la04 la05 la06 la07 la08 la09 | ||||||
|         solvers.put("greedyLRPT", new GreedySolver(LRPT)); | 	// --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 | ||||||
|         PriorityESTRule EST_SPT = PriorityESTRule.EST_SPT; | 	// --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 | ||||||
|         solvers.put("greedyEST_SPT", new GreedySolver(EST_SPT)); | 	// --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 | ||||||
|         PriorityESTRule EST_LRPT = PriorityESTRule.EST_LRPT; | 	// --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 | ||||||
|         solvers.put("greedyEST_LRPT", new GreedySolver(EST_LRPT)); | 	 | ||||||
|     } | 	/** All solvers available in this program */ | ||||||
| 
 |     private static HashMap<String, Solver> solvers; | ||||||
|     @SuppressWarnings("unused") |     static { | ||||||
| 	public static void main(String[] args) { |         solvers = new HashMap<>(); | ||||||
|         ArgumentParser parser = ArgumentParsers.newFor("jsp-solver").build() |         solvers.put("basic", new BasicSolver()); | ||||||
|                 .defaultHelp(true) |         solvers.put("random", new RandomSolver()); | ||||||
|                 .description("Solves jobshop problems."); |         // Add new solvers here | ||||||
| 
 |         // ******************** Greedy Solver ******************** // | ||||||
|         parser.addArgument("-t", "--timeout") |         PriorityRule SPT = PriorityRule.SPT; | ||||||
|                 .setDefault(1L) |         solvers.put("Greedy-SPT", new GreedySolver(SPT)); | ||||||
|                 .type(Long.class) |         PriorityRule LRPT = PriorityRule.LRPT; | ||||||
|                 .help("Solver timeout in seconds for each instance"); |         solvers.put("Greedy-LRPT", new GreedySolver(LRPT)); | ||||||
|         parser.addArgument("--solver") |         PriorityESTRule EST_SPT = PriorityESTRule.EST_SPT; | ||||||
|                 .nargs("+") |         solvers.put("Greedy-EST_SPT", new GreedySolver(EST_SPT)); | ||||||
|                 .required(true) |         PriorityESTRule EST_LRPT = PriorityESTRule.EST_LRPT; | ||||||
|                 .help("Solver(s) to use (space separated if more than one)"); |         solvers.put("Greedy-EST_LRPT", new GreedySolver(EST_LRPT)); | ||||||
| 
 |          | ||||||
|         parser.addArgument("--instance") |         // ******************* Descent Solver ******************** // | ||||||
|                 .nargs("+") |         solvers.put("Descent-SPT",      new DescentSolver(SPT)); | ||||||
|                 .required(true) |         solvers.put("Descent-LRPT",     new DescentSolver(LRPT)); | ||||||
|                 .help("Instance(s) to solve (space separated if more than one)"); |         solvers.put("Descent-EST_SPT",  new DescentSolver(EST_SPT)); | ||||||
| 
 |         solvers.put("Descent-EST_LRPT", new DescentSolver(EST_LRPT)); | ||||||
|         Namespace ns = null; |          | ||||||
|         try { |         // ******************** Taboo Solver ********************* // | ||||||
|             ns = parser.parseArgs(args); |         solvers.put("Taboo-EST_LRPT(1,1)",   new TabooSolver(EST_LRPT, 1, 1)); | ||||||
|         } catch (ArgumentParserException e) { |          | ||||||
|             parser.handleError(e); |         solvers.put("Taboo-EST_LRPT(1,10)",  new TabooSolver(EST_LRPT, 1, 10)); | ||||||
|             System.exit(1); |         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)); | ||||||
|         PrintStream output = System.out; |         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)); | ||||||
|         long solveTimeMs = ns.getLong("timeout") * 1000; |         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)); | ||||||
|         List<String> solversToTest = ns.getList("solver"); |         solvers.put("Taboo-EST_LRPT(9,10)",  new TabooSolver(EST_LRPT, 9, 10)); | ||||||
|         for(String solverName : solversToTest) { |         solvers.put("Taboo-EST_LRPT(10,10)", new TabooSolver(EST_LRPT, 10, 10)); | ||||||
|             if(!solvers.containsKey(solverName)) { |          | ||||||
|                 System.err.println("ERROR: Solver \"" + solverName + "\" is not avalaible."); |         solvers.put("Taboo-EST_LRPT(1,100)",   new TabooSolver(EST_LRPT, 1, 100)); | ||||||
|                 System.err.println("       Available solvers: " + solvers.keySet().toString()); |         solvers.put("Taboo-EST_LRPT(6,100)",   new TabooSolver(EST_LRPT, 6, 100)); | ||||||
|                 System.err.println("       You can provide your own solvers by adding them to the `Main.solvers` HashMap."); |         solvers.put("Taboo-EST_LRPT(8,100)",   new TabooSolver(EST_LRPT, 8, 100)); | ||||||
|                 System.exit(1); |         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)); | ||||||
|         List<String> instances = ns.<String>getList("instance"); |         solvers.put("Taboo-EST_LRPT(20,100)",  new TabooSolver(EST_LRPT, 20, 100)); | ||||||
|         for(String instanceName : instances) { |         solvers.put("Taboo-EST_LRPT(50,100)",  new TabooSolver(EST_LRPT, 50, 100)); | ||||||
|             if(!BestKnownResult.isKnown(instanceName)) { |         solvers.put("Taboo-EST_LRPT(100,100)", new TabooSolver(EST_LRPT, 100, 100)); | ||||||
|                 System.err.println("ERROR: instance \"" + instanceName + "\" is not avalaible."); |          | ||||||
|                 System.err.println("       available instances: " + Arrays.toString(BestKnownResult.instances)); |         solvers.put("Taboo-EST_LRPT(1,1000)",   new TabooSolver(EST_LRPT, 1, 1000)); | ||||||
|                 System.exit(1); |         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)); | ||||||
|         float[] runtimes = new float[solversToTest.size()]; |         solvers.put("Taboo-EST_LRPT(14,1000)",  new TabooSolver(EST_LRPT, 14, 1000)); | ||||||
|         float[] distances = new float[solversToTest.size()]; |         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)); | ||||||
|         try { |         solvers.put("Taboo-EST_LRPT(100,1000)", new TabooSolver(EST_LRPT, 100, 1000)); | ||||||
|             output.print(  "                         ");; |          | ||||||
|             for(String s : solversToTest) |         solvers.put("Taboo-EST_LRPT(1,5000)",   new TabooSolver(EST_LRPT, 1, 5000)); | ||||||
|                 output.printf("%-30s", s); |         solvers.put("Taboo-EST_LRPT(6,5000)",   new TabooSolver(EST_LRPT, 6, 5000)); | ||||||
|             output.println(); |         solvers.put("Taboo-EST_LRPT(8,5000)",   new TabooSolver(EST_LRPT, 8, 5000)); | ||||||
|             output.print("instance size  best      "); |         solvers.put("Taboo-EST_LRPT(10,5000)",  new TabooSolver(EST_LRPT, 10, 5000)); | ||||||
|             for(String s : solversToTest) { |         solvers.put("Taboo-EST_LRPT(12,5000)",  new TabooSolver(EST_LRPT, 12, 5000)); | ||||||
|                 output.print("runtime makespan ecart        "); |         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)); | ||||||
|             output.println(); |         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));      | ||||||
| 
 |     } | ||||||
|         for(String instanceName : instances) { | 
 | ||||||
|             int bestKnown = BestKnownResult.of(instanceName); | 
 | ||||||
| 
 |     public static void main(String[] args) { | ||||||
| 
 |         ArgumentParser parser = ArgumentParsers.newFor("jsp-solver").build() | ||||||
|             Path path = Paths.get("instances/", instanceName); |                 .defaultHelp(true) | ||||||
|             Instance instance = Instance.fromFile(path); |                 .description("Solves jobshop problems."); | ||||||
| 
 | 
 | ||||||
|             output.printf("%-8s %-5s %4d      ",instanceName, instance.numJobs +"x"+instance.numTasks, bestKnown); |         parser.addArgument("-t", "--timeout") | ||||||
| 
 |                 .setDefault(1L) | ||||||
|             for(int solverId = 0 ; solverId < solversToTest.size() ; solverId++) { |                 .type(Long.class) | ||||||
|                 String solverName = solversToTest.get(solverId); |                 .help("Solver timeout in seconds for each instance"); | ||||||
|                 Solver solver = solvers.get(solverName); |         parser.addArgument("--solver") | ||||||
|                 long start = System.currentTimeMillis(); |                 .nargs("+") | ||||||
|                 long deadline = System.currentTimeMillis() + solveTimeMs; |                 .required(true) | ||||||
|                 Result result = solver.solve(instance, deadline); |                 .help("Solver(s) to use (space separated if more than one)"); | ||||||
|                 long runtime = System.currentTimeMillis() - start; | 
 | ||||||
| 
 |         parser.addArgument("--instance") | ||||||
|                 if(!result.schedule.isValid()) { |                 .nargs("+") | ||||||
|                     System.err.println("ERROR: solver returned an invalid schedule"); |                 .required(true) | ||||||
|                     System.exit(1); |                 .help("Instance(s) to solve (space separated if more than one)"); | ||||||
|                 } | 
 | ||||||
| 
 |         Namespace ns = null; | ||||||
|                 assert result.schedule.isValid(); |         try { | ||||||
|                 int makespan = result.schedule.makespan(); |             ns = parser.parseArgs(args); | ||||||
|                 float dist = 100f * (makespan - bestKnown) / (float) bestKnown; |         } catch (ArgumentParserException e) { | ||||||
|                 runtimes[solverId] += (float) runtime / (float) instances.size(); |             parser.handleError(e); | ||||||
|                 distances[solverId] += dist / (float) instances.size(); |             System.exit(1); | ||||||
| 
 |         } | ||||||
|                 output.printf("%7d %8s %5.1f        ", runtime, makespan, dist); | 
 | ||||||
|                 output.flush(); |         PrintStream output = System.out; | ||||||
|             } | 
 | ||||||
|             output.println(); |         long solveTimeMs = ns.getLong("timeout") * 1000; | ||||||
| 
 | 
 | ||||||
|         } |         List<String> solversToTest = ns.getList("solver"); | ||||||
| 
 |         for(String solverName : solversToTest) { | ||||||
| 
 |             if(!solvers.containsKey(solverName)) { | ||||||
|         output.printf("%-8s %-5s %4s      ", "AVG", "-", "-"); |                 System.err.println("ERROR: Solver \"" + solverName + "\" is not avalaible."); | ||||||
|         for(int solverId = 0 ; solverId < solversToTest.size() ; solverId++) { |                 System.err.println("       Available solvers: " + solvers.keySet().toString()); | ||||||
|             output.printf("%7.1f %8s %5.1f        ", runtimes[solverId], "-", distances[solverId]); |                 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"); | ||||||
|         } catch (Exception e) { |         List<String> instances = new ArrayList<>(); | ||||||
|             e.printStackTrace(); |         for(String instancePrefix : instancePrefixes) { | ||||||
|             System.exit(1); |             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; | package jobshop; | ||||||
| 
 | 
 | ||||||
| import java.util.Optional; | public class Result { | ||||||
| 
 | 
 | ||||||
| @SuppressWarnings("unused") |     public Result(Instance instance, Schedule schedule, ExitCause cause) { | ||||||
| public class Result { |         this.instance = instance; | ||||||
| 
 |         this.schedule = schedule; | ||||||
|     public Result(Instance instance, Schedule schedule, ExitCause cause) { |         this.cause = cause; | ||||||
|         this.instance = instance; |     } | ||||||
|         this.schedule = schedule; | 
 | ||||||
|         this.cause = cause; |     public enum ExitCause { | ||||||
|     } |         Timeout, ProvedOptimal, Blocked | ||||||
| 
 |     } | ||||||
|     public enum ExitCause { | 
 | ||||||
|         Timeout, ProvedOptimal, Blocked |     public final Instance instance; | ||||||
|     } |     public final Schedule schedule; | ||||||
| 
 |     public final ExitCause cause; | ||||||
|     public final Instance instance; | 
 | ||||||
|     public final Schedule schedule; | 
 | ||||||
|     public final ExitCause cause; | } | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -1,157 +1,153 @@ | ||||||
| package jobshop; | package jobshop; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| import java.util.Arrays; | import jobshop.encodings.Task; | ||||||
| import java.util.Comparator; | 
 | ||||||
| import java.util.LinkedList; | import java.util.*; | ||||||
| import java.util.List; | import java.util.stream.IntStream; | ||||||
| import java.util.Optional; | 
 | ||||||
| import java.util.stream.IntStream; | public class Schedule { | ||||||
| 
 |     public final Instance pb; | ||||||
| import jobshop.encodings.Task; |     // 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 | ||||||
| public class Schedule { |     final int[][] times; | ||||||
|     public final Instance pb; | 
 | ||||||
|     // start times of each job and task |     public Schedule(Instance pb, int[][] times) { | ||||||
|     // times[j][i] is the start time of task (j,i) : i^th task of the j^th job |         this.pb = pb; | ||||||
|     final int[][] times; |         this.times = new int[pb.numJobs][]; | ||||||
| 
 |         for(int j = 0 ; j < pb.numJobs ; j++) { | ||||||
|     public Schedule(Instance pb, int[][] times) { |             this.times[j] = Arrays.copyOf(times[j], pb.numTasks); | ||||||
|         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]; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public int startTime(int job, int task) { |     /** Returns true if this schedule is valid (no constraint is violated) */ | ||||||
|         return times[job][task]; |     public boolean isValid() { | ||||||
|     } |         for(int j = 0 ; j<pb.numJobs ; j++) { | ||||||
| 
 |             for(int t = 1 ; t<pb.numTasks ; t++) { | ||||||
|     /** Returns true if this schedule is valid (no constraint is violated) */ |                 if(startTime(j, t-1) + pb.duration(j, t-1) > startTime(j, t)) | ||||||
|     public boolean isValid() { |                     return false; | ||||||
|         for(int j = 0 ; j<pb.numJobs ; j++) { |             } | ||||||
|             for(int t = 1 ; t<pb.numTasks ; t++) { |             for(int t = 0 ; t<pb.numTasks ; t++) { | ||||||
|                 if(startTime(j, t-1) + pb.duration(j, t-1) > startTime(j, t)) |                 if(startTime(j, t) < 0) | ||||||
|                     return false; |                     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++) { | ||||||
|         for (int machine = 0 ; machine < pb.numMachines ; machine++) { |                     int t2 = pb.task_with_machine(j2, machine); | ||||||
|             for(int j1=0 ; j1<pb.numJobs ; j1++) { | 
 | ||||||
|                 int t1 = pb.task_with_machine(j1, machine); |                     boolean t1_first = startTime(j1, t1) + pb.duration(j1, t1) <= startTime(j2, t2); | ||||||
|                 for(int j2=j1+1 ; j2<pb.numJobs ; j2++) { |                     boolean t2_first = startTime(j2, t2) + pb.duration(j2, t2) <= startTime(j1, t1); | ||||||
|                     int t2 = pb.task_with_machine(j2, machine); | 
 | ||||||
| 
 |                     if(!t1_first && !t2_first) | ||||||
|                     boolean t1_first = startTime(j1, t1) + pb.duration(j1, t1) <= startTime(j2, t2); |                         return false; | ||||||
|                     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() { | ||||||
|         return true; |         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)); | ||||||
|     public int makespan() { |         } | ||||||
|         int max = -1; |         return max; | ||||||
|         for(int j = 0 ; j<pb.numJobs ; j++) { |     } | ||||||
|             max = Math.max(max, startTime(j, pb.numTasks-1) + pb.duration(j, pb.numTasks -1)); | 
 | ||||||
|         } |     public int startTime(Task task) { | ||||||
|         return max; |         return startTime(task.job, task.task); | ||||||
|     } |     } | ||||||
|      | 
 | ||||||
|     public int startTime(Task task) { |     public int endTime(Task task) { | ||||||
|         return startTime(task.job, task.task); |         return startTime(task) + pb.duration(task.job, task.task); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public int endTime(Task task) { |     public boolean isCriticalPath(List<Task> path) { | ||||||
|         return startTime(task) + pb.duration(task.job, task.task); |         if(startTime(path.get(0)) != 0) { | ||||||
|     } |             return false; | ||||||
|      |         } | ||||||
|     public boolean isCriticalPath(List<Task> path) { |         if(endTime(path.get(path.size()-1)) != makespan()) { | ||||||
|         if(startTime(path.get(0)) != 0) { |             return false; | ||||||
|             return false; |         } | ||||||
|         } |         for(int i=0 ; i<path.size()-1 ; i++) { | ||||||
|         if(endTime(path.get(path.size()-1)) != makespan()) { |             if(endTime(path.get(i)) != startTime(path.get(i+1))) | ||||||
|             return false; |                 return false; | ||||||
|         } |         } | ||||||
|         for(int i=0 ; i<path.size()-1 ; i++) { |         return true; | ||||||
|             if(endTime(path.get(i)) != startTime(path.get(i+1))) |     } | ||||||
|                 return false; | 
 | ||||||
|         } |     public List<Task> criticalPath() { | ||||||
|         return true; |         // select task with greatest end time | ||||||
|     } |         Task ldd = IntStream.range(0, pb.numJobs) | ||||||
| 
 |                 .mapToObj(j -> new Task(j, pb.numTasks-1)) | ||||||
|     public List<Task> criticalPath() { |                 .max(Comparator.comparing(this::endTime)) | ||||||
|         // select task with greatest end time |                 .get(); | ||||||
|         Task ldd = IntStream.range(0, pb.numJobs) |         assert endTime(ldd) == makespan(); | ||||||
|                 .mapToObj(j -> new Task(j, pb.numTasks-1)) | 
 | ||||||
|                 .max(Comparator.comparing(this::endTime)) |         // list that will contain the critical path. | ||||||
|                 .get(); |         // we construct it from the end, starting with the | ||||||
|         assert endTime(ldd) == makespan(); |         // task that finishes last | ||||||
| 
 |         LinkedList<Task> path = new LinkedList<>(); | ||||||
|         // list that will contain the critical path. |         path.add(0,ldd); | ||||||
|         // we construct it from the end, starting with the | 
 | ||||||
|         // task that finishes last |         // keep adding tasks to the path until the first task in the path | ||||||
|         LinkedList<Task> path = new LinkedList<>(); |         // starts a time 0 | ||||||
|         path.add(0,ldd); |         while(startTime(path.getFirst()) != 0) { | ||||||
| 
 |             Task cur = path.getFirst(); | ||||||
|         // keep adding tasks to the path until the first task in the path |             int machine = pb.machine(cur.job, cur.task); | ||||||
|         // starts a time 0 | 
 | ||||||
|         while(startTime(path.getFirst()) != 0) { |             // will contain the task that was delaying the start | ||||||
|             Task cur = path.getFirst(); |             // of our current task | ||||||
|             int machine = pb.machine(cur.job, cur.task); |             Optional<Task> latestPredecessor = Optional.empty(); | ||||||
| 
 | 
 | ||||||
|             // will contain the task that was delaying the start |             if(cur.task > 0) { | ||||||
|             // of our current task |                 // our current task has a predecessor on the job | ||||||
|             Optional<Task> latestPredecessor = Optional.empty(); |                 Task predOnJob = new Task(cur.job, cur.task -1); | ||||||
| 
 | 
 | ||||||
|             if(cur.task > 0) { |                 // if it was the delaying task, save it to predecessor | ||||||
|                 // our current task has a predecessor on the job |                 if(endTime(predOnJob) == startTime(cur)) | ||||||
|                 Task predOnJob = new Task(cur.job, cur.task -1); |                     latestPredecessor = Optional.of(predOnJob); | ||||||
| 
 |             } | ||||||
|                 // if it was the delaying task, save it to predecessor |             if(!latestPredecessor.isPresent()) { | ||||||
|                 if(endTime(predOnJob) == startTime(cur)) |                 // no latest predecessor found yet, look among tasks executing on the same machine | ||||||
|                     latestPredecessor = Optional.of(predOnJob); |                 latestPredecessor = IntStream.range(0, pb.numJobs) | ||||||
|             } |                         .mapToObj(j -> new Task(j, pb.task_with_machine(j, machine))) | ||||||
|             if(!latestPredecessor.isPresent()) { |                         .filter(t -> endTime(t) == startTime(cur)) | ||||||
|                 // no latest predecessor found yet, look among tasks executing on the same machine |                         .findFirst(); | ||||||
|                 latestPredecessor = IntStream.range(0, pb.numJobs) |             } | ||||||
|                         .mapToObj(j -> new Task(j, pb.task_with_machine(j, machine))) |             // at this point we should have identified a latest predecessor, either on the job or on the machine | ||||||
|                         .filter(t -> endTime(t) == startTime(cur)) |             assert latestPredecessor.isPresent() && endTime(latestPredecessor.get()) == startTime(cur); | ||||||
|                         .findFirst(); |             // insert predecessor at the beginning of the path | ||||||
|             } |             path.add(0, latestPredecessor.get()); | ||||||
|             // 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); |         assert isCriticalPath(path); | ||||||
|             // insert predecessor at the beginning of the path |         return path; | ||||||
|             path.add(0, latestPredecessor.get()); |     } | ||||||
|         } |      | ||||||
|         assert isCriticalPath(path); |     public Schedule copy() { | ||||||
|         return path; |         return new Schedule(this.pb, this.times); | ||||||
|     } |     } | ||||||
| 
 |      | ||||||
|     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 = ""; | ||||||
|     /* Implémentation de la méthode toString() de la classe Schedule*/ |     	for (int i = 0; i < this.times.length; i++) { | ||||||
|     /****************************************************************/ |     		res += "Job " + Integer.toString(i + 1) + " starting times : \n"; | ||||||
|     public String toString() { |     		for (int j = 0; j < this.times[i].length; j++) { | ||||||
|     	String res = ""; |     			res += "\tTask " + Integer.toString(j + 1) + " starts at time : " + Integer.toString(this.times[i][j]) + "\n"; | ||||||
|     	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++) { |     	return res; | ||||||
|     			res += "\tTask " + Integer.toString(j + 1) + " starts at time : " + Integer.toString(this.times[i][j]) + "\n"; |     } | ||||||
|     		} | } | ||||||
|     	} |  | ||||||
|     	return res; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| package jobshop; | package jobshop; | ||||||
| 
 | 
 | ||||||
| public interface Solver { | public interface Solver { | ||||||
| 
 | 
 | ||||||
|     Result solve(Instance instance, long deadline); |     Result solve(Instance instance, long deadline); | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,116 +1,84 @@ | ||||||
| package jobshop.encodings; | package jobshop.encodings; | ||||||
| 
 | 
 | ||||||
| import jobshop.Encoding; | import jobshop.Encoding; | ||||||
| import jobshop.Instance; | import jobshop.Instance; | ||||||
| import jobshop.Schedule; | import jobshop.Schedule; | ||||||
| 
 | 
 | ||||||
| import java.util.Arrays; | import java.util.Arrays; | ||||||
| import java.util.Comparator; | import java.util.Comparator; | ||||||
| import java.util.stream.IntStream; | import java.util.stream.IntStream; | ||||||
| 
 | 
 | ||||||
| /** Représentation par numéro de job. */ | /** Représentation par numéro de job. */ | ||||||
| public class JobNumbers extends Encoding { | public class JobNumbers extends Encoding { | ||||||
| 
 | 
 | ||||||
|     /** A numJobs * numTasks array containing the representation by job numbers. */ |     /** A numJobs * numTasks array containing the representation by job numbers. */ | ||||||
|     public final int[] jobs; |     public final int[] jobs; | ||||||
| 
 | 
 | ||||||
|     /** In case the encoding is only partially filled, indicates the index of first |     /** In case the encoding is only partially filled, indicates the index of the first | ||||||
|      * element of `jobs` that has not been set yet. */ |      * element of `jobs` that has not been set yet. */ | ||||||
|     public int nextToSet = 0; |     public int nextToSet = 0; | ||||||
| 
 | 
 | ||||||
|     public JobNumbers(Instance instance) { |     public JobNumbers(Instance instance) { | ||||||
|         super(instance); |         super(instance); | ||||||
| 
 | 
 | ||||||
|         jobs = new int[instance.numJobs * instance.numMachines]; |         jobs = new int[instance.numJobs * instance.numMachines]; | ||||||
|         Arrays.fill(jobs, -1); |         Arrays.fill(jobs, -1); | ||||||
|     } |     } | ||||||
|      | 
 | ||||||
|     public JobNumbers(Schedule schedule) { |     public JobNumbers(Schedule schedule) { | ||||||
|         super(schedule.pb); |         super(schedule.pb); | ||||||
| 
 | 
 | ||||||
|         this.jobs = new int[instance.numJobs * instance.numTasks]; |         this.jobs = new int[instance.numJobs * instance.numTasks]; | ||||||
| 
 | 
 | ||||||
|         // for each job indicates which is the next task to be scheduled |         // for each job indicates which is the next task to be scheduled | ||||||
|         int[] nextOnJob = new int[instance.numJobs]; |         int[] nextOnJob = new int[instance.numJobs]; | ||||||
| 
 | 
 | ||||||
|         while(Arrays.stream(nextOnJob).anyMatch(t -> t < instance.numTasks)) { |         while(Arrays.stream(nextOnJob).anyMatch(t -> t < instance.numTasks)) { | ||||||
|             Task next = IntStream |             Task next = IntStream | ||||||
|                     // for all jobs numbers |                     // for all jobs numbers | ||||||
|                     .range(0, instance.numJobs) |                     .range(0, instance.numJobs) | ||||||
|                     // build the next task for this job |                     // build the next task for this job | ||||||
|                     .mapToObj(j -> new Task(j, nextOnJob[j])) |                     .mapToObj(j -> new Task(j, nextOnJob[j])) | ||||||
|                     // only keep valid tasks (some jobs have no task left to be executed) |                     // only keep valid tasks (some jobs have no task left to be executed) | ||||||
|                     .filter(t -> t.task < instance.numTasks) |                     .filter(t -> t.task < instance.numTasks) | ||||||
|                     // select the task with the earliest execution time |                     // select the task with the earliest execution time | ||||||
|                     .min(Comparator.comparing(t -> schedule.startTime(t.job, t.task))) |                     .min(Comparator.comparing(t -> schedule.startTime(t.job, t.task))) | ||||||
|                     .get(); |                     .get(); | ||||||
| 
 | 
 | ||||||
|             this.jobs[nextToSet++] = next.job; |             this.jobs[nextToSet++] = next.job; | ||||||
|             nextOnJob[next.job] += 1; |             nextOnJob[next.job] += 1; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public Schedule toSchedule() { |     public Schedule toSchedule() { | ||||||
|         // time at which each machine is going to be freed |         // time at which each machine is going to be freed | ||||||
|         int[] nextFreeTimeResource = new int[instance.numMachines]; |         int[] nextFreeTimeResource = new int[instance.numMachines]; | ||||||
| 
 | 
 | ||||||
|         // for each job, the first task that has not yet been scheduled |         // for each job, the first task that has not yet been scheduled | ||||||
|         int[] nextTask = new int[instance.numJobs]; |         int[] nextTask = new int[instance.numJobs]; | ||||||
| 
 | 
 | ||||||
|         // for each task, its start time |         // for each task, its start time | ||||||
|         int[][] startTimes = new int[instance.numJobs][instance.numTasks]; |         int[][] startTimes = new int[instance.numJobs][instance.numTasks]; | ||||||
| 
 | 
 | ||||||
|         // compute the earliest start time for every task of every job |         // compute the earliest start time for every task of every job | ||||||
|         for(int job : jobs) { |         for(int job : jobs) { | ||||||
|             int task = nextTask[job]; |             int task = nextTask[job]; | ||||||
|             int machine = instance.machine(job, task); |             int machine = instance.machine(job, task); | ||||||
|             // earliest start time for this task |             // earliest start time for this task | ||||||
|             int est = task == 0 ? 0 : startTimes[job][task-1] + instance.duration(job, task-1); |             int est = task == 0 ? 0 : startTimes[job][task-1] + instance.duration(job, task-1); | ||||||
|             est = Math.max(est, nextFreeTimeResource[machine]); |             est = Math.max(est, nextFreeTimeResource[machine]); | ||||||
| 
 | 
 | ||||||
|             startTimes[job][task] = est; |             startTimes[job][task] = est; | ||||||
|             nextFreeTimeResource[machine] = est + instance.duration(job, task); |             nextFreeTimeResource[machine] = est + instance.duration(job, task); | ||||||
|             nextTask[job] = task + 1; |             nextTask[job] = task + 1; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return new Schedule(instance, startTimes); |         return new Schedule(instance, startTimes); | ||||||
|     } |     } | ||||||
|      | 
 | ||||||
|     public static JobNumbers fromSchedule(Schedule sched) { |     @Override | ||||||
| 		JobNumbers jo = new JobNumbers(sched.pb); |     public String toString() { | ||||||
| 		 |         return Arrays.toString(Arrays.copyOfRange(jobs,0, nextToSet)); | ||||||
| 		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)); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -1,120 +1,126 @@ | ||||||
| package jobshop.encodings; | package jobshop.encodings; | ||||||
| 
 | 
 | ||||||
| import java.util.Comparator; | import jobshop.Encoding; | ||||||
| import java.util.Optional; | import jobshop.Instance; | ||||||
| import java.util.stream.IntStream; | import jobshop.Schedule; | ||||||
| 
 | 
 | ||||||
| import jobshop.Encoding; | import java.util.Comparator; | ||||||
| import jobshop.Instance; | import java.util.Optional; | ||||||
| import jobshop.Schedule; | import java.util.stream.IntStream; | ||||||
| 
 | 
 | ||||||
| 
 | public class ResourceOrder extends Encoding { | ||||||
| public class ResourceOrder extends Encoding { | 
 | ||||||
| 	 |     // for each machine m, taskByMachine[m] is an array of tasks to be | ||||||
| 	public final Task[][] tasksByMachine; |     // executed on this machine in the same order | ||||||
| 	 |     public final Task[][] tasksByMachine; | ||||||
| 	public final int[] nextFreeSlot; | 
 | ||||||
| 	 |     // for each machine, indicate on many tasks have been initialized | ||||||
| 	public ResourceOrder(Instance instance) { |     public final int[] nextFreeSlot; | ||||||
| 		super(instance); | 
 | ||||||
| 		 |     /** Creates a new empty resource order. */ | ||||||
| 		this.tasksByMachine = new Task[instance.numMachines][instance.numJobs]; |     public ResourceOrder(Instance instance) | ||||||
| 		for (int i = 0; i < instance.numMachines; i++) { |     { | ||||||
| 			for (int j = 0; j < instance.numJobs; j++) { |         super(instance); | ||||||
| 				this.tasksByMachine[i][j] = new Task(-1,-1); | 
 | ||||||
| 			} |         // 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) |         // no task scheduled on any machine (0 is the default value) | ||||||
|         nextFreeSlot = new int[instance.numMachines]; |         nextFreeSlot = new int[instance.numMachines]; | ||||||
| 	} |     } | ||||||
| 	 | 
 | ||||||
| 	public ResourceOrder(Schedule schedule) { |     /** Creates a resource order from a schedule. */ | ||||||
|         super(schedule.pb); |     public ResourceOrder(Schedule schedule) | ||||||
|         Instance pb = schedule.pb; |     { | ||||||
| 
 |         super(schedule.pb); | ||||||
|         this.tasksByMachine = new Task[pb.numMachines][]; |         Instance pb = schedule.pb; | ||||||
|         this.nextFreeSlot = new int[instance.numMachines]; | 
 | ||||||
| 
 |         this.tasksByMachine = new Task[pb.numMachines][]; | ||||||
|         for(int m = 0 ; m<schedule.pb.numMachines ; m++) { |         this.nextFreeSlot = new int[instance.numMachines]; | ||||||
|             final int machine = m; | 
 | ||||||
| 
 |         for(int m = 0 ; m<schedule.pb.numMachines ; m++) { | ||||||
|             // for thi machine, find all tasks that are executed on it and sort them by their start time |             final int machine = m; | ||||||
|             tasksByMachine[m] = | 
 | ||||||
|                     IntStream.range(0, pb.numJobs) // all job numbers |             // for thi machine, find all tasks that are executed on it and sort them by their start time | ||||||
|                             .mapToObj(j -> new Task(j, pb.task_with_machine(j, machine))) // all tasks on this machine (one per job) |             tasksByMachine[m] = | ||||||
|                             .sorted(Comparator.comparing(t -> schedule.startTime(t.job, t.task))) // sorted by start time |                     IntStream.range(0, pb.numJobs) // all job numbers | ||||||
|                             .toArray(Task[]::new); // as new array and store in tasksByMachine |                             .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 | ||||||
|             // indicate that all tasks have been initialized for machine m |                             .toArray(Task[]::new); // as new array and store in tasksByMachine | ||||||
|             nextFreeSlot[m] = instance.numJobs; | 
 | ||||||
|         } |             // indicate that all tasks have been initialized for machine m | ||||||
| 	 } |             nextFreeSlot[m] = instance.numJobs; | ||||||
| 	 |         } | ||||||
| 	 |     } | ||||||
| 	@Override | 
 | ||||||
|     public Schedule toSchedule() { |     @Override | ||||||
|         // indicate for each task that have been scheduled, its start time |     public Schedule toSchedule() { | ||||||
|         int [][] startTimes = new int [instance.numJobs][instance.numTasks]; |         // 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 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, 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]; |         // 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)) { |         // 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 |             // selects a task that has noun scheduled predecessor on its job and machine : | ||||||
|             //  - it is the next to be scheduled on its job |             //  - it is the next to be schedule on a machine | ||||||
|             // if there is no such task, we have cyclic dependency and the solution is invalid |             //  - it is the next to be scheduled on its job | ||||||
|             Optional<Task> schedulable = |             // if there is no such task, we have cyclic dependency and the solution is invalid | ||||||
|                     IntStream.range(0, instance.numMachines) // all machines ... |             Optional<Task> schedulable = | ||||||
|                     .filter(m -> nextToScheduleByMachine[m] < instance.numJobs) // ... with unscheduled jobs |                     IntStream.range(0, instance.numMachines) // all machines ... | ||||||
|                     .mapToObj(m -> this.tasksByMachine[m][nextToScheduleByMachine[m]]) // tasks that are next to schedule on a machine ... |                     .filter(m -> nextToScheduleByMachine[m] < instance.numJobs) // ... with unscheduled jobs | ||||||
|                     .filter(task -> task.task == nextToScheduleByJob[task.job])  // ... and on their job |                     .mapToObj(m -> this.tasksByMachine[m][nextToScheduleByMachine[m]]) // tasks that are next to schedule on a machine ... | ||||||
|                     .findFirst(); // select the first one if any |                     .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 |             if(schedulable.isPresent()) { | ||||||
|                 Task t = schedulable.get(); |                 // we found a schedulable task, lets call it t | ||||||
|                 int machine = instance.machine(t.job, t.task); |                 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); |                 // compute the earliest start time (est) of the task | ||||||
|                 est = Math.max(est, releaseTimeOfMachine[instance.machine(t.job, t.task)]); |                 int est = t.task == 0 ? 0 : startTimes[t.job][t.task-1] + instance.duration(t.job, t.task-1); | ||||||
|                 startTimes[t.job][t.task] = est; |                 est = Math.max(est, releaseTimeOfMachine[instance.machine(t)]); | ||||||
| 
 |                 startTimes[t.job][t.task] = est; | ||||||
|                 // mark the task as scheduled | 
 | ||||||
|                 nextToScheduleByJob[t.job]++; |                 // mark the task as scheduled | ||||||
|                 nextToScheduleByMachine[machine]++; |                 nextToScheduleByJob[t.job]++; | ||||||
|                 // increase the release time of the machine |                 nextToScheduleByMachine[machine]++; | ||||||
|                 releaseTimeOfMachine[machine] = est + instance.duration(t.job, t.task); |                 // increase the release time of the machine | ||||||
|             } else { |                 releaseTimeOfMachine[machine] = est + instance.duration(t.job, t.task); | ||||||
|                 // no tasks are schedulable, there is no solution for this resource ordering |             } else { | ||||||
|                 return null; |                 // 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); |         // we exited the loop : all tasks have been scheduled successfully | ||||||
|     } |         return new Schedule(instance, startTimes); | ||||||
| 	 |     } | ||||||
| 	@Override | 
 | ||||||
|     public String toString() { |     /** Creates an exact copy of this resource order. */ | ||||||
| 		String res = ""; |     public ResourceOrder copy() { | ||||||
| 		for (int i = 0; i < this.tasksByMachine.length; i++) { |         return new ResourceOrder(this.toSchedule()); | ||||||
| 			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"; | 	@Override | ||||||
| 			} |     public String toString() { | ||||||
| 		} | 		String res = ""; | ||||||
|         return 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; | package jobshop.encodings; | ||||||
| 
 | 
 | ||||||
| import java.util.Objects; | import java.util.Objects; | ||||||
| 
 | 
 | ||||||
| /** Represents a task (job,task) of an jobshop problem. | /** 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) |  * Example : (2, 3) repesents the fourth task of the third job. (remeber that we tart counting at 0) | ||||||
|  * */ |  * */ | ||||||
| public final class Task { | public final class Task { | ||||||
| 
 | 
 | ||||||
|     /** Identifier of the job */ |     /** Identifier of the job */ | ||||||
|     public final int job; |     public final int job; | ||||||
| 
 | 
 | ||||||
|     /** Index of the task inside the job. */ |     /** Index of the task inside the job. */ | ||||||
|     public final int task; |     public final int task; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     public Task(int job, int task) { |     public Task(int job, int task) { | ||||||
|         this.job = job; |         this.job = job; | ||||||
|         this.task = task; |         this.task = task; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public boolean equals(Object o) { |     public boolean equals(Object o) { | ||||||
|         if (this == o) return true; |         if (this == o) return true; | ||||||
|         if (o == null || getClass() != o.getClass()) return false; |         if (o == null || getClass() != o.getClass()) return false; | ||||||
|         Task task1 = (Task) o; |         Task task1 = (Task) o; | ||||||
|         return job == task1.job && |         return job == task1.job && | ||||||
|                 task == task1.task; |                 task == task1.task; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public int hashCode() { |     public int hashCode() { | ||||||
|         return Objects.hash(job, task); |         return Objects.hash(job, task); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public String toString() { |     public String toString() { | ||||||
|         return "Job " + this.job + " Task " + this.task; |         return "(" + job +", " + task + '}'; | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     public Task add_one() { |     public Task add_one() { | ||||||
|     	return new Task(this.job + 1, this.task + 1); |     	return new Task(this.job + 1, this.task + 1); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,21 +1,21 @@ | ||||||
| package jobshop.solvers; | package jobshop.solvers; | ||||||
| 
 | 
 | ||||||
| import jobshop.Instance; | import jobshop.Instance; | ||||||
| import jobshop.Result; | import jobshop.Result; | ||||||
| import jobshop.Solver; | import jobshop.Solver; | ||||||
| import jobshop.encodings.JobNumbers; | import jobshop.encodings.JobNumbers; | ||||||
| 
 | 
 | ||||||
| public class BasicSolver implements Solver { | public class BasicSolver implements Solver { | ||||||
|     @Override |     @Override | ||||||
|     public Result solve(Instance instance, long deadline) { |     public Result solve(Instance instance, long deadline) { | ||||||
| 
 | 
 | ||||||
|         JobNumbers sol = new JobNumbers(instance); |         JobNumbers sol = new JobNumbers(instance); | ||||||
|         for(int t = 0 ; t<instance.numTasks ; t++) { |         for(int t = 0 ; t<instance.numTasks ; t++) { | ||||||
|             for(int j = 0 ; j<instance.numJobs ; j++) { |             for(int j = 0 ; j<instance.numJobs ; j++) { | ||||||
|                 sol.jobs[sol.nextToSet++] = j; |                 sol.jobs[sol.nextToSet++] = j; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return new Result(instance, sol.toSchedule(), Result.ExitCause.Blocked); |         return new Result(instance, sol.toSchedule(), Result.ExitCause.Blocked); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -2,15 +2,34 @@ package jobshop.solvers; | ||||||
| 
 | 
 | ||||||
| import jobshop.Instance; | import jobshop.Instance; | ||||||
| import jobshop.Result; | import jobshop.Result; | ||||||
|  | import jobshop.Result.ExitCause; | ||||||
| import jobshop.Schedule; | import jobshop.Schedule; | ||||||
| import jobshop.Solver; | import jobshop.Solver; | ||||||
| import jobshop.encodings.ResourceOrder; | import jobshop.encodings.ResourceOrder; | ||||||
| import jobshop.encodings.Task; | import jobshop.encodings.Task; | ||||||
|  | import jobshop.solvers.GreedySolver.PriorityESTRule; | ||||||
|  | import jobshop.solvers.GreedySolver.PriorityRule; | ||||||
| 
 | 
 | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| 
 | 
 | ||||||
| public class DescentSolver implements Solver { | 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. |     /** 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. |      * 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)] |      * Represent the task sequence : [(0,2) (2,1)] | ||||||
|      * |      * | ||||||
|      * */ |      * */ | ||||||
|     public static class Block { | 	public static class Block { | ||||||
|         /** machine on which the block is identified */ |         /** machine on which the block is identified */ | ||||||
|         final int machine; |         final int machine; | ||||||
|         /** index of the first task of the block */ |         /** index of the first task of the block */ | ||||||
|  | @ -78,7 +97,7 @@ public class DescentSolver implements Solver { | ||||||
|             // Retrieve the tasks to be swap |             // Retrieve the tasks to be swap | ||||||
|         	Task task1 = order.tasksByMachine[this.machine][this.t1]; |         	Task task1 = order.tasksByMachine[this.machine][this.t1]; | ||||||
|             Task task2 = order.tasksByMachine[this.machine][this.t2]; |             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.t1] = task2; | ||||||
|             order.tasksByMachine[this.machine][this.t2] = task1; |             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 + "}"; |         	return "Swap: {M" + this.machine + " | t1 = " + this.t1 + " | t2 = " + this.t2 + "}"; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 |     // ************************************************************************************************************* // | ||||||
| 
 |     // *************************************** DescentSolver: solve Method ***************************************** // | ||||||
|  |     // ************************************************************************************************************* // | ||||||
|     @Override |     @Override | ||||||
|     public Result solve(Instance instance, long deadline) { |     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. */ |     /** Returns a list of all blocks of the critical path. */ | ||||||
|     public List<Block> blocksOfCriticalPath(ResourceOrder order) { |     public List<Block> blocksOfCriticalPath(ResourceOrder order) { | ||||||
|     	List<Block> criticalBlockList = new ArrayList<>(); |     	List<Block> criticalBlockList = new ArrayList<>(); | ||||||
|     	List<Integer> checkedMachines = new ArrayList<>(); |     	Block currentBlock; | ||||||
|     	 |  | ||||||
|     	// Obtain the critical task list from the resource order instance |     	// Obtain the critical task list from the resource order instance | ||||||
|         Schedule criticalSchedule = order.toSchedule(); |         Schedule criticalSchedule = order.toSchedule(); | ||||||
|         List<Task> criticalTaskList = criticalSchedule.criticalPath(); |         List<Task> criticalTaskList = criticalSchedule.criticalPath(); | ||||||
|          |          | ||||||
|         Block currentBlock; |         int totalNumMachines = criticalSchedule.pb.numMachines; | ||||||
|         int currentMachine, m; |         int totalNumJobs     = criticalSchedule.pb.numJobs; | ||||||
|         int firstTask = 0, lastTask = 0; |  | ||||||
|         Task currentTask; |  | ||||||
|          |          | ||||||
|         System.out.print("Number of Jobs     : " + order.instance.numJobs + "\n"); |         Task currentTaskRO; | ||||||
|         System.out.print("Number of Tasks    : " + order.instance.numTasks + "\n"); |         int currentTaskIndexRO, currentCriticalTaskIndex, firstTask, lastTask; | ||||||
|         System.out.print("Number of Machines : " + order.instance.numMachines + "\n"); |  | ||||||
|         System.out.print("Critical path      : " + criticalTaskList + "\n"); |  | ||||||
|          |          | ||||||
|         // Initialize the block list |         // We check for all machines | ||||||
|         for(int i = 0; i < order.instance.numMachines; i++) { |         for(int currentMachine = 0; currentMachine < totalNumMachines; currentMachine++) { | ||||||
|         	currentBlock = new Block(i, -1, -1); |         	currentTaskIndexRO = 0; | ||||||
|         	criticalBlockList.add(i, currentBlock); |             while(currentTaskIndexRO < (totalNumJobs-1)){ | ||||||
|         } |                 currentTaskRO = order.tasksByMachine[currentMachine][currentTaskIndexRO]; | ||||||
|          |                 if (criticalTaskList.contains(currentTaskRO)) { | ||||||
|         for(int i = 0; i < criticalTaskList.size(); i++) { |                     currentCriticalTaskIndex = criticalTaskList.indexOf(currentTaskRO); | ||||||
|         	currentTask = criticalTaskList.get(i); |                     //If the next task in the critical path is running in the same machine try find the last task index | ||||||
|         	currentMachine = order.instance.machine(currentTask.job, currentTask.task); |                     if(currentMachine == criticalSchedule.pb.machine(criticalTaskList.get(currentCriticalTaskIndex+1))) { | ||||||
|         	 |                         firstTask = currentTaskIndexRO; | ||||||
|         	// When we find a machine we have not explored, we start searching for all its appearances in the critical path  |                         while(currentCriticalTaskIndex < (criticalTaskList.size()-1) && currentMachine == criticalSchedule.pb.machine(criticalTaskList.get(currentCriticalTaskIndex+1))){ | ||||||
|         	// and we safe the first and last occurrence of the machine.   |                         	// We advance in the list | ||||||
|         	if(!checkedMachines.contains(currentMachine)) { |                             currentCriticalTaskIndex++; | ||||||
|         		firstTask = 0; |                             // We have to also advance in the resource order | ||||||
|                 lastTask = 0; |                             currentTaskIndexRO++; | ||||||
|         		for(int index = i; index < criticalTaskList.size(); index++) { |                         } | ||||||
| 	        		m = order.instance.machine(criticalTaskList.get(index).job, criticalTaskList.get(index).task); |                         // Create and add the new block to the list | ||||||
| 	        		// If we find a task running in the same machine and it is not the first task, add 1 to the last task |                         lastTask = currentTaskIndexRO; | ||||||
| 	        		if(currentMachine == m && index > i){ |                 	    currentBlock = new Block(currentMachine, firstTask, lastTask); | ||||||
| 	    				lastTask++; |                         criticalBlockList.add(currentBlock); | ||||||
| 	        		} |                     } | ||||||
|         		} |                 } | ||||||
|             	// Add the machine to the checked machines list |                 // We move on to the next task in the resource order | ||||||
|             	checkedMachines.add(currentMachine); |                 currentTaskIndexRO++; | ||||||
|             	// Create and add the new block to the list |             } | ||||||
|             	currentBlock = new Block(currentMachine, firstTask, lastTask); |  | ||||||
|             	criticalBlockList.set(currentMachine, currentBlock); |  | ||||||
|         	} |  | ||||||
|         } |         } | ||||||
|         return criticalBlockList; |         return criticalBlockList; | ||||||
|     } |      } | ||||||
|      |  | ||||||
| 
 | 
 | ||||||
|     /** For a given block, return the possible swaps for the Nowicki and Smutnicki neighborhood */ |      /** For a given block, return the possible swaps for the Nowicki and Smutnicki neighborhood */ | ||||||
|     public List<Swap> neighbors(Block block) { |      public List<Swap> neighbors(Block block) { | ||||||
|     	List<Swap> swapList = new ArrayList<>(); |     	List<Swap> swapList = new ArrayList<>(); | ||||||
|     	Swap currentSwap; |     	Swap swap1, swap2; | ||||||
|     	 |     	 | ||||||
|     	int machine   = block.machine; |     	int machine   = block.machine; | ||||||
|     	int firstTask = block.firstTask; |     	int firstTask = block.firstTask; | ||||||
|     	int lastTask  = block.lastTask; |     	int lastTask  = block.lastTask; | ||||||
|     	 |     	 | ||||||
|     	// Case when there is just one element in the block |     	// One single swap if there are just 2 elements in the block, two swaps if there are more than 2. | ||||||
|     	if(firstTask == lastTask) { |  		if(firstTask + 1 == lastTask) { | ||||||
|     		swapList = null; |  			swap1 = new Swap(machine, firstTask, lastTask); | ||||||
|     	} |  			swapList.add(swap1); | ||||||
|     	 |  		} else { | ||||||
|      	for(int i = firstTask; i < lastTask; i++) { |  			swap1 = new Swap(machine, firstTask, firstTask+1); | ||||||
|      		if(i == firstTask + 1) { |  			swap2 = new Swap(machine, lastTask-1 , lastTask); | ||||||
|      			currentSwap = new Swap(machine, firstTask, i); |  			swapList.add(swap1); | ||||||
|      			swapList.add(currentSwap); |  			swapList.add(swap2); | ||||||
|      		} |  		} | ||||||
|      		if (i == lastTask - 1) { |  | ||||||
|      			currentSwap = new Swap(machine, i, lastTask); |  | ||||||
|      			swapList.add(currentSwap); |  | ||||||
|      		} |  | ||||||
|     	} |  | ||||||
|         return swapList; |         return swapList; | ||||||
|     } |      }    | ||||||
| 
 |      // ************************************************************************************************************* // | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -3,9 +3,9 @@ package jobshop.solvers; | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| 
 | 
 | ||||||
| import jobshop.*; | import jobshop.*; | ||||||
|  | import jobshop.Result.ExitCause; | ||||||
| import jobshop.encodings.ResourceOrder; | import jobshop.encodings.ResourceOrder; | ||||||
| import jobshop.encodings.Task; | import jobshop.encodings.Task; | ||||||
| import jobshop.solvers.GreedySolver.PriorityESTRule; |  | ||||||
| 
 | 
 | ||||||
| public class GreedySolver implements Solver { | public class GreedySolver implements Solver { | ||||||
| 	 | 	 | ||||||
|  | @ -100,12 +100,12 @@ public class GreedySolver implements Solver { | ||||||
| 			// Search for the date or dates which start sooner | 			// Search for the date or dates which start sooner | ||||||
| 			ArrayList<Task> priorityTasks = new ArrayList<>(); | 			ArrayList<Task> priorityTasks = new ArrayList<>(); | ||||||
| 			int minStartDate = Integer.MAX_VALUE; | 			int minStartDate = Integer.MAX_VALUE; | ||||||
| 
 | 			Task currentTask; | ||||||
| 			 | 			int currentMachine, currentStartDate; | ||||||
| 			for(int i = 0; i < achievableTasks.size(); i++) { | 			for(int i = 0; i < achievableTasks.size(); i++) { | ||||||
| 				Task currentTask = achievableTasks.get(i); | 				currentTask = achievableTasks.get(i); | ||||||
| 				int currentMachine = instance.machine(currentTask.job, currentTask.task); | 				currentMachine = instance.machine(currentTask); | ||||||
| 				int currentStartDate = Integer.max(nextStartDateJobs[currentTask.job], nextStartDateMachines[currentMachine]); | 				currentStartDate = Integer.max(nextStartDateJobs[currentTask.job], nextStartDateMachines[currentMachine]); | ||||||
| 						 | 						 | ||||||
| 				if(currentStartDate < minStartDate) { | 				if(currentStartDate < minStartDate) { | ||||||
| 					minStartDate = currentStartDate; | 					minStartDate = currentStartDate; | ||||||
|  | @ -124,16 +124,18 @@ public class GreedySolver implements Solver { | ||||||
| 	/********************** Greedy Solver: Constructors + Solve function *************************/ | 	/********************** Greedy Solver: Constructors + Solve function *************************/ | ||||||
| 	/*********************************************************************************************/ | 	/*********************************************************************************************/ | ||||||
| 	 | 	 | ||||||
| 	public PriorityRule priorityRule; | 	private PriorityRule priorityRule; | ||||||
| 	public PriorityESTRule priorityESTRule; | 	private PriorityESTRule priorityESTRule; | ||||||
| 	 | 	 | ||||||
| 	// 2 constructors: the default and one with the EST restriction | 	// 2 constructors: the default and one with the EST restriction | ||||||
| 	public GreedySolver(PriorityRule rule) { | 	public GreedySolver(PriorityRule rule) { | ||||||
|  | 		super(); | ||||||
| 		this.priorityRule = rule; | 		this.priorityRule = rule; | ||||||
| 		this.priorityESTRule = null; | 		this.priorityESTRule = null; | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 	public GreedySolver(PriorityESTRule ruleEST) { | 	public GreedySolver(PriorityESTRule ruleEST) { | ||||||
|  | 		super(); | ||||||
| 		this.priorityESTRule = ruleEST; | 		this.priorityESTRule = ruleEST; | ||||||
| 		this.priorityRule = null; | 		this.priorityRule = null; | ||||||
| 	} | 	} | ||||||
|  | @ -143,7 +145,7 @@ public class GreedySolver implements Solver { | ||||||
| 	@Override | 	@Override | ||||||
|     public Result solve(Instance instance, long deadline) { |     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 | 		// 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[] nextStartDateJobs = new int[instance.numJobs]; | ||||||
| 		int[] nextStartDateMachines = new int[instance.numMachines]; | 		int[] nextStartDateMachines = new int[instance.numMachines]; | ||||||
|  | @ -152,14 +154,13 @@ public class GreedySolver implements Solver { | ||||||
| 		ResourceOrder solution = new ResourceOrder(instance); | 		ResourceOrder solution = new ResourceOrder(instance); | ||||||
| 		// Array list with all the achievable current tasks | 		// Array list with all the achievable current tasks | ||||||
|         ArrayList<Task> achievableTasks = new ArrayList<>(); |         ArrayList<Task> achievableTasks = new ArrayList<>(); | ||||||
|          |        | ||||||
|         // Initialize the array list with all the first task achievable |         // Initialize the array list with all the first task achievable | ||||||
| 		for(int i = 0 ; i < instance.numJobs ; i++) { | 		for(int i = 0 ; i < instance.numJobs ; i++) { | ||||||
| 			Task currentTask = new Task(i, 0); | 			achievableTasks.add(new Task(i, 0)); | ||||||
| 			achievableTasks.add(currentTask); |  | ||||||
|         } |         } | ||||||
| 		 | 		 | ||||||
|         while(!achievableTasks.isEmpty()) { |         while(!achievableTasks.isEmpty() && deadline > System.currentTimeMillis()) { | ||||||
|             // We take the task we should do now in function of the priority rule used |             // We take the task we should do now in function of the priority rule used | ||||||
|         	Task currentTask = null; |         	Task currentTask = null; | ||||||
|         	if(priorityESTRule == 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."); |         		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 |             // We remove the current task from the achievable tasks list | ||||||
|             achievableTasks.remove(currentTask); |             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 it's not the last task of the job, we update the array list with the new task | ||||||
|             if (currentTask.task < (instance.numTasks - 1)) { |             if (currentTask.task < (instance.numTasks - 1)) { | ||||||
|  | @ -185,10 +188,16 @@ public class GreedySolver implements Solver { | ||||||
|             } |             } | ||||||
|              |              | ||||||
|             // We add the current task to the solution |             // We add the current task to the solution | ||||||
|             int nextFreeSlot = solution.nextFreeSlot[currentMachine]++; |             nextFreeSlot = solution.nextFreeSlot[currentMachine]++; | ||||||
|             solution.tasksByMachine[currentMachine][nextFreeSlot] = currentTask; |             solution.tasksByMachine[currentMachine][nextFreeSlot] = currentTask; | ||||||
|         } |         } | ||||||
| 
 |     	// We find the exit cause in order to create the result we will return | ||||||
|         return new Result(instance, solution.toSchedule(), Result.ExitCause.Blocked); |     	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; | package jobshop.solvers; | ||||||
| 
 | 
 | ||||||
| import jobshop.*; | import jobshop.*; | ||||||
| import jobshop.encodings.JobNumbers; | import jobshop.encodings.JobNumbers; | ||||||
| 
 | 
 | ||||||
| import java.util.Optional; | import java.util.Optional; | ||||||
| import java.util.Random; | import java.util.Random; | ||||||
| 
 | 
 | ||||||
| @SuppressWarnings("unused") | public class RandomSolver implements Solver { | ||||||
| public class RandomSolver implements Solver { | 
 | ||||||
| 
 |     @Override | ||||||
|     @Override |     public Result solve(Instance instance, long deadline) { | ||||||
|     public Result solve(Instance instance, long deadline) { |         Random generator = new Random(0); | ||||||
|         Random generator = new Random(0); | 
 | ||||||
| 
 |         JobNumbers sol = new JobNumbers(instance); | ||||||
|         JobNumbers sol = new JobNumbers(instance); | 
 | ||||||
| 
 |         for(int j = 0 ; j<instance.numJobs ; j++) { | ||||||
|         for(int j = 0 ; j<instance.numJobs ; j++) { |             for(int t = 0 ; t<instance.numTasks ; t++) { | ||||||
|             for(int t = 0 ; t<instance.numTasks ; t++) { |                 sol.jobs[sol.nextToSet++] = j; | ||||||
|                 sol.jobs[sol.nextToSet++] = j; |             } | ||||||
|             } |         } | ||||||
|         } |         Schedule best = sol.toSchedule(); | ||||||
|         Schedule best = sol.toSchedule(); |         while(deadline - System.currentTimeMillis() > 1) { | ||||||
|         while(deadline - System.currentTimeMillis() > 1) { |             shuffleArray(sol.jobs, generator); | ||||||
|             shuffleArray(sol.jobs, generator); |             Schedule s = sol.toSchedule(); | ||||||
|             Schedule s = sol.toSchedule(); |             if(s.makespan() < best.makespan()) { | ||||||
|             if(s.makespan() < best.makespan()) { |                 best = s; | ||||||
|                 best = s; |             } | ||||||
|             } |         } | ||||||
|         } | 
 | ||||||
| 
 | 
 | ||||||
| 
 |         return new Result(instance, best, Result.ExitCause.Timeout); | ||||||
|         return new Result(instance, best, Result.ExitCause.Timeout); |     } | ||||||
|     } | 
 | ||||||
| 
 |     /** Simple Fisher–Yates array shuffling */ | ||||||
|     /** Simple Fisher–Yates array shuffling */ |     private static void shuffleArray(int[] array, Random random) | ||||||
|     private static void shuffleArray(int[] array, Random random) |     { | ||||||
|     { |         int index; | ||||||
|         int index; |         for (int i = array.length - 1; i > 0; i--) | ||||||
|         for (int i = array.length - 1; i > 0; i--) |         { | ||||||
|         { |             index = random.nextInt(i + 1); | ||||||
|             index = random.nextInt(i + 1); |             if (index != i) | ||||||
|             if (index != i) |             { | ||||||
|             { |                 array[index] ^= array[i]; | ||||||
|                 array[index] ^= array[i]; |                 array[i] ^= array[index]; | ||||||
|                 array[i] ^= array[index]; |                 array[index] ^= array[i]; | ||||||
|                 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; | package jobshop.encodings; | ||||||
| 
 | 
 | ||||||
| import jobshop.Instance; | import jobshop.Instance; | ||||||
| import jobshop.Result; | import jobshop.Result; | ||||||
| import jobshop.Schedule; | import jobshop.Schedule; | ||||||
| import jobshop.Solver; | import jobshop.Solver; | ||||||
| import jobshop.solvers.BasicSolver; | import jobshop.solvers.BasicSolver; | ||||||
| import jobshop.solvers.GreedySolver; | import org.junit.Test; | ||||||
| import jobshop.solvers.GreedySolver.PriorityRule; | 
 | ||||||
| 
 | import java.io.IOException; | ||||||
| import org.junit.Test; | import java.nio.file.Paths; | ||||||
| 
 | 
 | ||||||
| import java.io.IOException; | public class EncodingTests { | ||||||
| import java.nio.file.Paths; | 
 | ||||||
| 
 |     @Test | ||||||
| public class EncodingTests { |     public void testJobNumbers() throws IOException { | ||||||
| 
 |         Instance instance = Instance.fromFile(Paths.get("instances/aaa1")); | ||||||
|     @Test | 
 | ||||||
|     public void testJobNumbers() throws IOException { |         // numéro de jobs : 1 2 2 1 1 2 (cf exercices) | ||||||
|         Instance instance = Instance.fromFile(Paths.get("instances/aaa1")); |         JobNumbers enc = new JobNumbers(instance); | ||||||
| 
 |         enc.jobs[enc.nextToSet++] = 0; | ||||||
|         // numéro de jobs : 1 2 2 1 1 2 (cf exercices) |         enc.jobs[enc.nextToSet++] = 1; | ||||||
|         JobNumbers enc = new JobNumbers(instance); |         enc.jobs[enc.nextToSet++] = 1; | ||||||
|         enc.jobs[enc.nextToSet++] = 0; |         enc.jobs[enc.nextToSet++] = 0; | ||||||
|         enc.jobs[enc.nextToSet++] = 1; |         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; |         Schedule sched = enc.toSchedule(); | ||||||
|         enc.jobs[enc.nextToSet++] = 1; |         // TODO: make it print something meaningful | ||||||
| 
 |         // by implementing the toString() method | ||||||
|         Schedule sched = enc.toSchedule(); |         System.out.println(sched); | ||||||
|         // TODO: make it print something meaningful |         assert sched.isValid(); | ||||||
|         // by implementing the toString() method |         assert sched.makespan() == 12; | ||||||
|         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; | ||||||
|         // numéro de jobs : 1 1 2 2 1 2 |         enc.jobs[enc.nextToSet++] = 0; | ||||||
|         enc = new JobNumbers(instance); |         enc.jobs[enc.nextToSet++] = 1; | ||||||
|         enc.jobs[enc.nextToSet++] = 0; |         enc.jobs[enc.nextToSet++] = 1; | ||||||
|         enc.jobs[enc.nextToSet++] = 0; |         enc.jobs[enc.nextToSet++] = 0; | ||||||
|         enc.jobs[enc.nextToSet++] = 1; |         enc.jobs[enc.nextToSet++] = 1; | ||||||
|         enc.jobs[enc.nextToSet++] = 1; | 
 | ||||||
|         enc.jobs[enc.nextToSet++] = 0; |         sched = enc.toSchedule(); | ||||||
|         enc.jobs[enc.nextToSet++] = 1; |         assert sched.isValid(); | ||||||
| 
 |         assert sched.makespan() == 14; | ||||||
|         sched = enc.toSchedule(); |     } | ||||||
|         assert sched.isValid(); | 
 | ||||||
|         assert sched.makespan() == 14; |     @Test | ||||||
|     } |     public void testBasicSolver() throws IOException { | ||||||
| 
 |         Instance instance = Instance.fromFile(Paths.get("instances/aaa1")); | ||||||
|     @Test | 
 | ||||||
|     public void testBasicSolver() throws IOException { |         // build a solution that should be equal to the result of BasicSolver | ||||||
|         Instance instance = Instance.fromFile(Paths.get("instances/aaa1")); |         JobNumbers enc = new JobNumbers(instance); | ||||||
| 
 |         enc.jobs[enc.nextToSet++] = 0; | ||||||
|         // build a solution that should be equal to the result of BasicSolver |         enc.jobs[enc.nextToSet++] = 1; | ||||||
|         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++] = 0; |         enc.jobs[enc.nextToSet++] = 1; | ||||||
|         enc.jobs[enc.nextToSet++] = 1; | 
 | ||||||
|         enc.jobs[enc.nextToSet++] = 0; |         Schedule sched = enc.toSchedule(); | ||||||
|         enc.jobs[enc.nextToSet++] = 1; |         assert sched.isValid(); | ||||||
| 
 |         assert sched.makespan() == 12; | ||||||
|         Schedule sched = enc.toSchedule(); | 
 | ||||||
|         assert sched.isValid(); |         Solver solver = new BasicSolver(); | ||||||
|         assert sched.makespan() == 12; |         Result result = solver.solve(instance, System.currentTimeMillis() + 10); | ||||||
| 
 | 
 | ||||||
|         Solver solver = new BasicSolver(); |         assert result.schedule.isValid(); | ||||||
|         Result result = solver.solve(instance, System.currentTimeMillis() + 10); |         assert result.schedule.makespan() == sched.makespan(); // should have the same makespan | ||||||
| 
 |     } | ||||||
|         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 |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue