Replaced references to depricated Set and ImmutableSet classes with set and frozenset types

This commit is contained in:
kwikrick 2009-11-17 10:27:29 +00:00
parent 74386c1710
commit fac2609def
7 changed files with 343 additions and 365 deletions

View File

@ -13,16 +13,22 @@ from graph import Graph
from method import Method, MethodGraph
from diagnostic import diag_print
from notify import Notifier
from sets import Set, ImmutableSet
from multimethod import MultiVariable, MultiMethod
from cluster import *
from configuration import Configuration
from gmatch import gmatch
from method import OrMethod
# Basic methods
# -----------------------------------------------------------
# ----------Method classes used by ClusterSolver -------------
# -----------------------------------------------------------
class ClusterMethod(MultiMethod):
"""A derive is a method such that a single ouput cluster is a
subconsraint of a single input cluster."""
"""A method that determines a single output cluster from a ser of input clusters.
Subclasses should ensure that the output cluster satisfies all the constraints
in the input clusters.
"""
def __init__(self):
self.consistent = None
@ -144,33 +150,89 @@ class SelectionMethod(MultiMethod):
def __str__(self):
return "SelectionMethod#%d(%s & %s ->%s)"%(id(self),str(self._inputs[0]), str(self._constraints), str(self._outputs[0]))
# --------------------------------------
# helper functions for pattern matching
# --------------------------------------
def pattern2graph(pattern):
"""convert pattern to pattern graph"""
pgraph = Graph()
pgraph.add_vertex("point")
pgraph.add_vertex("distance")
pgraph.add_vertex("rigid")
pgraph.add_vertex("balloon")
pgraph.add_vertex("hedgehog")
for clpattern in pattern:
(pattype, patname, patvars) = clpattern
pgraph.add_edge(pattype, patname)
for var in patvars:
pgraph.add_edge(patname, var)
if pattype == "hedgehog":
pgraph.add_edge("cvar"+"#"+patname, patvars[0])
pgraph.add_edge(patname, "cvar"+"#"+patname)
#diag_print("pattern graph:"+str(pgraph),"match");
return pgraph
def reference2graph(nlet):
"""convert nlet to reference graph"""
rgraph = Graph()
rgraph.add_vertex("point")
rgraph.add_vertex("distance")
rgraph.add_vertex("rigid")
rgraph.add_vertex("balloon")
rgraph.add_vertex("hedgehog")
for cluster in nlet:
for var in cluster.vars:
rgraph.add_edge(cluster, var)
if isinstance(cluster, Rigid):
rgraph.add_edge("rigid", cluster)
if len(cluster.vars) == 1:
rgraph.add_edge("point", cluster)
elif len(cluster.vars) == 2:
rgraph.add_edge("distance", cluster)
if isinstance(cluster, Balloon):
rgraph.add_edge("balloon", cluster)
if isinstance(cluster, Hedgehog):
rgraph.add_edge("hedgehog", cluster)
rgraph.add_edge("cvar"+"#"+str(id(cluster)), cluster.cvar)
rgraph.add_edge(cluster, "cvar"+"#"+str(id(cluster)))
#diag_print("reference graph:"+str(rgraph),"match");
return rgraph
def rootname(cluster):
return "root#"+str(id(cluster))
def is_information_increasing(method):
infinc = True
connected = Set()
output = method.outputs()[0]
for cluster in method.input_clusters():
if num_constraints(cluster.intersection(output)) >= num_constraints(output):
infinc = False
break
return infinc
# ---------- main class --------------
# --------------------------------------------------
# ---------- ClusterSolver main class --------------
# --------------------------------------------------
class ClusterSolver(Notifier):
"""Constraints are Clusers: Rigids, Hedgehogs and Balloons.
After adding each cluster, the solver tries to merge
clusters, adding new clusters and methods between clusters.
"""
Finds a generic solution for problems formulated by Clusters.
Cluster are added and removed using the add and remove methods.
After adding each Cluster, the solver tries to merge it with
others, resulting in new Clusters.
The generic solution is a directed acyclic graph of Clusters and Methods.
Particilar problems and solutions are represented by a Configuration
for each cluster.
For each Cluster a set of Configurations can be set using the
set method. Configurations are propagated via Methods and can
be retrieved with the get method.
"""
# ------- PUBLIC METHODS --------
def __init__(self, dimension):
def __init__(self, dimension, methodclasses):
"""Create a new empty solver"""
# init superclasses
Notifier.__init__(self)
# store arguments
self.dimension = dimension
self.methodclasses = methodclasses
# init instance vars
self._graph = Graph()
self._graph.add_vertex("_root")
@ -190,6 +252,9 @@ class ClusterSolver(Notifier):
self._mg.set(self._prototype_selection_var, True)
# store map of selection_constraints to SelectionMethod (or None)
self._selection_method = {}
# store root cluster (will be assigned when first cluster added)
self.rootcluster = None
def variables(self):
"""get list of variables"""
@ -251,14 +316,28 @@ class ClusterSolver(Notifier):
"""Return a set of configurations associated with a cluster"""
return self._mg.get(cluster)
def set_root(self, rigid):
"""Make given rigid cluster the root cluster
def set_root(self, cluster):
"""Set root cluster, used for positionig and orienting the solutions"""
diag_print("set root "+str(self.rootcluster), "clsolver")
if self.rootcluster != None:
oldrootvar = rootname(self.rootcluster)
self._mg.set(oldrootvar, False)
newrootvar = rootname(cluster)
self._mg.set(newrootvar, True)
self.rootcluster = cluster
arguments:
cluster: A Rigid
"""
self._graph.rem_vertex("_root")
self._graph.add_edge("_root", rigid)
def get_root(self):
"""returns current root cluster or None"""
return self.rootcluster
##def set_root(self, rigid):
## """Make given rigid cluster the root cluster
##
## arguments:
## cluster: A Rigid
## """
## self._graph.rem_vertex("_root")
## self._graph.add_edge("_root", rigid)
def find_dependend(self, object):
"""Return a list of objects that depend on given object directly."""
@ -354,6 +433,7 @@ class ClusterSolver(Notifier):
self._add_to_group("_variables", var)
def _add_cluster(self, cluster):
# add in appriate way for type
if isinstance(cluster, Rigid):
self._add_rigid(cluster)
elif isinstance(cluster, Hedgehog):
@ -362,6 +442,16 @@ class ClusterSolver(Notifier):
self._add_balloon(cluster)
else:
raise StandardError, "unsupported type", type(cluster)
# add root-variable if needed with default value False
root = rootname(cluster)
if not self._mg.contains(root):
self._mg.add_variable(root, False)
self._mg.set(root, False)
# add root-variable to dependency graph
self._add_dependency(cluster, root)
# if there is no root cluster, this one will be it
if self.get_root() == None:
self.set_root(cluster)
def _add_rigid(self, newcluster):
"""add a rigid cluster if not already in system"""
@ -374,9 +464,6 @@ class ClusterSolver(Notifier):
for var in newcluster.vars:
self._add_variable(var)
self._add_dependency(var, newcluster)
# if there is no root cluster, this one will be it
if len(self._graph.outgoing_vertices("_root")) == 0:
self._graph.add_edge("_root", newcluster)
# add to top level
self._add_top_level(newcluster)
# add to methodgraph
@ -472,9 +559,9 @@ class ClusterSolver(Notifier):
def _add_prototype_selector(self, merge):
incluster = merge.outputs()[0]
constraints = merge.prototype_constraints()
vars = Set()
vars = set()
for con in constraints:
vars.union_update(con.variables())
vars.update(con.variables())
selclusters = []
for var in vars:
clusters = self._graph.outgoing_vertices(var)
@ -562,14 +649,140 @@ class ClusterSolver(Notifier):
#end def
def _search(self, newcluster):
raise StandardError, "Not implemented. ClusterSolver is an abstract class, please use ClusterSolver2D or ClusterSolver3D"
diag_print("search from: "+str(newcluster),"clsolver")
# find all toplevel clusters connected to newcluster via one or more variables
connected = set()
for var in newcluster.vars:
dependend = self.find_dependend(var)
dependend = filter(lambda x: self.is_top_level(x), dependend)
connected.update(dependend)
diag_print("search: connected clusters="+str(connected),"clsolver")
# try applying methods
if self._try_method(connected):
return True
return False
def _try_method(self, nlet):
"""finds a possible rewrite rule applications on given set of clusters, applies it
and returns True iff successfull
"""
refgraph = reference2graph(nlet)
for methodclass in self.methodclasses:
matches = gmatch(methodclass.patterngraph, refgraph)
if len(matches) > 0:
diag_print("number of matches = "+str(len(matches)), "clsolver")
for s in matches:
# diag_print("try match: "+str(s),"clsolver")
method = apply(methodclass, [s])
succes = self._add_method_complete(method)
if succes:
#raw_input()
#print "press key"
return True
# end for match
# end for method
return False
def _add_method_complete(self, merge):
# diag_print("add_method_complete "+str(merge), "clsolver")
# check that method has one output
if len(merge.outputs()) != 1:
raise StandardError, "merge number of outputs != 1"
output = merge.outputs()[0]
# check that the method is information increasing (infinc)
infinc = True
connected = set()
for var in output.vars:
dependend = self.find_dependend(var)
dependend = filter(lambda x: self.is_top_level(x), dependend)
connected.update(dependend)
#for cluster in merge.input_clusters():
# if cluster in connected:
# connected.remove(cluster)
# NOTE 07-11-2007 (while writing the paper): this implementation of information increasing may not be correct. We may need to check that the total sum of the information in the overlapping clusters is equal to the information in the output.
for cluster in connected:
if num_constraints(cluster.intersection(output)) >= num_constraints(output):
infinc = False
break
diag_print("information increasing:"+str(infinc),"clsolver")
# check if method reduces number of clusters (reduc)
nremove = 0
for cluster in merge.input_clusters():
if num_constraints(cluster.intersection(output)) >= num_constraints(cluster):
# will be removed from toplevel
nremove += 1
reduc = (nremove > 1)
diag_print("reduce # clusters:"+str(reduc),"clsolver")
# check if the method is redundant
if not infinc and not reduc:
diag_print("method is redundant","clsolver")
return False
# check consistency and local/global overconstrained
consistent = True
local_oc = False
for i1 in range(0, len(merge.input_clusters())):
for i2 in range(i1+1, len(merge.input_clusters())):
c1 = merge.input_clusters()[i1]
c2 = merge.input_clusters()[i2]
if num_constraints(c1.intersection(c2)) != 0:
local_oc = True
consistent = consistent and self._is_consistent_pair(c1, c2)
merge.consistent = consistent
merge.overconstrained = local_oc
# global overconstrained? (store in output cluster)
overconstrained = not consistent
for cluster in merge.input_clusters():
overconstrained = overconstrained or cluster.overconstrained
output.overconstrained = overconstrained
# add to graph
self._add_cluster(output)
self._add_method(merge)
# remove input clusters from top_level
merge.restore_toplevel = [] # make restore list in method
for cluster in merge.input_clusters():
# do not remove rigids from toplevel if method does not consider root
if isinstance(cluster, Rigid):
if hasattr(merge,"noremove") and merge.noremove == True:
continue
# remove input clusters when all its constraints are in output cluster
if num_constraints(cluster.intersection(output)) >= num_constraints(cluster):
diag_print("remove from top-level: "+str(cluster),"clsolver")
self._rem_top_level(cluster)
merge.restore_toplevel.append(cluster)
else:
diag_print("keep top-level: "+str(cluster),"clsolver")
# add method to determine root-variable
self._add_root_method(merge.input_clusters(),merge.outputs()[0])
# add solution selection methods
output2 = self._add_prototype_selector(merge)
output3 = self._add_solution_selector(output2)
return True
def _add_root_method(self,inclusters,outcluster):
inroots = []
for cluster in inclusters:
inroots.append(rootname(cluster))
outroot = rootname(outcluster)
method = OrMethod(inroots, outroot)
# add method
self._add_method(method)
# make sure its deleted when cluster is deleted
self._add_dependency(outcluster, method)
# -- removing objects
def _remove(self, object):
# find all indirectly dependend objects
todelete = [object]+self._find_descendend(object)
torestore = Set()
torestore = set()
# remove all objects
for item in todelete:
# if merge removed items from toplevel then add them back to top level
@ -605,38 +818,36 @@ class ClusterSolver(Notifier):
self._process_new()
# --- root selection
def _contains_root(self, input_cluster):
"""returns True iff input_cluster is root cluster or was determined by
merging with the root cluster."""
# start from root cluster. Follow merges upwards until:
# - input cluster found -> True
# - no more merges -> False
if len(self._graph.outgoing_vertices("_root")) > 1:
raise StandardError, "more than one root cluster"
if len(self._graph.outgoing_vertices("_root")) == 1:
cluster = self._graph.outgoing_vertices("_root")[0]
else:
cluster = None
while (cluster != None):
if cluster is input_cluster:
return True
fr = self._graph.outgoing_vertices(cluster)
me = filter(lambda x: isinstance(x, Merge), fr)
me = filter(lambda x: cluster in x.outputs(), me)
if len(me) > 1:
raise StandardError, "root cluster merged more than once"
elif len(me) == 0:
cluster = None
elif len(me[0].outputs()) != 1:
raise StandardError, "a merge with number of outputs != 1"
else:
cluster = me[0].outputs()[0]
#while
return False
##def _contains_root(self, input_cluster):
## """returns True iff input_cluster is root cluster or was determined by
## merging with the root cluster."""
##
## # start from root cluster. Follow merges upwards until:
## # - input cluster found -> True
## # - no more merges -> False
##
## if len(self._graph.outgoing_vertices("_root")) > 1:
## raise StandardError, "more than one root cluster"
## if len(self._graph.outgoing_vertices("_root")) == 1:
## cluster = self._graph.outgoing_vertices("_root")[0]
## else:
## cluster = None
## while (cluster != None):
## if cluster is input_cluster:
## return True
## fr = self._graph.outgoing_vertices(cluster)
## me = filter(lambda x: isinstance(x, Merge), fr)
## me = filter(lambda x: cluster in x.outputs(), me)
## if len(me) > 1:
## raise StandardError, "root cluster merged more than once"
## elif len(me) == 0:
## cluster = None
## elif len(me[0].outputs()) != 1:
## raise StandardError, "a merge with number of outputs != 1"
## else:
## cluster = me[0].outputs()[0]
## #while
## return False
#def
# ---- consistency
@ -848,7 +1059,7 @@ class ClusterSolver(Notifier):
## dependend.append(obj)
## candidates = filter(lambda x: self._contains_distance(x, distance), dependend)
## # determine sources, i.e. clusters created from clusters that do not contain the distance
## sources = Set()
## sources = set()
## for c1 in candidates:
## methods = filter(lambda v: isinstance(v, Method), self._graph.ingoing_vertices(c1))
## if len(methods) == 0:
@ -868,7 +1079,7 @@ class ClusterSolver(Notifier):
## for source in sources:
## diag_print(str(source), "clsolver")
## # filter sources for dependencies
## #unfiltered = Set(sources)
## #unfiltered = set(sources)
## #for s1 in unfiltered:
## # if s1 not in sources: continue
## # descendants = self._find_descendants(s1)
@ -889,7 +1100,7 @@ class ClusterSolver(Notifier):
## dependend.append(obj)
## candidates = filter(lambda x: self._contains_angle(x, angle), dependend)
## # determine sources, i.e. clusters created from clusters that do not contain the angle
## sources = Set()
## sources = set()
## for c1 in candidates:
## methods = filter(lambda v: isinstance(v, Method), self._graph.ingoing_vertices(c1))
## if len(methods) == 0:
@ -912,8 +1123,8 @@ class ClusterSolver(Notifier):
##def _roots(self,object):
## front = [object]
## result = Set()
## done = Set()
## result = set()
## done = set()
## while len(front) > 0:
## x = front.pop()
## if x not in done:
@ -930,14 +1141,14 @@ class ClusterSolver(Notifier):
##def _all_sources_constraint_in_cluster(self, constraint, cluster):
## if not self._contains_constraint(cluster, constraint):
## return Set()
## return set()
## elif self._is_atomic(cluster):
## return Set([cluster])
## return set([cluster])
## else:
## method = self._determining_method(cluster)
## sources = Set()
## sources = set()
## for inp in method.input_clusters():
## sources.union_update(self._all_sources_constraint_in_cluster(constraint, inp))
## sources.update(self._all_sources_constraint_in_cluster(constraint, inp))
## return sources
# class ClusterSolver

View File

@ -1,251 +1,21 @@
"""A generic 3D geometric constraint solver"""
from clsolver import *
from sets import Set
from diagnostic import diag_print, diag_select
from selconstr import *
from intersections import *
from configuration import Configuration
from cluster import *
from map import Map
from gmatch import gmatch
from method import OrMethod
def pattern2graph(pattern):
"""convert pattern to pattern graph"""
pgraph = Graph()
pgraph.add_vertex("point")
pgraph.add_vertex("distance")
pgraph.add_vertex("rigid")
pgraph.add_vertex("balloon")
pgraph.add_vertex("hedgehog")
for clpattern in pattern:
(pattype, patname, patvars) = clpattern
pgraph.add_edge(pattype, patname)
for var in patvars:
pgraph.add_edge(patname, var)
if pattype == "hedgehog":
pgraph.add_edge("cvar"+"#"+patname, patvars[0])
pgraph.add_edge(patname, "cvar"+"#"+patname)
#diag_print("pattern graph:"+str(pgraph),"match");
return pgraph
def reference2graph(nlet):
"""convert nlet to reference graph"""
rgraph = Graph()
rgraph.add_vertex("point")
rgraph.add_vertex("distance")
rgraph.add_vertex("rigid")
rgraph.add_vertex("balloon")
rgraph.add_vertex("hedgehog")
for cluster in nlet:
for var in cluster.vars:
rgraph.add_edge(cluster, var)
if isinstance(cluster, Rigid):
rgraph.add_edge("rigid", cluster)
if len(cluster.vars) == 1:
rgraph.add_edge("point", cluster)
elif len(cluster.vars) == 2:
rgraph.add_edge("distance", cluster)
if isinstance(cluster, Balloon):
rgraph.add_edge("balloon", cluster)
if isinstance(cluster, Hedgehog):
rgraph.add_edge("hedgehog", cluster)
rgraph.add_edge("cvar"+"#"+str(id(cluster)), cluster.cvar)
rgraph.add_edge(cluster, "cvar"+"#"+str(id(cluster)))
#diag_print("reference graph:"+str(rgraph),"match");
return rgraph
def rootname(cluster):
return "root#"+str(id(cluster))
class ClusterSolver3D(ClusterSolver):
"""A generic 3D geometric constraint solver.
Finds a generic solution for problems formulated by cluster-constraints.
Constraints are Clusers: Rigids, Hedgehogs and Balloons.
Cluster are added and removed using the add and remove methods.
After adding each Cluster, the solver tries to merge it with
other clusters, resulting in new Clusters and Methods.
The generic solution is a directed acyclic graph of Clusters and Methods.
Particilar problems and solutions are represented by a Configuration
for each cluster.
For each Cluster a set of Configurations can be set using the
set method. Configurations are propagated via Methods and can
be retrieved with the get method.
"""
# ------- PUBLIC METHODS --------
"""A generic 3D geometric constraint solver. See ClusterSolver for details."""
# ------- PUBLIC METHODS --------
def __init__(self):
"""Instantiate a ClusterSolver3D"""
ClusterSolver.__init__(self, 3)
self.rootcluster = None
ClusterSolver.__init__(self, 3, [MergePR, MergeDR, MergeRR, MergeSR, DeriveTTD, DeriveDDD, DeriveADD, DeriveDAD, DeriveAA])
# overriding ClusterSolver.set_root
def set_root(self, cluster):
"""Set root cluster, used for positionig and orienting the solutions"""
diag_print("set root "+str(self.rootcluster), "clsolver3D")
if self.rootcluster != None:
oldrootvar = rootname(self.rootcluster)
self._mg.set(oldrootvar, False)
newrootvar = rootname(cluster)
self._mg.set(newrootvar, True)
self.rootcluster = cluster
# ------------ INTERNALLY USED METHODS --------
# --------------
# search methods
# --------------
def _search(self, newcluster):
diag_print("search from: "+str(newcluster),"clsolver3D")
# find all toplevel clusters connected to newcluster via one or more variables
connected = Set()
for var in newcluster.vars:
dependend = self.find_dependend(var)
dependend = filter(lambda x: self.is_top_level(x), dependend)
connected.union_update(dependend)
diag_print("search: connected clusters="+str(connected),"clsolver3D")
# try applying methods
if self._try_method(connected):
return True
return False
def _try_method(self, nlet):
"""finds a possible rewrite rule applications on given set of clusters, applies it
and returns True iff successfull
"""
refgraph = reference2graph(nlet)
for methodclass in [MergePR, MergeDR, MergeRR, MergeSR, DeriveTTD, DeriveDDD, DeriveADD, DeriveDAD, DeriveAA]:
matches = gmatch(methodclass.patterngraph, refgraph)
if len(matches) > 0:
diag_print("number of matches = "+str(len(matches)), "clsolver3D")
for s in matches:
# diag_print("try match: "+str(s),"clsolver3D")
method = apply(methodclass, [s])
succes = self._add_method_complete(method)
if succes:
#raw_input()
#print "press key"
return True
# end for match
# end for method
return False
def _add_method_complete(self, merge):
# diag_print("add_method_complete "+str(merge), "clsolver3D")
# check that method has one output
if len(merge.outputs()) != 1:
raise StandardError, "merge number of outputs != 1"
output = merge.outputs()[0]
# check that the method is information increasing (infinc)
infinc = True
connected = Set()
for var in output.vars:
dependend = self.find_dependend(var)
dependend = filter(lambda x: self.is_top_level(x), dependend)
connected.union_update(dependend)
#for cluster in merge.input_clusters():
# if cluster in connected:
# connected.remove(cluster)
# NOTE 07-11-2007 (while writing the paper): this implementation of information increasing may not be correct. We may need to check that the total sum of the information in the overlapping clusters is equal to the information in the output.
for cluster in connected:
if num_constraints(cluster.intersection(output)) >= num_constraints(output):
infinc = False
break
diag_print("information increasing:"+str(infinc),"clsolver3D")
# check if method reduces number of clusters (reduc)
nremove = 0
for cluster in merge.input_clusters():
if num_constraints(cluster.intersection(output)) >= num_constraints(cluster):
# will be removed from toplevel
nremove += 1
reduc = (nremove > 1)
diag_print("reduce # clusters:"+str(reduc),"clsolver3D")
# check if the method is redundant
if not infinc and not reduc:
diag_print("method is redundant","clsolver3D")
return False
# check consistency and local/global overconstrained
consistent = True
local_oc = False
for i1 in range(0, len(merge.input_clusters())):
for i2 in range(i1+1, len(merge.input_clusters())):
c1 = merge.input_clusters()[i1]
c2 = merge.input_clusters()[i2]
if num_constraints(c1.intersection(c2)) != 0:
local_oc = True
consistent = consistent and self._is_consistent_pair(c1, c2)
merge.consistent = consistent
merge.overconstrained = local_oc
# global overconstrained? (store in output cluster)
overconstrained = not consistent
for cluster in merge.input_clusters():
overconstrained = overconstrained or cluster.overconstrained
output.overconstrained = overconstrained
# add to graph
self._add_cluster(output)
self._add_method(merge)
# remove input clusters from top_level
merge.restore_toplevel = [] # make restore list in method
for cluster in merge.input_clusters():
# do not remove rigids from toplevel if method does not consider root
if isinstance(cluster, Rigid):
if hasattr(merge,"noremove") and merge.noremove == True:
continue
# remove input clusters when all its constraints are in output cluster
if num_constraints(cluster.intersection(output)) >= num_constraints(cluster):
diag_print("remove from top-level: "+str(cluster),"clsolver3D")
self._rem_top_level(cluster)
merge.restore_toplevel.append(cluster)
else:
diag_print("keep top-level: "+str(cluster),"clsolver3D")
# add method to determine root-variable
self._add_root_method(merge.input_clusters(),merge.outputs()[0])
# add solution selection methods
output2 = self._add_prototype_selector(merge)
output3 = self._add_solution_selector(output2)
return True
def _add_root_method(self,inclusters,outcluster):
inroots = []
for cluster in inclusters:
inroots.append(rootname(cluster))
outroot = rootname(outcluster)
method = OrMethod(inroots, outroot)
# add method
self._add_method(method)
# make sure its deleted when cluster is deleted
self._add_dependency(outcluster, method)
# overriding superclass function
def _add_cluster(self, cluster):
# call superclass function
ClusterSolver._add_cluster(self, cluster)
# add root-variable if needed with default value False
root = rootname(cluster)
if not self._mg.contains(root):
self._mg.add_variable(root, False)
self._mg.set(root, False)
# add root-variable to dependency graph
self._add_dependency(cluster, root)
# class ClusterSolver3D
# ----------------------------------------------
# ---------- Methods for 3D solving -------------
@ -261,7 +31,7 @@ class MergePR(ClusterMethod):
in1 = map["$p"]
in2 = map["$r"]
# create ouput
outvars = Set(in1.vars).union(in2.vars)
outvars = set(in1.vars).union(in2.vars)
out = Rigid(outvars)
# set method properties
in1root = rootname(in1)
@ -304,7 +74,7 @@ class MergeDR(ClusterMethod):
in1 = map["$d"]
in2 = map["$r"]
# create ouput
outvars = Set(in1.vars).union(in2.vars)
outvars = set(in1.vars).union(in2.vars)
out = Rigid(outvars)
# set method properties
in1root = rootname(in1)
@ -347,7 +117,7 @@ class MergeRR(ClusterMethod):
in1 = map["$r1"]
in2 = map["$r2"]
# create output
out = Rigid(Set(in1.vars).union(in2.vars))
out = Rigid(set(in1.vars).union(in2.vars))
# set method parameters
in1root = rootname(in1)
in2root = rootname(in2)
@ -636,7 +406,7 @@ class MergeSR(ClusterMethod):
in1 = map["$r"]
in2 = map["$s"]
# create output
out = Rigid(Set(in2.vars))
out = Rigid(set(in2.vars))
# set method parameters
self._inputs = [in1, in2]
self._outputs = [out]

