「达摩院MindOpt」优化FlowShop流水线作业排班问题

news2024/11/17 0:06:17

FlowShop流水线作业

在企业在面临大量多样化的生产任务时,如何合理地安排流水线作业以提高生产效率及确保交货期成为了一个重要的问题。

一个典型的问题就是FlowShop流水线作业安排问题,也有称为生产下料问题。它涉及到多台机器、多个工序以及多个作业的调度安排。在这个问题中,我们需要对多个作业在一组流水线上的处理顺序进行安排,以使得完成所有作业的总时间最短。

与FlowShop相似的还有JobShop调度问题,它们都涉及到多个作业在多台机器上的处理顺序安排,但FlowShop是顺序安排,处理顺序一致,JobShop是作业处理顺序可以不同,安排更灵活,调度约束相对复杂。通常JobShop调度问题通常比FlowShop调度问题更难求解。

本案例将着重介绍FlowShop问题,将向大家介绍如何运用数学规划方法来解决这一问题,帮助企业优化生产过程,实现生产目标。

1. 问题描述

有一个公司生产几套产品,这些产品各不一样,生产各个环节的耗时会不一致,即在每个工序上的耗时不一致。工厂的机器资源有限,如何合理安排产品的生产,让总生产耗时最短?

image.png

  • 假设所有产品都设计成按同样顺序来经过这些加工工序。
  • 各个产品在各个工序的耗时如下表,当有些工序不需要的时候,我们用耗时0来表示

产品ID产品任务1产品任务2产品任务3产品任务4产品任务5产品任务6产品任务7产品任务8产品任务9产品任务10产品任务11产品任务12产品任务13产品任务14产品任务15产品任务16产品任务17产品任务18产品任务19产品任务20
工序机器15483157177365338278776911429127732876894
工序机器2793119956709960556361737547142186577
工序机器316894915894560235764716341634726757740
工序机器4665831687891135949858593941564054775131
工序机器5585620855335534169138672849478758186828

  • 加工完后,工序资源能立即释放出来去生产下一个产品。(此处时简化问题,把工序准备时间加一起了,实际中工序准备可以分开,同一个产品可以在上一个工序还没有生产完的时候就开始准备,即时间可以有重叠,本案例不讨论此情况)
  • 每个工序同时处理的产品只有一种。

请问,如何安排生产,可以让最后完工的时间最小?

2. 数据准备

根据问题的描述,我们整理相应的数据为方便程序读的数据,如CSV的表格。
另外,这里我们做两份数据,方便大家理解怎么将自己业务数据整理后输入。
数据1:Raw数据:根据原问题的表格整理,prductionTime_Raw.csv文件

产品ID产品任务1产品任务2产品任务3产品任务4产品任务5产品任务6产品任务7产品任务8产品任务9产品任务10产品任务11产品任务12产品任务13产品任务14产品任务15产品任务16产品任务17产品任务18产品任务19产品任务20
工序机器15483157177365338278776911429127732876894
工序机器2793119956709960556361737547142186577
工序机器316894915894560235764716341634726757740
工序机器4665831687891135949858593941564054775131
工序机器5585620855335534169138672849478758186828

数据2:修改后数据,修改内容主要是:

  1. 前一天已经生产到一半的任务,已完成的工序耗时设为0;
  2. 不同产品生产工序有区别,将有些不需要执行的工序,耗时设置为0。

修改后的数据如下,同 prductionTime.csv文件


产品ID产品任务1产品任务2产品任务3产品任务4产品任务5产品任务6产品任务7产品任务8产品任务9产品任务10产品任务11产品任务12产品任务13产品任务14产品任务15产品任务16产品任务17产品任务18产品任务19产品任务20
工序机器1000077365338278776911429127732876894
工序机器20009956709960556061737547142186577
工序机器30049158906023576470634163472675040
工序机器40583168780135949858593941564054775131
工序机器55856208553053416913867284947058186828

3. 数学建模

这是个经典的FlowShop问题,最小化生产时间。决策的变量是不同产品/工件的生产顺序。

