I need to be able to compare two integer expressions, which may include literal integers, addition, unary negation, integer constants, and infinity, and decide if an inequality between them is satisfiable. This is part of a larger program, so there is no way for me to know ahead of time what those expressions will look like.
I have considered defining an integer constant and just letting it take any value, but then I realized that Infinity < 5 would be satisfiable.
I have considered defining a constant and making a universally quantified assertion that it is greater than all integers, but I don't know what Sort I should say it is. If I tell Z3 that the Sort of my Infinity constant is integer, I think it will probably happily go off and try to find me THE LARGEST INTEGER! I'm pretty sure that won't end the way I want.
I would create a composite type consisting of an integer and a boolean that says whether this particular value is infinity or not. Then, you need to define arithmetic on this. For example, if one of the operands is infinity then the result of an addition is infinity as well. Otherwise, it's the actual sum of the integers. Comparisons would be defined in a similar way (case based).
There is no need to actually create a type in the Z3 system. Just always create values in int/bool pairs in your code. A few helper functions can do that.
Doing this you will probably create a harder problem for Z3 to solve and maybe even escalate the logic you are using.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed last month.
Improve this question
I'm reading Crafting Interpreters. It's very readable. Now I'm reading
chapter 17 Compiling Expressions and find algorithm:
Vaughan Pratt’s “top-down operator precedence parsing”. The implementation is very brief
and I don't understand it why it works.
So I read Vaughan Pratt’s “top-down operator precedence parsing” paper. It's so old
and not easy to read. I read related blogs about it and spend days reading the
original paper.
related blogs :
https://abarker.github.io/typped/pratt_parsing_intro.html
https://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/
https://matklad.github.io/2020/04/13/simple-but-powerful-pratt-parsing.html
I am now more confident that I can write an implementation. But I still can't see the
trick behind the magic. Here are some of my questions, if I can describe them clealy:
What grammar can Pratt’s parser handle? Floyd Operator Grammar? I even take a look
at Floyd's paper, but it's very abstract. Or Pratt’s parser can handle any Language
as long as it meets the restrictions on page 44
These restrictions on the language, while slightly irksome,...
On page 45,Theorem 2, Proof.
First assign even integers (to make room for the followin~terpolations) to the data type classes.
Then to each argument position assign an integer lying strictly (where possible) between the integers
corresponding to the classes of the argument and result types.
On page 44,
The idea is to assign data types to classes and then to totally order
the classes.
An example might be, in ascending order,Outcomes (e.g., the pseudo-result of “print”), Booleans,
Graphs (e.g. trees, lists, plexes), Strings, Algebraics (e.g. integers, complex nos, polynomials)...
I can't figure out what the term "data type" means in this paper. If it means primitive
data types in a programming language, like boolean , int , char in Java, then the following exmaple
may be Counterexample
1 + 2 * 3
for +, it's argument type is number, say assign integer 2 to data type number class. +'s result data type is
also a number. so + must have the integer 2. But the same is for *. In this way + and * would have the same
binding power.
I guess data type in this paper is the AST Node type. So +'s result type is term, *'s result type is factor,
which will have a bigger integger than +'s. But I can't be sure.
By data type, Pratt meant, roughly, "primitive data type in the programming language being parsed". (Although he included some things which are often not thought about as types, unless you program in C or C++, and I don't think he contemplated user-defined types.)
But Pratt is not really talking about a parsing algorithm on page 44. What he's talking about is language design. He wants languages to be designed in such a way that a simple semantic rule involving argument and result types can be used to determine operator precedence. He wants this rule, apparently, in order to save the programmer the task of memorizing arbitrary operator precedence tables (or to have to deal with different languages ordering operators in different ways.)
These are indeed laudable goals, but I'm afraid that the train had already left the station when Pratt was writing that paper. Half a century later, it's evident that we're never going to achieve that level of interlanguage consistency. Fortunately, we can always use parentheses, and we can even write compilers which nag at you about not using redundant parentheses until you give up and write them.
Anyway, that paragraph probably contravened SO's no-opinions policy, so let's get back to Pratt's paper. The rule he proposes is that all of a languages primitive datatypes be listed in a fixed total ordering, with the hope that all language designers will choose the same ordering. (I use the word "dominates" to describe this ordering: type A dominates another type B if A comes later in Pratt's list than B. A type does not dominate itself.)
At one end of the ordering is the null type, which is the result type of an operator which doesn't have a return value. Pratt calls this type "Outcome", since an operator which doesn't return anything must have had some side-effect --its "outcome"-- in order to not be pointless. At the other end of the ordering is what C++ calls a reference type: something which can be used as an argument to an assignment operator. And he then proposes a semantic rule: no operator can produce a result whose type dominates the type of one or more of its arguments, unless the operator's syntax unambiguously identifies the arguments.
That last exception is clearly necessary, since there will always be operators which produce types subordinate to the types of their arguments. Pratt's example is the length operator, which in his view must require parentheses because the Integer type dominates the String and Collection types, so length x, which returns an Integer given a String, cannot be legal. (You could write length(x) or |x| (provided | is not used for other purposes), because those syntaxes are unambiguous.)
It's worth noting that this rule must also apply to implicit coercions, which is equivalent to saying that the rule applies to all overloads of a single operator symbol. (C++ was still far in the future when Pratt was writing, but implicit coercions were common.)
Given that total ordering on types and the restriction (which Pratt calls "slightly irksome") on operator syntax, he then proposes a single simple syntactic rule: operator associativity is resolved by eliminating all possibilities which would violate type ordering. If that's not sufficient to resolve associativity, it can only be the case that there is only one type between the result and argument types of the two operators vying for precedence. In that case, associativity is to the left.
Pratt goes on to prove that this rule is sufficient to remove all ambiguity, and furthermore that it is possible to derive Floyd's operator precedence relation from type ordering (and the knowledge about return and argument types of every operator). So syntactically, Pratt's languages are similar to Floyd's operator precedence grammars.
But remember that Pratt is talking about language design, not parsing. (Up to that point of the paper.) Floyd, on the other hand, was only concerned with parsing, and his parsing model would certainly allow a prefix length operator. (See, for example, C's sizeof operator.) So the two models are not semantically equivalent.
This reduces the amount of memorization needed by someone learning the language: they only have to memorize the order of types. They don't need to try to memorize the precedence between, say, a concatenation operator and a division operator, because they can just work it out from the fact that Integer dominates String. [Note 1]
Unfortunately, Pratt has to deal with the fact that "left associative unless you have a type mismatch" really does not cover all the common expectations for expression parsing. Although not every language complies, most of us would be surprised to find that a*4 + b*6 was parsed as ((a * 4) + b) * 6, and would demand an explanation. So Pratt proposes that it is possible to make an exception by creating "pseudotypes". We can pretend that the argument and return types of multiplication and division are different from (and dominate) the argument and return types of addition and subtraction. Then we can allow the Product type to be implicitly coerced to the Sum type (conceptually, because the coercion does nothing), thereby forcing the desired parse.
Of course, he has now gone full circle: the programmer needs to memorise both the type ordering rules, but also the pseudotype ordering rules, which are nothing but precedence rules in disguise.
The rest of the paper describes the actual algorithm, which is quite clever. Although it is conceptually identical to Floyd's operator precedence parsing, Pratt's algorithm is a top-down algorithm; it uses the native call stack instead of requiring a separate stack algorithm, and it allows the parser to interpolate code with production parsing without waiting for the production to terminate.
I think I've already deviated sufficiently from SO's guidelines in the tone of this answer, so I'll leave it at that, with no other comment about the relative virtues of top-down and bottom-up control flows.
Notes
Integer dominates String means that there is no implicit coercion from a String to an Integer, the same reason that the length operator needs to be parenthesised. There could be an implicit coercion from Integer to String. So the expression a divide b concatenate c must be parsed as (a divide b) concatenate c. a divide (b concatenate c) is disallowed and so the parser can ignore the possibility.
I am working on a satisfiability check for transition conditions of GRAFCET Diagrams (which is used to model the behaviour of a programmable logic controller). For this purpose I am using the Z3 SMT Solver.
In addition to normal operators (AND, OR, NOT and EQUALITY) the GRAFCET specification allows RISING and FALLING EDGE operators in its conditions.
Exemple: ↑a (RISING EDGE)
Explanation: The conditions is statisfied if the variable a changes its value from FALSE to TRUE.
My first thought would be to check, if there is a variable combination that statisfies a and also a variable combination that statisfies NOT(a). This way I could proof that the RISING EDGE could possibly occure.
[Q]: Is it possible to translate these operators directly in propositional logic or somthing similar to check satisfiablity in one forumula.
Raising/falling edges suggests change over time. In a SAT/SMT context, variables do not change. To model what you want, you’ll have to capture the value in successive points in different variables and check that the first is False and second is True for raising, etc.
You can also use an array indexed by an integer to represent the value. It all depends on how you translate these diagrams to SAT. In any case, the value of each variable will be constant in the model. (That is, checking a and Not(a) at the same time will always be unsatisfiable.)
I was curious that are there any ternary operator being used in programming language except ?: operator. And could found only 2 from wikipedia
Is it only operator we have been used? Are there any more than these?
Element update
Another useful class of ternary operator, especially in functional languages, is the "element update" operation. For example, OCaml expressions have three kinds of update syntax:
a.b<-c means the record a where field b has value c
a.(b)<-c means the array a where index b has value c
a.[b]<-c means the string a where index b has value c
Note that these are not "update" in the sense of "assignment" or "modification"; the original object is unchanged, and a new object is yielded that has the stated properties. Consequently, these operations cannot be regarded as a simple composition of two binary operators.
Similarly, the Isabelle theorem prover has:
a(|b := c|) meaning the record a where field b has value c
Array slice
Yet another sort of ternary operator is array slice, for example in Python we have:
a[b:c] meaning an array whose first element is a[b] and last element is a[c-1]
In fact, Python has a quaternary form of slice:
a[b:c:d] meaning an array whose elements are a[b + n*d] where n ranges from 0 to the largest value such that b + n*d < c
Bash/ksh variable substitution
Although quite obscure, bash has several forms of variable expansion (apparently borrowed from ksh) that are ternary:
${var:pos:len} is a maximum of len characters from $var, starting at pos
${var/Pattern/Replacement} is $var except the first substring within it that matches Pattern is replaced with Replacement
${var//Pattern/Replacement} is the same except all matches are replaced
${var/#Pattern/Replacement} is like the first case except Pattern has to match a prefix of $var
${var/%Pattern/Replacement} is like the previous except for matching a suffix
These are borderline in my opinion, being close to ordinary functions that happen to accept three arguments, written in the sometimes baroque style of shell syntax. But, I include them as they are entirely made of non-letter symbols.
Congruence modulo
In mathematics, an important ternary relation is congruence modulo:
a ≡ b (mod c) is true iff a and b both belong to the same equivalence class in c
I'm not aware of any programming language that has this, but programming languages often borrow mathematical notation, so it's possible it exists in an obscure language. (Of course, most programming languages have mod as a binary operator, allowing the above to be expressed as (a mod c) == (b mod c).) Furthermore, unlike the bash variable substitution syntax, if this were introduced in some language, it would not be specific to that language since it is established notation elsewhere, making it more similar to ?: in ubiquity.
Excluded
There are some categories of operator I've chosen to exclude from the category of "ternary" operator:
Operations like function application (a(b,c)) that could apply to any number of operators.
Specific named functions (e.g., f(a,b,c)) that accept three arguments, as there are too many of them for any to be interesting in this context.
Operations like SUM (Σ) or let that function as a binding introduction of a new variable, since IMO a ternary operator ought to act on three already-existing things.
One-letter operators in languages like sed that happen to accept three arguments, as these really are like the named function case, and the language just has a very terse naming convention.
Well it’s not a ternary operator per-say but I do think the three way comparison operator is highly underrated.
The ternary operator is appropriate when a computation has to take place, even if I cannot use the effect inside of an if/else statement or switch statement Consequently, 0 or the DEFAULT VALUE is treated as a DEFAULT VALUE when I try the computation.
The if/else or switch statements require me to enumerate every case that can take place and are only helpful if the ability to discriminate between a numeric value and a branching choice can help. In some cases, it is clear why it won't help if a condition test exists, simply because I am either too early or too late to do something about the condition, even though some other function is unable to test for the given condition.
The ternary operator forces a computation to have the effect that can pass through the code that follows it. Other types of condition tests resort to using, for instance, the && and || operators which can't guarantee a pass through.
I am using functions in my solver to model discrete time. The problem is that right now we use functions like z3.Function('f', IntSort(), IntSort()) and negative input values to the functions is really not applicable here because time starts at t=0. This causes problems when I want to proove things because the solver finds negative time solutions that should not be considered at all.
So my question is: Is there some kind of unsigned int sort (UnsignedIntSort) in z3?
As pointed out in the comments, there's no such sort; and your best bet is to make sure you have t >= 0 assertions for all uses.
Note that this is actually trickier in practice. Not only you need to make this assertion for all your "fresh" variables, but also whenever you do any arithmetic with such variables to ensure the results remain within the domain. That is, if you ever compute t-1, then you'll want t >= 1 as an assertion appearing, assuming the result of that expression is used as a time value itself.
This can get really tedious really quick, so having a mechanism ("overloaded arithmetic") can simplify life. But of course, that depends on exactly how you are programming your constraints, whether you're using SMT-Lib, or one of the APIs via a higher-level language.
There is no unsigned sort in SMT or Z3, because bit-vectors can trivially be used for this purpose. Bit-vectors hemselves are neither unsigned nor signed, but they are strings of bits. Signed and unsigned semantics are then implemented in separate functions, i.e., there is no generic less-than operator for bit-vectors, but there are bvult and bvslt for unsigned and signed less-than. Thus, as long as you stick to the unsigned flavours of all BV functions, you will always preserve unsigned semantics.
Also, in models, bit-vectors are usually provided as bit-strings (in binary or hex), i.e., there are no negative values. Insofar, in your application, you can always assume all bit-vectors are unsigned until you start using the *s* functions.
In my engine I have a Lua VM for scripting. In the scripts, I write things like:
stage = stage + 1
if (stage == 5) then ... end
and
objnum = tonumber("5")
if (stage == objnum)
According to the Lua sources, Lua uses a simple equality operator when comparing doubles, the internal number type it uses.
I am aware of precision problems when dealing with floating point values, so I want to know if the comparison is safe, that is, will there be any problems with simply comparing these numbers using Lua's default '==' operation? If so, are there any countermeasures I can employ to make sure 1+2 always compares as equal to 3? Will converting the values to strings work?
You may be better off by converting to string and then comparing the results if you only care about equality in some cases. For example:
> print(21, 0.07*300, 21 == 0.07*300, tostring(21) == tostring(0.07*300))
21 21 false true
I learned this hard way when I gave my students an assignment with these numbers (0.07 and 300) and asked them to implement a unit test that then miserably failed complaining that 21 is not equal 21 (it was comparing actual numbers, but displaying stringified values). It was a good reason for us to have a discussion about comparing floating point values.
I can employ to make sure 1+2 always compares as equal to 3?
You needn't worry. The number type in Lua is double, which can hold many more integers exactly than a long int.
Comparison and basic operations on doubles is safe in certain situations. In particular if the numbers and their result can be expressed exactly - including all low value integers.
So 2+1 == 3 will be fine for doubles.
NOTE: I believe there's even some guarantees for certain math functions ( like pow and sqrt ) and if your compiler/library respects those then sqrt(4.0)==2.0 or 4.0 == pow(2.0,2.0) will reliably be true.
By default, Lua is compiled with c++ floats, and behind the scenes number comparisons boils down to float comparisons in c/c++, which are indeed problematic and discussed in several threads, e.g. most-effective-way-for-float-and-double-comparison.
Lua makes the situation only slightly worse by converting all numbers, including c++ integers, into floats. So you need to keep it in mind.