【(较大规模)作业车间调度JSP】通过OR-Tools的区间变量建模求解的效率对比实验

文章目录

  • 问题描述
  • Python调用OR-Tools建模求解(实验一)
    • 1. 声明问题的模型
    • 2. 创建区间变量
    • 3. 创建约束条件
    • 4. 求解模型
    • 5. 基于 plotly 展示甘特图
  • 不同场景下的求解效率对比
    • 实验二:工件的工序数有差异
    • 实验三:消除工件的加工时长差异
    • 实验三与实验一的对比分析


相关文章:
《【作业车间调度JSP】通过python调用PuLP线性规划库求解》
《【作业车间调度JSP】通过python调用OR-Tools的区间变量建模求解》

问题描述

JSP(Job Shop Scheduling Problem)问题是指车间作业调度问题,是生产调度领域中的经典问题之一。JSP问题涉及到一组工件(Jobs)和一组机器(Machines),每个工件都有一系列工序需要在不同的机器上完成,每个工序有一个特定的加工时间。通过确定每个工件的工序顺序和在每台机器上的开始时间,以最优化既定的目标。这个问题的复杂性(NP-Hard问题)和实际应用的广泛性使得研究和优化JSP一直是运筹学和制造业领域的热点。

在前面的相关文章中,仅测试了小规模的算例,例如只有 6 个工件,且每个工件仅 6 个工序。在大规模问题下,有些求解器的求解时间急剧增加,有些求解器仍然表现出很有优势的性能,因此,本文通过更大规模的算例进行实验。

基于 Hurink-sdata 数据集中算例 abz7.fjs 进行实验,具体的算例数据解析可以参考文章《解析FJSP问题的标准测试数据集的Python代码》,该JSP算例有 20 个待加工工件,15台机器,每个工件有15道工序,总共的工序一共有300步。以最小化全部工件的完工时间为目标。

Python调用OR-Tools建模求解(实验一)

对于JSP问题而言,最基本的约束有两块:(1)工件的工序需按顺序加工,前序工序加工完才能加工后续工序;(2)机器加工的不重叠性,即机器在同一时间只能完成一个加工任务。

特别的,OR-Tools具有关于区间变量的特定约束,即去重叠。因此,本文基于OR-Tools的区间变量进行建模求解,验证区间变量在这类带顺序的模型(VRP/JSP…)中的效果。通过《解析FJSP问题的标准测试数据集的Python代码》当中的代码进行解析。

1. 声明问题的模型

OR-Tools 的 cp_model 在建模之前需要先声明问题的模型。

import collections
from ortools.sat.python import cp_modelmodel = cp_model.CpModel()

2. 创建区间变量

在这里,区间变量指每个任务的加工时间段,即机器被某道工序占用的时间段,当工序在机器上的加工时间固定时,这个区间变量的长度 duration 也固定,进一步地,当工序的开始加工时间固定,则相对应的结束时间也固定。

对每个工序都要建立一个区间变量,而区间变量的基本元素包括,工序的开始加工时间(变量),结束加工时间(变量),加工时长(常量)。为了尽量减少可行解空间大小,开始时间和结束时间的上界尽可能紧凑,这里我们取所有工序的加工时长之和作为时间变量的上界。

# 命名元组:存储变量信息(相当于实例化一道工序)
task_type = collections.namedtuple("task_type", "start end interval")
# 存储所有工序信息
all_tasks = {}
# 将工序信息按可上机器(一台)进行存储
machine_to_intervals = collections.defaultdict(list)
# 时间变量的上界
horizon = sum(job_step_machine_2_ptime[job] for job in job_step_machine_2_ptime)for job_id in range(Job_num):for task_id in range(job_2_step_num[job_id]):machine_ = job_step_2_avail_machines[job_id, task_id][0]duration = job_step_machine_2_ptime[job_id, task_id, machine_]suffix = f"_{job_id}_{task_id}_{duration}"start_var = model.NewIntVar(0, horizon, "start" + suffix)end_var = model.NewIntVar(0, horizon, "end" + suffix)interval_var = model.NewIntervalVar(start=start_var, size=duration, end=end_var, name="interval" + suffix)all_tasks[job_id, task_id] = task_type(start=start_var, end=end_var, interval=interval_var)machine_to_intervals[machine_].append(interval_var)

