Issues with Reading an Optimization Model from MPS Files and and Solving Using or-tools

333 Views Asked by At

I can successfully read the MPS file and solve it using Gurobi, which confirms the feasibility of the problem. But I'm striving to utilize or-tools, particularly the "PDLP" solver for specific reasons, and I'm encountering an infeasibility error from or-tools. Here's my approach:

from ortools.linear_solver import pywraplp
import gurobipy as gp
from collections import defaultdict

file_path = "237794.mps"



def parse_mps_updated(file_path):
    with open(file_path, 'r') as file:
        mode = None  
        objective = {}  
        constraints = defaultdict(lambda: {'sense': None, 'rhs': None, 'coefficients': {}})  
        variables = {}  
        
        for line in file:
            line = line.strip()
            if not line:
                continue
            
            if line in ['ROWS', 'COLUMNS', 'RHS', 'BOUNDS', 'SOS', 'RANGES']:
                mode = line
                continue
            
            fields = line.split()
            
            if mode == 'ROWS':
                sense, name = fields[0], fields[1]
                if sense == 'N':
                    continue
                else:
                    constraints[name]['sense'] = sense
            
            elif mode == 'COLUMNS':
                if fields[2] in ['INTORG', 'INTEND']:
                    continue 
                
                var_name = fields[0]
                try:
                    constr_name, coeff = fields[1], float(fields[2])
                except ValueError:
                    continue  
                        
                if constr_name == 'OBJ':
                    objective[var_name] = coeff
                else:
                    constraints[constr_name]['coefficients'][var_name] = coeff
                                                
                if var_name not in variables:
                    variables[var_name] = {'lb': 0.0, 'ub': float('inf')}
                        
            elif mode == 'RHS':
                constr_name, rhs = fields[1], float(fields[2])
                constraints[constr_name]['rhs'] = rhs
            
            elif mode == 'BOUNDS':
                bound_type, bound_name, var_name = fields[0], fields[1], fields[2]
                bound_value = float(fields[3]) if len(fields) > 3 else None

                
                if bound_type == 'LO':
                    variables[var_name]['lb'] = bound_value
                elif bound_type == 'UP':
                    variables[var_name]['ub'] = bound_value
                elif bound_type == 'FX':
                    variables[var_name]['lb'] = bound_value
                    variables[var_name]['ub'] = bound_value

                    
        return objective, constraints, variables

parsed_objective, parsed_constraints, parsed_variables = parse_mps_updated(file_path)
len(parsed_objective), len(parsed_constraints), len(parsed_variables)


solver = pywraplp.Solver.CreateSolver('PDLP')

ortools_variables = {}
for var_name, bounds in parsed_variables.items():
    lb, ub = bounds['lb'], bounds['ub']
    ortools_variables[var_name] = solver.NumVar(lb, ub, var_name)

for constr_name, constr_data in parsed_constraints.items():
    coefficients = constr_data['coefficients']
    rhs = constr_data['rhs']
    if rhs is None:
        rhs = 0
    
    sense = constr_data['sense']
    if sense == 'E': 
        constraint = solver.RowConstraint(rhs, rhs, constr_name)
    elif sense == 'L':  
        constraint = solver.RowConstraint(-solver.infinity(), rhs, constr_name)
    elif sense == 'G':  
        constraint = solver.RowConstraint(rhs, solver.infinity(), constr_name)

    
    for var_name, coeff in coefficients.items():
        constraint.SetCoefficient(ortools_variables[var_name], coeff)
objective_expr = solver.Objective()
for var_name, coeff in parsed_objective.items():
    objective_expr.SetCoefficient(ortools_variables[var_name], coeff)

ort_num_vars = solver.NumVariables()
ort_num_constraints = solver.NumConstraints()
ort_num_vars, ort_num_constraints
status = solver.Solve()

if status == pywraplp.Solver.OPTIMAL:
    optimal_value = solver.Objective().Value()
    print(f"Optimal Objective Value: {optimal_value}")
elif status == pywraplp.Solver.INFEASIBLE:
    print("The problem is infeasible.")
elif status == pywraplp.Solver.UNBOUNDED:
    print("The problem is unbounded.")
else:
    print("The solver did not find an optimal solution.")

The problem becomes feasible for or-tools When I exclude the following code snippet:

if sense == 'E': constraint = solver.RowConstraint(rhs, rhs, constr_name)

However, even with this change, the optimal solution provided by or-tools is incorrect. I appreciate any insights.

1

There are 1 best solutions below

1
watchdogs132 On

Using model_builder API simplifies this quite a bit.

Example use:

from ortools.linear_solver.python import model_builder

mps_path = "./prob.mps"
model = model_builder.ModelBuilder()
model.import_from_mps_file(mps_path)

solver = model_builder.ModelSolver("SAT")
solver.enable_output(True)
solver.set_time_limit_in_seconds(100)
solver.set_solver_specific_parameters("num_workers:17, num_violation_ls:2, use_lb_relax_lns:true")
solver.solve(model)