2022 전국 대학원 수학적 모델링 대회 화웨이 컵 문제 B 정사각형 부품 조립 배치 최적화 문제 해결 전체 프로세스에 대한 문서화 및 절차

2022 전국 대학원 수학 모델링 대회 화웨이 컵

문제 B: 사각형 부품 조립 배치 최적화 문제

재현된 원본 제목:

  배경 소개
  지능형 제조는 "Made in China 2025"의 주요 방향으로 지정되었으며 개인화된 맞춤화, 짧은 제품 및 시스템 수명 주기, 상호 연결된 서비스 모델 등은 지능형 제조 전환에서 기업의 주요 경쟁 포인트가 되었습니다. 전자 장치, 자동차, 항공 우주 부품 등과 같은 개별 산업의 제품을 예로 들어 보겠습니다. 이러한 제품은 모두 기계 설계에 의존하고 분산 처리가 가능하며 유연하게 조립할 수 있으며 유사한 제품의 스타일이 다양합니다. 이러한 제품의 경우 고객은 무한한 제품 수요, 예측할 수 없는 주문 규모, 극도로 높은 제품 품질 요구 사항을 가질 수 있습니다. 현재 "개인화 맞춤화"에 대한 서비스 수요는 기업이 효율적이고 빠른 수요 분석 및 제품 설계 능력, 유연하고 간결한 생산 프로세스, 완벽하고 정교한 전체 프로세스 생산 제어 능력을 요구합니다.
  사각파츠제품(플레이트제품이라고도 함)은 플레이트를 주원료로 하고, 평면가공 후 여러 개의 플레이트 액세서리를 조립하여 성형한 제품의 일종입니다. 3C(컴퓨팅, 통신, 가전제품), 패널 가구, 유리, 판금 부품 및 기타 산업과 같은 일반적인 사각형 부품 제품 제조 회사는 대부분 "다품종 및 소량 배치" 맞춤형 맞춤형 생산을 채택하고 있습니다. 기업 주문, 생산 조직은 일반적으로 주문 일괄 처리를 사용하여 일괄 절단을 달성하고 원자재 활용률을 향상시키는 "주문 일괄 처리 + 대량 생산 + 주문 정렬" 모델을 채택합니다. 처리가 완료된 후 다른 고객에 따라 정렬됩니다. 명령.
  위에서 언급한 개인화 맞춤형 생산 모델에서 주문 배치 및 레이아웃의 최적화는 매우 중요하며, 주문 배치는 서로 다른 주문을 여러 배치로 결합하여 주문의 배치 생산을 달성하는 것입니다. 소규모 배치, 다양한 품종 및 대규모 주문의 배치 생산 시 배치가 너무 작으면 재료 활용률이 낮아지고 생산 효율성도 낮아집니다. 배치가 너무 크면 재료 활용률이 낮아집니다. 증가하지만 주문 배송 시간을 보장할 수 없고, 주문 분류가 더 어려워지고, 생산 효율성이 떨어지고, 버퍼 용량이 부족하여 혼잡이 발생하므로 개인화와 생산 효율성 간의 모순을 해결해야 합니다.
  레이아웃 최적화는 본질적으로 블랭킹 문제(절단 및 채우기 문제라고도 함)입니다.최적화의 목적은 플레이트의 사각형 부품 레이아웃을 합리적으로 계획하여 블랭킹 과정에서 플레이트의 낭비를 줄이고 절단 과정을 단순화하는 것입니다. 이 문제는 계산 복잡도가 높은 조합 최적화 문제이며 운영 연구의 중요한 분야이기도 합니다. 많은 제조회사의 생산체인에서 제품 및 부품 생산의 첫 번째 단계로서 블랭킹은 과소평가할 수 없는 재료와 자원을 소모합니다. 에너지 낭비와 환경적 책임을 맡아 해결해야 할 핵심 문제입니다.
  문제 설명
  주문 일괄 처리 문제: 주문 배송 시간, 장비 용량 부하, 저장 용량, 자재 활용도, 생산 효율성, 생산 프로세스 제약 조건 등과 같은 요소를 고려하여 생산 주문 일괄 처리를 최적화합니다. 동일한 자재, 유사한 납기, 유사한 프로세스의 주문을 동일한 생산 배치로 배열하고, 주문 배치 최적화를 통해 납기 보장, 원자재 활용률 향상, 장비 생산 효율성 향상 등을 수행합니다. 데이터의 통일된 처리를 용이하게 하고 문제의 본질을 반영하기 위해 이번 대회의 모든 주문에 대한 배송 날짜는 동일하며 구별이 없습니다. 배치는 여러 주문의 모든 작업을 완료하고 완료되지 않은 주문 작업을 포함하지 않는 주문 모음으로 정의됩니다.
  블랭킹 최적화 문제(레이아웃 최적화 문제라고도 함): 동일한 생산 배치의 정사각형 부품의 크기 및 수량에 따라 원본 조각의 사양 및 수량을 선택하고 블랭킹 및 레이아웃을 최적화하여 원본의 활용률을 극대화합니다. 시트. 절단 공정의 공정 요구 사항에 따라 레이아웃 계획은 "단두대 절단이라고도 함"(단두대 절단이라고도 함) 제약 조건을 충족해야 합니다. 모든 직선 절단은 보드가 분리 가능해야 합니다. 즉, 각 직선 cut은 보드를 두 조각으로 분리합니다). 블랭킹 최적화 문제는 "하나의 크기가 모든 것에 적합" 제약이 있는 플레이트 프로파일 사각형 부분 레이아웃 최적화 문제에 속합니다.
  절단 공정의 다양한 방법을 고려하면 길로틴 절단과 비단두대 절단으로 구분할 수 있습니다(그림 1 참조). 길로틴 절단은 정밀한 방법과 비정밀 방법으로 세분할 수 있습니다(절단 단계 수에 따라). ) 그림 2의 3단계 레이아웃 방식은 크게 3단계 비정확 레이아웃 방식(3NE), 3단계 동질 레이아웃 방식(3E), 3단계 동질 레이아웃 방식으로 나뉜다. 방법(3H). 그 중 3E와 3H 레이아웃 방식은 정사각형 부품을 3단계로 정확한 치수로 절단할 수 있으므로 둘 다 정확한 레이아웃 방식이다. 3NE 레이아웃 방법에서 일부 정사각형 부품은 크기 요구 사항을 충족하기 위해 추가적인 4단계 절단이 필요합니다.