数学模型如下:
min ⁡ e M m a x , J m a x s.t. ∑ k ∈ J x i , k = 1 ∀ i ∈ J ∑ i ∈ J x i , k = 1 ∀ k ∈ J e m , k ≥ s m , k + ∑ i ∈ J P i , m ⋅ x i , k ∀ m ∈ M , k ∈ J s m , k + 1 ≥ e m , k ∀ m ∈ M , k ∈ { 1 , 2 , . . , J m a x − 1 } s m + 1 , k ≥ e m , k ∀ k ∈ J , M ∈ { 1 , 2 , . . , M m a x − 1 } s 1 , 1 = 0 s m , k , e m , k ≥ 0 ∀ m ∈ M , k ∈ J x i , k ∈ { 0 , 1 } ∀ k , i ∈ I \begin{array}{rll} \min & e_{{M_{max},J_{max}}} & \\ \text{s.t.} & \sum_{k \in J} x_{i,k} = 1 & \forall i \in J \\ & \sum_{i \in J} x_{i,k} = 1 & \forall k \in J \\ & e_{m,k} \geq s_{m,k} + \sum_{i \in J} P_{i,m} \cdot x_{i,k} & \forall m \in M, k \in J\\ & s_{m,k+1} \geq e_{m,k} & \forall m \in M , k \in \{1,2,..,J_{max}-1\} \\ & s_{m+1,k} \geq e_{m,k} & \forall k \in J , M \in \{1,2,..,M_{max}-1\}\\ & s_{1,1}=0 &\\ & s_{m,k},e_{m,k}\geq 0 & \forall m \in M, k\in J \\ & x_{i,k}\in\{0,1\} & \forall k,i \in I \end{array} mins.t.eMmax,JmaxkJxi,k=1iJxi,k=1em,ksm,k+iJPi,mxi,ksm,k+1em,ksm+1,kem,ks1,1=0sm,k,em,k0xi,k{0,1}iJkJmM,kJmM,k{1,2,..,Jmax1}kJ,M{1,2,..,Mmax1}mM,kJk,iI
更细节的数学公式请查看案例

4. MindOpt APL 建模和求解

MindOpt APL是一款代数建模语言,它可以方便地将数学语言描述成程序,然后调用多种求解器求解。MindOpt Solver支持混合整数线性规划(MILP)问题的求解,可选用它。

改写上面的数据图和数学模型,其中数据为了读取和索引加序号方便,我们把上面的表存储为kkv的长表单形式 prductionTime_long.csvprductionTime_long_Raw.csv,并把产品清单和工序清单名字以数字的形式分别存入:Products_name.csv、Machines_name.csv
(请注意,由于我们里面需要用到m+1这样的顺序概念,因此建议把工序的ID用从1开始的顺序排的数字来记录,编程序更方便。)

代码解析

决策变量
var x[<i,k> in Jobs*Jobs] binary;
  • 这是一个二进制决策变量用于表示作业i是否排在位置k上。
  • 如果作业i排在位置k,则x[i,k]等于1,否则等于0。
  • 注意这里使用了JobsJobs,正常情况下应该是JobsMachines或者其他表示作业与位置之间关系的集合。使用Jobs*Jobs可能是为了表示作业顺序而非作业和机器之间的关系。

var s[<m,k> in Machines * Jobs] >= 0;
  • 这个变量’s’代表作业k在机器m上的开始时间。
  • 约束条件保证’s’的值大于或等于0,表示不能有负的开始时间。

var e[<m,k> in Machines * Jobs] >= 0;
  • 这个变量’e’代表作业k在机器m上的结束时间。
  • 同样地,约束条件保证’e’的值大于或等于0,表示不能有负的结束时间。
决策目标
minimize TotalTime: e[lastMachines,lastJobs];

其中 e[m,k] 表示作业 k 在机器 m 上的结束时间。这里 lastMachines 和 lastJobs 分别指最后一台机器和最后一个作业。

约束
  1. 该约束条件表示每个产品必须在一个位置上进行处理。对于每个产品i,通过对其所有位置k上的处理决策进行求和,得到的结果必须等于1,表示每个产品只能在一个位置上进行处理。
subto constraint_1: forall { i in Jobs} sum {k in Jobs} x[i,k] == 1;
  1. 该约束条件表示每个位置只能处理一个产品。对于每个位置k,通过对其所有产品i的处理决策进行求和,得到的结果必须等于1,表示每个位置只能处理一个产品。
subto constraint_1_1: forall { k in Jobs} sum {i in Jobs} x[i,k] == 1; 
  1. 该约束条件表示产品在每个工序的结束时间必须大于等于产品在该工序的开始时间加上该工序的耗时。对于每个工序m和产品k,通过对产品i在工序m上的处理决策乘以其耗时,求和得到的结果必须小于等于产品在该工序的结束时间。
subto constraint_2: forall {<m,k> in Machines * Jobs} e[m,k] >= s[m,k] + sum {i in Jobs} (ProductionTime[i,m] * x[i,k]); 
  1. 该约束条件表示产品在每个工序的下一个位置上的开始时间必须大于等于产品在当前位置的结束时间。对于每个工序m和产品k,下一个位置k+1上的开始时间必须大于等于当前位置k上的结束时间。
subto constraint_3: forall {<m,k> in Machines * (Jobs without {lastJobs})} s[m,k+1] >= e[m,k];
  1. 该约束条件表示产品在下一个工序的同一位置上的开始时间必须大于等于产品在当前工序的结束时间。对于每个工序m和产品k,下一个工序m+1上的同一位置k的开始时间必须大于等于当前工序m上的结束时间。
subto constraint_3_1: forall {<m,k> in (Machines without {lastMachines}) * Jobs } s[m+1,k] >= e[m,k]; 
  1. 该约束条件表示第一个工序中第一个产品的开始时间必须为0,即从0时刻开始生产第一个产品。
subto constraint_4: s[1,1] == 0;

完整代码

代码第11和12行是切换不同的问题数据。

然后如下代码,在Notebook的cell中运行它,进行建模、求解,并整理存储结果:

clear model;
option modelname flowshop_demo; #定义存储文件名

# ----------建模--------Start----
# flowshop_production.mapl

# 读取数据
param fileDir = "data/";
set Jobs = {read fileDir+"Products_name.csv" as "<1n>" skip 1}; # 读取产品任务列表
set Machines = {read fileDir+"Machines_name.csv" as "<1n>" skip 1}; # 读取工序机器列表
#两种任务数据,可改注释#符号切换
param ProductionTime[Jobs*Machines] = read fileDir+"prductionTime_long_Raw.csv" as "<1n,2n> 3n" skip 1; #读取每个产品在每个工序的耗时
#param ProductionTime[Jobs*Machines] = read fileDir+"prductionTime_long.csv" as "<1n,2n> 3n" skip 1; #读取每个产品在每个工序的耗时

param lastJobs = card(Jobs);
param lastMachines = card(Machines);
print "总共有{}个产品任务,{}个工序机器" % lastJobs,lastMachines;

# 声明变量
var x[<i,k> in Jobs*Jobs] binary;
var s[<m,k> in Machines * Jobs] >= 0;
var e[<m,k> in Machines * Jobs] >= 0;

# 申明目标
minimize TotalTime: e[lastMachines,lastJobs];

# 约束
subto constraint_1:
    forall { i in Jobs}
        sum {k in Jobs} x[i,k] == 1;
subto constraint_1_1:
    forall { k in Jobs}
        sum {i in Jobs} x[i,k] == 1;

subto constraint_2:
    forall {<m,k> in Machines * Jobs}
        e[m,k] >= s[m,k] + sum {i in Jobs} (ProductionTime[i,m] * x[i,k]);

subto constraint_3:
    forall {<m,k> in Machines * (Jobs without {lastJobs})}  
        s[m,k+1] >= e[m,k];
subto constraint_3_1:
    forall {<m,k> in (Machines without {lastMachines}) * Jobs }
        s[m+1,k] >= e[m,k];

subto constraint_4:
        s[1,1] == 0;

#求解
option solver mindopt;     # (可选)指定求解用的求解器,默认是MindOpt

#option mindopt_options 'max_time=600'; #设置求解器参数
#option mindopt_options 'print=0'; #设置求解器输出级别,减少过程打印
solve;         # 求解

# 结果打印和检查结果
print "----------------结果打印和存文件--------------";
#display; #打印太多,注释了
print "最小生产耗时 = ",e[lastMachines,lastJobs];

运行上述代码结果如下:

总共有20个产品任务,5个工序机器
Running mindoptampl
wantsol=1
MindOpt Version 1.0.1 (Build date: 20231114)
Copyright (c) 2020-2023 Alibaba Cloud.

Start license validation (current time : 28-DEC-2023 20:40:53).
License validation terminated. Time : 0.006s

