当前位置: 首页 > article >正文

Gurobi基础语法之字典

Python中的字典:dict

        我们先来介绍一下Python语法中的 dict 类型, 字典中可以通过任意键值对数据进行映射,任何无法修改的python对象都可以当作键值来使用,这些无法修改的Python对象包括:整数(比如:1),浮点数(比如:1.1),字符串(比如:"uyt"),元组。

        下面分别用整数和元组作为键值创建 dict 类型的变量

用整数作为键值创建 dict 类型的变量

int_dict = {1: 'one', 2: 'two', 3: 'three'}
print(int_dict)  # {1: 'one', 2: 'two', 3: 'three'}
print(int_dict[1])  # one

用元组作为键值创建 dict 类型的变量(此tuple_dict 非后面讲的 tupledict

tuple_dict = {('a', 1): 'a_one', ('b', 2): 'b_two', ('c', 3): 'c_three'}
print(tuple_dict)  # {('a', 1): 'a_one', ('b', 2): 'b_two', ('c', 3): 'c_three'}
print(tuple_dict[('b', 2)])  # b_two

值得注意的是:

通过元组访问字典时可以省略圆括号,因此以下语句同样也是同样有效的:
print(tuple_dict['b', 2])  # b_two

        无论是python中的dict, 还是C++中的unordered_map,都是在用键值就能找到value,从功能上来讲,就可以把他们之中的键值当作一个下标来理解

        既然都有了dict,为什么Gurobi之中还创建了很多诸如multidict,  tupledict这样的东西?

Gurobi中的multidict

        首先,multidict 只是一个函数,往这个函数中传入一个 dict 字典,其中的每个键值对由键和一个列表构成,那么经过multidict处理之后将会很方便的得到多个字典,下面举个例子来说明将一个dict 分解成多个新的字典的过程,

keys, dict1, dict2 = gp.multidict( {
'key1': [1, 2],
'key2': [1, 3],
'key3': [1, 4] } )

这就将{ key1': [1, 2], key2': [1, 3], key3': [1, 4] } 这个字典分成了三个部分:

keys: 作为一个gurobi中专有的 tuplelist 类型的变量,实际上是['key1', 'key2', 'key3']

dict1: 作为一个gurobi中专有的 tupledict 类型的变量,实际上是{'key1': 1, 'key2': 1, 'key3': 1}

dict2: 作为一个gurobi中专有的 tupledict 类型的变量,实际上是{'key1': 2, 'key2': 3, 'key3': 4}

 那么multidict这个函数的作用就显而易见了:

在建模过程中,有可能遇到如下场景:有多个决策变量,每个决策变量都有上下界,那么这些决策变量可以用multidict快速的将一个决策变量和上下界都建立字典关系,比如对于上面的dict1 和 dict2来说,key1的上下界是1, 2,key2的上下界是1, 3,key3的上下界是1, 4

Gurobi 中的 tupledict 和 tuplelist

tupledict

对于tupledict来说,实际上这是一个dict容器类的一个子类,在文章一开头就已经用dict定义了一个名为tuple_dict的变量,当时就说 此 tuple_dict 非后面讲的 tupledict,这体现在如下几点:

tupledict 的定义:在gurobi中,用一个  tuple 作为字典中的key,如果字典中有多个键值对,则 这些 key(即元组)的长度都必须相同

tupledict 提供了 sum 和 prod 方法,可以方便地创建线性表达式,这些表达式可以直接用于构建模型的约束和目标函数。

tupledict 这个子类提供的新方法是 sum 和 prod,

gurobi中对tupledict对象调用 sum 方法

以如下代码为例:

m = Model()
x = m.addVars(2, 3) 
expr1 = x.sum()  # 创建一个包含所有变量的和的线性表达式
expr2 = x.sum(1, '*') 
expr3 = x.sum('*', 1)

n = Model()
y = n.addVars(10, 10) 
expr4 = y.sum(range(1, 6), 1)

代码运行结果

对上面这段代码的解释:首先 x 调用 gurobi 中的 addVars 这个方法,能够获得一个 tupledict类型的对象,这个对象实际上是一个以两个下标组成的元组作为 tuplelist 的key,此时相当于创建了一个2行3列的变量矩阵,变量的下标从(1,1)到(2,3)

上图表明了x 这个变量矩阵的的是按照 tuplelist 的存储结构进行存储的,调用sum方法就是把这个变量矩阵中的每一个变量都相加,也就是说,创建了一个包含所有变量的和的线性表达式。具体来说,它将所有变量x11, x12, x13, x21, x22, x23相加。用数学公式表示为:

expr1 = x11 ​+ x12 ​+ x13 ​+ x21 ​+ x22​ + x23​

对于expr2 = x.sum(1, '*')   创建了一个包含第一行所有变量的和的线性表达式。具体来说,它将第一行的变量x11, x12, x13相加。用数学公式表示为: expr2 = x11​ + x12 ​+ x13​    

而expr3将第一列的变量x11, x21相加。用数学公式表示为:expr3 = x11 + x21

对于expr4来说,其获得了y这个变量矩阵的第一列的前 5 个变量线性表达式。用数学公式表示为:expr4 = y11 + y21 + y31 + y41 + y51

gurobi中对tupledict对象调用 prod 方法

下面用几个例子来说明这个方法:

例1:tupledict可以和dict类型的变量通过 prod 方法进行相乘

m = gp.Model()
x = m.addVars(2, 2)
coef = { (0, 0) : 0.3, (0, 1) : 0.5, (1, 0) : 0.1, (1, 1) : 0.7 }
# coef = { (0, 0) : 0.3, (0, 1) : 0.5, (1, 0) : 0.1} # 得到 0.3x11 + 0.5x12 + 0.1x21
# coef = { (1, 1) : 0.3, (1, 2) : 0.5, (2, 1) : 0.1} # 得到 0.3x22
expr = x.prod(coef)
print(expr)

值得注意的是,在coef中只有与(0, 0),(0, 1),(1, 0),(1, 1) 这四个元组匹配的键值对才会参与prod,prod之后的结果只有coef的第一个键值对

练习:阿山想要知道应该怎么学习什么技能才能成为一个运筹优化算法的专家,现在已知有三种技能是成为专家的必学技能,分别是python以及gurobi的编程技能,调研建模对象相关背景的能力,算法性能的测试技能,现在阿山要分配合理的时间,在尽可能短的时间内获得更高的技术水平,请你编写一段程序表达这个问题的目标函数

提示:既然 dict 都可以和 tupledict 使用 prod,那么tupledict 是否可以和 tupledict 相乘?

~

~

~

skill, time = multidict({
    'coding' : 4,
    'business' : 4,
    'test' : 1
})

m = gp.Model()
x = m.addVars(skill, name = 's')
expr = x.prod(time)
m.setObjective(expr, GRB.MINIMIZE)

注意:这里添加变量和 相乘都可以用其他的方法替代,具体可以看我的另外一篇博客

tuplelist

tuplelist 的定义:在gurobi中,用一个  tuple 作为列表中的元素,如果列表中有多个元素,则这些 元素(即元组)的长度都必须相同

 tuplelist 提供了select函数,由于 列表中的元组长度一致,所以可以理解成一个矩阵,那么select方法就可以通过指定对应位置处的元素取值,以下面这个例子为例:

Cities= [('A','B','C','D'), ('A','C','D','E'), ('B','C','B','C'),('B','D','B','C'),('C','A','B','C')]
Routes = tuplelist(Cities)
print(Routes.select('A','*'))
print(Routes.select('*','C', 'B'))

 将会打印出,

select方法的返回值会自动打印 tuplelist 的行列数,


http://www.kler.cn/a/518830.html

相关文章:

  • 第二十一周:Mask R-CNN
  • MySQL数据库笔记——版本号机制和CAS(Compare And Swap)
  • 攻防世界bad_python
  • 开发环境搭建-3:配置 nodejs 开发环境 (fnm+ node + pnpm)
  • 跟我学C++中级篇——容器的连接
  • 基于模糊PID的孵化箱温度控制系统(论文+源码)
  • Leecode刷题C语言之找到最接近0的数字
  • 网络安全 | F5-Attack Signatures详解
  • mysql-04.索引
  • 2_高并发内存池_各层级的框架设计及ThreadCache(线程缓存)申请内存设计
  • 数据可视化的图表
  • 找不到mfc140u,具体原因分析
  • Ubuntu20.04 深度学习环境配置(持续完善)
  • RA-Eco-RA2L1-48PIN-V1.0开发板前期准备避坑指南
  • Apache Doris 2.1.8 版本正式发布
  • 51单片机——串口向电脑发送数据
  • RDMA 工作原理 | 支持 RDMA 的网络协议
  • C语言教程——文件处理(2)
  • 神经网络|(四)概率论基础知识-古典概型
  • MaxCompute—阿里云原生大数据计算机服务——SQL概述与服务支持
  • linux-execve的使用
  • C# 利用ssh 开启一个命令交互窗口
  • 微信小程序部分用户报错ERR_CONNECTION_REFUSED连接被拒绝
  • 海外问卷调查如何影响企业的经营?在品牌建设中有何指导意义?
  • 【PyTorch】3.张量类型转换
  • 使用JavaScript实现猜数字小功能