View File

@ -1,7 +1,6 @@
"""Clusters are generalised constraints on sets of points in R^n. Cluster
types are Rigids, Hedgehogs and Balloons. """
from sets import Set, ImmutableSet
from multimethod import MultiVariable
class Distance:
@ -23,11 +22,11 @@ class Distance:
+str(self.vars[1])+")"
def __hash__(self):
return hash(ImmutableSet(self.vars))
return hash(frozenset(self.vars))
def __eq__(self, other):
if isinstance(other, Distance):
return ImmutableSet(self.vars) == ImmutableSet(other.vars)
return frozenset(self.vars) == frozenset(other.vars)
else:
return False
@ -47,13 +46,13 @@ class Angle:
def __eq__(self, other):
if isinstance(other, Angle):
return self.vars[2] == other.vars[2] and ImmutableSet(self.vars) == ImmutableSet(other.vars)
return self.vars[2] == other.vars[2] and frozenset(self.vars) == frozenset(other.vars)
else:
return False
def __hash__(self):
return hash(ImmutableSet(self.vars))
return hash(frozenset(self.vars))
def __str__(self):
return "ang("\
@ -72,7 +71,7 @@ class Cluster(MultiVariable):
self.creationtime = Cluster.staticcounter
def intersection(self, other):
shared = Set(self.vars).intersection(other.vars)
shared = set(self.vars).intersection(other.vars)
# note, a one point cluster is never returned
#because it is not a constraint
if len(shared) < 2:
@ -89,7 +88,7 @@ class Cluster(MultiVariable):
else:
return None
elif isinstance(other, Hedgehog):
xvars = Set(shared) - Set([other.cvar])
xvars = set(shared) - set([other.cvar])
if other.cvar in self.vars and len(xvars) >= 2:
return Hedgehog(other.cvar,xvars)
else:
@ -101,20 +100,20 @@ class Cluster(MultiVariable):
else:
return None
elif isinstance(other, Hedgehog):
xvars = Set(shared) - Set([other.cvar])
xvars = set(shared) - set([other.cvar])
if other.cvar in self.vars and len(xvars) >= 2:
return Hedgehog(other.cvar,xvars)
else:
return None
elif isinstance(self, Hedgehog):
if isinstance(other, Rigid) or isinstance(other, Balloon):
xvars = Set(shared) - Set([self.cvar])
xvars = set(shared) - set([self.cvar])
if self.cvar in other.vars and len(xvars) >= 2:
return Hedgehog(self.cvar,xvars)
else:
return None
elif isinstance(other, Hedgehog):
xvars = Set(self.xvars).intersection(other.xvars)
xvars = set(self.xvars).intersection(other.xvars)
if self.cvar == other.cvar and len(xvars) >= 2:
return Hedgehog(self.cvar,xvars)
else:
@ -134,7 +133,7 @@ class Rigid(Cluster):
vars - list of variables
"""
Cluster.__init__(self)
self.vars = ImmutableSet(vars)
self.vars = frozenset(vars)
self.overconstrained = False
def __str__(self):
@ -165,7 +164,7 @@ class Hedgehog(Cluster):
self.cvar = cvar
if len(xvars) < 2:
raise StandardError, "hedgehog must have at least three variables"
self.xvars = ImmutableSet(xvars)
self.xvars = frozenset(xvars)
self.vars = self.xvars.union([self.cvar])
self.overconstrained = False
@ -194,7 +193,7 @@ class Balloon(Cluster):
Cluster.__init__(self)
if len(variables) < 3:
raise StandardError, "balloon must have at least three variables"
self.vars = ImmutableSet(variables)
self.vars = frozenset(variables)
self.overconstrained = False
def __str__(self):
@ -240,10 +239,10 @@ def over_angles(c1, c2):
def over_distances(c1, c2):
"""determine set of distances in c1 and c2"""
if not (isinstance(c1, Rigid) and isinstance(c2, Rigid)):
return Set()
return set()
else:
shared = list(Set(c1.vars).intersection(c2.vars))
overdists = Set()
shared = list(set(c1.vars).intersection(c2.vars))
overdists = set()
for i in range(len(shared)):
for j in range(i):
v1 = shared[i]
@ -253,10 +252,10 @@ def over_distances(c1, c2):
def over_angles_hh(hog1, hog2):
# determine duplicate angles
shared = list(Set(hog1.xvars).intersection(hog2.xvars))
shared = list(set(hog1.xvars).intersection(hog2.xvars))
if not hog1.cvar == hog2.cvar:
return Set()
overangles = Set()
return set()
overangles = set()
for i in range(len(shared)):
for j in range(i):
v1 = shared[i]
@ -266,8 +265,8 @@ def over_angles_hh(hog1, hog2):
def over_angles_bb(b1, b2):
# determine duplicate angles
shared = list(Set(b1.vars).intersection(b2.vars))
overangles = Set()
shared = list(set(b1.vars).intersection(b2.vars))
overangles = set()
for i in range(len(shared)):
for j in range(i+1, len(shared)):
for k in range(j+1, len(shared)):
@ -282,8 +281,8 @@ def over_angles_bb(b1, b2):
def over_angles_cb(cluster, balloon):
# determine duplicate angles
# note: identical to over_angles_bb and (non-existent) over_angles_cc
shared = list(Set(cluster.vars).intersection(balloon.vars))
overangles = Set()
shared = list(set(cluster.vars).intersection(balloon.vars))
overangles = set()
for i in range(len(shared)):
for j in range(i+1, len(shared)):
for k in range(j+1, len(shared)):
@ -297,10 +296,10 @@ def over_angles_cb(cluster, balloon):
def over_angles_bh(balloon, hog):
# determine duplicate angles
shared = list(Set(balloon.vars).intersection(hog.xvars))
shared = list(set(balloon.vars).intersection(hog.xvars))
if hog.cvar not in balloon.vars:
return Set()
overangles = Set()
return set()
overangles = set()
for i in range(len(shared)):
for j in range(i+1,len(shared)):
v1 = shared[i]
@ -310,10 +309,10 @@ def over_angles_bh(balloon, hog):
def over_angles_ch(cluster, hog):
# determine duplicate angles
shared = list(Set(cluster.vars).intersection(hog.xvars))
shared = list(set(cluster.vars).intersection(hog.xvars))
if hog.cvar not in cluster.vars:
return Set()
overangles = Set()
return set()
overangles = set()
for i in range(len(shared)):
for j in range(i+1,len(shared)):
v1 = shared[i]

View File

@ -2,7 +2,6 @@
A configuration is a set of named points with coordinates."""
from sets import Set
from matfunc import Vec, Mat
from intersections import *
from tolerance import *
@ -113,7 +112,7 @@ class Configuration:
def _merge_transform_2D(self, other):
"""returns a new configurations which is this one plus the given other configuration transformed, such that common points will overlap (if possible)."""
shared = Set(self.vars()).intersection(other.vars())
shared = set(self.vars()).intersection(other.vars())
underconstrained = self.underconstrained or other.underconstrained
if len(shared) == 0:
underconstrained = True
@ -152,7 +151,7 @@ class Configuration:
def merge_scale_2D(self, other, vars=[]):
"""returns a new configurations which is this one plus the given other configuration transformed, such that common points will overlap (if possible)."""
if len(vars) == 0:
shared = Set(self.vars()).intersection(other.vars())
shared = set(self.vars()).intersection(other.vars())
else:
shared = vars
underconstrained = self.underconstrained or other.underconstrained
@ -186,7 +185,7 @@ class Configuration:
"""returns a matrix for a rigid transformation
such that points in other are mapped onto points in self
"""
shared = Set(self.vars()).intersection(other.vars())
shared = set(self.vars()).intersection(other.vars())
underconstrained = self.underconstrained or other.underconstrained
if len(shared) == 0:
underconstrained = True
@ -253,7 +252,7 @@ class Configuration:
return t
def _merge_scale_transform_3D(self, other):
shared = Set(self.vars()).intersection(other.vars())
shared = set(self.vars()).intersection(other.vars())
if len(shared) == 0:
return self._merge_transform_3D(other)
elif len(shared) == 1:

View File

@ -41,7 +41,7 @@ def gmatch(pattern, reference):
outmatches = []
for n in onumbers:
outmatches += reference.outfan(n)
matches = Set(inmatches).intersection(outmatches)
matches = set(inmatches).intersection(outmatches)
newsolutions = []
if solutions == None:
for refvar in matches:

View File

@ -31,7 +31,6 @@ Copyright Rick van der Meiden - 2003, 2004, 2005
"""
import random
from sets import Set,ImmutableSet
from notify import Notifier
class Graph (Notifier):
@ -199,9 +198,8 @@ class Graph (Notifier):
def adjacent_vertices(self, v):
"""list of adjacent (ingoing or outgoing) vertices"""
from sets import Set
iset = Set(self.ingoing_vertices(v))
oset = Set(self.outgoing_vertices(v))
iset = set(self.ingoing_vertices(v))
oset = set(self.outgoing_vertices(v))
vset = iset.union(oset)
return list(vset)
@ -300,11 +298,11 @@ class Graph (Notifier):
def connected_subsets(self):
"""returns a set of (undirectionally) connected subsets of vertices"""
todo = Set(self.vertices())
subsets = Set()
todo = set(self.vertices())
subsets = set()
while (todo):
v = todo.pop()
s = Set(self.connected(v))
s = set(self.connected(v))
for x in s:
todo.remove(x)
s.add(v)
@ -324,13 +322,13 @@ class Graph (Notifier):
graph = Graph()
for edge in self.edges():
(v1,v2) = edge
g1 = ImmutableSet([v1])
g2 = ImmutableSet([v2])
g1 = frozenset([v1])
g2 = frozenset([v2])
graph.add_edge(g1,g2)
# Stoer/Wagner algorithm
mincutvalue = None
mincut = ImmutableSet()
mincut = frozenset()
while len(graph.vertices()) > 1:
(phasecut,phasecutvalue) = self._mincutphase(graph)
if mincutvalue == None or phasecutvalue < mincutvalue:
@ -339,8 +337,8 @@ class Graph (Notifier):
# rewrite output
g1 = mincut
g2 = ImmutableSet(self.vertices()).difference(g1)
edges = Set()
g2 = frozenset(self.vertices()).difference(g1)
edges = set()
for v in g1:
for k in self.adjacent_vertices(v):
if k in g2:
@ -356,7 +354,7 @@ class Graph (Notifier):
if self.has_edge(k,v):
edges.add((k,v))
return (mincutvalue, ImmutableSet(edges), g1, g2)
return (mincutvalue, frozenset(edges), g1, g2)
def _mincutphase(self, graph):
# returns the last vertex (group) added and the cut value

View File

@ -1,7 +1,6 @@
"""Base classes for multi-valued assignments in methodgraphs"""
from method import Method, MethodGraph
from sets import Set
class MultiVariable:
"""For representing multi-valued variables
@ -34,6 +33,8 @@ class MultiMethod(Method):
The 'multi_execute' method must return a list of possible values for the output variable.
The output values returned by subsequent calls multi-execute are collected and stored in the
output MultiVariable.
Note that a set of values for the outputvariable is stored, so that equivalent values are only stored once.
"""
def __init__(self):
@ -65,10 +66,10 @@ class MultiMethod(Method):
if len(multi_inputs) > 0:
mvar = multi_inputs[0]
values = inmap[mvar]
output = Set()
output = set()
for value in values:
base_inmap[mvar] = value
output.union_update(self._recurse_execute(inmap, base_inmap, multi_inputs[1:]))
output.update(self._recurse_execute(inmap, base_inmap, multi_inputs[1:]))
return output
else:
return self.multi_execute(base_inmap)