def reduce(diagram, linear=True): variables = [t[0] for t in column_variables + row_variables] if linear: reduction = LinearReduction(diagram.pool) result = reduction.reduce(diagram.root_node.node_id, variables) else: reduction = SmtReduce(diagram.pool) result = reduction.reduce(diagram.root_node.node_id, variables) return Diagram(diagram.pool, result)
def reduce(self, variables=None, method="linear"): if method == "linear": from pyxadd.reduce import LinearReduction reducer = LinearReduction(self.pool) elif method == "smt": from pyxadd.reduce import SmtReduce reducer = SmtReduce(self.pool) else: raise RuntimeError("Unknown reduction method {} (valid options are 'linear' or 'smt')".format(method)) return Diagram(self.pool, reducer.reduce(self.root_node.node_id, variables))
class ConstantWalker(DownUpWalker): def __init__(self, diagram, diagram_vars): DownUpWalker.__init__(self, diagram) self._diagram_vars = diagram_vars self._reduction = LinearReduction(self.diagram.pool) def visit_internal_aggregate(self, internal_node, true_result, false_result): node_id = self._reduction.reduce((true_result + false_result).root_node.node_id, self._diagram_vars) return self.diagram.pool.diagram(node_id) def visit_internal_down(self, internal_node, parent_message): if parent_message is None: parent_message = self._initial_message() bounds, path = parent_message bounds_t = dict(bounds) bounds_f = dict(bounds) # Avoiding having to find all integer points in complex areas by only looking at "simple" constraints operator = internal_node.test.operator if operator.is_singular(): var = operator.variables[0] lb, ub = bounds[var] if var in bounds else (-oo, oo) bounds_t[var] = internal_node.test.update_bounds(var, lb, ub, test=True) bounds_f[var] = internal_node.test.update_bounds(var, lb, ub, test=False) pool = self.diagram.pool path_t = path & pool.diagram(pool.internal(LinearTest(operator), pool.one_id, pool.zero_id)) path_f = path & pool.diagram(pool.internal(LinearTest(~operator), pool.one_id, pool.zero_id)) return (bounds_t, path_t), (bounds_f, path_f) def visit_terminal(self, terminal_node, parent_message): print(parent_message, terminal_node.expression) if parent_message is None: parent_message = self._initial_message() bounds, path = parent_message pool = self.diagram.pool if terminal_node.expression == 0: return pool.diagram(pool.zero_id) elif len(terminal_node.expression.free_symbols) == 0: return path * pool.diagram(terminal_node.node_id) else: variables_present = terminal_node.expression.free_symbols # FIXME todo return pool.diagram(pool.zero_id) def _initial_message(self): return {}, self.diagram.pool.diagram(self.diagram.pool.one_id)
def reduce(self, variables=None, method="linear", smt_solver=None): if method == "linear": from pyxadd.reduce import LinearReduction reducer = LinearReduction(self.pool) elif method == "smt": from pyxadd.reduce import SmtReduce reducer = SmtReduce(self.pool, solver=smt_solver) else: raise RuntimeError( "Unknown reduction method {} (valid options are 'linear' or 'smt')" .format(method)) return Diagram(self.pool, reducer.reduce(self.root_node.node_id, variables))