-
Notifications
You must be signed in to change notification settings - Fork 5
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
Polyhedral Contract Syntax #129
Comments
FYI: I made a branch with WIP for this issue: https://github.com/FormalSystems/pacti/tree/polyhedra-contracts Currently, it handles the canonical polyhedral term syntax: I tried running the test suite but I got this error:
Any suggestions? |
Hi Nicolas,
The error you get seems to indicate that coverage support for pytest is not installed. I don't know how that could be the case since pyproject includes directives to install coverage support:
Would rerunning pdm install make sense? My local installation has the folder |
Thanks Inigo!
Success! So far, I believe that this achieves the 1st part of the ticket: parser support. The next step is the pretty-printer... |
Great to hear that 😃 |
In testing against the space_mission case study, I found that there were some bugs in the regex patterns that I'm fixing. I also noticed that the previous |
I am not surprised... The original intent was to only enter expressions of the form 'ax + by <= c' (which is what the low-level representation supports), so the '<=' was assumed to be fixed and was probably ignored. |
I pushed a commit that implements the pretty printer described above. It would be nice if pretty-printing the parsing of an input contract string would result in the same output string as the input string. Unfortunately, this is not the case for our rules.
Rule 1 is the canonical pattern; there is no rewrite. Consider the input string: For parsing, we apply rule 4 and rewrite it as: For pretty-printing, we then have an ambiguity, as this pair could match the pos/neg results of rules 2,3,4 depending on the order in which we look for them. Is this really a big deal? In principle no because What do you think? |
FYI: Here is an example of the pretty-printer: It produces this:
|
I am wondering whether we need to augment There are several places where
This is hard to read... So I'm proposing to change the
to add optional pretty-printer functions based on this: For IoContract, we need 3 kinds of optional printer functions:
Now, I get something more readable:
|
Thanks, Nicolas, for implementing this! It makes the tool more user-friendly. It just struck me that reporting results (including plotting) is an important application of a tool that aims to help users to deal with specifications. Regarding your questions:
I agree that there is ambiguity. I would say that our higher priority rule to check in this case is equality (rule 4). It is better to output
The output looks great. It would be nice to remove spaces after an opening
Right now, we print contracts by defining a I agree that the output you get is the way to go (it seems the constants need to be floating-point formatted--there are some long strings: Something to think about is that someone at some point may be using small numbers in constraints. Then scientific notation would be appropriate. We could decide for the user and output all numbers in scientific notation with a couple of fractional digits by default, or we could give the user the ability of passing a format string to Pacti. |
I think it would be preferable to have the I started w/ the optional pretty-printing functions because it was simple and I could see how this works in my case study. After running into a few errors from I agree about the higher priority of rule 4 for printing and about removing the spaces for the Can you elaborate about formatting floating-point numbers? For the pattern-based rewriting, I used |
What I had in mind is that the internal representation of a contract may be
This is tricky, and may depend on the application... |
From previous discussion, we have to
Something else that would be useful here is to
|
Regarding In Python, there are at least two different libraries providing this kind of support: Which one should we use? |
Regarding
Since Polyhedra uses |
Overloaded This allows making as significant simplification of |
This issue is related to #144, which talks about improving the user experience of importing Pacti's functionality. We should probably chat about the use of |
Following a discussion with Inigo, there are some API-breaking changes due to the polyhedral contract syntax. The unit tests pass and show examples of the new API usage. In the spirit of #144, it should suffice to have the following import:
The biggest breaking change stems from this kind of imports/code that will not work:
Previously,
The above is just a sketch of a doc that we should write somewhere... Finally, I added unit tests for the 4 variants of PolyhedralContract string syntax. See |
Made a fix to the serialization of numbers -- it turns out that there were two kinds of numbers:
These cases are handled by a new
|
Per Google's naming conventions, the method I think the ideal import statement would be from pacti import PolyhedralContract Then the user could build contracts by executing |
I've applied some of the naming conventions:
|
It is unclear to me what kind of refactoring we would need to do to achieve the ideal import objective:
Currently, we can do this:
It works because of the Can you elaborate on what it would take to achieve this ideal import? |
Fixed the serialization bug that Inigo and I found on |
Just catching up with this thread. The changes to the string API look great. To address #144 and have import statements like |
Hi @ayush9pandey, completely agree. We made some changes to the API, and now we say from pacti.terms.polyhedra import PolyhedralContract What used to be |
In the notation below, The table below maps an input pattern syntax into pairs of positive and negative constraints (i.e., the internal polyhedral representation). For serialization, if prefixes are present, then matching positive/negative constraints are mapped to the pattern form; otherwise, the constraints are scanned to find corresponding positive/negative constraint pairs that can be mapped to the pattern form.
For 7a and 7b, the positive constraint expansion produces Rules 1b, 2b, 3b, 4b, 5, and 6b could have optional numbers on either or both sides of the comparison.
Yes; see rule 5a.
Yes, see rule 1b. Moreover, in the above, whenever there is a combination of 2 linear terms (e.g., |
#161 is relevant to this discussion. The idea is to also support
This would translate into
where |
This comment was marked as resolved.
This comment was marked as resolved.
Yes, could you please run |
This comment was marked as off-topic.
This comment was marked as off-topic.
Thanks for the additional details. It sounds like we should add it as a dependency. |
This issue requires a parser capability well beyond what is reasonable to tackle with the current regular expression approach. Defining the syntax of Pacti's Polyhedral terms as a formal grammar makes sense, which means defining a PEG parser and looking for available options here: The top two PEG libraries are pyparsing and parsimonious. They both have very high stars on GitHub: 1.8K and 1.6K, respectively; however, there are a few reasons to choose pyparsing over parsimonious:
For these reasons, I propose using pyparsing to specify the Polyhedral term grammar and implement a corresponding parser. |
Thanks for doing this research, @NicolasRouquette! |
Creating the grammar to parse a generalized version of the above table is easy with pyparsing, which allows defining grammar in a similar way to a PEG parser. If you are interested in following progress, see this branch: The remaining work involves the following:
The time investment is about a day of work. |
This will be a great addition. Thanks, @NicolasRouquette! |
FYI: I generated the railroad diagrams: https://github.com/pacti-org/pacti/blob/issue-129/docs/expression.html Open this file in a browser; it should look like this: Generating this diagram is, unfortunately, awkward; I tried to import the grammar from a separate file that would create the diagram, but this resulted in circular Python import errors. Also, the generated HTML file is missing a style that shows shapes with a different color than the background; without the style, we see black rounded rectangles without the internal details. Despite these difficulties, using this diagram as a reference for the Polyhedral term grammar might be helpful. |
This commit concludes the first step described above. The remaining step involves mapping the |
This commit is WIP for the last step. The functionality for mapping |
This commit fixes all unit tests; however, I realize that we need to review the mapping. The table is incomplete because it does not address the general case supported by the grammar, which, in a compact form, is as follows:
The mapping is defined in https://github.com/pacti-org/pacti/blob/issue-129/src/pacti/terms/polyhedra/serializer.py There are some examples here: https://github.com/pacti-org/pacti/blob/issue-129/examples/grammar/from_string.py |
Based on a recent discussion/review with @iincer, we concluded that:
|
The absolute value restriction may be too restrictive; consider this inequality:
Geometrically, the solutions are in either 1 or 2 regions. We can calculate the number of solution regions using without creating a plot: https://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.label.html#scipy.ndimage.label Here is an example: import numpy as np
from scipy import ndimage
# Create a meshgrid for x and y values
x = np.linspace(-10, 10, 100)
y = np.linspace(-10, 10, 100)
X, Y = np.meshgrid(x, y)
k = -2
# Calculate the inequality
Z = np.abs(X + Y) - np.abs(X - Y) - k
# Create a new Z array for the colorscale
# 0 = green
# 1 = red
Z_color = np.where(Z <= 0, 0, 1)
# Label contiguous regions in the Z_color array
labeled_array, num_features = ndimage.label(Z_color == 0)
# Print the number of contiguous green regions
print("Number of contiguous green regions:", num_features) This prints:
We could incorporate this test to ensure that the solutions to each PolyhedralTerm are within a single contiguous geometrical region. What do you think @iincer ? |
I like the use of |
Ah, if the requirement is a single convex region, then we should verify that the resulting set of linear inequalities yields a single convex region after expanding all absolute terms. We can use |
I am pretty sure that requiring the nonnegativity of the coefficients multiplying the absolute values is sufficient, since the only place where non-convexity pops up is when we have |
So it is OK to have something like this: for arbitrary values of as long as |
The |
With:
We can write contracts in a human-friendly way like this:
This approach delegates parsing the string expressions to Sympy, which accepts expressions that are not Polyhedral.
The resulting error messages can be difficult for users to understand.
This issue is about defining the syntax of Polyhedra constraints for parsing and rendering sketched as follows:
LHS <= RHS
where:
RHS
is a numerical constantLHS
is of the form:\sigma c V
wherec
is a constant,V
is a variable.For convenience, the following forms would be supported by rewrite as conjunctions of (1) above:
| LHS | <= RHS
Rewrite as the conjunction of:
LHS <= RHS
-(LHS) <= RHS
| LHS | = 0
Rewrite as the conjunction of:
LHS <= 0
-(LHS) <= 0
LHS = RHS
Rewrite as the conjunction of:
LHS <= RHS
- (LHS) <= -(RHS)
In the above:
-(RHS)
means negating the sign of theRHS
constante.g.
-(4)
becomes-4
and-(-3)
becomes3
and-(+2)
becomes-2
-(LHS)
means negating the effective sign of each atomicc V
term in theLHS
expressione.g.,
-(x-y)
becomes-x+y
The parser would reject any string expression that does not match any of (1,2,3,4).
This ticket entails two parts:
Parser
This involves updating
pacti.terms.polyhedra.loaders.string_to_polyhedra_contract
to implement Regex-based parsing for the forms (1,2,3,4) above instead of usingSympy
.Pretty-printer
Mapping the
pacti.iocontract.IoContract
internal representation of a Polyhedra contract according to the forms (1,2,3,4) above with a new function:pacti.terms.polyhedra.loaders.polyhedra_contract_to_string
The text was updated successfully, but these errors were encountered: