Lambda Calculus - Inserting Parentheses? - parsing

This is a question from my midterm that I do not understand how to do.
Insert parentheses in to clarify how it's parsed
x y λx.x y
The answer is : ((x y) (λx.(x y))))
Could someone explain how you do that?

Well, first of all, that is not the answer. ((x y) (λx.(x y)))) is invalid, it has one extra closing parenthesis.
( ( x y ) ( λx.( x y ) ) ) ) Note the imbalanced parenthesis
However, I will be ignoring that from here on out by assuming you meant: ((x y) (λx.(x y))), with the final parenthesis removed. I didn't mean to be nit-picking there, I believe this was probably just a typo, my IDE puts red lines under my code all the time for adding or neglecting to add a parenthesis by mistake, but I did think that this should be pointed out.
If the question was provided to you in this form without any other information, I will say that it is probably not very good, and it would have bothered me greatly if I saw it on a final, because there is some ambiguity in it. This could be solved in several valid ways that I can see, but the corrected version of the answer you provided is arguably the cleanest.
So looking back at x y λx.x y
Some syntactically valid, but non-equivalent possible ways of wrapping the variables could be:
((x y) (λx.(x y)))
(x y)(λx.x)y - is equivalent to (x y)y
x (y ((λx.x) y) ) - is equivalent to x (y y)
x (y (λx.(x y)))
When approaching the problem, note that λx.___ is the only completed abstraction. Therefore you know there will be an open parenthesis to the left of λ, and we have: _x_ _y_(λx._x_ _y_, some obvious pieces of intuition, based on the fact that the final solution must indeed be closed and balanced would provide:(x_ _y_ (λx.(x_ _y)_* where a _ designates the possibility of one or more parenthesis, either open, or closed, see the _*, which could only be a closing parenthesis. Beyond this, the rest of the blanks can be filled in in any way so long as the parenthesis remain balanced.
My guess is that either:
There was something more to the question left out here, like maybe you knew or could determine some example inputs and outputs, or were told to make the cleanest possible outcome (very subjective)
This was a multiple choice question, and the other options could be ruled out. Perhaps they were not efficiently placing the parenthesis, including excessive wasted parenthesis, like in ((((x y) (λx.(x y))))). Perhaps they were plainly invalid, like (x (y λx))(.x y). Or perhaps the parenthesis were unbalanced, as in your original claim of ((x y) (λx.(x y)))), or a more exaggerated, less subtle ((x y)) (λx.(x y))))).
This would in my mind make a decent multiple choice problem, or with more information, a somewhat vague and open-ended, but not too terrible fill in the blank with more information provided. If it was given as is, I do have a problem with it, but maybe your professor would accept all valid answers that are formatted in a reasonable way. If the answer you provided, including the extra unbalanced closing parenthesis, is actually what he used as the correct one (perhaps in a multiple choice), then there is a bigger problem, because that answer is plainly wrong.
Sorry about answering this kinda late, hopefully the question is still useful to you, and hopefully if so this was of some help.

Related

Z3: Are functions realized with inlining?

Are functions in z3 realized by inlining? E.g. would this
(define-fun f ((parameter Int)) Int (* parameter parameter))
(assert (= (f x) y))
automatically be replaced by this?:
(assert (= (* x x) y))
I know that in https://smtlib.github.io/jSMTLIB/SMTLIBTutorial.pdf#subsection.3.9.4 (page 38) it is mentioned that they are "equivalent"/"an abbreviation", but I just wanted to make sure whether this means that the function calls themselves are replaced.
Thanks so much!
Yes, the SMT-LIB standard indeed defines define-fun to be a C-style macro that is syntactically expanded to its defining expression.
However, while this defines its semantics, the definition does not necessarily require SMT-LIB tools, most notably SMT solvers, to actually implement define-fun like this. Hence, it could be that an SMT solver behaved differently, e.g. in terms of performance, if you ran it on two versions of a program: one with define-funs, and a second where you manually replaced all define-funs with their corresponding expressions.
The last bit is pure speculation from my side, though; you'd have to look at, e.g. Z3's sources (or maybe just its verbose debug output) to find out what a particular tool actually does.

Using a Closure instead of a Global Variable

This question is a continuation of the comments at Using Local Special Variables, regarding how best to avoid global variables. As I understand it, global variables are problematic mainly because they have the potential to interfere with referential transparency. Transparency is violated if an expression changes a global value using information outside its calling context (eg, a previous value of the global variable itself, or any other external values). In these cases evaluating the expression may have different results at different times, either in the value(s) returned or in side effects. (However, it seems not all global updates are problematic, since some updates may not depend on any external information--eg, resetting a global counter to 0). The normal global approach for a deeply embedded counter might look like:
* (defparameter *x* 0)
*X*
* (defun foo ()
(incf *x*))
FOO
* (defun bar ()
(foo))
BAR
* (bar)
1
* *x*
1
This would seem to violate referential transparency because (incf *x*) depends on the external (global) value of *x* to do its work. The following is an attempt to maintain both functionality and referential transparency by eliminating the global variable, but I'm not convinced that it really does:
* (let ((x 0))
(defun inc-x () (incf x))
(defun reset-x () (setf x 0))
(defun get-x () x))
GET-X
* (defun bar ()
(inc-x))
BAR
* (defun foo ()
(bar))
FOO
* (get-x)
0
* (foo)
1
* (get-x)
1
The global variable is now gone, but it still seems like the expression (inc-x) has a (latent) side effect, and it will return different (but unused) values each time it is called. Does this confirm that using a closure on the variable in question does not solve the transparency problem?
global variables are problematic mainly because they have the potential to interfere with referential transparency
If one wants to create a global configuration value, a global variable in Common Lisp is just fine.
Often it's desirable to package a bunch of configuration state and then it may be better to put that into an object.
There is no general requirement for procedures to be referential transparent.
It's useful to guide software design by software engineering principles, but often easy debugging and maintenance is more important than strict principles.
(let ((x 0))
(defun inc-x () (incf x))
(defun reset-x () (setf x 0))
(defun get-x () x))
Practically above means that it
is difficult to inspect
has problematic effects of reloading the code
prohibits the file compiler to recognize the top-level nature of the functions
creates a whole API for just managing a single variable
Referential transparency means that if you bind some variable x to an expression e, you can replace all occurrences of x by e without changing the outcome. For example:
(let ((e (* pi 2)))
(list (cos e) (sin e)))
The above could be written:
(list (cos (* pi 2))
(sin (* pi 2)))
The resulting value is equivalent to the first one for some useful definition of equivalence (here equalp, but you could choose another one). Contrast this with:
(let ((e (random))
(list e e))
Here above, each call to random gives a different result (statistically), and thus the behaviour is different if you reuse the same result multiple times or generate a new after each call.
Special variables are like additional arguments to functions, they can influence the outcome of a result simply by being bound to different values. Consider *default-pathname-defaults*, which is used to build pathnames.
In fact, for a given binding of that variable, each call to (merge-pathnames "foo") returns the same result. The result changes only if you use the same expression in different dynamical context, which is no different than calling a function with different arguments.
The main difficulty is that the special variable is hidden, i.e. you might not know that it influences some expressions, and that's why you need them documented and limited in number.
What breaks referential transparency is the presence of side-effects, whether you are using lexical or special variables. In both cases, a place is modified as part of the execution of the function, which means that you need to consider when and how often you call it.
You could have better suggestions if you explained a bit more how your code is organized. You said that you have many special variables due to prototyping but in the refactoring you want to do it seems as-if you want to keep to prototypal code mostly untouched. Maybe there is a way to pack things in a nice modular way but we can't help without knowing more about why you need many special variables, etc.
That code isn't referentially transparent. It is an improvement from special variables though.
The code you put would be a functional nonce if you dropped the reset-x.
My answer to your previous question had general guidelines about special variables. For your specific case, perhaps they are worth it? I could see the case for using special variables as a nonce, for example, where it is probably silly to pass them around.
Common Lisp has so many facilities for dealing with global information, so there is rarely a need for having lots of global variables. You could define an *env* alist to store your values in, or put them in a hash table, or put them into symbol plists, or package them in a closure to pass around, or do something else, or use CLOS.
Where is the side effect of the second example ? The x inside the let isn't accessible from the outside.
Here's another closure example, with top-level functions, and a counter explicitly inside it.
(defun repeater (n)
(let ((counter -1))
(lambda ()
(if (< counter n)
(incf counter)
(setf counter 0)))))
(defparameter *my-repeater* (repeater 3))
;; *MY-REPEATER*
(funcall *my-repeater*)
0
(funcall *my-repeater*)
1
https://lispcookbook.github.io/cl-cookbook/functions.html#closures

Grammar with Epsilon or Lambda

So I have a set of grammar
S -> X Y
X -> a X
X ->
Y -> b
Z -> a Z
Z -> a
My only confusing with this grammar is that 2nd Production for X
There is nothing there. Is that the equivalent of using Epsilon ε, or Lamda λ
I am assuming it is merely a difference in notation for the grammars but wanted to be sure as I am trying to build the first and follow sets
Both ε and λ (and sometimes Λ) are used by different writers to represent the empty string. In modern writing, ε is much more common but you'll often find λ in older textbooks, and Λ in even older ones.
The point of using these symbols is to make the empty sequence visible. However it is written, it is the empty sequence and should be read as though it were nothing, as in your production X ⇒ .
If you find it difficult getting your head around the idea that a symbol means nothing, then you might enjoy reading Charles Seife's Zero: The Biography of a Dangerous Idea or Robert Kaplan's The Nothing that Is: A Natural History of Zero, both published in the emblematic year 2K and both of which explore the long and difficult struggle to understand the concept of nothing. ("No one goes out to buy zero fish" -- Alfred North Whitehead).
It has been suggested that Λ/λ comes from the German word "leer", meaning empty, while ε comes from English "empty". There was a time when German was more common in academic discussion of mathematical logic, so the theory seems reasonable.

Are soft constraints disjunctions?

In Z3, soft constraints can be implemented by placing the actual constraint P on the right-hand side of an implication whose left-hand side is a fresh boolean variable, e.g. assert (=> b1 P). Constraints can then be "switched on" per check-sat by listing bs which are to be considered true, e.g. (check-sat b1).
Question: What happens with such constraints P if their guard variable b is not included in a check-sat? I assume Z3 treats b's value as unknown, and then branches over the implication/over b's value - is that correct?
Background: The background of my question is that I use Z3 in incremental mode (push/pop blocks), and that I check assertions P by (push)(assert (not P))(check-sat)(pop); if the check-sat is unsat then P holds.
I thought about using soft constraints instead, i.e. to replace each such push/pop block by (declare-const b_i Int)(assert (=> b_i P))(check-sat b_i). Each b_i would only be used once. However, if Z3 may branch over all previous b_j, then it sounds as if that might potentially slow down Z3 quite a bit - hence my question.
(P.S.: I am aware of this answer by Leo, which says that soft constraints might also reduce performance because certain optimisations might not be applicable.)
Yes, if the value of b1 is not fixed, it will be treated just like any other Boolean.

How do I get Z3 to return minimal model?

If I give Z3 a formula like p | q, I would expect Z3 to return p=true, q=don't care (or with p and q switched) but instead it seems to insist on assigning values to both p and q (even though I don't have completion turned on when calling Eval()). Besides being surprised at this, my question then is what if p and q are not simple prop. vars but expensive expressions and I know that typically either p or q will be true. Is there an easy way to ask Z3 to return a "minimal" model and not waste its time trying to satisfy both p and q? I already tried MkITE but that makes no difference. Or do i have to use some kind of tactic to enforce this?
thanks!
PS. I wanted to add that I have turned off AUTO_CONFIG, yet Z3 is trying to assign values to constants in both branches of the or: eg in the snippet below I want it to assign either to path2_2 and path2_1 or to path2R_2 and path2R_1 but not both
(or (and (select a!5 path2_2) a!6 (select a!5 path2_1) a!7)
(and (select a!5 path2R_2) a!8 (select a!5 path2R_1) a!9))
Z3 has a feature called relevancy propagation. It is described in this article. It does what you want. Note that, in most cases relevancy propagation has a negative impact on performance. In our experiments, it is only useful for problems containing quantifiers (quantifier reasoning is so expensive that it is pays off). By default, Z3 will use relevancy propagation in problems that contain quantifiers. Otherwise, it will not use it.
Here is an example on how to turn it on when the problem does not have quantifiers (the example is also available online here)
x, y = Bools('x y')
s = Solver()
s.set(auto_config=False, relevancy=2)
s.add(Or(x, y))
print s.check()
print s.model()

Resources