여기에 이미지 설명을 삽입하세요.
  문서마다 절단 단계가 다르기 때문에 문서마다 절단 단계별로 명칭이 다르며, 이해를 돕고 표현 형태의 통일성을 위해 주요 단계 모듈에 대한 설명은 영어를 사용한다.자세한 내용은 그림 3을 참조한다. (실제 절단 과정에서 A 칼은 긴 변에 수직이거나 짧은 변에 수직일 수 있습니다. 그림 3은 한 변에 수직을 예로 들어 설명합니다.)
여기에 이미지 설명을 삽입하세요.
  공통 단은 최대 3~4개이므로 3단 절단 방식을 예로 들면(그림 3), 1단의 가로 절단 생성 모듈을 Stripe1, Strip2와 같이 스트라이프(stripe)라고 하고, 2단은 수직 단계의 절단 생성 모듈을 스택(stack)이라고 하며, 예를 들어 Strip1이 계속해서 Stack1, Stack2, Stack3으로 절단되고, 3단계 수평 절단 생성 모듈을 아이템(제품 품목)이라고 하며, Stack1이 계속해서 절단됩니다. Item1, Item2 및 Item3으로 잘라냅니다.
  이 경쟁 질문은
  두 개의 하위 문제로 구성됩니다. 두 번째 하위 문제의 제약 조건은 첫 번째 하위 문제를 기반으로 하고 호환되지만 두 하위 문제에서 제공하는 데이터는 관련이 없습니다. 개념 정의 및 프로세스 설명이 업계의 것과 다른 경우 이 경쟁 질문이 우선합니다. 이 질문은 다음을 가정합니다.
  1. 플러시 절단의 절단 방법만 고려됩니다(직선 절단, 절단 방향은 보드의 한쪽 가장자리에 수직이며 각 직선 절단 중에 보드가 두 조각으로 분리될 수 있음이 보장됩니다). 라인 커팅) 2. 커팅 단계 수는 3개를 초과하지 않으며
  동일 각 단계의 커팅 방향은 동일함
  3. 레이아웃 방법은 정밀 레이아웃임
  4. 원본 시트는 하나만 있다고 가정 사양 및 충분한 수량;
  5. 레이아웃 계획에서는 톱 절단 폭(즉, 절단 간격의 폭)의 영향을 고려할 필요가 없습니다.
  하위 문제 1: 레이아웃 최적화 문제. 생산 주문 요구 사항 및 관련 제약 사항을 충족하면서 판재의 양을 최대한 줄이기 위한 혼합 정수 프로그래밍 모델의 구축이 필요합니다.
  제약사항:
  1. 동일한 스택에 있는 제품 항목의 너비(또는 길이)가 동일해야 합니다.
  2. 최종 절단으로 생성된 제품 항목은 완전하고 접합되지 않습니다.
  이 하위 문제에는 데이터 세트 A를 입력으로 사용하여 프로그래밍이 필요하며 출력 요구 사항은 5부에 표시됩니다.
  하위 문제 2: 주문 일괄 처리 문제. 데이터 세트 B의 모든 주문을 배치로 그룹화한 다음 각 배치를 독립적으로 배열하는 혼합 정수 프로그래밍 모델을 구축하여 주문 요구 사항 및 관련 제약 조건을 충족하면서 사용되는 원본 시트의 양을 가능한 한 적게 해야 합니다. .
  하위 문제 1의 제약 조건을 충족하는 것에 기초하여 추가 요구 사항이 필요합니다:
  1) 각 주문은 배치로만 나타나야 합니다.
  2) 각 배치에서 동일한 재료의 제품 항목(항목)은 동일한 판 원재료를 사용할 수 있습니다. 3) 처리 링크
  의 빠른 흐름을 보장하기 위해 각 배치의 총 제품 항목(항목) 수는 제한을 초과할 수 없습니다.
  4) 공장 용량 제한으로 인해 각 항목의 총 면적은 제한됩니다. 제품 항목(항목) 배치는 제한 값을 초과할 수 없습니다.
이 하위 질문에는 프로그래밍이 필요하고 데이터 세트 B를 입력으로 사용하며 출력 결과 요구 사항은 5부에 표시됩니다.

전체 솔루션 프로세스 개요(요약)

  본 논문에서는 혼합정수계획법 모델의 해결을 위해 반복법과 K-Means 군집분석법을 사용하여 정사각형 부분의 배열 최적화 및 배치 문제를 연구한다.
  문제 1에서는 패널의 절단 문제를 프로젝트 부품의 적층 문제로 처리합니다. 먼저, 원본 필름 소모품의 최소 수량을 목적 함수로 사용하여 주어진 제약 조건을 갖는 혼합 정수 프로그래밍 모델 I을 구축합니다. 각 아이템은 한번 쌓아야 하며, 스택의 높이가 적당해야 한다고 규정하고 있으므로 더미변수 α, β, γ를 설정하여 아이템, 스택, 스트라이프, 빈이 순차적으로 포함되는지를 결정한다. 품목의 스택 높이는 8개로 제한됩니다. 스택의 높이를 초과해야 하며, 스택의 너비는 원본 조각의 너비를 초과해서는 안 되며, 스트립의 높이는 원본 조각의 높이를 초과해서는 안 됩니다. 실제 응용에서는 항목의 높이 h를 레이아웃의 기초로 사용하고 모델 I에 넣어 더미 변수 매개변수 값인 α, β, γ,… 스택의 수치적 인덱스를 알 수 없으므로 조정 매개변수 H, 평균, 중앙값을 설정하여 모형을 최적화하였고, 최종적으로 정렬용 높이, 평균, 중앙값을 조정 매개변수로 사용한 모형이 가장 좋은 피팅 효과를 갖는 것으로 나타났다. 데이터 세트 A에서는 평균 플레이트 사용률이 94.06%에 달했습니다.
  두 번째 질문에서는 주문 번호를 일괄 처리할 수 없고 판재가 다르기 때문에 데이터 양이 많을 때 주문이 제한된 부품의 일괄 처리 문제를 해결하는 것을 고려할 필요가 있습니다. 먼저 동일한 주문 번호를 모아서 소재 관련 지수 구성 매트릭스를 K-Means 클러스터링의 기반으로 설정하고 단일 배치의 총 제품 품목 수를 1,000개로 제한하고 총 면적의 상한을 제한합니다. ​​단일 제품 배치는 250 평방 미터입니다. 유클리드 거리와 클래스 평균 거리를 통해 클러스터 패밀리를 나누고, 분류 요구 사항을 충족하는 최소 카테고리 수 K를 찾고, 최적의 실행 가능한 솔루션을 찾고 제품 항목이 일괄 처리될 때까지 하이퍼 매개 변수 max_order, min_order 및 K를 지속적으로 조정합니다. 제품 항목이 일괄 완성된 후 각 배치의 서로 다른 재료의 제품 항목을 그룹화하고 각 그룹마다 Model I의 레이아웃 최적화 방법을 별도로 사용하여 최종 출력 결과가 83.32%입니다.
  본 글의 1번 문제의 반복 메소드 솔루션 코드는 타사 라이브러리를 호출하지 않고, 모두 자체적으로 작성 및 캡슐화되어 있으며, 작업 속도가 빠르고 수정 가능성이 강한 특징을 갖고 있습니다. 이 기사에서는 정사각형 부품의 주문 일괄 처리 및 레이아웃 최적화 모델링 결과가 상대적으로 견고하며 수하물 문제 및 블랭킹 문제에 대한 확실한 지침을 제공할 수 있습니다. 또한 PCB 회로 기판, 반시 가구, 3C 가전 제품 및 기타 분야에도 실용적입니다. .응용 프로그램에는 특정 참조 값이 있습니다.

