updates to not consider already paired source/drains

This commit is contained in:
Andy Eschbacher
2017-05-18 13:03:18 -04:00
parent 39b7b09272
commit 7675a60dee
@@ -2,7 +2,7 @@
import plpy import plpy
import numpy as np import numpy as np
import cvxopt import cvxopt
from cvxopt.glpk import ilp from cvxopt import solvers
from crankshaft.analysis_data_provider import AnalysisDataProvider from crankshaft.analysis_data_provider import AnalysisDataProvider
class Optim(object): class Optim(object):
@@ -12,7 +12,7 @@ class Optim(object):
- source_amount * (marginal_cost + transport_cost * distance) - source_amount * (marginal_cost + transport_cost * distance)
""" """
def __init__(self, source_query, drain_query, dist_matrix_query, def __init__(self, source_query, drain_query, dist_matrix_table,
capacity_column, production_column, marginal_column, capacity_column, production_column, marginal_column,
**kwargs): **kwargs):
@@ -26,28 +26,55 @@ class Optim(object):
'solver': kwargs.get('solver', 'glpk')} 'solver': kwargs.get('solver', 'glpk')}
self._check_model_params() self._check_model_params()
# TODO: add source_fixed and source_free ids
# NOTE: this means that fixed sources will need to have their costs
# calculated separately
# TODO: drain_capacity will not be just reading the column - it will
# be reading the column and subtracting already-claimed values
# NOTE: after this, the rest of the algorithm _may_ be unchanged
# other than adding back the fixed sources to the table at the end of
# the calcuation
# database ids # database ids
self.ids = { self.ids = {
'drain': self.data_provider.get_column(drain_query, 'drain': self.data_provider.get_column(drain_query,
'cartodb_id', 'cartodb_id',
id_col='cartodb_id',
dtype=int), dtype=int),
'source': self.data_provider.get_column(source_query, 'source_free': self.data_provider.get_column(
'cartodb_id', source_query,
dtype=int)} 'cartodb_id',
dtype=int,
condition='drain_id is null'),
'source_fixed': self.data_provider.get_column(
source_query,
'cartodb_id',
dtype=int,
condition='drain_id is not null')}
plpy.notice('self.ids[drain]: {}'.format(self.ids['drain']))
plpy.notice('self.ids[source_free]: {}'.format(self.ids['source_free']))
plpy.notice('self.ids[source_fixed]: {}'.format(self.ids['source_fixed']))
# model data # model data
self.model_data = { self.model_data = {
'drain_capacity': self.data_provider.get_column(drain_query, 'drain_capacity': self.data_provider.get_reduced_column(
capacity_column), drain_query,
capacity_column,
source_query,
production_column,
id_col='cartodb_id',
dtype=int),
'source_amount': self.data_provider.get_column(source_query, 'source_amount': self.data_provider.get_column(source_query,
production_column), production_column,
'marginal_cost': self.data_provider.get_column(drain_query, condition='drain_id is null'),
marginal_column), 'marginal_cost': self.data_provider.get_column(
drain_query,
marginal_column),
'distance': 'distance':
self.data_provider.get_distance_matrix(dist_matrix_query, self.data_provider.get_distance_matrix(dist_matrix_table,
self.ids['source'], self.ids['source_free'],
self.ids['drain'])} self.ids['drain'])}
plpy.notice(self.model_data)
self.model_data['cost'] = self.calc_cost() self.model_data['cost'] = self.calc_cost()
self.n_sources = len(self.ids['source']) self.n_sources = len(self.ids['source_free'])
self.n_drains = len(self.ids['drain']) self.n_drains = len(self.ids['drain'])
def _check_constraints(self): def _check_constraints(self):
@@ -101,7 +128,7 @@ class Optim(object):
drain_id_crosswalk[idx] = cid drain_id_crosswalk[idx] = cid
source_id_crosswalk = {} source_id_crosswalk = {}
for idx, cid in enumerate(self.ids['source']): for idx, cid in enumerate(self.ids['source_free']):
# matrix index -> cartodb_id # matrix index -> cartodb_id
source_id_crosswalk[idx] = cid source_id_crosswalk[idx] = cid
@@ -216,10 +243,12 @@ class Optim(object):
range(n_pairings), range(n_pairings),
range(n_pairings)) range(n_pairings))
], tc='d') ], tc='d')
for var in (cost, ineq_maxs, drain_capacity, A, b):
plpy.notice('size: {}'.format(var.size))
plpy.notice('{}, {}, {}'.format(n_pairings, self.n_sources, self.n_drains))
# solve # solve
sol = cvxopt.solvers.lp(c=cost, G=ineq_maxs, h=drain_capacity, sol = solvers.lp(c=cost, G=ineq_maxs, h=drain_capacity,
A=A, b=b, solver=self.model_params['solver']) A=A, b=b, solver=self.model_params['solver'])
if sol['status'] != 'optimal': if sol['status'] != 'optimal':
raise Exception("No solution possible: {}".format(sol)) raise Exception("No solution possible: {}".format(sol))