@jetta/blocks-allocator 0.0.0-stage → 0.1.0-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (282) hide show
  1. package/README.md +103 -2
  2. package/package.json +67 -5
  3. package/src/Allocation_Attempt.js +135 -0
  4. package/src/Allocation_Error_Handler.js +69 -0
  5. package/src/Allocation_Flow.js +162 -0
  6. package/src/Allocation_Optimization/Allocation_LP.js +150 -0
  7. package/src/Allocation_Optimization/Block_Allocator.js +129 -0
  8. package/src/Allocation_Optimization/Block_Layer_Order.js +50 -0
  9. package/src/Allocation_Optimization/Block_Potential_Weight.js +54 -0
  10. package/src/Allocation_Optimization/Chosen_Blocks_Stock_Cap.js +82 -0
  11. package/src/Allocation_Optimization/block_builder/Allocation_Item_Creator.js +37 -0
  12. package/src/Allocation_Optimization/block_builder/Block_Item_List_Validator.js +18 -0
  13. package/src/Allocation_Optimization/block_builder/Block_Wall_Builder.js +303 -0
  14. package/src/Allocation_Optimization/block_builder/Blocks_Builder.js +40 -0
  15. package/src/Allocation_Optimization/block_builder/Next_Block_Position.js +33 -0
  16. package/src/Allocation_Optimization/block_builder/Slot_Item_Assigner.js +45 -0
  17. package/src/Allocation_Optimization/block_builder/Stacking_Validation.js +30 -0
  18. package/src/Allocation_Optimization/block_builder/assert_tie_ratio_block_matches_orientation_below.js +44 -0
  19. package/src/Allocation_Optimization/block_builder/block_shape_stock.js +129 -0
  20. package/src/Allocation_Optimization/block_builder/exceptions/Empty_Block_Item_List_Exception.js +21 -0
  21. package/src/Allocation_Optimization/block_builder/exceptions/Invalid_Stacking_Exception.js +14 -0
  22. package/src/Allocation_Optimization/block_builder/exceptions/No_Suitable_Item_Exception.js +16 -0
  23. package/src/Allocation_Optimization/block_builder/exceptions/Restricted_Block_Exception.js +21 -0
  24. package/src/Allocation_Optimization/block_builder/should_omit_block_group_id.js +29 -0
  25. package/src/Allocation_Optimization/block_builder/snap_elevated_block_wall_items.js +34 -0
  26. package/src/Allocation_Optimization/block_builder/stacking_rules_input.js +52 -0
  27. package/src/Allocation_Optimization/cap_chosen_blocks_by_shape_stock.js +110 -0
  28. package/src/Allocation_Optimization/density_groups/Adaptive_Density_Group_Preparer.js +21 -0
  29. package/src/Allocation_Optimization/density_groups/Adaptive_Density_Group_Selector.js +55 -0
  30. package/src/Allocation_Optimization/density_groups/Adaptive_Density_Group_Threshold_Resolver.js +28 -0
  31. package/src/Allocation_Optimization/density_groups/Adaptive_Density_Group_Thresholds.js +23 -0
  32. package/src/Allocation_Optimization/density_groups/Container_Utilization.js +67 -0
  33. package/src/Allocation_Optimization/density_groups/Density_Group_Partitioner.js +74 -0
  34. package/src/Allocation_Optimization/density_groups/Density_Group_Scheduler.js +168 -0
  35. package/src/Allocation_Optimization/density_groups/Density_Group_Stock.js +49 -0
  36. package/src/Allocation_Optimization/density_groups/Density_Groups_Strategy.js +26 -0
  37. package/src/Allocation_Optimization/density_groups/Item_Density_Calculator.js +20 -0
  38. package/src/Allocation_Optimization/density_groups/Lock_Weight_Ahead_Release.js +75 -0
  39. package/src/Allocation_Optimization/exceptions/Invalid_Item_Amount_Exception.js +17 -0
  40. package/src/Allocation_Optimization/exceptions/No_Valid_Allocation_Exception.js +14 -0
  41. package/src/Allocation_Optimization/exceptions/Optimization_Infeasible_Exception.js +14 -0
  42. package/src/Allocation_Optimization/functions/Measure_Reader.js +20 -0
  43. package/src/Allocation_Optimization/functions/Weight_Getter/Measure_Cobination_Mode.js +25 -0
  44. package/src/Allocation_Optimization/functions/Weight_Getter/Measure_Cobination_Strategies.js +8 -0
  45. package/src/Allocation_Optimization/functions/Weight_Getter/Measure_Combination_Mode_Checkers.js +70 -0
  46. package/src/Allocation_Optimization/functions/Weight_Getter/Translation.js +22 -0
  47. package/src/Allocation_Optimization/functions/Weight_Getter/Variable_Weight_Getter.js +85 -0
  48. package/src/Allocation_Optimization/functions/Weight_Getter/constants.js +16 -0
  49. package/src/Allocation_Optimization/functions/measure_to_optimize.js +6 -0
  50. package/src/Allocation_Optimization/item_consumption_heuristic/Capacity_Bias_Item_Order.js +76 -0
  51. package/src/Allocation_Optimization/item_consumption_heuristic/Choose_Item_Heuristic_Context.js +63 -0
  52. package/src/Allocation_Optimization/item_consumption_heuristic/Item_Chooser.js +159 -0
  53. package/src/Allocation_Optimization/item_consumption_heuristic/Item_For_Slot_Chooser.js +49 -0
  54. package/src/Allocation_Optimization/item_consumption_heuristic/Slot_Compatible_Items_Finder.js +88 -0
  55. package/src/Allocation_Optimization/item_consumption_heuristic/Slots_Items_Assigner.js +182 -0
  56. package/src/Allocation_Optimization/item_consumption_heuristic/Stack_Slot_Calculator.js +87 -0
  57. package/src/Allocation_Optimization/item_consumption_heuristic/Weight_Slot_Distribution.js +72 -0
  58. package/src/Allocation_Optimization/item_consumption_heuristic/exceptions/Empty_Slot_Exception.js +17 -0
  59. package/src/Allocation_Optimization/item_consumption_heuristic/exceptions/Item_Taller_Than_Limit_Exception.js +21 -0
  60. package/src/Allocation_Optimization/item_consumption_heuristic/exceptions/No_Available_Items_Exception.js +14 -0
  61. package/src/Allocation_Optimization/item_consumption_heuristic/exceptions/No_Slots_For_Items_Exception.js +14 -0
  62. package/src/Allocation_Optimization/lp_model/Block_Weight_Calculator.js +31 -0
  63. package/src/Allocation_Optimization/lp_model/LP_Data_Processor.js +42 -0
  64. package/src/Allocation_Optimization/lp_model/LP_Item_Slot_Assignment.js +93 -0
  65. package/src/Allocation_Optimization/lp_model/LP_Result_Mapper.js +47 -0
  66. package/src/Allocation_Optimization/lp_model/model_builder/Dimension_Range_Helper.js +49 -0
  67. package/src/Allocation_Optimization/lp_model/model_builder/Item_Assignment_Variables.js +133 -0
  68. package/src/Allocation_Optimization/lp_model/model_builder/LP_Model_Builder.js +132 -0
  69. package/src/Allocation_Optimization/lp_model/model_builder/exceptions/Missing_Item_Stock_Exception.js +18 -0
  70. package/src/Allocation_Optimization/lp_model/model_builder/goal_function/Goal_Function_Creator.js +83 -0
  71. package/src/Allocation_Optimization/lp_model/model_builder/item_dimension_hashes.js +31 -0
  72. package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Block_Item_Amount_Restriction.js +53 -0
  73. package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Coherence_Restriction.js +65 -0
  74. package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Container_Supported_Weight_Restriction.js +42 -0
  75. package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Relational_Exact_Pass_Amount_Restriction.js +62 -0
  76. package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Relational_Group_Restriction.js +97 -0
  77. package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Single_Item_Type_Restriction.js +79 -0
  78. package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Space_Restriction.js +47 -0
  79. package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Unavailable_Block_Restriction.js +27 -0
  80. package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Uniform_Block_Measure_Restriction.js +92 -0
  81. package/src/Allocation_Optimization/next_group_id_after_preloaded.js +30 -0
  82. package/src/Allocation_Optimization/preferential_blocks/Preferential_Block_Identifier.js +74 -0
  83. package/src/Allocation_Optimization/preferential_blocks/key_item/Key_Item_Mapper.js +49 -0
  84. package/src/Allocation_Optimization/preferential_blocks/key_item/rules/Almost_Unique_Item.js +31 -0
  85. package/src/Allocation_Optimization/preferential_blocks/key_item/rules/Cant_Stack_It_Self.js +68 -0
  86. package/src/Allocation_Optimization/preferential_blocks/key_item/rules/Rule_Interface.js +26 -0
  87. package/src/Allocation_Optimization/tie_ratio/Tie_Ratio_Intercalation_State.js +49 -0
  88. package/src/Allocation_Optimization/tie_ratio/Tie_Ratio_Orientation_Filter.js +33 -0
  89. package/src/Allocation_Optimization/tie_ratio/Tie_Ratio_Vertical_Stack_Filter.js +20 -0
  90. package/src/Allocation_Optimization/tie_ratio/collect_tie_ratio_orientations_below_footprint.js +64 -0
  91. package/src/Allocation_Optimization/tie_ratio/filter_blocks_by_orientation.js +17 -0
  92. package/src/Allocation_Optimization/tie_ratio/find_orientation_below_space.js +77 -0
  93. package/src/Allocation_Optimization/tie_ratio/loose_on_block/allocated_item_penetrates_any.js +31 -0
  94. package/src/Allocation_Optimization/tie_ratio/loose_on_block/apply_loose_placement_to_allocated_item.js +94 -0
  95. package/src/Allocation_Optimization/tie_ratio/loose_on_block/axis_overlap_length.js +16 -0
  96. package/src/Allocation_Optimization/tie_ratio/loose_on_block/block_local_origin.js +18 -0
  97. package/src/Allocation_Optimization/tie_ratio/loose_on_block/box_fits_inside_container.js +39 -0
  98. package/src/Allocation_Optimization/tie_ratio/loose_on_block/build_allocated_item_at_placement.js +18 -0
  99. package/src/Allocation_Optimization/tie_ratio/loose_on_block/build_placement_on_generic_supporter.js +64 -0
  100. package/src/Allocation_Optimization/tie_ratio/loose_on_block/build_slot_grid_from_cluster.js +66 -0
  101. package/src/Allocation_Optimization/tie_ratio/loose_on_block/compare_group_ids.js +20 -0
  102. package/src/Allocation_Optimization/tie_ratio/loose_on_block/container_with_pending_wall_items.js +26 -0
  103. package/src/Allocation_Optimization/tie_ratio/loose_on_block/empty_space_is_on_floor.js +16 -0
  104. package/src/Allocation_Optimization/tie_ratio/loose_on_block/finalize_loose_item_placement.js +58 -0
  105. package/src/Allocation_Optimization/tie_ratio/loose_on_block/find_best_generic_supporter_placement.js +58 -0
  106. package/src/Allocation_Optimization/tie_ratio/loose_on_block/find_next_free_slot_index.js +119 -0
  107. package/src/Allocation_Optimization/tie_ratio/loose_on_block/find_supporter_directly_below.js +51 -0
  108. package/src/Allocation_Optimization/tie_ratio/loose_on_block/find_tie_ratio_supporter_cluster.js +57 -0
  109. package/src/Allocation_Optimization/tie_ratio/loose_on_block/footprint_xz_overlap_area.js +26 -0
  110. package/src/Allocation_Optimization/tie_ratio/loose_on_block/item_fits_supporter_slot.js +22 -0
  111. package/src/Allocation_Optimization/tie_ratio/loose_on_block/loose_footprint_region_from_options.js +24 -0
  112. package/src/Allocation_Optimization/tie_ratio/loose_on_block/loose_item_fits_inside_container.js +21 -0
  113. package/src/Allocation_Optimization/tie_ratio/loose_on_block/loose_item_has_geometric_support.js +21 -0
  114. package/src/Allocation_Optimization/tie_ratio/loose_on_block/loose_on_block_slot_state.js +88 -0
  115. package/src/Allocation_Optimization/tie_ratio/loose_on_block/placement_coords_fit_inside_container.js +34 -0
  116. package/src/Allocation_Optimization/tie_ratio/loose_on_block/read_empilhar_area_igual_from_allocation_item.js +12 -0
  117. package/src/Allocation_Optimization/tie_ratio/loose_on_block/realigned_loose_geometry_gates.js +25 -0
  118. package/src/Allocation_Optimization/tie_ratio/loose_on_block/resolve_loose_on_generic_supporter.js +65 -0
  119. package/src/Allocation_Optimization/tie_ratio/loose_on_block/resolve_loose_placement_position.js +68 -0
  120. package/src/Allocation_Optimization/tie_ratio/loose_on_block/resolve_placement_y_at_slot.js +45 -0
  121. package/src/Allocation_Optimization/tie_ratio/loose_on_block/resolve_without_tie_ratio_cluster.js +79 -0
  122. package/src/Allocation_Optimization/tie_ratio/loose_on_block/select_tie_ratio_slot_placement.js +84 -0
  123. package/src/Allocation_Optimization/tie_ratio/loose_on_block/slot_footprint_collision.js +105 -0
  124. package/src/Allocation_Optimization/tie_ratio/loose_on_block/tie_ratio_cluster_selection.js +119 -0
  125. package/src/Allocation_Optimization/tie_ratio/loose_on_block/tie_ratio_footprint_overlap.js +56 -0
  126. package/src/Allocation_Optimization/tie_ratio/loose_on_block/tie_ratio_placement_plane.js +109 -0
  127. package/src/Allocation_Optimization/tie_ratio/loose_on_block/tie_ratio_supporter_predicate.js +23 -0
  128. package/src/Allocation_Optimization/tie_ratio/loose_on_block/try_tie_ratio_slot_placement.js +62 -0
  129. package/src/Allocation_Optimization/tie_ratio/snap_stacked_items_to_floor_footprints.js +138 -0
  130. package/src/Allocation_Optimization/tie_ratio/supporters_by_top_y_index.js +78 -0
  131. package/src/Allocation_Optimization/tie_ratio/tie_ratio_orientation_below_empty_space.js +89 -0
  132. package/src/Allocation_Optimization/tie_ratio/tie_ratio_orientation_from_group.js +48 -0
  133. package/src/Block_Management.js +34 -0
  134. package/src/Blocks_Preparation/Cube_Map_Function.js +27 -0
  135. package/src/Blocks_Wall_Allocation.js +3 -0
  136. package/src/IO/Answer_Status.js +4 -0
  137. package/src/IO/Output_Builder.js +35 -0
  138. package/src/IO/count_allocated_items.js +31 -0
  139. package/src/IO/create_error_response.js +62 -0
  140. package/src/IO/format_allocation_error_message.js +25 -0
  141. package/src/Item_Continuation_Lock.js +129 -0
  142. package/src/Item_Picking_Continuity.js +41 -0
  143. package/src/allocation_flow/chooser_session_state.js +21 -0
  144. package/src/allocation_flow/compound_probe_fallback.js +17 -0
  145. package/src/allocation_flow/container_remaining_capacity.js +23 -0
  146. package/src/allocation_flow/density_group_item_filter.js +31 -0
  147. package/src/allocation_flow/effective_item_fingerprint.js +14 -0
  148. package/src/allocation_flow/item_continuation_lock_gate.js +38 -0
  149. package/src/allocation_flow/no_space_left_recovery.js +48 -0
  150. package/src/allocation_flow/run_allocation_iteration.js +155 -0
  151. package/src/allocation_flow/space_skip_state.js +91 -0
  152. package/src/allocation_flow/try_no_space_left_recovery.js +50 -0
  153. package/src/exceptions/Invalid_Parameter_Exception.js +17 -0
  154. package/src/exceptions/Relational_Allocation_Incomplete_Exception.js +24 -0
  155. package/src/exceptions/Relational_Colocation_Violation_Exception.js +23 -0
  156. package/src/exceptions/Relational_Config_Mismatch_Exception.js +17 -0
  157. package/src/exceptions/There_Is_No_Block_Options_To_Allocate_Exception.js +14 -0
  158. package/src/index.js +6 -0
  159. package/src/input_preparation/Block_Formatter.js +179 -0
  160. package/src/input_preparation/Input_Creator.js +76 -0
  161. package/src/input_preparation/Input_State_Preparation.js +47 -0
  162. package/src/input_preparation/State_Builder.js +27 -0
  163. package/src/input_preparation/block_formatter/align_flush_axis_config.js +36 -0
  164. package/src/input_preparation/block_formatter/align_flush_axis_single_round.js +112 -0
  165. package/src/input_preparation/block_formatter/align_flush_stacked_slots.js +67 -0
  166. package/src/input_preparation/block_formatter/overlapped_slots.js +24 -0
  167. package/src/input_preparation/block_formatter/parallelepiped_shell.js +38 -0
  168. package/src/input_preparation/block_formatter/rectangle_coverage.js +112 -0
  169. package/src/input_preparation/block_formatter/shell_face_coverage.js +64 -0
  170. package/src/input_preparation/block_formatter/shell_snap_convergence.js +104 -0
  171. package/src/input_preparation/block_preparation/Block_Data_To_Object_Transformer.js +57 -0
  172. package/src/input_preparation/block_preparation/Block_Module_Name.js +17 -0
  173. package/src/input_preparation/block_preparation/Blocks_Creator.js +101 -0
  174. package/src/input_preparation/block_preparation/Blocksmith.js +19 -0
  175. package/src/input_preparation/block_preparation/block_modules/create_block_candidates.js +41 -0
  176. package/src/input_preparation/block_preparation/block_modules/manual_blocks.js +10 -0
  177. package/src/input_preparation/block_preparation/block_modules/module_registry.js +20 -0
  178. package/src/input_preparation/block_preparation/block_modules/run_creator.js +34 -0
  179. package/src/input_preparation/block_preparation/block_modules/single_item_blocks.js +12 -0
  180. package/src/input_preparation/block_preparation/block_modules/spiral_blocks.js +12 -0
  181. package/src/input_preparation/block_preparation/block_modules/tie_ratio_blocks.js +12 -0
  182. package/src/input_preparation/block_preparation/block_modules/tower_blocks.js +12 -0
  183. package/src/input_preparation/block_preparation/exceptions/Failed_To_Create_Block_Exception.js +14 -0
  184. package/src/input_preparation/block_preparation/exceptions/Failed_To_Retrieve_Block_Exception.js +17 -0
  185. package/src/input_preparation/block_preparation/exceptions/Missing_Object_Store_Exception.js +10 -0
  186. package/src/input_preparation/block_preparation/exceptions/No_Blocks_Were_Created_Exception.js +14 -0
  187. package/src/input_preparation/block_preparation/input/Input_Creator.js +96 -0
  188. package/src/input_preparation/block_preparation/manual_blocks/Manual_Blocks.js +95 -0
  189. package/src/input_preparation/build_empty_space_finder_options.js +43 -0
  190. package/src/input_preparation/item_preparation/Items_Reader.js +27 -0
  191. package/src/input_preparation/min_extents_from_items.js +29 -0
  192. package/src/input_preparation/stackability_index/Blocks_Stackability_Index_Calculator.js +58 -0
  193. package/src/input_preparation/stackability_index/Slots_Stackability_index_Calculator.js +28 -0
  194. package/src/input_preparation/stackability_index/Stackability_Input_Creator.js +27 -0
  195. package/src/input_preparation/stackability_index/stackability_index_pop_stack.js +81 -0
  196. package/src/input_preparation/stacking_constraints/Weight_Stacking_Validation.js +15 -0
  197. package/src/lp_optimizer_result_status.js +20 -0
  198. package/src/messages/Allocator_Message.js +42 -0
  199. package/src/messages/resolve_error_message_entry.js +57 -0
  200. package/src/models/Allocated_Item.js +136 -0
  201. package/src/models/Allocation_Item.js +219 -0
  202. package/src/models/Block.js +198 -0
  203. package/src/models/Cargo_Profile.js +418 -0
  204. package/src/models/Preloaded_Allocated_Item.js +132 -0
  205. package/src/models/Slot.js +67 -0
  206. package/src/models/Stacking_Rules.js +58 -0
  207. package/src/models/auxiliaryFunctions/Available_Block_Module_List_Creator.js +9 -0
  208. package/src/models/auxiliaryFunctions/Measure_Translator.js +24 -0
  209. package/src/models/auxiliaryFunctions/item_json_reader.js +44 -0
  210. package/src/models/item_json_reader.js +71 -0
  211. package/src/models/placed_item_record.js +70 -0
  212. package/src/models/preloaded_rotation_helpers.js +38 -0
  213. package/src/models/slots_have_same_measure.js +45 -0
  214. package/src/models/transport/Container.js +162 -0
  215. package/src/models/transport/Transport.js +62 -0
  216. package/src/models/transport/build_stacking_feasibility_checker.js +64 -0
  217. package/src/models/transport/container_stacking_checkpoint.js +42 -0
  218. package/src/models/transport/factory/Container_Factory.js +46 -0
  219. package/src/models/transport/factory/Corner_Casting_Factory.js +62 -0
  220. package/src/models/transport/factory/Previously_Allocated_Item_Factory.js +28 -0
  221. package/src/models/transport/factory/Transport_Factory.js +13 -0
  222. package/src/models/transport/items_for_empty_space_finder.js +91 -0
  223. package/src/models/transport/resolve_container_stacking_inputs.js +23 -0
  224. package/src/models/transport/stacking_input_from_wire.js +58 -0
  225. package/src/optimizer_connection_errors.js +50 -0
  226. package/src/relational/Relational_Error_Codes.js +7 -0
  227. package/src/relational/finalize_relational_allocation.js +20 -0
  228. package/src/relational/has_relational_items.js +11 -0
  229. package/src/relational/is_relational_error_code.js +15 -0
  230. package/src/relational/resolve_relational_container_sequences.js +29 -0
  231. package/src/run_core_allocation.js +118 -0
  232. package/src/space_and_block_chooser/Space_And_Blocks_Chooser.js +115 -0
  233. package/src/space_and_block_chooser/blocks_filters/Block_Filter_Interface.js +19 -0
  234. package/src/space_and_block_chooser/blocks_filters/Filter_Runner.js +46 -0
  235. package/src/space_and_block_chooser/blocks_filters/initial_blocks_filter/Block_With_Overlapped_Slots_Filter.js +14 -0
  236. package/src/space_and_block_chooser/blocks_filters/initial_blocks_filter/Initial_Blocks_Filter_List.js +19 -0
  237. package/src/space_and_block_chooser/blocks_filters/pos_selection_filters/Blocks_Bigger_Than_Space_Filter.js +17 -0
  238. package/src/space_and_block_chooser/blocks_filters/pos_selection_filters/Post_Selection_Filter_List.js +9 -0
  239. package/src/space_and_block_chooser/blocks_filters/pre_selection_filter/Insuficient_Items_Filter.js +81 -0
  240. package/src/space_and_block_chooser/blocks_filters/pre_selection_filter/Pre_Selection_Filter_List.js +8 -0
  241. package/src/space_and_block_chooser/blocks_filters/pre_selection_filter/max_tower_height/Blocks_Lower_Than_Max_Tower_Height.js +23 -0
  242. package/src/space_and_block_chooser/blocks_filters/pre_selection_filter/max_tower_height/Max_Tower_Height.js +82 -0
  243. package/src/space_and_block_chooser/build_allocated_item_snapshots.js +19 -0
  244. package/src/space_and_block_chooser/compound_first_empty_space_branch.js +61 -0
  245. package/src/space_and_block_chooser/compound_first_with_leftover_fill.js +142 -0
  246. package/src/space_and_block_chooser/compound_first_without_leftover_fill.js +56 -0
  247. package/src/space_and_block_chooser/empty_spaces_where_post_selection_keeps_blocks.js +83 -0
  248. package/src/space_and_block_chooser/exceptions/Invalid_Space_To_Allocate_Exception.js +14 -0
  249. package/src/space_and_block_chooser/leftover_space_memory.js +113 -0
  250. package/src/space_and_block_chooser/leftover_unitary_blocks.js +153 -0
  251. package/src/space_and_block_chooser/leftover_unitary_empty_spaces.js +135 -0
  252. package/src/space_and_block_chooser/probe_set_pool.js +35 -0
  253. package/src/space_and_block_chooser/run_space_and_block_selection_attempt.js +88 -0
  254. package/src/tools/Array_Validator.js +6 -0
  255. package/src/tools/Clone.js +27 -0
  256. package/src/tools/Hash.js +8 -0
  257. package/src/tools/Rounder.js +5 -0
  258. package/src/tools/String_To_Boolean.js +12 -0
  259. package/src/tools/cargo_profile/Cargo_Profile_Field_Value_Resolver.js +44 -0
  260. package/src/tools/compact_items_with_stock.js +9 -0
  261. package/src/tools/mm_to_allocation_domain.js +14 -0
  262. package/src/tracing/Allocation_Tracer.js +52 -0
  263. package/src/tracing/Trace_Context.js +18 -0
  264. package/src/tracing/trace_outcome.js +18 -0
  265. package/src/tracing/traced_step.js +57 -0
  266. package/src/validation/Item_Continuation_Lock_Flag.js +52 -0
  267. package/src/validation/Item_Validation.js +29 -0
  268. package/src/validation/Relational_Colocation_Validator.js +60 -0
  269. package/src/validation/Relational_Completeness_Validator.js +146 -0
  270. package/src/validation/Relational_Continuation_Lock_Validation.js +37 -0
  271. package/src/validation/Relational_Proportional_Normalizer.js +194 -0
  272. package/src/validation/Validation.js +9 -0
  273. package/src/validation/Validation_Runner.js +20 -0
  274. package/src/validation/exceptions/Invalid_Block_Module_Config_Exception.js +14 -0
  275. package/src/validation/exceptions/Invalid_Input_Exception.js +14 -0
  276. package/src/validation/exceptions/Invalid_Input_Type_Exception.js +14 -0
  277. package/src/validation/schemas/allocated_item_schema.js +18 -0
  278. package/src/validation/schemas/allocation_request_schema.js +178 -0
  279. package/src/validation/schemas/container_row_schema.js +16 -0
  280. package/src/validation/schemas/item_schema.js +60 -0
  281. package/src/validation/schemas/transport_env_schema.js +19 -0
  282. package/src/validation/validate_block_module_config.js +147 -0
@@ -0,0 +1,53 @@
1
+ const create_hash = require('../../../../tools/Hash')
2
+ const { VariableType, create_variable, create_restriction } = require('@jetta/lp-framework')
3
+ const create_item_assignment_variables = require('../Item_Assignment_Variables')
4
+ const read_stock = create_item_assignment_variables.read_stock
5
+
6
+ /**
7
+ * Creates restrictions that assign compatible item stock to block slot shapes
8
+ * while respecting item availability.
9
+ * @param {object[]} block_list - An array of Block objects.
10
+ * @param {object[]} item_list - An array of Item objects.
11
+ * @param {{slot_demand_list: Array, variables_by_item: Map<string, string[]>, id_to_stock_map: Map<string, number>}} [item_assignment_context] - Precomputed
12
+ * assignment graph from create_item_assignment_variables; when omitted, it is computed from block_list and item_list.
13
+ * @returns {Restriction[]} An array of LP restrictions.
14
+ */
15
+ module.exports = function create_block_item_amount_restriction(block_list, item_list, item_assignment_context)
16
+ {
17
+ const bundle = item_assignment_context ?? create_item_assignment_variables(block_list, item_list)
18
+ const { slot_demand_list, variables_by_item, id_to_stock_map } = bundle
19
+ const restriction_list = []
20
+ for (const slot_demand of slot_demand_list)
21
+ {
22
+ restriction_list.push(build_slot_demand_restriction(slot_demand))
23
+ }
24
+ restriction_list.push(...build_item_stock_restrictions(variables_by_item, id_to_stock_map))
25
+ return restriction_list
26
+ }
27
+
28
+ function build_slot_demand_restriction(slot_demand)
29
+ {
30
+ const { block_id, slot_hash, required_amount, compatibility_list } = slot_demand
31
+ const name = `block_item_demand_${create_hash(`${block_id};${slot_hash}`)}`
32
+ const variable_list = compatibility_list.map(
33
+ entry => create_variable(entry.variable_name, 1, VariableType.INTEGER)
34
+ )
35
+ variable_list.push(create_variable(block_id, -required_amount, VariableType.INTEGER))
36
+ return create_restriction(name, variable_list, {lower_limit: 0, upper_limit: 0})
37
+ }
38
+
39
+ function build_item_stock_restrictions(variables_by_item, id_to_stock_map)
40
+ {
41
+ const restriction_list = []
42
+ let count = 0
43
+ for (const [item_id, variable_name_list] of variables_by_item.entries())
44
+ {
45
+ const total_stock = read_stock(id_to_stock_map, item_id)
46
+ const variable_list = variable_name_list.map(
47
+ name => create_variable(name, 1, VariableType.INTEGER)
48
+ )
49
+ const name = `max_item_per_block_${item_id}-${++count}`
50
+ restriction_list.push(create_restriction(name, variable_list, {lower_limit: 0, upper_limit: total_stock}))
51
+ }
52
+ return restriction_list
53
+ }
@@ -0,0 +1,65 @@
1
+ const { VariableType, create_restriction, create_variable } = require('@jetta/lp-framework')
2
+ const { get_dimension_range } = require('../Dimension_Range_Helper')
3
+
4
+ /**
5
+ * Builds LP restrictions that tie penalty variables to block usage per dimension range (for uniformity penalty).
6
+ * @param {Array<{ name: string }>} penalty_var_list - List of penalty variables (names like "used_penalty_range_<range_id>").
7
+ * @param {Array<object>} block_list - List of blocks; each must have get_id() and match get_dimension_range() for filtering.
8
+ * @returns {Array<import('@jetta/lp-framework').Restriction>} List of coherence restrictions (binary check, upper, and lower per range).
9
+ */
10
+ function create_coherence_restrictions(penalty_var_list, block_list)
11
+ {
12
+ const size = penalty_var_list.length
13
+ const restriction_list = []
14
+
15
+ for (let index = 0; index < size; index++)
16
+ {
17
+ const penalty_var = penalty_var_list[index]
18
+ const var_name = penalty_var.name
19
+ const splitted_var_name = var_name.split('_')
20
+ const range_id = Number(splitted_var_name[splitted_var_name.length - 1])
21
+ if (Number.isNaN(range_id))
22
+ {
23
+ continue
24
+ }
25
+ const blocks_in_range = block_list.filter(block => get_dimension_range(block) === range_id)
26
+ const sum_block_vars = blocks_in_range.map(block => create_variable(block.get_id(), 1, VariableType.INTEGER))
27
+ const variable = create_variable(var_name, 1, VariableType.INTEGER)
28
+ const name = `binary_check_${var_name}`
29
+ const restriction = create_restriction(name, [variable], {lower_limit: 0, upper_limit: 1})
30
+ const upper = create_upper_coherence_restriction(range_id, var_name, sum_block_vars)
31
+ const lower = create_lower_coherence_restriction(range_id, var_name, sum_block_vars)
32
+ restriction_list.push(...[upper, lower, restriction])
33
+ }
34
+
35
+ return restriction_list
36
+ }
37
+
38
+ module.exports = create_coherence_restrictions
39
+
40
+ /**
41
+ * @param {number} range_id - Dimension range id.
42
+ * @param {string} penalty_var_name - Penalty variable name.
43
+ * @param {Array<object>} sum_block_vars - Variables for blocks in this range.
44
+ * @returns {import('@jetta/lp-framework').Restriction}
45
+ */
46
+ function create_upper_coherence_restriction(range_id, penalty_var_name, sum_block_vars)
47
+ {
48
+ const M = 10000
49
+ const variable_list = [...sum_block_vars, create_variable(penalty_var_name, -M, VariableType.INTEGER)]
50
+ const name = `pen_coherence_upper_${range_id}`
51
+ return create_restriction(name, variable_list, {lower_limit: 0, upper_limit: 0})
52
+ }
53
+
54
+ /**
55
+ * @param {number} range_id - Dimension range id.
56
+ * @param {string} penalty_var_name - Penalty variable name.
57
+ * @param {Array<object>} sum_block_vars - Variables for blocks in this range.
58
+ * @returns {import('@jetta/lp-framework').Restriction}
59
+ */
60
+ function create_lower_coherence_restriction(range_id, penalty_var_name, sum_block_vars)
61
+ {
62
+ const variable_list = [create_variable(penalty_var_name, 1, VariableType.INTEGER), ...sum_block_vars.map(v => create_variable(v.name, -1, VariableType.INTEGER))]
63
+ const name = `pen_coherence_lower_${range_id}`
64
+ return create_restriction(name, variable_list, {lower_limit: 0, upper_limit: 0})
65
+ }
@@ -0,0 +1,42 @@
1
+ const { VariableType, create_variable, create_restriction } = require('@jetta/lp-framework')
2
+ const {
3
+ get_dimension_to_max_weight_map,
4
+ calculate_block_potential_weight
5
+ } = require('../../../Block_Potential_Weight')
6
+
7
+ /**
8
+ * Creates a single LP restriction to ensure the total weight of items in the chosen blocks
9
+ * does not exceed the container's supported weight.
10
+ * @param {object} container - The container object, with a supported_weight() method.
11
+ * @param {object[]} block_list - An array of Block objects.
12
+ * @param {object[]} item_list - An array of Item objects.
13
+ * @returns {Restriction[]} An array containing the single weight restriction.
14
+ */
15
+ module.exports = function create_container_supported_weight_restriction(container, block_list, item_list)
16
+ {
17
+ const dimension_to_max_weight_map = get_dimension_to_max_weight_map(item_list)
18
+ const variable_list = []
19
+
20
+ for (const block of block_list)
21
+ {
22
+ const block_potential_weight = calculate_block_potential_weight(block, dimension_to_max_weight_map)
23
+
24
+ if (block_potential_weight > 0)
25
+ {
26
+ variable_list.push(create_variable(block.get_id(), block_potential_weight, VariableType.INTEGER))
27
+ }
28
+ }
29
+
30
+ if (variable_list.length === 0)
31
+ {
32
+ return []
33
+ }
34
+
35
+ const supported_weight = typeof container.supported_weight === 'function'
36
+ ? container.supported_weight()
37
+ : container.supported_weight
38
+
39
+ const name = 'container_supported_weight'
40
+ const restriction = create_restriction(name, variable_list, {lower_limit: 0, upper_limit: supported_weight})
41
+ return [restriction]
42
+ }
@@ -0,0 +1,62 @@
1
+ const { VariableType, create_variable, create_restriction } = require('@jetta/lp-framework')
2
+ const Cargo_Profile = require('../../../../models/Cargo_Profile')
3
+ const create_item_assignment_variables = require('../Item_Assignment_Variables')
4
+ const has_relational_items = require('../../../../relational/has_relational_items')
5
+
6
+ const RELATIONAL_EXACT_PASS_PREFIX = 'relational_exact_pass_amount_'
7
+
8
+ /**
9
+ * Forces each relational item to allocate exactly its pass amount when enabled.
10
+ * @param {object[]} block_list
11
+ * @param {object[]} item_list
12
+ * @param {object} [item_assignment_context]
13
+ * @returns {Restriction[]}
14
+ */
15
+ module.exports = function create_relational_exact_pass_amount_restriction(
16
+ block_list,
17
+ item_list,
18
+ item_assignment_context
19
+ )
20
+ {
21
+ if (!Cargo_Profile.relational_lp_require_exact_pass_amount())
22
+ {
23
+ return []
24
+ }
25
+
26
+ if (!has_relational_items(item_list))
27
+ {
28
+ return []
29
+ }
30
+
31
+ const bundle = item_assignment_context ?? create_item_assignment_variables(block_list, item_list)
32
+ const { variables_by_item } = bundle
33
+ const restriction_list = []
34
+
35
+ for (const item of item_list)
36
+ {
37
+ if (!item.get_relational_group_id())
38
+ {
39
+ continue
40
+ }
41
+
42
+ const variable_name_list = variables_by_item.get(item.get_id()) || []
43
+ if (variable_name_list.length === 0)
44
+ {
45
+ continue
46
+ }
47
+
48
+ const variable_list = variable_name_list.map(
49
+ name => create_variable(name, 1, VariableType.INTEGER)
50
+ )
51
+ const name = `${RELATIONAL_EXACT_PASS_PREFIX}${item.get_id()}`
52
+ const amount = item.get_amount()
53
+ restriction_list.push(create_restriction(name, variable_list, {
54
+ lower_limit: amount,
55
+ upper_limit: amount
56
+ }))
57
+ }
58
+
59
+ return restriction_list
60
+ }
61
+
62
+ module.exports.RELATIONAL_EXACT_PASS_PREFIX = RELATIONAL_EXACT_PASS_PREFIX
@@ -0,0 +1,97 @@
1
+ const { VariableType, create_variable, create_restriction } = require('@jetta/lp-framework')
2
+ const Cargo_Profile = require('../../../../models/Cargo_Profile')
3
+ const create_item_assignment_variables = require('../Item_Assignment_Variables')
4
+
5
+ const RELATIONAL_GROUP_MULTIPLE_PREFIX = 'relational_group_multiple_'
6
+ const RELATIONAL_GROUP_RATIO_PREFIX = 'relational_group_ratio_'
7
+
8
+ /**
9
+ * Builds LP restrictions that keep each relational group on proportional integer multiples.
10
+ * Gated by Cargo_Profile.enforce_relational_group_co_location().
11
+ * @param {object[]} block_list
12
+ * @param {object[]} item_list
13
+ * @param {object} [item_assignment_context]
14
+ * @returns {Restriction[]}
15
+ */
16
+ module.exports = function create_relational_group_restriction(block_list, item_list, item_assignment_context)
17
+ {
18
+ if (!Cargo_Profile.enforce_relational_group_co_location())
19
+ {
20
+ return []
21
+ }
22
+
23
+ const bundle = item_assignment_context ?? create_item_assignment_variables(block_list, item_list)
24
+ const { variables_by_item } = bundle
25
+ const groups = build_relational_groups(item_list)
26
+
27
+ if (groups.size === 0)
28
+ {
29
+ return []
30
+ }
31
+
32
+ const restriction_list = []
33
+
34
+ for (const [group_id, group_items] of groups.entries())
35
+ {
36
+ restriction_list.push(...build_group_restrictions(group_id, group_items, variables_by_item))
37
+ }
38
+
39
+ return restriction_list
40
+ }
41
+
42
+ module.exports.RELATIONAL_GROUP_MULTIPLE_PREFIX = RELATIONAL_GROUP_MULTIPLE_PREFIX
43
+ module.exports.RELATIONAL_GROUP_RATIO_PREFIX = RELATIONAL_GROUP_RATIO_PREFIX
44
+
45
+ function build_relational_groups(item_list)
46
+ {
47
+ const groups = new Map()
48
+
49
+ for (const item of item_list)
50
+ {
51
+ const group_id = item.get_relational_group_id()
52
+ if (!group_id)
53
+ {
54
+ continue
55
+ }
56
+
57
+ if (!groups.has(group_id))
58
+ {
59
+ groups.set(group_id, [])
60
+ }
61
+ groups.get(group_id).push(item)
62
+ }
63
+
64
+ return groups
65
+ }
66
+
67
+ function build_group_restrictions(group_id, group_items, variables_by_item)
68
+ {
69
+ const restriction_list = []
70
+ const multiple_name = `${RELATIONAL_GROUP_MULTIPLE_PREFIX}${group_id}`
71
+ const anchor = group_items[0]
72
+ const anchor_vars = variables_by_item.get(anchor.get_id()) || []
73
+
74
+ if (anchor_vars.length === 0)
75
+ {
76
+ return []
77
+ }
78
+
79
+ for (const item of group_items)
80
+ {
81
+ const variable_name_list = variables_by_item.get(item.get_id()) || []
82
+ if (variable_name_list.length === 0)
83
+ {
84
+ continue
85
+ }
86
+
87
+ const ratio = item.get_relational_link_quantity()
88
+ const variable_list = variable_name_list.map(
89
+ name => create_variable(name, 1, VariableType.INTEGER)
90
+ )
91
+ variable_list.push(create_variable(multiple_name, -ratio, VariableType.INTEGER))
92
+ const name = `${RELATIONAL_GROUP_RATIO_PREFIX}${group_id}_${item.get_id()}`
93
+ restriction_list.push(create_restriction(name, variable_list, {lower_limit: 0, upper_limit: 0}))
94
+ }
95
+
96
+ return restriction_list
97
+ }
@@ -0,0 +1,79 @@
1
+ const { VariableType, create_variable, create_restriction } = require('@jetta/lp-framework')
2
+ const Cargo_Profile = require('../../../../models/Cargo_Profile')
3
+ const create_item_assignment_variables = require('../Item_Assignment_Variables')
4
+ const has_relational_items = require('../../../../relational/has_relational_items')
5
+ const read_stock = create_item_assignment_variables.read_stock
6
+
7
+ const SINGLE_ITEM_TYPE_INDICATOR_PREFIX = 'single_item_type_indicator_'
8
+ const SINGLE_ITEM_TYPE_COUPLING_PREFIX = 'single_item_type_coupling_'
9
+ const SINGLE_ITEM_TYPE_CAP_NAME = 'single_item_type_cap'
10
+
11
+ /**
12
+ * Builds restrictions that force at most one item type to have positive count
13
+ * across all chosen blocks, gated by Cargo_Profile.enforce_single_item_type().
14
+ * Skipped when enforce_relational_group_co_location() is on and item_list
15
+ * contains relational_group_id items (relational bundles need multiple SKUs).
16
+ *
17
+ * For each item i: y_i in {0, 1} and sum(assignment_vars(i)) - stock_i * y_i <= 0.
18
+ * Globally: sum_i y_i <= 1.
19
+ * @param {object[]} block_list - Block objects.
20
+ * @param {object[]} item_list - Item objects.
21
+ * @param {{slot_demand_list: Array, variables_by_item: Map<string, string[]>, id_to_stock_map: Map<string, number>}} [item_assignment_context] - Precomputed
22
+ * assignment graph from create_item_assignment_variables; when omitted, it is computed from block_list and item_list.
23
+ * @returns {Restriction[]} Empty when gated off or skipped for relational co-location; otherwise N coupling rows + 1 cap row.
24
+ */
25
+ module.exports = function create_single_item_type_restriction(block_list, item_list, item_assignment_context)
26
+ {
27
+ const enforce_single_item_type = Cargo_Profile.enforce_single_item_type()
28
+ const enforce_relational_co_location = Cargo_Profile.enforce_relational_group_co_location()
29
+ const relational_items_present = has_relational_items(item_list)
30
+ const skip_for_relational = enforce_relational_co_location && relational_items_present
31
+
32
+ if (!enforce_single_item_type || skip_for_relational)
33
+ {
34
+ return []
35
+ }
36
+ const bundle = item_assignment_context ?? create_item_assignment_variables(block_list, item_list)
37
+ const { variables_by_item, id_to_stock_map } = bundle
38
+ if (variables_by_item.size === 0)
39
+ {
40
+ return []
41
+ }
42
+ const coupling_restriction_list = build_coupling_restrictions(variables_by_item, id_to_stock_map)
43
+ const cap_restriction = build_cap_restriction(variables_by_item)
44
+ return [...coupling_restriction_list, cap_restriction]
45
+ }
46
+
47
+ module.exports.SINGLE_ITEM_TYPE_INDICATOR_PREFIX = SINGLE_ITEM_TYPE_INDICATOR_PREFIX
48
+ module.exports.SINGLE_ITEM_TYPE_COUPLING_PREFIX = SINGLE_ITEM_TYPE_COUPLING_PREFIX
49
+ module.exports.SINGLE_ITEM_TYPE_CAP_NAME = SINGLE_ITEM_TYPE_CAP_NAME
50
+
51
+ function build_coupling_restrictions(variables_by_item, id_to_stock_map)
52
+ {
53
+ const restriction_list = []
54
+ for (const [item_id, variable_name_list] of variables_by_item.entries())
55
+ {
56
+ const stock = read_stock(id_to_stock_map, item_id)
57
+ restriction_list.push(build_coupling_restriction(item_id, variable_name_list, stock))
58
+ }
59
+ return restriction_list
60
+ }
61
+
62
+ function build_coupling_restriction(item_id, variable_name_list, stock)
63
+ {
64
+ const indicator_name = `${SINGLE_ITEM_TYPE_INDICATOR_PREFIX}${item_id}`
65
+ const variable_list = variable_name_list.map(
66
+ name => create_variable(name, 1, VariableType.INTEGER)
67
+ )
68
+ variable_list.push(create_variable(indicator_name, -stock, VariableType.INTEGER))
69
+ const name = `${SINGLE_ITEM_TYPE_COUPLING_PREFIX}${item_id}`
70
+ return create_restriction(name, variable_list, {lower_limit: -stock, upper_limit: 0})
71
+ }
72
+
73
+ function build_cap_restriction(variables_by_item)
74
+ {
75
+ const variable_list = [...variables_by_item.keys()].map(item_id =>
76
+ create_variable(`${SINGLE_ITEM_TYPE_INDICATOR_PREFIX}${item_id}`, 1, VariableType.INTEGER)
77
+ )
78
+ return create_restriction(SINGLE_ITEM_TYPE_CAP_NAME, variable_list, {lower_limit: 0, upper_limit: 1})
79
+ }
@@ -0,0 +1,47 @@
1
+ const { VariableType, create_variable, create_restriction } = require('@jetta/lp-framework')
2
+
3
+ const measure_to_optimize = require('../../../functions/measure_to_optimize')
4
+ const { read_measure_to_be_optimized } = require('../../../functions/Measure_Reader')
5
+
6
+ /**
7
+ * Builds the space restriction: sum of block measures (by optimization dimension) must not exceed the given space.
8
+ * @param {object} empty_space - Space to allocate; must have length/width or get_length/get_width per measure config.
9
+ * @param {Array<object>} block_list - Blocks; each must have get_id() and the measure used by the optimizer.
10
+ * @returns {Array<import('@jetta/lp-framework').Restriction>} A single-element array containing the space restriction.
11
+ */
12
+ function create_space_restriction(empty_space, block_list)
13
+ {
14
+ const variable_list = create_variable_list(block_list)
15
+ const space_measure = get_measure(empty_space)
16
+ const name = 'space_restriction'
17
+ const restriction = create_restriction(name, variable_list, {lower_limit: 0, upper_limit: space_measure})
18
+ return [restriction]
19
+ }
20
+
21
+ module.exports = create_space_restriction
22
+
23
+ function create_variable_list(block_list)
24
+ {
25
+ return block_list.map(block =>
26
+ {
27
+ const measure = get_measure(block)
28
+ return create_variable(block.get_id(), measure, VariableType.INTEGER)
29
+ })
30
+ }
31
+
32
+ /**
33
+ * @param {object} obj - Object with length/width or get_length/get_width.
34
+ * @returns {number} Measure value for the current optimization dimension.
35
+ */
36
+ function get_measure(obj)
37
+ {
38
+ switch (read_measure_to_be_optimized())
39
+ {
40
+ case measure_to_optimize.LENGTH:
41
+ return obj.length !== undefined ? obj.length : obj.get_length()
42
+ case measure_to_optimize.WIDTH:
43
+ return obj.width !== undefined ? obj.width : obj.get_width()
44
+ default:
45
+ throw new Error('invalid measure identifier')
46
+ }
47
+ }
@@ -0,0 +1,27 @@
1
+ const { VariableType, create_variable, create_restriction } = require('@jetta/lp-framework')
2
+
3
+ /**
4
+ * Builds restrictions that cap the number of times each block can be used when it has an explicit max amount.
5
+ * @param {Array<object>} block_list - Blocks; each must have get_id().
6
+ * @param {object} block_amount_restrictions - Map of block id to maximum allowed amount (upper bound).
7
+ * @returns {Array<import('@jetta/lp-framework').Restriction>} One restriction per block that has an entry in block_amount_restrictions.
8
+ */
9
+ function create_block_restricted_to_0_restriction(block_list, block_amount_restrictions)
10
+ {
11
+ const restriction_list = []
12
+ for (const block of block_list)
13
+ {
14
+ const restrict_to = block_amount_restrictions[block.get_id()]
15
+ if (restrict_to !== undefined)
16
+ {
17
+ const variable = create_variable(block.get_id(), 1, VariableType.INTEGER)
18
+ const name = `block ${block.get_id()} is restricted to ${restrict_to}`
19
+ const restriction = create_restriction( name, [variable], {lower_limit: 0, upper_limit: restrict_to})
20
+ restriction_list.push(restriction)
21
+ }
22
+ }
23
+
24
+ return restriction_list
25
+ }
26
+
27
+ module.exports = create_block_restricted_to_0_restriction
@@ -0,0 +1,92 @@
1
+ const { VariableType, create_variable, create_restriction } = require('@jetta/lp-framework')
2
+ const Cargo_Profile = require('../../../../models/Cargo_Profile')
3
+ const { get_dimension_range } = require('../Dimension_Range_Helper')
4
+ const has_relational_items = require('../../../../relational/has_relational_items')
5
+
6
+ const UNIFORM_BLOCK_MEASURE_INDICATOR_PREFIX = 'uniform_block_measure_indicator_'
7
+ const UNIFORM_BLOCK_MEASURE_COUPLING_PREFIX = 'uniform_block_measure_coupling_'
8
+ const UNIFORM_BLOCK_MEASURE_CAP_NAME = 'uniform_block_measure_cap'
9
+ const BIG_M = 10000
10
+
11
+ /**
12
+ * Builds restrictions that force at most one orthogonal-dimension bucket across chosen blocks,
13
+ * gated by Cargo_Profile.enforce_uniform_block_measure().
14
+ * Skipped when relational co-location is enforced and relational items are present
15
+ * (same skip pattern as single-item-type), because ratio groups need differently sized
16
+ * unitary blocks in one wall.
17
+ *
18
+ * For each range r: sum(x_b for b in range) - M * y_r <= 0.
19
+ * Globally: sum_r y_r <= 1.
20
+ * @param {object[]} block_list - Block objects.
21
+ * @param {object[]} [item_list=[]] - Items for the relational skip check.
22
+ * @returns {import('@jetta/lp-framework').Restriction[]} Empty when the flag is off or skipped.
23
+ */
24
+ module.exports = function create_uniform_block_measure_restriction(block_list, item_list = [])
25
+ {
26
+ const enforce_uniform = Cargo_Profile.enforce_uniform_block_measure()
27
+ const enforce_relational_co_location = Cargo_Profile.enforce_relational_group_co_location()
28
+ const skip_for_relational = enforce_relational_co_location && has_relational_items(item_list)
29
+
30
+ if (!enforce_uniform || skip_for_relational)
31
+ {
32
+ return []
33
+ }
34
+ const blocks_by_range = group_blocks_by_dimension_range(block_list)
35
+ if (blocks_by_range.size === 0)
36
+ {
37
+ return []
38
+ }
39
+ const coupling_restriction_list = build_coupling_restrictions(blocks_by_range)
40
+ const cap_restriction = build_cap_restriction(blocks_by_range)
41
+ return [...coupling_restriction_list, cap_restriction]
42
+ }
43
+
44
+ module.exports.UNIFORM_BLOCK_MEASURE_INDICATOR_PREFIX = UNIFORM_BLOCK_MEASURE_INDICATOR_PREFIX
45
+ module.exports.UNIFORM_BLOCK_MEASURE_COUPLING_PREFIX = UNIFORM_BLOCK_MEASURE_COUPLING_PREFIX
46
+ module.exports.UNIFORM_BLOCK_MEASURE_CAP_NAME = UNIFORM_BLOCK_MEASURE_CAP_NAME
47
+
48
+ function group_blocks_by_dimension_range(block_list)
49
+ {
50
+ const blocks_by_range = new Map()
51
+ for (const block of block_list)
52
+ {
53
+ const range_id = get_dimension_range(block)
54
+ const blocks_in_range = blocks_by_range.get(range_id) ?? []
55
+ blocks_in_range.push(block)
56
+ blocks_by_range.set(range_id, blocks_in_range)
57
+ }
58
+ return blocks_by_range
59
+ }
60
+
61
+ function build_coupling_restrictions(blocks_by_range)
62
+ {
63
+ const restriction_list = []
64
+ for (const [range_id, blocks_in_range] of blocks_by_range.entries())
65
+ {
66
+ restriction_list.push(build_coupling_restriction(range_id, blocks_in_range))
67
+ }
68
+ return restriction_list
69
+ }
70
+
71
+ function build_coupling_restriction(range_id, blocks_in_range)
72
+ {
73
+ const indicator_name = `${UNIFORM_BLOCK_MEASURE_INDICATOR_PREFIX}${range_id}`
74
+ const block_variables = blocks_in_range.map(
75
+ block => create_variable(block.get_id(), 1, VariableType.INTEGER)
76
+ )
77
+ block_variables.push(create_variable(indicator_name, -BIG_M, VariableType.INTEGER))
78
+ const name = `${UNIFORM_BLOCK_MEASURE_COUPLING_PREFIX}${range_id}`
79
+ return create_restriction(name, block_variables, { lower_limit: -BIG_M, upper_limit: 0 })
80
+ }
81
+
82
+ function build_cap_restriction(blocks_by_range)
83
+ {
84
+ const variable_list = [...blocks_by_range.keys()].map(range_id =>
85
+ create_variable(`${UNIFORM_BLOCK_MEASURE_INDICATOR_PREFIX}${range_id}`, 1, VariableType.INTEGER)
86
+ )
87
+ return create_restriction(
88
+ UNIFORM_BLOCK_MEASURE_CAP_NAME,
89
+ variable_list,
90
+ { lower_limit: 0, upper_limit: 1 }
91
+ )
92
+ }
@@ -0,0 +1,30 @@
1
+ function numeric_group_id(item)
2
+ {
3
+ const item_group_id = item.get_group_id()
4
+ if (item_group_id === undefined || item_group_id === null)
5
+ {
6
+ return -1
7
+ }
8
+ const group_id = Number(item_group_id)
9
+ return Number.isFinite(group_id) ? group_id : -1
10
+ }
11
+
12
+ /**
13
+ * Keeps generated block group ids above preloaded numeric group ids.
14
+ * @param {object} container
15
+ * @param {number} current_next_group_id
16
+ * @returns {number}
17
+ */
18
+ function resolve_next_group_id(container, current_next_group_id)
19
+ {
20
+ if (typeof container.get_allocated_items !== 'function')
21
+ {
22
+ return current_next_group_id
23
+ }
24
+ const preloaded_group_ids = container.get_allocated_items()
25
+ .map(numeric_group_id)
26
+ const highest_group_id = Math.max(-1, ...preloaded_group_ids)
27
+ return Math.max(current_next_group_id, highest_group_id + 1)
28
+ }
29
+
30
+ module.exports = resolve_next_group_id
@@ -0,0 +1,74 @@
1
+ const Key_Item_Mapper = require('./key_item/Key_Item_Mapper')
2
+
3
+ /**
4
+ * @class Preferential_Block_Identifier
5
+ * @description Identifies and marks blocks that are considered "preferential"
6
+ * based on a set of key items. A block is preferential if it can perfectly fit at least one key item.
7
+ */
8
+ class Preferential_Block_Identifier
9
+ {
10
+ #key_items
11
+
12
+ /**
13
+ * @constructor
14
+ * @description Initializes the Preferential_Block_Identifier by identifying key items.
15
+ * @param {object} transport - The transport object (container) against which key items are filtered.
16
+ * @param {Array<JSON>} items_to_allocate - The list of items that need to be allocated.
17
+ */
18
+ constructor( transport, items_to_allocate, key_item_mapper = new Key_Item_Mapper() )
19
+ {
20
+ this.#key_items = key_item_mapper.filter_key_items(transport, items_to_allocate)
21
+ }
22
+
23
+ /**
24
+ * Checks if a given block can perfectly fit any of the key items.
25
+ * @param {object} block - The block to check.
26
+ * @returns {boolean} - True if the block fits a key item, false otherwise.
27
+ */
28
+ #block_fits_key_item(block)
29
+ {
30
+ const slots = block.get_slot_list()
31
+ for (const key_item of this.#key_items)
32
+ {
33
+ for (const slot of slots)
34
+ {
35
+ if (slot.some_rotation_fits_perfectly(key_item))
36
+ {
37
+ return true
38
+ }
39
+ }
40
+ }
41
+ return false
42
+ }
43
+
44
+ /**
45
+ * Iterates through a list of blocks and marks the ones that are preferential.
46
+ * @param {Array<object>} blocks - The list of blocks to evaluate.
47
+ */
48
+ mark_preferential_blocks(blocks)
49
+ {
50
+ let skip_all = true
51
+ for (const block of blocks)
52
+ {
53
+ if (block.get_slot_list().length > 1)
54
+ {
55
+ skip_all = false
56
+ break
57
+ }
58
+ }
59
+ if (skip_all)
60
+ {
61
+ return
62
+ }
63
+
64
+ for (const block of blocks)
65
+ {
66
+ if (block.get_slot_list().length > 1 && this.#block_fits_key_item(block))
67
+ {
68
+ block.set_preference()
69
+ }
70
+ }
71
+ }
72
+ }
73
+
74
+ module.exports = Preferential_Block_Identifier