Call CPLEX from Python (DO cplex)

1.First of all

This is Qiita's first post. This article was recorded as a memorandum and may be incorrect.

The development environment provided by IBM ILOG as an optimization solution is called IBM ILOG CPLEX Optimization Studio. C / C ++ / Java / Python are examples of CPLEX development languages, and optimization problems can also be described using the OPL language using the Eclipse Plugin. CPLEX Studio's integrated development environment (IDE) basically allows you to solve optimization problems interactively with development using the OPL language, while solving multi-objective optimization problems and further different solutions obtained with CPLEX. It seems to be a little difficult to use in situations such as applying to the problem of. Therefore, this time, I will write an article with the meaning of recording the construction of the development environment by Python API as a memorandum. Here, there are two major CPLEX Python APIs, DOCplex [1] and Python-API (Legacy) [2], but it seems that the legacy version will be abolished in the not too distant future, so here we will use DOCplex. We will build the development environment used.

2. Operating environment

Operation check -Ubuntu 18.04 Bionic (64bit, 8GB, on VMWare) ・ CPLEX Optimization Studio 12.9 -Python 3.7.3 It was done at.

3. Installation procedure for CPLEX Studio 12.9

First, DL CPLEX Studio. Download .bin from site [3](assuming you put it in ~ / Downloads). Although it is a download method, it is omitted here because it can be easily downloaded by reading [3].

After downloading, let's start the installation. Let's go to ~ / Downloads and work on it.


$cd ~/Downloads

First, give execute permission to the .bin file.

$chmod +x CPLEX_OPT_STUD_129_LNX_X86-64.bin

Then run the .bin file.

$sudo ./CPLEX_OPT_STUD_129_LNX_X86-64.bin

In some language, the installer will launch and ask you some questions. It is summarized below. If you don't like it, just hit quit to stop.

  1. Local selection:-> 1. English or 2. Japanese
  2. It is recommended to quit all programs before installation:-> ENTER or back
  3. Specify installation path: / opt / ibm / ILOG / CPLEX_Studio129 is the default
  4. Press ENTER to install:-> ENTER
  5. Check disk capacity (about 2GB):-> ENTER
  6. Successful installation:-> ENTER

You need to go through some paths. CPLEX has two optimization engines, Mathematical Programming (MP) and Constraint Programming (CP), each with a different binary path. Open the shell configuration file (~ / .bashrc) and write the following export after the last line.

$echo "export LD_LIBRARY_PATH="/opt/ibm/ILOG/CPLEX_Studio129/opl/bin/x86-64_linux:$LD_LIBRARY_PATH"
$echo "export PATH="/opt/ibm/ILOG/CPLEX_Studio129/opl/bin/x86-64_linux:$PATH"
$echo "export PATH="/opt/ibm/ILOG/CPLEX_Studio129/cplex/bin/x86-64_linux:$PATH"
$echo "export PATH="/opt/ibm/ILOG/CPLEX_Studio129/cpoptimizer/bin/x86-64_linux:$PATH"

If you add it, I will reflect it.


$source ~/.bashrc

Now let's see if the command works.

$cplex
Welcome to IBM(R) ILOG(R) CPLEX(R) Interactive Optimizer 12.9.0.0
with Simplex, Mixed Integer & Barrier Optimizers
5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21
Copyright IBM Corp. 1988, 2019. All Rights Reserved.
Type 'help' for a list of available commands.
Type 'help' followed by a command name for more
information on commands.

Let's also start and check the constraint programming optimization engine.

$cpoptimizer
Welcome to IBM(R) ILOG(R) CP Interactive Optimizer 12.9.0.0
with Simplex, Mixed Integer & Barrier Optimizers
5724-Y48 5724-Y49 5724-Y54 5724-Y55 5724-A06 5724-A29
Copyright IBM Corp. 1990, 2019. All Rights Reserved.

Type 'help' for a list of available commands.
Type 'help' followed by a command name for more
information on commands.

Also, if the path passes, the following command should also pass. If the contents of help are displayed in a sloppy manner, the path is passing without any problem.

$oplrun

