Closed aichao closed 2 years ago
Hi Alan,
can you please provide us with your code or with a file of your problem e.g. in lp
or mps
format?
Best wishes, Jurgen
Hi Jurgen,
Thank you for the quick reply. Attached is my model in .mps
format:
The python code that generated this model is:
def create_joint_optimization_model(problem: OptimizationProblem) -> pygcgopt.Model:
""" Create a GCG optimization model from the OptimizationProblem
Create a GCG Model from the mathematical program:
minimize f'x
where Ax <= b
lb <= x <= ub
The decision variable `x` may be a mixture of "Integer", "Continuous", and "Binary" variables
:param problem: OptimizationProblem
The optimization problem.
:return: Model
The GCG Model
"""
model = pygcgopt.Model("Joint Optimization")
a_indptr = np.frombuffer(problem.a_indptr, dtype=np.int32)
a_indices = np.frombuffer(problem.a_indices, dtype=np.int32)
a_data = np.frombuffer(problem.a_data, dtype=float)
start_i = 0
start_col = 0
x = []
for p in problem.portfolio:
nx = len(p.lots_ms) + len(p.lots_h)
f = np.frombuffer(p.f, dtype=float)
lb = np.frombuffer(p.lb, dtype=float)
ub = np.frombuffer(p.ub, dtype=float)
x_core = [model.addVar(vtype='I', name=('p' + p.id + '_x_core' + str(i)), lb=lb[i], ub=ub[i], obj=f[i])
for i in range(nx)]
nx_ne = nx + p.ne
x_dist = [model.addVar(vtype='C', name=('p' + p.id + '_x_dist' + str(i - nx)), lb=0., ub=model.infinity(),
obj=f[i])
for i in range(nx, nx_ne)]
nx_ne_ns = nx_ne + p.n_slack
x_slack = [model.addVar(vtype='C', name=('p' + p.id + '_x_slack' + str(i - nx_ne)), lb=0., ub=model.infinity(),
obj=f[i])
for i in range(nx_ne, nx_ne_ns)]
x_bin = [model.addVar(vtype='B', name=('p' + p.id + '_x_ind' + str(i - nx_ne_ns)), lb=0, ub=1, obj=0.)
for i in range(nx_ne_ns, p.n)]
x.extend(x_core + x_dist + x_slack + x_bin)
# <= constraints
b = np.frombuffer(p.b, dtype=float)
for i in range(start_i, start_i + p.nc):
start = a_indptr[i]
end = a_indptr[i + 1]
coeffs = a_data[start:end]
model.addCons(pygcgopt.quicksum(
coeff_j * x[j] for coeff_j, j in zip(coeffs, a_indices[start:end])) <= b[i - start_i])
start_i += p.nc
start_col += p.n
# if joint problem, extend the decision variables to the link variables and add the complicating constraints
if problem.HasField("b_joint"):
x.extend([model.addVar(vtype='B', name=('joint_l_ind' + str(i)), lb=0, ub=1, obj=0.)
for i in range(2 * problem.n_joint_lots)])
x.extend([model.addVar(vtype='B', name=('joint_c_ind' + str(i)), lb=0, ub=1, obj=0.)
for i in range(problem.n_joint_cusips)])
b_joint = np.frombuffer(problem.b_joint, dtype=float)
for i, b_j in enumerate(b_joint):
start = a_indptr[start_i + i]
end = a_indptr[start_i + i + 1]
coeffs = a_data[start:end]
model.addCons(pygcgopt.quicksum(coeff_j * x[j] for coeff_j, j in zip(coeffs, a_indices[start:end])) <= b_j)
model.data = x
model.setMinimize()
model.writeProblem('joint_model.mps')
return model
Here, OptimizationProblem
is a protobuf message containing the f
, b
, lb
, ub
vectors as NumPy arrays and the A
matrix as a scipy CSR matrix. Each "portfolio"
in the OptimizationProblem
contains a sub-problem, and the A
matrix has the familiar block diagonal structure of sub-problems with complicating constraints at the bottom. There should be 20 such sub-problems in the attached model.
When I said earlier that the same model generated using PySCIPOpt runs fine, I mean that the above code with pyscipopt
instead of pygcgopt
generates a model that runs. Maybe that is a bad assumption that I can just substitute pyscipopt
with pygcgopt
?
Thanks again to you and the team for providing GCG and and now PyGCGOpt to the world!
With Best Regards, Alan
Hi Alan,
one way how to solve this issue in PyGCGOpt
is to detect without presolving. Therefore, you only need to call the function detect()
before you optimize.
Here, you already know the block diagonal structure of your problem because of that I additionally suggest to you to specify it manually using pygcgopt
, if GCG
does not already identify it as the best decomposition. For more information about manually specifying a decomposition, I refer to our example in the documentation.
Yes, your assumption is right. The Model
class of pygcgopt
does contain all the methods of the Model
class of pyscipopt
because it inherits from it.
Best wishes, Jurgen
Hi Jurgen,
Thank you for the solution. Detecting without presolving works and makes sense. I will also look at your example for manually specifying the decomposition. I am closing this issue now.
Best wishes, Alan
Hi All,
First, I want to thank you guys for putting together a python wrapper to GCG. However, after installing SCIP Optimization Suite 8.0.0 with GCG 3.5.0 and PyGCGOpt 0.1.4, I get a segmentation fault optimizing my MIP model, see log below. The same model, encoded as a SCIP model using PySCIPOpt, runs fine. I know that this is not a lot of information to go by, but I was wondering if you can offer some advice as to how to debug.
Best, Alan