@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.
- package/README.md +103 -2
- package/package.json +67 -5
- package/src/Allocation_Attempt.js +135 -0
- package/src/Allocation_Error_Handler.js +69 -0
- package/src/Allocation_Flow.js +162 -0
- package/src/Allocation_Optimization/Allocation_LP.js +150 -0
- package/src/Allocation_Optimization/Block_Allocator.js +129 -0
- package/src/Allocation_Optimization/Block_Layer_Order.js +50 -0
- package/src/Allocation_Optimization/Block_Potential_Weight.js +54 -0
- package/src/Allocation_Optimization/Chosen_Blocks_Stock_Cap.js +82 -0
- package/src/Allocation_Optimization/block_builder/Allocation_Item_Creator.js +37 -0
- package/src/Allocation_Optimization/block_builder/Block_Item_List_Validator.js +18 -0
- package/src/Allocation_Optimization/block_builder/Block_Wall_Builder.js +303 -0
- package/src/Allocation_Optimization/block_builder/Blocks_Builder.js +40 -0
- package/src/Allocation_Optimization/block_builder/Next_Block_Position.js +33 -0
- package/src/Allocation_Optimization/block_builder/Slot_Item_Assigner.js +45 -0
- package/src/Allocation_Optimization/block_builder/Stacking_Validation.js +30 -0
- package/src/Allocation_Optimization/block_builder/assert_tie_ratio_block_matches_orientation_below.js +44 -0
- package/src/Allocation_Optimization/block_builder/block_shape_stock.js +129 -0
- package/src/Allocation_Optimization/block_builder/exceptions/Empty_Block_Item_List_Exception.js +21 -0
- package/src/Allocation_Optimization/block_builder/exceptions/Invalid_Stacking_Exception.js +14 -0
- package/src/Allocation_Optimization/block_builder/exceptions/No_Suitable_Item_Exception.js +16 -0
- package/src/Allocation_Optimization/block_builder/exceptions/Restricted_Block_Exception.js +21 -0
- package/src/Allocation_Optimization/block_builder/should_omit_block_group_id.js +29 -0
- package/src/Allocation_Optimization/block_builder/snap_elevated_block_wall_items.js +34 -0
- package/src/Allocation_Optimization/block_builder/stacking_rules_input.js +52 -0
- package/src/Allocation_Optimization/cap_chosen_blocks_by_shape_stock.js +110 -0
- package/src/Allocation_Optimization/density_groups/Adaptive_Density_Group_Preparer.js +21 -0
- package/src/Allocation_Optimization/density_groups/Adaptive_Density_Group_Selector.js +55 -0
- package/src/Allocation_Optimization/density_groups/Adaptive_Density_Group_Threshold_Resolver.js +28 -0
- package/src/Allocation_Optimization/density_groups/Adaptive_Density_Group_Thresholds.js +23 -0
- package/src/Allocation_Optimization/density_groups/Container_Utilization.js +67 -0
- package/src/Allocation_Optimization/density_groups/Density_Group_Partitioner.js +74 -0
- package/src/Allocation_Optimization/density_groups/Density_Group_Scheduler.js +168 -0
- package/src/Allocation_Optimization/density_groups/Density_Group_Stock.js +49 -0
- package/src/Allocation_Optimization/density_groups/Density_Groups_Strategy.js +26 -0
- package/src/Allocation_Optimization/density_groups/Item_Density_Calculator.js +20 -0
- package/src/Allocation_Optimization/density_groups/Lock_Weight_Ahead_Release.js +75 -0
- package/src/Allocation_Optimization/exceptions/Invalid_Item_Amount_Exception.js +17 -0
- package/src/Allocation_Optimization/exceptions/No_Valid_Allocation_Exception.js +14 -0
- package/src/Allocation_Optimization/exceptions/Optimization_Infeasible_Exception.js +14 -0
- package/src/Allocation_Optimization/functions/Measure_Reader.js +20 -0
- package/src/Allocation_Optimization/functions/Weight_Getter/Measure_Cobination_Mode.js +25 -0
- package/src/Allocation_Optimization/functions/Weight_Getter/Measure_Cobination_Strategies.js +8 -0
- package/src/Allocation_Optimization/functions/Weight_Getter/Measure_Combination_Mode_Checkers.js +70 -0
- package/src/Allocation_Optimization/functions/Weight_Getter/Translation.js +22 -0
- package/src/Allocation_Optimization/functions/Weight_Getter/Variable_Weight_Getter.js +85 -0
- package/src/Allocation_Optimization/functions/Weight_Getter/constants.js +16 -0
- package/src/Allocation_Optimization/functions/measure_to_optimize.js +6 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/Capacity_Bias_Item_Order.js +76 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/Choose_Item_Heuristic_Context.js +63 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/Item_Chooser.js +159 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/Item_For_Slot_Chooser.js +49 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/Slot_Compatible_Items_Finder.js +88 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/Slots_Items_Assigner.js +182 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/Stack_Slot_Calculator.js +87 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/Weight_Slot_Distribution.js +72 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/exceptions/Empty_Slot_Exception.js +17 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/exceptions/Item_Taller_Than_Limit_Exception.js +21 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/exceptions/No_Available_Items_Exception.js +14 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/exceptions/No_Slots_For_Items_Exception.js +14 -0
- package/src/Allocation_Optimization/lp_model/Block_Weight_Calculator.js +31 -0
- package/src/Allocation_Optimization/lp_model/LP_Data_Processor.js +42 -0
- package/src/Allocation_Optimization/lp_model/LP_Item_Slot_Assignment.js +93 -0
- package/src/Allocation_Optimization/lp_model/LP_Result_Mapper.js +47 -0
- package/src/Allocation_Optimization/lp_model/model_builder/Dimension_Range_Helper.js +49 -0
- package/src/Allocation_Optimization/lp_model/model_builder/Item_Assignment_Variables.js +133 -0
- package/src/Allocation_Optimization/lp_model/model_builder/LP_Model_Builder.js +132 -0
- package/src/Allocation_Optimization/lp_model/model_builder/exceptions/Missing_Item_Stock_Exception.js +18 -0
- package/src/Allocation_Optimization/lp_model/model_builder/goal_function/Goal_Function_Creator.js +83 -0
- package/src/Allocation_Optimization/lp_model/model_builder/item_dimension_hashes.js +31 -0
- package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Block_Item_Amount_Restriction.js +53 -0
- package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Coherence_Restriction.js +65 -0
- package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Container_Supported_Weight_Restriction.js +42 -0
- package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Relational_Exact_Pass_Amount_Restriction.js +62 -0
- package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Relational_Group_Restriction.js +97 -0
- package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Single_Item_Type_Restriction.js +79 -0
- package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Space_Restriction.js +47 -0
- package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Unavailable_Block_Restriction.js +27 -0
- package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Uniform_Block_Measure_Restriction.js +92 -0
- package/src/Allocation_Optimization/next_group_id_after_preloaded.js +30 -0
- package/src/Allocation_Optimization/preferential_blocks/Preferential_Block_Identifier.js +74 -0
- package/src/Allocation_Optimization/preferential_blocks/key_item/Key_Item_Mapper.js +49 -0
- package/src/Allocation_Optimization/preferential_blocks/key_item/rules/Almost_Unique_Item.js +31 -0
- package/src/Allocation_Optimization/preferential_blocks/key_item/rules/Cant_Stack_It_Self.js +68 -0
- package/src/Allocation_Optimization/preferential_blocks/key_item/rules/Rule_Interface.js +26 -0
- package/src/Allocation_Optimization/tie_ratio/Tie_Ratio_Intercalation_State.js +49 -0
- package/src/Allocation_Optimization/tie_ratio/Tie_Ratio_Orientation_Filter.js +33 -0
- package/src/Allocation_Optimization/tie_ratio/Tie_Ratio_Vertical_Stack_Filter.js +20 -0
- package/src/Allocation_Optimization/tie_ratio/collect_tie_ratio_orientations_below_footprint.js +64 -0
- package/src/Allocation_Optimization/tie_ratio/filter_blocks_by_orientation.js +17 -0
- package/src/Allocation_Optimization/tie_ratio/find_orientation_below_space.js +77 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/allocated_item_penetrates_any.js +31 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/apply_loose_placement_to_allocated_item.js +94 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/axis_overlap_length.js +16 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/block_local_origin.js +18 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/box_fits_inside_container.js +39 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/build_allocated_item_at_placement.js +18 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/build_placement_on_generic_supporter.js +64 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/build_slot_grid_from_cluster.js +66 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/compare_group_ids.js +20 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/container_with_pending_wall_items.js +26 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/empty_space_is_on_floor.js +16 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/finalize_loose_item_placement.js +58 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/find_best_generic_supporter_placement.js +58 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/find_next_free_slot_index.js +119 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/find_supporter_directly_below.js +51 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/find_tie_ratio_supporter_cluster.js +57 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/footprint_xz_overlap_area.js +26 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/item_fits_supporter_slot.js +22 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/loose_footprint_region_from_options.js +24 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/loose_item_fits_inside_container.js +21 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/loose_item_has_geometric_support.js +21 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/loose_on_block_slot_state.js +88 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/placement_coords_fit_inside_container.js +34 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/read_empilhar_area_igual_from_allocation_item.js +12 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/realigned_loose_geometry_gates.js +25 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/resolve_loose_on_generic_supporter.js +65 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/resolve_loose_placement_position.js +68 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/resolve_placement_y_at_slot.js +45 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/resolve_without_tie_ratio_cluster.js +79 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/select_tie_ratio_slot_placement.js +84 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/slot_footprint_collision.js +105 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/tie_ratio_cluster_selection.js +119 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/tie_ratio_footprint_overlap.js +56 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/tie_ratio_placement_plane.js +109 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/tie_ratio_supporter_predicate.js +23 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/try_tie_ratio_slot_placement.js +62 -0
- package/src/Allocation_Optimization/tie_ratio/snap_stacked_items_to_floor_footprints.js +138 -0
- package/src/Allocation_Optimization/tie_ratio/supporters_by_top_y_index.js +78 -0
- package/src/Allocation_Optimization/tie_ratio/tie_ratio_orientation_below_empty_space.js +89 -0
- package/src/Allocation_Optimization/tie_ratio/tie_ratio_orientation_from_group.js +48 -0
- package/src/Block_Management.js +34 -0
- package/src/Blocks_Preparation/Cube_Map_Function.js +27 -0
- package/src/Blocks_Wall_Allocation.js +3 -0
- package/src/IO/Answer_Status.js +4 -0
- package/src/IO/Output_Builder.js +35 -0
- package/src/IO/count_allocated_items.js +31 -0
- package/src/IO/create_error_response.js +62 -0
- package/src/IO/format_allocation_error_message.js +25 -0
- package/src/Item_Continuation_Lock.js +129 -0
- package/src/Item_Picking_Continuity.js +41 -0
- package/src/allocation_flow/chooser_session_state.js +21 -0
- package/src/allocation_flow/compound_probe_fallback.js +17 -0
- package/src/allocation_flow/container_remaining_capacity.js +23 -0
- package/src/allocation_flow/density_group_item_filter.js +31 -0
- package/src/allocation_flow/effective_item_fingerprint.js +14 -0
- package/src/allocation_flow/item_continuation_lock_gate.js +38 -0
- package/src/allocation_flow/no_space_left_recovery.js +48 -0
- package/src/allocation_flow/run_allocation_iteration.js +155 -0
- package/src/allocation_flow/space_skip_state.js +91 -0
- package/src/allocation_flow/try_no_space_left_recovery.js +50 -0
- package/src/exceptions/Invalid_Parameter_Exception.js +17 -0
- package/src/exceptions/Relational_Allocation_Incomplete_Exception.js +24 -0
- package/src/exceptions/Relational_Colocation_Violation_Exception.js +23 -0
- package/src/exceptions/Relational_Config_Mismatch_Exception.js +17 -0
- package/src/exceptions/There_Is_No_Block_Options_To_Allocate_Exception.js +14 -0
- package/src/index.js +6 -0
- package/src/input_preparation/Block_Formatter.js +179 -0
- package/src/input_preparation/Input_Creator.js +76 -0
- package/src/input_preparation/Input_State_Preparation.js +47 -0
- package/src/input_preparation/State_Builder.js +27 -0
- package/src/input_preparation/block_formatter/align_flush_axis_config.js +36 -0
- package/src/input_preparation/block_formatter/align_flush_axis_single_round.js +112 -0
- package/src/input_preparation/block_formatter/align_flush_stacked_slots.js +67 -0
- package/src/input_preparation/block_formatter/overlapped_slots.js +24 -0
- package/src/input_preparation/block_formatter/parallelepiped_shell.js +38 -0
- package/src/input_preparation/block_formatter/rectangle_coverage.js +112 -0
- package/src/input_preparation/block_formatter/shell_face_coverage.js +64 -0
- package/src/input_preparation/block_formatter/shell_snap_convergence.js +104 -0
- package/src/input_preparation/block_preparation/Block_Data_To_Object_Transformer.js +57 -0
- package/src/input_preparation/block_preparation/Block_Module_Name.js +17 -0
- package/src/input_preparation/block_preparation/Blocks_Creator.js +101 -0
- package/src/input_preparation/block_preparation/Blocksmith.js +19 -0
- package/src/input_preparation/block_preparation/block_modules/create_block_candidates.js +41 -0
- package/src/input_preparation/block_preparation/block_modules/manual_blocks.js +10 -0
- package/src/input_preparation/block_preparation/block_modules/module_registry.js +20 -0
- package/src/input_preparation/block_preparation/block_modules/run_creator.js +34 -0
- package/src/input_preparation/block_preparation/block_modules/single_item_blocks.js +12 -0
- package/src/input_preparation/block_preparation/block_modules/spiral_blocks.js +12 -0
- package/src/input_preparation/block_preparation/block_modules/tie_ratio_blocks.js +12 -0
- package/src/input_preparation/block_preparation/block_modules/tower_blocks.js +12 -0
- package/src/input_preparation/block_preparation/exceptions/Failed_To_Create_Block_Exception.js +14 -0
- package/src/input_preparation/block_preparation/exceptions/Failed_To_Retrieve_Block_Exception.js +17 -0
- package/src/input_preparation/block_preparation/exceptions/Missing_Object_Store_Exception.js +10 -0
- package/src/input_preparation/block_preparation/exceptions/No_Blocks_Were_Created_Exception.js +14 -0
- package/src/input_preparation/block_preparation/input/Input_Creator.js +96 -0
- package/src/input_preparation/block_preparation/manual_blocks/Manual_Blocks.js +95 -0
- package/src/input_preparation/build_empty_space_finder_options.js +43 -0
- package/src/input_preparation/item_preparation/Items_Reader.js +27 -0
- package/src/input_preparation/min_extents_from_items.js +29 -0
- package/src/input_preparation/stackability_index/Blocks_Stackability_Index_Calculator.js +58 -0
- package/src/input_preparation/stackability_index/Slots_Stackability_index_Calculator.js +28 -0
- package/src/input_preparation/stackability_index/Stackability_Input_Creator.js +27 -0
- package/src/input_preparation/stackability_index/stackability_index_pop_stack.js +81 -0
- package/src/input_preparation/stacking_constraints/Weight_Stacking_Validation.js +15 -0
- package/src/lp_optimizer_result_status.js +20 -0
- package/src/messages/Allocator_Message.js +42 -0
- package/src/messages/resolve_error_message_entry.js +57 -0
- package/src/models/Allocated_Item.js +136 -0
- package/src/models/Allocation_Item.js +219 -0
- package/src/models/Block.js +198 -0
- package/src/models/Cargo_Profile.js +418 -0
- package/src/models/Preloaded_Allocated_Item.js +132 -0
- package/src/models/Slot.js +67 -0
- package/src/models/Stacking_Rules.js +58 -0
- package/src/models/auxiliaryFunctions/Available_Block_Module_List_Creator.js +9 -0
- package/src/models/auxiliaryFunctions/Measure_Translator.js +24 -0
- package/src/models/auxiliaryFunctions/item_json_reader.js +44 -0
- package/src/models/item_json_reader.js +71 -0
- package/src/models/placed_item_record.js +70 -0
- package/src/models/preloaded_rotation_helpers.js +38 -0
- package/src/models/slots_have_same_measure.js +45 -0
- package/src/models/transport/Container.js +162 -0
- package/src/models/transport/Transport.js +62 -0
- package/src/models/transport/build_stacking_feasibility_checker.js +64 -0
- package/src/models/transport/container_stacking_checkpoint.js +42 -0
- package/src/models/transport/factory/Container_Factory.js +46 -0
- package/src/models/transport/factory/Corner_Casting_Factory.js +62 -0
- package/src/models/transport/factory/Previously_Allocated_Item_Factory.js +28 -0
- package/src/models/transport/factory/Transport_Factory.js +13 -0
- package/src/models/transport/items_for_empty_space_finder.js +91 -0
- package/src/models/transport/resolve_container_stacking_inputs.js +23 -0
- package/src/models/transport/stacking_input_from_wire.js +58 -0
- package/src/optimizer_connection_errors.js +50 -0
- package/src/relational/Relational_Error_Codes.js +7 -0
- package/src/relational/finalize_relational_allocation.js +20 -0
- package/src/relational/has_relational_items.js +11 -0
- package/src/relational/is_relational_error_code.js +15 -0
- package/src/relational/resolve_relational_container_sequences.js +29 -0
- package/src/run_core_allocation.js +118 -0
- package/src/space_and_block_chooser/Space_And_Blocks_Chooser.js +115 -0
- package/src/space_and_block_chooser/blocks_filters/Block_Filter_Interface.js +19 -0
- package/src/space_and_block_chooser/blocks_filters/Filter_Runner.js +46 -0
- package/src/space_and_block_chooser/blocks_filters/initial_blocks_filter/Block_With_Overlapped_Slots_Filter.js +14 -0
- package/src/space_and_block_chooser/blocks_filters/initial_blocks_filter/Initial_Blocks_Filter_List.js +19 -0
- package/src/space_and_block_chooser/blocks_filters/pos_selection_filters/Blocks_Bigger_Than_Space_Filter.js +17 -0
- package/src/space_and_block_chooser/blocks_filters/pos_selection_filters/Post_Selection_Filter_List.js +9 -0
- package/src/space_and_block_chooser/blocks_filters/pre_selection_filter/Insuficient_Items_Filter.js +81 -0
- package/src/space_and_block_chooser/blocks_filters/pre_selection_filter/Pre_Selection_Filter_List.js +8 -0
- package/src/space_and_block_chooser/blocks_filters/pre_selection_filter/max_tower_height/Blocks_Lower_Than_Max_Tower_Height.js +23 -0
- package/src/space_and_block_chooser/blocks_filters/pre_selection_filter/max_tower_height/Max_Tower_Height.js +82 -0
- package/src/space_and_block_chooser/build_allocated_item_snapshots.js +19 -0
- package/src/space_and_block_chooser/compound_first_empty_space_branch.js +61 -0
- package/src/space_and_block_chooser/compound_first_with_leftover_fill.js +142 -0
- package/src/space_and_block_chooser/compound_first_without_leftover_fill.js +56 -0
- package/src/space_and_block_chooser/empty_spaces_where_post_selection_keeps_blocks.js +83 -0
- package/src/space_and_block_chooser/exceptions/Invalid_Space_To_Allocate_Exception.js +14 -0
- package/src/space_and_block_chooser/leftover_space_memory.js +113 -0
- package/src/space_and_block_chooser/leftover_unitary_blocks.js +153 -0
- package/src/space_and_block_chooser/leftover_unitary_empty_spaces.js +135 -0
- package/src/space_and_block_chooser/probe_set_pool.js +35 -0
- package/src/space_and_block_chooser/run_space_and_block_selection_attempt.js +88 -0
- package/src/tools/Array_Validator.js +6 -0
- package/src/tools/Clone.js +27 -0
- package/src/tools/Hash.js +8 -0
- package/src/tools/Rounder.js +5 -0
- package/src/tools/String_To_Boolean.js +12 -0
- package/src/tools/cargo_profile/Cargo_Profile_Field_Value_Resolver.js +44 -0
- package/src/tools/compact_items_with_stock.js +9 -0
- package/src/tools/mm_to_allocation_domain.js +14 -0
- package/src/tracing/Allocation_Tracer.js +52 -0
- package/src/tracing/Trace_Context.js +18 -0
- package/src/tracing/trace_outcome.js +18 -0
- package/src/tracing/traced_step.js +57 -0
- package/src/validation/Item_Continuation_Lock_Flag.js +52 -0
- package/src/validation/Item_Validation.js +29 -0
- package/src/validation/Relational_Colocation_Validator.js +60 -0
- package/src/validation/Relational_Completeness_Validator.js +146 -0
- package/src/validation/Relational_Continuation_Lock_Validation.js +37 -0
- package/src/validation/Relational_Proportional_Normalizer.js +194 -0
- package/src/validation/Validation.js +9 -0
- package/src/validation/Validation_Runner.js +20 -0
- package/src/validation/exceptions/Invalid_Block_Module_Config_Exception.js +14 -0
- package/src/validation/exceptions/Invalid_Input_Exception.js +14 -0
- package/src/validation/exceptions/Invalid_Input_Type_Exception.js +14 -0
- package/src/validation/schemas/allocated_item_schema.js +18 -0
- package/src/validation/schemas/allocation_request_schema.js +178 -0
- package/src/validation/schemas/container_row_schema.js +16 -0
- package/src/validation/schemas/item_schema.js +60 -0
- package/src/validation/schemas/transport_env_schema.js +19 -0
- package/src/validation/validate_block_module_config.js +147 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const { build_message_entry } = require('../../../messages/resolve_error_message_entry')
|
|
2
|
+
const { ALLOCATOR_MESSAGE } = require('../../../messages/Allocator_Message')
|
|
3
|
+
|
|
4
|
+
class No_Slots_For_Items_Exception extends Error
|
|
5
|
+
{
|
|
6
|
+
constructor()
|
|
7
|
+
{
|
|
8
|
+
const message_key = ALLOCATOR_MESSAGE.NO_SLOTS_FOR_ITEMS
|
|
9
|
+
super(message_key)
|
|
10
|
+
this.message_entry = build_message_entry(message_key)
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
module.exports = No_Slots_For_Items_Exception
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const Cargo_Profile = require('../../models/Cargo_Profile')
|
|
2
|
+
const Measure_Reader = require('../functions/Measure_Reader')
|
|
3
|
+
const measure_to_optimize = require('../functions/measure_to_optimize')
|
|
4
|
+
const get_custom_weight = require('../functions/Weight_Getter/Variable_Weight_Getter')
|
|
5
|
+
|
|
6
|
+
function get_measure(obj)
|
|
7
|
+
{
|
|
8
|
+
switch (Measure_Reader.read_measure_to_be_optimized())
|
|
9
|
+
{
|
|
10
|
+
case measure_to_optimize.LENGTH:
|
|
11
|
+
return obj.length !== undefined ? obj.length : obj.get_length()
|
|
12
|
+
case measure_to_optimize.WIDTH:
|
|
13
|
+
return obj.width !== undefined ? obj.width : obj.get_width()
|
|
14
|
+
default:
|
|
15
|
+
throw new Error('invalid measure identifier')
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function buff_block(block)
|
|
20
|
+
{
|
|
21
|
+
return Cargo_Profile.enable_blocks_extra_score() ? (1 + (block.is_block() ? 1 : 0)) / 1.5 : 1
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = function calculate_block_var_weight(block)
|
|
25
|
+
{
|
|
26
|
+
const measure = Number(get_measure(block))
|
|
27
|
+
const custom_additional_weight = get_custom_weight(block)
|
|
28
|
+
const base_weight = (measure * 10) + Number(custom_additional_weight)
|
|
29
|
+
const buff_blocks = buff_block(block)
|
|
30
|
+
return base_weight * buff_blocks
|
|
31
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
|
|
2
|
+
class LP_Data_Processor
|
|
3
|
+
{
|
|
4
|
+
/**
|
|
5
|
+
* Sanitizes available usable blocks based on restricted blocks.
|
|
6
|
+
* Filters out fully restricted blocks and identifies multi-slot blocks.
|
|
7
|
+
* @param {Array<Object>} available_block_list - A list of available usable block objects.
|
|
8
|
+
* @param {Object} restricted_block_map - An object mapping block IDs to their restricted status.
|
|
9
|
+
* @returns {Array<Object>} A filtered list of usable block objects, prioritizing multi-slot blocks if available.
|
|
10
|
+
*/
|
|
11
|
+
sanitize(available_block_list, restricted_block_map = {})
|
|
12
|
+
{
|
|
13
|
+
const fully_restricted_ids = new Set()
|
|
14
|
+
for (const block_id of Object.keys(restricted_block_map))
|
|
15
|
+
{
|
|
16
|
+
if (restricted_block_map[block_id] == 0)
|
|
17
|
+
{
|
|
18
|
+
fully_restricted_ids.add(block_id)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (fully_restricted_ids.size === 0)
|
|
22
|
+
{
|
|
23
|
+
return available_block_list
|
|
24
|
+
}
|
|
25
|
+
return available_block_list.filter(block => !fully_restricted_ids.has(block.get_id()))
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Removes duplicate blocks from a list based on their IDs.
|
|
30
|
+
* If multiple blocks have the same ID, only the last occurrence is kept.
|
|
31
|
+
* @param {Array<Object>} blocks - A list of block objects.
|
|
32
|
+
* @returns {Array<Object>} A new list of blocks with duplicates removed.
|
|
33
|
+
*/
|
|
34
|
+
remove_duplicates(blocks)
|
|
35
|
+
{
|
|
36
|
+
const map = {}
|
|
37
|
+
blocks.forEach(block => map[block.get_id()] = block)
|
|
38
|
+
return Object.values(map)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
module.exports = LP_Data_Processor
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
const round = require('../../tools/Rounder')
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Builds per-block-instance item id queues from LP block_item_amount variables.
|
|
5
|
+
* @param {object} result - Optimizer result with variables().
|
|
6
|
+
* @param {{ slot_demand_list: object[] }} item_assignment_context
|
|
7
|
+
* @returns {Map<string, string[]>} block_id -> ordered item ids (one per block instance)
|
|
8
|
+
*/
|
|
9
|
+
function build_block_instance_item_queues(result, item_assignment_context)
|
|
10
|
+
{
|
|
11
|
+
const variable_values = index_variable_values(result)
|
|
12
|
+
const queues = new Map()
|
|
13
|
+
|
|
14
|
+
for (const slot_demand of item_assignment_context.slot_demand_list)
|
|
15
|
+
{
|
|
16
|
+
merge_slot_demand_into_queues(slot_demand, variable_values, queues)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return queues
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function index_variable_values(result)
|
|
23
|
+
{
|
|
24
|
+
const values = new Map()
|
|
25
|
+
|
|
26
|
+
for (const variable of result.variables())
|
|
27
|
+
{
|
|
28
|
+
if (!variable.name.startsWith('block_item_amount_'))
|
|
29
|
+
{
|
|
30
|
+
continue
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const amount = round(variable.value)
|
|
34
|
+
if (amount > 0)
|
|
35
|
+
{
|
|
36
|
+
values.set(variable.name, amount)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return values
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function merge_slot_demand_into_queues(slot_demand, variable_values, queues)
|
|
44
|
+
{
|
|
45
|
+
const { block_id, required_amount, compatibility_list } = slot_demand
|
|
46
|
+
const item_ids_for_slot_shape = expand_item_counts(compatibility_list, variable_values)
|
|
47
|
+
|
|
48
|
+
if (item_ids_for_slot_shape.length === 0)
|
|
49
|
+
{
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (required_amount !== 1)
|
|
54
|
+
{
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const block_instances = item_ids_for_slot_shape.length
|
|
59
|
+
if (!queues.has(block_id))
|
|
60
|
+
{
|
|
61
|
+
queues.set(block_id, new Array(block_instances))
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const block_queue = queues.get(block_id)
|
|
65
|
+
for (let index = 0; index < block_instances; index++)
|
|
66
|
+
{
|
|
67
|
+
if (!block_queue[index])
|
|
68
|
+
{
|
|
69
|
+
block_queue[index] = []
|
|
70
|
+
}
|
|
71
|
+
block_queue[index].push(item_ids_for_slot_shape[index])
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function expand_item_counts(compatibility_list, variable_values)
|
|
76
|
+
{
|
|
77
|
+
const item_ids = []
|
|
78
|
+
|
|
79
|
+
for (const entry of compatibility_list)
|
|
80
|
+
{
|
|
81
|
+
const count = variable_values.get(entry.variable_name) || 0
|
|
82
|
+
for (let index = 0; index < count; index++)
|
|
83
|
+
{
|
|
84
|
+
item_ids.push(entry.item_id)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return item_ids
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
module.exports = {
|
|
92
|
+
build_block_instance_item_queues
|
|
93
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
|
|
2
|
+
const round = require('../../tools/Rounder')
|
|
3
|
+
const { read_measure_to_be_optimized } = require('../functions/Measure_Reader')
|
|
4
|
+
const { build_block_instance_item_queues } = require('./LP_Item_Slot_Assignment')
|
|
5
|
+
|
|
6
|
+
class LP_Result_Mapper
|
|
7
|
+
{
|
|
8
|
+
constructor(block_map)
|
|
9
|
+
{
|
|
10
|
+
this.block_map = block_map
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
map_result(result, item_assignment_context = null)
|
|
14
|
+
{
|
|
15
|
+
const allocated_blocks = {
|
|
16
|
+
optimized_measure: read_measure_to_be_optimized(),
|
|
17
|
+
chosen_blocks: [],
|
|
18
|
+
block_instance_item_queues: new Map()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
for (const variable of result.variables())
|
|
22
|
+
{
|
|
23
|
+
const is_block_var = (variable) => this.block_map[variable.name]
|
|
24
|
+
if (is_block_var(variable))
|
|
25
|
+
{
|
|
26
|
+
const block_object = this.block_map[variable.name]
|
|
27
|
+
const chosen_block = { block: block_object, amount: round(variable.value) }
|
|
28
|
+
if (chosen_block.amount > 0)
|
|
29
|
+
{
|
|
30
|
+
allocated_blocks.chosen_blocks.push(chosen_block)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (item_assignment_context)
|
|
36
|
+
{
|
|
37
|
+
allocated_blocks.block_instance_item_queues = build_block_instance_item_queues(
|
|
38
|
+
result,
|
|
39
|
+
item_assignment_context
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return allocated_blocks
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = LP_Result_Mapper
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const Cargo_Profile = require('../../../models/Cargo_Profile')
|
|
2
|
+
const { read_measure_to_be_optimized } = require('../../functions/Measure_Reader')
|
|
3
|
+
const measure_to_optimize = require('../../functions/measure_to_optimize')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Shared helpers for block dimension ranges used by the uniformity penalty and coherence restrictions.
|
|
7
|
+
* @module Dimension_Range_Helper
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Returns the perpendicular measure used for block equalization (width when optimizing length, length when optimizing width).
|
|
12
|
+
* @param {object} obj - Object with width/length or get_width/get_length.
|
|
13
|
+
* @returns {number} The penalty measure value.
|
|
14
|
+
*/
|
|
15
|
+
function get_penalty_measure(obj)
|
|
16
|
+
{
|
|
17
|
+
switch (read_measure_to_be_optimized())
|
|
18
|
+
{
|
|
19
|
+
case measure_to_optimize.LENGTH:
|
|
20
|
+
return obj.width !== undefined ? obj.width : obj.get_width()
|
|
21
|
+
case measure_to_optimize.WIDTH:
|
|
22
|
+
return obj.length !== undefined ? obj.length : obj.get_length()
|
|
23
|
+
default:
|
|
24
|
+
throw new Error('invalid measure identifier')
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Returns the dimension range id for a block, used for uniformity penalty and coherence restrictions.
|
|
30
|
+
* @param {object} block - The block object.
|
|
31
|
+
* @returns {number} The range id (same as used in penalty variable names).
|
|
32
|
+
*/
|
|
33
|
+
function get_dimension_range(block)
|
|
34
|
+
{
|
|
35
|
+
const tolerance = Cargo_Profile.block_equalization_tolerance()
|
|
36
|
+
if (tolerance <= 0)
|
|
37
|
+
{
|
|
38
|
+
return get_penalty_measure(block)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const penalty_measure = get_penalty_measure(block)
|
|
42
|
+
const range_id = Math.ceil(penalty_measure / tolerance) * tolerance
|
|
43
|
+
return range_id
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
module.exports = {
|
|
47
|
+
get_penalty_measure,
|
|
48
|
+
get_dimension_range
|
|
49
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
const create_hash = require('../../../tools/Hash')
|
|
2
|
+
const {
|
|
3
|
+
get_dimension_hash,
|
|
4
|
+
collect_rotation_dimension_hashes
|
|
5
|
+
} = require('./item_dimension_hashes')
|
|
6
|
+
const Missing_Item_Stock_Exception = require('./exceptions/Missing_Item_Stock_Exception')
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Builds the LP assignment graph between blocks, slot shapes, and compatible items.
|
|
10
|
+
* Single source of truth for the `block_item_amount_<hash>` variable naming used by
|
|
11
|
+
* Block_Item_Amount_Restriction and Single_Item_Type_Restriction.
|
|
12
|
+
* @param {object[]} block_list - Block objects (must expose get_id and get_slot_list).
|
|
13
|
+
* @param {object[]} item_list - Item objects (must expose get_id, get_amount and get_all_rotated_options).
|
|
14
|
+
* @returns {{
|
|
15
|
+
* slot_demand_list: Array<{block_id: string, slot_hash: string, required_amount: number, compatibility_list: Array<{item_id: string, variable_name: string}>}>,
|
|
16
|
+
* variables_by_item: Map<string, string[]>,
|
|
17
|
+
* id_to_stock_map: Map<string, number>
|
|
18
|
+
* }}
|
|
19
|
+
*/
|
|
20
|
+
function create_item_assignment_variables(block_list, item_list)
|
|
21
|
+
{
|
|
22
|
+
const { dim_to_id_map, id_to_stock_map } = build_item_dimension_and_stock_maps(item_list)
|
|
23
|
+
const slot_demand_list = build_block_slot_demand_list(block_list, dim_to_id_map)
|
|
24
|
+
const variables_by_item = group_variable_names_by_item(slot_demand_list)
|
|
25
|
+
return { slot_demand_list, variables_by_item, id_to_stock_map }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Reads stock for an item id from the map built with create_item_assignment_variables.
|
|
30
|
+
* @param {Map<string, number>} id_to_stock_map - Item id to available amount.
|
|
31
|
+
* @param {string} item_id - Item id to resolve.
|
|
32
|
+
* @returns {number} Stock amount for the item.
|
|
33
|
+
* @throws {Missing_Item_Stock_Exception} When the item id is missing from the map.
|
|
34
|
+
*/
|
|
35
|
+
function read_stock(id_to_stock_map, item_id)
|
|
36
|
+
{
|
|
37
|
+
const amount = id_to_stock_map.get(item_id)
|
|
38
|
+
if (amount === undefined)
|
|
39
|
+
{
|
|
40
|
+
throw new Missing_Item_Stock_Exception(item_id)
|
|
41
|
+
}
|
|
42
|
+
return amount
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
module.exports = create_item_assignment_variables
|
|
46
|
+
module.exports.read_stock = read_stock
|
|
47
|
+
|
|
48
|
+
function build_item_dimension_and_stock_maps(item_list)
|
|
49
|
+
{
|
|
50
|
+
const dim_to_id_map = new Map()
|
|
51
|
+
const id_to_stock_map = new Map()
|
|
52
|
+
for (const item of item_list)
|
|
53
|
+
{
|
|
54
|
+
const item_id = item.get_id()
|
|
55
|
+
index_item_rotations(dim_to_id_map, item)
|
|
56
|
+
if (!id_to_stock_map.has(item_id))
|
|
57
|
+
{
|
|
58
|
+
id_to_stock_map.set(item_id, item.get_amount())
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return { dim_to_id_map, id_to_stock_map }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function index_item_rotations(dim_to_id_map, item)
|
|
65
|
+
{
|
|
66
|
+
const item_id = item.get_id()
|
|
67
|
+
for (const hash of collect_rotation_dimension_hashes(item))
|
|
68
|
+
{
|
|
69
|
+
if (!dim_to_id_map.has(hash))
|
|
70
|
+
{
|
|
71
|
+
dim_to_id_map.set(hash, new Set())
|
|
72
|
+
}
|
|
73
|
+
dim_to_id_map.get(hash).add(item_id)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function build_block_slot_demand_list(block_list, dim_to_id_map)
|
|
78
|
+
{
|
|
79
|
+
const slot_demand_list = []
|
|
80
|
+
for (const block of block_list)
|
|
81
|
+
{
|
|
82
|
+
const block_id = block.get_id()
|
|
83
|
+
const demand_by_slot_hash = get_block_slot_demand(block)
|
|
84
|
+
for (const [slot_hash, required_amount] of demand_by_slot_hash.entries())
|
|
85
|
+
{
|
|
86
|
+
slot_demand_list.push({
|
|
87
|
+
block_id,
|
|
88
|
+
slot_hash,
|
|
89
|
+
required_amount,
|
|
90
|
+
compatibility_list: build_compatibility_list(block_id, slot_hash, dim_to_id_map)
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return slot_demand_list
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function get_block_slot_demand(block)
|
|
98
|
+
{
|
|
99
|
+
const demand_by_slot_hash = new Map()
|
|
100
|
+
for (const slot of block.get_slot_list())
|
|
101
|
+
{
|
|
102
|
+
const slot_hash = get_dimension_hash(slot)
|
|
103
|
+
const current_count = demand_by_slot_hash.get(slot_hash) || 0
|
|
104
|
+
demand_by_slot_hash.set(slot_hash, current_count + 1)
|
|
105
|
+
}
|
|
106
|
+
return demand_by_slot_hash
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function build_compatibility_list(block_id, slot_hash, dim_to_id_map)
|
|
110
|
+
{
|
|
111
|
+
const compatible_id_set = dim_to_id_map.get(slot_hash) || new Set()
|
|
112
|
+
return [...compatible_id_set].map(item_id => ({
|
|
113
|
+
item_id,
|
|
114
|
+
variable_name: `block_item_amount_${create_hash(`${block_id};${slot_hash};${item_id}`)}`
|
|
115
|
+
}))
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function group_variable_names_by_item(slot_demand_list)
|
|
119
|
+
{
|
|
120
|
+
const variables_by_item = new Map()
|
|
121
|
+
for (const slot_demand of slot_demand_list)
|
|
122
|
+
{
|
|
123
|
+
for (const entry of slot_demand.compatibility_list)
|
|
124
|
+
{
|
|
125
|
+
if (!variables_by_item.has(entry.item_id))
|
|
126
|
+
{
|
|
127
|
+
variables_by_item.set(entry.item_id, [])
|
|
128
|
+
}
|
|
129
|
+
variables_by_item.get(entry.item_id).push(entry.variable_name)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return variables_by_item
|
|
133
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
const create_coherence_restrictions = require('./restrictions/Coherence_Restriction')
|
|
2
|
+
const create_item_assignment_variables = require('./Item_Assignment_Variables')
|
|
3
|
+
const create_block_item_amount_restriction = require('./restrictions/Block_Item_Amount_Restriction')
|
|
4
|
+
const create_container_supported_weight_restriction = require('./restrictions/Container_Supported_Weight_Restriction')
|
|
5
|
+
const create_block_restricted_to_0_restriction = require('./restrictions/Unavailable_Block_Restriction')
|
|
6
|
+
const create_single_item_type_restriction = require('./restrictions/Single_Item_Type_Restriction')
|
|
7
|
+
const create_uniform_block_measure_restriction = require('./restrictions/Uniform_Block_Measure_Restriction')
|
|
8
|
+
const create_relational_group_restriction = require('./restrictions/Relational_Group_Restriction')
|
|
9
|
+
const create_relational_exact_pass_amount_restriction = require('./restrictions/Relational_Exact_Pass_Amount_Restriction')
|
|
10
|
+
const create_space_restriction = require('./restrictions/Space_Restriction')
|
|
11
|
+
const Goal_Function_Creator = require('./goal_function/Goal_Function_Creator')
|
|
12
|
+
|
|
13
|
+
function validate_data(data)
|
|
14
|
+
{
|
|
15
|
+
if (data == null || typeof data !== 'object')
|
|
16
|
+
{
|
|
17
|
+
throw new Error('LP_Model_Builder: data is required and must be an object')
|
|
18
|
+
}
|
|
19
|
+
const required = ['optimizer', 'container', 'empty_space', 'block_list', 'item_list']
|
|
20
|
+
for (const key of required)
|
|
21
|
+
{
|
|
22
|
+
if (data[key] === undefined)
|
|
23
|
+
{
|
|
24
|
+
throw new Error(`LP_Model_Builder: data.${key} is required`)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (!Array.isArray(data.block_list) || !Array.isArray(data.item_list))
|
|
28
|
+
{
|
|
29
|
+
throw new Error('LP_Model_Builder: data.block_list and data.item_list must be arrays')
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Assembles the full LP model: goal function and all restrictions (space, block-item, container weight,
|
|
35
|
+
* coherence, unavailable blocks, and single-item-type caps where applicable).
|
|
36
|
+
*/
|
|
37
|
+
class LP_Model_Builder
|
|
38
|
+
{
|
|
39
|
+
#goal_function
|
|
40
|
+
#optimizer
|
|
41
|
+
#container
|
|
42
|
+
#empty_space
|
|
43
|
+
#block_list
|
|
44
|
+
#item_list
|
|
45
|
+
#block_amount_map
|
|
46
|
+
#enable_uniformity_penalty
|
|
47
|
+
#item_assignment_context = null
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @param {object} data - Builder configuration.
|
|
51
|
+
* @param {object} data.optimizer - LP optimizer instance to receive goal and restrictions.
|
|
52
|
+
* @param {object} data.container - Container (e.g. supported_weight).
|
|
53
|
+
* @param {object} data.empty_space - Space to allocate (measure used for space restriction).
|
|
54
|
+
* @param {Array<object>} data.block_list - Available blocks.
|
|
55
|
+
* @param {Array<object>} data.item_list - Items for block-item constraints.
|
|
56
|
+
* @param {object} data.block_amount_map - Map of block id to max amount (unavailable-block restrictions).
|
|
57
|
+
* @param {boolean} [data.enable_uniformity_penalty=true] - Whether to add uniformity penalty in the goal.
|
|
58
|
+
*/
|
|
59
|
+
constructor(data)
|
|
60
|
+
{
|
|
61
|
+
validate_data(data)
|
|
62
|
+
const {
|
|
63
|
+
optimizer,
|
|
64
|
+
container,
|
|
65
|
+
empty_space,
|
|
66
|
+
block_list,
|
|
67
|
+
item_list,
|
|
68
|
+
block_amount_map,
|
|
69
|
+
enable_uniformity_penalty = true
|
|
70
|
+
} = data
|
|
71
|
+
this.#optimizer = optimizer
|
|
72
|
+
this.#container = container
|
|
73
|
+
this.#empty_space = empty_space
|
|
74
|
+
this.#block_list = block_list
|
|
75
|
+
this.#item_list = item_list
|
|
76
|
+
this.#block_amount_map = block_amount_map
|
|
77
|
+
this.#enable_uniformity_penalty = enable_uniformity_penalty
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Builds the LP model: goal function and all restrictions, and registers them with the optimizer.
|
|
82
|
+
* @returns {void}
|
|
83
|
+
*/
|
|
84
|
+
build_model()
|
|
85
|
+
{
|
|
86
|
+
const penalty_vars = this.#build_goal_function()
|
|
87
|
+
this.#optimizer.set_goal_function(this.#goal_function)
|
|
88
|
+
this.#build_restrictions(penalty_vars)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Returns the item assignment context built during the last build_model() call.
|
|
93
|
+
* @returns {{slot_demand_list: Array, variables_by_item: Map<string, string[]>, id_to_stock_map: Map<string, number>}|null}
|
|
94
|
+
*/
|
|
95
|
+
get_item_assignment_context()
|
|
96
|
+
{
|
|
97
|
+
return this.#item_assignment_context
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
#build_goal_function()
|
|
101
|
+
{
|
|
102
|
+
const goal_function_creator = new Goal_Function_Creator(this.#block_list, this.#enable_uniformity_penalty)
|
|
103
|
+
const {goal_function, penalty_vars} = goal_function_creator.create_goal_function()
|
|
104
|
+
this.#goal_function = goal_function
|
|
105
|
+
return penalty_vars
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
#build_restrictions(penalty_var_list)
|
|
109
|
+
{
|
|
110
|
+
this.#item_assignment_context = create_item_assignment_variables(this.#block_list, this.#item_list)
|
|
111
|
+
const restriction_list = [
|
|
112
|
+
...create_space_restriction(this.#empty_space, this.#block_list),
|
|
113
|
+
...create_block_item_amount_restriction(this.#block_list, this.#item_list, this.#item_assignment_context),
|
|
114
|
+
...create_container_supported_weight_restriction(this.#container, this.#block_list, this.#item_list),
|
|
115
|
+
...create_coherence_restrictions(penalty_var_list, this.#block_list),
|
|
116
|
+
...create_uniform_block_measure_restriction(this.#block_list, this.#item_list),
|
|
117
|
+
...create_block_restricted_to_0_restriction(this.#block_list, this.#block_amount_map ?? {}),
|
|
118
|
+
...create_single_item_type_restriction(this.#block_list, this.#item_list, this.#item_assignment_context),
|
|
119
|
+
...create_relational_group_restriction(this.#block_list, this.#item_list, this.#item_assignment_context),
|
|
120
|
+
...create_relational_exact_pass_amount_restriction(this.#block_list, this.#item_list, this.#item_assignment_context)
|
|
121
|
+
]
|
|
122
|
+
|
|
123
|
+
this.#add_restriction_list(restriction_list)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
#add_restriction_list(restriction_list)
|
|
127
|
+
{
|
|
128
|
+
restriction_list.forEach(restriction => this.#optimizer.add_restriction(restriction))
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
module.exports = LP_Model_Builder
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const { build_message_entry } = require('../../../../messages/resolve_error_message_entry')
|
|
2
|
+
const { ALLOCATOR_MESSAGE } = require('../../../../messages/Allocator_Message')
|
|
3
|
+
|
|
4
|
+
class Missing_Item_Stock_Exception extends Error
|
|
5
|
+
{
|
|
6
|
+
/**
|
|
7
|
+
* @param {string|number} item_id
|
|
8
|
+
*/
|
|
9
|
+
constructor(item_id)
|
|
10
|
+
{
|
|
11
|
+
const message_key = ALLOCATOR_MESSAGE.MISSING_ITEM_STOCK
|
|
12
|
+
super(message_key)
|
|
13
|
+
this.message_entry = build_message_entry(message_key, [String(item_id)])
|
|
14
|
+
this.item_id = item_id
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = Missing_Item_Stock_Exception
|
package/src/Allocation_Optimization/lp_model/model_builder/goal_function/Goal_Function_Creator.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
const {
|
|
2
|
+
GoalFunction,
|
|
3
|
+
OptimizationCriteria,
|
|
4
|
+
VariableType,
|
|
5
|
+
create_variable
|
|
6
|
+
} = require('@jetta/lp-framework')
|
|
7
|
+
const Cargo_Profile = require('../../../../models/Cargo_Profile')
|
|
8
|
+
const { get_dimension_range } = require('../Dimension_Range_Helper')
|
|
9
|
+
const calculate_block_var_weight = require('../../Block_Weight_Calculator')
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Builds the LP goal function (objective) and optional uniformity penalty variables for block equalization.
|
|
13
|
+
*/
|
|
14
|
+
module.exports = class Goal_Function_Creator
|
|
15
|
+
{
|
|
16
|
+
#goal_function
|
|
17
|
+
#block_list
|
|
18
|
+
#enable_uniformity_penalty
|
|
19
|
+
#penalty_vars = []
|
|
20
|
+
/**
|
|
21
|
+
* @param {Array<object>} block_list - List of blocks; each must have get_id().
|
|
22
|
+
* @param {boolean} enable_uniformity_penalty - Whether to add uniformity penalty variables when equalization is enabled.
|
|
23
|
+
*/
|
|
24
|
+
constructor(block_list, enable_uniformity_penalty)
|
|
25
|
+
{
|
|
26
|
+
this.#block_list = block_list
|
|
27
|
+
this.#enable_uniformity_penalty = enable_uniformity_penalty
|
|
28
|
+
this.#goal_function = new GoalFunction(OptimizationCriteria.MAX)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Builds the goal function with block variables and, when enabled, uniformity penalty variables.
|
|
33
|
+
* @returns {{ goal_function: import('@jetta/lp-framework').GoalFunction, penalty_vars: Array<object> }} The goal function and list of penalty variables for coherence restrictions.
|
|
34
|
+
*/
|
|
35
|
+
create_goal_function()
|
|
36
|
+
{
|
|
37
|
+
this.#add_block_variables_to_goal(this.#block_list)
|
|
38
|
+
const enabled = Cargo_Profile.enable_block_equalization()
|
|
39
|
+
if (enabled && this.#enable_uniformity_penalty)
|
|
40
|
+
{
|
|
41
|
+
this.#add_uniformity_penalty_to_goal()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
goal_function: this.#goal_function,
|
|
46
|
+
penalty_vars: this.#penalty_vars
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
#add_block_variables_to_goal(block_list)
|
|
51
|
+
{
|
|
52
|
+
for (const block of block_list)
|
|
53
|
+
{
|
|
54
|
+
const var_name = block.get_id()
|
|
55
|
+
const weight = calculate_block_var_weight(block)
|
|
56
|
+
const variable = create_variable(var_name, weight, VariableType.INTEGER)
|
|
57
|
+
this.#goal_function.set_variable(variable)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
#add_uniformity_penalty_to_goal()
|
|
62
|
+
{
|
|
63
|
+
const unique_ranges = [...new Set(this.#block_list.map(b => get_dimension_range(b)))]
|
|
64
|
+
|
|
65
|
+
for (const range_id of unique_ranges)
|
|
66
|
+
{
|
|
67
|
+
const penalty_var_name = `used_penalty_range_${range_id}`
|
|
68
|
+
const penalty_variable = this.#create_penalty_variable(penalty_var_name)
|
|
69
|
+
this.#goal_function.set_variable(penalty_variable)
|
|
70
|
+
this.#penalty_vars.push(penalty_variable)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
#create_penalty_variable(name)
|
|
75
|
+
{
|
|
76
|
+
const penalty_coefficient = parseInt(Cargo_Profile.block_equalization_penalty_coefficient())
|
|
77
|
+
const penalty_variable = create_variable(name, penalty_coefficient, VariableType.INTEGER)
|
|
78
|
+
return penalty_variable
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the same dimension string key used across LP restrictions (width;height;length).
|
|
3
|
+
* @param {object} cube - Object with get_width, get_height, and get_length methods.
|
|
4
|
+
* @returns {string} Semicolon-separated dimensions.
|
|
5
|
+
*/
|
|
6
|
+
function get_dimension_hash(cube)
|
|
7
|
+
{
|
|
8
|
+
return `${cube.get_width()};${cube.get_height()};${cube.get_length()}`
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Collects dimension hashes for every rotation of an item (matches Block_Item indexing).
|
|
13
|
+
* @param {object} item - Item with get_all_rotated_options().
|
|
14
|
+
* @returns {Set<string>} Unique dimension hashes for all rotated orientations.
|
|
15
|
+
*/
|
|
16
|
+
function collect_rotation_dimension_hashes(item)
|
|
17
|
+
{
|
|
18
|
+
const hash_set = new Set()
|
|
19
|
+
|
|
20
|
+
for (const rotated_item of item.get_all_rotated_options())
|
|
21
|
+
{
|
|
22
|
+
hash_set.add(get_dimension_hash(rotated_item))
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return hash_set
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
module.exports = {
|
|
29
|
+
get_dimension_hash,
|
|
30
|
+
collect_rotation_dimension_hashes
|
|
31
|
+
}
|