Model summary.
 - Num. variables     : 600
 - Num. constraints   : 315
 - Num. nonzeros      : 3350
 - Num. integer vars. : 400
 - Bound range        : [1.0e+00,1.0e+00]
 - Objective range    : [1.0e+00,1.0e+00]

Branch-and-cut method started.
Original model: nrow = 315 ncol = 600 nnz = 3350
Tolerance: primal = 1e-06 int = 1e-06 mipgap = 0.0001 mipgapAbs = 1e-06
Limit: time = 1.79769313486232e+308 node = -1 stalling = -1 solution = -1
presolver terminated; took 0 ms
presolver terminated; took 163 ms
Parallelism: root=4, tree=4
      accept new sol: obj 1448 bnd vio 1.11022302462516e-16 int vio 1.11022302462516e-16 mipgap 1 time 3
Model summary.
 - Num. variables     : 476
 - Num. constraints   : 192
 - Num. nonzeros      : 7883
 - Bound range        : [1.0e+00,5.4e+01]
 - Objective range    : [1.0e+00,8.7e+01]
 - Matrix range       : [1.0e+00,3.5e+02]

Presolver started.
Presolver terminated. Time : 0.002s

Simplex method started.
Model fingerprint: =Y2dmN2bgdnYgN2dm5mZ

    Iteration       Objective       Dual Inf.     Primal Inf.     Time
            0     1.45592e+02      0.0000e+00      4.0472e+01     0.00s  
          595     1.24863e+03      0.0000e+00      0.0000e+00     0.02s  
Postsolver started.
Simplex method terminated. Time : 0.018s

Root relaxation: 1248.62782173302 iteration = 595 time = 0.02
 #node(P:0 Q:0) #(dual:1248.63 best:1448 gap:13.77%) #time = 3
      accept new sol: obj 1410 bnd vio 2.8421709430404e-14 int vio 2.22044604925031e-16 mipgap 0.114448353380835 time 3
      accept new sol: obj 1385 bnd vio 1.95761774137987e-14 int vio 1.45008721583694e-16 mipgap 0.098463666618756 time 3
      accept new sol: obj 1376 bnd vio 2.22044604925031e-16 int vio 2.22044604925031e-16 mipgap 0.0925669900196054 time 3
      accept new sol: obj 1349 bnd vio 4.2632564145606e-14 int vio 2.22044604925031e-16 mipgap 0.0744048764025033 time 3
      accept new sol: obj 1344 bnd vio 2.8421709430404e-13 int vio 1.11022302462516e-16 mipgap 0.0709614421629293 time 4
      accept new sol: obj 1304 bnd vio 2.8421709430404e-13 int vio 9.99200722162641e-16 mipgap 0.0424633268918535 time 5
      accept new sol: obj 1291 bnd vio 3.33066907387547e-16 int vio 3.33066907387547e-16 mipgap 0.03282120702322 time 7
      accept new sol: obj 1290 bnd vio 2.22044604925031e-16 int vio 2.22044604925031e-16 mipgap 0.0320714560209124 time 13
      accept new sol: obj 1278 bnd vio 2.79866832656529e-14 int vio 3.33066907387547e-16 mipgap 0.0223161708476798 time 24
Branch-and-cut method terminated. Time : 31.571s


OPTIMAL; objective 1278.00

Completed.
----------------结果打印和存文件--------------
最小生产耗时 = 1278
产品,序号,……,|第1个工序s,耗时,|第2个工序s,耗时,|第3个工序s,耗时,|第4个工序s,耗时,|第5个工序s,耗时,|最后结束时间
1,9,……,|343,54,|397,79,|488,16,|562,66,|645,58,|703
2,8,……,|260,83,|394,3,|399,89,|504,58,|589,56,|645
3,11,……,|474,15,|532,11,|636,49,|714,31,|759,20,|779
4,7,……,|189,71,|285,99,|384,15,|436,68,|504,85,|589
5,10,……,|397,77,|476,56,|532,89,|628,78,|706,53,|759
6,4,……,|71,36,|129,70,|199,45,|255,91,|362,35,|397
7,12,……,|489,53,|543,99,|685,60,|745,13,|779,53,|832
8,15,……,|647,38,|722,60,|799,23,|884,59,|1001,41,|1042
9,2,……,|32,27,|74,5,|79,57,|150,49,|199,69,|268
10,18,……,|849,87,|942,56,|998,64,|1062,85,|1147,13,|1160
11,13,……,|542,76,|642,3,|751,7,|758,85,|866,86,|952
12,20,……,|1030,91,|1135,61,|1196,1,|1197,9,|1206,72,|1278
13,6,……,|175,14,|212,73,|321,63,|397,39,|496,8,|504
14,14,……,|618,29,|647,75,|758,41,|843,41,|952,49,|1001
15,3,……,|59,12,|82,47,|136,63,|199,56,|268,47,|315
16,17,……,|772,77,|928,14,|951,47,|1020,40,|1060,87,|1147
17,1,……,|0,32,|32,21,|53,26,|79,54,|133,58,|191
18,16,……,|685,87,|782,86,|868,75,|943,77,|1042,18,|1060
19,5,……,|107,68,|207,5,|244,77,|346,51,|397,68,|465
20,19,……,|936,94,|1030,77,|1107,40,|1147,31,|1178,28,|1206

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

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