上述创建变量的代码中,先创建了 start_varend_var 变量,然后将这两个变量传入模型的函数NewIntervalVar以创建区间变量。其中,当区间变量内指定了end后,则默认end变量的值与start变量的值的差距为duration

然后将创建的变量存储进 all_task 字典,并按工序的可上机器存储到 machine_to_intervals 字典。

注意:OR-Tools的CP-SAT求解器支持的基础变量类型只有整数型变量(包括布尔变量),因此对时间变量时创建为整数变量,可通过系数的方式来控制变量精度。

3. 创建约束条件

在OR-Tools中,有专门针对区间变量的约束AddNoOverlap,即指定若干区间变量之间彼此不重叠,但无先后关系保证,这类约束成为不相容约束(Disjunctive constraints),在JSP问题中体现在,机器在同一时间只能加工一个任务(暂不考虑批量加工),此时需要约束同一机器上的区间变量彼此之间不重叠。

约束1:机器上的加工工序不能重叠(不相容约束)

for machine in machine_to_intervals:model.AddNoOverlap(machine_to_intervals[machine])

约束2:每个工件内的待加工工序具有先后顺序。

for job_id in range(Job_num):for task_id in range(job_2_step_num[job_id]-1):model.Add(all_tasks[job_id, task_id + 1].start >= all_tasks[job_id, task_id].end)

约束3:最大完工时间等于所有工序完工时间的最大值。

obj_var = model.NewIntVar(0, horizon, "makespan")
model.AddMaxEquality(obj_var, [all_tasks[index].end for index in all_tasks])
model.Minimize(obj_var)

4. 求解模型

OR-Tools的CP-SAT需要模型先创建求解器,再调用Solve()函数进行求解。

solver = cp_model.CpSolver()
status = solver.Solve(model)

打印求解结果:

print(f"Optimal Schedule Length: {solver.ObjectiveValue()}")
print("\nStatistics")
print(f"  - conflicts: {solver.NumConflicts()}")
print(f"  - branches : {solver.NumBranches()}")
print(f"  - wall time: {solver.WallTime()}s")

由于求解时间较长(>5 min),因此求解达到终止条件时(Gap<5%)就返回当前可行解,之后可行解在向最优解步进时Gap的收敛速度急剧下降。

Optimal Schedule Length: 685.0Statistics- conflicts: 3388- branches : 7498- wall time: 5.044260157s

5. 基于 plotly 展示甘特图

甘特图是查看车间调度问题方案的最直观形式,基于上面的求解结果画的甘特图如下:

在这里插入图片描述

import datetime
import plotly.figure_factory as ffj_record = {}
for job_id in range(Job_num):for task_id in range(job_2_step_num[job_id]):start_ = solver.Value(all_tasks[job_id, task_id].start)start_time=str(datetime.timedelta(seconds=start_))machine_ = job_step_2_avail_machines[job_id, task_id][0]duration = job_step_machine_2_ptime[job_id, task_id, machine_]end_time=str(datetime.timedelta(seconds=start_+duration))j_record[(machine_, job_id)]=[start_time,end_time]gantt_data = []
for machine_ in range(1, Machine_num+1):for job_ in range(Job_num):if (machine_, job_) in j_record:gantt_data.append(dict(Task=f"Machine_{machine_}", Start=f"2023-12-01 {str(j_record[machine_, job_][0])}", Finish=f"2023-12-01 {str(j_record[machine_, job_][1])}", Resource=f"Job_{job_}"))fig = ff.create_gantt(gantt_data, index_col='Resource', group_tasks=True, show_colorbar=False, title="Gantt Chart of JSP(Mk10 240)")fig.show()

该求解结果的甘特图中,不展示图例的原因是该plotly库默认只有十种颜色的条形图,而本案例中的工件有20个,感兴趣的可以在库方法 create_gantt 中增加新的颜色。

不同场景下的求解效率对比

基于上述的求解结果,现在提出一个问题,即不同的工序分布是否会对求解效率有影响。

由于 JSP 问题的极度非凸的特性,可能很难去证明这种分布对效率的影响关系,但可以通过一些实验对特殊情况下的效率变化进行简单的判断。

实验二:工件的工序数有差异

为了保证可比性,这里的实验基于上述的 abz7.fjs 数据进行修改,在大部分的标准测试数据中工件的工序数都是相等的。这里我们对不等长的工艺流程问题进行求解效率的对比。

直观的,我们将一部分工件的工序移到另一部分工件工序的末尾,可以达到目的。然而,值得注意的是,若把每个工件的工序当成独立的色块,则不论如何修改这些工序所在的工件,问题的求解规模貌似没有变化,但是这部分往后移的工序的最早开工时间就会受到限制,总体目标值会更大。除此之外,还会有其他的变化吗?

调整后的数据如下:

20  15  1   
16  1   3   24  1   4   12  1   10  17  1   5   27  1   1   21  1   7   25  1   9   27  1   8   26  1   2   30  1   6   31  1   12  18  1   15  16  1   14  39  1   11  19  1   13  26   1   1   36 
17  1   7   30  1   4   15  1   13  20  1   12  19  1   2   24  1   14  15  1   11  28  1   3   36  1   6   26  1   8   15  1   1   11  1   9   23  1   15  20  1   10  26  1   5   28  1   13  17  1   7   15 
18  1   7   35  1   1   22  1   14  23  1   8   32  1   3   20  1   4   12  1   13  19  1   11  23  1   10  17  1   2   14  1   6   16  1   12  29  1   9   16  1   5   22  1   15  22  1   5   15  1   10  32  1   11  16
19  1   10  20  1   7   29  1   2   19  1   8   14  1   13  33  1   5   30  1   1   32  1   6   21  1   12  29  1   11  24  1   15  25  1   3   29  1   4   13  1   9   20  1   14  18  1   3   21  1   14  20  1   10  33  1   4   27 
20  1   12  23  1   14  20  1   2   28  1   7   32  1   8   16  1   6   18  1   9   24  1   10  23  1   4   24  1   11  34  1   3   24  1   1   24  1   15  28  1   13  15  1   5   18  1   5   23  1   14  40  1   11  12  1   7   23  1   8   27  
21  1   9   24  1   12  19  1   15  21  1   2   33  1   8   34  1   7   35  1   6   40  1   11  36  1   4   23  1   3   26  1   5   15  1   10  28  1   14  38  1   13  13  1   1   25  1   4   36  1   3   29  1   2   18  1   12  13  1   7   33  1   13  13  
22  1   14  27  1   4   30  1   7   21  1   9   19  1   13  12  1   5   27  1   3   39  1   10  13  1   15  12  1   6   36  1   11  21  1   12  17  1   2   29  1   1   17  1   8   33  1   12  36  1   5   12  1   11  33  1   15  19  1   10  16  1   14  27  1   1   21  
23  1   6   27  1   5   19  1   7   29  1   10  20  1   4   21  1   11  40  1   9   14  1   15  39  1   14  39  1   3   27  1   2   36  1   13  12  1   12  37  1   8   22  1   1   13  1   9   39  1   15  31  1   4   31  1   8   32  1   10  20  1   14  29  1   5   13  1   7   26  
24  1   14  32  1   12  29  1   9   24  1   4   27  1   6   40  1   5   21  1   10  26  1   1   27  1   15  27  1   7   16  1   3   21  1   11  13  1   8   28  1   13  28  1   2   32  1   10  16  1   4   17  1   2   12  1   3   13  1   13  40  1   7   17  1   9   30  1   5   38  1   1   13  
25  1   13  35  1   2   11  1   6   39  1   15  18  1   8   23  1   1   34  1   4   24  1   14  11  1   9   30  1   12  31  1   5   15  1   11  15  1   3   28  1   10  26  1   7   33   1   4   31  1   12  22  1   14  36  1   1   16  1   8   11  1   15  14  1   5   29  1   7   28  1   3   22  1   11  17  
14  1   11  28  1   6   37  1   13  29  1   2   31  1   8   25  1   9   13  1   15  14  1   5   20  1   4   27  1   10  25  1   14  31  1   12  14  1   7   25  1   3   39  
13  1   1   22  1   12  25  1   6   28  1   14  35  1   5   31  1   9   21  1   10  20  1   15  19  1   3   29  1   8   32  1   11  18  1   2   18  1   4   11   
12  1   13  39  1   6   32  1   3   36  1   9   14  1   4   28  1   14  37  1   1   38  1   7   20  1   8   19  1   12  12  1   15  22  1   2   36    
11  1   9   28  1   2   29  1   15  40  1   13  23  1   5   34  1   6   33  1   7   27  1   11  17  1   1   20  1   8   28  1   12  21   
10  1   10  21  1   15  34  1   4   30  1   13  38  1   1   11  1   12  16  1   3   14  1   6   14  1   2   34  1   9   33  
9  1   10  13  1   15  40  1   8   36  1   5   17  1   1   13  1   6   33  1   9   25  1   14  24  1   11  23  
8  1   4   25  1   6   15  1   3   28  1   13  40  1   8   39  1   2   31  1   9   35  1   7   31  
7  1   13  22  1   11  14  1   1   12  1   3   20  1   6   12  1   2   18  1   12  17  
6  1   6   18  1   11  30  1   8   38  1   15  22  1   14  15  1   12  20  
5  1   10  31  1   9   39  1   13  27  1   2   14  1   6   33 
Optimal Schedule Length: 724.0Statistics- conflicts: 4400- branches : 9376- wall time: 5.084242107000001s