모델 가정:

  1. 원본 조각의 사양이 균일하고 재료가 고르게 분포되어 불순물 영역이 없습니다.
  2. 절단 공정은 정면 절단 방식을 채택합니다.
  3. 완성된 부품이 서로 독립적이며 겹치는 부분이 없습니다. 제품간 [3]
  4. 컷팅된 제품이 완성되어 스플라이싱을 할 수 없음
  5. 첫 번째 컷은 원본 피스의 짧은 변의 수평 방향과 평행함
  6. 각각의 컷은 항상 수직 방향임 이전 컷의 컷팅 방향 [4]
  7. 컷팅의 최대 3단계만 고려됩니다
  8. ​​레이아웃 이 방법은 정확한 레이아웃만 고려합니다.

문제 분석:

  문제 1의 분석 문제
  1에서는 플레이트의 레이아웃을 최적화하고 원본 플레이트의 가능한 최소 소비를 얻기 위해 혼합 정수 프로그래밍 모델을 구축해야 합니다. 이 목표를 달성하기 위해 원본 필름 소모품의 최소 수량을 목적 함수로 간주하고 제약 조건을 충분히 고려한 기반으로 bin(원본 필름), 스트라이프(스트립), 스택(스택), 항목( 제품 항목) ), 각 절단 단계 간의 특정 연결을 해석하고 일치하는 매개변수를 설정함으로써 이 질문의 목표와 관련된 방정식 시스템을 구축할 수 있습니다. 후진적 사고방식을 사용하여 원본 필름의 절단 문제를 순서 부분의 결합 문제로 간주하여 필요한 순서 부분을 쌓고, 항목을 스택으로 결합하고, 스택을 줄무늬로 결합한 후 줄무늬를 쌓는다. 이를 조합하여 나머지 부분을 구성하고, 정보를 수집하면 최종적으로 제목에 따른 원본 영화가 형성됩니다. 모델을 결정한 후에는 먼저 반복적 방법을 사용하여 주문 요구 사항을 지속적으로 입력하여 국소 최적 솔루션을 찾는 것을 고려하십시오.
  질문 2 분석
  질문 1을 기반으로 질문 2에는 새로운 제약 조건이 추가됩니다.첫 번째는 배치 항목에 대한 제한으로 각 배치의 제품 항목 수는 1,000개를 초과할 수 없으며 단일 항목의 총 면적은 1,000개를 초과할 수 없습니다. 제품 품목의 배치는 1,000개를 초과할 수 없으며, 250제곱미터를 초과할 수 없습니다. 둘째, 주문 번호와 자재는 배치 분할의 기준으로 제공됩니다. 동일한 주문을 다른 배치로 분할할 수 없습니다. , 주문마다 재료가 다를 수 있습니다. 이를 위해서는 먼저 제약 조건에 따라 주문을 분류한 다음 분류된 각 배치의 레이아웃을 개별적으로 최적화해야 합니다. 레이아웃 최적화가 주요 문제로 간주된다면 배치 문제는 3단계 레이아웃의 하위 문제로 간주될 수 있습니다. 주문 배치 문제[1]에 직면하여, 우리는 먼저 제품 부품을 주문 번호에 따라 하나의 카테고리로 분류한 다음 제약 조건을 적용하여 K-Means 클러스터링을 수행하는 것을 고려합니다. 플레이트 원본 필름의 활용률이 높으며 동일한 배치에 동일한 재료가 최대한 포함되어야 합니다. 클러스터링이 완료된 후 각 카테고리를 배치로 분류하고, 문제 1의 혼합 정수 프로그래밍 모델을 사용하여 각 배치에서 서로 다른 재질의 제품 항목을 반복하여 최종적으로 각 배치의 대략적인 해를 구합니다 [2] .

