def compose(self, other): # If we were given two references to the same object, then # make a copy. if self is other: other = deepcopy(self) # Make sure we are given a Relation raise_objs_not_like_types(other, Relation) # Make sure the arities are valid if other.arity_out() != self.arity_in(): raise ValueError( "Compose failure: Output arity of second relation (%d) does not match input arity of first relation (%d)" % (other.arity_out(), self.arity_in()) ) self.print_debug("Compose: \n\t%s\n\n\t.compose(%s)\n\n\t" % (self, other)) # Collection of new composed relations new_relations = [] for rel1 in self.relations: for rel2 in other.relations: new_relations.append(self._compose(rel1, rel2)) new_relation = Relation(relations=new_relations) self.print_debug("\n\tCompose output: %s\n" % (new_relation)) return new_relation
def _apply(self, set, rel): # Make sure we are given a PresSet and a PresRelation raise_objs_not_like_types(set, PresSet) raise_objs_not_like_types(rel, PresRelation) # Make sure the arities are valid if rel.arity_in() != set.arity(): raise ValueError( "Apply failure: Input arity of relation (%d) does not match arity of set (%d)" % (rel.arity_out(), set.arity()) ) # Copy the given set and relation set_copy = deepcopy(set) rel_copy = deepcopy(rel) # Rename tuple variables by appending '1' and '2' self._rename_vars(set_copy, set_copy.tuple_set.vars, "1") self._rename_vars(rel_copy, rel_copy.tuple_in.vars + rel_copy.tuple_out.vars, "2") # Create the new set that will end up being the final result new_tuple_set = deepcopy(rel_copy.tuple_out) new_symbolics = deepcopy(set_copy.symbolics) + deepcopy(rel_copy.symbolics) new_set = PresSet(new_tuple_set, Conjunction([]), new_symbolics) # Copy over the constraints from the set and relation self._copy_constraints(new_set, set_copy, rel_copy) # Add equality constraints for set_tuple = rel_tuple_in self._create_equality_constraints(new_set, set_copy.tuple_set.vars, rel_copy.tuple_in.vars) # Rename the resulting tuple back to the original names self._unrename_vars(new_set, rel.tuple_in.vars + rel.tuple_out.vars, "2") return new_set
def apply(self, other): # Make sure we are given a Relation raise_objs_not_like_types( other, Relation, "Apply failure: Can only apply objects that look like a Relation object to a Set" ) # Make sure the arities are valid if other.arity_in() != self.arity(): raise ValueError( "Apply failure: Input arity of relation (%d) does not match arity of set (%d)" % (other.arity_out(), self.arity()) ) # Collection of new applied sets new_sets = [] for set in self.sets: for rel in other.relations: new_sets.append(self._apply(set, rel)) new_set = Set(sets=new_sets) self.print_debug("Apply: %s.apply(%s)=%s" % (self, other, new_set)) return new_set
def inFuncExp(self,node): from iegen.ast import NormExp if type(0)!=type(node.coeff): raise ValueError('FuncExp.coeff must be an integer.') if type('')!=type(node.name): raise ValueError('FuncExp.name must be a string.') raise_objs_not_like_types(node.args,NormExp)
def _get_formula_rename_dict(self, formula, other_formula): rename = {} # Make sure we are given a PresSet or a PresRelation raise_objs_not_like_types(formula, [PresSet, PresRelation]) # Make sure the two sets have the same arity if formula.arity() != other_formula.arity(): raise ValueError("The given formulas differ in arity") if like_type(formula, PresSet): from_vars = formula.tuple_set.vars to_vars = other_formula.tuple_set.vars for i in xrange(len(from_vars)): rename[from_vars[i].id] = to_vars[i].id else: from_vars = formula.tuple_in.vars to_vars = other_formula.tuple_in.vars for i in xrange(len(from_vars)): rename[from_vars[i].id] = to_vars[i].id from_vars = formula.tuple_out.vars to_vars = other_formula.tuple_out.vars for i in xrange(len(from_vars)): rename[from_vars[i].id] = to_vars[i].id return rename
def simplify(obj): from iegen import Set,Relation from iegen.ast import PresSet,PresRelation,VarTuple,Conjunction,Equality,Inequality,VarExp,FuncExp,NormExp from iegen.ast.visitor import SortVisitor raise_objs_not_like_types(obj,[Set,Relation,PresSet,PresRelation,VarTuple,Conjunction,Equality,Inequality,VarExp,FuncExp,NormExp]) #Iteratively apply simplification rules until no rules apply changed_outer=True while changed_outer: changed_outer=False #Iteratively apply simplification rules for each rule group for rule_group in _registered_rules: changed=True while changed: changed=False #Apply each simplification rule in the current rule group for rule,instance in _registered_rules[rule_group]: #Is this a function call? if instance is None: changed=rule(obj) or changed #This is a method call else: changed=rule(instance,obj) or changed changed_outer=changed or changed_outer #Apply a sort just to make sure things are ordered properly SortVisitor().visit(obj)
def _get_prefix_rename_dict(self, formula, prefix): rename = {} # Make sure we are given a PresSet or a PresRelation raise_objs_not_like_types(formula, [PresSet, PresRelation]) if like_type(formula, PresSet): for var in formula.tuple_set.vars: rename[var.id] = prefix + "_" + var.id else: for var in formula.tuple_in.vars: rename[var.id] = prefix + "_in_" + var.id for var in formula.tuple_out.vars: rename[var.id] = prefix + "_out_" + var.id return rename
def _compose(self, r1, r2): # Make sure we are given PresRelations raise_objs_not_like_types([r1, r2], PresRelation) # Make sure the arities are valid if r2.arity_out() != r1.arity_in(): raise ValueError( "Compose failure: Output arity of second relation (%d) does not match input arity of first relation (%d)" % (r2.arity_out(), r1.arity_in()) ) # Copy the given relationsn r1_copy = deepcopy(r1) r2_copy = deepcopy(r2) # Rename tuple variables by appending '1' and '2' self._rename_vars(r1_copy, r1_copy.tuple_in.vars + r1_copy.tuple_out.vars, "1") self._rename_vars(r2_copy, r2_copy.tuple_in.vars + r2_copy.tuple_out.vars, "2") self.print_debug("\n\tinputs after rename:\n\t%s\n\t%s\n" % (r1_copy, r2_copy)) # Create the new relation that will end up being the final result new_tuple_in = deepcopy(r2_copy.tuple_in) new_tuple_out = deepcopy(r1_copy.tuple_out) new_symbolics = deepcopy(r1_copy.symbolics) + deepcopy(r2_copy.symbolics) new_rel = PresRelation(new_tuple_in, new_tuple_out, Conjunction([]), new_symbolics) # Copy over the constraints from the relations self._copy_constraints(new_rel, r1_copy, r2_copy) # Add equality constraints for r2_out = r1_in self._create_equality_constraints(new_rel, r2_copy.tuple_out.vars, r1_copy.tuple_in.vars) self.print_debug("\n\toutput before unrename:\n\t%s\n" % (new_rel)) # Rename the resulting tuple back to the original names if necessary r2_ids = [var.id for var in r2.tuple_in.vars] r2_ids.extend([var.id for var in r2.tuple_out.vars]) r1_ids = [var.id for var in r1.tuple_in.vars] r1_ids.extend([var.id for var in r1.tuple_out.vars]) # Also check if possible. Don't unrename if the relations shared # any variable names. if 0 == len(set(r2_ids).intersection(set(r1_ids))): self._unrename_vars(new_rel, r1.tuple_in.vars + r1.tuple_out.vars, "1") self._unrename_vars(new_rel, r2.tuple_in.vars + r2.tuple_out.vars, "2") return new_rel
def is_const(self,syms=None): from iegen import Symbolic syms=[] if syms is None else syms raise_objs_not_like_types(syms,Symbolic) if not self._has_terms(): return True else: res=True for term in self.terms: term_matches_sym=False for sym in syms: if term.id==sym.name: term_matches_sym=True if not term_matches_sym: res=False return res
def inPresRelation(self,node): from iegen import Symbolic from iegen.ast import VarTuple,Conjunction raise_objs_not_like_types(node.tuple_in,VarTuple) raise_objs_not_like_types(node.tuple_out,VarTuple) raise_objs_not_like_types(node.conjunct,Conjunction) raise_objs_not_like_types(node.symbolics,Symbolic) if None is self.arity: self.arity=node.arity() elif node.arity()!=self.arity: raise ValueError('All relations in a Relation must have the same input and output arity.')
def __init__(self, set_string=None, symbolics=None, sets=None): symbolics = [] if symbolics is None else symbolics if None is not set_string and None is sets: # Ensure we are given Symbolic objects raise_objs_not_like_types( symbolics, Symbolic, "Set construction failure: symbolics must be a collect of objects that look like a Symbolic", ) self.sets = [PresParser.parse_set(set_string, symbolics)] elif None is not sets and None is set_string: if len(symbolics) > 0: raise ValueError("Cannot specify symbolics when specifying a collection of sets.") if len(sets) > 0: self.sets = sets else: raise ValueError("Must specify at least one set in the sets collection.") else: raise ValueError("Set.__init__ takes either a set string or a collection of sets.")
def __init__(self, relation_string=None, symbolics=None, relations=None): symbolics = [] if symbolics is None else symbolics if None is not relation_string and None is relations: # Ensure we are given Symbolic objects raise_objs_not_like_types( symbolics, Symbolic, "Set construction failure: symbolics must be a collect of objects that look like a Symbolic", ) self.relations = [PresParser.parse_relation(relation_string, symbolics)] elif None is not relations and None is relation_string: if len(symbolics) > 0: raise ValueError("Cannot specify symbolics when specifying a collection of relations.") if len(relations) > 0: self.relations = relations else: raise ValueError("Must specify at least one relation in the relations collection") else: raise ValueError("Relation.__init__ takes either a relation string or a collection of relations.")
def inPresSet(self,node): from iegen import Symbolic from iegen.ast import VarTuple,Conjunction raise_objs_not_like_types(node.tuple_set,VarTuple) raise_objs_not_like_types(node.conjunct,Conjunction) raise_objs_not_like_types(node.symbolics,Symbolic) if None is self.arity: self.arity=node.arity() elif node.arity()!=self.arity: raise ValueError('All sets in a Set must have the same arity.')
def inSet(self,node): from iegen.ast import PresSet raise_objs_not_like_types(node.sets,PresSet,True)
def inNormExp(self,node): from iegen.ast import VarExp,FuncExp raise_objs_not_like_types(node.terms,[VarExp,FuncExp]) if type(0)!=type(node.const): raise ValueError('NormExp.const must be an integer.')
def inInequality(self,node): from iegen.ast import VarExp,FuncExp,NormExp raise_objs_not_like_types(node.exp,NormExp)
def inConjunction(self,node): from iegen.ast import Equality,Inequality raise_objs_not_like_types(node.constraints,[Equality,Inequality])
def inVarTuple(self,node): from iegen.ast import VarExp raise_objs_not_like_types(node.vars,VarExp) self.in_var_tuple=True
def inRelation(self,node): from iegen.ast import PresRelation raise_objs_not_like_types(node.relations,PresRelation)