在这里插入图片描述
如上结果,在改变工序的工件分布情况后,求解的目标值比先前的实验目标更高,这符合我们的预期,就是部分工序的最早开工时间更晚,导致目标值会更高,且该问题下的方案会比前一个问题的方案的甘特图较稀疏,这些都是很直观的差异。

但是,在求解效率上,同样是收敛到 Gap<5%,实验二的多次求解的平均求解时间是显著短于实验一的,一方面可能是由于理论的最优目标值上升,导致的下界值更大,更快地达到Gap=5%,这个猜测很好理解且很合理。

实验三:消除工件的加工时长差异

但进一步地考虑,会不会是因为实验二将部分工件的部分工序移到了另一部分工件上,导致工件的总体加工时长不同导致的?现考虑新的实验,即在实验二数据的基础上,修改每个工件工序的加工时长,控制每个工件的工序总加工时长一致。

修改方式为仅修改最后一步的加工时长,以实验二中最大总加工时长的工件为基准,其他工件的最后一个工序的加工时长加上差值,以此消除不同工件之间加工时长的差异。数据如下:

20  15  1   
16  1   3   24  1   4   12  1   10  17  1   5   27  1   1   21  1   7   25  1   9   27  1   8   26  1   2   30  1   6   31  1   12  18  1   15  16  1   14  39  1   11  19  1   13  26   1   1   258 
17  1   7   30  1   4   15  1   13  20  1   12  19  1   2   24  1   14  15  1   11  28  1   3   36  1   6   26  1   8   15  1   1   11  1   9   23  1   15  20  1   10  26  1   5   28  1   13  17  1   7   263 
18  1   7   35  1   1   22  1   14  23  1   8   32  1   3   20  1   4   12  1   13  19  1   11  23  1   10  17  1   2   14  1   6   16  1   12  29  1   9   16  1   5   22  1   15  22  1   5   15  1   10  32  1   11  247
19  1   10  20  1   7   29  1   2   19  1   8   14  1   13  33  1   5   30  1   1   32  1   6   21  1   12  29  1   11  24  1   15  25  1   3   29  1   4   13  1   9   20  1   14  18  1   3   21  1   14  20  1   10  33  1   4   186 
20  1   12  23  1   14  20  1   2   28  1   7   32  1   8   16  1   6   18  1   9   24  1   10  23  1   4   24  1   11  34  1   3   24  1   1   24  1   15  28  1   13  15  1   5   18  1   5   23  1   14  40  1   11  12  1   7   23  1   8   167  
21  1   9   24  1   12  19  1   15  21  1   2   33  1   8   34  1   7   35  1   6   40  1   11  36  1   4   23  1   3   26  1   5   15  1   10  28  1   14  38  1   13  13  1   1   25  1   4   36  1   3   29  1   2   18  1   12  13  1   7   33  1   13  77  
22  1   14  27  1   4   30  1   7   21  1   9   19  1   13  12  1   5   27  1   3   39  1   10  13  1   15  12  1   6   36  1   11  21  1   12  17  1   2   29  1   1   17  1   8   33  1   12  36  1   5   12  1   11  33  1   15  19  1   10  16  1   14  27  1   1   120  
23  1   6   27  1   5   19  1   7   29  1   10  20  1   4   21  1   11  40  1   9   14  1   15  39  1   14  39  1   3   27  1   2   36  1   13  12  1   12  37  1   8   22  1   1   13  1   9   39  1   15  31  1   4   31  1   8   32  1   10  20  1   14  29  1   5   13  1   7   26  
24  1   14  32  1   12  29  1   9   24  1   4   27  1   6   40  1   5   21  1   10  26  1   1   27  1   15  27  1   7   16  1   3   21  1   11  13  1   8   28  1   13  28  1   2   32  1   10  16  1   4   17  1   2   12  1   3   13  1   13  40  1   7   17  1   9   30  1   5   38  1   1   42  
25  1   13  35  1   2   11  1   6   39  1   15  18  1   8   23  1   1   34  1   4   24  1   14  11  1   9   30  1   12  31  1   5   15  1   11  15  1   3   28  1   10  26  1   7   33   1   4   31  1   12  22  1   14  36  1   1   16  1   8   11  1   15  14  1   5   29  1   7   28  1   3   22  1   11  34  
14  1   11  28  1   6   37  1   13  29  1   2   31  1   8   25  1   9   13  1   15  14  1   5   20  1   4   27  1   10  25  1   14  31  1   12  14  1   7   25  1   3   297  
13  1   1   22  1   12  25  1   6   28  1   14  35  1   5   31  1   9   21  1   10  20  1   15  19  1   3   29  1   8   32  1   11  18  1   2   18  1   4   318   
12  1   13  39  1   6   32  1   3   36  1   9   14  1   4   28  1   14  37  1   1   38  1   7   20  1   8   19  1   12  12  1   15  22  1   2   319    
11  1   9   28  1   2   29  1   15  40  1   13  23  1   5   34  1   6   33  1   7   27  1   11  17  1   1   20  1   8   28  1   12  337   
10  1   10  21  1   15  34  1   4   30  1   13  38  1   1   11  1   12  16  1   3   14  1   6   14  1   2   34  1   9   404  
9  1   10  13  1   15  40  1   8   36  1   5   17  1   1   13  1   6   33  1   9   25  1   14  24  1   11  415  
8  1   4   25  1   6   15  1   3   28  1   13  40  1   8   39  1   2   31  1   9   35  1   7   403  
7  1   13  22  1   11  14  1   1   12  1   3   20  1   6   12  1   2   18  1   12  518  
6  1   6   18  1   11  30  1   8   38  1   15  22  1   14  15  1   12  493  
5  1   10  31  1   9   39  1   13  27  1   2   14  1   6   505 
Optimal Schedule Length: 1763.0Statistics- conflicts: 132- branches : 861- wall time: 0.2170565s

