在docker容器中使用cplex-python37

2023-11-06 03:20

本文主要是介绍在docker容器中使用cplex-python37,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

技术背景

线性规划是常见的问题求解形式,可以直接跟实际问题进行对接,包括目标函数的建模和各种约束条件的限制等,最后对参数进行各种变更,以找到满足约束条件情况下可以达到的最优解。Cplex是一个由IBM主推的线性规划求解器,可以通过调用cplex的接口,直接对规定形式的线性规划的配置文件.lp文件进行求解。这里我们介绍一下,基于docker来调用cplex的python接口,对线性规划问题进行求解。

基于Docker部署Cplex环境

由于cplex依赖于python3.7版本,而我们本地使用的python版本是python3.8,因此我们考虑使用docker容器来制作一个python37+cplex的容器镜像,用于计算线性规划的问题。关于docker容器的使用,在另外3篇博客(博客1,博客2,博客3)。首先我们在dockerhub上面找一个python37的镜像:


这里我们习惯性的选择星星最高的那个,然后下载到本地:
[dechin-root cplex]# docker pull rackspacedot/python37
Using default tag: latest
latest: Pulling from rackspacedot/python37
Digest: sha256:5ae238bd5d6b06af739ac1b2666111955966d563cb6aea8b366fb446425eb299
Status: Downloaded newer image for rackspacedot/python37:latest
docker.io/rackspacedot/python37:latest

下载完成后,可以在本地的镜像仓库中看到这个新的镜像:

[dechin-root cplex]# docker images
REPOSITORY                                                 TAG       IMAGE ID       CREATED          SIZE
rackspacedot/python37                                      latest    ab7083b6c7c4   3 months ago     1.02GB

下载完成后我们可以进入这个镜像,用pip安装一个最新的cplex。其实cplex的安装还是非常简单的,只是对于python的版本有要求而已。

[dechin-root cplex]# docker run -it rackspacedot/python37 /bin/bash
root@c766ed62d149:/# python3 -m pip install cplex
Collecting cplexDownloading cplex-20.1.0.1-cp37-cp37m-manylinux1_x86_64.whl (30.9 MB)|████████████████████████████████| 30.9 MB 347 kB/s 
Installing collected packages: cplex
Successfully installed cplex-20.1.0.1

安装完成后,我们可以进入python3的命令行界面,测试一下cplex的安装情况:

root@c766ed62d149:/# python3
Python 3.7.9 (default, Nov 18 2020, 14:29:12) 
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cplex
>>> exit()

这里如果没有报错,就表示安装成功了。那么最后,我们需要把刚才对容器镜像的修改永久的保留下来,我们先用ps查看刚才的修改被保存到哪里:

[dechin-root cplex]# docker ps -n 2
CONTAINER ID   IMAGE                   COMMAND       CREATED          STATUS                     PORTS     NAMES
c766ed62d149   rackspacedot/python37   "/bin/bash"   2 minutes ago    Exited (0) 6 seconds ago             xenodochial_ardinghelli
af037db88540   cplex                   "/bin/bash"   48 minutes ago   Up 48 minutes                        magical_cori

在过去的2条记录中我们发现对容器镜像的修改被保存到c766开头的容器中,这时我们可以直接对这个编号的容器进行提交保存:

[dechin-root cplex]# docker commit c766 cplex-py37
sha256:34e2729697010b1320c2f7dbfd1fc45004e9ffae6a1d26ffb8748b5627cb2224

如果出现以上的反馈,就表示我们成功的把刚才下载cplex的这一修改永久的保存进cplex-py37这个新容器中,这样就可以在本地的容器仓库里面看到这个新的容器:

[dechin-root cplex]# docker images
REPOSITORY                                                 TAG       IMAGE ID       CREATED              SIZE
cplex-py37                                                 latest    34e272969701   About a minute ago   1.15GB

