123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- import copy
- import json
- from collections import defaultdict
- from .models import LocationGroupModel, alloction_pre
- from .queries import LocationQueries
- class AllocationAlgorithm:
- CAPACITY_MAP = {'T1':1, 'T2':2, 'T4':4, 'S4':4, 'T5':5}
- @classmethod
- def generate_plan(cls, total_pallets, layer_capacity, current_pressure):
- def allocate(remain, path, pressure, layer_state, depth=0):
- if remain <= 0:
- return path, pressure
-
- balance_factor = 1.0 - (0.1 * min(depth, 5))
- layer_priority = sorted(
- enumerate(pressure),
- key=lambda x: (x[1] * balance_factor, x[0])
- )
- for layer_idx, _ in layer_priority:
- candidates = sorted(
- [(t, c) for t, c in cls.CAPACITY_MAP.items()
- if layer_state[layer_idx].get(t, 0) > 0],
- key=lambda x: (abs(x[1]-remain), -x[1])
- )
- for loc_type, cap in candidates:
- new_state = copy.deepcopy(layer_state)
- new_state[layer_idx][loc_type] -= 1
-
- # new_pressure = [p-1 if p>0 else 0 for p in pressure]
- new_pressure = [p if p>0 else 0 for p in pressure]
- allocated = min(cap, remain)
- new_pressure[layer_idx] += allocated
- result = allocate(
- remain - allocated,
- path + [f"{layer_idx+1}_{loc_type}"],
- new_pressure,
- new_state,
- depth + 1
- )
- if result:
- return result
- return None
- return allocate(total_pallets, [], current_pressure, layer_capacity)
- @staticmethod
- def format_solution(solution):
- result = defaultdict(lambda: defaultdict(int))
- for item in solution:
- parts = item.split('_')
- if len(parts) == 2:
- layer, loc_type = parts
- result[layer][loc_type] += 1
- return json.dumps(result)
-
- @staticmethod
- def allocation_plan_left_right(location_type_list,batch_number,start_location,container_code):
- locations=[]
- existing_solution = alloction_pre.objects.filter(batch_number=batch_number).first()
- for layer, location_type_dict in location_type_list.items():
- if not location_type_dict:
- continue
- # 获取库位类型列表
- location_type = list(location_type_dict.keys())
- demand_number = sum(location_type_dict.values())
- print (f"[1]层{layer} 需求数量: {demand_number}, 库位: {location_type}")
- location_groups = LocationGroupModel.objects.filter(
- group_type__in=location_type,
- layer=layer,
- status='available'
- )
- if not location_groups:
- print(f"层{layer} 无库位")
- # 根据起始位置选择排序字段
- if start_location == '203':
- ordered_groups = location_groups.order_by('left_priority')
- elif start_location == '103':
- ordered_groups = location_groups.order_by('right_priority')
- else:
- ordered_groups = location_groups.none()
- number = 0
- for location_group in ordered_groups:
- if number >= demand_number:
- break
- locations.append(f"{layer}_{location_group.id}")
- number += 1
-
- existing_solution.layer_solution_type = locations
- existing_solution.save()
- print(f"[2]分配方案: {locations}")
- return locations if locations else None
-
- def generate_WCS_location(location_list_cnumber):
- allocation_target_location = (
- location_list_cnumber.warehouse_code + '-'
- + f"{int(location_list_cnumber.row):02d}" + '-'
- + f"{int(location_list_cnumber.col):02d}" + '-'
- + f"{int(location_list_cnumber.layer):02d}"
- )
- return allocation_target_location
|