在这里插入图片描述
结果发现,实验三平均求解0.2s左右的时间,Gap就收敛到5%以内,实验二到实验三的差距仅在统一了每个工件的总加工时长,带来的求解效率差距显著,由此可见,工序数对求解效率的影响可能更多地是由于工序的开工时间晚导致目标下限提高,进而减少了Gap收敛到5%以内的时间。而真正对求解时间有巨大影响的因素来自统一工序加工时长而改变的深层次原因。

实验三的求解时间缩短了二十多倍,而目标值提高不到3倍,由此可见是由于某些因素的改变导致的求解结构的变化,进而极大地改变了求解效率。

实验三与实验一的对比分析

对于实验三的效率急剧提升,我们进行猜测,难道工序的总工序加工时间保持一致?就能提高求解效率?假设实验三每个工件的工序都在同一台机器上加工,显然该猜测不成立,因为此时不论最后一步的加工时长多长,问题的求解规模是完全不变的。

而之所以实验三有极大的效率变化,是因为工件的工序处在不同的机器上加工,因此我们进一步猜测,这种求解收敛的效率,受到不同设备的可上工序的总加工时长的影响,时长差异越大,则求解收敛效率越高。从直观地理解来看,当瓶颈工序,瓶颈设备显著,则目标值的优化空间会限制在关键工序上,此时整体问题的收敛效率高。

根据实验二和实验三的数据调整可知,实验三数据中机器的可加工工序数与实验一一致,不发生改变,因此比较实验一和实验三的可加工工序的总时长,如下:

