Skip to content

Instantly share code, notes, and snippets.

@AndrewBMartin
Created May 27, 2014 21:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AndrewBMartin/20dbf7bba1e2ed7538c9 to your computer and use it in GitHub Desktop.
Save AndrewBMartin/20dbf7bba1e2ed7538c9 to your computer and use it in GitHub Desktop.
Python wrapper to store an lp file as a model object
""""
Try to create model, variable and constraint objects.
Try to read the lp into a model object faster.
"""
import os
from profilehooks import profile, timecall
class Model(object):
def __init__(self):
self.name = ''
self.variables = []
self.constraints = []
self.obj = ''
self.sense = 'Maximize'
self.model_file
@staticmethod
def try_split(line):
if len(line.split(">=")) > 1:
return (line.split(">="), ">=")
elif len(line.split("<=")) > 1:
return (line.split("<="), "<=")
elif len(line.split("=")) > 1:
return (line.split("="), "=")
elif len(line.split(">")) > 1:
return (line.split(">"), ">")
elif len(line.split("<")) > 1:
return (line.split("<"), "<")
@profile
def read(self, model_file):
variables = []
var_names = set()
constraints = []
objective = ''
senses = ['=', '>=', '<=', '>', '<']
## Please Refactor ##
with open(model_file, 'r') as data:
# store current constraint
tmp = ''
# when passing through the lp we start
# in the objective function. Process the
# objective function and constraints
# differently.
in_constraints = False
in_variables = False
title = data.readline()
make_new_con_next_line = False
# Go through the lp file line by line and
# create constraint and variable objects.
for a,line in enumerate(data):
if a % 100000 == 0:
print a
# The portion of the lp beneath "Subject To"
if in_constraints:
# We're in the variable bounds section
if 'Bounds' in line:
in_constraints = False
in_variables = True
continue
if ':' in line:
if tmp:
constraints.append(tmp)
tmp = ""
split_line = line.split(":")
tmp = Constraint(split_line[0])
line = split_line[1]
elif [bit for bit in line if bit in senses]:
split_line, sense = self.try_split(line)
tmp.rhs = split_line[1]
tmp.sense = sense
line = split_line[0]
split_at_spaces = line.split(" ")
sense = False
var = ''
coeff_and_sense = ''
for item in split_at_spaces:
if item == '+' or item == '-':
coeff_and_sense = item
elif any(i.isalpha() for i in item):
var = Variable(item)
if var.name not in var_names:
variables.append(var)
var_names.add(var.name)
# If a coefficient is 1 then nothing
# is written in the lp file to represent it.
# This is the default coefficient.
tmp.variables[var.name] = coeff_and_sense
elif item.strip():
coeff_and_sense += " " + item
# for now assume all variables are free.
# If I find a situation where this is not the
# case then make appropriate changes.
elif in_variables:
if 'free' in line:
continue
# The portion of the lp before "Subect To"
# This feels unclean, but it's easier than
# making a function right now.
else:
if 'ubject' in line:
in_constraints = True
if tmp:
constraints.append(tmp)
tmp = ''
if ':' in line:
tmp = Constraint(line.split(" ")[2][:-1])
continue
elif 'aximize' in line or 'inimize' in line:
make_new_con_next_line = True
self.sense = line
if ':' in line:
tmp = Constraint(line.split(" ")[1][:-1])
elif make_new_con_next_line:
split_line = line.split(":")
tmp = Constraint(split_line[0])
tmp.obj = True
make_new_con_next_line = False
line = split_line[1]
if tmp:
split_at_spaces = line.split(" ")
sense = '+'
var = ''
coeff_and_sense = ''
for item in split_at_spaces:
if item == '+' or item == '-':
coeff_and_sense = item
elif any(i.isalpha() for i in item):
var = Variable(item.strip())
if var.name not in var_names:
variables.append(var)
var_names.add(var.name)
# If a coefficient is 1 then nothing
# is written in the lp file to represent it.
# This is the default coefficient.
tmp.variables[var.name] = coeff_and_sense
elif item.strip():
coeff_and_sense += " " + item
var.obj = float(item)
self.variables = variables
self.constraints = constraints
class Constraint(object):
def __init__(self, name):
self.name = name
self.variables = {}
self.rhs = ''
self.obj = False
self.obj = 0 # update this to include in the objective function
class Variable(object):
def __init__(self, name):
self.name = name
self.X = ''
self.UB = float("inf")
self.LB = 0
self.obj = 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment