algorithms.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  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: (abs(x[1]-remain), -x[1])
  23. )
  24. for loc_type, cap in candidates:
  25. new_state = copy.deepcopy(layer_state)
  26. new_state[layer_idx][loc_type] -= 1
  27. # new_pressure = [p-1 if p>0 else 0 for p in pressure]
  28. new_pressure = [p if p>0 else 0 for p in pressure]
  29. allocated = min(cap, remain)
  30. new_pressure[layer_idx] += allocated
  31. result = allocate(
  32. remain - allocated,
  33. path + [f"{layer_idx+1}_{loc_type}"],
  34. new_pressure,
  35. new_state,
  36. depth + 1
  37. )
  38. if result:
  39. return result
  40. return None
  41. return allocate(total_pallets, [], current_pressure, layer_capacity)
  42. @staticmethod
  43. def format_solution(solution):
  44. result = defaultdict(lambda: defaultdict(int))
  45. for item in solution:
  46. parts = item.split('_')
  47. if len(parts) == 2:
  48. layer, loc_type = parts
  49. result[layer][loc_type] += 1
  50. return json.dumps(result)
  51. @staticmethod
  52. def allocation_plan_left_right(location_type_list,batch_number,start_location,container_code):
  53. locations=[]
  54. existing_solution = alloction_pre.objects.filter(batch_number=batch_number).first()
  55. for layer, location_type_dict in location_type_list.items():
  56. if not location_type_dict:
  57. continue
  58. # 获取库位类型列表
  59. location_type = list(location_type_dict.keys())
  60. demand_number = sum(location_type_dict.values())
  61. print (f"[1]层{layer} 需求数量: {demand_number}, 库位: {location_type}")
  62. location_groups = LocationGroupModel.objects.filter(
  63. group_type__in=location_type,
  64. layer=layer,
  65. status='available'
  66. )
  67. if not location_groups:
  68. print(f"层{layer} 无库位")
  69. # 根据起始位置选择排序字段
  70. if start_location == '203':
  71. ordered_groups = location_groups.order_by('left_priority')
  72. elif start_location == '103':
  73. ordered_groups = location_groups.order_by('right_priority')
  74. else:
  75. ordered_groups = location_groups.none()
  76. number = 0
  77. for location_group in ordered_groups:
  78. if number >= demand_number:
  79. break
  80. locations.append(f"{layer}_{location_group.id}")
  81. number += 1
  82. existing_solution.layer_solution_type = locations
  83. existing_solution.save()
  84. print(f"[2]分配方案: {locations}")
  85. return locations if locations else None
  86. def generate_WCS_location(location_list_cnumber):
  87. allocation_target_location = (
  88. location_list_cnumber.warehouse_code + '-'
  89. + f"{int(location_list_cnumber.row):02d}" + '-'
  90. + f"{int(location_list_cnumber.col):02d}" + '-'
  91. + f"{int(location_list_cnumber.layer):02d}"
  92. )
  93. return allocation_target_location