# 实验一
{1: 428, 2: 497, 3: 525, 4: 464, 5: 454, 6: 549, 7: 530, 8: 530, 9: 498, 10: 443, 11: 461, 12: 447, 13: 501, 14: 556, 15: 483}
方差:1660.2095238095237# 实验三
{1: 778, 2: 780, 3: 783, 4: 930, 5: 454, 6: 1021, 7: 1150, 8: 670, 9: 869, 10: 443, 11: 1101, 12: 1737, 13: 565, 14: 556, 15: 483}
方差:116802.38095238095

因此可知,JSP 问题中。设备上的可加工工序的总时长的差异越大,则问题的收敛效率越高,而工序在不同工件上的分布,以及工件的工序数、工件的工序总加工时长等并不很决定性的因素(引起的求解效率的变化不足以支撑它是关键因素)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/216538.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

节日气氛拉满的毛衣~你喜欢吗?

节日氛围感毛衣一眼就心动采用北极绒面料厚实软糯有质感拼接彩点正是氛围感的来源 整件穿上超级显白显气质 随便搭件牛仔裤还是休闲裤 来穿都很亮眼&#xff01;&#xff01;

Nginx首页修改及使用Nginx实现端口转发

按照我之前博客给的方法搭建好这样一个CTF靶场 但是呢它默认是在8000端口 如何直接访问IP地址或者域名就可以实现直接访问到靶场呢 我们需要将80端口的内容转发到8000&#xff0c;使用nginx实现端口转发功能 首先我们安装nginx&#xff1a; 安装工具和库 yum -y install gc…

CompletableFuture使用小结

为什么需要CompletableFuture CompletableFuture继承了CompletionStage接口和Future接口&#xff0c;在原有Future的基础上增加了异步回调、流式处理以及任务组合&#xff0c;成为JDK8多任务协同场景下一个有效利器。 CompletableFuture使用示例 提交有返回值的异步任务 通…

AI全栈大模型工程师(二十四)常用的超参

文章目录 七、先介绍几个常用的超参7.1、过拟合与欠拟合7.2、学习率调整策略八、自然语言处理常见的网络结构8.1、文本卷积神经网络 TextCNN8.2、循环神经网络 RNN8.3、Attention (for RNN)后记七、先介绍几个常用的超参 7.1、过拟合与欠拟合 奥卡姆剃刀: 两个处于竞争地位的…

6000字告诉你内向的程序员该如何工作比较合适

本文首发于我的个人掘金博客&#xff0c;看到很多人都比较喜欢这篇文章&#xff0c;分享给大家。 个人博客主页&#xff1a;https://www.aijavapro.cn 个人掘金主页&#xff1a;juejin.cn/user/2359988032644541/posts 个人的知识星球: 觉醒的新世界程序员 一、背景 之前写了…

【离散数学】——期末刷题题库( 二元关系)

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

在HarmonyOS上使用ArkUI实现计步器应用

介绍 本篇Codelab使用ArkTS语言实现计步器应用&#xff0c;应用主要包括计步传感器、定位服务和后台任务功能&#xff1a; 通过订阅计步器传感器获取计步器数据&#xff0c;处理后显示。通过订阅位置服务获取位置数据&#xff0c;处理后显示。通过服务开发实现后台任务功能。…

Ubuntu系统使用快速入门实践(七)——软件安装与使用(6)

Ubuntu系统使用快速入门实践系列文章 下面是Ubuntu系统使用系列文章的总链接&#xff0c;本人发表这个系列的文章链接均收录于此 Ubuntu系统使用快速入门实践系列文章总链接 下面是专栏地址&#xff1a; Ubuntu系统使用快速入门实践系列文章专栏 文章目录 Ubuntu系统使用快速…

外贸获客引流详细教程,小白也能懂!

一、引子 随着全球化的不断发展&#xff0c;国际贸易日益频繁&#xff0c;许多外贸企业为了拓展市场&#xff0c;获取更多客户&#xff0c;都在努力提高营销策略。 然而&#xff0c;对于许多外贸新手来说&#xff0c;如何高效地进行获客引流仍然是一个难题&#xff0c;今天&a…

机械中常用的一些术语

目录 一、OEMSOP:SOP编写指南 WI(标准作业指导书):标准作业程序 &#xff08;SOP&#xff09;:SOP和WI的区别&#xff1a;一、PFC、FMEA、PCP、WIPPAP、PSW&#xff1a;APQP&#xff1a;BOM&#xff08;Bill of Material&#xff09;物料清单DV&#xff08;设计验证&#xff09…

“产学研用”深度融合,校企合作助力烟花产业数字化发展

为推动烟花行业数字化转型升级&#xff0c;充分发挥科教资源优势&#xff0c;技术成果及创新资源&#xff0c;推动构建产学研用高效协同&#xff0c;加快提升烟花产业创新能力&#xff0c;助力企业在国内外复杂的市场环境下提升发展能力及竞争能力。12月6日&#xff0c;烟花生产…

前端知识(十)———JavaScript 使用URL跳转传递数组对象数据类型的方法

目录 首先了解一下正常传递基本数据类型 JavaScript跳转页面方法 JavaScript路由传递参数 JavaScript路由接收参数传递对象、数组 在前端有的时候会需要用链接进行传递参数&#xff0c;基本数据类型的传递还是比较简单的&#xff0c;但是如果要传递引用数据类型就比较麻烦了…

如何让弹出的.py文件窗口缩小

原图比例如下&#xff0c;很明显实际大小已经超出屏幕显示范围&#xff1a; 参考这篇文章的代码&#xff0c;新定义一个函数&#xff1a; def get_scaling():user32 windll.user32# 获取现在的尺寸&#xff08;缩放后now_width user32.GetSystemMetrics(0)now_height user…

Day07 Liunx高级系统设计8-线程

概述 进程与线程 进程 : 系统分配资源的基本单位 , 可以简单理解为一个正在进行的程序 线程 : 操作系统调度的最小单位 , 就是一段代码的执行顺序 注意&#xff1a; 1, 一个进程必须要有一个线程 , 该线程被称为主线程 2, 一个进程可以有多个线程 , 除主线程外的其他线程都是…

我的创作三周年纪念日

今天收到CSDN官方的来信&#xff0c;创作三周纪念日到了。 Dear: Hann Yang &#xff0c;有幸再次遇见你&#xff1a; 还记得 2020 年 12 月 12 日吗&#xff1f; 你撰写了第 1 篇技术博客&#xff1a; 《vba程序用7重循环来计算24》 在这平凡的一天&#xff0c;你赋予了它…

MacOS 12 开放指定端口 指定ip访问

MacOS 12 开放指定端口 指定ip访问 在 macOS 上开放一个端口&#xff0c;并指定只能特定的 IP 访问&#xff0c;你可以使用 macOS 内置的 pfctl&#xff08;Packet Filter&#xff09;工具来实现。 以下是一些基本的步骤&#xff1a; 1、 编辑 pf 配置文件&#xff1a; 打开 /…

leetcode 30. 串联所有单词的子串(优质解法)

代码&#xff1a; class Solution {public static List<Integer> findSubstring(String s, String[] words) {List<Integer> integerListnew ArrayList<>();int lengthwords.length; //words 数组中的字符串个数int sizewords[0].length(); //words 数组…

C++STL的vector模拟实现

文章目录 前言成员变量成员函数构造函数push_backpop_backinserterase析构函数拷贝构造 前言 成员变量 namespace but {template<class T>class vector{public:typedef T* iterator;private:iterator _start;iterator _finish;iterator _end_of_storage;}; }我们之前实…

Docker的安装与简单操作命令

目录 前言 docker的安装 基础docker操作 容器管理 镜像管理 容器镜像封装与加载 前言 前文简单说明了容器技术出现的背景&#xff0c;与对docker做了结构上的介绍Container容器技术简介-CSDN博客https://blog.csdn.net/qq_72569959/article/details/134814887 讲到dock…

研究前沿| Nat Communi:大豆节间距调控基因RIN1的分子机制解析

引言 株型是决定作物产量的重要性状。以半矮秆利用和提高氮肥利用效率为标志的绿色革命提高了作物抗倒伏能力&#xff0c;使水稻、小麦等作物可以通过密植提高单产&#xff0c;产量大幅提升。但是&#xff0c;大豆绿色革命基因尚未发现&#xff0c;与水稻和小麦产量提升相比&am…