several bug-fixes.

added some assertions to prevent user errors.
test.py: added problematic diamond_3d problem
This commit is contained in:
kwikrick 2011-03-29 21:29:11 +00:00
parent e758e3c225
commit b3189bac28
5 changed files with 102 additions and 21 deletions

View File

@ -2,23 +2,59 @@ TODO/WISH LIST
--------------
Code: Some bits of the code are ugly:
- vector module, matpy module and Numpy package, all offer similar functionality.
Use only one, get rid of two.
- more documentation!
- vector module, matpy module and Numpy package, all offer similar
functionality. Use only one, get rid of two.
- more documentation!
Speed: The solver is currently much too slow. The problem is the pattern matching algorithms that is used to find
combinations of clusters that can be rewritten/merged. Solutions:
- hand-coded matching algorithms per merge rule (labourous and error prone)
- incremental pattern matching system (work in progress)
- compliled implementation (Psycho/C++/Haskell/???)
Speed: The solver is currently much too slow. The problem is the pattern
matching algorithms that is used to find combinations of clusters that
can be rewritten/merged. Solutions:
- incremental pattern matching system (work in progress)
- compliled implementation (Psycho/C++/Haskell/???)
Rules: More rewrite rules to increase the problem domain:
- larger subproblems (octahedron, variable radius spheres/cylinders)
- new clusters types (N degrees of freedom)
- larger subproblems (octahedron, variable radius spheres/cylinders)
- new clusters types (N degrees of freedom)
Extentions:
- implement geometry: lines, planes, spheres, cylinders, tori (mappings to cluster)
- constraints on parameters (equality, algebraic constraints)
- different variable domains (integers, reals, n-dimensional points, surfaces, volumes, logic variables, lists)
- implement geometry: lines, planes, spheres, cylinders, tori (mappings to
cluster)
- constraints on parameters (equality, algebraic constraints)
- different variable domains (integers, reals, n-dimensional points,
surfaces, volumes, logic variables, lists)
Easy of use:
- move use_prototype flag to GeometricProblem (instead of in
GeometricSolver)
- check dimension of prototype points when adding to problem
BUGS:
- following should be well-constraint, gives underconstrained (need extra rule/pattern)
def diamond_3d():
"""creates a diamond shape with point 'v1'...'v4' in 3D with one solution"""
L=10.0
problem = GeometricProblem(dimension=3)
problem.add_point('v1', vector([0.0, 0.0, 0.0]))
problem.add_point('v2', vector([-5.0, 5.0, 0.0]))
problem.add_point('v3', vector([5.0, 5.0, 0.0]))
problem.add_point('v4', vector([0.0, 10.0, 0.0]))
problem.add_constraint(DistanceConstraint('v1', 'v2', L))
problem.add_constraint(DistanceConstraint('v1', 'v3', L))
problem.add_constraint(DistanceConstraint('v2', 'v3', L))
problem.add_constraint(DistanceConstraint('v2', 'v4', L))
problem.add_constraint(DistanceConstraint('v3', 'v4', L))
# this bit of code constrains the points v1...v4 in a plane with point p above v1
problem.add_point('p', vector([0.0, 0.0, 1.0]))
problem.add_constraint(DistanceConstraint('v1', 'p', 1.0))
problem.add_constraint(AngleConstraint('v2','v1','p', math.pi/2))
problem.add_constraint(AngleConstraint('v3','v1','p', math.pi/2))
problem.add_constraint(AngleConstraint('v4','v1','p', math.pi/2))
- when fixed (by swapping v1 and v3 in last bit of code)
sometimes raises:
StandardError: more than one candidate prototype cluster for variable v2
or:
FixConstraint(v2=[-5.0, 5.0, 0.0]) not satisfied
FixConstraint(v1=[0.0, 0.0, 0.0]) not satisfied

View File

@ -280,8 +280,10 @@ class ClusterSolver(Notifier):
clusters = self._graph.outgoing_vertices(var)
clusters = filter(lambda c: isinstance(c, Rigid), clusters)
clusters = filter(lambda c: len(c.vars) == 1, clusters)
if len(clusters) != 1:
raise StandardError, "no prototype cluster for variable "+str(v)
if len(clusters) < 1:
raise StandardError, "no prototype cluster for variable "+str(var)
elif len(clusters) > 1:
raise StandardError, "more than one candidate prototype cluster for variable "+str(var)
selclusters.append(clusters[0])
outcluster = incluster.copy()
selector = PrototypeMethod(incluster, selclusters, outcluster, constraints, self._prototype_selection_var)
@ -357,7 +359,7 @@ class ClusterSolver(Notifier):
if len(self._applicable_methods) > 0:
method = iter(self._applicable_methods).next()
#print "applicable methods:", map(str, self._applicable_methods)
print "incremental search found:", method
diag_print("incremental search found:"+str(method),"clsolver._process_new")
self._add_method_complete(method)
else:
newobject = self._new.pop()

View File

