Example #1
0
  def add_edge(self, *args, **kwargs):
    '''Adds an edge between `source` and `dest`. `shared_variables` represents a
    list of variables, how `source` depends on `dest`. Returns edge object.

    :param shared_variables: A list of variables.
    :return: An :class:`Edge` instance.
    '''
    edge = None
    if len(args) == 1:
      edge = args[0]
      if not isinstance(edge, Edge):
        raise TypeError()
    else:
      edge = Edge(*args, **kwargs)
    nx.DiGraph.add_edge(self, edge.get_source().get_name(),
                        edge.get_dest().get_name(),
                        edge)
    logging.debug("Add edge between %s and %s with %d shared variable(s)",
                  edge.get_source().get_name(), edge.get_dest().get_name(),
                  edge.get_num_shared_variables())
    for node in (self.node[edge.get_source().get_name()],
                 self.node[edge.get_dest().get_name()]):
      node['shared_variables'] |= edge.get_shared_variables()
      node['local_variables'] = (
        set(node['model'].get_columns_names())
        - set(node['shared_variables']))
    return edge
Example #2
0
 def check_params(self, params):
   if not isinstance(params, dict):
     raise TypeError()
   if params['num_blocks'] and max(params['num_constraints']) < max(params['num_blocks']):
     logging.debug('Number of constraints cannot be less that number of blocks: %d < %d' \
                    % (max(params['num_constraints']), max(params['num_blocks'])))
     return False
   return True
Example #3
0
 def _process_decomposition_tree(self, tree):
   # TODO(d2rk): merge nodes if necessary.
   for node in tree.get_nodes():
     if node.get_num_shared_variables() > self._driver_params.max_num_shared_variables:
       logging.debug('Node %s has too many shared variables: %d > %d',
                     node.get_name(), node.get_num_shared_variables(),
                     self._driver_params.max_num_shared_variables)
       return False
   return True
Example #4
0
 def execute(self, sql, *args):
   '''Replaces :func:`execute` with a logging variant.'''
   if args:
     parameters = []
     for arg in args:
       if isinstance(arg, buffer):
         parameters.append('<blob>')
       else:
         parameters.append(repr(arg))
     logging.debug('SQL Execute: %s - \n %s', sql,
                   '\n '.join(str(param) for param in parameters))
   else:
     logging.debug(sql)
   return super(SQLiteCursorWrapper, self).execute(sql, *args)
Example #5
0
  def build_from_scratch(cls, objective_coefficients, constraints_coefficients,
                         constraints_senses, constraints_rhs,
                         constraints_names=[], variables_lower_bounds=[],
                         variables_upper_bounds=[], variables_names=[]):
    """Builds model from a scratch.

    The following code snippet shows how to define two models from scratch,
    where the first model needs to be maximized and the second one --
    minimized::

      MPModelBuilder.build_from_scratch([1, 1, 2], [[1, 2, 3], ['L', 'L'], [1, 1]])
      MPModelBuilder.build_from_scratch(([1, 1, 2], False), [[1, 2, 3], ['L', 'L'], [1, 1]])

    :param objective_coefficients: This parameter can be represented
      either a list of objective function variable coefficients, or a tuple,
      where the first element is a list of coefficients and the second one is
      ``True`` or ``False``, that defines objective function maximization or
      minimization. By default does maximization (see :func:`set_objective`).
    :param constraints_coefficients: Left-hand side or constraint matrix.
    :param constraints_senses: A list of senses of the constraints.
    :param constraints_rhs: A list of rhs bounds.
    :param constraints_names: A list of constraints names.
    :param variables_lower_bounds: A list of variables lower bounds.
    :param variables_upper_bounds: A list of variables upper bounds.
    :param variables_names: A list of variables names, where each name
      represented by a string.
    :returns: A :class:`MPModel` instance.

    :raises: :exc:`TypeError`
    """
    logging.debug('Build new model from scratch')
    if not bool(len(variables_names)):
      variables_names = []
      for i in range(1, len(objective_coefficients) + 1):
        variables_names.append(cls.VARIABLE_NAME_FORMAT.format(index=i))
    if not bool(len(variables_lower_bounds)):
      variables_lower_bounds = [0.0] * len(objective_coefficients)
    if not bool(len(variables_upper_bounds)):
      variables_upper_bounds = [1.0] * len(objective_coefficients)
    if not bool(len(constraints_names)):
      constraints_names = []
      for i in range(1, len(constraints_senses) + 1):
        constraints_names.append(cls.CONSTRAINT_NAME_FORMAT.format(index=i))
    return (mp_model.MPModel()
            .set_columns(variables_lower_bounds, variables_upper_bounds,
                         variables_names)
            .set_objective(objective_coefficients)
            .set_rows(constraints_coefficients, constraints_senses,
                      constraints_rhs, constraints_names))
