MicroCity NotesMicroCity Notes
Notes
  • MicroCity Web
  • MicroCity Desktop

    • 1. MicroCity Introduction
    • 2. Getting Started with MicroCity
    • 3. User Interface
    • 4. Script Writing
  • GitHub

    • MicroCity Desktop Repository
    • MicroCity Web Repository
    • MicroCity Web Online Environment
  • 简体中文
  • English
Notes
  • MicroCity Web
  • MicroCity Desktop

    • 1. MicroCity Introduction
    • 2. Getting Started with MicroCity
    • 3. User Interface
    • 4. Script Writing
  • GitHub

    • MicroCity Desktop Repository
    • MicroCity Web Repository
    • MicroCity Web Online Environment
  • 简体中文
  • English
  • Table of Contents
  • General Knowledge

    • Quick Start with Lua Language
    • Version Information of MicroCity
    • Advancement of Simulation Time
    • Object-Oriented Programming
    • Tools
  • MicroCity

    • Visualization of Results
    • Operating Networks
    • Model Solving
  • MicroCityWeb

    • User Interface Overview
    • 3D Scene
    • 3D Objects
    • Discrete Event Simulation and Program Control
    • Mixed integer programming
    • Debugging
  • Concepts

    • Ideas for Warehouse Automation Simulation
    • General Drawing Code
    • Port AGV Service Process 3D Simulation Approach

Mixed integer programming

Mixed-Integer Programming (MIP) is a powerful mathematical optimization technique used to solve problems where some of the decision variables are required to be integers. This article provides a step-by-step guide on creating and solving MIP models using Lua programming language in the context of MicroCity Web.

Translate info

This section is translated with assistance from ChatGPT, and the translation may not be accurate. If you have any questions, please leave remark below.

Creating a Mixed-Integer Programming Model

Creating an integer programming model object.

local mip = math.newmip() -- Assign the created model object to mip

Setting the Objective Function

In MicroCity Web, the first line of the model is the objective function, added using the mip:addrow() function.

You can choose to maximize or minimize the objective function. The usage is as follows:

Maximize
mip:addrow(coeff, 'max') -- Maximize the objective function
Minimize
mip:addrow(coeff, 'min') -- Minimize the objective function

Parameter Description and Examples

ParameterPurpose
mipMathematical model object. Sets the objective function for the model
coeffCoefficients of the objective function, a table variable. Determines the coefficients of the objective function in the model.
"min" or "max"Determines whether to minimize or maximize the objective function.

coeff is a list of coefficients for the objective function, a table variable. Suppose you want to minimize the function

4x1+12x2+18x34x_1+12x_2+18x_3 4x1​+12x2​+18x3​

the approach to adding the objective function is as follows:

-- Assuming you have already created the model object and stored it in the variable mip
-- Set the objective function to 4*x1 + 12*x2 + 18*x3, minimize
mip:addrow({4, 12, 18}, "min")

Adding Constraints

Adding Constraint Equations

In MicroCity Web, use mip:addrow() to add the remaining constraint equations. The usage is as follows:

≥
mip:addrow(cons, ">=", b)
=
mip:addrow(cons, "==", b)

Parameter Description

ParameterPurpose
mipThe integer programming model object created at the beginning
consCoefficients of the constraint equation. Like cons in setting the objective function, it's a table variable. Determines the coefficients of the variables in the constraint equation.
"<=" or ">=" or "=="Determines the relationship between the constraint equation and the right-hand side.
bThe right-hand side of the constraint equation.

Example

The objective function has been set to 4x1+12x2+18x34x_1+12x_2+18x_34x1​+12x2​+18x3​. Suppose you want to add two constraint equations for this function:

{x1+3x3≥32x2+2x3≥5\left\{\begin{matrix} x_1+3x_3\ge3 \\ 2x_2+2x_3\ge5 \end{matrix}\right. {x1​+3x3​≥32x2​+2x3​≥5​

Add the corresponding constraint equations:

-- Add constraint: x1 + 3*x3 ≥ 3
mip:addrow({ 1, 0, 3 }, ">=", 3)

-- Add constraint: 2*x2 + 2*x3 ≥ 5
mip:addrow({ 0, 2, 2 }, ">=", 5)

It can be noticed that the number of coefficients is the same as the number of variables in the objective function. Therefore, before programming, it is necessary to determine the total number of variables and arrange the positions of each variable.

Setting Variable Types

MicroCity's mathematical programming supports integer programming. The default variable range is non-negative real numbers (≥0). Below is a detailed method for setting variable types.

You can set the i-th variable in the model as an integer variable or a 0-1 variable. If you don't set the variable to these types, it defaults to a non-negative real number.

Integer Variable
-- Set the first variable (first column, col 1) as an integer variable
mip:addrow('c1', 'int')
0-1 Variable
-- Set the second variable (second column, col 2) as a 0-1 variable
mip:addrow('c2', 'bin')

Model Solution and Output

Model Solution

Since the objective function and constraint equations have been added, solving the model is straightforward:

mip:solve()

After executing this statement, the mathematical model stored in the variable mip is solved 🎉

Output

After solving, you still need to output; otherwise, you won't know the results. Below are some commonly used functions for outputting the solution.

Get the value of the objective function:

mip['obj']

Get the value of the i-th variable:

mip['c'..i]

Here is a simple example from modeling to solving for reference. (It's just putting the pieces together)

Example:

minf=4x1+12x2+18x3s.t.{x1+3x3≥32x2+2x3≥5x1,x2,x3∈Nminf=4x_1+12x_2+18x_3\\ s.t.\left\{\begin{matrix} x_1+3x_3\ge3 \\ 2x_2+2x_3\ge5 \\ x_1,x_2,x_3\in N \end{matrix}\right. minf=4x1​+12x2​+18x3​s.t.⎩⎨⎧​x1​+3x3​≥32x2​+2x3​≥5x1​,x2​,x3​∈N​

N represents the set of natural numbers (non-negative integers)

Script

local mip = math.newmip()

-- Set objective functio
mip:addrow({4, 12, 18}, "min") 

-- Add constraints
mip:addrow({ 1, 0, 3 }, ">=", 3) -- x1 + 3*x3 ≥ 3
mip:addrow({ 0, 2, 2 }, ">=", 5) -- 2*x2 + 2*x3 ≥ 5

-- Set all variables as integers
for i = 1, 3 do
    mip:addrow('c'..i, 'int')
end

-- Solve the model
mip:solve()

-- Output the value of the objective function
print("Objective function value:", mip['obj'])

-- Output the value of each variable
for i = 1, 3 do
    print("x"..i.."=",mip['c'..i])
end

Output

Objective function value: 42.0
x1= 0.0
x2= 2.0
x3= 1.0

Online Execution

Check this example in MicroCityWeb

Some Modeling Techniques

Linearization

Sometimes we encounter modeling problems with multiple subscripts, such as decision variables xijx_{ij}xij​, where iii and jjj are indices. In such cases, linearization encoding is necessary.

Suppose the decision variable itself has a shape of 3 rows and 4 columns, i.e.:

Col 1Col 2Col 3Col 4
x11x_{11}x11​x12x_{12}x12​x13x_{13}x13​x14x_{14}x14​
x21x_{21}x21​x22x_{22}x22​x23x_{23}x23​x24x_{24}x24​
x31x_{31}x31​x32x_{32}x32​x33x_{33}x33​x34x_{34}x34​

Suppose the objective function wants to sum these decision variables, i.e. F=∑i=13∑j=14xijF=\sum_{i=1}^3\sum_{j=1}^4x_{ij}F=∑i=13​∑j=14​xij​. If you want to input this into the objective function, you can linearize it as x11+x12+...+x14+x21+...+x24+x31+...+x34x_{11}+x_{12}+...+x_{14}+x_{21}+...+x_{24}+x_{31}+...+x_{34}x11​+x12​+...+x14​+x21​+...+x24​+x31​+...+x34​.

Since there are only two dimensions, you can use two for loops to achieve this:

local cons = {}
for i = 1, 3 do -- First dimension
    for j = 1, 4 do -- Second dimension
        cons[4 * (i - 1) + j] = 1 -- Fill in the coefficient
        -- The idea here is similar to carrying in arithmetic
    end
end

Example: Assignment Model

Now let's look at the specific usage of multi-dimensional linearization and its convenience using a practical example.

People A, B, C, and D deliver goods A, B, C, and D, respectively. The required time is shown in the table below. If each person delivers only one type of goods, which person should be assigned to deliver which type of goods to minimize the total time?

Person\ItemABCD
A149415
B117910
C132105
D1791513

Assuming goods A, B, C, D correspond to indices 1, 2, 3, 4, respectively, let xij=1x_{ij}=1xij​=1 represent person i delivering goods j, and xij=0x_{ij}=0xij​=0 represent person i not delivering goods j.

The mathematical model for the above problem can be represented as

minZ=∑i=14∑j=14cijxijs.t.{∑j=14xij=1,i=1,2,...,4∑i=14xij=1,j=1,2,...,4xij=0,1minZ=\sum_{i=1}^4\sum_{j=1}^4c_{ij}x_{ij}\\ s.t.\left\{\begin{matrix} \sum_{j=1}^4x_{ij}=1, i=1,2,...,4 \\ \sum_{i=1}^4x_{ij}=1, j=1,2,...,4 \\ x_{ij}=0,1 \end{matrix}\right. minZ=i=1∑4​j=1∑4​cij​xij​s.t.⎩⎨⎧​∑j=14​xij​=1,i=1,2,...,4∑i=14​xij​=1,j=1,2,...,4xij​=0,1​

Solution code

-- Efficiency matrix
local cost = {
    {14, 9, 4, 15},
    {11, 7, 9, 10},
    {13, 2, 10, 5},
    {17, 9, 15, 13}
}

local mip = math.newmip()

-- Create the objective function
local coeff = {}
for i = 1, 4 do
    for j = 1, 4 do
        -- Easily convert the 2D array to a 1D array here
        coeff[4 * (i - 1) + j] = cost[i][j]
    end
end

mip:addrow(coeff, "min")

-- Add constraints
for k = 1, 4 do -- Control the value of the first dimension
    local cons = {}
    for i = 1, 4 do
        for j = 1, 4 do
            if i == k then -- Sum for j, check i
                cons[4 * (i - 1) + j] = 1
            else
                cons[4 * (i - 1) + j] = 0
            end
        end
    end
    mip:addrow(cons, "==", 1)
end

for k = 1, 4 do -- Control the value of the second dimension
    local cons = {}
    for i = 1, 4 do
        for j = 1, 4 do
            if j == k then -- Sum for i, check j
                cons[4 * (i - 1) + j] = 1
            else
                cons[4 * (i - 1) + j] = 0
            end
        end
    end
    mip:addrow(cons, "==", 1)
end

-- Solve the model
mip:solve()

-- Output the value of the objective function
print("Objective function value:", mip['obj'])

-- Output the decision variables
for i = 1, 4 do -- First dimension
    for j = 1, 4 do -- Second dimension
        local x = mip['c' .. 4 * (i - 1) + j]
        if x ~= 0 then
            print("x[" .. i .. "][" .. j .. "]=", x)
        end
    end
end

Output

Objective function value: 29.0
x[1][3]= 1.0
x[2][1]= 1.0
x[3][4]= 1.0
x[4][2]= 1.0

Online Execution

Check this example in MicroCityWeb

ResultPersonItem
x13=1x_{13}=1x13​=1AC
x21=1x_{21}=1x21​=1BA
x34=1x_{34}=1x34​=1CD
x42=1x_{42}=1x42​=1DB

Handling Intermediate Variables

Sometimes, there are intermediate variables in a model that must have corresponding positions in the matrix to be solved, and these intermediate variables do not participate in the calculation of the objective function value. The coefficients of the intermediate variables at their corresponding positions can be set to 0.

Suppose x1,x2,x3,x4x_1, x_2, x_3, x_4x1​,x2​,x3​,x4​ are decision variables, and y1,y2y_1, y_2y1​,y2​ are intermediate variables. The objective function is:

z=∑i=14xiz=\sum_{i=1}^4x_i z=i=1∑4​xi​

The coefficients of the objective function can be set as follows:

local fcons = {1, 1, 1, 1, 0, 0}
-- The first 4 elements correspond to decision variables,
-- and the last 2 elements correspond to intermediate variables

Afterward, you can proceed with the general process 😎

Last Updated:
Contributors: huuhghhgyg
Prev
Discrete Event Simulation and Program Control
Next
Debugging