clsolver now removes point varbles with no dependend clusters

This commit is contained in:
kwikrick 2012-08-24 12:57:26 +00:00
parent 6b26a009f1
commit 53d95d4a34
3 changed files with 28 additions and 27 deletions

View File

@ -574,8 +574,13 @@ class ClusterSolver(Notifier):
if isinstance(item, SelectionMethod): if isinstance(item, SelectionMethod):
for con in item.iter_constraints(): for con in item.iter_constraints():
self._selection_method[con] = None self._selection_method[con] = None
elif isinstance(item, MultiVariable): if isinstance(item, MultiVariable):
self._mg.rem_variable(item) self._mg.rem_variable(item)
# remove variables with no dependent clusters
if isinstance(item, Cluster):
for var in item.vars:
if len(self.find_dependend(var)) == 0:
self._graph.remove(var)
# notify listeners # notify listeners
self.send_notify(("remove", item)) self.send_notify(("remove", item))
# restore toplevel (also added to _new) # restore toplevel (also added to _new)

View File

@ -291,15 +291,21 @@ class GeometricSolver (Listener):
Listener.__init__(self) Listener.__init__(self)
# init variables # init variables
# the problem on which this solver works
self.problem = problem self.problem = problem
# shortcut to the dimension of the problem
self.dimension = problem.dimension self.dimension = problem.dimension
self.cg = problem.cg # shortcut to the constraint graph of the problem
self.cg = problem.cg
# the cluster-solver (or dr for decomposition-recombination)
if self.problem.dimension == 2: if self.problem.dimension == 2:
self.dr = ClusterSolver2D() self.dr = ClusterSolver2D()
elif self.problem.dimension == 3: elif self.problem.dimension == 3:
self.dr = ClusterSolver3D() self.dr = ClusterSolver3D()
else: else:
raise StandardError, "Sorry, can't solve problems of dimension < 2 or > 3." raise StandardError, "Sorry, can't solve problems of dimension < 2 or > 3."
# a map from problem variables and constraints to clusters, and vice versa
self._map = {} self._map = {}
# enable prototype based selection by default # enable prototype based selection by default
@ -341,10 +347,14 @@ class GeometricSolver (Listener):
return self.get_status() return self.get_status()
def get_result(self): def get_result(self):
"""Depricated. Use get_cluster instead.""" """Depricated. Use get_decomposition."""
return self.get_cluster() return self.get_decomposition()
def get_cluster(self): def get_cluster(self):
"""Depricated. Use get_decomposition."""
return self.get_decomposition()
def get_decomposition(self):
"""Returns a GeometricDecomposition (the root of a tree of clusters), """Returns a GeometricDecomposition (the root of a tree of clusters),
describing the solutions and the decomposition of the problem.""" describing the solutions and the decomposition of the problem."""
# several drcluster can maps to a single geoclusters # several drcluster can maps to a single geoclusters
@ -426,7 +436,7 @@ class GeometricSolver (Listener):
def get_solutions(self): def get_solutions(self):
"""Returns a list of Configurations, which will be empty if the """Returns a list of Configurations, which will be empty if the
problem has no solutions. Note: this method is problem has no solutions. Note: this method is
cheaper but less informative than get_cluster. The cheaper but less informative than get_decomposition. The
list and the configurations should not be changed (since they are list and the configurations should not be changed (since they are
references to objects in the solver).""" references to objects in the solver)."""
rigids = filter(lambda c: isinstance(c, Rigid), self.dr.top_level()) rigids = filter(lambda c: isinstance(c, Rigid), self.dr.top_level())
@ -444,7 +454,7 @@ class GeometricSolver (Listener):
GeometricDecomposition.EMPTY, GeometricDecomposition.EMPTY,
GeometricDecomposition.I_OVER, GeometricDecomposition.I_OVER,
GeometricDecomposition.I_UNDER. GeometricDecomposition.I_UNDER.
Note: this method is cheaper but less informative than get_cluster. Note: this method is cheaper but less informative than get_decomposition.
""" """
rigids = filter(lambda c: isinstance(c, Rigid), self.dr.top_level()) rigids = filter(lambda c: isinstance(c, Rigid), self.dr.top_level())
if len(rigids) == 0: if len(rigids) == 0:
@ -502,7 +512,7 @@ class GeometricSolver (Listener):
else: else:
raise StandardError, "message from unknown source"+str((object, message)) raise StandardError, "message from unknown source"+str((object, message))
# internal methods # --------------- internal methods ------------------
def _set_prototype_selection(self, enabled): def _set_prototype_selection(self, enabled):
"""Enable (True) or disable (False) use of prototype for solution selection""" """Enable (True) or disable (False) use of prototype for solution selection"""
@ -526,11 +536,12 @@ class GeometricSolver (Listener):
self._map[rigid] = var self._map[rigid] = var
self.dr.add(rigid) self.dr.add(rigid)
self._update_variable(var) self._update_variable(var)
def _rem_variable(self, var): def _rem_variable(self, var):
diag_print("GeometricSolver._rem_variable","gcs") diag_print("GeometricSolver._rem_variable","gcs")
if var in self._map: if var in self._map:
self.dr.remove(self._map[var]) self.dr.remove(self._map[var])
# Note: CLSolver automatically removes variables with no dependent clusters
del self._map[var] del self._map[var]
def _add_constraint(self, con): def _add_constraint(self, con):

View File

@ -15,6 +15,7 @@ from time import time
# create statistics for solving time # create statistics for solving time
def stats_solving(minsize, maxsize, repeats): def stats_solving(minsize, maxsize, repeats):
print "times for solving problems from scratch"
print "size \t # \t time \t result" print "size \t # \t time \t result"
for size in range(minsize,maxsize+1): for size in range(minsize,maxsize+1):
for i in range(1,repeats+1): for i in range(1,repeats+1):
@ -29,6 +30,7 @@ def stats_solving(minsize, maxsize, repeats):
# create statistics for incremental solving time # create statistics for incremental solving time
def stats_incremental(minsize, maxsize, repeats): def stats_incremental(minsize, maxsize, repeats):
#diag_select("clsolver.remove") #diag_select("clsolver.remove")
print "times for incremental re-solving (one constraint removed and re-added)"
print "size \t # \t time \t result" print "size \t # \t time \t result"
for size in range(minsize,maxsize+1): for size in range(minsize,maxsize+1):
for i in range(1,repeats+1): for i in range(1,repeats+1):
@ -43,26 +45,10 @@ def stats_incremental(minsize, maxsize, repeats):
t = t2-t1 t = t2-t1
print size,"\t",i,"\t",t,"\t",result print size,"\t",i,"\t",t,"\t",result
# create statistics for parametric change
def stats_parametric_incremental(minsize, maxsize, repeats):
#diag_select("clsolver.remove")
print "size \t # \t time \t result"
for size in range(minsize,maxsize+1):
for i in range(1,repeats+1):
problem = random_triangular_problem_3D(size,10.0,0.0,0.0)
solver = GeometricSolver(problem)
constraint = random.choice(problem.cg.constraints())
t1 = time()
problem.rem_constraint(constraint)
problem.add_constraint(constraint)
result = solver.get_status()
t2 = time()
t = t2-t1
print size,"\t",i,"\t",t,"\t",result
# create statistics for parametric change # create statistics for parametric change
def stats_parametric(minsize, maxsize, repeats): def stats_parametric(minsize, maxsize, repeats):
#diag_select("clsolver.remove") #diag_select("clsolver.remove")
print "times for parameteric updates (one constraint parameter)"
print "size \t # \t time \t result" print "size \t # \t time \t result"
for size in range(minsize,maxsize+1): for size in range(minsize,maxsize+1):
for i in range(1,repeats+1): for i in range(1,repeats+1):
@ -82,7 +68,6 @@ def runstats():
repeats = 1 repeats = 1
stats_solving(minsize, maxsize, repeats) stats_solving(minsize, maxsize, repeats)
stats_incremental(minsize, maxsize, repeats) stats_incremental(minsize, maxsize, repeats)
stats_parametric_incremental(minsize, maxsize, repeats)
stats_parametric(minsize, maxsize, repeats) stats_parametric(minsize, maxsize, repeats)
if __name__ == "__main__": if __name__ == "__main__":