杉数求解器-多商品问题的求解(数模玩家必看)

文摘   2024-07-25 11:49   湖北  

杉数求解器这个案例很常见,我们直接讲代码吧。多商品问题约束其实好理解

我们可以尝试一下做一下杉数官网的题目。

本文参考代码:muticommodity.py。

import coptpy as cpfrom coptpy import COPTimport mathimport itertools

日常导库奥。

ORIG = ['GARY', 'CLEV', 'PITT']DEST = ['FRA', 'DET', 'LAN', 'WIN', 'STL', 'FRE', 'LAF']PROD = ['bands', 'coils', 'plate']

解释一下,这个orig是原始地点列表,dest是目的地,prod是产品名称。

supply_list = [400, 800, 200,               700, 1600, 300,               800, 1800, 300]supply = dict(zip(itertools.product(ORIG, PROD), supply_list))

这个是原始地点和供应量。字典这个功能别忘记了,是一个映射。(体会一下,很好理解的)好家伙这个地方可以求解这个题目了2024年亚太赛中文赛C题-一种常见的调度问题求解模型(含相似题对比和提示词工程)

demand_list = [300, 500, 100,               300, 750, 100,               100, 400,   0,                75, 250,  50,               650, 950, 200,               225, 850, 100,               250, 500, 250]demand = dict(zip(itertools.product(DEST, PROD), demand_list))

这个是需求数据,那好我们讲通透一点吧。

各位同学们看哈,原始地点是3个所以是3行,产品是3个所以是3列,没问题吧。然后看需求,我们看看需求因为是7个目的地所以7行没问题吧,然后是3个产品3列对吧?解释完了。
limit_list = [625.0] * len(ORIG) * len(DEST)limit = dict(zip(itertools.product(ORIG, DEST), limit_list))
#limit_list: 每个原始地点和目的地点间运输限制的列表。#limit: 字典,将每个原始地点和目的地点的组合映射到运输限制

代码注释如上。

cost_list = [30, 39, 41,             10, 14, 15,              ...             15, 20, 20]cost = dict(zip(itertools.product(ORIG, DEST, PROD), cost_list))

这个是成本数据,代码设计的时候注意这个cost这一行,ORIG,DEST,PROD梦幻联动。

env = cp.Envr()mmulti = env.createModel()

杉数行为,我们不解释,准备放大招。

vtrans = mmulti.addVars(ORIG, DEST, PROD, nameprefix='trans')
#vtrans: 定义了从每个原始地点到每个目的地点每种产品的运输量的决策变量

接下来三个约束

mmulti.addConstrs((vtrans.sum(i, '*', k) == supply[i, k] for i in ORIG for k in PROD), nameprefix='supply')mmulti.addConstrs((vtrans.sum('*', j, k) == demand[j, k] for j in DEST for k in PROD), nameprefix='demand')mmulti.addConstrs((vtrans.sum(i, j, '*') <= limit[i, j] for i in ORIG for j in DEST), nameprefix='multi')
#供应约束: 确保每种产品从每个原始地点运输的总量与供应相匹配。#需求约束: 确保每种产品运输到每个目的地的总量与需求相匹配。#多限制约束: 限制每个原始地点到每个目的地的总运输量。

接下来最小化运输成本

mmulti.setObjective(vtrans.prod(cost), COPT.MINIMIZE)

我们设置一个参数

mmulti.setParam(COPT.Param.TimeLimit, 100)mmulti.solve()

第一是求解,其实设置的是求解时间,设置不设置不影响问题本身。

if mmulti.status == COPT.OPTIMAL:    print('\nObjective value: {}'.format(mmulti.objval))    print('Variable solution: ')    multvars = mmulti.getVars()    for mvar in multvars:        if math.fabs(mvar.x) >= 1e-6:            print('    {0:s} = {1:.6f}'.format(mvar.name, mvar.x))

这段代码是通用的代码,这下知道了吧。

这个问题本质上是混合整数规划问题。

Cardinal Optimizer v7.1.3. Build date Apr 29 2024Copyright Cardinal Operations 2024. All Rights Reserved
Setting parameter 'TimeLimit' to 100Model fingerprint: be2910e5
Using Cardinal Optimizer v7.1.3 on WindowsHardware has 4 cores and 8 threads. Using instruction set X86_AVX512_E1 (14)Minimizing an LP problem
The original problem has: 51 rows, 63 columns and 189 non-zero elementsThe presolved problem has: 41 rows, 60 columns and 145 non-zero elements
Starting the simplex solver using up to 8 threads
Method Iteration Objective Primal.NInf Dual.NInf TimeDual 0 0.0000000000e+00 26 0 0.02sDual 45 1.9951537592e+05 0 0 0.02sPostsolvingDual 45 1.9950000000e+05 0 0 0.02s
Solving finishedStatus: Optimal Objective: 1.9950000000e+05 Iterations: 45 Time: 0.03s
Objective value: 199500.0Variable solution: trans(GARY,STL,bands) = 400.000000 trans(GARY,STL,coils) = 25.000000 trans(GARY,STL,plate) = 200.000000 trans(GARY,FRE,coils) = 625.000000 trans(GARY,LAF,coils) = 150.000000 trans(CLEV,FRA,bands) = 225.000000 trans(CLEV,FRA,plate) = 50.000000 trans(CLEV,DET,coils) = 525.000000 trans(CLEV,DET,plate) = 100.000000 trans(CLEV,LAN,coils) = 400.000000 trans(CLEV,WIN,coils) = 150.000000 trans(CLEV,WIN,plate) = 50.000000 trans(CLEV,STL,bands) = 250.000000 trans(CLEV,STL,coils) = 300.000000 trans(CLEV,FRE,coils) = 225.000000 trans(CLEV,FRE,plate) = 100.000000 trans(CLEV,LAF,bands) = 225.000000 trans(PITT,FRA,bands) = 75.000000 trans(PITT,FRA,coils) = 500.000000 trans(PITT,FRA,plate) = 50.000000 trans(PITT,DET,bands) = 300.000000 trans(PITT,DET,coils) = 225.000000 trans(PITT,LAN,bands) = 100.000000 trans(PITT,WIN,bands) = 75.000000 trans(PITT,WIN,coils) = 100.000000 trans(PITT,STL,coils) = 625.000000 trans(PITT,FRE,bands) = 225.000000 trans(PITT,LAF,bands) = 25.000000 trans(PITT,LAF,coils) = 350.000000 trans(PITT,LAF,plate) = 250.000000

这也太清楚了吧,爱了,结果显示:从哪到哪送啥玩意。

#Variable solution 列出了每个变量的解释。#每行表示一条运输路径,格式为 trans(起始地点, 目的地点, 货物类型) = 数量。#例如,trans(GARY, STL, bands) = 400.000000 表示从GARY到STL运输bands类型的货物400个单位。

我们看结果知道,我们使用的是双对偶法。

那好我们今天到这里吧。

最近北太天元在和杉数科技合作:

杉数科技与北太振寰达成战略合作,携手推动国产科学计算与智能决策融合发展

北太天元和杉数科技达成合作之后会让智能决策和科学计算领域飞速发展,让我们关注他们并且支持:


支持国产,我们一起努力!!!

师苑数模
发布数模协会培训推文,讲解数模算法。赛题讲解及比赛通知。学校竞赛结果及学校竞赛成绩发布等文章。
 最新文章