@ -14,7 +14,9 @@ from notify import Notifier, Listener
from tolerance import tol_eq
from intersections import angle_3p, distance_2p
from selconstr import SelectionConstraint
from geosolver.intersections import is_left_handed, is_right_handed, transform_point, make_hcs_3d
from geosolver.intersections import is_left_handed, is_right_handed
from geosolver.intersections import is_clockwise, is_counterclockwise
from geosolver.intersections import transform_point, make_hcs_3d
# ----------- GeometricProblem -------------
@ -50,6 +52,7 @@ class GeometricProblem (Notifier, Listener):
def add_point(self, variable,pos):
"""add a point variable with a prototype position"""
position = vector.vector(pos)
assert len(position) == self.dimension
if variable not in self.prototype:
self.prototype[variable] = position
self.cg.add_variable(variable)
@ -881,19 +884,28 @@ class RigidConstraint(ParametricConstraint):
def __str__(self):
return "RigidConstraint("+str(self._variables)+")"
class ClockwiseConstraint (SelectionConstraint):
"""A selection constraint for 3 points to have a clockwise orientation (not co-linear!)"""
def __init__(self, v1, v2, v3):
SelectionConstraint.__init__(self, is_clockwise, [v1,v2,v3])
class CounterClockwiseConstraint (SelectionConstraint):
"""A selection constraint for 3 points to have a counter-clockwise orientation (not co-linear!)"""
def __init__(self, v1, v2, v3):
SelectionConstraint.__init__(self, is_counterclockwise, [v1,v2,v3])
class RightHandedConstraint (SelectionConstraint):
"""A selection constraint for 4 points to have a right-handed orientation"""
"""A selection constraint for 4 points to have a right-handed orientation (not co-planar!)"""
def __init__(self, v1, v2, v3, v4):
SelectionConstraint.__init__(self, is_right_handed, [v1,v2,v3,v4])
class LeftHandedConstraint (SelectionConstraint):
"""A selection constraint for 4 points to have a left-handed orientation"""
"""A selection constraint for 4 points to have a left-handed orientation (not co-planar!)"""
def __init__(self, v1, v2, v3, v4):
SelectionConstraint.__init__(self, is_left_handed, [v1,v2,v3,v4])
class NotRightHandedConstraint (SelectionConstraint):
"""A selection constraint for 4 points to not have a rigth-handed orientation, i.e. left-handed or co-planar"""
"""A selection constraint for 4 points to not have a right-handed orientation, i.e. left-handed or co-planar"""
def __init__(self, v1, v2, v3, v4):
SelectionConstraint.__init__(self, fnot(is_right_handed), [v1,v2,v3,v4])

View File

@ -227,13 +227,19 @@ def distance_2p(p1, p2):
def is_clockwise(p1,p2,p3):
""" returns True iff triangle p1,p2,p3 is clockwise oriented"""
assert len(p1)==2
assert len(p1)==len(p2)
assert len(p2)==len(p3)
u = p2 - p1
v = p3 - p2;
v = p3 - p2
perp_u = vector.vector([-u[1], u[0]])
return tol_lt(vector.dot(perp_u,v),0)
def is_counterclockwise(p1,p2,p3):
""" returns True iff triangle p1,p2,p3 is counterclockwise oriented"""
assert len(p1)==2
assert len(p1)==len(p2)
assert len(p2)==len(p3)
u = p2 - p1
v = p3 - p2;
perp_u = vector.vector([-u[1], u[0]])
@ -241,6 +247,10 @@ def is_counterclockwise(p1,p2,p3):
def is_colinear(p1,p2,p3):
""" returns True iff triangle p1,p2,p3 is colinear (neither clockwise of counterclockwise oriented)"""
assert len(p1)==2
assert len(p1)==len(p2)
assert len(p2)==len(p3)
u = p2 - p1
v = p3 - p2;
perp_u = vector.vector([-u[1], u[0]])

View File

@ -225,6 +225,27 @@ def overconstrained_tetra():
#problem.add_constraint(AngleConstraint('v1', 'v2', 'v3', math.pi/4))
return problem
def diamond_3d():
"""creates a diamond shape with point 'v1'...'v4' in 3D with one solution"""
# Following should be well-constraint, gives underconstrained (need extra rule/pattern)
L=10.0
problem = GeometricProblem(dimension=3)
problem.add_point('v1', vector([0.0, 0.0, 0.0]))
problem.add_point('v2', vector([-5.0, 5.0, 0.0]))
problem.add_point('v3', vector([5.0, 5.0, 0.0]))
problem.add_point('v4', vector([0.0, 10.0, 0.0]))
problem.add_constraint(DistanceConstraint('v1', 'v2', L))
problem.add_constraint(DistanceConstraint('v1', 'v3', L))
problem.add_constraint(DistanceConstraint('v2', 'v3', L))
problem.add_constraint(DistanceConstraint('v2', 'v4', L))
problem.add_constraint(DistanceConstraint('v3', 'v4', L))
# this bit of code constrains the points v1...v4 in a plane with point p above it
problem.add_point('p', vector([0.0, 0.0, 1.0]))
problem.add_constraint(DistanceConstraint('v1', 'p', 1.0))
problem.add_constraint(AngleConstraint('v2','v1','p', math.pi/2))
problem.add_constraint(AngleConstraint('v3','v1','p', math.pi/2))
problem.add_constraint(AngleConstraint('v4','v1','p', math.pi/2))
# -------- 2D problems
def ddd_problem():