-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add generic expression constraint (generalization of Pin
)
#31
Conversation
Pin
)
Codecov Report
❗ Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more. @@ Coverage Diff @@
## main #31 +/- ##
==========================================
- Coverage 92.96% 92.77% -0.20%
==========================================
Files 29 30 +1
Lines 725 747 +22
==========================================
+ Hits 674 693 +19
- Misses 51 54 +3
|
I like it, but it is also more complex than
|
yeah class Pin(ExpressionConstraint):
def __init__(self, attribute: str) -> None:
super().__init__(f"{attribute} == True", eval_nodes=True, eval_edges=True)
Yes, the meat of it is here (will add more comments inline) with contextlib.suppress(NameError):
# here we evaluate the expression with the node/edge dict as the namespace
# if a key (like the "attribute" in Pin) is missing, it will raise a NameError and we just move on
# if it is present, the expression will evaluate to a boolean. If True, we select, else we exclude
if eval(self.expression, None, node_or_edge):
select.set_coefficient(indicators[id_], 1) # type: ignore
else:
exclude.set_coefficient(indicators[id_], 1) # type: ignore here's an example of how that works with In [1]: eval('x == 1', {'x': 1})
Out[1]: True
In [2]: eval('x == 1', {'x': 3})
Out[2]: False
In [3]: eval('x == 1', {'y': 3})
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[3], line 1
----> 1 eval('x == 1', {'y': 3})
File <string>:1
NameError: name 'x' is not defined |
extended the class docstring and added more comments inline |
Great, this looks good now. Thanks! |
Hey @funkey, curious how you feel about this constraint.
It generalizes the
Pin
constraint to support any expression evaluated against the namespace of the node dictfor example, if the nodes in a graph are:
Then the following constraint will select node 0:
this uses
eval
, and therefore introduces a slight safety risk. This could be made more safe by adding a small function to check that the expression string only uses simple comparison operators (i.e. no function calls or attribute access, etc...)