@jetta/blocks-allocator 0.0.0-stage → 0.1.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,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
|
+
}
|
package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Coherence_Restriction.js
ADDED
|
@@ -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
|