algorithms.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import copy
  2. import json
  3. from collections import defaultdict
  4. from .models import LocationGroupModel, alloction_pre
  5. from .queries import LocationQueries
  6. class AllocationAlgorithm:
  7. CAPACITY_MAP = {'T1':1, 'T2':2, 'T4':4, 'S4':4, 'T5':5}
  8. @classmethod
  9. def generate_plan(cls, total_pallets, layer_capacity, current_pressure):
  10. def allocate(remain, path, pressure, layer_state, depth=0):
  11. if remain <= 0:
  12. return path, pressure
  13. balance_factor = 1.0 - (0.1 * min(depth, 5))
  14. layer_priority = sorted(
  15. enumerate(pressure),
  16. key=lambda x: (x[1] * balance_factor, x[0])
  17. )
  18. for layer_idx, _ in layer_priority:
  19. candidates = sorted(
  20. [(t, c) for t, c in cls.CAPACITY_MAP.items()
  21. if layer_state[layer_idx].get(t, 0) > 0],
  22. key=lambda x: (
  23. 0 if x[1] == remain else 1,
  24. 0 if x[1] > remain else 1,
  25. x[1] if x[1] > remain else -x[1],
  26. )
  27. )
  28. for loc_type, cap in candidates:
  29. new_state = copy.deepcopy(layer_state)
  30. new_state[layer_idx][loc_type] -= 1
  31. # new_pressure = [p-1 if p>0 else 0 for p in pressure]
  32. new_pressure = [p if p>0 else 0 for p in pressure]
  33. allocated = min(cap, remain)
  34. new_pressure[layer_idx] += allocated
  35. result = allocate(
  36. remain - allocated,
  37. path + [f"{layer_idx+1}_{loc_type}"],
  38. new_pressure,
  39. new_state,
  40. depth + 1
  41. )
  42. if result:
  43. return result
  44. return None
  45. return allocate(total_pallets, [], current_pressure, layer_capacity)
  46. @staticmethod
  47. def format_solution(solution):
  48. result = defaultdict(lambda: defaultdict(int))
  49. for item in solution:
  50. parts = item.split('_')
  51. if len(parts) == 2:
  52. layer, loc_type = parts
  53. result[layer][loc_type] += 1
  54. return json.dumps(result)
  55. @staticmethod
  56. def allocation_plan_left_right(location_type_list,batch_number,start_location,container_code):
  57. locations=[]
  58. existing_solution = alloction_pre.objects.filter(batch_number=batch_number).first()
  59. for layer, location_type_dict in location_type_list.items():
  60. if not location_type_dict:
  61. continue
  62. # 获取库位类型列表
  63. location_type = list(location_type_dict.keys())
  64. demand_number = sum(location_type_dict.values())
  65. print (f"[1]层{layer} 需求数量: {demand_number}, 库位: {location_type}")
  66. location_groups = LocationGroupModel.objects.filter(
  67. group_type__in=location_type,
  68. layer=layer,
  69. status='available'
  70. )
  71. if not location_groups:
  72. print(f"层{layer} 无库位")
  73. # 根据起始位置选择排序字段
  74. if start_location == '203':
  75. ordered_groups = location_groups.order_by('left_priority')
  76. elif start_location == '103':
  77. ordered_groups = location_groups.order_by('right_priority')
  78. else:
  79. ordered_groups = location_groups.none()
  80. number = 0
  81. for location_group in ordered_groups:
  82. if number >= demand_number:
  83. break
  84. locations.append(f"{layer}_{location_group.id}")
  85. number += 1
  86. existing_solution.layer_solution_type = locations
  87. existing_solution.save()
  88. print(f"[2]分配方案: {locations}")
  89. return locations if locations else None
  90. def generate_WCS_location(location_list_cnumber):
  91. allocation_target_location = (
  92. location_list_cnumber.warehouse_code + '-'
  93. + f"{int(location_list_cnumber.row):02d}" + '-'
  94. + f"{int(location_list_cnumber.col):02d}" + '-'
  95. + f"{int(location_list_cnumber.layer):02d}"
  96. )
  97. return allocation_target_location
  98. def generate_WMS_location(location):
  99. # location = 'SZ-01-01-01'
  100. # if location == '203':
  101. # warehouse_code
  102. # elif location == '103':
  103. # return 'SZ-01-01-02'
  104. # else:
  105. warehouse_code, row, col, layer = location.split('-')
  106. from .models import LocationModel
  107. location_obj = LocationModel.objects.filter(warehouse_code=warehouse_code, row=row, col=col, layer=layer).first()
  108. return location_obj