모델 구축 및 솔루션 종합 논문 썸네일

여기에 이미지 설명을 삽입하세요.

여기에 이미지 설명을 삽입하세요.

모든 논문은 아래 "QQ 명함만 모델링"을 참고하시고, QQ 명함을 클릭하시면 됩니다.

암호:

일부 Python 프로그램은 다음과 같습니다.

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import os
import time
import pandas as pd
from demo import Cycle_solution_A
# 衡量指标
def metrics(data, number, max_length, max_width):
 """
 :parameter
 data:[[序号:index, 订单 id:item_id, 订单材料:item_material, 订单所需要数
量:item_num, 材料长度:item_length, 材料宽度:item_width, 订单号:item_order]*size]
 number:消耗的总板材
 max_length:板材长
 max_width:板材宽
 """
 total_item = 0.
 for vector in data:
 total_item += vector[4] * vector[5]
 run_rate = total_item / (number*max_length*max_width)
 return run_rate
# 问题一
# 加载数据
file_A = []
for i in range(1, 5):
 file_path = os.path.join(r"E:\python document\challenge\2022 年 B 题\子问题 1-数
据集 A", "dataA"+str(i)+".csv")
 if os.path.exists(file_path):
 file_A.append(pd.read_csv(file_path))
data_A_lis = []
avg_length = []
for i in file_A:
 avg_length.append(i['item_length'].mean())
 j = i.sort_values(by='item_length', ascending=False)
 j = j.values.tolist()
 data_A_lis.append(j)
# [序号:index, 订单 id:item_id, 订单材料:item_material, 订单所需要数量:item_num, 
材料长度:item_length, 材料宽度:item_width, 订单号:item_order]
print(data_A_lis)
# 参数
max_length = 2440
max_width = 1220
path = r"E:\python document\challenge\2022 年 B 题\solution_A"
f_txt = open(r"E:\python document\challenge\2022 年 B 题\solution_A\min_n.txt", "w")
# 求解
min_n_data_A = []
rate_A_lis = []
run_time_lis = []
_time = time.time()
for A_index, data_set in enumerate(data_A_lis):
 data_size = len(data_set)
 paths = os.path.join(path, "A{0}".format(A_index+1))
 solution = Cycle_solution_A(data_size, paths, avg_length[A_index], max_length, 
max_width)
 min_n, cut_program = solution.cycle_com(data_set)
 cut_program.to_csv(r"E:\python document\challenge\2022 年 B 题
\solution_A\A{
    
    0}\data_A{
    
    0}_cut_program.csv".format(A_index+1), index=None, 
encoding='utf_8_sig')
 rate = metrics(data_set, min_n, max_length, max_width)
 run_time_lis.append(time.time() - _time)
 min_n_data_A.append(min_n)
 rate_A_lis.append(rate)
 print("data_A{0}:finish".format(A_index+1))
f_txt.write("min_n_data_A:" + "\n")
f_txt.write(str(min_n_data_A) + "\n" + "\n")
f_txt.write("rate_A_lis:" + "\n")
f_txt.write(str(rate_A_lis) + "\n" + "\n")
f_txt.write("run_time:" + "\n")
f_txt.write(str(run_time_lis) + "\n" + "\n")
print(min_n_data_A)
print(rate_A_lis)
class Cycle_solution_A():
def __init__(self, data_size, path, average_length, max_length=2440, 
max_width=1220):
 self.max_length = max_length
 self.path = path
 self.average_length = average_length
 self.max_width = max_width
 self.data_size = data_size
 # alpha、beta、gamma 的定义
 self.alpha = []
 self.beta = []
 self.gamma = []
 for j in range(data_size):
 self.alpha.append([0 if j > i else 1 for i in range(data_size)])
 for j in range(data_size):
 self.beta.append([0 if j > i else 1 for i in range(data_size)])
 for j in range(data_size):
 self.gamma.append([0 if j > i else 1 for i in range(data_size)])
 def cycle_com(self, data):
 """
 :parameter
 data:[[序号:index, 订单 id:item_id, 订单材料:item_material, 订单所需要
数 量 :item_num, 材 料 长 度 :item_length, 材料宽度 :item_width, 订 单
号:item_order]*size]
 """
 stack_lis, info_stack_lis, alpha = self.item_into_stack(data, self.alpha)
 stripe_lis, stripe_index_lis, info_stripe_lis, beta = 
