Draft: Refactor constraints to positive
Change Summary
This MR refactors the way in which coordinate constraints are expressed logically. Previously, constraints were specified as functions that returned True when the given point was outside the interval of constraint (or failed to pass the constraint). This was counter intuitive in many cases. Presently, constraints are specified as functions that return True when the point is inside the interval of constraint (or passes the constraint).
Example:
Let m_1
be the coordiante we want to constrain in the interval [m_-, m_+] \subset \mathbb{R}
. The below pseudo code shows the old and new ways of implementing this constraint:
def old_constraint(m1, bound_low, bound_high):
# Returns True if m1 invalid
# Returns False if m1 valid
return m1 < bound_low or m1 > bound_high
def new_constraint(m1, bound_low, bound_high):
# Returns False if m1 invalid
# Returns True if m1 valid
return m1 >= bound_low and m1 <= bound_high
Notes
More than Logical Inversion
This MR might seem to only logically invert the syntax of constraints in manifold
; however, there is a key difference in edge case behavior. Previously, when a NaN
was given, the constraint would return False (meaning Pass), since bool(numpy.nan)
is False. This had the downstream effect of including erroneous templates in the bank (where coordinate functions failed). Now, when a NaN
is given, the constraint returns False (meaning Fail).