Created
May 27, 2014 21:49
-
-
Save AndrewBMartin/20dbf7bba1e2ed7538c9 to your computer and use it in GitHub Desktop.
Python wrapper to store an lp file as a model object
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""" | |
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