相关文章

QWebEngineView类方法、属性、信号与槽汇总

文章目录 📖 介绍 📖🏡 环境 🏡📒 使用方法 📒📝 使用示例📝 方法📝 属性📝 信号(Signals)📝 槽(Slots)⚓️ 相关链接 ⚓️📖 介绍 📖 QWebEngineView 是 Qt 提供的一个用于呈现 Web 内容的类,基于 Google 的 Chromium 浏览器引擎。它提供了对现…

在线直线度测量仪确保了出厂圆棒无不合格品

在线直线度测量仪确保了出厂圆棒无不合格品 随着生产设备的改进&#xff0c;利用基础材料进行生产的厂家对品质要求也越来越高&#xff0c;其中圆形棒管材的直线度尺寸&#xff0c;也是广受关注&#xff0c;对其进行矫直检测&#xff0c;使其出厂无不合格品。 变抽检为全检 以前…

C 语言每日一题——旋转数组的最小数字

一、题目内容 提供一下该OJ题的链接&#xff1a;旋转数组的最小数字_牛客题霸_牛客网 (nowcoder.com) 二、题目分析 通过示例1可知&#xff0c;我们写代码的目的是在数组中找到一个最大值&#xff0c;并且返回来&#xff1b; 我们很容易的会想到创建一个变量&#xff1a;int…

企业培训系统源码:构建智能、可扩展的学习平台

企业培训系统在现代企业中扮演着至关重要的角色。本文将通过深度解析企业培训系统的源码&#xff0c;介绍如何构建一个智能、可扩展的学习平台&#xff0c;涉及关键技术和代码实例。 1. 技术栈选择与项目初始化 在构建企业培训系统之前&#xff0c;选择适当的技术栈是至关重…

先锋WEB燃气收费系统 Upload.aspx 文件上传漏洞复现

0x01 产品简介 先锋WEB燃气收费系统是一种先进的在线燃气收费解决方案,旨在简化和优化燃气收费的流程和管理。该系统基于Web平台,提供了一系列功能和工具,使燃气公司能够高效地进行收费、账单管理和客户服务。 0x02 漏洞概述 先锋WEB燃气收费系统/AjaxService/Upload.asp…

Windows压缩包的MySQL安装方式

1.下载压缩包 https://cdn.mysql.com//Downloads/MySQL-8.0/mysql-8.0.35-winx64.zip 2.解压压缩包&#xff08;建议将解压到非C盘&#xff0c;路径不要出现特殊符号&#xff09; 3.在MySQL主目录下&#xff0c;创建my.ini空文件&#xff08;先创建一个txt文件&#xff0c;进…

软件测试|selenium 元素无法选择异常的原因及解决

简介 在进行 Web 自动化测试时&#xff0c;使用 Selenium 可能会遇到各种异常情况。其中之一就是 ElementNotSelectableException 异常&#xff0c;该异常通常意味着在尝试选择一个不可选元素时出现了问题。本文将详细介绍这个异常的原因、可能的解决方法&#xff0c;并提供示…

微信小程序开发学习笔记《10》页面导航

微信小程序开发学习笔记《10》页面导航 博主正在学习微信小程序开发&#xff0c;希望记录自己学习过程同时与广大网友共同学习讨论。导航 官方文档 一、介绍 1. 什么是页面导航 页面导航指的是页面之间的相互跳转。例如&#xff0c;浏览器中实现页面导航的方式有如下两种: …

<蓝桥杯软件赛>零基础备赛20周--第14周--BFS

报名明年4月蓝桥杯软件赛的同学们&#xff0c;如果你是大一零基础&#xff0c;目前懵懂中&#xff0c;不知该怎么办&#xff0c;可以看看本博客系列&#xff1a;备赛20周合集 20周的完整安排请点击&#xff1a;20周计划 每周发1个博客&#xff0c;共20周。 在QQ群上交流答疑&am…

C++I/O流——(2)预定义格式的输入/输出(第一节)

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd; 含泪播种的人一定能含笑收获&#xff…

snmp协议配置

引言 SNMP&#xff08;Simple Network Management Protocol&#xff09;是一种网络管理协议&#xff0c;用于管理和监控网络设备、操作系统和应用程序。它提供了一组用于检索和修改网络设备配置、监视设备状态和性能的标准化方法。 SNMP 是一个客户端-服务器协议&#xff0c;…

【Docker】数据管理之数据卷的挂载

一、什么是数据卷 为了很好的实现数据保存和数据共享&#xff0c;Docker提出了Volume这个概念&#xff0c;简单的说就是绕过默认的联合 文件系统&#xff0c;而以正常的文件或者目录的形式存在于宿主机上。又被称作数据卷。数据卷提供了一些有用的特性&#xff1a; 数据卷可以在…

java自定义排序Comparator

&#x1f4d1;前言 本文主要是【java】——java自定义排序Comparator的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304;每…

《C++ Primer》第14章 重载运算与类型转换(一)

参考资料&#xff1a; 《C Primer》第5版《C Primer 习题集》第5版 14.1 基本概念&#xff08;P490&#xff09; 重载的运算符是具有特殊名字的函数&#xff0c;其名字有 operator 和要定义的运算符组合而成。和其他函数一样&#xff0c;重载运算符也具有返回类型、参数列表…

人工智能推动供应链革命的成功

人工智能推动供应链革命的成功 目录 人工智能推动供应链革命的成功一、供应链管理不断变化的面貌二、拥挤的解决方案景观三、踏上人工智能驱动的转型1. 价值创造识别、战略和路线图2. 目标解决方案设计和供应商选择3. 实施与系统集成4. 变革管理、能力建设和全面价值获取 新技术…

深思这届CES,前沿新物种「辣眼睛」背后

作者 | 陈然 来源 | 洞见新研社 每届CES都会让不少人发出“无趣”的感叹。的确&#xff0c;无论是置身会场还是看网络上的报道&#xff0c;到处都是熙熙攘攘的人群&#xff0c;很难从中发现哪些产品或创意值得把玩一番。 实际上&#xff0c;辣眼睛的新物种常有&#xff0c;制…

发动机装备3d虚拟在线云展馆360度展示每处细节

在当今数字化的时代&#xff0c;消费者对于线上购物的需求与期待日益增长。尤其在购车这一大宗消费行为上&#xff0c;消费者不再满足于传统的图片与文字介绍。为了满足这一市场需求&#xff0c;我们引入了3D线上展示技术。 3D汽车模型实景互动展示是一种通过先进的三维建模技术…

软件测试|selenium 元素无此属性NoSuchAttributeException问题分析与解决

简介 在使用Selenium进行Web自动化测试时&#xff0c;我们可能会遇到NoSuchAttributeException异常。这个异常通常在尝试访问一个元素的属性&#xff08;attribute&#xff09;时抛出&#xff0c;但该属性不存在。本文将介绍NoSuchAttributeException异常的常见原因以及解决方…

Exception in thread “main“ java.lang.ArrayIndexOutOfBoundsException(数组创建问题)

数组在Java中使用还是比较多的&#xff0c;通过索引去数组中寻值&#xff0c;也可以通过数组索引去赋值 问题描述&#xff1a; 我们在直接使用未被new的数组时就会出现这种情况&#xff0c; 这边简单创建一个运行类 public class a {public static void main(String[] args)…

大数据-hive函数与mysql函数的辨析及练习-将多行聚合成一行

目录 1. &#x1f959;collect_list: 聚合-不去重 2. &#x1f959;collect_set(col): 聚合-去重 3. &#x1f959;mysql的聚合函数-group_concat 4. leetcode练习题 1. &#x1f959;collect_list: 聚合-不去重 将组内的元素收集成数组 不会去重 2. &#x1f959;collec…