Example #6
0
 def decompose(self):
   self._decomposition_tree = decomposition_tree.DecompositionTree(self._model)
   igraph = interaction_graph.InteractionGraph(self.get_model())
   cliques = list(map(set, networkx.find_cliques(igraph)))
   logging.debug("%d clique(s) were found." % len(cliques))
   submodels_cache = []
   for i, clique in enumerate(cliques):
     submodel = self._build_submodel(clique)
     self._decomposition_tree.add_node(submodel)
     submodels_cache.append(submodel)
     for j, other_clique in enumerate(cliques[:i]):
       other_submodel = submodels_cache[j]
       shared_cols_scope = clique & other_clique
       if shared_cols_scope:
         self._decomposition_tree.add_edge(submodel, other_submodel,
                                           shared_cols_scope)
   self._decomposition_tree.set_root(submodels_cache[-1])
Example #7
0
 def execute(self, request):
   model = request.get_model()
   logging.debug('Solve model %s that has %d row(s) and %d column(s)'
                 ' with solver %s',
                 model.get_name(), model.get_num_rows(),
                 model.get_num_columns(), request.get_solver_id())
   solver = backend_solvers.get_instance_of(request.get_solver_id())
   if not solver:
     raise Error("Cannot instantiate backend solver by id: %d" %
                 request.get_solver_id())
   try:
     solver.load_model(model)
     solver.solve()
   except Error, e:
     # TODO: send back a report.
     logging.exception("Cannot execute given request: cannot solve the model.")
     return None
Example #8
0
 def set_root(self, root):
   logging.debug("Set %s as root node." % root.get_name())
   self._root = root
Example #9
0
 def _remove_node(self, node):
   logging.debug('Remove node %s', node.get_name())
   nodes = self._dtree_traversal.mark_node_as_visited(node)
   for node in nodes:
     self._add_node(node)
Example #10
0
 def _add_node(self, node):
   logging.debug('Add node %s', node.get_name())
   enumerator = shared_variables_enumerator.SharedVariablesEnumerator(
     node.get_model(), node.get_shared_variables(), node.get_local_variables())
   self._enumerators[node] = enumerator
   self._unsolved_models_counter[node] = 0
Example #11
0
 def process_response(self, response):
   cxt = self._frozen_contexts.pop(response.get_id())
   solution = response.get_solution()
   logging.debug("Process %s solution produced by %d with status %d",
                 response.get_id(), cxt.solver_id_stack[0], solution.get_status())
   cxt.solver_id_stack.pop(0)
   # Check F3: whether optimal solution has been found.
   if (not solution.get_status() is mp_solution.MPSolution.NOT_SOLVED
       and not solution.get_variables_values() is None):
     if ((sum(solution.get_variables_values().tolist()) % 1.0) == 0 and
         solution.is_optimal()):
       objective_value = solution.get_objective_value()
       # Check F2: do we need to continue?
       # NOTE: the best objective value will be checked inside of
       # set_best_objective_value().
       if cxt.set_best_objective_value(objective_value):
         logging.debug('Model %s has a new best objective value: %f',
                       response.get_id(), objective_value)
         cxt.partial_solution.update_variables_values(solution)
         cxt.partial_solution.set_objective_value(objective_value)
         logging.debug('Write %s solution to the table.', response.get_id())
         self._solution_table.write_solution(cxt.submodel, cxt.partial_solution)
       else:
         logging.debug("Solution is rejected: not the best objective value"
                       ": %f <= %f", objective_value, cxt.best_objective_value)
     else:
       logging.debug("Solution is rejected: "
                     "not optimal or fractional solution.")
   else:
     logging.debug("Solution is rejected: model wasn't solved.")
   if len(cxt.solver_id_stack) == 0:
     self._search_tree.mark_model_as_solved(cxt.candidate_model)
   else:
     self._active_contexts[cxt.candidate_model.get_name()] = cxt
Example #12
0
 def executescript(self, sql):
   '''Replaces :func:`executescript` with a logging variant.'''
   logging.debug('SQL ExecuteScript: %s', sql)
   return super(SQLiteCursorWrapper, self).executescript(sql)
Example #13
0
 def executemany(self, sql, seq_parameters):
   '''Replaces executemany() with a logging variant.'''
   seq_params_list = list(seq_parameters)
   logging.debug('SQL ExecuteMany: %s - \n %s', sql,
                 '\n '.join(str(param) for param in seq_params_list))
   return super(SQLiteCursorWrapper, self).executemany(sql, seq_params_list)