[If command not found is displayed and it does not start properly] It seems that the LD_LIBRARY_PATH setting may not be reflected (is it OS-dependent? ..?). You can work around this by registering the path in the shared library (I don't know much about this ...). It seems to be okay if you create a file called hogehoge.conf under /etc/ld.so.conf.d and add LD_LIBRARY_PATH.


$sudo vim /etc/ld.so.conf.d/oplrun.conf

I will write the following inside.

/opt/ibm/ILOG/CPLEX_Studio129/opl/bin/x86-64_linux/
/opt/ibm/ILOG/CPLEX_Studio129/cplex/bin/x86-64_linux/
/opt/ibm/ILOG/CPLEX_Studio129/cpoptimizer/bin/x86-64_linux/

Save the file and rebuild the cache.

$sudo ldconfig

4. DOCplex setup

In this article, I have installed CPLEX in / opt / ibm / ILOG / CPLEX_Studio129 / ... Hereafter, / opt / ibm / ILOG / CPLEX_129 will be placed as (CPLEX_DIR). If you set any path yourself, CPLEX_DIR should be a different path. be careful.

Go to (CPLEX_DIR) / python / docplex / and you will find a file called setup.py, run it.

$cd (CPLEX_DIR)/python/docplex
$sudo python3 setup.py install

Setup will start and finish within seconds. This completes the DOCplex environment construction.

5. Solve the example

From here, I will briefly touch on how to write using the official reference sample [4]. Since I am studying myself, there are some uncertainties, but I would be grateful if I could contribute in any way.

Here, I will take up the first example of [4], The Transportation Problem.

example-qiita1.png

This is a problem that minimizes the cost of transporting goods located at two locations to three locations. The figure is a Directed Acyclic Graph (DAG) with non-negative integer weights. The Out-going node on the left shows the locations where supplies can be carried out. In addition, the number written in red is the weight of each node and indicates the total amount of goods that can be transported. The number in green next to the In-coming node on the right is the total amount of supplies required by the site. The arc between the nodes indicates the transportable route, and the weight on the arc indicates the transportation cost per material.

There are several combinations for calculating transportation costs in this problem. Since this is a simple example, the optimal solution can be easily found as follows.

Node 3 can only receive supplies from node 1 and requires 7 supplies. Therefore, since only the material 15 of the node 1 is sent to the node 3, the remaining amount of the node 1 is 8, and at this time, the material 7 is sent to the node 3 at the transportation cost 2, so the transportation cost of 2 × 7 = 14 is required. To do.

Similarly, since node 4 can only receive supplies from node 2, the amount of leftovers in node 2 is 20-10 = 10, and the transportation cost at this time is 10 x 5 = 50, so the amount of leftovers in node 1 is 8. , Node 2 has 10 leftovers, and Node 5 needs 15 supplies. At this time, since the transportation cost from node 2 to node 5 is low, if we decide to preferentially carry supplies from node 2, node 2 will carry all 10 and the remaining amount will be 0, while node 5 will need 5 supplies. I will. Finally, all requirements can be met by sending only 5 supplies from node 1 to node 5. In the process here, node 2 carries 10 at transportation cost 3, so 10 × 3 = 30 transportation cost, and node 1 carries only 5 at transportation cost 4, so 5 × 4 = 20 transportation cost is required.

From the above, the final transportation cost is only 14 + 50 + 30 + 20 = 114.

In order to establish this problem as an optimization problem, it is necessary to organize the objective function and constraints, and define the decision variables.

Based on the above, it seems good to set the coefficient of determination to the following.

I will write the program below.

sample.py


 #URL/You can solve the problem in the cloud by writing the Key.
 #Since local execution is assumed here, it is set to None.
url=None
key=None

 #Preparation of data
 #Node 1 is 15,Node 2 has only 20 supplies
capacities = {1:15, 2:20} 
 #Node 3 is 7,Node 4 is 10,Node 5 has 15 requests
demands = {3:7, 4:10, 5:15}
 #At this time, the cost in the arc is(1,3)=2, (1,5)=4, (2,4)=5, (2,5)=Because it is 3
costs = {(1,3):2, (1,5):4, (2,4):5, (2,5):3}
source = range(1,3) #range in python(i,j)Is i...j-Up to 1
target  = range(3,6)

 #description of a problem
 #Import docplex
from docplex.mp.model import Model
tm = Model(name='transportation')

 #decision (continuous) variable 
 #Variable x(i,j)Is defined in the problem tm. x is a continuous variable, i refers to source, and j refers to target. However, this exists in costs(Those who are connected to the arc)Only in cases.
x = {(i,j): tm.continuous_var(name='x_{0}_{1}'.format(i,j)) for i in source for j in target if (i,j) in costs}
tm.print_information()

 #add constraints
 # (1,3), (1,5)The total amount of supplies that carry[1]  (=15)Do not exceed
 # (2,4), (2,5)The total amount of supplies that carry[2]  (=20)Do not exceed
for i in source:
    tm.add_constraint(tm.sum(x[i,j] for j in target if (i,j) in costs) <= capacities[i] )
for j in target:
    tm.add_constraint(tm.sum(x[i,j] for i in source if (i,j) in costs) >= demands[j] )

 #Objective function
 #Objective function is arc(i,j)Minimize the total amount of transportation costs in between
tm.minimize(tm.sum(x[i,j]*costs[i,j] for i in source for j in target if (i,j) in costs))

 #Solve
 #Solve the problem
tms = tm.solve(url=url,key=key)

 #Display and exceptions
 #Show solution
assert tms
tms.display()

When run, you get:


Model: transportation
 - number of variables: 4
   - binary=0, integer=0, continuous=4
 - number of constraints: 0
   - linear=0
 - parameters: defaults
solution for: transportation
objective: 114.000
x_1_3 = 7.000
x_1_5 = 5.000
x_2_4 = 10.000
x_2_5 = 10.000

This is the end of the introduction of DOCplex (Python-API).

Reference link

1: DOCplex Official Reference 2: Python-API(Legacy) 3: CPLEX Download 4: DOCplex Official Reference-Example

Recommended Posts

Call CPLEX from Python (DO cplex)
Call Matlab from Python to optimize
Call a Python function from p5.js.
Call C from Python with DragonFFI
Call popcount from Ruby / Python / C #
Call python from nim with Nimpy
Call C / C ++ from Python on Mac
Call c language from python (python.h)
sql from python
MeCab from Python
Call a command from Python (Windows version)
Call Python library for text normalization from MATLAB
Call a Python script from Embedded Python in C ++ / C ++
Call Polly from the AWS SDK for Python
An easy way to call Java from Python
Use thingsspeak from python
Touch MySQL from Python 3
Operate Filemaker from Python
Use fluentd from python
Access bitcoind from python
Changes from Python 3.0 to Python 3.5
Changes from Python 2 to Python 3.0
Python from or import
Use MySQL from Python
Run python from excel
Install python from source
Execute command from Python
Operate neutron from Python!
Use MySQL from Python
Operate LXC from Python
Do Houdini with Python3! !! !!
Manipulate riak from python
Force Python from Fortran
Use BigQuery from python.
Execute command from python
[Python] Read From Stdin
Use mecab-ipadic-neologd from python
Call your own python module from the ROS package
[Python] How to call a c function from python (ctypes)
Call C language functions from Python to exchange multidimensional arrays
Deep Python learned from DEAP
Do Django with CodeStar (Python3.6.8, Django2.2.9)
Post from Python to Slack
Grammar features added from Python3.6
Cheating from PHP to Python
Make MeCab available from Python3
Do Django with CodeStar (Python3.8, Django2.1.15)
Information obtained from tweet_id (Python)
OCR from PDF in Python
Run illustrator script from python
Use MySQL from Anaconda (python)
Anaconda updated from 4.2.0 to 4.3.0 (python3.5 updated to python3.6)
Study from Python Hour4: Object-oriented ②
Query Athena from Lambda Python
Access Oracle DB from Python
Study from Python Hour3: Functions
Start / stop GCE from python
Stop Omxplayer from Python code
Switch from python2.7 to python3.6 (centos7)
Connect to sqlite from python
Install pyenv from Homebrew, install Python from pyenv