到这里,我们使用docker部署的cplex求解器的环境就已经完成了,下一步我们用真实的线性规划的问题来进行测试。

线性规划问题求解

上面的章节主要是为了展示基于docker的cplex环境部署,用同样的方法我们此前已经制作好了一个名为cplex的容器镜像,这里我们直接用来测试。容器的拉起方法,要绑定本地存放有线性规划问题定义的文件所在的目录:

[dechin-root cplex]# docker run -it -v /home/dechin/projects/2021-quantum/cplex/:/home/ cplex /bin/bash

线性规划问题定义

Cplex可以识别lp格式的文件,这里我们展示一个测试用例来说明这个线性规划的问题是如何定义的:

[dechin-root cplex]# cat test.lp 
Maximizeobj: 2 x1 + 3 x2 + 4 x3
Subject Toc1: 3 x1 + 4 x2 + 5 x3 <= 8
Bounds0 <= x1 <= 10 <= x2 <= 10 <= x3 <= 1
Binaryx1 x2 x3
End

在这个问题中,我们的目标是优化这样的一个函数:

\[max\{2x_1+3x_2+4x_3\} \]

就是找这么一个函数的最大值,这些参数\(x_1,x_2,x_3\)都是二元变量,即\(x\in\{0,1\}\),而且需要满足给定的约束条件:

\[3x_1+4x_2+5x_3\leq8 \]

问题解析与代码求解

其实这是一个典型的单背包问题的案例:给定一个承重量为8的背包,需要装3个物品\(\{x_1,x_2,x_3\}\)中的某几个拿去卖。这三个物品的重量分别是\(\{3,4,5\}\),因此我们没办法将所有的物品一次性装到包里面,因为这会超过背包的承重量。而这3个物品的收益分别是\(\{2,3,4\}\),对于这个问题来说,就是要最大化这个收益。比如说,我们只装\(x_1,x_2\)两个物品,也就是\(x_1=1,x_2=1,x_3=0\),那么总重量是7,并没有超过背包的承重量,而总的收益是5。这是一组可行解,但不一定是最优解,接下来我们看看cplex是否有可能找到这个问题的最优解。

root@af037db88540:/home# python3
Python 3.7.9 (default, Nov 18 2020, 14:29:12) 
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cplex
>>> lp = cplex.Cplex() # 初始化对象
>>> lp.read('test.lp') # 读取线性规划文件
>>> lp.solve() # 求解
Version identifier: 12.10.0.0 | 2019-11-27 | 843d4de
CPXPARAM_Read_DataCheck                          1
Found incumbent of value 0.000000 after 0.00 sec. (0.00 ticks)
Tried aggregator 1 time.
MIP Presolve eliminated 1 rows and 3 columns.
MIP Presolve modified 3 coefficients.
All rows and columns eliminated.
Presolve time = 0.00 sec. (0.00 ticks)Root node processing (before b&c):Real time             =    0.00 sec. (0.00 ticks)
Parallel b&c, 8 threads:Real time             =    0.00 sec. (0.00 ticks)Sync time (average)   =    0.00 sec.Wait time (average)   =    0.00 sec.------------
Total (root+branch&cut) =    0.00 sec. (0.00 ticks)
>>> lp.solution.get_objective_value() # 获取求解的目标函数值
6.0
>>> lp.solution.get_values() # 获取最终的参数值
[1.0, 0.0, 1.0]

这个示例中我们将每一步的含义都直接注释在代码中,我们直接调用cplex的接口,写好lp文件,就可以很轻松的进行求解了。得到的最终的解是\(\{1,0,1\}\),也就是总重量为8,未超过承重量,而总收益为6,高于我们刚才手工找到的可行解的收益值。同时这也是这个问题的唯一最优解,这一点其实我们可以手工验证。

总结概要

在这篇文章中我们介绍了如何使用docker去搭建一个cplex线性规划求解器的编程环境,制作完docker容器,我们也展示了如何写一个线性规划问题定义的文件,并使用cplex对给定一个背包问题的线性规划(实际上是一个二元规划问题)文件进行求解。

版权声明

本文首发链接为:https://www.cnblogs.com/dechinphy/p/cplex.html
作者ID:DechinPhy
更多原著文章请参考:https://www.cnblogs.com/dechinphy/

参考链接

  1. https://blog.csdn.net/qq_33670304/article/details/102882863

这篇关于在docker容器中使用cplex-python37的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/354178

相关文章

vue使用docxtemplater导出word

《vue使用docxtemplater导出word》docxtemplater是一种邮件合并工具,以编程方式使用并处理条件、循环,并且可以扩展以插入任何内容,下面我们来看看如何使用docxtempl... 目录docxtemplatervue使用docxtemplater导出word安装常用语法 封装导出方

Linux换行符的使用方法详解

《Linux换行符的使用方法详解》本文介绍了Linux中常用的换行符LF及其在文件中的表示,展示了如何使用sed命令替换换行符,并列举了与换行符处理相关的Linux命令,通过代码讲解的非常详细,需要的... 目录简介检测文件中的换行符使用 cat -A 查看换行符使用 od -c 检查字符换行符格式转换将

使用Jackson进行JSON生成与解析的新手指南

《使用Jackson进行JSON生成与解析的新手指南》这篇文章主要为大家详细介绍了如何使用Jackson进行JSON生成与解析处理,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 核心依赖2. 基础用法2.1 对象转 jsON(序列化)2.2 JSON 转对象(反序列化)3.

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

Elasticsearch 在 Java 中的使用教程

《Elasticsearch在Java中的使用教程》Elasticsearch是一个分布式搜索和分析引擎,基于ApacheLucene构建,能够实现实时数据的存储、搜索、和分析,它广泛应用于全文... 目录1. Elasticsearch 简介2. 环境准备2.1 安装 Elasticsearch2.2 J

使用C#代码在PDF文档中添加、删除和替换图片

《使用C#代码在PDF文档中添加、删除和替换图片》在当今数字化文档处理场景中,动态操作PDF文档中的图像已成为企业级应用开发的核心需求之一,本文将介绍如何在.NET平台使用C#代码在PDF文档中添加、... 目录引言用C#添加图片到PDF文档用C#删除PDF文档中的图片用C#替换PDF文档中的图片引言在当

Java中List的contains()方法的使用小结

《Java中List的contains()方法的使用小结》List的contains()方法用于检查列表中是否包含指定的元素,借助equals()方法进行判断,下面就来介绍Java中List的c... 目录详细展开1. 方法签名2. 工作原理3. 使用示例4. 注意事项总结结论:List 的 contain

C#使用SQLite进行大数据量高效处理的代码示例

《C#使用SQLite进行大数据量高效处理的代码示例》在软件开发中,高效处理大数据量是一个常见且具有挑战性的任务,SQLite因其零配置、嵌入式、跨平台的特性,成为许多开发者的首选数据库,本文将深入探... 目录前言准备工作数据实体核心技术批量插入:从乌龟到猎豹的蜕变分页查询:加载百万数据异步处理:拒绝界面

Android中Dialog的使用详解

《Android中Dialog的使用详解》Dialog(对话框)是Android中常用的UI组件,用于临时显示重要信息或获取用户输入,本文给大家介绍Android中Dialog的使用,感兴趣的朋友一起... 目录android中Dialog的使用详解1. 基本Dialog类型1.1 AlertDialog(

Python使用自带的base64库进行base64编码和解码

《Python使用自带的base64库进行base64编码和解码》在Python中,处理数据的编码和解码是数据传输和存储中非常普遍的需求,其中,Base64是一种常用的编码方案,本文我将详细介绍如何使... 目录引言使用python的base64库进行编码和解码编码函数解码函数Base64编码的应用场景注意