self.stack_into_stripe(stack_lis, info_stack_lis, self.beta)
 bin_lis, bin_lis_index, info_bin_lis, gamma = self.stripe_into_bin(stripe_lis, 
info_stripe_lis, self.gamma)
 file = self.picture(data, stack_lis, info_stack_lis, stripe_lis, info_stripe_lis, 
bin_lis)
 min_number = 0
 for index, i in enumerate(gamma):
 min_number += i[index]
 return min_number, file
 def item_into_stack(self, data, alpha):
 # 构造出 stack stak:[list1, list2,....],list 的第一个元素为 stack 的计算标号
 stack_lis = []
 for item_index, item in enumerate(data):
 if len(stack_lis) == 0:
stack_lis.append([item_index+1])
 else:
 for index, i in enumerate(stack_lis):
 if data[i[0] - 1][5] == item[5]:
 stack_length = 0
for j in i:
 stack_length += data[j-1][4]
 if stack_length + item[4] <= self.average_length:
 stack_lis[index].append(item_index+1)
 else:
 # 转换 h 和 w
 # if data[i[0] - 1][5] == item[4]:
 # data[item_index][4], data[item_index][5] = 
data[item_index][5], data[item_index][4]
 # if stack_length + item[4] <= 
self.average_length:
 # stack_lis[index].append(item_index + 1)
 # else:
 # stack_lis.append([item_index+1])
stack_lis.append([item_index+1])
break
 else:
 continue
 sum = 0
 for i in stack_lis:
 for j in i:
 if item_index + 1 == j:
 sum += 1
 if sum == 0:
 stack_lis.append([item_index + 1])
 # 处理 alpha
 for vector in stack_lis:
 # 计算序号变为 python 序号
 set_vector = []
 for number in vector:
 set_vector.append(number - 1)
 cycle_set = list(set(range(self.data_size)) - set(set_vector))
 for j in cycle_set:
 alpha[vector[0] - 1][j] = 0
 if len(vector) > 1:
 for j in vector[1:]:
 for k in range(self.data_size):
 alpha[j - 1][k] = 0
 # 输出 stack 的高度和宽度信息(先高后宽)
info_stack = [[],[]]
 for i in stack_lis:
 stack_length = 0
 for j in i:
 stack_length += data[j - 1][4]
 info_stack[0].append(stack_length)
 info_stack[1].append(data[i[0] - 1][5])
 return stack_lis, info_stack, alpha
 def stack_into_stripe(self, stack, info_stack, beta):
 # 先对 stack 做一次排序
 stack_length = info_stack[0]
 stack_width = info_stack[1]
 sort_stack = []
 for index, i in enumerate(stack_width):
 sort_stack.append([stack_length[index], i, stack[index]])
 # 排序
 n = len(sort_stack)
 for i in range(n):
 min = i
 for j in range(i+1, n):
 if sort_stack[j][0] < sort_stack[min][0]:
 min = j
 sort_stack[min], sort_stack[i] = sort_stack[i], sort_stack[min]
 sort_stack = sort_stack[::-1]
 # 分出数据
 finish_sort_stack = []
 sort_info_stack = []
 for i in sort_stack:
 sort_info_stack.append([i[0], i[1]])
 finish_sort_stack.append(i[2])
 # 构造出 stripe, stripe:[[number,element1, element2, ....], .....],number 为其
序号,element 为包含的 stack 序号
 stripe_lis = []
 for item_index, item in enumerate(finish_sort_stack):
 if len(stripe_lis) == 0:
 stripe_lis.append([item_index])
 else:
 for i_index, i in enumerate(stripe_lis):
 stripe_width = 0
for j in i:
 stripe_width += sort_info_stack[j][1]
 if stripe_width + sort_info_stack[item_index][1] <= 
self.max_width:
 stripe_lis[i_index].append(item_index)
break
 else:
 continue
 sum = 0
 for i in stripe_lis:
 for j in i:
 if item_index == j:
 sum += 1
 if sum == 0:
 stripe_lis.append([item_index])
 # 输出 stripe 的宽度信息
 info_stripe = []
 max_length_index = []
 for v_index, vector in enumerate(stripe_lis):
 stripe_width = 0
 stripe_length = []
 for j_index, j in enumerate(vector):
 stripe_length.append(sort_info_stack[j][0])
 stripe_width += sort_info_stack[j][1]
 info_stripe.append([max(stripe_length), stripe_width])
 max_length_index.append(stripe_length.index(max(stripe_length)))
 # 将 stripe 做序号转变
 true_stripe_lis = []
 for v_index, vector in enumerate(stripe_lis):
 max_index = max_length_index[v_index]
 true_stripe_lis.append([finish_sort_stack[vector[max_index]][0]])
 for j_index, j in enumerate(vector):
 true_stripe_lis[v_index].append(finish_sort_stack[j][0])
 # 处理 beta
 first_vector = []
 for vector in true_stripe_lis:
 # 计算序号变为 python 序号
 first_vector.append(vector[0]-1)
 set_vector = []
 for number in vector[1:]:
 set_vector.append(number - 1)
 cycle_set = list(set(range(self.data_size)) - set(set_vector))
 for j in cycle_set:
 beta[vector[0] - 1][j] = 0
 zero_lis = list(set(range(self.data_size)) - set(first_vector))
 for i in zero_lis:
 for j in range(self.data_size):
 beta[i][j] = 0
 return true_stripe_lis, stripe_lis, info_stripe, beta
 def stripe_into_bin(self, stripe, info_stripe, gamma):
# 先对 stack 做一次排序
 sort_stripe = []
 for index, i in enumerate(stripe):
 sort_stripe.append([info_stripe[index][0], info_stripe[index][1], i])
 # 排序
 n = len(sort_stripe)
 for i in range(n):
 min = i
 for j in range(i + 1, n):
 if sort_stripe[j][0] < sort_stripe[min][0]:
 min = j
 sort_stripe[min], sort_stripe[i] = sort_stripe[i], sort_stripe[min]
 sort_stripe = sort_stripe[::-1]
 # 分出数据
 finish_sort_stripe = []
 sort_info_stripe = []
 for i in sort_stripe:
 sort_info_stripe.append([i[0], i[1]])
 finish_sort_stripe.append(i[2])
 # 构造出 bin, bin:[[number,element1, element2, ....], .....],number 为其序,element 为包含的 bin 序号
 bin_lis = []
 for item_index, item in enumerate(finish_sort_stripe):
 if len(bin_lis) == 0:
 bin_lis.append([item_index])
 else:
 for i_index, i in enumerate(bin_lis):
 bin_length = 0
for j in i:
 bin_length += sort_info_stripe[j][0]
 if bin_length + sort_info_stripe[item_index][0] <= 
self.max_length:
 bin_lis[i_index].append(item_index)
break
 else:
 continue
 sum = 0
 for i in bin_lis:
 for j in i:
 if item_index == j:
 sum += 1
 if sum == 0:
 bin_lis.append([item_index])
 # 输出 bin 的高宽信息
 info_bin = []
max_length_index = []
 for v_index, vector in enumerate(bin_lis):
 bin_width = []
 bin_length = 0
 for j_index, j in enumerate(vector):
 bin_width.append(sort_info_stripe[j][1])
 bin_length += sort_info_stripe[j][0]
 info_bin.append([bin_length, max(bin_width)])
 max_length_index.append(bin_width.index(max(bin_width)))
 # 将 bin 做序号转变
 true_bin_lis = []
 for v_index, vector in enumerate(bin_lis):
 
true_bin_lis.append([finish_sort_stripe[vector[max_length_index[v_index]]][0]])
 for j_index, j in enumerate(vector):
 true_bin_lis[v_index].append(finish_sort_stripe[j][0])
 # 处理 gamma
 first_vector = []
 for vector in true_bin_lis:
 # 计算序号变为 python 序号
 first_vector.append(vector[0] - 1)
 set_vector = []
 for number in vector[1:]:
 set_vector.append(number - 1)
 cycle_set = list(set(range(self.data_size)) - set(set_vector))
 for j in cycle_set:
 gamma[vector[0] - 1][j] = 0
 zero_lis = list(set(range(self.data_size)) - set(first_vector))
 for i in zero_lis:
 for j in range(self.data_size):
 gamma[i][j] = 0
 return true_bin_lis, bin_lis, info_bin, gamma
 def picture(self, data, stack_lis, info_stack_lis, stripe_lis, info_stripe_lis, bin_lis):
 # 找出每个 bin 所含的订单 id
 # 制作 bin、stripe、stack 的高宽信息字典
 info_stack_dict = {
    
    }
 for stack_index, stack_i in enumerate(stack_lis):
 info_stack_dict[stack_i[0]] = [info_stack_lis[0][stack_index], 
info_stack_lis[1][stack_index]]
 info_stripe_dict = {
    
    }
 for stripe_index, stripe_i in enumerate(stripe_lis):
 info_stripe_dict[stripe_i[0]] = info_stripe_lis[stripe_index]
 stripe_dict = {
    
    }
 for v_index, vector in enumerate(stripe_lis):
