Source code for src.ilp_manager
import pulp
from itertools import product
from naming_utils import s_star_index_node, index_color_node
[docs]class ILPManager(object):
"""Model the 185th problem in Project Euler as an ILP (Integer Linear Program)"""
def __init__(self, m):
"""To instantiate this module, please specify the length on sequences."""
self.m = m
self.n_digits = 10
self.optimal_status = 'Optimal'
self.active_edge = 1.0
[docs] def build_ilp_solver(self, sequences_list, n_correct_vertices_list):
"""
Given input sequences, and number or correct vertices in each of them,
build an ILP representation of the problem.
:param sequences_list: List of sequences, each of length self.m, of integers between 0 and 9.
:param n_correct_vertices_list: Number of correct vertices in each sequence in sequences_list. \
A vertex is correct if its color is equal to the color of \
the corresponding vertex in the solution s_star.
:return: tuple, containing:
* ilp_solver: Pulp instance, holding all the information needed for the solution.
* s_star_to_color_edges: The edges (variables) in the ilp_solver.
"""
print "Building ILP..."
ilp_solver = pulp.LpProblem("ilp_solver", pulp.LpMinimize)
s_star_to_color_edges = self._get_s_star_to_color_edges()
ilp_solver += 0
self._add_s_star_constraints(ilp_solver, s_star_to_color_edges)
self._add_correct_vertices_constraints(ilp_solver, s_star_to_color_edges,
n_correct_vertices_list, sequences_list)
return ilp_solver, s_star_to_color_edges
[docs] def solve_ilp(self, ilp_solver, s_star_to_color_edges):
"""
Given a solver with the needed information, solve the ILP and extract the solution to problem 185.
:param ilp_solver: Pulp instance, holding all the information needed for the solution.
:param s_star_to_color_edges: The edges (variables) in the ilp_solver.
:return: s_star: List of integers that is the solution to problem 185.
"""
print "Solving ILP..."
ilp_solver.solve()
self._assert_optimal(ilp_solver)
s_star = self._get_solution(s_star_to_color_edges)
return s_star
def _get_s_star_to_color_edges(self):
s_star_to_color_edges = pulp.LpVariable.dicts("s_star_to_color_edges",
((s_star_index_node(i), index_color_node(i, c))
for i, c in product(range(self.m), range(self.n_digits))),
cat="Binary")
return s_star_to_color_edges
def _add_s_star_constraints(self, ilp_solver, s_star_to_color_edges):
for i in range(self.m):
ilp_solver += pulp.lpSum(s_star_to_color_edges[s_star_index_node(i), index_color_node(i, c)]
for c in range(self.n_digits)) == 1
def _add_correct_vertices_constraints(self, ilp_solver, s_star_to_color_edges,
n_correct_vertices_list, sequences_list):
for i, s in enumerate(sequences_list):
ilp_solver += pulp.lpSum(s_star_to_color_edges[s_star_index_node(i), index_color_node(i, s[i])]
for i in range(self.m)) == n_correct_vertices_list[i]
def _assert_optimal(self, ilp_solver):
assert (pulp.LpStatus[ilp_solver.status] == self.optimal_status)
def _get_solution(self, s_star_to_color_edges):
s_star_unsorted = {i: c
for i, c in product(range(self.m), range(10))
if pulp.value(s_star_to_color_edges[s_star_index_node(i), index_color_node(i, c)])
== self.active_edge}
s_star = [s_star_unsorted[i] for i in range(self.m)]
return s_star