Let me start by saying that I am an absolute beginner in Linear Programming and Python Gekko.
I was laying laminate in my friend's house and I thought it would be cool to write a program such that the laminate is laid in as optimal configuration as possible.
Below are the constraints for laying the laminate
- Each piece should be of minLaminateSize
- Each should overlap with its adjacent piece for a length of minOverlap
The optimal configuration would be
- Reusing the laminate as efficiently as possible by pairing the top piece with the bottom piece in any column
- Make as less cuts as possible. So ideal cut would be making a full laminate into two pieces and placing the top piece in one of the column and bottom piece in another column.
I was able to quickly write the below program in python Gekko. But i am going crazy as some of the constraints defined are breaking
from gekko import GEKKO
import numpy as np
from gekko.apm import get_file
#Initialize Model
m = GEKKO()
columnRange=10
#define parameter
height=[400,400,400,400,400,400,400,400,400,400]
laminateSize = 120
minOverlap = 40
minLaminateSize = 40
top = m.Array(m.Var,(columnRange))
bottom = m.Array(m.Var,(columnRange))
matchingSize = m.Array(m.Var,(columnRange))
numberOfCompleteLaminate = m.Array(m.Var,(columnRange))
x = m.Array(m.Var,(columnRange,columnRange))
#initialize variables
top=[m.Var(integer=False,lb=0, ub=laminateSize) for i in range(columnRange)]
bottom=[m.Var(120,integer=False,lb=0, ub=laminateSize) for i in range(columnRange)]
numberOfCompleteLaminate=[m.Var(integer=True,lb=0, ub=10) for i in range(columnRange)]
for i in range(columnRange):
x[i] = [m.Var(integer=True,lb=0, ub=1 ) for j in range(columnRange)]
for i in range(columnRange):
m.Equation(top[i]+bottom[i]+numberOfCompleteLaminate[i]*laminateSize == height[i])
m.Equation(top[i]>=minLaminateSize )
m.Equation(bottom[i]>=minLaminateSize )
for i in range(columnRange-1):
j=i+1
m.Equation( m.abs2(top[j] - top[i] ) >= minOverlap)
m.Equation( m.abs2(top[j] - top[i] ) <= laminateSize-minOverlap )
for i in range(columnRange):
m.Equation( sum( x[i,j] for j in range(columnRange) ) <= 1 )
m.Equation( sum( x[j,i] for j in range(columnRange) ) <= 1)
m.Maximize(m.sum(numberOfCompleteLaminate) )
for i in range(columnRange):
matchingSize[i]=0
for j in range(columnRange):
matchingSize[i]=matchingSize[i] + x[i][j] * (top[i] + bottom[j] )
m.Equation(matchingSize[i]<=laminateSize)
m.Maximize(matchingSize[i])
m.Maximize(m.sum(x))
#Set global options
m.options.SOLVER = 1
m.options.SCALING=1
m.options.IMODE = 3
m.solver_options = ['minlp_maximum_iterations 1500', \
# minlp iterations with integer solution
'minlp_max_iter_with_int_sol 10', \
# treat minlp as nlp
'minlp_as_nlp 0', \
# nlp sub-problem max iterations
'nlp_maximum_iterations 50', \
# 1 = depth first, 2 = breadth first
'minlp_branch_method 1', \
# maximum deviation from whole number
'minlp_integer_tol 0.1', \
# covergence tolerance
'minlp_gap_tol 0.01']
#Solve simulation
m.solve()
#Results
print(numberOfCompleteLaminate)
print(top)
print(bottom)
print(x)
The above program gives the below result
[[2.0], [2.0], [2.0], [2.0], [2.0], [2.0], [2.0], [2.0], [2.0], [2.0]]
[[40.0], [80.0], [120.0], [80.0], [40.0], [40.0], [80.0], [120.0], [80.0], [40.0]]
[[120.0], [80.0], [40.0], [80.0], [120.0], [120.0], [80.0], [40.0], [80.0], [120.0]]
Although an optimal result is found, i see that the constraint is not fulfilled. For eg: [40.0], [40.0] This combination should never exist as the overlap constrain would not be fulfilled. Defined by the below line of code
m.Equation( m.abs2(top[j] - top[i] ) >= minOverlap)
I have a couple of questions
- Am I on the right path, is there any settings that I have to change to solve the constraints.
- Is there a better way to write the program and solve it more efficiently
- Also i see that if the number of columns are more like 15 or 20 it is taking forever to solve the problem. Is there anything i can do to efficiently solve the problem. I am also okay with multithreading or running it on a powerful computer.
I badly need help, I am going crazy.