tem in enumerate(stack):
 all_bin_lis[b_index][sp_index + 1][sc_index + 1][it_index] 
= [item, stack_dict.get(item)]
 # 制作 cut_program.csv 表
 # 小心计算序号是 1 到 n,引用序号要变成 0 到 n-1
 # [材质, bin_index, item_index, 起点 x 坐标, 起点 y 坐标, x 方向长度(width), 
y 方向长度(length)]
 cut_program_lis = []
 for bin_index, bin in enumerate(all_bin_lis):
 # 整个图
 fig, ax = plt.subplots()
 ax.spines['right'].set_visible(False)
 ax.spines['top'].set_visible(False)
 ax.spines['left'].set_visible(False)
 ax.spines['bottom'].set_visible(False)
 ax.plot([0, 1220], [0, 0], color="k", linewidth=2.5)
 ax.plot([1220, 1220], [0, 2440], color="k", linewidth=2.5)
 ax.plot([0, 0], [0, 2440], color="k", linewidth=2.5)
 ax.plot([0, 1220], [2440, 2440], color="k", linewidth=2.5)
 # stripe 的直线位置
 total_stripe_length = 0.
 for stripe_index, stripe in enumerate(bin[1:]):
 stripe_length, stripe_width = info_stripe_dict.get(stripe[0])[0], 
info_stripe_dict.get(stripe[0])[1]
 total_stripe_length += stripe_length
 ax.plot([0, 1220], [total_stripe_length, total_stripe_length], color="k", 
linewidth=2)
 # stack 的竖线位置
 total_stack_width = 0.
 for stack_index, stack in enumerate(*stripe[1:]):
stack_length, stack_width = info_stack_dict.get(stack[0])[0], 
info_stack_dict.get(stack[0])[1]
 total_stack_width += stack_width
ax.plot([total_stack_width, total_stack_width], 
[total_stripe_length - stripe_length, total_stripe_length], color="g", linewidth=1.5)
 # item 的位置
 total_item_length = 0.
 for item_index, item in enumerate(*stack[1:]):
 item_length, item_width = data[item - 1][4], data[item - 1][5]
 total_item_length += item_length
 cut_program_lis.append([data[item - 1][2], bin[0], data[item - 1][1], 
total_stack_width - stack_width, total_item_length - item_length + total_stripe_length -
stripe_length, stack_width, item_length])
 ax.plot([total_stack_width - stack_width, total_stack_width], 
[total_item_length + total_stripe_length - stripe_length, total_item_length+ 
total_stripe_length - stripe_length], color="y", linewidth=1)
 adjust_text([ax.text(x=(total_stack_width - stack_width + 
total_stack_width) / 2, y= (total_item_length - 3*item_length/10) + total_stripe_length -
stripe_length , rotation=60, s="id:{0}".format(data[item - 1][1]), ha="left")])
 ax.fill_between([total_stack_width - stack_width, total_stack_width], 
total_item_length + total_stripe_length - stripe_length, stripe_length + total_stripe_length 
- stripe_length, facecolor='dimgray', alpha=1)
 ax.fill_between([total_stack_width, 1220], total_stripe_length - stripe_length, 
total_stripe_length, facecolor='dimgray', alpha=1)
 ax.fill_between([0, 1220], total_stripe_length, 2440, facecolor='dimgray', alpha=1)
 paths = os.path.join(self.path, "cutting_pic{0}.jpg".format(bin[0]))
 plt.savefig(paths)
 plt.close()
cut_program = pd.DataFrame(cut_program_lis)
cut_program.columns = ['原片材质', '原片序号', '产品 id', '产品 x 坐标', '产品 y 坐标', '
产品 x 方向长度', '产品 y 方向长度']
return cut_program
모든 논문은 아래 "QQ 명함만 모델링"을 참고하시고, QQ 명함을 클릭하시면 됩니다.

추천

출처blog.csdn.net/weixin_43292788/article/details/132834908