diff --git a/data/flowshop/flowshop-Ta100.json b/data/flowshop/flowshop-Ta100.json new file mode 100644 index 00000000..73ea4bf6 --- /dev/null +++ b/data/flowshop/flowshop-Ta100.json @@ -0,0 +1,856 @@ +{ + "allMachines" : [ { + "id" : 0, + "jobs" : [ 148, 147, 82, 23, 126, 164, 184, 146, 183, 161, 2, 192, 178, 38, 116, 136, 83, 170, 52, 162, 151, 74, 149, 5, 31, 29, 104, 165, 32, 182, 18, 27, 145, 137, 160, 180, 15, 199, 63, 194, 28, 132, 20, 43, 189, 60, 87, 19, 17, 64, 56, 48, 66, 81, 25, 110, 78, 121, 105, 77, 69, 174, 67, 85, 47, 80, 102, 106, 133, 163, 157, 175, 140, 176, 169, 21, 123, 152, 86, 46, 130, 73, 13, 68, 53, 181, 88, 10, 92, 1, 153, 6, 84, 97, 129, 172, 112, 3, 93, 11, 89, 193, 131, 150, 7, 71, 57, 45, 114, 117, 127, 171, 36, 37, 168, 50, 159, 188, 156, 94, 177, 99, 39, 90, 14, 44, 143, 26, 119, 173, 75, 42, 185, 98, 4, 8, 155, 58, 96, 59, 144, 196, 24, 134, 108, 76, 166, 54, 103, 109, 16, 55, 142, 49, 0, 101, 62, 187, 115, 113, 107, 141, 128, 167, 22, 135, 195, 65, 120, 122, 33, 41, 70, 91, 34, 51, 190, 61, 100, 72, 191, 9, 95, 118, 198, 111, 158, 35, 12, 138, 40, 139, 186, 30, 179, 124, 154, 197, 79, 125 ], + "makespan" : 10727, + "processTime" : [ 7, 3, 45, 44, 54, 36, 79, 40, 10, 51, 39, 45, 96, 30, 89, 70, 96, 32, 55, 98, 15, 79, 92, 9, 49, 11, 57, 44, 55, 91, 23, 13, 23, 80, 69, 74, 4, 40, 19, 93, 86, 45, 2, 65, 79, 17, 28, 90, 5, 67, 71, 28, 47, 56, 19, 92, 57, 52, 77, 4, 45, 94, 81, 61, 56, 97, 44, 86, 61, 64, 64, 95, 63, 27, 9, 49, 31, 14, 67, 72, 49, 74, 46, 84, 6, 48, 19, 56, 65, 18, 91, 57, 31, 19, 85, 37, 92, 28, 83, 61, 51, 97, 14, 36, 30, 11, 2, 20, 65, 67, 7, 56, 67, 96, 46, 27, 42, 48, 30, 89, 5, 53, 70, 44, 94, 97, 26, 87, 79, 11, 44, 11, 46, 86, 35, 44, 9, 25, 48, 86, 85, 90, 58, 72, 90, 81, 18, 2, 10, 93, 15, 2, 78, 41, 40, 99, 78, 78, 74, 41, 64, 60, 32, 30, 66, 30, 58, 54, 78, 65, 69, 13, 86, 43, 6, 61, 17, 57, 45, 94, 50, 18, 67, 20, 42, 45, 67, 21, 64, 79, 92, 66, 9, 80, 67, 59, 68, 72, 51, 10 ] + }, { + "id" : 1, + "jobs" : [ ], + "makespan" : 0, + "processTime" : [ 88, 75, 17, 86, 77, 83, 27, 65, 58, 15, 28, 23, 50, 73, 36, 2, 46, 49, 51, 44, 97, 26, 58, 88, 40, 31, 88, 36, 53, 59, 17, 86, 72, 88, 61, 47, 80, 65, 47, 18, 98, 12, 51, 81, 70, 3, 45, 87, 89, 15, 13, 90, 40, 85, 19, 99, 52, 44, 94, 34, 35, 53, 86, 32, 3, 20, 64, 14, 24, 80, 57, 75, 59, 5, 26, 21, 25, 97, 24, 84, 48, 3, 1, 84, 78, 21, 25, 54, 30, 45, 52, 54, 19, 17, 57, 1, 17, 60, 95, 87, 36, 30, 14, 41, 3, 44, 88, 22, 37, 29, 70, 81, 58, 17, 93, 81, 34, 49, 33, 72, 84, 2, 1, 11, 56, 91, 29, 46, 68, 7, 75, 18, 98, 32, 42, 89, 91, 16, 83, 47, 30, 1, 18, 64, 16, 58, 5, 42, 1, 22, 60, 48, 31, 60, 82, 87, 84, 3, 34, 75, 40, 71, 26, 86, 65, 33, 94, 30, 41, 64, 22, 91, 71, 41, 54, 56, 11, 47, 7, 5, 8, 32, 79, 11, 32, 26, 3, 26, 36, 15, 5, 71, 28, 91, 69, 41, 11, 71, 70, 66 ] + }, { + "id" : 2, + "jobs" : [ ], + "makespan" : 0, + "processTime" : [ 69, 74, 88, 93, 19, 26, 92, 76, 16, 16, 55, 10, 71, 20, 46, 43, 9, 57, 85, 5, 41, 85, 61, 33, 25, 82, 91, 22, 49, 89, 33, 37, 37, 20, 60, 82, 70, 18, 17, 12, 44, 91, 58, 3, 79, 24, 16, 42, 77, 20, 31, 42, 34, 87, 69, 81, 37, 2, 90, 96, 68, 98, 3, 12, 7, 20, 86, 21, 34, 4, 95, 44, 22, 31, 71, 23, 52, 92, 21, 96, 22, 88, 87, 24, 17, 82, 1, 65, 22, 77, 38, 20, 77, 64, 49, 46, 74, 96, 56, 94, 81, 79, 49, 94, 3, 59, 66, 85, 69, 7, 22, 68, 89, 50, 28, 56, 55, 69, 90, 29, 33, 54, 19, 72, 86, 29, 42, 56, 76, 24, 79, 77, 56, 35, 22, 91, 95, 41, 41, 23, 10, 78, 50, 97, 90, 95, 74, 1, 28, 21, 69, 20, 89, 46, 92, 79, 33, 26, 92, 66, 39, 16, 93, 84, 16, 59, 33, 18, 11, 17, 7, 68, 15, 51, 78, 52, 30, 75, 11, 79, 75, 66, 98, 88, 8, 45, 74, 15, 99, 55, 90, 84, 56, 50, 19, 81, 18, 41, 1, 46 ] + }, { + "id" : 3, + "jobs" : [ ], + "makespan" : 0, + "processTime" : [ 22, 83, 19, 8, 62, 40, 71, 48, 49, 40, 83, 57, 68, 50, 99, 89, 90, 40, 1, 26, 72, 35, 35, 23, 40, 83, 85, 83, 53, 97, 99, 20, 41, 58, 42, 62, 99, 76, 95, 25, 2, 48, 16, 87, 33, 24, 22, 5, 41, 42, 69, 62, 59, 47, 88, 92, 3, 53, 45, 5, 87, 2, 98, 98, 20, 69, 70, 77, 51, 50, 65, 27, 79, 75, 14, 92, 98, 50, 85, 9, 52, 40, 2, 27, 13, 22, 70, 93, 62, 62, 45, 88, 53, 82, 24, 88, 22, 28, 93, 30, 61, 34, 68, 43, 87, 2, 45, 68, 11, 14, 25, 81, 11, 91, 37, 20, 4, 57, 50, 55, 34, 14, 64, 90, 74, 80, 29, 13, 67, 61, 22, 9, 32, 68, 60, 49, 48, 7, 76, 13, 87, 2, 20, 98, 2, 22, 68, 33, 6, 63, 40, 18, 87, 80, 16, 34, 61, 13, 83, 85, 76, 75, 54, 9, 21, 96, 88, 21, 17, 53, 4, 72, 23, 11, 39, 64, 20, 54, 12, 35, 1, 24, 14, 5, 74, 90, 40, 52, 66, 53, 92, 42, 23, 47, 14, 12, 12, 70, 56, 39 ] + }, { + "id" : 4, + "jobs" : [ ], + "makespan" : 0, + "processTime" : [ 26, 5, 53, 1, 56, 85, 21, 8, 47, 66, 12, 4, 50, 44, 16, 37, 73, 46, 8, 88, 42, 61, 13, 27, 91, 83, 87, 47, 26, 98, 60, 84, 57, 20, 36, 51, 68, 35, 31, 82, 93, 79, 68, 94, 26, 96, 99, 86, 69, 58, 82, 37, 15, 49, 18, 28, 68, 14, 90, 15, 76, 33, 31, 88, 3, 2, 14, 40, 25, 56, 98, 67, 1, 59, 89, 10, 56, 68, 46, 77, 29, 32, 51, 68, 8, 83, 31, 68, 65, 50, 86, 60, 69, 18, 23, 76, 75, 53, 72, 7, 5, 32, 81, 59, 28, 88, 56, 20, 13, 93, 24, 36, 58, 49, 44, 27, 42, 71, 51, 89, 28, 89, 11, 94, 92, 93, 39, 59, 84, 81, 30, 69, 19, 49, 44, 19, 51, 11, 16, 7, 31, 88, 17, 29, 16, 2, 52, 21, 38, 49, 53, 9, 41, 55, 25, 13, 4, 74, 52, 90, 5, 40, 51, 29, 17, 8, 91, 85, 77, 20, 93, 65, 83, 35, 23, 4, 27, 19, 71, 15, 91, 73, 36, 16, 70, 62, 65, 77, 83, 25, 98, 63, 47, 11, 38, 29, 31, 63, 35, 97 ] + }, { + "id" : 5, + "jobs" : [ ], + "makespan" : 0, + "processTime" : [ 60, 37, 28, 70, 4, 71, 65, 83, 67, 93, 43, 9, 75, 22, 6, 49, 71, 82, 72, 4, 69, 18, 49, 77, 74, 64, 24, 24, 22, 68, 53, 45, 98, 69, 77, 4, 61, 71, 49, 26, 57, 46, 52, 80, 65, 43, 95, 69, 51, 24, 19, 55, 69, 94, 98, 54, 36, 57, 88, 94, 44, 13, 70, 8, 16, 44, 67, 45, 12, 75, 95, 37, 10, 28, 94, 36, 38, 84, 90, 58, 50, 80, 1, 98, 39, 26, 56, 2, 4, 79, 93, 86, 71, 28, 90, 90, 57, 39, 54, 93, 57, 96, 20, 27, 52, 17, 28, 6, 10, 79, 81, 38, 67, 88, 90, 56, 71, 97, 92, 30, 74, 66, 3, 89, 74, 15, 51, 62, 77, 88, 14, 38, 62, 73, 23, 26, 70, 4, 8, 9, 54, 84, 5, 53, 50, 84, 92, 23, 78, 78, 62, 55, 24, 22, 46, 27, 35, 94, 93, 53, 87, 46, 85, 26, 87, 26, 24, 6, 99, 85, 51, 36, 40, 96, 73, 31, 16, 31, 34, 50, 14, 21, 77, 26, 1, 13, 65, 30, 18, 5, 27, 88, 42, 3, 82, 8, 67, 16, 73, 74 ] + }, { + "id" : 6, + "jobs" : [ ], + "makespan" : 0, + "processTime" : [ 68, 42, 14, 51, 1, 60, 44, 49, 89, 52, 53, 35, 80, 18, 46, 60, 41, 36, 78, 81, 12, 79, 25, 28, 40, 99, 70, 21, 83, 1, 59, 41, 91, 62, 97, 47, 1, 58, 5, 82, 24, 94, 66, 68, 76, 35, 49, 38, 95, 82, 56, 41, 73, 43, 71, 73, 1, 71, 73, 55, 59, 71, 18, 1, 83, 40, 60, 73, 23, 35, 20, 84, 44, 23, 38, 44, 40, 15, 52, 94, 42, 32, 71, 5, 37, 7, 69, 44, 69, 24, 32, 53, 61, 83, 27, 91, 31, 46, 17, 24, 23, 36, 12, 21, 60, 67, 62, 40, 99, 54, 78, 11, 81, 59, 82, 99, 97, 77, 64, 78, 75, 45, 37, 74, 12, 11, 13, 15, 70, 51, 18, 92, 86, 25, 52, 53, 81, 67, 32, 62, 53, 11, 11, 61, 35, 3, 21, 5, 6, 87, 95, 84, 39, 48, 49, 99, 27, 81, 42, 90, 54, 49, 75, 36, 53, 92, 13, 11, 87, 97, 50, 37, 24, 22, 53, 19, 47, 64, 59, 55, 58, 18, 83, 11, 90, 40, 73, 11, 71, 88, 66, 75, 73, 27, 12, 30, 56, 34, 7, 84 ] + }, { + "id" : 7, + "jobs" : [ ], + "makespan" : 0, + "processTime" : [ 2, 62, 62, 58, 14, 32, 27, 52, 90, 34, 90, 81, 70, 37, 89, 91, 75, 82, 40, 32, 57, 89, 36, 24, 61, 19, 15, 52, 58, 18, 28, 79, 6, 99, 92, 92, 47, 35, 35, 79, 66, 68, 7, 37, 17, 33, 53, 53, 94, 86, 56, 22, 12, 32, 75, 94, 79, 73, 6, 15, 97, 35, 7, 40, 59, 28, 81, 15, 80, 58, 12, 78, 55, 10, 96, 29, 13, 58, 40, 11, 90, 78, 4, 91, 30, 9, 73, 17, 22, 91, 12, 49, 97, 20, 39, 43, 44, 56, 54, 76, 72, 93, 16, 24, 96, 92, 90, 27, 17, 85, 9, 56, 61, 76, 35, 79, 71, 87, 24, 6, 9, 88, 70, 9, 33, 24, 68, 49, 51, 45, 31, 75, 11, 45, 52, 59, 32, 69, 25, 7, 30, 19, 14, 89, 71, 75, 2, 31, 39, 81, 25, 87, 10, 74, 24, 75, 19, 60, 21, 77, 35, 76, 75, 25, 78, 47, 70, 33, 53, 24, 94, 7, 92, 29, 78, 92, 15, 68, 74, 33, 63, 2, 57, 88, 42, 68, 77, 79, 95, 79, 9, 11, 83, 11, 67, 62, 55, 92, 30, 40 ] + }, { + "id" : 8, + "jobs" : [ ], + "makespan" : 0, + "processTime" : [ 34, 49, 84, 38, 88, 55, 2, 10, 44, 75, 37, 63, 47, 1, 88, 97, 96, 60, 14, 98, 72, 33, 84, 29, 22, 91, 13, 34, 34, 81, 63, 20, 45, 50, 32, 66, 49, 4, 20, 17, 62, 74, 34, 81, 55, 87, 80, 29, 35, 73, 62, 9, 88, 17, 90, 44, 98, 84, 66, 2, 39, 41, 6, 48, 86, 65, 43, 73, 34, 70, 8, 95, 9, 90, 79, 14, 75, 94, 43, 7, 66, 63, 12, 55, 18, 91, 32, 21, 2, 99, 46, 56, 44, 39, 43, 47, 38, 53, 34, 72, 16, 42, 81, 31, 81, 68, 11, 41, 83, 60, 46, 32, 74, 94, 58, 14, 37, 77, 9, 70, 26, 67, 18, 24, 57, 27, 37, 86, 31, 46, 59, 2, 98, 65, 9, 32, 87, 51, 23, 39, 86, 3, 61, 42, 60, 98, 7, 7, 70, 13, 44, 76, 58, 16, 28, 6, 47, 15, 94, 22, 7, 33, 33, 52, 4, 28, 16, 51, 25, 64, 82, 48, 81, 76, 83, 1, 24, 91, 86, 38, 90, 73, 95, 4, 81, 58, 5, 36, 48, 42, 43, 40, 58, 89, 89, 84, 95, 16, 66, 20 ] + }, { + "id" : 9, + "jobs" : [ ], + "makespan" : 0, + "processTime" : [ 48, 12, 62, 95, 91, 52, 70, 89, 18, 18, 83, 4, 72, 62, 77, 89, 90, 63, 70, 77, 76, 36, 30, 95, 20, 79, 67, 61, 96, 81, 3, 71, 83, 88, 21, 92, 55, 82, 50, 49, 3, 53, 70, 39, 63, 74, 7, 85, 76, 44, 9, 10, 51, 30, 37, 67, 78, 58, 58, 36, 97, 30, 73, 50, 29, 44, 25, 51, 69, 96, 37, 41, 2, 46, 79, 16, 87, 76, 11, 1, 27, 87, 99, 60, 30, 68, 32, 85, 45, 7, 97, 38, 55, 29, 93, 5, 12, 46, 61, 65, 35, 72, 10, 3, 78, 19, 85, 45, 43, 87, 15, 78, 75, 14, 87, 40, 84, 65, 4, 68, 32, 75, 25, 49, 7, 5, 75, 58, 40, 15, 82, 40, 32, 63, 39, 53, 85, 47, 28, 15, 42, 97, 70, 53, 59, 88, 58, 53, 46, 78, 60, 70, 33, 74, 39, 25, 34, 59, 82, 89, 94, 83, 51, 56, 82, 52, 30, 63, 47, 29, 99, 8, 64, 17, 45, 37, 9, 6, 90, 69, 80, 61, 22, 5, 86, 25, 57, 19, 24, 94, 93, 16, 99, 30, 49, 7, 19, 15, 28, 84 ] + } ], + "jobs" : [ { + "id" : 0, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 424 + }, { + "id" : 1, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 442 + }, { + "id" : 2, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 472 + }, { + "id" : 3, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 544 + }, { + "id" : 4, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 466 + }, { + "id" : 5, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 540 + }, { + "id" : 6, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 498 + }, { + "id" : 7, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 520 + }, { + "id" : 8, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 488 + }, { + "id" : 9, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 460 + }, { + "id" : 10, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 523 + }, { + "id" : 11, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 331 + }, { + "id" : 12, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 679 + }, { + "id" : 13, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 357 + }, { + "id" : 14, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 592 + }, { + "id" : 15, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 627 + }, { + "id" : 16, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 687 + }, { + "id" : 17, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 547 + }, { + "id" : 18, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 474 + }, { + "id" : 19, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 553 + }, { + "id" : 20, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 553 + }, { + "id" : 21, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 541 + }, { + "id" : 22, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 483 + }, { + "id" : 23, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 433 + }, { + "id" : 24, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 462 + }, { + "id" : 25, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 642 + }, { + "id" : 26, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 597 + }, { + "id" : 27, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 424 + }, { + "id" : 28, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 529 + }, { + "id" : 29, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 683 + }, { + "id" : 30, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 438 + }, { + "id" : 31, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 496 + }, { + "id" : 32, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 553 + }, { + "id" : 33, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 634 + }, { + "id" : 34, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 587 + }, { + "id" : 35, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 617 + }, { + "id" : 36, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 534 + }, { + "id" : 37, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 484 + }, { + "id" : 38, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 368 + }, { + "id" : 39, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 483 + }, { + "id" : 40, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 535 + }, { + "id" : 41, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 610 + }, { + "id" : 42, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 424 + }, { + "id" : 43, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 635 + }, { + "id" : 44, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 563 + }, { + "id" : 45, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 436 + }, { + "id" : 46, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 494 + }, { + "id" : 47, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 584 + }, { + "id" : 48, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 632 + }, { + "id" : 49, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 511 + }, { + "id" : 50, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 468 + }, { + "id" : 51, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 396 + }, { + "id" : 52, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 488 + }, { + "id" : 53, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 540 + }, { + "id" : 54, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 584 + }, { + "id" : 55, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 724 + }, { + "id" : 56, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 509 + }, { + "id" : 57, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 508 + }, { + "id" : 58, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 687 + }, { + "id" : 59, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 356 + }, { + "id" : 60, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 647 + }, { + "id" : 61, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 470 + }, { + "id" : 62, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 473 + }, { + "id" : 63, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 438 + }, { + "id" : 64, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 362 + }, { + "id" : 65, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 429 + }, { + "id" : 66, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 554 + }, { + "id" : 67, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 495 + }, { + "id" : 68, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 413 + }, { + "id" : 69, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 588 + }, { + "id" : 70, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 551 + }, { + "id" : 71, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 643 + }, { + "id" : 72, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 344 + }, { + "id" : 73, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 394 + }, { + "id" : 74, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 595 + }, { + "id" : 75, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 334 + }, { + "id" : 76, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 515 + }, { + "id" : 77, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 648 + }, { + "id" : 78, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 479 + }, { + "id" : 79, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 509 + }, { + "id" : 80, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 475 + }, { + "id" : 81, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 577 + }, { + "id" : 82, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 374 + }, { + "id" : 83, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 596 + }, { + "id" : 84, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 276 + }, { + "id" : 85, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 457 + }, { + "id" : 86, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 408 + }, { + "id" : 87, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 505 + }, { + "id" : 88, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 386 + }, { + "id" : 89, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 552 + }, { + "id" : 90, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 592 + }, { + "id" : 91, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 561 + }, { + "id" : 92, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 577 + }, { + "id" : 93, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 399 + }, { + "id" : 94, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 530 + }, { + "id" : 95, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 524 + }, { + "id" : 96, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 462 + }, { + "id" : 97, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 505 + }, { + "id" : 98, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 619 + }, { + "id" : 99, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 609 + }, { + "id" : 100, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 437 + }, { + "id" : 101, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 611 + }, { + "id" : 102, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 365 + }, { + "id" : 103, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 379 + }, { + "id" : 104, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 518 + }, { + "id" : 105, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 467 + }, { + "id" : 106, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 533 + }, { + "id" : 107, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 374 + }, { + "id" : 108, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 447 + }, { + "id" : 109, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 575 + }, { + "id" : 110, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 377 + }, { + "id" : 111, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 537 + }, { + "id" : 112, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 641 + }, { + "id" : 113, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 634 + }, { + "id" : 114, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 600 + }, { + "id" : 115, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 499 + }, { + "id" : 116, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 537 + }, { + "id" : 117, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 697 + }, { + "id" : 118, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 447 + }, { + "id" : 119, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 586 + }, { + "id" : 120, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 400 + }, { + "id" : 121, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 553 + }, { + "id" : 122, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 318 + }, { + "id" : 123, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 556 + }, { + "id" : 124, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 585 + }, { + "id" : 125, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 472 + }, { + "id" : 126, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 409 + }, { + "id" : 127, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 531 + }, { + "id" : 128, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 643 + }, { + "id" : 129, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 429 + }, { + "id" : 130, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 454 + }, { + "id" : 131, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 431 + }, { + "id" : 132, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 540 + }, { + "id" : 133, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 541 + }, { + "id" : 134, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 378 + }, { + "id" : 135, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 515 + }, { + "id" : 136, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 649 + }, { + "id" : 137, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 338 + }, { + "id" : 138, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 380 + }, { + "id" : 139, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 308 + }, { + "id" : 140, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 508 + }, { + "id" : 141, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 473 + }, { + "id" : 142, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 324 + }, { + "id" : 143, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 658 + }, { + "id" : 144, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 489 + }, { + "id" : 145, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 606 + }, { + "id" : 146, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 397 + }, { + "id" : 147, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 218 + }, { + "id" : 148, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 322 + }, { + "id" : 149, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 585 + }, { + "id" : 150, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 523 + }, { + "id" : 151, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 469 + }, { + "id" : 152, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 490 + }, { + "id" : 153, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 516 + }, { + "id" : 154, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 441 + }, { + "id" : 155, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 544 + }, { + "id" : 156, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 422 + }, { + "id" : 157, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 503 + }, { + "id" : 158, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 667 + }, { + "id" : 159, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 688 + }, { + "id" : 160, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 501 + }, { + "id" : 161, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 549 + }, { + "id" : 162, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 575 + }, { + "id" : 163, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 433 + }, { + "id" : 164, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 489 + }, { + "id" : 165, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 471 + }, { + "id" : 166, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 517 + }, { + "id" : 167, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 372 + }, { + "id" : 168, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 535 + }, { + "id" : 169, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 518 + }, { + "id" : 170, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 571 + }, { + "id" : 171, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 445 + }, { + "id" : 172, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 579 + }, { + "id" : 173, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 421 + }, { + "id" : 174, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 532 + }, { + "id" : 175, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 417 + }, { + "id" : 176, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 216 + }, { + "id" : 177, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 512 + }, { + "id" : 178, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 489 + }, { + "id" : 179, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 473 + }, { + "id" : 180, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 530 + }, { + "id" : 181, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 388 + }, { + "id" : 182, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 628 + }, { + "id" : 183, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 274 + }, { + "id" : 184, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 526 + }, { + "id" : 185, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 472 + }, { + "id" : 186, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 526 + }, { + "id" : 187, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 366 + }, { + "id" : 188, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 604 + }, { + "id" : 189, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 535 + }, { + "id" : 190, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 615 + }, { + "id" : 191, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 556 + }, { + "id" : 192, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 518 + }, { + "id" : 193, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 439 + }, { + "id" : 194, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 506 + }, { + "id" : 195, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 413 + }, { + "id" : 196, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 432 + }, { + "id" : 197, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 490 + }, { + "id" : 198, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 417 + }, { + "id" : 199, + "allMachines" : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + "processingTimeSum" : 560 + } ], + "machine" : 0, + "score" : "0hard/-10727soft" +} \ No newline at end of file diff --git a/scoredirector-benchmark.properties b/scoredirector-benchmark.properties index 1eed5967..17ee9080 100644 --- a/scoredirector-benchmark.properties +++ b/scoredirector-benchmark.properties @@ -1,15 +1,15 @@ # Not including this file with your benchmarks will execute all examples across all supported score director types. -# Possible values: cs, cs_justified, easy, incremental +# Possible values: cs, cs_justified # Not including either will cause all examples to not be executed for that score director type. # If included, example may still not be executed because it has no support for that score director type. -score_director_type=cs,cs_justified,easy,incremental +score_director_type=cs,cs_justified -# Possible values: cloud_balancing, conference_scheduling, curriculum_course, examination, machine_reassignment, -# meeting_scheduling, nurse_rostering, patient_admission_scheduling, task_assigning, -# traveling_tournament, tsp, vehicle_routing +# Possible values: cloud_balancing, conference_scheduling, curriculum_course, examination, flow_shop, +# machine_reassignment, meeting_scheduling, nurse_rostering, patient_admission_scheduling, +# task_assigning, traveling_tournament, vehicle_routing # Not including either will cause all score director types to not be executed for that example. -example=cloud_balancing,conference_scheduling,curriculum_course,examination,machine_reassignment,meeting_scheduling,nurse_rostering,patient_admission_scheduling,task_assigning,traveling_tournament,tsp,vehicle_routing +example=flow_shop,machine_reassignment,meeting_scheduling,nurse_rostering,patient_admission_scheduling,task_assigning,traveling_tournament,vehicle_routing # How many forks to run each example with. # Default is 10. diff --git a/src/main/java/ai/timefold/solver/benchmarks/competitive/tsplib95/TSPLIBDataset.java b/src/main/java/ai/timefold/solver/benchmarks/competitive/tsplib95/TSPLIBDataset.java index cd5c31ff..a75ba9f3 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/competitive/tsplib95/TSPLIBDataset.java +++ b/src/main/java/ai/timefold/solver/benchmarks/competitive/tsplib95/TSPLIBDataset.java @@ -50,21 +50,21 @@ public enum TSPLIBDataset implements Dataset { d198(15780), d493(35002), d657(48912), - d1291(50801), - d1655(62128), - d2103(80450), + d1291(50801, true, true), + d1655(62128, true, true), + d2103(80450, true, true), d15112(157308, true, true), d18512(64523, true, true), dantzig42(699), - dsj1000(18660188), + dsj1000(18660188, true, true), eil51(426), eil76(538), eil101(629), fl417(11861), - fl1400(20127), - fl1577(22249), - fl3795(28772), - fnl4461(182566), + fl1400(20127, true, true), + fl1577(22249, true, true), + fl3795(28772, true, true), + fnl4461(182566, true, true), fri26(937), ft53(6905, false), ft70(38673, false), @@ -103,13 +103,13 @@ public enum TSPLIBDataset implements Dataset { lin105(14379), lin318(42029), // linhp318(41345), // No support for FIXED_EDGES; LocalSolver has it. - nrw1379(56638), + nrw1379(56638, true, true), p43(5620, false), p654(34643), pa561(2763), pcb442(50778), - pcb1173(56892), - pcb3038(137694), + pcb1173(56892, true, true), + pcb3038(137694, true, true), pla7397(23260728, true, true), pla33810(66048945, true, true), pla85900(142382641, true, true), @@ -123,8 +123,8 @@ public enum TSPLIBDataset implements Dataset { pr264(49135), pr299(48191), pr439(107217), - pr1002(259045), - pr2392(378032), + pr1002(259045, true, true), + pr2392(378032, true, true), rat99(1211), rat195(2323), rat575(6773), @@ -135,16 +135,16 @@ public enum TSPLIBDataset implements Dataset { rbg443(2720, false), rd100(7910), rd400(15281), - rl1304(252948), - rl1323(270199), - rl1889(316536), + rl1304(252948, true, true), + rl1323(270199, true, true), + rl1889(316536, true, true), rl5915(565530, true, true), rl5934(556045, true, true), rl11849(923288, true, true), ry48p(14422, false), si175(21407), si535(48450), - si1032(92650), + si1032(92650, true, true), st70(675), swiss42(1273), ts225(126643), @@ -152,20 +152,20 @@ public enum TSPLIBDataset implements Dataset { u159(42080), u574(36905), u724(41910), - u1060(224094), - u1432(152970), - u1817(57201), - u2152(64253), - u2319(234256), + u1060(224094, true, true), + u1432(152970, true, true), + u1817(57201, true, true), + u2152(64253, true, true), + u2319(234256, true, true), ulysses16(6859), ulysses22(7013), usa13509(19982859, true, true), - vm1084(239297), - vm1748(336556); + vm1084(239297, true, true), + vm1748(336556, true, true); private final int bestKnownDistance; private final boolean symmetric; - private final boolean large; + private final boolean large; // Datasets over 1000 are typically marked large; one list var => 1000+ sized lists. TSPLIBDataset(int bestKnownDistance) { this(bestKnownDistance, true); diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/cloudbalancing/optional/score/CloudBalancingIncrementalScoreCalculator.java b/src/main/java/ai/timefold/solver/benchmarks/examples/cloudbalancing/optional/score/CloudBalancingIncrementalScoreCalculator.java deleted file mode 100644 index b9b93558..00000000 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/cloudbalancing/optional/score/CloudBalancingIncrementalScoreCalculator.java +++ /dev/null @@ -1,152 +0,0 @@ -package ai.timefold.solver.benchmarks.examples.cloudbalancing.optional.score; - -import java.util.HashMap; -import java.util.Map; - -import ai.timefold.solver.benchmarks.examples.cloudbalancing.domain.CloudBalance; -import ai.timefold.solver.benchmarks.examples.cloudbalancing.domain.CloudComputer; -import ai.timefold.solver.benchmarks.examples.cloudbalancing.domain.CloudProcess; -import ai.timefold.solver.core.api.score.HardSoftScore; -import ai.timefold.solver.core.api.score.calculator.IncrementalScoreCalculator; - -public class CloudBalancingIncrementalScoreCalculator - implements IncrementalScoreCalculator { - - private Map cpuPowerUsageMap; - private Map memoryUsageMap; - private Map networkBandwidthUsageMap; - private Map processCountMap; - - private int hardScore; - private int softScore; - - @Override - public void resetWorkingSolution(CloudBalance cloudBalance) { - int computerListSize = cloudBalance.getComputerList().size(); - cpuPowerUsageMap = new HashMap<>(computerListSize); - memoryUsageMap = new HashMap<>(computerListSize); - networkBandwidthUsageMap = new HashMap<>(computerListSize); - processCountMap = new HashMap<>(computerListSize); - for (CloudComputer computer : cloudBalance.getComputerList()) { - cpuPowerUsageMap.put(computer, 0); - memoryUsageMap.put(computer, 0); - networkBandwidthUsageMap.put(computer, 0); - processCountMap.put(computer, 0); - } - hardScore = 0; - softScore = 0; - for (CloudProcess process : cloudBalance.getProcessList()) { - insert(process); - } - } - - @Override - public void beforeEntityAdded(Object entity) { - // Do nothing - } - - @Override - public void afterEntityAdded(Object entity) { - // TODO the maps should probably be adjusted - insert((CloudProcess) entity); - } - - @Override - public void beforeVariableChanged(Object entity, String variableName) { - retract((CloudProcess) entity); - } - - @Override - public void afterVariableChanged(Object entity, String variableName) { - insert((CloudProcess) entity); - } - - @Override - public void beforeEntityRemoved(Object entity) { - retract((CloudProcess) entity); - } - - @Override - public void afterEntityRemoved(Object entity) { - // Do nothing - // TODO the maps should probably be adjusted - } - - private void insert(CloudProcess process) { - CloudComputer computer = process.getComputer(); - if (computer != null) { - int cpuPower = computer.getCpuPower(); - int oldCpuPowerUsage = cpuPowerUsageMap.get(computer); - int oldCpuPowerAvailable = cpuPower - oldCpuPowerUsage; - int newCpuPowerUsage = oldCpuPowerUsage + process.getRequiredCpuPower(); - int newCpuPowerAvailable = cpuPower - newCpuPowerUsage; - hardScore += Math.min(newCpuPowerAvailable, 0) - Math.min(oldCpuPowerAvailable, 0); - cpuPowerUsageMap.put(computer, newCpuPowerUsage); - - int memory = computer.getMemory(); - int oldMemoryUsage = memoryUsageMap.get(computer); - int oldMemoryAvailable = memory - oldMemoryUsage; - int newMemoryUsage = oldMemoryUsage + process.getRequiredMemory(); - int newMemoryAvailable = memory - newMemoryUsage; - hardScore += Math.min(newMemoryAvailable, 0) - Math.min(oldMemoryAvailable, 0); - memoryUsageMap.put(computer, newMemoryUsage); - - int networkBandwidth = computer.getNetworkBandwidth(); - int oldNetworkBandwidthUsage = networkBandwidthUsageMap.get(computer); - int oldNetworkBandwidthAvailable = networkBandwidth - oldNetworkBandwidthUsage; - int newNetworkBandwidthUsage = oldNetworkBandwidthUsage + process.getRequiredNetworkBandwidth(); - int newNetworkBandwidthAvailable = networkBandwidth - newNetworkBandwidthUsage; - hardScore += Math.min(newNetworkBandwidthAvailable, 0) - Math.min(oldNetworkBandwidthAvailable, 0); - networkBandwidthUsageMap.put(computer, newNetworkBandwidthUsage); - - int oldProcessCount = processCountMap.get(computer); - if (oldProcessCount == 0) { - softScore -= computer.getCost(); - } - int newProcessCount = oldProcessCount + 1; - processCountMap.put(computer, newProcessCount); - } - } - - private void retract(CloudProcess process) { - CloudComputer computer = process.getComputer(); - if (computer != null) { - int cpuPower = computer.getCpuPower(); - int oldCpuPowerUsage = cpuPowerUsageMap.get(computer); - int oldCpuPowerAvailable = cpuPower - oldCpuPowerUsage; - int newCpuPowerUsage = oldCpuPowerUsage - process.getRequiredCpuPower(); - int newCpuPowerAvailable = cpuPower - newCpuPowerUsage; - hardScore += Math.min(newCpuPowerAvailable, 0) - Math.min(oldCpuPowerAvailable, 0); - cpuPowerUsageMap.put(computer, newCpuPowerUsage); - - int memory = computer.getMemory(); - int oldMemoryUsage = memoryUsageMap.get(computer); - int oldMemoryAvailable = memory - oldMemoryUsage; - int newMemoryUsage = oldMemoryUsage - process.getRequiredMemory(); - int newMemoryAvailable = memory - newMemoryUsage; - hardScore += Math.min(newMemoryAvailable, 0) - Math.min(oldMemoryAvailable, 0); - memoryUsageMap.put(computer, newMemoryUsage); - - int networkBandwidth = computer.getNetworkBandwidth(); - int oldNetworkBandwidthUsage = networkBandwidthUsageMap.get(computer); - int oldNetworkBandwidthAvailable = networkBandwidth - oldNetworkBandwidthUsage; - int newNetworkBandwidthUsage = oldNetworkBandwidthUsage - process.getRequiredNetworkBandwidth(); - int newNetworkBandwidthAvailable = networkBandwidth - newNetworkBandwidthUsage; - hardScore += Math.min(newNetworkBandwidthAvailable, 0) - Math.min(oldNetworkBandwidthAvailable, 0); - networkBandwidthUsageMap.put(computer, newNetworkBandwidthUsage); - - int oldProcessCount = processCountMap.get(computer); - int newProcessCount = oldProcessCount - 1; - if (newProcessCount == 0) { - softScore += computer.getCost(); - } - processCountMap.put(computer, newProcessCount); - } - } - - @Override - public HardSoftScore calculateScore() { - return HardSoftScore.of(hardScore, softScore); - } - -} diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/cloudbalancing/optional/score/CloudBalancingMapBasedEasyScoreCalculator.java b/src/main/java/ai/timefold/solver/benchmarks/examples/cloudbalancing/optional/score/CloudBalancingMapBasedEasyScoreCalculator.java deleted file mode 100644 index 05372e0d..00000000 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/cloudbalancing/optional/score/CloudBalancingMapBasedEasyScoreCalculator.java +++ /dev/null @@ -1,92 +0,0 @@ -package ai.timefold.solver.benchmarks.examples.cloudbalancing.optional.score; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import ai.timefold.solver.benchmarks.examples.cloudbalancing.domain.CloudBalance; -import ai.timefold.solver.benchmarks.examples.cloudbalancing.domain.CloudComputer; -import ai.timefold.solver.benchmarks.examples.cloudbalancing.domain.CloudProcess; -import ai.timefold.solver.core.api.score.HardSoftScore; -import ai.timefold.solver.core.api.score.calculator.EasyScoreCalculator; - -public class CloudBalancingMapBasedEasyScoreCalculator implements EasyScoreCalculator { - - @Override - public HardSoftScore calculateScore(CloudBalance cloudBalance) { - int computerListSize = cloudBalance.getComputerList().size(); - Map cpuPowerUsageMap = new HashMap<>(computerListSize); - Map memoryUsageMap = new HashMap<>(computerListSize); - Map networkBandwidthUsageMap = new HashMap<>(computerListSize); - for (CloudComputer computer : cloudBalance.getComputerList()) { - cpuPowerUsageMap.put(computer, 0); - memoryUsageMap.put(computer, 0); - networkBandwidthUsageMap.put(computer, 0); - } - Set usedComputerSet = new HashSet<>(computerListSize); - - visitProcessList(cpuPowerUsageMap, memoryUsageMap, networkBandwidthUsageMap, - usedComputerSet, cloudBalance.getProcessList()); - - int hardScore = sumHardScore(cpuPowerUsageMap, memoryUsageMap, networkBandwidthUsageMap); - int softScore = sumSoftScore(usedComputerSet); - - return HardSoftScore.of(hardScore, softScore); - } - - private void visitProcessList(Map cpuPowerUsageMap, - Map memoryUsageMap, Map networkBandwidthUsageMap, - Set usedComputerSet, List processList) { - // We loop through the processList only once for performance - for (CloudProcess process : processList) { - CloudComputer computer = process.getComputer(); - if (computer != null) { - int cpuPowerUsage = cpuPowerUsageMap.get(computer) + process.getRequiredCpuPower(); - cpuPowerUsageMap.put(computer, cpuPowerUsage); - int memoryUsage = memoryUsageMap.get(computer) + process.getRequiredMemory(); - memoryUsageMap.put(computer, memoryUsage); - int networkBandwidthUsage = networkBandwidthUsageMap.get(computer) + process.getRequiredNetworkBandwidth(); - networkBandwidthUsageMap.put(computer, networkBandwidthUsage); - usedComputerSet.add(computer); - } - } - } - - private int sumHardScore(Map cpuPowerUsageMap, Map memoryUsageMap, - Map networkBandwidthUsageMap) { - int hardScore = 0; - for (Map.Entry usageEntry : cpuPowerUsageMap.entrySet()) { - CloudComputer computer = usageEntry.getKey(); - int cpuPowerAvailable = computer.getCpuPower() - usageEntry.getValue(); - if (cpuPowerAvailable < 0) { - hardScore += cpuPowerAvailable; - } - } - for (Map.Entry usageEntry : memoryUsageMap.entrySet()) { - CloudComputer computer = usageEntry.getKey(); - int memoryAvailable = computer.getMemory() - usageEntry.getValue(); - if (memoryAvailable < 0) { - hardScore += memoryAvailable; - } - } - for (Map.Entry usageEntry : networkBandwidthUsageMap.entrySet()) { - CloudComputer computer = usageEntry.getKey(); - int networkBandwidthAvailable = computer.getNetworkBandwidth() - usageEntry.getValue(); - if (networkBandwidthAvailable < 0) { - hardScore += networkBandwidthAvailable; - } - } - return hardScore; - } - - private int sumSoftScore(Set usedComputerSet) { - int softScore = 0; - for (CloudComputer usedComputer : usedComputerSet) { - softScore -= usedComputer.getCost(); - } - return softScore; - } - -} diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/domain/Room.java b/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/domain/Room.java index 9c8a1e0f..afbb9b3a 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/domain/Room.java +++ b/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/domain/Room.java @@ -1,6 +1,6 @@ package ai.timefold.solver.benchmarks.examples.conferencescheduling.domain; -import java.util.Set; +import java.util.SequencedSet; import ai.timefold.solver.benchmarks.examples.common.domain.AbstractPersistable; import ai.timefold.solver.benchmarks.examples.common.persistence.jackson.JacksonUniqueIdGenerator; @@ -13,9 +13,8 @@ public class Room extends AbstractPersistable { private String name; private int capacity; - private Set talkTypeSet; - private Set unavailableTimeslotSet; - private Set tagSet; + private SequencedSet talkTypeSet; + private SequencedSet tagSet; public Room() { } @@ -49,19 +48,19 @@ public void setCapacity(int capacity) { this.capacity = capacity; } - public Set getTalkTypeSet() { + public SequencedSet getTalkTypeSet() { return talkTypeSet; } - public void setTalkTypeSet(Set talkTypeSet) { + public void setTalkTypeSet(SequencedSet talkTypeSet) { this.talkTypeSet = talkTypeSet; } - public Set getTagSet() { + public SequencedSet getTagSet() { return tagSet; } - public void setTagSet(Set tagSet) { + public void setTagSet(SequencedSet tagSet) { this.tagSet = tagSet; } @@ -74,12 +73,12 @@ public Room withCapacity(int capacity) { return this; } - public Room withTalkTypeSet(Set talkTypeSet) { + public Room withTalkTypeSet(SequencedSet talkTypeSet) { this.talkTypeSet = talkTypeSet; return this; } - public Room withTagSet(Set tagSet) { + public Room withTagSet(SequencedSet tagSet) { this.tagSet = tagSet; return this; } diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/domain/Speaker.java b/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/domain/Speaker.java index 87461876..21d1be17 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/domain/Speaker.java +++ b/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/domain/Speaker.java @@ -1,7 +1,7 @@ package ai.timefold.solver.benchmarks.examples.conferencescheduling.domain; -import java.util.Set; +import java.util.SequencedSet; import ai.timefold.solver.benchmarks.examples.common.domain.AbstractPersistable; import ai.timefold.solver.benchmarks.examples.common.persistence.jackson.JacksonUniqueIdGenerator; @@ -13,13 +13,13 @@ public class Speaker extends AbstractPersistable { private String name; - private Set unavailableTimeslotSet; - private Set preferredTimeslotTagSet; - private Set undesiredTimeslotTagSet; - private Set requiredRoomTagSet; - private Set preferredRoomTagSet; - private Set prohibitedRoomTagSet; - private Set undesiredRoomTagSet; + private SequencedSet unavailableTimeslotSet; + private SequencedSet preferredTimeslotTagSet; + private SequencedSet undesiredTimeslotTagSet; + private SequencedSet requiredRoomTagSet; + private SequencedSet preferredRoomTagSet; + private SequencedSet prohibitedRoomTagSet; + private SequencedSet undesiredRoomTagSet; public Speaker() { } @@ -45,59 +45,59 @@ public void setName(String name) { this.name = name; } - public Set getUnavailableTimeslotSet() { + public SequencedSet getUnavailableTimeslotSet() { return unavailableTimeslotSet; } - public void setUnavailableTimeslotSet(Set unavailableTimeslotSet) { + public void setUnavailableTimeslotSet(SequencedSet unavailableTimeslotSet) { this.unavailableTimeslotSet = unavailableTimeslotSet; } - public Set getPreferredTimeslotTagSet() { + public SequencedSet getPreferredTimeslotTagSet() { return preferredTimeslotTagSet; } - public void setPreferredTimeslotTagSet(Set preferredTimeslotTagSet) { + public void setPreferredTimeslotTagSet(SequencedSet preferredTimeslotTagSet) { this.preferredTimeslotTagSet = preferredTimeslotTagSet; } - public Set getUndesiredTimeslotTagSet() { + public SequencedSet getUndesiredTimeslotTagSet() { return undesiredTimeslotTagSet; } - public void setUndesiredTimeslotTagSet(Set undesiredTimeslotTagSet) { + public void setUndesiredTimeslotTagSet(SequencedSet undesiredTimeslotTagSet) { this.undesiredTimeslotTagSet = undesiredTimeslotTagSet; } - public Set getRequiredRoomTagSet() { + public SequencedSet getRequiredRoomTagSet() { return requiredRoomTagSet; } - public void setRequiredRoomTagSet(Set requiredRoomTagSet) { + public void setRequiredRoomTagSet(SequencedSet requiredRoomTagSet) { this.requiredRoomTagSet = requiredRoomTagSet; } - public Set getPreferredRoomTagSet() { + public SequencedSet getPreferredRoomTagSet() { return preferredRoomTagSet; } - public void setPreferredRoomTagSet(Set preferredRoomTagSet) { + public void setPreferredRoomTagSet(SequencedSet preferredRoomTagSet) { this.preferredRoomTagSet = preferredRoomTagSet; } - public Set getProhibitedRoomTagSet() { + public SequencedSet getProhibitedRoomTagSet() { return prohibitedRoomTagSet; } - public void setProhibitedRoomTagSet(Set prohibitedRoomTagSet) { + public void setProhibitedRoomTagSet(SequencedSet prohibitedRoomTagSet) { this.prohibitedRoomTagSet = prohibitedRoomTagSet; } - public Set getUndesiredRoomTagSet() { + public SequencedSet getUndesiredRoomTagSet() { return undesiredRoomTagSet; } - public void setUndesiredRoomTagSet(Set undesiredRoomTagSet) { + public void setUndesiredRoomTagSet(SequencedSet undesiredRoomTagSet) { this.undesiredRoomTagSet = undesiredRoomTagSet; } @@ -105,37 +105,37 @@ public void setUndesiredRoomTagSet(Set undesiredRoomTagSet) { // With methods // ************************************************************************ - public Speaker withUnavailableTimeslotSet(Set unavailableTimeslotTest) { + public Speaker withUnavailableTimeslotSet(SequencedSet unavailableTimeslotTest) { this.unavailableTimeslotSet = unavailableTimeslotTest; return this; } - public Speaker withPreferredTimeslotTagSet(Set preferredTimeslotTagSet) { + public Speaker withPreferredTimeslotTagSet(SequencedSet preferredTimeslotTagSet) { this.preferredTimeslotTagSet = preferredTimeslotTagSet; return this; } - public Speaker withUndesiredTimeslotTagSet(Set undesiredTimeslotTagSet) { + public Speaker withUndesiredTimeslotTagSet(SequencedSet undesiredTimeslotTagSet) { this.undesiredTimeslotTagSet = undesiredTimeslotTagSet; return this; } - public Speaker withRequiredRoomTagSet(Set requiredRoomTagSet) { + public Speaker withRequiredRoomTagSet(SequencedSet requiredRoomTagSet) { this.requiredRoomTagSet = requiredRoomTagSet; return this; } - public Speaker withPreferredRoomTagSet(Set preferredRoomTagSet) { + public Speaker withPreferredRoomTagSet(SequencedSet preferredRoomTagSet) { this.preferredRoomTagSet = preferredRoomTagSet; return this; } - public Speaker withUndesiredRoomTagSet(Set undesiredRoomTagSet) { + public Speaker withUndesiredRoomTagSet(SequencedSet undesiredRoomTagSet) { this.undesiredRoomTagSet = undesiredRoomTagSet; return this; } - public Speaker withProhibitedRoomTagSet(Set prohibitedRoomTagSet) { + public Speaker withProhibitedRoomTagSet(SequencedSet prohibitedRoomTagSet) { this.prohibitedRoomTagSet = prohibitedRoomTagSet; return this; } diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/domain/Talk.java b/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/domain/Talk.java index 19282f7a..545ae332 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/domain/Talk.java +++ b/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/domain/Talk.java @@ -1,7 +1,7 @@ package ai.timefold.solver.benchmarks.examples.conferencescheduling.domain; import java.util.List; -import java.util.Set; +import java.util.SequencedSet; import ai.timefold.solver.benchmarks.examples.common.domain.AbstractPersistable; import ai.timefold.solver.benchmarks.examples.common.persistence.jackson.JacksonUniqueIdGenerator; @@ -21,18 +21,18 @@ public class Talk extends AbstractPersistable { private String title; private TalkType talkType; private List speakerList; - private Set themeTrackTagSet; - private Set sectorTagSet; - private Set audienceTypeSet; + private SequencedSet themeTrackTagSet; + private SequencedSet sectorTagSet; + private SequencedSet audienceTypeSet; private int audienceLevel; - private Set contentTagSet; + private SequencedSet contentTagSet; private String language; - private Set requiredRoomTagSet; - private Set preferredRoomTagSet; - private Set prohibitedRoomTagSet; - private Set undesiredRoomTagSet; - private Set mutuallyExclusiveTalksTagSet; - private Set prerequisiteTalkSet; + private SequencedSet requiredRoomTagSet; + private SequencedSet preferredRoomTagSet; + private SequencedSet prohibitedRoomTagSet; + private SequencedSet undesiredRoomTagSet; + private SequencedSet mutuallyExclusiveTalksTagSet; + private SequencedSet prerequisiteTalkSet; private int favoriteCount; private int crowdControlRisk; @@ -60,7 +60,7 @@ public int overlappingThemeTrackCount(Talk other) { return overlappingCount(themeTrackTagSet, other.themeTrackTagSet); } - private static int overlappingCount(Set left, Set right) { + private static int overlappingCount(SequencedSet left, SequencedSet right) { int leftSize = left.size(); if (leftSize == 0) { return 0; @@ -69,8 +69,8 @@ private static int overlappingCount(Set left, Set right) { if (rightSize == 0) { return 0; } - Set smaller = leftSize < rightSize ? left : right; - Set other = smaller == left ? right : left; + SequencedSet smaller = leftSize < rightSize ? left : right; + SequencedSet other = smaller == left ? right : left; int overlappingCount = 0; for (Item_ item : smaller) { // Iterate over smaller set, lookup in the larger. if (other.contains(item)) { @@ -94,7 +94,7 @@ public int overlappingContentCount(Talk other) { } - private static int missingCount(Set required, Set available) { + private static int missingCount(SequencedSet required, SequencedSet available) { int requiredCount = required.size(); if (requiredCount == 0) { return 0; // If no items are required, none can be missing. @@ -256,12 +256,12 @@ public String toString() { } @ValueRangeProvider - public Set getTimeslotRange() { + public SequencedSet getTimeslotRange() { return talkType.getCompatibleTimeslotSet(); } @ValueRangeProvider - public Set getRoomRange() { + public SequencedSet getRoomRange() { return talkType.getCompatibleRoomSet(); } @@ -301,27 +301,27 @@ public List getSpeakerList() { return speakerList; } - public Set getThemeTrackTagSet() { + public SequencedSet getThemeTrackTagSet() { return themeTrackTagSet; } - public void setThemeTrackTagSet(Set themeTrackTagSet) { + public void setThemeTrackTagSet(SequencedSet themeTrackTagSet) { this.themeTrackTagSet = themeTrackTagSet; } - public Set getSectorTagSet() { + public SequencedSet getSectorTagSet() { return sectorTagSet; } - public void setSectorTagSet(Set sectorTagSet) { + public void setSectorTagSet(SequencedSet sectorTagSet) { this.sectorTagSet = sectorTagSet; } - public Set getAudienceTypeSet() { + public SequencedSet getAudienceTypeSet() { return audienceTypeSet; } - public void setAudienceTypeSet(Set audienceTypeSet) { + public void setAudienceTypeSet(SequencedSet audienceTypeSet) { this.audienceTypeSet = audienceTypeSet; } @@ -333,11 +333,11 @@ public void setAudienceLevel(int audienceLevel) { this.audienceLevel = audienceLevel; } - public Set getContentTagSet() { + public SequencedSet getContentTagSet() { return contentTagSet; } - public void setContentTagSet(Set contentTagSet) { + public void setContentTagSet(SequencedSet contentTagSet) { this.contentTagSet = contentTagSet; } @@ -349,35 +349,35 @@ public void setSpeakerList(List speakerList) { this.speakerList = speakerList; } - public Set getRequiredRoomTagSet() { + public SequencedSet getRequiredRoomTagSet() { return requiredRoomTagSet; } - public void setRequiredRoomTagSet(Set requiredRoomTagSet) { + public void setRequiredRoomTagSet(SequencedSet requiredRoomTagSet) { this.requiredRoomTagSet = requiredRoomTagSet; } - public Set getPreferredRoomTagSet() { + public SequencedSet getPreferredRoomTagSet() { return preferredRoomTagSet; } - public void setPreferredRoomTagSet(Set preferredRoomTagSet) { + public void setPreferredRoomTagSet(SequencedSet preferredRoomTagSet) { this.preferredRoomTagSet = preferredRoomTagSet; } - public Set getProhibitedRoomTagSet() { + public SequencedSet getProhibitedRoomTagSet() { return prohibitedRoomTagSet; } - public void setProhibitedRoomTagSet(Set prohibitedRoomTagSet) { + public void setProhibitedRoomTagSet(SequencedSet prohibitedRoomTagSet) { this.prohibitedRoomTagSet = prohibitedRoomTagSet; } - public Set getUndesiredRoomTagSet() { + public SequencedSet getUndesiredRoomTagSet() { return undesiredRoomTagSet; } - public void setUndesiredRoomTagSet(Set undesiredRoomTagSet) { + public void setUndesiredRoomTagSet(SequencedSet undesiredRoomTagSet) { this.undesiredRoomTagSet = undesiredRoomTagSet; } @@ -405,19 +405,19 @@ public void setRoom(Room room) { this.room = room; } - public Set getMutuallyExclusiveTalksTagSet() { + public SequencedSet getMutuallyExclusiveTalksTagSet() { return mutuallyExclusiveTalksTagSet; } - public void setMutuallyExclusiveTalksTagSet(Set mutuallyExclusiveTalksTagSet) { + public void setMutuallyExclusiveTalksTagSet(SequencedSet mutuallyExclusiveTalksTagSet) { this.mutuallyExclusiveTalksTagSet = mutuallyExclusiveTalksTagSet; } - public Set getPrerequisiteTalkSet() { + public SequencedSet getPrerequisiteTalkSet() { return prerequisiteTalkSet; } - public void setPrerequisiteTalkSet(Set prerequisiteTalkSet) { + public void setPrerequisiteTalkSet(SequencedSet prerequisiteTalkSet) { this.prerequisiteTalkSet = prerequisiteTalkSet; } @@ -451,17 +451,17 @@ public Talk withSpeakerList(List speakerList) { return this; } - public Talk withThemeTrackTagSet(Set themeTrackTagSet) { + public Talk withThemeTrackTagSet(SequencedSet themeTrackTagSet) { this.themeTrackTagSet = themeTrackTagSet; return this; } - public Talk withSectorTagSet(Set sectorTagSet) { + public Talk withSectorTagSet(SequencedSet sectorTagSet) { this.sectorTagSet = sectorTagSet; return this; } - public Talk withAudienceTypeSet(Set audienceTypeSet) { + public Talk withAudienceTypeSet(SequencedSet audienceTypeSet) { this.audienceTypeSet = audienceTypeSet; return this; } @@ -471,7 +471,7 @@ public Talk withAudienceLevel(int audienceLevel) { return this; } - public Talk withContentTagSet(Set contentTagSet) { + public Talk withContentTagSet(SequencedSet contentTagSet) { this.contentTagSet = contentTagSet; return this; } @@ -481,32 +481,32 @@ public Talk withLanguage(String language) { return this; } - public Talk withRequiredRoomTagSet(Set requiredRoomTagSet) { + public Talk withRequiredRoomTagSet(SequencedSet requiredRoomTagSet) { this.requiredRoomTagSet = requiredRoomTagSet; return this; } - public Talk withPreferredRoomTagSet(Set preferredRoomTagSet) { + public Talk withPreferredRoomTagSet(SequencedSet preferredRoomTagSet) { this.preferredRoomTagSet = preferredRoomTagSet; return this; } - public Talk withProhibitedRoomTagSet(Set prohibitedRoomTagSet) { + public Talk withProhibitedRoomTagSet(SequencedSet prohibitedRoomTagSet) { this.prohibitedRoomTagSet = prohibitedRoomTagSet; return this; } - public Talk withUndesiredRoomTagSet(Set undesiredRoomTagSet) { + public Talk withUndesiredRoomTagSet(SequencedSet undesiredRoomTagSet) { this.undesiredRoomTagSet = undesiredRoomTagSet; return this; } - public Talk withMutuallyExclusiveTalksTagSet(Set mutuallyExclusiveTalksTagSet) { + public Talk withMutuallyExclusiveTalksTagSet(SequencedSet mutuallyExclusiveTalksTagSet) { this.mutuallyExclusiveTalksTagSet = mutuallyExclusiveTalksTagSet; return this; } - public Talk withPrerequisiteTalksCodesSet(Set prerequisiteTalksCodesSet) { + public Talk withPrerequisiteTalksCodesSet(SequencedSet prerequisiteTalksCodesSet) { this.prerequisiteTalkSet = prerequisiteTalksCodesSet; return this; } diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/domain/TalkType.java b/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/domain/TalkType.java index c2ab6bbd..13b2941f 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/domain/TalkType.java +++ b/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/domain/TalkType.java @@ -1,7 +1,7 @@ package ai.timefold.solver.benchmarks.examples.conferencescheduling.domain; import java.util.LinkedHashSet; -import java.util.Set; +import java.util.SequencedSet; import ai.timefold.solver.benchmarks.examples.common.domain.AbstractPersistable; import ai.timefold.solver.benchmarks.examples.common.persistence.jackson.JacksonUniqueIdGenerator; @@ -13,8 +13,8 @@ public class TalkType extends AbstractPersistable { private String name; - private Set compatibleTimeslotSet; - private Set compatibleRoomSet; + private SequencedSet compatibleTimeslotSet; + private SequencedSet compatibleRoomSet; public TalkType() { } @@ -45,19 +45,19 @@ public void setName(String name) { this.name = name; } - public Set getCompatibleTimeslotSet() { + public SequencedSet getCompatibleTimeslotSet() { return compatibleTimeslotSet; } - public void setCompatibleTimeslotSet(Set compatibleTimeslotSet) { + public void setCompatibleTimeslotSet(SequencedSet compatibleTimeslotSet) { this.compatibleTimeslotSet = new LinkedHashSet<>(compatibleTimeslotSet); } - public Set getCompatibleRoomSet() { + public SequencedSet getCompatibleRoomSet() { return compatibleRoomSet; } - public void setCompatibleRoomSet(Set compatibleRoomSet) { + public void setCompatibleRoomSet(SequencedSet compatibleRoomSet) { this.compatibleRoomSet = new LinkedHashSet<>(compatibleRoomSet); } diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/domain/Timeslot.java b/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/domain/Timeslot.java index fdb6208f..8df85395 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/domain/Timeslot.java +++ b/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/domain/Timeslot.java @@ -3,7 +3,7 @@ import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; -import java.util.Set; +import java.util.SequencedSet; import ai.timefold.solver.benchmarks.examples.common.domain.AbstractPersistable; import ai.timefold.solver.benchmarks.examples.common.persistence.jackson.JacksonUniqueIdGenerator; @@ -17,8 +17,8 @@ public class Timeslot extends AbstractPersistable { private LocalDateTime startDateTime; private LocalDateTime endDateTime; - private Set talkTypeSet; - private Set tagSet; + private SequencedSet talkTypeSet; + private SequencedSet tagSet; // Cached private int durationInMinutes; @@ -108,19 +108,19 @@ public void setEndDateTime(LocalDateTime endDateTime) { : (int) Duration.between(startDateTime, endDateTime).toMinutes(); } - public Set getTalkTypeSet() { + public SequencedSet getTalkTypeSet() { return talkTypeSet; } - public void setTalkTypeSet(Set talkTypeSet) { + public void setTalkTypeSet(SequencedSet talkTypeSet) { this.talkTypeSet = talkTypeSet; } - public Set getTagSet() { + public SequencedSet getTagSet() { return tagSet; } - public void setTagSet(Set tagSet) { + public void setTagSet(SequencedSet tagSet) { this.tagSet = tagSet; } @@ -138,12 +138,12 @@ public Timeslot withEndDateTime(LocalDateTime endDateTime) { return this; } - public Timeslot withTalkTypeSet(Set talkTypeSet) { + public Timeslot withTalkTypeSet(SequencedSet talkTypeSet) { this.talkTypeSet = talkTypeSet; return this; } - public Timeslot withTagSet(Set tagSet) { + public Timeslot withTagSet(SequencedSet tagSet) { this.tagSet = tagSet; return this; } diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/persistence/ConferenceSchedulingGenerator.java b/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/persistence/ConferenceSchedulingGenerator.java index 97e8ab16..e96bdc88 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/persistence/ConferenceSchedulingGenerator.java +++ b/src/main/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/persistence/ConferenceSchedulingGenerator.java @@ -13,6 +13,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Random; +import java.util.SequencedSet; import java.util.Set; import java.util.stream.Collectors; @@ -281,7 +282,7 @@ private void createTimeslotList(ConferenceSolution solution, int timeslotListSiz timeslot.setEndDateTime(LocalDateTime.of(day, pair.value())); var talkType = timeslot.getDurationInMinutes() >= 120 ? labTalkType : breakoutTalkType; talkType.getCompatibleTimeslotSet().add(timeslot); - timeslot.setTalkTypeSet(Collections.singleton(talkType)); + timeslot.setTalkTypeSet(new LinkedHashSet<>(Collections.singleton(talkType))); timeslotOptionsIndex++; var tagSet = new LinkedHashSet(2); if (timeslot.getStartDateTime().getHour() == 13) { @@ -308,7 +309,7 @@ private void createRoomList(ConferenceSolution solution, int roomListSize) { talkType = breakoutTalkType; } talkType.getCompatibleRoomSet().add(room); - room.withTalkTypeSet(Collections.singleton(talkType)); + room.withTalkTypeSet(new LinkedHashSet<>(Collections.singleton(talkType))); var tagSet = new LinkedHashSet(roomTagProbabilityList.size()); for (var roomTagProbability : roomTagProbabilityList) { if ((i == 0 || i == 4 || random.nextDouble() < roomTagProbability.value()) @@ -333,7 +334,7 @@ private void createSpeakerList(ConferenceSolution solution, int speakerListSize) for (var i = 0; i < speakerListSize; i++) { var speaker = new Speaker(i); speaker.setName(speakerNameGenerator.generateNextValue()); - Set unavailableTimeslotSet; + SequencedSet unavailableTimeslotSet; var preferredTimeslotTagSet = new LinkedHashSet(); var undesiredTimeslotTagSet = new LinkedHashSet(); var timeslotList = solution.getTimeslotList(); @@ -411,7 +412,8 @@ private void createTalkList(ConferenceSolution solution, int talkListSize) { if (random.nextDouble() < 0.20) { sectorTagSet.add(sectorTagOptions.get(random.nextInt(sectorTagOptions.size()))); } - talk.setAudienceTypeSet(Collections.singleton(audienceTypeOptions.get(random.nextInt(audienceTypeOptions.size())))); + var audienceType = audienceTypeOptions.get(random.nextInt(audienceTypeOptions.size())); + talk.setAudienceTypeSet(new LinkedHashSet<>(Collections.singleton(audienceType))); talk.setAudienceLevel(1 + random.nextInt(3)); var contentTagSet = new LinkedHashSet(); for (var contentTagOption : contentTagOptions) { diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/curriculumcourse/domain/Course.java b/src/main/java/ai/timefold/solver/benchmarks/examples/curriculumcourse/domain/Course.java index 3fe9ebd6..76be102a 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/curriculumcourse/domain/Course.java +++ b/src/main/java/ai/timefold/solver/benchmarks/examples/curriculumcourse/domain/Course.java @@ -4,7 +4,7 @@ import java.util.Arrays; import java.util.LinkedHashSet; -import java.util.Set; +import java.util.SequencedSet; import java.util.stream.Collectors; import ai.timefold.solver.benchmarks.examples.common.domain.AbstractPersistable; @@ -21,7 +21,7 @@ public class Course extends AbstractPersistable { private int lectureSize; private int minWorkingDaySize; - private Set curriculumSet; + private SequencedSet curriculumSet; private int studentSize; public Course() { @@ -70,11 +70,11 @@ public void setMinWorkingDaySize(int minWorkingDaySize) { this.minWorkingDaySize = minWorkingDaySize; } - public Set getCurriculumSet() { + public SequencedSet getCurriculumSet() { return curriculumSet; } - public void setCurriculumSet(Set curriculumSet) { + public void setCurriculumSet(SequencedSet curriculumSet) { this.curriculumSet = curriculumSet; } diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/curriculumcourse/domain/Lecture.java b/src/main/java/ai/timefold/solver/benchmarks/examples/curriculumcourse/domain/Lecture.java index 1b70689b..8da48071 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/curriculumcourse/domain/Lecture.java +++ b/src/main/java/ai/timefold/solver/benchmarks/examples/curriculumcourse/domain/Lecture.java @@ -1,6 +1,6 @@ package ai.timefold.solver.benchmarks.examples.curriculumcourse.domain; -import java.util.Set; +import java.util.SequencedSet; import ai.timefold.solver.benchmarks.examples.common.domain.AbstractPersistable; import ai.timefold.solver.benchmarks.examples.curriculumcourse.domain.solver.LectureComparatorFactory; @@ -101,7 +101,7 @@ public int getStudentSize() { } @JsonIgnore - public Set getCurriculumSet() { + public SequencedSet getCurriculumSet() { return course.getCurriculumSet(); } diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/examination/domain/Topic.java b/src/main/java/ai/timefold/solver/benchmarks/examples/examination/domain/Topic.java index 220b452a..e5ff3d07 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/examination/domain/Topic.java +++ b/src/main/java/ai/timefold/solver/benchmarks/examples/examination/domain/Topic.java @@ -1,7 +1,8 @@ package ai.timefold.solver.benchmarks.examples.examination.domain; import java.util.Arrays; -import java.util.Set; +import java.util.LinkedHashSet; +import java.util.SequencedSet; import java.util.stream.Collectors; import ai.timefold.solver.benchmarks.examples.common.domain.AbstractPersistable; @@ -14,11 +15,11 @@ public class Topic extends AbstractPersistable { private int duration; // in minutes - private Set studentSet; + private SequencedSet studentSet; // Calculated during initialization, not modified during score calculation. private boolean frontLoadLarge; - private Set coincidenceTopicSet = null; + private SequencedSet coincidenceTopicSet = null; public int getDuration() { return duration; @@ -28,11 +29,11 @@ public void setDuration(int duration) { this.duration = duration; } - public Set getStudentSet() { + public SequencedSet getStudentSet() { return studentSet; } - public void setStudentSet(Set studentSet) { + public void setStudentSet(SequencedSet studentSet) { this.studentSet = studentSet; } @@ -49,11 +50,11 @@ public void setFrontLoadLarge(boolean frontLoadLarge) { this.frontLoadLarge = frontLoadLarge; } - public Set getCoincidenceTopicSet() { + public SequencedSet getCoincidenceTopicSet() { return coincidenceTopicSet; } - public void setCoincidenceTopicSet(Set coincidenceTopicSet) { + public void setCoincidenceTopicSet(SequencedSet coincidenceTopicSet) { this.coincidenceTopicSet = coincidenceTopicSet; } @@ -81,7 +82,7 @@ public Topic withDuration(int duration) { } public Topic withStudents(Student... students) { - this.setStudentSet(Arrays.stream(students).collect(Collectors.toSet())); + this.setStudentSet(Arrays.stream(students).collect(Collectors.toCollection(LinkedHashSet::new))); return this; } @@ -90,7 +91,7 @@ public Topic withFrontLoadLarge(boolean frontLoadLarge) { return this; } - public Topic withCoincidenceTopicSet(Set coincidenceTopicSet) { + public Topic withCoincidenceTopicSet(SequencedSet coincidenceTopicSet) { this.setCoincidenceTopicSet(coincidenceTopicSet); return this; } diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/examination/persistence/ExaminationImporter.java b/src/main/java/ai/timefold/solver/benchmarks/examples/examination/persistence/ExaminationImporter.java index 0453f82a..d5e87d08 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/examination/persistence/ExaminationImporter.java +++ b/src/main/java/ai/timefold/solver/benchmarks/examples/examination/persistence/ExaminationImporter.java @@ -19,6 +19,7 @@ import java.util.Locale; import java.util.Map; import java.util.Queue; +import java.util.SequencedSet; import java.util.Set; import ai.timefold.solver.benchmarks.examples.common.persistence.AbstractTxtSolutionImporter; @@ -116,7 +117,7 @@ private void readTopicListAndStudentList() throws IOException { var line = bufferedReader.readLine(); var lineTokens = line.split(SPLIT_REGEX); topic.setDuration(Integer.parseInt(lineTokens[0])); - Set topicStudentList = new LinkedHashSet<>(lineTokens.length - 1); + SequencedSet topicStudentList = new LinkedHashSet<>(lineTokens.length - 1); for (var j = 1; j < lineTokens.length; j++) { topicStudentList.add(findOrCreateStudent(studentMap, Integer.parseInt(lineTokens[j]))); } diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/app/FlowShopApp.java b/src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/app/FlowShopApp.java index 8330bb9b..90ed81d3 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/app/FlowShopApp.java +++ b/src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/app/FlowShopApp.java @@ -25,11 +25,8 @@ public FlowShopApp() { super("FlowShop Scheduling Problem", """ Assign jobs to a machine. - All jobs must be assigned. - A machine can run only one job at the time. - A job can only begin on the machine once it has completed on the previous machine or after the prior job has finished. """, SOLVER_CONFIG, DATA_DIR_NAME); diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/machinereassignment/optional/score/MachineReassignmentIncrementalScoreCalculator.java b/src/main/java/ai/timefold/solver/benchmarks/examples/machinereassignment/optional/score/MachineReassignmentIncrementalScoreCalculator.java deleted file mode 100644 index 36e0704c..00000000 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/machinereassignment/optional/score/MachineReassignmentIncrementalScoreCalculator.java +++ /dev/null @@ -1,601 +0,0 @@ -package ai.timefold.solver.benchmarks.examples.machinereassignment.optional.score; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import ai.timefold.solver.benchmarks.examples.machinereassignment.domain.MachineReassignment; -import ai.timefold.solver.benchmarks.examples.machinereassignment.domain.MrBalancePenalty; -import ai.timefold.solver.benchmarks.examples.machinereassignment.domain.MrGlobalPenaltyInfo; -import ai.timefold.solver.benchmarks.examples.machinereassignment.domain.MrLocation; -import ai.timefold.solver.benchmarks.examples.machinereassignment.domain.MrMachine; -import ai.timefold.solver.benchmarks.examples.machinereassignment.domain.MrMachineCapacity; -import ai.timefold.solver.benchmarks.examples.machinereassignment.domain.MrNeighborhood; -import ai.timefold.solver.benchmarks.examples.machinereassignment.domain.MrProcessAssignment; -import ai.timefold.solver.benchmarks.examples.machinereassignment.domain.MrResource; -import ai.timefold.solver.benchmarks.examples.machinereassignment.domain.MrService; -import ai.timefold.solver.benchmarks.examples.machinereassignment.score.MrConstraints; -import ai.timefold.solver.core.api.score.HardSoftScore; -import ai.timefold.solver.core.api.score.calculator.ConstraintMatchAwareIncrementalScoreCalculator; -import ai.timefold.solver.core.api.score.calculator.IncrementalScoreCalculator; -import ai.timefold.solver.core.api.score.constraint.ConstraintMatchTotal; -import ai.timefold.solver.core.api.score.constraint.ConstraintRef; -import ai.timefold.solver.core.api.score.constraint.Indictment; -import ai.timefold.solver.core.impl.score.constraint.DefaultConstraintMatchTotal; - -public class MachineReassignmentIncrementalScoreCalculator - implements - ConstraintMatchAwareIncrementalScoreCalculator, - IncrementalScoreCalculator { - - protected static final String CONSTRAINT_PACKAGE = "ai.timefold.solver.examples.machinereassignment.solver"; - - private MachineReassignment machineReassignment; - private MrGlobalPenaltyInfo globalPenaltyInfo; - - private Map serviceScorePartMap; - private Map movedProcessCountToServiceCount; - private int serviceMoveCost; - private Map machineScorePartMap; - - private long hardScore; - private long softScore; - - @Override - public void resetWorkingSolution( - MachineReassignment machineReassignment) { - this.machineReassignment = machineReassignment; - hardScore = 0L; - softScore = 0L; - globalPenaltyInfo = machineReassignment.getGlobalPenaltyInfo(); - List serviceList = - machineReassignment.getServiceList(); - serviceScorePartMap = new HashMap<>(serviceList.size()); - for (MrService service : serviceList) { - serviceScorePartMap.put(service, new MrServiceScorePart(service)); - } - movedProcessCountToServiceCount = new HashMap<>(serviceList.size()); - movedProcessCountToServiceCount.put(0, serviceList.size()); - serviceMoveCost = 0; - List machineList = - machineReassignment.getMachineList(); - machineScorePartMap = new HashMap<>(machineList.size()); - for (MrMachine machine : machineList) { - machineScorePartMap.put(machine, new MrMachineScorePart(machine)); - } - for (MrProcessAssignment processAssignment : machineReassignment - .getProcessAssignmentList()) { - MrMachine originalMachine = - processAssignment.getOriginalMachine(); - if (originalMachine != null) { - machineScorePartMap.get(originalMachine).initOriginalProcessAssignment(processAssignment); - } - } - for (MrProcessAssignment processAssignment : machineReassignment - .getProcessAssignmentList()) { - insert(processAssignment); - } - } - - @Override - public void beforeEntityAdded(Object entity) { - // Do nothing - } - - @Override - public void afterEntityAdded(Object entity) { - // TODO the maps should probably be adjusted - insert((MrProcessAssignment) entity); - } - - @Override - public void beforeVariableChanged(Object entity, String variableName) { - retract((MrProcessAssignment) entity); - } - - @Override - public void afterVariableChanged(Object entity, String variableName) { - insert((MrProcessAssignment) entity); - } - - @Override - public void beforeEntityRemoved(Object entity) { - retract((MrProcessAssignment) entity); - } - - @Override - public void afterEntityRemoved(Object entity) { - // Do nothing - // TODO the maps should probably be adjusted - } - - private void - insert(MrProcessAssignment processAssignment) { - MrMachine machine = processAssignment.getMachine(); - if (machine != null) { - MrServiceScorePart serviceScorePart = serviceScorePartMap.get(processAssignment.getService()); - serviceScorePart.addProcessAssignment(processAssignment); - MrMachineScorePart machineScorePart = machineScorePartMap.get(machine); - machineScorePart.addProcessAssignment(processAssignment); - } - } - - private void - retract(MrProcessAssignment processAssignment) { - MrMachine machine = processAssignment.getMachine(); - if (machine != null) { - MrServiceScorePart serviceScorePart = serviceScorePartMap.get(processAssignment.getService()); - serviceScorePart.removeProcessAssignment(processAssignment); - MrMachineScorePart machineScorePart = machineScorePartMap.get(machine); - machineScorePart.removeProcessAssignment(processAssignment); - } - } - - @Override - public HardSoftScore calculateScore() { - return HardSoftScore.of(hardScore, softScore); - } - - private class MrServiceScorePart { - - private final MrService service; - - private Map locationBag; - private Map neighborhoodBag; - private int movedProcessCount; - - private MrServiceScorePart(MrService service) { - this.service = service; - locationBag = new HashMap<>(machineReassignment.getLocationList().size()); - hardScore -= service.getLocationSpread(); - List neighborhoodList = - machineReassignment.getNeighborhoodList(); - neighborhoodBag = new HashMap<>(neighborhoodList.size()); - for (MrNeighborhood neighborhood : neighborhoodList) { - neighborhoodBag.put(neighborhood, 0); - } - movedProcessCount = 0; - } - - private void addProcessAssignment( - MrProcessAssignment processAssignment) { - // Spread constraints - MrLocation location = - processAssignment.getLocation(); - Integer locationProcessCount = locationBag.get(location); - if (locationProcessCount == null) { - if (service.getLocationSpread() > locationBag.size()) { - hardScore += (service.getLocationSpread() - locationBag.size()); - } - locationBag.put(location, 1); - if (service.getLocationSpread() > locationBag.size()) { - hardScore -= (service.getLocationSpread() - locationBag.size()); - } - } else { - locationBag.put(location, locationProcessCount + 1); - } - // Dependency constraints - MrNeighborhood neighborhood = - processAssignment.getNeighborhood(); - int neighborhoodProcessCount = neighborhoodBag.get(neighborhood) + 1; - neighborhoodBag.put(neighborhood, neighborhoodProcessCount); - for (MrService toDependencyService : service - .getToDependencyServiceList()) { - int toDependencyNeighborhoodProcessCount = serviceScorePartMap.get(toDependencyService).neighborhoodBag - .get(neighborhood); - if (toDependencyNeighborhoodProcessCount == 0) { - hardScore--; - } - } - if (neighborhoodProcessCount == 1) { - for (MrService fromDependencyService : service - .getFromDependencyServiceList()) { - int fromDependencyNeighborhoodProcessCount = serviceScorePartMap.get(fromDependencyService).neighborhoodBag - .get(neighborhood); - hardScore += fromDependencyNeighborhoodProcessCount; - } - } - // Service move cost - if (processAssignment.isMoved()) { - int oldServiceCount = movedProcessCountToServiceCount.get(movedProcessCount); - movedProcessCountToServiceCount.put(movedProcessCount, oldServiceCount - 1); - if (serviceMoveCost == movedProcessCount) { - serviceMoveCost++; - softScore -= globalPenaltyInfo.getServiceMoveCostWeight(); - } - movedProcessCount++; - Integer newServiceCount = movedProcessCountToServiceCount.get(movedProcessCount); - if (newServiceCount == null) { - newServiceCount = 0; - } - movedProcessCountToServiceCount.put(movedProcessCount, newServiceCount + 1); - } - } - - private void removeProcessAssignment( - MrProcessAssignment processAssignment) { - // Spread constraints - MrLocation location = processAssignment.getLocation(); - int locationProcessCount = locationBag.get(location); - if (locationProcessCount == 1) { - if (service.getLocationSpread() > locationBag.size()) { - hardScore += (service.getLocationSpread() - locationBag.size()); - } - locationBag.remove(location); - if (service.getLocationSpread() > locationBag.size()) { - hardScore -= (service.getLocationSpread() - locationBag.size()); - } - } else { - locationBag.put(location, locationProcessCount - 1); - } - // Dependency constraints - MrNeighborhood neighborhood = processAssignment.getNeighborhood(); - int neighborhoodProcessCount = neighborhoodBag.get(neighborhood) - 1; - neighborhoodBag.put(neighborhood, neighborhoodProcessCount); - for (MrService toDependencyService : service - .getToDependencyServiceList()) { - int toDependencyNeighborhoodProcessCount = serviceScorePartMap.get(toDependencyService).neighborhoodBag - .get(neighborhood); - if (toDependencyNeighborhoodProcessCount == 0) { - hardScore++; - } - } - if (neighborhoodProcessCount == 0) { - for (MrService fromDependencyService : service - .getFromDependencyServiceList()) { - int fromDependencyNeighborhoodProcessCount = serviceScorePartMap.get(fromDependencyService).neighborhoodBag - .get(neighborhood); - hardScore -= fromDependencyNeighborhoodProcessCount; - } - } - // Service move cost - if (processAssignment.isMoved()) { - int oldServiceCount = movedProcessCountToServiceCount.get(movedProcessCount); - // Hack: This will linger a few entries with key 0 in movedProcessCountToServiceCount - movedProcessCountToServiceCount.put(movedProcessCount, oldServiceCount - 1); - if (oldServiceCount == 1 && serviceMoveCost == movedProcessCount) { - serviceMoveCost--; - softScore += globalPenaltyInfo.getServiceMoveCostWeight(); - } - movedProcessCount--; - int newServiceCount = movedProcessCountToServiceCount.get(movedProcessCount); - movedProcessCountToServiceCount.put(movedProcessCount, newServiceCount + 1); - } - } - - } - - private class MrMachineScorePart { - - private final MrMachine machine; - private final List machineCapacityScorePartList; - private Map serviceBag; - - public MrMachineScorePart(MrMachine machine) { - this.machine = machine; - List machineCapacityList = - machine.getMachineCapacityList(); - machineCapacityScorePartList = new ArrayList<>(machineCapacityList.size()); - for (MrMachineCapacity machineCapacity : machineCapacityList) { - machineCapacityScorePartList.add(new MrMachineCapacityScorePart(machineCapacity)); - } - serviceBag = new HashMap<>(10); - doBalancePenaltyCosts(); - } - - public void initOriginalProcessAssignment( - MrProcessAssignment processAssignment) { - for (MrMachineCapacityScorePart machineCapacityScorePart : machineCapacityScorePartList) { - machineCapacityScorePart.initOriginalProcessAssignment(processAssignment); - } - } - - private void addProcessAssignment( - MrProcessAssignment processAssignment) { - // Balance cost - undoBalancePenaltyCosts(); - for (MrMachineCapacityScorePart machineCapacityScorePart : machineCapacityScorePartList) { - machineCapacityScorePart.addProcessAssignment(processAssignment); - } - // Service conflict - MrService service = - processAssignment.getService(); - int serviceProcessCount = serviceBag.computeIfAbsent(service, k -> 0); - if (serviceProcessCount > 1) { - hardScore += (serviceProcessCount - 1); - } - serviceProcessCount++; - if (serviceProcessCount > 1) { - hardScore -= (serviceProcessCount - 1); - } - if (serviceProcessCount == 0) { - serviceBag.remove(service); - } else { - serviceBag.put(service, serviceProcessCount); - } - // Balance cost - doBalancePenaltyCosts(); - // Move costs - if (processAssignment.isMoved()) { - // Process move cost - softScore -= (long) processAssignment.getProcessMoveCost() * globalPenaltyInfo.getProcessMoveCostWeight(); - // Machine move cost - softScore -= (long) processAssignment.getMachineMoveCost() * globalPenaltyInfo.getMachineMoveCostWeight(); - } - } - - private void removeProcessAssignment( - MrProcessAssignment processAssignment) { - undoBalancePenaltyCosts(); - for (MrMachineCapacityScorePart machineCapacityScorePart : machineCapacityScorePartList) { - machineCapacityScorePart.removeProcessAssignment(processAssignment); - } - // Service conflict - MrService service = - processAssignment.getService(); - int serviceProcessCount = serviceBag.computeIfAbsent(service, k -> 0); - if (serviceProcessCount > 1) { - hardScore += (serviceProcessCount - 1); - } - serviceProcessCount--; - if (serviceProcessCount > 1) { - hardScore -= (serviceProcessCount - 1); - } - if (serviceProcessCount == 0) { - serviceBag.remove(service); - } else { - serviceBag.put(service, serviceProcessCount); - } - doBalancePenaltyCosts(); - // Move costs - if (processAssignment.isMoved()) { - // Process move cost - softScore += (long) processAssignment.getProcessMoveCost() * globalPenaltyInfo.getProcessMoveCostWeight(); - // Machine move cost - softScore += (long) processAssignment.getMachineMoveCost() * globalPenaltyInfo.getMachineMoveCostWeight(); - } - } - - private void doBalancePenaltyCosts() { - for (MrBalancePenalty balancePenalty : machineReassignment - .getBalancePenaltyList()) { - long originAvailable = machineCapacityScorePartList.get(balancePenalty.getOriginResource().getIndex()) - .getBalanceAvailable(); - long targetAvailable = machineCapacityScorePartList.get(balancePenalty.getTargetResource().getIndex()) - .getBalanceAvailable(); - if (originAvailable > 0L) { - long minimumTargetAvailable = originAvailable * balancePenalty.getMultiplicand(); - // targetAvailable might be negative, but that's ok (and even avoids score traps) - if (targetAvailable < minimumTargetAvailable) { - softScore -= (minimumTargetAvailable - targetAvailable) * balancePenalty.getWeight(); - } - } - } - } - - private void undoBalancePenaltyCosts() { - for (MrBalancePenalty balancePenalty : machineReassignment - .getBalancePenaltyList()) { - long originAvailable = machineCapacityScorePartList.get(balancePenalty.getOriginResource().getIndex()) - .getBalanceAvailable(); - long targetAvailable = machineCapacityScorePartList.get(balancePenalty.getTargetResource().getIndex()) - .getBalanceAvailable(); - if (originAvailable > 0L) { - long minimumTargetAvailable = originAvailable * balancePenalty.getMultiplicand(); - // targetAvailable might be negative, but that's ok (and even avoids score traps) - if (targetAvailable < minimumTargetAvailable) { - softScore += (minimumTargetAvailable - targetAvailable) * balancePenalty.getWeight(); - } - } - } - } - - } - - private class MrMachineCapacityScorePart { - - private final MrMachineCapacity machineCapacity; - private long maximumAvailable; - private long safetyAvailable; - private long balanceAvailable; // == maximumAvailable without transient - - private MrMachineCapacityScorePart(MrMachineCapacity machineCapacity) { - this.machineCapacity = machineCapacity; - maximumAvailable = machineCapacity.getMaximumCapacity(); - safetyAvailable = machineCapacity.getSafetyCapacity(); - balanceAvailable = machineCapacity.getMaximumCapacity(); - } - - private void initOriginalProcessAssignment( - MrProcessAssignment processAssignment) { - if (machineCapacity.isTransientlyConsumed()) { - // Capacity constraints + Transient usage constraints - long processUsage = processAssignment.getProcess().getProcessRequirement(machineCapacity.getResource()) - .getUsage(); - hardScore -= Math.min(maximumAvailable, 0); - maximumAvailable -= processUsage; - hardScore += Math.min(maximumAvailable, 0); - } - } - - private void addProcessAssignment( - MrProcessAssignment processAssignment) { - MrResource resource = - machineCapacity.getResource(); - long processUsage = processAssignment.getUsage(resource); - if (!machineCapacity.isTransientlyConsumed() || processAssignment.isMoved()) { - // Capacity constraints + Transient usage constraints - hardScore -= Math.min(maximumAvailable, 0); - maximumAvailable -= processUsage; - hardScore += Math.min(maximumAvailable, 0); - } - // Load cost - softScore -= Math.min(safetyAvailable, 0) * resource.getLoadCostWeight(); - safetyAvailable -= processUsage; - softScore += Math.min(safetyAvailable, 0) * resource.getLoadCostWeight(); - balanceAvailable -= processUsage; - } - - private void removeProcessAssignment( - MrProcessAssignment processAssignment) { - MrResource resource = machineCapacity.getResource(); - long processUsage = processAssignment.getUsage(resource); - if (!machineCapacity.isTransientlyConsumed() || processAssignment.isMoved()) { - // Capacity constraints + Transient usage constraints - hardScore -= Math.min(maximumAvailable, 0); - maximumAvailable += processUsage; - hardScore += Math.min(maximumAvailable, 0); - } - // Load cost - softScore -= Math.min(safetyAvailable, 0) * resource.getLoadCostWeight(); - safetyAvailable += processUsage; - softScore += Math.min(safetyAvailable, 0) * resource.getLoadCostWeight(); - balanceAvailable += processUsage; - } - - public long getBalanceAvailable() { - return balanceAvailable; - } - - } - - @Override - public void resetWorkingSolution(MachineReassignment workingSolution, boolean constraintMatchEnabled) { - resetWorkingSolution(workingSolution); - // ignore constraintMatchEnabled, it is always presumed enabled - } - - @Override - public Collection> getConstraintMatchTotals() { - DefaultConstraintMatchTotal maximumCapacityMatchTotal = - getConstraintMatchTotal( - MrConstraints.MAXIMUM_CAPACITY, - HardSoftScore.ONE_HARD); - DefaultConstraintMatchTotal serviceConflictMatchTotal = - getConstraintMatchTotal( - MrConstraints.SERVICE_CONFLICT, - HardSoftScore.ONE_HARD); - DefaultConstraintMatchTotal serviceLocationSpreadMatchTotal = - getConstraintMatchTotal( - MrConstraints.SERVICE_LOCATION_SPREAD, - HardSoftScore.ONE_HARD); - DefaultConstraintMatchTotal serviceDependencyMatchTotal = - getConstraintMatchTotal( - MrConstraints.SERVICE_DEPENDENCY, - HardSoftScore.ONE_HARD); - DefaultConstraintMatchTotal loadCostMatchTotal = - getConstraintMatchTotal( - MrConstraints.LOAD_COST, - HardSoftScore.ONE_SOFT); - DefaultConstraintMatchTotal balanceCostMatchTotal = - getConstraintMatchTotal( - MrConstraints.BALANCE_COST, - HardSoftScore.ONE_SOFT); - DefaultConstraintMatchTotal processMoveCostMatchTotal = - getConstraintMatchTotal( - MrConstraints.PROCESS_MOVE_COST, - HardSoftScore.ofSoft(globalPenaltyInfo.getProcessMoveCostWeight())); - DefaultConstraintMatchTotal serviceMoveCostMatchTotal = - getConstraintMatchTotal( - MrConstraints.SERVICE_MOVE_COST, - HardSoftScore.ofSoft(globalPenaltyInfo.getServiceMoveCostWeight())); - DefaultConstraintMatchTotal machineMoveCostMatchTotal = - getConstraintMatchTotal(MrConstraints.MACHINE_MOVE_COST, - HardSoftScore.ofSoft(globalPenaltyInfo.getMachineMoveCostWeight())); - - for (MrServiceScorePart serviceScorePart : serviceScorePartMap.values()) { - MrService service = serviceScorePart.service; - if (service.getLocationSpread() > serviceScorePart.locationBag.size()) { - serviceLocationSpreadMatchTotal.addConstraintMatch(List.of(service), - HardSoftScore.of( - -(service.getLocationSpread() - serviceScorePart.locationBag.size()), 0)); - } - } - for (MrMachineScorePart machineScorePart : machineScorePartMap.values()) { - for (MrMachineCapacityScorePart machineCapacityScorePart : machineScorePart.machineCapacityScorePartList) { - if (machineCapacityScorePart.maximumAvailable < 0L) { - maximumCapacityMatchTotal.addConstraintMatch(List.of(machineCapacityScorePart.machineCapacity), - HardSoftScore.of(machineCapacityScorePart.maximumAvailable, 0)); - } - if (machineCapacityScorePart.safetyAvailable < 0L) { - loadCostMatchTotal.addConstraintMatch(List.of(machineCapacityScorePart.machineCapacity), - HardSoftScore.of(0, machineCapacityScorePart.safetyAvailable - * machineCapacityScorePart.machineCapacity.getResource().getLoadCostWeight())); - } - } - for (MrBalancePenalty balancePenalty : machineReassignment.getBalancePenaltyList()) { - long originAvailable = machineScorePart.machineCapacityScorePartList - .get(balancePenalty.getOriginResource().getIndex()).getBalanceAvailable(); - long targetAvailable = machineScorePart.machineCapacityScorePartList - .get(balancePenalty.getTargetResource().getIndex()).getBalanceAvailable(); - if (originAvailable > 0L) { - long minimumTargetAvailable = originAvailable * balancePenalty.getMultiplicand(); - // targetAvailable might be negative, but that's ok (and even avoids score traps) - if (targetAvailable < minimumTargetAvailable) { - balanceCostMatchTotal.addConstraintMatch(List.of(machineScorePart.machine, balancePenalty), - HardSoftScore.of(0, - -(minimumTargetAvailable - targetAvailable) * balancePenalty.getWeight())); - } - } - } - for (Map.Entry entry : machineScorePart.serviceBag - .entrySet()) { - Integer serviceProcessCount = entry.getValue(); - if (serviceProcessCount > 1) { - serviceConflictMatchTotal.addConstraintMatch(List.of(machineScorePart.machine, entry.getKey()), - HardSoftScore.of(-(serviceProcessCount - 1), 0)); - } - } - } - for (MrProcessAssignment processAssignment : machineReassignment.getProcessAssignmentList()) { - for (MrService toDependencyService : processAssignment.getService().getToDependencyServiceList()) { - MrServiceScorePart serviceScorePart = serviceScorePartMap.get(toDependencyService); - int toDependencyNeighborhoodProcessCount = - serviceScorePart.neighborhoodBag.getOrDefault(processAssignment.getNeighborhood(), 0); - if (toDependencyNeighborhoodProcessCount == 0) { - serviceDependencyMatchTotal.addConstraintMatch(List.of(processAssignment, toDependencyService), - HardSoftScore.of(-1, 0)); - } - } - if (processAssignment.isMoved()) { - processMoveCostMatchTotal.addConstraintMatch(List.of(processAssignment), - HardSoftScore.of(0, - -((long) processAssignment.getProcessMoveCost() - * globalPenaltyInfo.getProcessMoveCostWeight()))); - machineMoveCostMatchTotal.addConstraintMatch(List.of(processAssignment), - HardSoftScore.of(0, - -((long) processAssignment.getMachineMoveCost() - * globalPenaltyInfo.getMachineMoveCostWeight()))); - } - } - for (int i = 0; i < serviceMoveCost; i++) { - serviceMoveCostMatchTotal.addConstraintMatch(List.of(i), - HardSoftScore.of(0, -globalPenaltyInfo.getServiceMoveCostWeight())); - } - - List> constraintMatchTotalList = new ArrayList<>(4); - constraintMatchTotalList.add(maximumCapacityMatchTotal); - constraintMatchTotalList.add(serviceConflictMatchTotal); - constraintMatchTotalList.add(serviceLocationSpreadMatchTotal); - constraintMatchTotalList.add(serviceDependencyMatchTotal); - constraintMatchTotalList.add(loadCostMatchTotal); - constraintMatchTotalList.add(balanceCostMatchTotal); - constraintMatchTotalList.add(processMoveCostMatchTotal); - constraintMatchTotalList.add(serviceMoveCostMatchTotal); - constraintMatchTotalList.add(machineMoveCostMatchTotal); - return constraintMatchTotalList; - } - - private static DefaultConstraintMatchTotal getConstraintMatchTotal(String constraintName, - HardSoftScore constraintWeight) { - return new DefaultConstraintMatchTotal<>(ConstraintRef.of(constraintName), constraintWeight); - } - - @Override - public Map> getIndictmentMap() { - return null; // Calculate it non-incrementally from getConstraintMatchTotals() - } - -} diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/machinereassignment/optional/score/MrMachineTransientUsage.java b/src/main/java/ai/timefold/solver/benchmarks/examples/machinereassignment/optional/score/MrMachineTransientUsage.java deleted file mode 100644 index 4b88fb36..00000000 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/machinereassignment/optional/score/MrMachineTransientUsage.java +++ /dev/null @@ -1,73 +0,0 @@ -package ai.timefold.solver.benchmarks.examples.machinereassignment.optional.score; - -import static java.util.Comparator.comparing; -import static java.util.Comparator.comparingLong; - -import java.util.Comparator; -import java.util.Objects; - -import ai.timefold.solver.benchmarks.examples.machinereassignment.domain.MrMachine; -import ai.timefold.solver.benchmarks.examples.machinereassignment.domain.MrMachineCapacity; -import ai.timefold.solver.benchmarks.examples.machinereassignment.domain.MrResource; - -public class MrMachineTransientUsage implements Comparable { - - private static final Comparator COMPARATOR = comparing( - (MrMachineTransientUsage transientUsage) -> transientUsage.getClass().getName()) - .thenComparing(transientUsage -> transientUsage.machineCapacity, - comparingLong(MrMachineCapacity::getId)) - .thenComparingLong(transientUsage -> transientUsage.usage); - - private MrMachineCapacity machineCapacity; - private long usage; - - public MrMachineTransientUsage( - MrMachineCapacity machineCapacity, long usage) { - this.machineCapacity = machineCapacity; - this.usage = usage; - } - - public MrMachineCapacity getMachineCapacity() { - return machineCapacity; - } - - public long getUsage() { - return usage; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - final MrMachineTransientUsage other = (MrMachineTransientUsage) o; - return Objects.equals(machineCapacity, other.machineCapacity) && - usage == other.usage; - } - - @Override - public int hashCode() { - return Objects.hash(machineCapacity, usage); - } - - public MrMachine getMachine() { - return machineCapacity.getMachine(); - } - - public MrResource getResource() { - return machineCapacity.getResource(); - } - - @Override - public String toString() { - return getMachine() + "-" + getResource() + "=" + usage; - } - - @Override - public int compareTo(MrMachineTransientUsage o) { - return COMPARATOR.compare(this, o); - } -} diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/machinereassignment/optional/score/MrMachineUsage.java b/src/main/java/ai/timefold/solver/benchmarks/examples/machinereassignment/optional/score/MrMachineUsage.java deleted file mode 100644 index b1c318fe..00000000 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/machinereassignment/optional/score/MrMachineUsage.java +++ /dev/null @@ -1,89 +0,0 @@ -package ai.timefold.solver.benchmarks.examples.machinereassignment.optional.score; - -import static java.util.Comparator.comparing; -import static java.util.Comparator.comparingLong; - -import java.util.Comparator; -import java.util.Objects; - -import ai.timefold.solver.benchmarks.examples.machinereassignment.domain.MrMachine; -import ai.timefold.solver.benchmarks.examples.machinereassignment.domain.MrMachineCapacity; -import ai.timefold.solver.benchmarks.examples.machinereassignment.domain.MrResource; - -public class MrMachineUsage implements Comparable { - - private static final Comparator COMPARATOR = comparing( - (MrMachineUsage machineUsage) -> machineUsage.getClass().getName()) - .thenComparing(machineUsage -> machineUsage.machineCapacity, - comparingLong(MrMachineCapacity::getId)) - .thenComparingLong(machineUsage -> machineUsage.usage); - - private MrMachineCapacity machineCapacity; - private long usage; - - public MrMachineUsage(MrMachineCapacity machineCapacity, - long usage) { - this.machineCapacity = machineCapacity; - this.usage = usage; - } - - public MrMachineCapacity getMachineCapacity() { - return machineCapacity; - } - - public long getUsage() { - return usage; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - final MrMachineUsage other = (MrMachineUsage) o; - return Objects.equals(machineCapacity, other.machineCapacity) && - usage == other.usage; - } - - @Override - public int hashCode() { - return Objects.hash(machineCapacity, usage); - } - - public MrMachine getMachine() { - return machineCapacity.getMachine(); - } - - public MrResource getResource() { - return machineCapacity.getResource(); - } - - public boolean isTransientlyConsumed() { - return machineCapacity.getResource().isTransientlyConsumed(); - } - - public long getLoadCostWeight() { - return machineCapacity.getResource().getLoadCostWeight(); - } - - public long getMaximumAvailable() { - return machineCapacity.getMaximumCapacity() - usage; - } - - public long getSafetyAvailable() { - return machineCapacity.getSafetyCapacity() - usage; - } - - @Override - public String toString() { - return getMachine() + "-" + getResource() + "=" + usage; - } - - @Override - public int compareTo(MrMachineUsage o) { - return COMPARATOR.compare(this, o); - } -} diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/machinereassignment/optional/score/MrServiceMovedProcessesCount.java b/src/main/java/ai/timefold/solver/benchmarks/examples/machinereassignment/optional/score/MrServiceMovedProcessesCount.java deleted file mode 100644 index 0755f1c1..00000000 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/machinereassignment/optional/score/MrServiceMovedProcessesCount.java +++ /dev/null @@ -1,63 +0,0 @@ -package ai.timefold.solver.benchmarks.examples.machinereassignment.optional.score; - -import static java.util.Comparator.comparing; -import static java.util.Comparator.comparingLong; - -import java.util.Comparator; -import java.util.Objects; - -import ai.timefold.solver.benchmarks.examples.machinereassignment.domain.MrService; - -public class MrServiceMovedProcessesCount implements Comparable { - - private static final Comparator COMPARATOR = comparing( - (MrServiceMovedProcessesCount count) -> count.service, comparingLong(MrService::getId)) - .thenComparingInt(count -> count.movedProcessesCount); - private MrService service; - private int movedProcessesCount; - - public MrServiceMovedProcessesCount(MrService service, int movedProcessesCount) { - this.service = service; - this.movedProcessesCount = movedProcessesCount; - } - - public MrService getService() { - return service; - } - - public int getMovedProcessesCount() { - return movedProcessesCount; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - final MrServiceMovedProcessesCount other = (MrServiceMovedProcessesCount) o; - return Objects.equals(service, other.service) && - movedProcessesCount == other.movedProcessesCount; - } - - @Override - public int hashCode() { - return Objects.hash(service, movedProcessesCount); - } - - public Long getServiceId() { - return service.getId(); - } - - @Override - public String toString() { - return service + "=" + movedProcessesCount; - } - - @Override - public int compareTo(MrServiceMovedProcessesCount o) { - return COMPARATOR.compare(this, o); - } -} diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/nurserostering/score/NurseRosteringConstraintProvider.java b/src/main/java/ai/timefold/solver/benchmarks/examples/nurserostering/score/NurseRosteringConstraintProvider.java index bf5cb7bf..d38e489b 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/nurserostering/score/NurseRosteringConstraintProvider.java +++ b/src/main/java/ai/timefold/solver/benchmarks/examples/nurserostering/score/NurseRosteringConstraintProvider.java @@ -6,7 +6,6 @@ import static ai.timefold.solver.benchmarks.examples.nurserostering.optional.score.EmployeeConsecutiveAssignmentStart.isWeekendAndNotFirstDayOfWeekend; import java.time.DayOfWeek; -import java.util.Arrays; import ai.timefold.solver.benchmarks.examples.nurserostering.domain.Employee; import ai.timefold.solver.benchmarks.examples.nurserostering.domain.NurseRosterParametrization; @@ -104,7 +103,6 @@ Constraint minimumAndMaximumNumberOfAssignments(ConstraintFactory constraintFact (employee, contract, shiftCount) -> contract.getViolationAmount(shiftCount)) .filter((employee, contract, violationAmount) -> violationAmount != 0) .penalize(HardSoftBigDecimalScore.ONE_SOFT, (employee, contract, violationAmount) -> violationAmount) - .indictWith((employee, contract, violationAmount) -> Arrays.asList(employee, contract)) .asConstraint("Minimum and maximum number of assignments"); } @@ -132,7 +130,6 @@ Constraint consecutiveWorkingDays(ConstraintFactory constraintFactory) { (employee, contract, shiftList) -> contract.getViolationAmount(shiftList.getLength())) .filter((contract, employee, violationAmount) -> violationAmount != 0) .penalize(HardSoftBigDecimalScore.ONE_SOFT, (contract, employee, violationAmount) -> violationAmount) - .indictWith((contract, employee, violationAmount) -> Arrays.asList(employee, contract)) .asConstraint("consecutiveWorkingDays"); } @@ -175,7 +172,6 @@ Constraint consecutiveFreeDays(ConstraintFactory constraintFactory) { }) .filter((employee, contract, violationAmount) -> violationAmount != 0) .penalize(HardSoftBigDecimalScore.ONE_SOFT, (employee, contract, violationAmount) -> violationAmount) - .indictWith((employee, contract, violationAmount) -> Arrays.asList(employee, contract)) .asConstraint("consecutiveFreeDays"); } @@ -195,7 +191,6 @@ Constraint maximumConsecutiveFreeDaysNoAssignments(ConstraintFactory constraintF .penalize(HardSoftBigDecimalScore.ONE_SOFT, (contract, employee, nrp) -> contract .getViolationAmount(nrp.getLastShiftDateDayIndex() - nrp.getFirstShiftDateDayIndex() + 1)) - .indictWith((contract, employee, nrp) -> Arrays.asList(employee, contract)) .asConstraint("maximumConsecutiveFreeDays - no shifts"); } @@ -218,7 +213,6 @@ Constraint consecutiveWorkingWeekends(ConstraintFactory constraintFactory) { (employee, contract, shiftList) -> contract.getViolationAmount(shiftList.getLength())) .filter((employee, contract, violationAmount) -> violationAmount != 0) .penalize(HardSoftBigDecimalScore.ONE_SOFT, (employee, contract, violationAmount) -> violationAmount) - .indictWith((employee, contract, violationAmount) -> Arrays.asList(employee, contract)) .asConstraint("consecutiveWorkingWeekends"); } @@ -239,7 +233,6 @@ Constraint startOnNotFirstDayOfWeekend(ConstraintFactory constraintFactory) { .penalize(HardSoftBigDecimalScore.ONE_SOFT, (employee, contract, shiftList) -> getDistanceToFirstDayOfWeekend(employee, shiftList.getFirstItem()) * contract.getWeight()) - .indictWith((employee, contract, shiftList) -> Arrays.asList(employee, contract)) .asConstraint("startOnNotFirstDayOfWeekend"); } @@ -260,7 +253,6 @@ Constraint endOnNotLastDayOfWeekend(ConstraintFactory constraintFactory) { .penalize(HardSoftBigDecimalScore.ONE_SOFT, (employee, contract, shiftList) -> getDistanceToLastDayOfWeekend(employee, shiftList.getLastItem()) * contract.getWeight()) - .indictWith((employee, contract, shiftList) -> Arrays.asList(employee, contract)) .asConstraint("endOnNotLastDayOfWeekend"); } @@ -286,7 +278,6 @@ Constraint identicalShiftTypesDuringWeekend(ConstraintFactory constraintFactory) .filter((contract, employee, type, count) -> count < employee.getWeekendLength()) .penalize(HardSoftBigDecimalScore.ONE_SOFT, (contract, employee, type, count) -> (employee.getWeekendLength() - count) * contract.getWeight()) - .indictWith((contract, employee, type, count) -> Arrays.asList(employee, contract)) .asConstraint("identicalShiftTypesDuringWeekend"); } diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/taskassigning/domain/Employee.java b/src/main/java/ai/timefold/solver/benchmarks/examples/taskassigning/domain/Employee.java index bd42b164..52ebb4e4 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/taskassigning/domain/Employee.java +++ b/src/main/java/ai/timefold/solver/benchmarks/examples/taskassigning/domain/Employee.java @@ -5,7 +5,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; -import java.util.Set; +import java.util.SequencedSet; import ai.timefold.solver.benchmarks.examples.common.domain.AbstractPersistable; import ai.timefold.solver.benchmarks.examples.common.persistence.jackson.JacksonUniqueIdGenerator; @@ -25,7 +25,7 @@ public class Employee extends AbstractPersistable { private String fullName; - private Set skillSet; + private SequencedSet skillSet; private Map affinityMap; @PlanningListVariable(allowsUnassignedValues = true) @@ -50,11 +50,11 @@ public void setFullName(String fullName) { this.fullName = fullName; } - public Set getSkillSet() { + public SequencedSet getSkillSet() { return skillSet; } - public void setSkillSet(Set skillSet) { + public void setSkillSet(SequencedSet skillSet) { this.skillSet = skillSet; } diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/taskassigning/persistence/TaskAssigningGenerator.java b/src/main/java/ai/timefold/solver/benchmarks/examples/taskassigning/persistence/TaskAssigningGenerator.java index 08db9cce..9734afed 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/taskassigning/persistence/TaskAssigningGenerator.java +++ b/src/main/java/ai/timefold/solver/benchmarks/examples/taskassigning/persistence/TaskAssigningGenerator.java @@ -9,6 +9,7 @@ import java.util.List; import java.util.Map; import java.util.Random; +import java.util.SequencedSet; import java.util.Set; import ai.timefold.solver.benchmarks.examples.common.app.CommonApp; @@ -194,7 +195,7 @@ private void createEmployeeList(TaskAssigningSolution solution, int employeeList if (skillSetSize > skillList.size()) { skillSetSize = skillList.size(); } - Set skillSet = new LinkedHashSet<>(skillSetSize); + SequencedSet skillSet = new LinkedHashSet<>(skillSetSize); for (int j = 0; j < skillSetSize; j++) { skillSet.add(skillList.get(skillListIndex)); skillListIndex = (skillListIndex + 1) % skillList.size(); @@ -219,20 +220,12 @@ private void createTaskTypeList(TaskAssigningSolution solution, int taskTypeList taskTypeNameGenerator.predictMaximumSizeAndReset(taskTypeListSize); for (int i = 0; i < taskTypeListSize; i++) { String title = taskTypeNameGenerator.generateNextValue(); - String code; - switch (title.replaceAll("[^ ]", "").length() + 1) { - case 3: - code = title.replaceAll("(\\w)\\w* (\\w)\\w* (\\w)\\w*", "$1$2$3"); - break; - case 2: - code = title.replaceAll("(\\w)\\w* (\\w)\\w*", "$1$2"); - break; - case 1: - code = title.replaceAll("(\\w)\\w*", "$1"); - break; - default: - throw new IllegalStateException("Cannot convert title (" + title + ") into a code."); - } + String code = switch (title.replaceAll("[^ ]", "").length() + 1) { + case 3 -> title.replaceAll("(\\w)\\w* (\\w)\\w* (\\w)\\w*", "$1$2$3"); + case 2 -> title.replaceAll("(\\w)\\w* (\\w)\\w*", "$1$2"); + case 1 -> title.replaceAll("(\\w)\\w*", "$1"); + default -> throw new IllegalStateException("Cannot convert title (" + title + ") into a code."); + }; if (codeSet.contains(code)) { int codeSuffixNumber = 1; while (codeSet.contains(code + codeSuffixNumber)) { diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/tsp/optional/score/TspEasyScoreCalculator.java b/src/main/java/ai/timefold/solver/benchmarks/examples/tsp/optional/score/TspEasyScoreCalculator.java deleted file mode 100644 index 9557a6a6..00000000 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/tsp/optional/score/TspEasyScoreCalculator.java +++ /dev/null @@ -1,24 +0,0 @@ -package ai.timefold.solver.benchmarks.examples.tsp.optional.score; - -import ai.timefold.solver.benchmarks.examples.tsp.domain.TspSolution; -import ai.timefold.solver.core.api.score.SimpleScore; -import ai.timefold.solver.core.api.score.calculator.EasyScoreCalculator; - -public class TspEasyScoreCalculator implements EasyScoreCalculator { - - @Override - public SimpleScore calculateScore(TspSolution tspSolution) { - var visitList = tspSolution.getTour().getVisitList(); - long score = 0; - for (var visit : visitList) { - if (visit.getTour() != null) { - score -= visit.getDistanceFromPreviousVisit(); - if (visit.getNext() == null) { - score -= visit.getDistanceToDepot(); - } - } - } - return SimpleScore.of(score); - } - -} diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/tsp/optional/score/TspIncrementalScoreCalculator.java b/src/main/java/ai/timefold/solver/benchmarks/examples/tsp/optional/score/TspIncrementalScoreCalculator.java deleted file mode 100644 index 72fb8390..00000000 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/tsp/optional/score/TspIncrementalScoreCalculator.java +++ /dev/null @@ -1,86 +0,0 @@ -package ai.timefold.solver.benchmarks.examples.tsp.optional.score; - -import ai.timefold.solver.benchmarks.examples.tsp.domain.Tour; -import ai.timefold.solver.benchmarks.examples.tsp.domain.TspSolution; -import ai.timefold.solver.core.api.score.SimpleScore; -import ai.timefold.solver.core.api.score.calculator.IncrementalScoreCalculator; - -import org.jspecify.annotations.NonNull; - -public class TspIncrementalScoreCalculator implements IncrementalScoreCalculator { - - private long score; - - @Override - public void resetWorkingSolution(TspSolution tspSolution) { - score = 0L; - for (var visit : tspSolution.getVisitList()) { - score -= visit.getDistanceFromPreviousVisit(); - } - score -= tspSolution.getVisitList().getLast().getDistanceToDepot(); - } - - @Override - public void beforeEntityAdded(@NonNull Object o) { - // Do nothing - } - - @Override - public void afterEntityAdded(@NonNull Object o) { - // Do nothing - } - - @Override - public void beforeVariableChanged(@NonNull Object o, @NonNull String s) { - // Do nothing - } - - @Override - public void afterVariableChanged(@NonNull Object o, @NonNull String s) { - // Do nothing - } - - @Override - public void beforeListVariableChanged(@NonNull Object entity, @NonNull String variableName, int fromIndex, int toIndex) { - var tour = (Tour) entity; - for (int index = fromIndex; index < toIndex; index++) { - var visit = tour.getVisitList().get(index); - score += visit.getDistanceFromPreviousVisit(); - } - if (toIndex < tour.getVisitList().size()) { - score += tour.getVisitList().get(toIndex).getDistanceFromPreviousVisit(); - } else if (toIndex > 0 && tour.getVisitList().get(toIndex - 1).getNext() != null) { - score += tour.getVisitList().get(toIndex - 1).getDistanceToDepot(); - } - } - - @Override - public void afterListVariableChanged(@NonNull Object entity, @NonNull String variableName, int fromIndex, int toIndex) { - var tour = (Tour) entity; - for (int index = fromIndex; index < toIndex; index++) { - var visit = tour.getVisitList().get(index); - score -= visit.getDistanceFromPreviousVisit(); - } - if (toIndex < tour.getVisitList().size()) { - score -= tour.getVisitList().get(toIndex).getDistanceFromPreviousVisit(); - } else if (toIndex > 0 && tour.getVisitList().get(toIndex - 1).getNext() != null) { - score -= tour.getVisitList().get(toIndex - 1).getDistanceToDepot(); - } - } - - @Override - public void beforeEntityRemoved(@NonNull Object o) { - // Do nothing - } - - @Override - public void afterEntityRemoved(@NonNull Object o) { - // Do nothing - } - - @Override - public SimpleScore calculateScore() { - return SimpleScore.of(score); - } - -} diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/tsp/package-info.java b/src/main/java/ai/timefold/solver/benchmarks/examples/tsp/package-info.java new file mode 100644 index 00000000..b7f28837 --- /dev/null +++ b/src/main/java/ai/timefold/solver/benchmarks/examples/tsp/package-info.java @@ -0,0 +1,6 @@ +/** + * Only exists for the TSPLIB95 competitive benchmark. + * It is not meaningfully different from VRP, therefore it will not be benchmarked using the score director benchmark. + * "flowshop" took its place there. + */ +package ai.timefold.solver.benchmarks.examples.tsp; \ No newline at end of file diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/vehiclerouting/optional/score/VehicleRoutingEasyScoreCalculator.java b/src/main/java/ai/timefold/solver/benchmarks/examples/vehiclerouting/optional/score/VehicleRoutingEasyScoreCalculator.java deleted file mode 100644 index 312f6bc2..00000000 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/vehiclerouting/optional/score/VehicleRoutingEasyScoreCalculator.java +++ /dev/null @@ -1,65 +0,0 @@ -package ai.timefold.solver.benchmarks.examples.vehiclerouting.optional.score; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import ai.timefold.solver.benchmarks.examples.vehiclerouting.domain.Customer; -import ai.timefold.solver.benchmarks.examples.vehiclerouting.domain.Vehicle; -import ai.timefold.solver.benchmarks.examples.vehiclerouting.domain.VehicleRoutingSolution; -import ai.timefold.solver.benchmarks.examples.vehiclerouting.domain.timewindowed.TimeWindowedCustomer; -import ai.timefold.solver.benchmarks.examples.vehiclerouting.domain.timewindowed.TimeWindowedVehicleRoutingSolution; -import ai.timefold.solver.core.api.score.HardSoftScore; -import ai.timefold.solver.core.api.score.calculator.EasyScoreCalculator; - -public class VehicleRoutingEasyScoreCalculator - implements - EasyScoreCalculator { - - @Override - public HardSoftScore calculateScore(VehicleRoutingSolution solution) { - boolean timeWindowed = solution instanceof TimeWindowedVehicleRoutingSolution; - List customerList = solution.getCustomerList(); - List vehicleList = solution.getVehicleList(); - Map vehicleDemandMap = - new HashMap<>(vehicleList.size()); - for (Vehicle vehicle : vehicleList) { - vehicleDemandMap.put(vehicle, 0); - } - long hardScore = 0L; - long softScore = 0L; - for (Customer customer : customerList) { - Vehicle vehicle = customer.getVehicle(); - if (vehicle != null) { - vehicleDemandMap.put(vehicle, vehicleDemandMap.get(vehicle) + customer.getDemand()); - // Score constraint distanceToPreviousStandstill - softScore -= customer.getDistanceFromPreviousStandstill(); - if (customer.getNextCustomer() == null) { - // Score constraint distanceFromLastCustomerToDepot - softScore -= customer.getLocation().getDistanceTo(vehicle.getLocation()); - } - if (timeWindowed) { - TimeWindowedCustomer timeWindowedCustomer = - (TimeWindowedCustomer) customer; - long maxEndTime = timeWindowedCustomer.getMaxEndTime(); - Long arrivalTime = timeWindowedCustomer.getArrivalTime(); - if (maxEndTime < arrivalTime) { - // Score constraint arrivalAfterMaxEndTime - hardScore -= (arrivalTime - maxEndTime); - } - } - } - } - for (Map.Entry entry : vehicleDemandMap.entrySet()) { - int capacity = entry.getKey().getCapacity(); - int demand = entry.getValue(); - if (demand > capacity) { - // Score constraint vehicleCapacity - hardScore -= (demand - capacity); - } - } - // Score constraint arrivalAfterMaxEndTimeAtDepot is a built-in hard constraint in VehicleRoutingImporter - return HardSoftScore.of(hardScore, softScore); - } - -} diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/vehiclerouting/optional/score/VehicleRoutingIncrementalScoreCalculator.java b/src/main/java/ai/timefold/solver/benchmarks/examples/vehiclerouting/optional/score/VehicleRoutingIncrementalScoreCalculator.java deleted file mode 100644 index 306c3b44..00000000 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/vehiclerouting/optional/score/VehicleRoutingIncrementalScoreCalculator.java +++ /dev/null @@ -1,191 +0,0 @@ -package ai.timefold.solver.benchmarks.examples.vehiclerouting.optional.score; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import ai.timefold.solver.benchmarks.examples.vehiclerouting.domain.Customer; -import ai.timefold.solver.benchmarks.examples.vehiclerouting.domain.Vehicle; -import ai.timefold.solver.benchmarks.examples.vehiclerouting.domain.VehicleRoutingSolution; -import ai.timefold.solver.benchmarks.examples.vehiclerouting.domain.timewindowed.TimeWindowedCustomer; -import ai.timefold.solver.benchmarks.examples.vehiclerouting.domain.timewindowed.TimeWindowedVehicleRoutingSolution; -import ai.timefold.solver.core.api.score.HardSoftScore; -import ai.timefold.solver.core.api.score.calculator.IncrementalScoreCalculator; - -public class VehicleRoutingIncrementalScoreCalculator - implements - IncrementalScoreCalculator { - - private boolean timeWindowed; - private Map vehicleDemandMap; - - private long hardScore; - private long softScore; - - @Override - public void resetWorkingSolution(VehicleRoutingSolution solution) { - timeWindowed = solution instanceof TimeWindowedVehicleRoutingSolution; - hardScore = 0L; - softScore = 0L; - List vehicleList = solution.getVehicleList(); - vehicleDemandMap = new HashMap<>(vehicleList.size()); - for (Vehicle vehicle : vehicleList) { - int demand = 0; - List customers = vehicle.getCustomers(); - for (int index = 0; index < customers.size(); index++) { - Customer customer = customers.get(index); - demand += customer.getDemand(); - softScore -= getDistanceFromPreviousStandstill(vehicle, customer, index); - if (timeWindowed) { - insertArrivalTime( - (TimeWindowedCustomer) customer); - } - } - if (customers.size() > 0) { - softScore -= getDistanceToDepot(vehicle, customers.size() - 1); - } - vehicleDemandMap.put(vehicle, demand); - hardScore += Math.min(vehicle.getCapacity() - demand, 0); - } - } - - @Override - public void beforeVariableChanged(Object entity, String variableName) { - if (variableName.equals("arrivalTime")) { - retractArrivalTime( - (TimeWindowedCustomer) entity); - } - } - - @Override - public void afterVariableChanged(Object entity, String variableName) { - if (variableName.equals("arrivalTime")) { - insertArrivalTime( - (TimeWindowedCustomer) entity); - } - } - - @Override - public void beforeListVariableChanged(Object entity, String variableName, int fromIndex, int toIndex) { - Vehicle vehicle = - (Vehicle) entity; - for (int index = fromIndex; index < toIndex; index++) { - Customer customer = vehicle.getCustomers().get(index); - // Score constraint vehicleCapacity - int capacity = vehicle.getCapacity(); - int oldDemand = vehicleDemandMap.get(vehicle); - int newDemand = oldDemand - customer.getDemand(); - hardScore += Math.min(capacity - newDemand, 0) - Math.min(capacity - oldDemand, 0); - vehicleDemandMap.put(vehicle, newDemand); - // Score constraint distanceFromPreviousCustomer - softScore += getDistanceFromPreviousStandstill(vehicle, customer, index); - } - if (toIndex < vehicle.getCustomers().size()) { - softScore += getDistanceFromPreviousStandstill(vehicle, toIndex); - } else if (toIndex > 0) { - // Score constraint distanceFromLastCustomerToDepot - softScore += getDistanceToDepot(vehicle, toIndex - 1); - } - } - - @Override - public void afterListVariableChanged(Object entity, String variableName, int fromIndex, int toIndex) { - Vehicle vehicle = - (Vehicle) entity; - for (int index = fromIndex; index < toIndex; index++) { - Customer customer = vehicle.getCustomers().get(index); - // Score constraint vehicleCapacity - int capacity = vehicle.getCapacity(); - int oldDemand = vehicleDemandMap.get(vehicle); - int newDemand = oldDemand + customer.getDemand(); - hardScore += Math.min(capacity - newDemand, 0) - Math.min(capacity - oldDemand, 0); - vehicleDemandMap.put(vehicle, newDemand); - // Score constraint distanceFromPreviousCustomer - softScore -= getDistanceFromPreviousStandstill(vehicle, customer, index); - } - if (toIndex < vehicle.getCustomers().size()) { - softScore -= getDistanceFromPreviousStandstill(vehicle, toIndex); - } else if (toIndex > 0) { - // Score constraint distanceFromLastCustomerToDepot - softScore -= getDistanceToDepot(vehicle, toIndex - 1); - } - } - - private long getDistanceToDepot(Vehicle vehicle, int index) { - return getDistanceToDepot(vehicle, vehicle.getCustomers().get(index), index); - } - - private long getDistanceToDepot(Vehicle vehicle, - Customer customer, int index) { - if (index == vehicle.getCustomers().size() - 1) { - return customer.getLocation().getDistanceTo(vehicle.getLocation()); - } - return 0; - } - - private long getDistanceFromPreviousStandstill(Vehicle vehicle, - int index) { - return getDistanceFromPreviousStandstill(vehicle, vehicle.getCustomers().get(index), index); - } - - private long getDistanceFromPreviousStandstill(Vehicle vehicle, Customer customer, int index) { - if (index == 0) { - return vehicle.getLocation().getDistanceTo(customer.getLocation()); - } - return vehicle.getCustomers().get(index - 1).getLocation().getDistanceTo(customer.getLocation()); - } - - private void insertArrivalTime( - TimeWindowedCustomer customer) { - Long arrivalTime = customer.getArrivalTime(); - if (arrivalTime != null) { - long maxEndTime = customer.getMaxEndTime(); - if (maxEndTime < arrivalTime) { - // Score constraint arrivalAfterMaxEndTime - hardScore -= (arrivalTime - maxEndTime); - } - } - // Score constraint arrivalAfterMaxEndTimeAtDepot is a built-in hard constraint in VehicleRoutingImporter - } - - private void retractArrivalTime(TimeWindowedCustomer customer) { - Long arrivalTime = customer.getArrivalTime(); - if (arrivalTime != null) { - long maxEndTime = customer.getMaxEndTime(); - if (maxEndTime < arrivalTime) { - // Score constraint arrivalAfterMaxEndTime - hardScore += (arrivalTime - maxEndTime); - } - } - } - - @Override - public HardSoftScore calculateScore() { - return HardSoftScore.of(hardScore, softScore); - } - - // ************************************************************************ - // Unused methods - // ************************************************************************ - - @Override - public void beforeEntityAdded(Object entity) { - throw new UnsupportedOperationException("The VRP example does not support adding vehicles."); - } - - @Override - public void afterEntityAdded(Object entity) { - throw new UnsupportedOperationException("The VRP example does not support adding vehicles."); - } - - @Override - public void beforeEntityRemoved(Object entity) { - throw new UnsupportedOperationException("The VRP example does not support removing vehicles."); - } - - @Override - public void afterEntityRemoved(Object entity) { - throw new UnsupportedOperationException("The VRP example does not support removing vehicles."); - } - -} diff --git a/src/main/java/ai/timefold/solver/benchmarks/micro/common/AbstractConfiguration.java b/src/main/java/ai/timefold/solver/benchmarks/micro/common/AbstractConfiguration.java index 6275a69e..82d01700 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/micro/common/AbstractConfiguration.java +++ b/src/main/java/ai/timefold/solver/benchmarks/micro/common/AbstractConfiguration.java @@ -43,7 +43,7 @@ protected static List parseExamples(String examples, E... values) { .map(e -> Arrays.stream(values) .filter(value -> value.toString().equalsIgnoreCase(e)) .findFirst() - .orElseThrow(() -> new IllegalArgumentException("Unknown example: " + e))) + .orElseThrow(() -> new IllegalArgumentException("Unknown example (%s)".formatted(e)))) .collect(Collectors.toList()); } } diff --git a/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/Configuration.java b/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/Configuration.java index 2ea50ebe..7545ae21 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/Configuration.java +++ b/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/Configuration.java @@ -24,8 +24,6 @@ public static Configuration read(InputStream inputStream) throws IOException { .map(sdt -> switch (sdt) { case "cs" -> ScoreDirectorType.CONSTRAINT_STREAMS; case "cs_justified" -> ScoreDirectorType.CONSTRAINT_STREAMS_JUSTIFIED; - case "easy" -> ScoreDirectorType.EASY; - case "incremental" -> ScoreDirectorType.INCREMENTAL; default -> throw new IllegalArgumentException("Unknown score director type: " + sdt); }) .collect(Collectors.toList()); diff --git a/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/Example.java b/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/Example.java index c9144be8..05d6ffeb 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/Example.java +++ b/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/Example.java @@ -7,12 +7,12 @@ import java.util.Set; import java.util.function.Function; -import ai.timefold.solver.benchmarks.examples.tsp.domain.solver.nearby.VisitNearbyDistanceMeter; import ai.timefold.solver.benchmarks.examples.vehiclerouting.domain.solver.nearby.CustomerNearbyDistanceMeter; import ai.timefold.solver.benchmarks.micro.scoredirector.problems.CloudBalancingProblem; import ai.timefold.solver.benchmarks.micro.scoredirector.problems.ConferenceSchedulingProblem; import ai.timefold.solver.benchmarks.micro.scoredirector.problems.CurriculumCourseProblem; import ai.timefold.solver.benchmarks.micro.scoredirector.problems.ExaminationProblem; +import ai.timefold.solver.benchmarks.micro.scoredirector.problems.FlowShopProblem; import ai.timefold.solver.benchmarks.micro.scoredirector.problems.MachineReassignmentProblem; import ai.timefold.solver.benchmarks.micro.scoredirector.problems.MeetingSchedulingProblem; import ai.timefold.solver.benchmarks.micro.scoredirector.problems.NurseRosteringProblem; @@ -20,31 +20,22 @@ import ai.timefold.solver.benchmarks.micro.scoredirector.problems.Problem; import ai.timefold.solver.benchmarks.micro.scoredirector.problems.TaskAssigningProblem; import ai.timefold.solver.benchmarks.micro.scoredirector.problems.TravelingTournamentProblem; -import ai.timefold.solver.benchmarks.micro.scoredirector.problems.TspProblem; import ai.timefold.solver.benchmarks.micro.scoredirector.problems.VehicleRoutingProblem; import ai.timefold.solver.core.impl.heuristic.selector.common.nearby.NearbyDistanceMeter; public enum Example { CLOUD_BALANCING(CloudBalancingProblem::new), - CONFERENCE_SCHEDULING(ConferenceSchedulingProblem::new, ScoreDirectorType.CONSTRAINT_STREAMS, - ScoreDirectorType.CONSTRAINT_STREAMS_JUSTIFIED), - CURRICULUM_COURSE(CurriculumCourseProblem::new, ScoreDirectorType.CONSTRAINT_STREAMS, - ScoreDirectorType.CONSTRAINT_STREAMS_JUSTIFIED), - EXAMINATION(ExaminationProblem::new, ScoreDirectorType.CONSTRAINT_STREAMS, ScoreDirectorType.CONSTRAINT_STREAMS_JUSTIFIED), - MACHINE_REASSIGNMENT(MachineReassignmentProblem::new, ScoreDirectorType.INCREMENTAL, ScoreDirectorType.CONSTRAINT_STREAMS, - ScoreDirectorType.CONSTRAINT_STREAMS_JUSTIFIED), - MEETING_SCHEDULING(MeetingSchedulingProblem::new, ScoreDirectorType.CONSTRAINT_STREAMS, - ScoreDirectorType.CONSTRAINT_STREAMS_JUSTIFIED), - NURSE_ROSTERING(NurseRosteringProblem::new, ScoreDirectorType.CONSTRAINT_STREAMS, - ScoreDirectorType.CONSTRAINT_STREAMS_JUSTIFIED), - PATIENT_ADMISSION_SCHEDULING(PatientAdmissionSchedulingProblem::new, ScoreDirectorType.CONSTRAINT_STREAMS, - ScoreDirectorType.CONSTRAINT_STREAMS_JUSTIFIED), - TASK_ASSIGNING(TaskAssigningProblem::new, ScoreDirectorType.CONSTRAINT_STREAMS, - ScoreDirectorType.CONSTRAINT_STREAMS_JUSTIFIED), - TRAVELING_TOURNAMENT(TravelingTournamentProblem::new, ScoreDirectorType.CONSTRAINT_STREAMS, - ScoreDirectorType.CONSTRAINT_STREAMS_JUSTIFIED), - TSP(TspProblem::new, VisitNearbyDistanceMeter.class), + CONFERENCE_SCHEDULING(ConferenceSchedulingProblem::new), + CURRICULUM_COURSE(CurriculumCourseProblem::new), + EXAMINATION(ExaminationProblem::new), + FLOW_SHOP(FlowShopProblem::new), + MACHINE_REASSIGNMENT(MachineReassignmentProblem::new), + MEETING_SCHEDULING(MeetingSchedulingProblem::new), + NURSE_ROSTERING(NurseRosteringProblem::new), + PATIENT_ADMISSION_SCHEDULING(PatientAdmissionSchedulingProblem::new), + TASK_ASSIGNING(TaskAssigningProblem::new), + TRAVELING_TOURNAMENT(TravelingTournamentProblem::new), VEHICLE_ROUTING(VehicleRoutingProblem::new, CustomerNearbyDistanceMeter.class); private final Function problemFactory; diff --git a/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/Main.java b/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/Main.java index af868495..fcdcfc35 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/Main.java +++ b/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/Main.java @@ -65,8 +65,6 @@ public void run(String[] args) throws RunnerException, IOException { var options = getBaseJmhConfig(configuration); options = processBenchmark(options, configuration, ScoreDirectorType.CONSTRAINT_STREAMS); options = processBenchmark(options, configuration, ScoreDirectorType.CONSTRAINT_STREAMS_JUSTIFIED); - options = processBenchmark(options, configuration, ScoreDirectorType.EASY); - options = processBenchmark(options, configuration, ScoreDirectorType.INCREMENTAL); options = initAsyncProfiler(options); var runner = new Runner(options.build()); diff --git a/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/ScoreDirectorType.java b/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/ScoreDirectorType.java index 8844c0fb..6614d663 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/ScoreDirectorType.java +++ b/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/ScoreDirectorType.java @@ -5,8 +5,6 @@ import ai.timefold.solver.benchmarks.micro.scoredirector.jmh.AbstractBenchmark; import ai.timefold.solver.benchmarks.micro.scoredirector.jmh.ConstraintStreamsBenchmark; import ai.timefold.solver.benchmarks.micro.scoredirector.jmh.ConstraintStreamsJustifiedBenchmark; -import ai.timefold.solver.benchmarks.micro.scoredirector.jmh.EasyBenchmark; -import ai.timefold.solver.benchmarks.micro.scoredirector.jmh.IncrementalBenchmark; import ai.timefold.solver.core.api.score.Score; import ai.timefold.solver.core.config.score.director.ScoreDirectorFactoryConfig; import ai.timefold.solver.core.config.solver.EnvironmentMode; @@ -19,10 +17,8 @@ */ public enum ScoreDirectorType implements Comparable { - EASY(EasyBenchmark.class, "easyExample"), CONSTRAINT_STREAMS_JUSTIFIED(ConstraintStreamsJustifiedBenchmark.class, "csJustifiedExample"), - CONSTRAINT_STREAMS(ConstraintStreamsBenchmark.class, "csExample"), - INCREMENTAL(IncrementalBenchmark.class, "incrementalExample"); + CONSTRAINT_STREAMS(ConstraintStreamsBenchmark.class, "csExample"); private final Class benchmarkClass; private final String benchmarkParamName; diff --git a/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/jmh/EasyBenchmark.java b/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/jmh/EasyBenchmark.java deleted file mode 100644 index 66c06044..00000000 --- a/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/jmh/EasyBenchmark.java +++ /dev/null @@ -1,22 +0,0 @@ -package ai.timefold.solver.benchmarks.micro.scoredirector.jmh; - -import ai.timefold.solver.benchmarks.micro.scoredirector.Example; -import ai.timefold.solver.benchmarks.micro.scoredirector.ScoreDirectorType; - -import org.openjdk.jmh.annotations.Param; - -public class EasyBenchmark extends AbstractBenchmark { - - @Param - public Example easyExample; - - @Override - protected ScoreDirectorType getScoreDirectorType() { - return ScoreDirectorType.EASY; - } - - @Override - protected Example getExample() { - return easyExample; - } -} diff --git a/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/jmh/IncrementalBenchmark.java b/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/jmh/IncrementalBenchmark.java deleted file mode 100644 index 7fb8698d..00000000 --- a/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/jmh/IncrementalBenchmark.java +++ /dev/null @@ -1,22 +0,0 @@ -package ai.timefold.solver.benchmarks.micro.scoredirector.jmh; - -import ai.timefold.solver.benchmarks.micro.scoredirector.Example; -import ai.timefold.solver.benchmarks.micro.scoredirector.ScoreDirectorType; - -import org.openjdk.jmh.annotations.Param; - -public class IncrementalBenchmark extends AbstractBenchmark { - - @Param - public Example incrementalExample; - - @Override - protected ScoreDirectorType getScoreDirectorType() { - return ScoreDirectorType.INCREMENTAL; - } - - @Override - protected Example getExample() { - return incrementalExample; - } -} diff --git a/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/problems/CloudBalancingProblem.java b/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/problems/CloudBalancingProblem.java index 1e6c16ed..821ae32f 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/problems/CloudBalancingProblem.java +++ b/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/problems/CloudBalancingProblem.java @@ -2,8 +2,6 @@ import ai.timefold.solver.benchmarks.examples.cloudbalancing.domain.CloudBalance; import ai.timefold.solver.benchmarks.examples.cloudbalancing.domain.CloudProcess; -import ai.timefold.solver.benchmarks.examples.cloudbalancing.optional.score.CloudBalancingIncrementalScoreCalculator; -import ai.timefold.solver.benchmarks.examples.cloudbalancing.optional.score.CloudBalancingMapBasedEasyScoreCalculator; import ai.timefold.solver.benchmarks.examples.cloudbalancing.persistence.CloudBalanceSolutionFileIO; import ai.timefold.solver.benchmarks.examples.cloudbalancing.score.CloudBalancingConstraintProvider; import ai.timefold.solver.benchmarks.micro.scoredirector.Example; @@ -24,10 +22,7 @@ protected ScoreDirectorFactoryConfig buildScoreDirectorFactoryConfig(ScoreDirect return switch (scoreDirectorType) { case CONSTRAINT_STREAMS, CONSTRAINT_STREAMS_JUSTIFIED -> scoreDirectorFactoryConfig.withConstraintProviderClass(CloudBalancingConstraintProvider.class); - case EASY -> - scoreDirectorFactoryConfig.withEasyScoreCalculatorClass(CloudBalancingMapBasedEasyScoreCalculator.class); - case INCREMENTAL -> - scoreDirectorFactoryConfig.withIncrementalScoreCalculatorClass(CloudBalancingIncrementalScoreCalculator.class); + default -> throw new UnsupportedOperationException("Score director: %s".formatted(scoreDirectorType)); }; } diff --git a/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/problems/FlowShopProblem.java b/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/problems/FlowShopProblem.java new file mode 100644 index 00000000..b92813bf --- /dev/null +++ b/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/problems/FlowShopProblem.java @@ -0,0 +1,44 @@ +package ai.timefold.solver.benchmarks.micro.scoredirector.problems; + +import ai.timefold.solver.benchmarks.examples.flowshop.domain.Job; +import ai.timefold.solver.benchmarks.examples.flowshop.domain.JobScheduleSolution; +import ai.timefold.solver.benchmarks.examples.flowshop.domain.Machine; +import ai.timefold.solver.benchmarks.examples.flowshop.persistence.FlowShopSolutionFileIO; +import ai.timefold.solver.benchmarks.examples.flowshop.score.FlowShopConstraintProvider; +import ai.timefold.solver.benchmarks.micro.scoredirector.Example; +import ai.timefold.solver.benchmarks.micro.scoredirector.ScoreDirectorType; +import ai.timefold.solver.core.api.domain.solution.SolutionFileIO; +import ai.timefold.solver.core.config.score.director.ScoreDirectorFactoryConfig; +import ai.timefold.solver.core.impl.domain.solution.descriptor.SolutionDescriptor; + +public final class FlowShopProblem extends AbstractProblem { + + public FlowShopProblem(ScoreDirectorType scoreDirectorType) { + super(Example.FLOW_SHOP, scoreDirectorType); + } + + @Override + protected ScoreDirectorFactoryConfig buildScoreDirectorFactoryConfig(ScoreDirectorType scoreDirectorType) { + var scoreDirectorFactoryConfig = buildInitialScoreDirectorFactoryConfig(); + return switch (scoreDirectorType) { + case CONSTRAINT_STREAMS, CONSTRAINT_STREAMS_JUSTIFIED -> + scoreDirectorFactoryConfig.withConstraintProviderClass(FlowShopConstraintProvider.class); + }; + } + + @Override + protected SolutionDescriptor buildSolutionDescriptor() { + return SolutionDescriptor.buildSolutionDescriptor(JobScheduleSolution.class, Machine.class, Job.class); + } + + @Override + protected SolutionFileIO createSolutionFileIO() { + return new FlowShopSolutionFileIO(); + } + + @Override + protected String getDatasetName() { + return "Ta100"; + } + +} diff --git a/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/problems/MachineReassignmentProblem.java b/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/problems/MachineReassignmentProblem.java index 9318e8e2..f95028e4 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/problems/MachineReassignmentProblem.java +++ b/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/problems/MachineReassignmentProblem.java @@ -2,7 +2,6 @@ import ai.timefold.solver.benchmarks.examples.machinereassignment.domain.MachineReassignment; import ai.timefold.solver.benchmarks.examples.machinereassignment.domain.MrProcessAssignment; -import ai.timefold.solver.benchmarks.examples.machinereassignment.optional.score.MachineReassignmentIncrementalScoreCalculator; import ai.timefold.solver.benchmarks.examples.machinereassignment.persistence.MachineReassignmentSolutionFileIO; import ai.timefold.solver.benchmarks.examples.machinereassignment.score.MachineReassignmentConstraintProvider; import ai.timefold.solver.benchmarks.micro.scoredirector.Example; @@ -24,8 +23,6 @@ protected ScoreDirectorFactoryConfig buildScoreDirectorFactoryConfig(ScoreDirect return switch (scoreDirectorType) { case CONSTRAINT_STREAMS, CONSTRAINT_STREAMS_JUSTIFIED -> scoreDirectorFactoryConfig.withConstraintProviderClass(MachineReassignmentConstraintProvider.class); - case INCREMENTAL -> scoreDirectorFactoryConfig - .withIncrementalScoreCalculatorClass(MachineReassignmentIncrementalScoreCalculator.class); default -> throw new UnsupportedOperationException("Score director: " + scoreDirectorType); }; } diff --git a/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/problems/TspProblem.java b/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/problems/TspProblem.java deleted file mode 100644 index bd5395b5..00000000 --- a/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/problems/TspProblem.java +++ /dev/null @@ -1,49 +0,0 @@ -package ai.timefold.solver.benchmarks.micro.scoredirector.problems; - -import ai.timefold.solver.benchmarks.examples.tsp.domain.Tour; -import ai.timefold.solver.benchmarks.examples.tsp.domain.TspSolution; -import ai.timefold.solver.benchmarks.examples.tsp.domain.Visit; -import ai.timefold.solver.benchmarks.examples.tsp.optional.score.TspEasyScoreCalculator; -import ai.timefold.solver.benchmarks.examples.tsp.optional.score.TspIncrementalScoreCalculator; -import ai.timefold.solver.benchmarks.examples.tsp.persistence.TspSolutionFileIO; -import ai.timefold.solver.benchmarks.examples.tsp.score.TspConstraintProvider; -import ai.timefold.solver.benchmarks.micro.scoredirector.Example; -import ai.timefold.solver.benchmarks.micro.scoredirector.ScoreDirectorType; -import ai.timefold.solver.core.api.domain.solution.SolutionFileIO; -import ai.timefold.solver.core.config.score.director.ScoreDirectorFactoryConfig; -import ai.timefold.solver.core.impl.domain.solution.descriptor.SolutionDescriptor; - -public final class TspProblem extends AbstractProblem { - - public TspProblem(ScoreDirectorType scoreDirectorType) { - super(Example.TSP, scoreDirectorType); - } - - @Override - protected ScoreDirectorFactoryConfig buildScoreDirectorFactoryConfig(ScoreDirectorType scoreDirectorType) { - var scoreDirectorFactoryConfig = buildInitialScoreDirectorFactoryConfig(); - return switch (scoreDirectorType) { - case CONSTRAINT_STREAMS, CONSTRAINT_STREAMS_JUSTIFIED -> - scoreDirectorFactoryConfig.withConstraintProviderClass(TspConstraintProvider.class); - case EASY -> scoreDirectorFactoryConfig.withEasyScoreCalculatorClass(TspEasyScoreCalculator.class); - case INCREMENTAL -> - scoreDirectorFactoryConfig.withIncrementalScoreCalculatorClass(TspIncrementalScoreCalculator.class); - }; - } - - @Override - protected SolutionDescriptor buildSolutionDescriptor() { - return SolutionDescriptor.buildSolutionDescriptor(TspSolution.class, Tour.class, Visit.class); - } - - @Override - protected SolutionFileIO createSolutionFileIO() { - return new TspSolutionFileIO(); - } - - @Override - protected String getDatasetName() { - return "vm1084"; - } - -} diff --git a/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/problems/VehicleRoutingProblem.java b/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/problems/VehicleRoutingProblem.java index 114ca3e3..4d0364fe 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/problems/VehicleRoutingProblem.java +++ b/src/main/java/ai/timefold/solver/benchmarks/micro/scoredirector/problems/VehicleRoutingProblem.java @@ -4,8 +4,6 @@ import ai.timefold.solver.benchmarks.examples.vehiclerouting.domain.Vehicle; import ai.timefold.solver.benchmarks.examples.vehiclerouting.domain.VehicleRoutingSolution; import ai.timefold.solver.benchmarks.examples.vehiclerouting.domain.timewindowed.TimeWindowedCustomer; -import ai.timefold.solver.benchmarks.examples.vehiclerouting.optional.score.VehicleRoutingEasyScoreCalculator; -import ai.timefold.solver.benchmarks.examples.vehiclerouting.optional.score.VehicleRoutingIncrementalScoreCalculator; import ai.timefold.solver.benchmarks.examples.vehiclerouting.persistence.VehicleRoutingSolutionFileIO; import ai.timefold.solver.benchmarks.examples.vehiclerouting.score.VehicleRoutingConstraintProvider; import ai.timefold.solver.benchmarks.micro.scoredirector.Example; @@ -26,9 +24,7 @@ protected ScoreDirectorFactoryConfig buildScoreDirectorFactoryConfig(ScoreDirect return switch (scoreDirectorType) { case CONSTRAINT_STREAMS, CONSTRAINT_STREAMS_JUSTIFIED -> scoreDirectorFactoryConfig.withConstraintProviderClass(VehicleRoutingConstraintProvider.class); - case EASY -> scoreDirectorFactoryConfig.withEasyScoreCalculatorClass(VehicleRoutingEasyScoreCalculator.class); - case INCREMENTAL -> - scoreDirectorFactoryConfig.withIncrementalScoreCalculatorClass(VehicleRoutingIncrementalScoreCalculator.class); + default -> throw new UnsupportedOperationException("Score director: %s".formatted(scoreDirectorType)); }; } diff --git a/src/main/resources/ai/timefold/solver/benchmarks/examples/flowshop/flowShopSolverConfig.xml b/src/main/resources/ai/timefold/solver/benchmarks/examples/flowshop/flowShopSolverConfig.xml index 2ee9ec17..22e4bdf1 100644 --- a/src/main/resources/ai/timefold/solver/benchmarks/examples/flowshop/flowShopSolverConfig.xml +++ b/src/main/resources/ai/timefold/solver/benchmarks/examples/flowshop/flowShopSolverConfig.xml @@ -16,7 +16,7 @@ ONLY_DOWN - 2 + 1 ai.timefold.solver.benchmarks.examples.flowshop.phase.NEHCustomPhase diff --git a/src/test/java/ai/timefold/solver/benchmarks/examples/cloudbalancing/app/CloudBalancingSolveAllTurtleTest.java b/src/test/java/ai/timefold/solver/benchmarks/examples/cloudbalancing/app/CloudBalancingSolveAllTurtleTest.java index fc3e3a61..2bce4953 100644 --- a/src/test/java/ai/timefold/solver/benchmarks/examples/cloudbalancing/app/CloudBalancingSolveAllTurtleTest.java +++ b/src/test/java/ai/timefold/solver/benchmarks/examples/cloudbalancing/app/CloudBalancingSolveAllTurtleTest.java @@ -1,7 +1,6 @@ package ai.timefold.solver.benchmarks.examples.cloudbalancing.app; import ai.timefold.solver.benchmarks.examples.cloudbalancing.domain.CloudBalance; -import ai.timefold.solver.benchmarks.examples.cloudbalancing.optional.score.CloudBalancingMapBasedEasyScoreCalculator; import ai.timefold.solver.benchmarks.examples.common.TestSystemProperties; import ai.timefold.solver.benchmarks.examples.common.app.CommonApp; import ai.timefold.solver.benchmarks.examples.common.app.UnsolvedDirSolveAllTurtleTest; @@ -16,8 +15,4 @@ protected CommonApp createCommonApp() { return new CloudBalancingApp(); } - @Override - protected Class overwritingEasyScoreCalculatorClass() { - return CloudBalancingMapBasedEasyScoreCalculator.class; - } } diff --git a/src/test/java/ai/timefold/solver/benchmarks/examples/common/app/SolveAllTurtleTest.java b/src/test/java/ai/timefold/solver/benchmarks/examples/common/app/SolveAllTurtleTest.java index b2ec529d..4ad7213c 100644 --- a/src/test/java/ai/timefold/solver/benchmarks/examples/common/app/SolveAllTurtleTest.java +++ b/src/test/java/ai/timefold/solver/benchmarks/examples/common/app/SolveAllTurtleTest.java @@ -5,7 +5,6 @@ import java.io.File; import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.Random; import java.util.function.Function; import java.util.stream.Collectors; @@ -13,10 +12,7 @@ import ai.timefold.solver.benchmarks.examples.common.TestSystemProperties; import ai.timefold.solver.core.api.domain.solution.PlanningSolution; -import ai.timefold.solver.core.api.score.calculator.EasyScoreCalculator; -import ai.timefold.solver.core.api.solver.Solver; import ai.timefold.solver.core.api.solver.SolverFactory; -import ai.timefold.solver.core.config.score.director.ScoreDirectorFactoryConfig; import ai.timefold.solver.core.config.solver.EnvironmentMode; import ai.timefold.solver.core.config.solver.SolverConfig; import ai.timefold.solver.core.config.solver.termination.TerminationConfig; @@ -47,37 +43,37 @@ default Solution_ loadProblem(File f) { protected abstract ProblemFactory createProblemFactory(CommonApp commonApp); private List getFilteredSolutionFiles(CommonApp commonApp) { - List solutionFiles = getSolutionFiles(commonApp); - String propertyValue = System.getProperty(TestSystemProperties.TURTLE_TEST_RUN_TIME_LIMIT); + var solutionFiles = getSolutionFiles(commonApp); + var propertyValue = System.getProperty(TestSystemProperties.TURTLE_TEST_RUN_TIME_LIMIT); if (propertyValue == null) { logger.info("Will run all tests due to no time limit being set."); return solutionFiles; } - int availableMinutes = Integer.parseInt(propertyValue); - int testCount = solutionFiles.size(); - int maximumTestCount = (int) Math.floor(availableMinutes / 10.0); // One test will take 10 minutes to run. + var availableMinutes = Integer.parseInt(propertyValue); + var testCount = solutionFiles.size(); + var maximumTestCount = (int) Math.floor(availableMinutes / 10.0); // One test will take 10 minutes to run. if (testCount <= maximumTestCount) { logger.info("Will run all tests as they all fit within the time limit of {} minutes.", availableMinutes); return solutionFiles; } - long seed = System.nanoTime(); + var seed = System.nanoTime(); logger.info("Will randomly filter out some tests to fit within the time window. Using random seed ({}).", seed); - Random random = new Random(seed); - double ratioOfTestsToRun = maximumTestCount / (double) testCount; - Map> testsPerParentDirectoryMap = solutionFiles.stream() + var random = new Random(seed); + var ratioOfTestsToRun = maximumTestCount / (double) testCount; + var testsPerParentDirectoryMap = solutionFiles.stream() .collect(Collectors.groupingBy(File::getParentFile, Collectors.toList())); List filteredSolutionFiles = new ArrayList<>(maximumTestCount); // Make sure that each directory gets at least one test. - for (List testsInDirectory : testsPerParentDirectoryMap.values()) { - int testsToRunInDirectory = (int) Math.max(1, testsInDirectory.size() * ratioOfTestsToRun); - for (int i = 0; i < testsToRunInDirectory; i++) { - int fileIndex = random.nextInt(testsInDirectory.size()); + for (var testsInDirectory : testsPerParentDirectoryMap.values()) { + var testsToRunInDirectory = (int) Math.max(1, testsInDirectory.size() * ratioOfTestsToRun); + for (var i = 0; i < testsToRunInDirectory; i++) { + var fileIndex = random.nextInt(testsInDirectory.size()); filteredSolutionFiles.add(testsInDirectory.remove(fileIndex)); } } // If we are still over the limit, remove random tests. while (filteredSolutionFiles.size() > maximumTestCount) { - int fileIndex = random.nextInt(filteredSolutionFiles.size()); + var fileIndex = random.nextInt(filteredSolutionFiles.size()); filteredSolutionFiles.remove(fileIndex); } logger.info("Filtered out ({}) out of ({}) tests to run in ({}) minutes.", @@ -88,8 +84,8 @@ private List getFilteredSolutionFiles(CommonApp commonApp) { @Execution(ExecutionMode.CONCURRENT) @TestFactory Stream runStepAndFullAssert() { - CommonApp commonApp = createCommonApp(); - ProblemFactory problemFactory = createProblemFactory(commonApp); + var commonApp = createCommonApp(); + var problemFactory = createProblemFactory(commonApp); /* * When run in Github Actions, we are limited by the maximum amount of time that the job can run for. * This code intends to limit the number of tests so that they can all run within the time limit. @@ -111,7 +107,7 @@ public void runStepAndFullAssert(SolverConfig solverConfig, Solution_ problem) { } private static SolverConfig buildSolverConfig(String solverConfigResource) { - SolverConfig solverConfig = SolverConfig.createFromXmlResource(solverConfigResource); + var solverConfig = SolverConfig.createFromXmlResource(solverConfigResource); // buildAndSolve() fills in minutesSpentLimit solverConfig.setTerminationConfig(new TerminationConfig()); if (MOVE_THREAD_COUNT_OVERRIDE != null) { @@ -124,19 +120,9 @@ private Solution_ buildAndSolve(SolverConfig solverConfig, EnvironmentMode envir Solution_ problem, long maximumMinutesSpent) { solverConfig.getTerminationConfig().setMinutesSpentLimit(maximumMinutesSpent); solverConfig.setEnvironmentMode(environmentMode); - Class easyScoreCalculatorClass = overwritingEasyScoreCalculatorClass(); - if (easyScoreCalculatorClass != null && environmentMode.isStepAssertOrMore()) { - ScoreDirectorFactoryConfig assertionScoreDirectorFactoryConfig = new ScoreDirectorFactoryConfig(); - assertionScoreDirectorFactoryConfig.setEasyScoreCalculatorClass(easyScoreCalculatorClass); - solverConfig.getScoreDirectorFactoryConfig().setAssertionScoreDirectorFactory( - assertionScoreDirectorFactoryConfig); - } - SolverFactory solverFactory = SolverFactory.create(solverConfig); - Solver solver = solverFactory.buildSolver(); + var solverFactory = SolverFactory. create(solverConfig); + var solver = solverFactory.buildSolver(); return solver.solve(problem); } - protected Class overwritingEasyScoreCalculatorClass() { - return null; - } } diff --git a/src/test/java/ai/timefold/solver/benchmarks/examples/common/app/SolverSmokeTest.java b/src/test/java/ai/timefold/solver/benchmarks/examples/common/app/SolverSmokeTest.java index 6bf4cd5b..e1943bfb 100644 --- a/src/test/java/ai/timefold/solver/benchmarks/examples/common/app/SolverSmokeTest.java +++ b/src/test/java/ai/timefold/solver/benchmarks/examples/common/app/SolverSmokeTest.java @@ -6,7 +6,6 @@ import java.io.File; import java.util.Arrays; -import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.stream.Stream; @@ -15,8 +14,6 @@ import ai.timefold.solver.core.api.domain.solution.PlanningSolution; import ai.timefold.solver.core.api.domain.solution.SolutionFileIO; import ai.timefold.solver.core.api.score.Score; -import ai.timefold.solver.core.api.score.ScoreExplanation; -import ai.timefold.solver.core.api.score.constraint.ConstraintMatchTotal; import ai.timefold.solver.core.api.solver.SolutionManager; import ai.timefold.solver.core.api.solver.Solver; import ai.timefold.solver.core.api.solver.SolverFactory; @@ -58,7 +55,7 @@ private static Stream moveThreadCounts() { @BeforeEach public void setUp() { - CommonApp commonApp = createCommonApp(); + var commonApp = createCommonApp(); solutionFileIO = commonApp.createSolutionFileIO(); solverConfigResource = commonApp.getSolverConfigResource(); } @@ -90,7 +87,7 @@ Stream runSpeedTest() { private DynamicTest createSpeedTest(String unsolvedDataFile, EnvironmentMode environmentMode, Score_ bestScoreLimit, String moveThreadCount) { - String testName = unsolvedDataFile.replaceFirst(".*/", "") + var testName = unsolvedDataFile.replaceFirst(".*/", "") + ", " + environmentMode + ", threads: " + moveThreadCount; @@ -108,22 +105,22 @@ private DynamicTest createSpeedTest(String unsolvedDataFile, EnvironmentMode env private void runSpeedTest(File unsolvedDataFile, Score_ bestScoreLimit, EnvironmentMode environmentMode, String moveThreadCount) { - SolverFactory solverFactory = buildSpeedSolverFactory(bestScoreLimit, environmentMode, moveThreadCount); - Solution_ problem = solutionFileIO.read(unsolvedDataFile); + var solverFactory = buildSpeedSolverFactory(bestScoreLimit, environmentMode, moveThreadCount); + var problem = solutionFileIO.read(unsolvedDataFile); logger.info("Opened: {}", unsolvedDataFile); - Solver solver = solverFactory.buildSolver(); - Solution_ bestSolution = solver.solve(problem); + var solver = solverFactory.buildSolver(); + var bestSolution = solver.solve(problem); assertScoreAndConstraintMatches(solverFactory, bestSolution, bestScoreLimit); } private SolverFactory buildSpeedSolverFactory(Score_ bestScoreLimit, EnvironmentMode environmentMode, String moveThreadCount) { - SolverConfig solverConfig = SolverConfig.createFromXmlResource(solverConfigResource); + var solverConfig = SolverConfig.createFromXmlResource(solverConfigResource); solverConfig.withEnvironmentMode(environmentMode) .withTerminationConfig(new TerminationConfig() .withBestScoreLimit(bestScoreLimit.toString())) .withMoveThreadCount(moveThreadCount); - ScoreDirectorFactoryConfig scoreDirectorFactoryConfig = + var scoreDirectorFactoryConfig = Objects.requireNonNullElseGet(solverConfig.getScoreDirectorFactoryConfig(), ScoreDirectorFactoryConfig::new); if (scoreDirectorFactoryConfig.getConstraintProviderClass() == null) { @@ -136,22 +133,16 @@ private SolverFactory buildSpeedSolverFactory(Score_ bestScoreLimit, private void assertScoreAndConstraintMatches(SolverFactory solverFactory, Solution_ bestSolution, Score_ bestScoreLimit) { assertThat(bestSolution).isNotNull(); - SolutionManager solutionManager = SolutionManager.create(solverFactory); - Score_ bestScore = solutionManager.update(bestSolution); + var solutionManager = SolutionManager. create(solverFactory); + var bestScore = solutionManager.update(bestSolution); assertThat(bestScore) - .as("The bestScore (" + bestScore + ") must be at least the bestScoreLimit (" + bestScoreLimit + ").") + .as("The bestScore (%s) must be at least the bestScoreLimit (%s)." + .formatted(bestScore, bestScoreLimit)) .isGreaterThanOrEqualTo(bestScoreLimit); - ScoreExplanation scoreExplanation = solutionManager.explain(bestSolution); - Map> constraintMatchTotals = - scoreExplanation.getConstraintMatchTotalMap(); - assertThat(constraintMatchTotals).isNotNull(); - assertThat(constraintMatchTotals.values().stream() - .map(ConstraintMatchTotal::getScore) - .reduce(Score::add) - .orElse(bestScore.zero())) - .isEqualTo(scoreExplanation.getScore()); - assertThat(scoreExplanation.getIndictmentMap()).isNotNull(); + var scoreAnalysis = solutionManager.analyze(bestSolution); + assertThat(bestScore) + .isEqualTo(scoreAnalysis.score()); } protected static class TestData> { diff --git a/src/test/java/ai/timefold/solver/benchmarks/examples/common/score/ConstraintProviderTest.java b/src/test/java/ai/timefold/solver/benchmarks/examples/common/score/ConstraintProviderTest.java index 2fd1712b..00252001 100644 --- a/src/test/java/ai/timefold/solver/benchmarks/examples/common/score/ConstraintProviderTest.java +++ b/src/test/java/ai/timefold/solver/benchmarks/examples/common/score/ConstraintProviderTest.java @@ -4,6 +4,7 @@ import java.lang.annotation.RetentionPolicy; import ai.timefold.solver.core.api.score.stream.test.ConstraintVerifier; + import org.junit.jupiter.api.Test; import org.junit.jupiter.api.parallel.Execution; import org.junit.jupiter.api.parallel.ExecutionMode; diff --git a/src/test/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/score/ConferenceSchedulingConstraintProviderTest.java b/src/test/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/score/ConferenceSchedulingConstraintProviderTest.java index e32cfeeb..7263884c 100644 --- a/src/test/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/score/ConferenceSchedulingConstraintProviderTest.java +++ b/src/test/java/ai/timefold/solver/benchmarks/examples/conferencescheduling/score/ConferenceSchedulingConstraintProviderTest.java @@ -1,12 +1,13 @@ package ai.timefold.solver.benchmarks.examples.conferencescheduling.score; -import static java.util.Collections.emptySet; import static java.util.Collections.singleton; import static java.util.Collections.singletonList; import java.time.LocalDateTime; import java.util.Arrays; -import java.util.HashSet; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.SequencedSet; import ai.timefold.solver.benchmarks.examples.common.score.AbstractConstraintProviderTest; import ai.timefold.solver.benchmarks.examples.common.score.ConstraintProviderTest; @@ -46,6 +47,10 @@ class ConferenceSchedulingConstraintProviderTest .withEndDateTime(START.plusDays(1).plusHours(1)) .withTagSet(singleton("c")); + private static SequencedSet singleton(T item) { + return new LinkedHashSet<>(Collections.singleton(item)); + } + // ************************************************************************ // Hard constraints // ************************************************************************ @@ -103,7 +108,7 @@ void talkPrerequisiteTalks( Room room = new Room(0); Talk talk1 = new Talk(1) .withRoom(room) - .withPrerequisiteTalksCodesSet(emptySet()) + .withPrerequisiteTalksCodesSet(new LinkedHashSet<>(0)) .withTimeslot(MONDAY_9_TO_10); Talk talk2 = new Talk(2) .withRoom(room) @@ -126,15 +131,15 @@ void talkMutuallyExclusiveTalksTags( Room room = new Room(0); Talk talk1 = new Talk(1) .withRoom(room) - .withMutuallyExclusiveTalksTagSet(emptySet()) + .withMutuallyExclusiveTalksTagSet(new LinkedHashSet<>(0)) .withTimeslot(MONDAY_9_TO_10); Talk talk2 = new Talk(2) .withRoom(room) - .withMutuallyExclusiveTalksTagSet(new HashSet<>(Arrays.asList("a", "b"))) + .withMutuallyExclusiveTalksTagSet(new LinkedHashSet<>(Arrays.asList("a", "b"))) .withTimeslot(MONDAY_9_TO_10); Talk talk3 = new Talk(3) .withRoom(room) - .withMutuallyExclusiveTalksTagSet(new HashSet<>(Arrays.asList("a", "b", "c"))) + .withMutuallyExclusiveTalksTagSet(new LinkedHashSet<>(Arrays.asList("a", "b", "c"))) .withTimeslot(MONDAY_9_TO_10); constraintVerifier.verifyThat( @@ -263,11 +268,11 @@ void talkRequiredRoomTags( .withTagSet(singleton("a")); Talk talk1 = new Talk(1) .withRoom(room) - .withRequiredRoomTagSet(new HashSet<>(Arrays.asList("a", "b"))) + .withRequiredRoomTagSet(new LinkedHashSet<>(Arrays.asList("a", "b"))) .withTimeslot(MONDAY_9_TO_10); Talk talk2 = new Talk(2) .withRoom(room) - .withRequiredRoomTagSet(emptySet()) + .withRequiredRoomTagSet(new LinkedHashSet<>(0)) .withTimeslot(MONDAY_10_TO_11); constraintVerifier.verifyThat( @@ -283,11 +288,11 @@ void talkProhibitedRoomTags( .withTagSet(singleton("a")); Talk talk1 = new Talk(1) .withRoom(room) - .withProhibitedRoomTagSet(new HashSet<>(Arrays.asList("a", "b"))) + .withProhibitedRoomTagSet(new LinkedHashSet<>(Arrays.asList("a", "b"))) .withTimeslot(MONDAY_9_TO_10); Talk talk2 = new Talk(2) .withRoom(room) - .withProhibitedRoomTagSet(emptySet()) + .withProhibitedRoomTagSet(new LinkedHashSet<>(0)) .withTimeslot(MONDAY_10_TO_11); constraintVerifier.verifyThat( @@ -684,11 +689,11 @@ void talkPreferredRoomTags( .withTagSet(singleton("a")); Talk talk1 = new Talk(1) .withRoom(room) - .withPreferredRoomTagSet(new HashSet<>(Arrays.asList("a", "b"))) + .withPreferredRoomTagSet(new LinkedHashSet<>(Arrays.asList("a", "b"))) .withTimeslot(MONDAY_9_TO_10); Talk talk2 = new Talk(2) .withRoom(room) - .withPreferredRoomTagSet(emptySet()) + .withPreferredRoomTagSet(new LinkedHashSet<>(0)) .withTimeslot(MONDAY_10_TO_11); constraintVerifier.verifyThat( @@ -704,11 +709,11 @@ void talkUndesiredRoomTags( .withTagSet(singleton("a")); Talk talk1 = new Talk(1) .withRoom(room) - .withUndesiredRoomTagSet(new HashSet<>(Arrays.asList("a", "b"))) + .withUndesiredRoomTagSet(new LinkedHashSet<>(Arrays.asList("a", "b"))) .withTimeslot(MONDAY_9_TO_10); Talk talk2 = new Talk(2) .withRoom(room) - .withUndesiredRoomTagSet(emptySet()) + .withUndesiredRoomTagSet(new LinkedHashSet<>(0)) .withTimeslot(MONDAY_10_TO_11); constraintVerifier.verifyThat( diff --git a/src/test/java/ai/timefold/solver/benchmarks/examples/flowshop/app/FlowShopSolveAllTurtleTest.java b/src/test/java/ai/timefold/solver/benchmarks/examples/flowshop/app/FlowShopSolveAllTurtleTest.java index a07900cc..b83af4ba 100644 --- a/src/test/java/ai/timefold/solver/benchmarks/examples/flowshop/app/FlowShopSolveAllTurtleTest.java +++ b/src/test/java/ai/timefold/solver/benchmarks/examples/flowshop/app/FlowShopSolveAllTurtleTest.java @@ -4,7 +4,6 @@ import ai.timefold.solver.benchmarks.examples.common.app.CommonApp; import ai.timefold.solver.benchmarks.examples.common.app.UnsolvedDirSolveAllTurtleTest; import ai.timefold.solver.benchmarks.examples.flowshop.domain.JobScheduleSolution; -import ai.timefold.solver.benchmarks.examples.flowshop.score.FlowShopEasyScoreCalculator; import org.junit.jupiter.api.condition.EnabledIfSystemProperty; @@ -16,8 +15,4 @@ protected CommonApp createCommonApp() { return new FlowShopApp(); } - @Override - protected Class overwritingEasyScoreCalculatorClass() { - return FlowShopEasyScoreCalculator.class; - } } diff --git a/src/test/java/ai/timefold/solver/benchmarks/examples/tsp/app/TspSolveAllTurtleTest.java b/src/test/java/ai/timefold/solver/benchmarks/examples/tsp/app/TspSolveAllTurtleTest.java index 15406be4..84175f38 100644 --- a/src/test/java/ai/timefold/solver/benchmarks/examples/tsp/app/TspSolveAllTurtleTest.java +++ b/src/test/java/ai/timefold/solver/benchmarks/examples/tsp/app/TspSolveAllTurtleTest.java @@ -4,7 +4,6 @@ import ai.timefold.solver.benchmarks.examples.common.app.CommonApp; import ai.timefold.solver.benchmarks.examples.common.app.UnsolvedDirSolveAllTurtleTest; import ai.timefold.solver.benchmarks.examples.tsp.domain.TspSolution; -import ai.timefold.solver.benchmarks.examples.tsp.optional.score.TspEasyScoreCalculator; import org.junit.jupiter.api.condition.EnabledIfSystemProperty; @@ -16,8 +15,4 @@ protected CommonApp createCommonApp() { return new TspApp(); } - @Override - protected Class overwritingEasyScoreCalculatorClass() { - return TspEasyScoreCalculator.class; - } } diff --git a/src/test/java/ai/timefold/solver/benchmarks/examples/vehiclerouting/app/VehicleRoutingSolveAllTurtleTest.java b/src/test/java/ai/timefold/solver/benchmarks/examples/vehiclerouting/app/VehicleRoutingSolveAllTurtleTest.java index 5a3bfb32..6f3f4b26 100644 --- a/src/test/java/ai/timefold/solver/benchmarks/examples/vehiclerouting/app/VehicleRoutingSolveAllTurtleTest.java +++ b/src/test/java/ai/timefold/solver/benchmarks/examples/vehiclerouting/app/VehicleRoutingSolveAllTurtleTest.java @@ -4,7 +4,6 @@ import ai.timefold.solver.benchmarks.examples.common.app.CommonApp; import ai.timefold.solver.benchmarks.examples.common.app.ImportDirSolveAllTurtleTest; import ai.timefold.solver.benchmarks.examples.vehiclerouting.domain.VehicleRoutingSolution; -import ai.timefold.solver.benchmarks.examples.vehiclerouting.optional.score.VehicleRoutingEasyScoreCalculator; import org.junit.jupiter.api.condition.EnabledIfSystemProperty; @@ -16,8 +15,4 @@ protected CommonApp createCommonApp() { return new VehicleRoutingApp(); } - @Override - protected Class overwritingEasyScoreCalculatorClass() { - return VehicleRoutingEasyScoreCalculator.class; - } }