-
Notifications
You must be signed in to change notification settings - Fork 59
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
Check cfg edge constraints #1084
Check cfg edge constraints #1084
Conversation
Implement update_edge_feasibility function that traverses through CFG and checks for logically impossible edges Create unit tests
… check-CFG-edge-constraints
Create test cases for both feasible and unfeasible edges in test_edge_feasibility Add handling of AugAssign node in creating edge Z3 constraints Update change log
…-CFG-edge-constraints
Pull Request Test Coverage Report for Build 11136792286Warning: This coverage report may be inaccurate.This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.
Details
💛 - Coveralls |
python_ta/cfg/graph.py
Outdated
@@ -274,11 +277,32 @@ def update_edge_z3_constraints(self) -> None: | |||
|
|||
# traverse into target node | |||
for node in edge.target.statements: | |||
if isinstance(node, Assign): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change should be extracted into a separate pull request. It is separate from checking edge feasibility; it is extending the existing capability of the Z3 constraint updating, which is a good change to make but is separate.
In your new PR, you should make sure to add an entry to the changelog describing this, as well as add new test cases for just this change.
) | ||
|
||
|
||
# TODO: determine and implement the expected behavior of this test case |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's okay to not include this test, but please don't include the commented out code in this PR. Instead, save it and include it in a future PR.
python_ta/cfg/graph.py
Outdated
@@ -3,12 +3,14 @@ | |||
from typing import Any, Dict, Generator, List, Optional, Set | |||
|
|||
try: | |||
import z3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use a consistent import style here. Either import Solver
on the line below, or only import z3
and then modify the usages of Z3_OP_UNINTERPRETED
to z3.Z3_OP_UNINTERPRETED
, etc. consistently throughout.
python_ta/cfg/graph.py
Outdated
for edge in path: | ||
solver.add(edge.z3_constraints[path_id]) | ||
if solver.check() == z3.sat: | ||
edge.is_feasible = True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, I'd like the default value of edge.is_feasible
to be True
(set in the initializer), and then set to False
when the Z3 solver gives "unsatisfiable" for every path that uses the edge.
This is the more conservative default value, in the sense that later on, we'll modify checks to ignore edges that are infeasible, so we want to avoid at all costs the error of marking an edge as infeasible when it's actually feasible.
Your current approach makes the updating a bit awkward because you're iterating across all paths, and then calling solver.check
for each path's edge. You should be able to do it the other way, iterating across all edges and then calling solver.check
for each edge's set of path constraints. ("if all constraints are unsatisfiable, edge.is_feasible = False
")
Set is_feasible to be true by default, and false only if all constrants are unsatisfiable Revert changes to update_edge_z3_constraints
… check-CFG-edge-constraints
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Raine-Yang-UofT okay great. I left one minor comment, but also note in my original instructions I asked you to do 3 things. You've done the first two now, and should add the third.
Render infeasible CFG edges in light grey Integrate Z3Visitor into CFG rendering
Fix an error that makes edge feasibility when z3 constraints are empty
Update expected snapshot test case for CFG diagram
Create test case without function precondition Refactor certain tests to replace get_paths() to get_edges()
…-Yang-UofT/pyta into check-CFG-edge-constraints
python_ta/cfg/cfg_generator.py
Outdated
@@ -13,6 +13,8 @@ | |||
from astroid import nodes | |||
from astroid.builder import AstroidBuilder | |||
|
|||
from python_ta.transforms.z3_visitor import Z3Visitor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As with my previous comments, here you should use a relative import (.transforms.z3_visitor
) and group this with the imports below.
But also similar to graph.py
, we need to check for whether Z3 has been successfully imported or not, and if not then make sure the previous functionality works correctly. You can test this by uninstalling Z3 from your Python environment and then calling generate_cfg
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Professor, I tested that when Z3 is uninstalled, z3_visitor
would raise an error as we did not check for Z3 dependency in its imports. I suggest we should modify z3_visitor
such that if Z3 dependency is not available, invoking the visitor would do nothing. This may be more convenient than checking for Z3 dependency whenever we want to use Z3Visitor
. Should I make this change in a separate PR or include it in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @Raine-Yang-UofT, please use the approach I described in my original comment. I don't agree with the approach of Z3Visitor
"doing nothing" if z3
isn't installed, I'd much rather it not be invoked at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@david-yz-liu No problem, I have added a check for z3 dependency in generating CFG. Now the CFG generation works correctly even with Z3 uninstalled. However, as the import of z3 are not checked in Z3Visitor
and Z3Parser
, we need to fix these two modules for PythonTA to function correctly without Z3. Let me know if I should propose this change in a new PR.
Change the import of Z3Visitor in graph.py to relative import
…-Yang-UofT/pyta into check-CFG-edge-constraints
Invoke Z3Visitor only if z3 is installed
python_ta/cfg/cfg_generator.py
Outdated
@@ -13,6 +13,7 @@ | |||
from astroid import nodes | |||
from astroid.builder import AstroidBuilder | |||
|
|||
from ..transforms.z3_visitor import Z3Visitor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Raine-Yang-UofT I'm not sure how you tried to test what I asked for, but transforms.z3_visitor
imports z3
, and so will raise an ImportError
if z3
isn't installed.
Check for import of Z3Visitor in cfg_generator so it works correctly without z3 Implement unit tests for running CFG without z3
Proposed Changes
Add
is_feasible
attribute toCFGEdge
and implemented update to edge feasibility based on thez3_constraints
attribute.Add handling of
AugAssign
node in creating edge Z3 constraints.Existing issue:
The current implementation cannot correctly handle variable reassignment after a conditional statement inside a loop, as shown in the test case
test_feasible_reassignment_in_while
intest_edge_feasibility
...
Screenshots of your changes (if applicable)
Type of Change
(Write an
X
or a brief description next to the type or types that best describe your changes.)Checklist
(Complete each of the following items for your pull request. Indicate that you have completed an item by changing the
[ ]
into a[x]
in the raw text, or by clicking on the checkbox in the rendered description on GitHub.)Before opening your pull request:
After opening your pull request:
Questions and Comments
(Include any questions or comments you have regarding your changes.)