MACHINE_START分析

本文深入分析了在友善mini2440提供的Linux2.6.32.2内核中,如何通过machine_desc结构体定义设备信息,解释了各个字段如nr, phys_io, io_pg_offst等的作用,并详细介绍了init_machine, init_irq, map_io等函数在内核启动过程中的应用。
在友善mini2440提供的linux2.6.32.2内核中,有如下定义
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.init_irq = s3c24xx_init_irq,
.map_io = mini2440_map_io,
.init_machine = mini2440_machine_init,
.timer = &s3c24xx_timer,
MACHINE_END
下面分析一下:
include/asm-arm/mach/arch.h中,有定义
#define MACHINE_START(_type,_name) \
static const struct machine_desc __mach_desc_##_type \
 __used \
 __attribute__((__section__(".arch.info.init"))) = { \
.nr = MACH_TYPE_##_type, \
.name = _name,
#define MACHINE_END \
};
列出machine_desc的定义:
struct machine_desc {
unsigned int nr;
unsigned int phys_io;
unsigned int io_pg_offst;
const char *name;
unsigned long boot_params;
unsigned int video_start;
unsigned int video_end;
unsigned int reserve_lp0 :1;
unsigned int reserve_lp1 :1;
unsigned int reserve_lp2 :1;
unsigned int soft_reboot :1;
void (*fixup)(struct machine_desc *,
struct tag *, char **,
struct meminfo *);
void (*map_io)(void);
void (*init_irq)(void);
struct sys_timer *timer;
void (*init_machine)(void);
};
按定义展开后:
static const struct machine_desc __mach_desc_MINI2440 \
 __used \
 __attribute__((__section__(".arch.info.init"))) = {
.nr = MACH_TYPE_MINI2440,
.name "FriendlyARM Mini2440 development board",
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.init_irq = s3c24xx_init_irq,
.map_io = mini2440_map_io,
.init_machine = mini2440_machine_init,
.timer = &s3c24xx_timer,
};
MACH_TYPE_MINI2440 是mini2440开发板在linux中的机器号。
"FriendlyARM Mini2440 development board"是开发板信息,在终端输入cat /proc/cpuinfo可以查看。
MACHINE_START主要是定义了"struct machine_desc"的类型,放在 section(".arch.info.init"),是初始化数据,Kernel 起来之后将被丢弃。
其余各个成员函数在setup_arch()中被赋值到内核结构体,在不同时期被调用:
1. .init_machine 在 arch/arm/kernel/setup.c 中被 customize_machine 调用,放在 arch_initcall() 段里面,会自动按顺序被调用。
2. .init_irq在start_kernel() --> init_IRQ() --> init_arch_irq()中被调用
3. .map_io 在 setup_arch() --> paging_init() --> devicemaps_init()中被调用
4. .timer是定义系统时钟,定义TIMER4为系统时钟,在arch/arm/plat-s3c/time.c中体现。在start_kernel() --> time_init()中被调用。
5. .boot_params是bootloader向内核传递的参数的位置,这要和bootloader中参数的定义要一致。
其他主要都在 setup_arch() 中用到。
MACHINE_START(MINI2440, "FriendlyARM Mini2440 development board")
CREATE DEFINER=`root`@`%` PROCEDURE `usp_OEE_GetMachineOEEAndStatusSingleClient`(IN `p_machine_id` bigint,IN `p_start_time` datetime,IN `p_end_time` datetime,IN `p_isHistory` CHAR(1),OUT `error` varchar(512)) label:BEGIN DECLARE v_now datetime; DECLARE v_start_fh,v_end_fh datetime; DECLARE v_now_date date; DECLARE v_now_time time; DECLARE v_start_shift,v_end_shift datetime; DECLARE V_QUERY_START,V_QUERY_END datetime; DECLARE V_MAX_TIME DATETIME; DECLARE V_MIN_START_TIME DATETIME; DECLARE V_MIN_END_TIME DATETIME; DECLARE V_MACHINE_NO varchar(60); DECLARE V_MACHINE_NAME varchar(250); DECLARE V_NOW_DAY DATETIME; DECLARE Time_Frame VARCHAR(10); SET v_now=NOW(); SET V_NOW_DAY=DATE_FORMAT(v_now,'%Y-%m-%d 08:00:00'); /*IF EXISTS(select * from usp_oee_getmachineoeeandstatussingleclient AS A WHERE A.MACHINE_ID=p_machine_id and A.V_QUERY_START=p_start_time and A.V_QUERY_END=p_end_time) then SELECT * from usp_oee_getmachineoeeandstatussingleclient AS A WHERE A.MACHINE_ID=p_machine_id and A.V_QUERY_START=p_start_time and A.V_QUERY_END=p_end_time; leave label; end if;*/ SET v_now_date=DATE_FORMAT(v_now,'%Y-%m-%d'); SET v_now_time=DATE_FORMAT(v_now,'%H:%i:%s'); IF(p_isHistory = 'N') THEN SET v_now=NOW(); SET v_now_date=DATE_FORMAT(v_now,'%Y-%m-%d'); SET v_now_time=DATE_FORMAT(v_now,'%H:00:00'); select MACHINE_NO,MACHINE_NAME,CASE WHEN c.BEGIN_TIME>c.END_TIME AND v_now_time<c.END_TIME THEN CONCAT(DATE_ADD(v_now_date,INTERVAL -1 DAY),' ',c.BEGIN_TIME) ELSE CONCAT(v_now_date,' ',c.BEGIN_TIME) END, CASE WHEN c.BEGIN_TIME>=c.END_TIME AND v_now_time>c.BEGIN_TIME THEN CONCAT(DATE_ADD(v_now_date,INTERVAL 1 DAY),' ',c.END_TIME) ELSE CONCAT(v_now_date,' ',c.END_TIME) END into V_MACHINE_NO,V_MACHINE_NAME,v_start_shift,v_end_shift from BAS_LINE_INFO a inner join FM_MACHINE_INFO d on a.LINE_ID=d.LINE_ID inner join BAS_SHIFT_INFO b on a.SHIFT_ID=b.SHIFT_ID inner join BAS_SHIFT_PERIOD c on b.SHIFT_ID=c.SHIFT_ID where d.MACHINE_ID=p_machine_id and (v_now_time>=c.BEGIN_TIME AND v_now_time<c.END_TIME OR (c.BEGIN_TIME>c.END_TIME AND (v_now_time>=c.BEGIN_TIME OR v_now_time<c.END_TIME)) OR c.BEGIN_TIME=c.END_TIME); SET V_QUERY_START=v_start_shift; SET V_QUERY_END=v_now; ELSE SELECT MACHINE_NO,MACHINE_NAME,p_start_time,p_end_time into V_MACHINE_NO,V_MACHINE_NAME,V_QUERY_START,V_QUERY_END FROM FM_MACHINE_INFO WHERE MACHINE_ID=p_machine_id; IF(p_end_time>NOW()) THEN SET v_now=NOW(); SET V_QUERY_END=v_now; ELSE SET v_now=p_end_time; END IF; SET v_now_date=DATE_FORMAT(v_now,'%Y-%m-%d'); SET v_now_time=DATE_FORMAT(v_now,'%H:%i:%s'); END IF; DROP TEMPORARY TABLE IF EXISTS TMP_PERIOD; CREATE TEMPORARY TABLE TMP_PERIOD ( MACHINE_ID BIGINT, START_TIME DATETIME, END_TIME DATETIME ); INSERT INTO TMP_PERIOD(MACHINE_ID,START_TIME,END_TIME) VALUES (p_machine_id,V_QUERY_START,V_QUERY_END); DROP TEMPORARY TABLE IF EXISTS TMP_ALARM_RECORD_SINGLE; CREATE TEMPORARY TABLE TMP_ALARM_RECORD_SINGLE ( MACHINE_ID BIGINT, START_TIME DATETIME, END_TIME DATETIME, ALARM_ID VARCHAR(30), IS_STAND CHAR(1) ); -- SELECT * FROM TMP_PERIOD; BEGIN DECLARE V_START_TIME DATETIME; DECLARE V_END_TIME DATETIME; DECLARE V_RECORD_STARTTIME DATETIME; DECLARE V_RECORD_ALARM_ID VARCHAR(20); DECLARE S INT DEFAULT 0; -- DECLARE MC CURSOR FOR SELECT START_TIME,END_TIME FROM TMP_PERIOD; DECLARE MC CURSOR FOR SELECT min(START_TIME),max(END_TIME) FROM TMP_PERIOD; DECLARE EXIT HANDLER FOR SQLSTATE '02000' SET S = 1 ; OPEN MC; REPEAT FETCH MC INTO V_START_TIME,V_END_TIME; ALARM:BEGIN insert into TMP_ALARM_RECORD_SINGLE(MACHINE_ID,ALARM_ID,START_TIME,END_TIME,IS_STAND) select a.MACHINE_ID,a.ALARM_ID,CASE WHEN V_START_TIME<A.START_TIME THEN A.START_TIME ELSE V_START_TIME END, CASE WHEN V_END_TIME>A.END_TIME THEN A.END_TIME ELSE V_END_TIME END,case when c.TYPE_NO='stand' then 'Y' else 'N' end IS_STAND from FM_ALARM_RECORD_SINGLE as a inner join FM_ALARM_INFO b on a.alarm_id=b.alarm_id inner join FM_ALARM_TYPE c on b.TYPE_ID=c.TYPE_ID where a.MACHINE_ID=p_machine_id and END_TIME>V_START_TIME and START_TIME<V_END_TIME; -- SELECT * FROM TMP_ALARM_RECORD_SINGLE; IF NOT EXISTS(SELECT ALARM_ID FROM TMP_ALARM_RECORD_SINGLE WHERE END_TIME>=V_END_TIME) THEN DROP TEMPORARY TABLE IF EXISTS TMP_ALARM; CREATE TEMPORARY TABLE TMP_ALARM ( MACHINE_ID BIGINT, STARTTIME DATETIME, ALARM_ID VARCHAR(30), IS_STAND CHAR(1) ); INSERT INTO TMP_ALARM (SELECT C.MACHINE_ID,A.START_TIME,A.ALARM_ID,'Y' FROM FM_ALARM_RECORD A inner join FM_STATION_DEVICE B on A.DEVICE_ID=B.ID inner join FM_MACHINE_INFO C on B.MACHINE_ID=C.MACHINE_ID INNER JOIN FM_ALARM_INFO D on A.alarm_id=D.alarm_id inner join FM_ALARM_TYPE E on D.TYPE_ID=E.TYPE_ID where B.MACHINE_ID=p_machine_id AND A.END_TIME IS NULL AND START_TIME<V_END_TIME AND E.TYPE_NO='stand' ORDER BY A.START_TIME LIMIT 1) UNION (SELECT C.MACHINE_ID,A.START_TIME,A.ALARM_ID,'N' FROM FM_ALARM_RECORD A inner join FM_STATION_DEVICE B on A.DEVICE_ID=B.ID inner join FM_MACHINE_INFO C on B.MACHINE_ID=C.MACHINE_ID INNER JOIN FM_ALARM_INFO D on A.alarm_id=D.alarm_id inner join FM_ALARM_TYPE E on D.TYPE_ID=E.TYPE_ID where B.MACHINE_ID=p_machine_id AND A.END_TIME IS NULL AND START_TIME<V_END_TIME AND E.TYPE_NO='stop' ORDER BY A.START_TIME LIMIT 1); -- SELECT * FROM TMP_ALARM; IF EXISTS (SELECT ALARM_ID FROM TMP_ALARM) THEN DROP TEMPORARY TABLE IF EXISTS TMP_ALARM_EXTEND; CREATE TEMPORARY TABLE TMP_ALARM_EXTEND SELECT * FROM TMP_ALARM_RECORD_SINGLE; IF EXISTS (SELECT ALARM_ID FROM TMP_ALARM WHERE IS_STAND='Y') THEN SELECT STARTTIME,ALARM_ID INTO V_RECORD_STARTTIME,V_RECORD_ALARM_ID FROM TMP_ALARM WHERE IS_STAND='Y'; DELETE FROM TMP_ALARM_EXTEND WHERE END_TIME>V_RECORD_STARTTIME; INSERT INTO TMP_ALARM_EXTEND(MACHINE_ID,START_TIME,END_TIME,ALARM_ID,IS_STAND) VALUES (p_machine_id,V_RECORD_STARTTIME,V_END_TIME,V_RECORD_ALARM_ID,'Y'); INSERT INTO TMP_ALARM_EXTEND(MACHINE_ID,START_TIME,END_TIME,ALARM_ID,IS_STAND) SELECT p_machine_id,START_TIME,V_RECORD_STARTTIME,ALARM_ID,IS_STAND FROM TMP_ALARM_RECORD_SINGLE WHERE START_TIME<V_RECORD_STARTTIME AND END_TIME>V_RECORD_STARTTIME; ELSEIF EXISTS (SELECT ALARM_ID FROM TMP_ALARM WHERE IS_STAND='N') THEN SELECT STARTTIME,ALARM_ID INTO V_RECORD_STARTTIME,V_RECORD_ALARM_ID FROM TMP_ALARM WHERE IS_STAND='N'; IF NOT EXISTS (SELECT * FROM TMP_ALARM_RECORD_SINGLE WHERE END_TIME>V_RECORD_STARTTIME) THEN INSERT INTO TMP_ALARM_EXTEND(MACHINE_ID,START_TIME,END_TIME,ALARM_ID,IS_STAND) VALUES (p_machine_id,V_RECORD_STARTTIME,V_END_TIME,V_RECORD_ALARM_ID,'N'); ELSE SELECT MAX(END_TIME) INTO V_MAX_TIME FROM TMP_ALARM_RECORD_SINGLE WHERE END_TIME>V_RECORD_STARTTIME; INSERT INTO TMP_ALARM_EXTEND(MACHINE_ID,START_TIME,END_TIME,ALARM_ID,IS_STAND) VALUES (p_machine_id,V_MAX_TIME,V_END_TIME,V_RECORD_ALARM_ID,'N'); END IF; END IF; DELETE FROM TMP_ALARM_RECORD_SINGLE; INSERT INTO TMP_ALARM_RECORD_SINGLE SELECT * FROM TMP_ALARM_EXTEND; END IF; END IF; END; UNTIL S END REPEAT; CLOSE MC; END; -- SELECT * FROM TMP_ALARM_RECORD_SINGLE; BEGIN DECLARE yield FLOAT DEFAULT 0; DECLARE PF FLOAT; DECLARE AV FLOAT; DECLARE OEE FLOAT; DECLARE Output INT; DECLARE Input INT; DECLARE Theory_Output INT; DECLARE Fling INT; DECLARE OKRate VARCHAR(10); DECLARE TossingRate VARCHAR(10); DECLARE Run_Duration FLOAT; DECLARE Theory_Duration FLOAT; DECLARE T_CT INT DEFAULT 0; DECLARE Status VARCHAR(10); DECLARE Stand_Duration FLOAT; DECLARE Stop_Duration FLOAT; #计算Input select IFNULL(SUM(a.VALUE),0) into Input from fm_data_record a inner join FM_DATA_INFO c ON a.DATA_ID=c.DATA_ID where a.MACHINE_ID=p_machine_id and c.TYPE in (1,2) and a.DATETIME BETWEEN V_QUERY_START and V_QUERY_END; select IFNULL(SUM(a.VALUE),0) into Output from fm_data_record a inner join FM_DATA_INFO c ON a.DATA_ID=c.DATA_ID where a.MACHINE_ID=p_machine_id and c.TYPE=1 and a.DATETIME BETWEEN V_QUERY_START and V_QUERY_END; select IFNULL(SUM(a.VALUE),0) into Fling from fm_data_record a inner join FM_DATA_INFO c ON a.DATA_ID=c.DATA_ID where a.MACHINE_ID=p_machine_id and c.TYPE<>1 and a.DATETIME BETWEEN V_QUERY_START and V_QUERY_END; SET Theory_Duration=ROUND(TIMESTAMPDIFF(SECOND,V_QUERY_START,V_QUERY_END)/60,2); -- SELECT * FROM TMP_ALARM_RECORD_SINGLE; SELECT case when IFNULL(ROUND(SUM(TIMESTAMPDIFF(SECOND,A.START_TIME,A.END_TIME))/60,2),0)>Theory_Duration then Theory_Duration else IFNULL(ROUND(SUM(TIMESTAMPDIFF(SECOND,A.START_TIME,A.END_TIME))/60,2),0) end INTO Stand_Duration FROM TMP_ALARM_RECORD_SINGLE A WHERE A.IS_STAND='Y'; SELECT case when IFNULL(ROUND(SUM(TIMESTAMPDIFF(SECOND,A.START_TIME,A.END_TIME))/60,2),0)>Theory_Duration then Theory_Duration else IFNULL(ROUND(SUM(TIMESTAMPDIFF(SECOND,A.START_TIME,A.END_TIME))/60,2),0) end INTO Stop_Duration FROM TMP_ALARM_RECORD_SINGLE A WHERE A.IS_STAND='N'; set RUN_DURATION=Theory_Duration-Stand_Duration-Stop_Duration; -- SELECT Theory_Duration,V_QUERY_START,V_QUERY_END,Stand_Duration,Stop_Duration; select YIELD_RATE/100,THEORY_CT into yield,T_CT from bas_machine_oee where MACHINE_ID=p_machine_id and v_now>=EFFECTIVE_DATE and v_now<FAILURE_DATE LIMIT 1; SET Theory_Output=Theory_Duration*60/T_CT; SET PF=IF(Run_Duration !=0,T_CT*Output/(Run_Duration*60),0); SET AV=IF(Theory_Duration !=0,Run_Duration/Theory_Duration,0); SET OEE=AV*PF*(CASE WHEN Input>0 THEN FORMAT(Output/Input,2) ELSE '0' END); IF DATE_FORMAT(p_end_time,'%H:%i:%s')='08:00:00' and DATE_FORMAT(p_start_time,'%H:%i:%s')='20:00:00' THEN SET Theory_Output=720*60/T_CT; SELECT p_machine_id as MACHINE_ID,V_MACHINE_NO as MACHINE_NO,V_MACHINE_NAME AS MACHINE_NAME,V_QUERY_START,V_QUERY_END,TRUNCATE(OEE*100,2) OEE,TRUNCATE(AV*100,2) AV,TRUNCATE(PF*100,2) PF,Output,Fling,case when (Output+Fling)>0 then ROUND(Output/(Output+Fling)*100,2) ELSE 0 END AS OKRate,case when (Output+Fling)>0 then ROUND(Fling/(Output+Fling)*100,2) ELSE 0 END AS TossingRate,Theory_Output,RUN_DURATION,720 as Theory_DURATION, Stand_Duration,Stop_Duration ,Case when Output>0 then TRUNCATE(Run_Duration*60/Output,2) else 0 end as CT; ELSEIF DATE_FORMAT(p_end_time,'%H:%i:%s')='20:00:00' THEN SET Theory_Output=720*60/T_CT; SELECT p_machine_id as MACHINE_ID,V_MACHINE_NO as MACHINE_NO,V_MACHINE_NAME AS MACHINE_NAME,V_QUERY_START,V_QUERY_END,TRUNCATE(OEE*100,2) OEE,TRUNCATE(AV*100,2) AV,TRUNCATE(PF*100,2) PF,Output,Fling,case when (Output+Fling)>0 then ROUND(Output/(Output+Fling)*100,2) ELSE 0 END AS OKRate,case when (Output+Fling)>0 then ROUND(Fling/(Output+Fling)*100,2) ELSE 0 END AS TossingRate,Theory_Output,RUN_DURATION,720 as Theory_DURATION, Stand_Duration,Stop_Duration ,Case when Output>0 then TRUNCATE(Run_Duration*60/Output,2) else 0 end as CT; else SET Theory_Output=1440*60/T_CT; SELECT p_machine_id as MACHINE_ID,V_MACHINE_NO as MACHINE_NO,V_MACHINE_NAME AS MACHINE_NAME,V_QUERY_START,V_QUERY_END,TRUNCATE(OEE*100,2) OEE,TRUNCATE(AV*100,2) AV,TRUNCATE(PF*100,2) PF,Output,Fling,case when (Output+Fling)>0 then ROUND(Output/(Output+Fling)*100,2) ELSE 0 END AS OKRate,case when (Output+Fling)>0 then ROUND(Fling/(Output+Fling)*100,2) ELSE 0 END AS TossingRate,Theory_Output,RUN_DURATION,1440 as Theory_DURATION, Stand_Duration,Stop_Duration ,Case when Output>0 then TRUNCATE(Run_Duration*60/Output,2) else 0 end as CT; end if; leave label; -- SELECT * from usp_oee_getmachineoeeandstatussingleclient AS A WHERE A.MACHINE_ID=p_machine_id and A.V_QUERY_START=p_start_time and A.V_QUERY_END=p_end_time AND TimeFrame=Time_Frame; IF NOT EXISTS(SELECT 1 FROM TMP_ALARM_RECORD_SINGLE) THEN SELECT V_QUERY_START START_TIME,V_QUERY_END END_TIME,TIMESTAMPDIFF(SECOND,V_QUERY_START,V_QUERY_END) Duration,'Run' Status; ELSE BEGIN DECLARE V_START_TIME DATETIME; DECLARE V_END_TIME DATETIME; DECLARE V_END_TIME_PRE DATETIME; DECLARE V_IS_STAND VARCHAR(1); DECLARE S INT DEFAULT 0; DECLARE MC CURSOR FOR SELECT START_TIME,END_TIME,IS_STAND FROM TMP_ALARM_RECORD_SINGLE ORDER BY START_TIME; DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET S = 1 ; DROP TEMPORARY TABLE IF EXISTS TMP_ALARM_RECORD_SINGLE_COMPLEMENT; CREATE TEMPORARY TABLE TMP_ALARM_RECORD_SINGLE_COMPLEMENT ( START_TIME DATETIME, END_TIME DATETIME ); SET V_END_TIME_PRE=V_QUERY_START; OPEN MC; REPEAT FETCH MC INTO V_START_TIME,V_END_TIME,V_IS_STAND; IF(V_END_TIME_PRE<V_START_TIME) THEN INSERT INTO TMP_ALARM_RECORD_SINGLE_COMPLEMENT VALUES (V_END_TIME_PRE,V_START_TIME); END IF; SET V_END_TIME_PRE=V_END_TIME; UNTIL S END REPEAT; CLOSE MC; IF(V_END_TIME<V_QUERY_END) THEN INSERT INTO TMP_ALARM_RECORD_SINGLE_COMPLEMENT VALUES (V_END_TIME,V_QUERY_END); END IF; select START_TIME,END_TIME,TIMESTAMPDIFF(SECOND,START_TIME,END_TIME) Duration,case when IS_STAND='Y' then 'Stand' else 'Stop' end Status from TMP_ALARM_RECORD_SINGLE UNION ALL select START_TIME,END_TIME,TIMESTAMPDIFF(SECOND,START_TIME,END_TIME) Duration,'Run' from TMP_ALARM_RECORD_SINGLE_COMPLEMENT ORDER BY START_TIME; END; END IF; END; END
最新发布
12-13
请你分析这段代码:import pandas as pd # 读取Excel文件,构建工序字典(工序名称: {机器: 加工时间}) file_path = r'F:\学校文件\论文\草稿\mk01.xlsx' df = pd.read_excel(file_path, sheet_name='Sheet1') process_dict = {} for idx, row in df.iterrows(): job = row['MK01'] op = row['gx'] machines = {} for col in df.columns[2:]: # 从M1到M6 time = row[col] if pd.notna(time): machines[col] = time process_dict[op] = machines # 假设这里的工序编码和机器编码是编码程序的输出 operation_sequence = [10, 5, 3, 10, 3, 10, 3, 1, 6, 10, 5, 6, 6, 9, 4, 2, 8, 7, 1, 7, 5, 9, 10, 1, 9, 5, 10, 8, 3, 1, 6, 3, 6, 8, 2, 6, 7, 2, 9, 4, 7, 1, 5, 9, 4, 4, 5, 8, 4, 7, 1, 8, 2, 9, 2] # 示例工序编码 machine_code = [6, 2, 2, 3, 6, 5, 1, 1, 6, 6, 1, 1, 3, 6, 1, 2, 6, 6, 5, 4, 2, 1, 4, 3, 4, 1, 4, 3, 6, 1, 2, 5, 1, 1, 3, 4, 3, 1, 1, 2, 5, 3, 4, 6, 3, 5, 3, 2, 6, 3, 4, 4, 4, 4, 1] # 示例机器编码 # 初始化变量 jobs = df['MK01'].unique() job_numbers = {job: int(job[3:]) for job in jobs} job_operations = {job: len(df[df['MK01'] == job]) for job in jobs} machine_start_times = [0] * 6 # 每台机器的当前可用时间 job_current_op = {job: 0 for job in jobs} total_time = 0 machine_loads = [0] * 6 # 初始化每台机器的负载 # 解码过程 for i in range(len(operation_sequence)): job_char = operation_sequence[i] job = f'job{job_char}' op_index = job_current_op[job] op_name = f'O{job_char}{op_index + 1}' job_current_op[job] += 1 machine_index = machine_code[i] - 1 # 机器编号从1开始,转换为索引 machine = f'M{machine_index + 1}' # 检查该工序是否支持在所选机器上加工 if machine in process_dict[op_name]: # 获取该工序在所选机器上的加工时间 processing_time = process_dict[op_name][machine] # 确定该工序的开始时间,取决于机器的可用时间和工件上一工序的完成时间 job_last_finish_time = max( [machine_start_times[j] for j in range(6) if op_name in process_dict and machine in process_dict[op_name]]) start_time = max(machine_start_times[machine_index], job_last_finish_time) # 更新机器的可用时间 machine_start_times[machine_index] = start_time + processing_time # 更新总加工时间 total_time = max(total_time, machine_start_times[machine_index]) # 更新机器的负载 machine_loads[machine_index] += processing_time print( f"工件 {job} 的工序 {op_name} 在机器 {machine} 上,从时间 {start_time} 开始加工,加工时间为 {processing_time}") else: print(f"错误:工序 {op_name} 不支持在机器 {machine} 上加工。") print(f"总加工时间: {total_time}") # 输出每台机器的负载 for i in range(6): print(f"机器 M{i + 1} 的负载: {machine_loads[i]}")
03-23
New_Lot_Loop_Info=\ {'C101': {390: {'PSR01': 40, 'PSR03': 35}, 410: {'HCI09': 20, 'HCI0B': 20}, 420: {'SEM04': 6, 'SEM05': 6, 'SEM06': 6, 'SEM07': 6, 'SEM67': 6}, 465: {'WPES07': 12, 'WPES65': 12}, 448: {'OCD02': 8, 'OCD03': 8}, 452: {'WPES04': 12, 'WPES08': 12}, 453: {'EPI07': 110, 'EPI08': 110, 'EPI0k': 130}}, 'C102': {390: {'PSR01': 40, 'PSR03': 35}, 410: {'HCI09': 20, 'HCI0B': 20}, 420: {'SEM04': 6, 'SEM05': 6, 'SEM06': 6, 'SEM07': 6, 'SEM67': 6}, 465: {'WPES07': 12, 'WPES65': 12}, 448: {'OCD02': 8, 'OCD03': 8}, 452: {'WPES04': 12, 'WPES08': 12}, 453: {'EPI07': 110, 'EPI08': 110, 'EPI0k': 130}}, 'C103': {390: {'PSR01': 40, 'PSR03': 35}, 410: {'HCI09': 20, 'HCI0B': 20}, 420: {'SEM04': 6, 'SEM05': 6, 'SEM06': 6, 'SEM07': 6, 'SEM67': 6}, 465: {'WPES07': 12, 'WPES65': 12}, 448: {'OCD02': 8, 'OCD03': 8}, 452: {'WPES04': 12, 'WPES08': 12}, 453: {'EPI07': 110, 'EPI08': 110, 'EPI0k': 130}}} # 定义变量 x={} # Lot是否在某个step_id的某个机台上加工 Step_Time_S={} # Lot在某个step_id的开始时间 Step_Time_E={} # Lot在某个step_id的结束时间 all_tasks={} Machine_Task = collections.defaultdict(list) task_type = collections.namedtuple("task_type", "start end") for lot_id,step_info in New_Lot_Loop_Info.items(): for step_id,machine_info in step_info.items(): Step_Time_S[lot_id,step_id]=model.NewIntVar(0,MAX_TIME,f"{lot_id}_{step_id}_start_time") Step_Time_E[lot_id,step_id]=model.NewIntVar(0,MAX_TIME,f"{lot_id}_{step_id}_end_time") for machine_id, process_time in machine_info.items(): x[lot_id,step_id,machine_id]=model.NewBoolVar(f"x_{lot_id}_{step_id}_{machine_id}") Process_Time = model.NewIntVar(0, MAX_TIME, f"Real_Process_Time_{lot_id}_{step_id}_{machine_id}") model.Add(Process_Time == process_time).OnlyEnforceIf(x[lot_id, step_id,machine_id]) Machine_Time_S = model.NewIntVar(0, MAX_TIME, f"Machine_Time_S_{lot_id}_{step_id}_{machine_id}") Machine_Time_E = model.NewIntVar(0, MAX_TIME, f"Machine_Time_E_{lot_id}_{step_id}_{machine_id}") model.Add(Machine_Time_S == 0).OnlyEnforceIf(x[lot_id,step_id,machine_id].Not()) model.Add(Machine_Time_E == 0).OnlyEnforceIf(x[lot_id,step_id,machine_id].Not()) Pro_Task = model.NewIntervalVar(start=Machine_Time_S, size= Process_Time, end=Machine_Time_E, name=f"Pro_Task_{lot_id}_{step_id}_{machine_id}") Machine_Task[machine_id].append(Pro_Task) # 将加工任务写入 all_tasks[lot_id, step_id, machine_id] = task_type(start=Machine_Time_S, end=Machine_Time_E) # 约束1:每个lot在每个step_id只能在一台机台上被加工 for lot_id,step_list in New_Lot_Loop_Info.items(): for step_id, machine_info in step_list.items(): model.Add(sum(x[lot_id,step_id,machine_id] for machine_id in machine_info) == 1) # 约束2:将每个step_id的开始时间和结束时间与上了哪个机器有关 for lot_id,step_info in New_Lot_Loop_Info.items(): for step_id,machine_info in step_info.items(): model.AddMaxEquality(Step_Time_S[lot_id, step_id],[all_tasks[lot_id, step_id, machine_id].start for machine_id in machine_info]) model.AddMaxEquality(Step_Time_E[lot_id, step_id],[all_tasks[lot_id, step_id, machine_id].end for machine_id in machine_info]) # 计算每个EPI机台的最晚结束时间 EPI_Machine_EndTime = {} # 存储每个EPI机台的最后一个任务结束时间 for machine_id in Machine_Task: if machine_id.startswith("EPI"): # 筛选EPI类型机台 max_end = model.NewIntVar(0, MAX_TIME, f"max_end_{machine_id}") end_times = [task.end for task in Machine_Task[machine_id]] model.AddMaxEquality(max_end, end_times) EPI_Machine_EndTime[machine_id] = max_end代码报错:AttributeError: 'IntervalVar' object has no attribute 'end'
03-14
<think>好的,我现在需要帮助用户理解他们提供的这段代码的含义。首先,用户的问题是关于如何将“工件必须按照其对应的工序执行”转化为MIP约束,之前已经给出了详细的步骤。现在用户展示了一段Python代码,并询问这段代码的含义。我需要仔细分析这段代码的结构和各个部分的作用。 首先,观察代码结构,发现使用了嵌套的循环,最外层是遍历New_Lot_Loop_Info的lot_id和step_info。然后内部遍历step_info的step_id和machine_info。这说明可能有多个lot(批次),每个lot有多个工序步骤,每个步骤又涉及多个机器。 接下来,用户定义了Step_Time_S和Step_Time_E作为model.NewIntVar,应该是每个步骤的开始和结束时间变量。然后对于每个machine_id和process_time,创建了一个布尔变量x,这可能用于表示某个lot的某个步骤是否在特定机器上加工。 然后,定义Process_Time变量,并将其约束为等于process_time,但只有在x为True时才生效。这说明当x被选中时,该步骤在该机器上的实际加工时间就是给定的process_time,否则可能不相关。 接着,创建了Machine_Time_S和Machine_Time_E变量,并添加了约束:如果x未被选中(即.Not()),则开始和结束时间设为0。这可能用于确保未被选中的机器时间不影响整体调度。 然后,将Machine_Time_E添加到Machine_End_Vars中,可能是为了后续计算每个机器的结束时间,比如最大完工时间。创建了IntervalVar,将开始时间、加工时间和结束时间关联起来,这可能用于安排机器上的任务间隔,避免冲突。 最后,将Pro_Task添加到Machine_Task和all_tasks中,可能用于后续的约束,如机器独占性约束,确保同一时间同一机器只能处理一个任务。 需要确定用户是否了解这些代码的具体作用,尤其是如何将这些变量和约束转化为MIP模型中的元素。用户可能是在使用OR-Tools库,特别是CP-SAT求解器,因为看到了NewIntVar、NewBoolVar和IntervalVar的使用,这些是OR-Tools中常见的建模方法。 用户可能的问题在于如何将这段代码映射到之前提到的MIP约束,比如工序顺序和机器独占性。需要指出代码中的变量定义和约束如何对应到之前的步骤,例如步骤之间的顺序约束可能还未在代码中体现,可能需要额外的约束来确保工序的顺序。 另外,需要注意用户是否了解IntervalVar的作用,它可能用于处理机器上的任务调度,自动处理时间冲突,但需要确认是否在模型中正确应用了这些间隔变量,例如通过添加NoOverlap约束。 最后,需要总结代码的整体目的,即构建了一个包含批次、工序步骤、机器的调度模型,定义了相关变量和约束,确保每个步骤在指定机器上的加工时间正确,并管理机器上的任务间隔,避免重叠。</think>以下是对该代码的详细解析,按功能模块分步说明其含义: --- ### **1. 数据结构与变量初始化** #### **(1) 外层循环:遍历批次(Lot)与工序步骤(Step)** ```python for lot_id, step_info in New_Lot_Loop_Info.items(): for step_id, machine_info in step_info.items(): ``` - **功能**:遍历所有批次(`lot_id`),以及每个批次对应的工序步骤(`step_id`)。 - **数据结构**: - `New_Lot_Loop_Info`:字典结构,键为批次号 `lot_id`,值为该批次的所有工序步骤信息 `step_info`。 - `step_info`:字典结构,键为工序步骤号 `step_id`,值为该工序可选的机器及其加工时间 `machine_info`。 - `machine_info`:字典结构,键为机器号 `machine_id`,值为该机器上加工此工序所需时间 `process_time`。 --- ### **2. 定义时间变量** #### **(1) 工序的开始与结束时间** ```python Step_Time_S[lot_id, step_id] = model.NewIntVar(0, MAX_TIME, f"{lot_id}_{step_id}_start_time") Step_Time_E[lot_id, step_id] = model.NewIntVar(0, MAX_TIME, f"{lot_id}_{step_id}_end_time") ``` - **功能**:为每个批次 `lot_id` 的每个工序步骤 `step_id` 定义两个整数变量: - `Step_Time_S`:工序的开始时间(从0到预设的最大时间 `MAX_TIME`)。 - `Step_Time_E`:工序的结束时间。 --- ### **3. 机器选择与加工时间绑定** #### **(1) 定义布尔变量表示机器选择** ```python x[lot_id, step_id, machine_id] = model.NewBoolVar(f"x_{lot_id}_{step_id}_{machine_id}") ``` - **功能**:定义二进制变量 `x[lot_id, step_id, machine_id]`,当批次 `lot_id` 的工序 `step_id` 选择在机器 `machine_id` 上加工时,该变量为1,否则为0。 #### **(2) 实际加工时间与机器选择的关联** ```python Process_Time = model.NewIntVar(0, MAX_TIME, f"Real_Process_Time_{lot_id}_{step_id}_{machine_id}") model.Add(Process_Time == process_time).OnlyEnforceIf(x[lot_id, step_id, machine_id]) ``` - **功能**: - 定义变量 `Process_Time` 表示实际加工时间。 - 约束:当且仅当选择机器 `machine_id`(即 `x[...] = 1`)时,`Process_Time` 必须等于预设的 `process_time`。 --- ### **4. 机器时间窗口管理** #### **(1) 定义机器任务的起止时间** ```python Machine_Time_S = model.NewIntVar(0, MAX_TIME, f"Machine_Time_S_{lot_id}_{step_id}_{machine_id}") Machine_Time_E = model.NewIntVar(0, MAX_TIME, f"Machine_Time_E_{lot_id}_{step_id}_{machine_id}") model.Add(Machine_Time_S == 0).OnlyEnforceIf(x[lot_id, step_id, machine_id].Not()) model.Add(Machine_Time_E == 0).OnlyEnforceIf(x[lot_id, step_id, machine_id].Not()) ``` - **功能**: - 定义机器任务的开始时间 `Machine_Time_S` 和结束时间 `Machine_Time_E`。 - 约束:如果未选择机器 `machine_id`(即 `x[...] = 0`),则强制机器任务的起止时间为0,表示该机器不参与此工序的加工。 #### **(2) 记录机器任务的结束时间** ```python Machine_End_Vars[machine_id].append(Machine_Time_E) ``` - **功能**:将每个机器 `machine_id` 上所有任务的结束时间 `Machine_Time_E` 存入列表 `Machine_End_Vars`,后续可用于计算最大完工时间(Makespan)。 --- ### **5. 定义加工任务间隔** #### **(1) 创建间隔变量(IntervalVar)** ```python Pro_Task = model.NewIntervalVar( start=Machine_Time_S, size=Process_Time, end=Machine_Time_E, name=f"Pro_Task_{lot_id}_{step_id}_{machine_id}" ) ``` - **功能**: - 定义时间间隔变量 `Pro_Task`,表示机器 `machine_id` 上加工任务的完整时间段。 - 关联关系:`Machine_Time_S`(开始时间) + `Process_Time`(加工时间) = `Machine_Time_E`(结束时间)。 #### **(2) 记录机器任务** ```python Machine_Task[machine_id].append(Pro_Task) all_tasks[lot_id, step_id, machine_id] = task_type(start=Machine_Time_S, end=Machine_Time_E) ``` - **功能**: - 将间隔变量 `Pro_Task` 存入 `Machine_Task[machine_id]`,后续可用于添加机器独占性约束(例如 `NoOverlap`)。 - 记录所有任务的起止时间到 `all_tasks`,可能用于可视化或调试。 --- ### **6. 整体逻辑总结** 1. **变量定义**: - 为每个工序步骤定义起止时间变量。 - 为每个工序-机器组合定义二进制选择变量。 2. **约束绑定**: - 加工时间与机器选择的关联。 - 未选机器的起止时间归零。 3. **任务调度**: - 通过间隔变量 `IntervalVar` 描述机器上的加工任务。 - 收集所有任务,为后续的机器独占性约束(如 `AddNoOverlap`)做准备。 --- ### **补充说明** - **适用场景**:此代码是典型的 **作业车间调度(Job Shop Scheduling)** 建模片段,用于处理多批次、多工序、多机器的复杂调度问题。 - **关键约束缺失**:当前代码未显式定义 **工序顺序约束**(例如“工序2必须在工序1完成后开始”),需额外添加类似 `model.Add(Step_Time_S[lot_id, j+1] >= Step_Time_E[lot_id, j])` 的约束。 - **目标函数**:通常需最小化最大完工时间,例如: ```python makespan = model.NewIntVar(0, MAX_TIME, "makespan") model.AddMaxEquality(makespan, [Step_Time_E[lot_id, step_id] for lot_id, step_id in Step_Time_E]) model.Minimize(makespan) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值