Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Model vector access #101

Merged
merged 7 commits into from
Apr 8, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 15 additions & 16 deletions optlang/cplex_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -723,40 +723,39 @@ def _set_objective_direction(self, direction):

@property
def primal_values(self):
# round primals
primal_values = [variable._round_primal_to_bounds(primal)
for variable, primal in zip(self.variables, self._get_primal_values())]
return collections.OrderedDict(
zip(self._get_variables_names(), primal_values)
)

def _get_primal_values(self):
try:
primal_values = collections.OrderedDict(
(variable.name, variable._round_primal_to_bounds(primal))
for variable, primal in zip(self.variables, self.problem.solution.get_values())
)
primal_values = self.problem.solution.get_values()
except CplexSolverError as err:
raise SolverError(str(err))
return primal_values

@property
def reduced_costs(self):
def _get_reduced_costs(self):
if self.is_integer:
raise ValueError("Dual values are not well-defined for integer problems")
try:
return collections.OrderedDict(
zip((variable.name for variable in self.variables), self.problem.solution.get_reduced_costs()))
return self.problem.solution.get_reduced_costs()
except CplexSolverError as err:
raise SolverError(str(err))

@property
def constraint_values(self):
def _get_constraint_values(self):
try:
return collections.OrderedDict(
zip((constraint.name for constraint in self.constraints), self.problem.solution.get_activity_levels()))
return self.problem.solution.get_activity_levels()
except CplexSolverError as err:
raise SolverError(str(err))

@property
def shadow_prices(self):
def _get_shadow_prices(self):
if self.is_integer:
raise ValueError("Dual values are not well-defined for integer problems")
try:
return collections.OrderedDict(
zip((constraint.name for constraint in self.constraints), self.problem.solution.get_dual_values()))
return self.problem.solution.get_dual_values()
except CplexSolverError as err:
raise SolverError(str(err))

Expand Down
59 changes: 26 additions & 33 deletions optlang/glpk_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@
glp_set_mat_row, glp_set_col_bnds, glp_set_row_bnds, GLP_FR, GLP_UP, GLP_LO, GLP_FX, GLP_DB, glp_del_rows, \
glp_get_mat_row, glp_get_row_ub, glp_get_row_type, glp_get_row_lb, glp_get_row_name, glp_get_obj_coef, \
glp_get_obj_dir, glp_scale_prob, GLP_SF_AUTO, glp_get_num_int, glp_get_num_bin, glp_mip_col_val, \
glp_mip_obj_val, glp_mip_status, GLP_ETMLIM, glp_adv_basis, glp_read_lp, glp_mip_row_val
glp_mip_obj_val, glp_mip_status, GLP_ETMLIM, glp_adv_basis, glp_read_lp, glp_mip_row_val, \
get_col_primals, get_col_duals, get_row_primals, get_row_duals



Expand Down Expand Up @@ -585,45 +586,37 @@ def objective(self, value):

@property
def primal_values(self):
primal_values = collections.OrderedDict()
is_mip = self._glpk_is_mip()
for index, variable in enumerate(self.variables):
if is_mip:
value = glp_mip_col_val(self.problem, index + 1)
else:
value = glp_get_col_prim(self.problem, index + 1)
primal_values[variable.name] = variable._round_primal_to_bounds(value)
return primal_values
# round primals
primal_values = [variable._round_primal_to_bounds(primal)
for variable, primal in zip(self.variables, self._get_primal_values())]
return collections.OrderedDict(
zip(self._get_variables_names(), primal_values)
)

@property
def reduced_costs(self):
def _get_primal_values(self):
if self._glpk_is_mip():
# no vector function (element wise)
return [glp_mip_col_val(self.problem, index + 1)
for index in range(len(self.variables))]
else:
return get_col_primals(self.problem)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_col_primals will return the mip values via glp_mip_col_val automatically if the problem is a MIP. That is done in C so no need for the if-statement.


def _get_reduced_costs(self):
if self.is_integer:
raise ValueError("Dual values are not well-defined for integer problems")
reduced_costs = collections.OrderedDict(
(var.name, glp_get_col_dual(self.problem, index + 1)) for index, var in enumerate(self.variables)
)
return reduced_costs
return get_col_duals(self.problem)

@property
def constraint_values(self):
dual_values = collections.OrderedDict()
is_mip = self._glpk_is_mip()
for index, constraint in enumerate(self.constraints):
if is_mip:
value = glp_mip_row_val(self.problem, index + 1)
else:
value = glp_get_row_prim(self.problem, index + 1)
dual_values[constraint.name] = value
return dual_values
def _get_constraint_values(self):
if self._glpk_is_mip():
# no vector function (element wise)
return [glp_mip_row_val(self.problem, index + 1) for index in range(len(self.constraints))]
else:
return get_row_primals(self.problem)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as before. Already handled by the swiglpk function. No need for glp_mip_row_val here as this is used already anyways.


@property
def shadow_prices(self):
def _get_shadow_prices(self):
if self.is_integer:
raise ValueError("Dual values are not well-defined for integer problems")
shadow_prices = collections.OrderedDict(
(constraint.name, glp_get_row_dual(self.problem, index + 1)) for index, constraint in enumerate(self.constraints)
)
return shadow_prices
return get_row_duals(self.problem)

def to_lp(self):
self.update()
Expand Down
72 changes: 68 additions & 4 deletions optlang/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -1202,16 +1202,37 @@ def status(self):
"""The solver status of the model."""
return self._status

def _get_variables_names(self):
"""The names of model variables.

Returns
-------
list
"""
return [variable.name for variable in self.variables]

@property
def primal_values(self):
"""The primal values of model variables.

The primal values are rounded to the bounds.
Returns
-------
collections.OrderedDict
"""
return collections.OrderedDict(
zip(self._get_variables_names(), self._get_primal_values())
)

def _get_primal_values(self):
"""The primal values of model variables.

Returns
-------
list
"""
# Fallback, if nothing faster is available
return collections.OrderedDict([(variable.name, variable.primal) for variable in self.variables])
return [variable.primal for variable in self.variables]

@property
def reduced_costs(self):
Expand All @@ -1221,8 +1242,28 @@ def reduced_costs(self):
-------
collections.OrderedDict
"""
return collections.OrderedDict(
zip(self._get_variables_names(), self._get_reduced_costs())
)

def _get_reduced_costs(self):
"""The reduced costs/dual values of all variables.

Returns
-------
list
"""
# Fallback, if nothing faster is available
return collections.OrderedDict([(variable.name, variable.dual) for variable in self.variables])
return [variable.dual for variable in self.variables]

def _get_constraint_names(self):
"""The names of model constraints.

Returns
-------
list
"""
return [constraint.name for constraint in self.constraints]

@property
def constraint_values(self):
Expand All @@ -1232,19 +1273,42 @@ def constraint_values(self):
-------
collections.OrderedDict
"""
return collections.OrderedDict(
zip(self._get_constraint_names(), self._get_constraint_values())
)

def _get_constraint_values(self):
"""The primal values of all constraints.

Returns
-------
list
"""
# Fallback, if nothing faster is available
return collections.OrderedDict([(constraint.name, constraint.primal) for constraint in self.constraints])
return [constraint.primal for constraint in self.constraints]

@property
def shadow_prices(self):
"""The shadow prices of model (dual values of all constraints).

Returns
-------
collections.OrderedDict
"""
return collections.OrderedDict(
zip(self._get_constraint_names(), self._get_shadow_prices())
)


def _get_shadow_prices(self):
"""The shadow prices of model (dual values of all constraints).

Returns
-------
collections.OrderedDict
"""
# Fallback, if nothing faster is available
return collections.OrderedDict([(constraint.name, constraint.dual) for constraint in self.constraints])
return [constraint.dual for constraint in self.constraints]

@property
def is_integer(self):
Expand Down