When using mixed assert and assert-soft in optimization tasks, e.g. maximize, the soft assertions are disregarded, if they would lead to a non-optimal result.
Is it possible to restrict the "softness" to the satisfiability search only? I.e.: If the soft assertion is satisfiable at all, it is kept and then treated as "hard" assertion in the optimization?
Example exhibiting the aforementioned:
(declare-fun x () Int)
(declare-fun y () Int)
(assert (< (+ x y) (* x y)))
(assert (>= x 0))
(assert (>= y x))
;(assert-soft (>= (* 4 x) y)); x->2, y->500
(assert (>= (* 4 x) y)); x->16, y->62
(assert (<= (* x y) 1000))
(maximize (+ x y))
(set-option :opt.priority pareto)
(check-sat)
(get-value (x y (+ x y) (* x y)))
(check-sat)
(get-value (x y (+ x y) (* x y)))
;...
This would be required to fulfill the following use case:
Given a complex fixed ruleset on a large (>1000) number of variables (mostly having a finite domain), a user can choose the desired values for any of those, which may lead to conflicts with the ruleset.
The individual values for a variable have ratings/weights.
So, given a set of user-selected (possibly conflicting) selections, the ruleset itself and finally the ratings of the set of all possible selections, one solution for all variables is to be found, which, while respecting all non-conflicting selections by the user, maximizes the total rating score.
I had the idea of using assert-soft for user selections to cancel out conflicting ones, while combining it with the optimization of z3 to get the "best" solution. However, this failed, which is the reason for this question.
My answer is yes, if you do it incrementally.
Assume that the set of soft-clauses has only a unique Boolean assignment which makes its associated MaxSMT problem optimal.
Then, it is easy to make satisfiable soft-clauses hard by fixing the value of the associated objective function. Although z3 does not allow to put explicit constraints on the name of a soft clause group (AFAIK), one can do it implicitly by using a lexicographic multi-objective combination rather than a pareto one.
Now, in your example we can safely switch from pareto to lexicographic search because there is only one extra objective function in addition to the one implicitly defined by assert-soft. Assuming the value of the assert-soft group being fixed, the whole problem degenerates to a single-objective formula which in turn has always at-most-one Pareto-optimal solution.
Of course, this is not possible if one plans to add more objectives to the formula. In this case, the only option is to solve the formula incrementally, as follows:
(set-option:produce-models true)
(declare-fun x () Int)
(declare-fun y () Int)
(declare-fun LABEL () Bool)
(assert (and
(or (not LABEL) (>= (* 4 x) y))
(or LABEL (not (>= (* 4 x) y)))
)) ; ~= LABEL <-> (>= (* 4 x) y)
(assert-soft LABEL)
(assert (< (+ x y) (* x y)))
(assert (>= x 0))
(assert (>= y x))
(assert (>= (* 4 x) y))
(assert (<= (* x y) 1000))
(check-sat)
(get-model)
(push 1)
; assert LABEL or !LABEL depending on its value in the model
(maximize (+ x y))
; ... add other objective functions ...
(set-option :opt.priority pareto)
(check-sat)
(get-value (x y (+ x y) (* x y)))
(check-sat)
(get-value (x y (+ x y) (* x y)))
...
(pop 1)
This solves the MaxSMT problem first, fixes the Boolean assignment of the soft-clauses in a way that makes them hard, and then proceeds with optimizing multiple objectives with the pareto combination.
Note that, if the MaxSMT problem admits multiple same-weight solutions for the same optimal value, then the previous approach would discard them and focus on only one assignment. To circumvent this, the ideal solution would be to fix the value of the MaxSMT objective rather than fixing its associated Boolean assignment, e.g. as follows:
(set-option:produce-models true)
(declare-fun x () Int)
(declare-fun y () Int)
(declare-fun LABEL () Bool)
(assert-soft (>= (* 4 x) y) :id soft)
(assert (< (+ x y) (* x y)))
(assert (>= x 0))
(assert (>= y x))
(assert (>= (* 4 x) y))
(assert (<= (* x y) 1000))
(minimize soft)
(check-sat)
(get-model)
(push 1)
; assert `soft` equal to its value in model, e.g.:
; (assert (= soft XXX )))
(maximize (+ x y))
; ... add other objective functions ...
(set-option :opt.priority pareto)
(check-sat)
(get-value (x y (+ x y) (* x y)))
(check-sat)
(get-value (x y (+ x y) (* x y)))
...
(pop 1)
At the time being, this kind of syntax for objective combination is supported by OptiMathSAT only. Unfortunately, OptiMathSAT does not yet support non-linear arithmetic in conjunction with optimization, so it can't be reliably used on your example.
Luckily, one can still use this approach with z3!
If there is only one extra objective function in addition to the group of soft-clauses, one can still use the lexicographic combination rather than pareto one and get the same result.
Otherwise, if there are multiple objectives in addition to the group of soft-clauses, it suffices to explicitly encode the MaxSMT problem with a Pseudo-Boolean objective as opposed to using the assert-soft command. In this way, one retains full control of the associated objective function and can easily fix its value to any number. Note, however, that this might decrease the performance of the solver in dealing with the formula depending on the quality of the MaxSMT encoding.
Related
I am looking at some questions in my textbook about whether or not the variables are free or bound. I am not sure about these two in particular.
First off, I want to make sure I understand the concept of free vs. bound. I am fairly sure this x is a free variable in the following:
variable x is free in expression "x"
I believe this is true but I just want to make sure.
These two questions I am not really sure about, however.
(/ (+ 1 x) (let x 2 (+ x x))),
(let x y (/ (+ 1 x) (let x 2 (+ x x))))
For the top expression, the x in the first subexpression is unbound(right?) but x in the second subexpression is bound to 2, so would that mean the x in regards to the expression as a whole is unbound?
For the bottom expression, x is bound to y, but y is a free variable(?). So would x be free because y is free or is it bound because x is still bounded to y?
For (/ (+ 1 x) (let x 2 (+ x x))), the x in the first subexpression is unbound but x in the second subexpression is bound to 2, so would that mean the x in regards to the expression as a whole is unbound?
Yes. Although I would use the terminology "is bound" or "is free" only with respect to a concrete variable expression, not to a name. As you can see, it's ambiguous what "x" refers to.
I'd say "the whole expression has a free variable x", which is what you usually care about when trying to evaluate the expression.
For (let x y (/ (+ 1 x) (let x 2 (+ x x)))), x is bound to y, but y is a free variable. So would x be free because y is free or is it bound because x is still bounded to y?
The x is bound (and can be substituted). y is free.
I decided reading SICP a little, just to see what it is all about (I am not MIT student, actually already almost done with studying, this is no homework, but the content might be homework for someone.). Since I have installed sbcl, I have to change syntax a little, compared to the book. However, I don't understand why my solution to exercise 1.3 is not working:
(defun square (x) (* x x))
(defun sum-of-squares (x y)
(+ (square x) (square y)))
(defun sum-of-squares-two-max (x y z) (
(cond
((eq (min x y z) x) (sum-of-squares y z))
((eq (min x y z) y) (sum-of-squares x z))
(t (sum-of-squares x y))
)))
To load this I run sbcl --load exercise-1.3.lisp. When I load it, I get the error:
; file: /home/xiaolong/development/LISP/SICP/exercise-1.3.lisp
; in: DEFUN SUM-OF-SQUARES-TWO-MAX
; ((COND ((EQ (MIN X Y Z) X) (SUM-OF-SQUARES Y Z))
; ((EQ (MIN X Y Z) Y) (SUM-OF-SQUARES X Z)) (T (SUM-OF-SQUARES X Y))))
;
; caught ERROR:
; illegal function call
; (DEFUN SUM-OF-SQUARES-TWO-MAX (X Y Z)
; ((COND ((EQ # X) (SUM-OF-SQUARES Y Z)) ((EQ # Y) (SUM-OF-SQUARES X Z))
; (T (SUM-OF-SQUARES X Y)))))
;
; caught STYLE-WARNING:
; The variable X is defined but never used.
;
; caught STYLE-WARNING:
; The variable Y is defined but never used.
;
; caught STYLE-WARNING:
; The variable Z is defined but never used.
;
; compilation unit finished
; caught 1 ERROR condition
; caught 3 STYLE-WARNING conditions
Multiple things I don't understand:
Why are some variables not used? I use all of them in the conditional ...
Why is a function call illegal? How can I compose functions if I cannot call a function from inside a function? (I probably can, but I am doing it wrong?)
When I comment out the third function, it loads without errors.
I checked the syntax for the conditional multiple times already, cannot find the mistake.
How can I correct this code?
Get rid of the extra open paren.
(defun sum-of-squares-two-max (x y z)
(cond
((eq (min x y z) x) (sum-of-squares y z))
((eq (min x y z) y) (sum-of-squares x z))
(t (sum-of-squares x y))))
The issue is that, with the paren, the code will call whatever your cond will evaluate to (as with all first items within parens). Without the paren, it knows that the result of the function is whatever the cond evaluates to.
Also, a general warning: SICP uses scheme, so you'll see some small differences between the book and what common lisp macros force you into.
I apologize in advance for this likely silly question :)
Suppose, I have a list of strings like
(define func-names '("add" "sub" "mul"))
And there are also functions defined like so
(define (add x y)
(+ x y))
(define (sub x y)
(- x y))
(define (mul x y)
(* x y))
As you can see, values of the strings in the list correspond to the names of the functions.
I need a way to iterate through the list and call the function that corresponds to a string value. Something like
(define (all-ops x y)
(map (lambda (name) (string->proc name x y)) func-names))
where string->proc is what I'm looking for. Something like Ruby's send/public_send method, if you're familiar with Ruby.
I'm mostly interested in answers applicable to Racket.
Thank you.
EDIT;
And I've forgotten to mention that there may be a million of function names, so cond, match would be tedious to use here.
Consider making a hash table that maps strings to function values.
That said, you can do as follows:
#lang racket
(define (add x y)
(+ x y))
(define ns (variable-reference->namespace (#%variable-reference)))
(define (string->procedure s)
(define sym (string->symbol s))
(eval sym ns))
(string->procedure "add")
((string->procedure "add") 1 2)
See also http://blog.racket-lang.org/2011/10/on-eval-in-dynamic-languages-generally.html
I know what I want to do, I am having trouble getting there. I am looking for some guidance. I am more or less forcing what I want done and there has to be a better way than the way I am trying to create this function. I currently get an unbound variable error right where I call (set! nadj) and (set! count).
I am trying to make a function where the user inputs a sentence. If more than 25% of that sentence consists of adjectives the function returns false.
This is what I have so far:
(define OK
(lambda (x)
(cond
((adj? (car x))
(set! count (+ count 1)))
((not (adj? (car x))
(set! nadj (+ nadj 1))))
((not (null? (OK (cdr x)))))
((null? x)
(set! sum (+ nadj count)))
;;(set! div (/ count sum))
;;(* 100 div)
;;(< div 25))
((else #f)))))
What I am trying to do is make a counter for the words that are an adjective and a counter for the words that are not. Then I am trying to add all of the words up and divide them by the amount of words that were adjectives. I then want to multiply that by 100 and return true if it is less than 25%. I am not looking for an answer, more or less I just want some guidance.
Here is the adj? function if you need to see it.
(define adjectives '(black brown fast hairy hot quick red slow))
(define adj?
(lambda(x)
(if ( member x adjectives) #t #f)))
I am sure this isn't normal Scheme notation. I program a lot in C++ and Java and I am having a hard time transitioning into Scheme.
You're correct in stating that your solution is not idiomatic Scheme - we try really hard to avoid mutating variables, all those set! operations are frowned upon: we don't really need them. A more idiomatic solution would be to pass along the counters as parameters, as demonstrated in #uselpa's answer. His solution uses explicit recursion via a named let.
We can go one step further, though - the true spirit of functional programming is to reuse existing higher-order procedures and compose them in such a way that they solve our problems. I don't know which Scheme interpreter you're using, but in Racket the OK procedure can be expressed as simply as this:
(define (OK x) ; assuming a non-empty list
(< (/ (count adj? x) ; count the number of adjectives
(length x)) ; divide by the total number of words
0.25)) ; is it less than 25%?
If your Scheme interpreter doesn't provide a count procedure import it from SRFI-1; also it's very easy to implement your own - again, this is in the spirit of functional programming: we want to build generic procedures that are useful in their own right, and easily reused and composed in other contexts:
(define (count pred lst)
(let loop ((lst lst) (counter 0))
(cond ((null? lst) counter)
((pred (car lst)) (loop (cdr lst) (+ 1 counter)))
(else (loop (cdr lst) counter)))))
Playing Devil's advocate it's possible to fix your function using an imperative style, as long as we define the variables first (by the way, that was causing the "unbound variable" error) - for example, place a let before the looping function: think of it as a variable declaration that happens before the recursion starts. Also notice that the empty list case must appear first, to avoid accessing an element in an empty list, and don't forget to advance the recursion at each step. This is ugly, but should work:
(define (OK x) ; assuming a non-empty list
; declare the counters outside the function
(let ((adj 0) (nadj 0))
; looping function
(let loop ((x x))
(cond
; is the list empty?
((null? x)
; is the number of adjectives less than 25%?
(< (/ adj (+ adj nadj)) 0.25))
; is current element an adjective?
((adj? (car x))
; increment adj counter
(set! adj (+ adj 1))
; always advance recursion
(loop (cdr x)))
; is current element anything other than an adjective?
(else
; increment nadj counter
(set! nadj (+ nadj 1))
; always advance recursion
(loop (cdr x)))))))
I don't know if you are familiar with the named let, but this comes in handy here:
(define (OK x)
(let loop ((x x) (adj 0) (nadj 0)) ; named let
(cond
((null? x) (< (/ adj (+ adj nadj)) 0.25))
((adj? (car x)) (loop (cdr x) (+ 1 adj) nadj))
(else (loop (cdr x) adj (+ 1 nadj))))))
This is a convenient notation for the following, equivalent code:
(define (OK x)
(define (loop x adj nadj)
(cond
((null? x) (< (/ adj (+ adj nadj)) 0.25))
((adj? (car x)) (loop (cdr x) (+ 1 adj) nadj))
(else (loop (cdr x) adj (+ 1 nadj)))))
(loop x 0 0))
so basically we define an internal function, and what is a loop in a language such as C++ and Java becomes a recursive call (and to add to the confusion, the procedure that gets called recursively is sometimes called loop, as in my example). Since the call is done in tail position, this is just as efficient in Scheme as a classic loop in the languages you mentioned.
Variable assignments are replaced by modifying the parameters of the recursive call, i.e. you usually find no set! procedures in such a simple case.
EDIT an example implementation using set!:
(define OK
(let ((adj 0) (nadj 0))
(lambda (x)
(cond
((null? x) (< (/ adj (+ adj nadj)) 0.25))
(else (if (adj? (car x))
(set! adj (+ 1 adj))
(set! nadj (+ 1 nadj)))
(OK (cdr x)))))))
You can't set an unbound variable, even a global one. Variables refer to locations; setting a variable that doesn't exist anywhere is impossible:
(set! a 1)
;Unbound variable: a ; a doesn't refer to any location yet
(define a)
;Value: a
(list a)
;Unassigned variable: a ; now it does, but it hasn't been assigned a value yet
(set! a 1)
;Value: a
(list a)
;Value: (1)
(set! a 2)
;Value: 1
(list a)
;Value: (2)
There's nothing wrong with localized and encapsulated mutation. Setting a global variable is by definition not localized.
You should have created local bindings (locations) for the variables you intended to use. The basic iteration built-in form do does it for you:
(define (OK x)
(do ((adj 0) (nadj 0))
((null? x) ; loop termination condition
(< (/ adj (+ adj nadj))
0.25)) ; return value form
; loop body
(if (adj? (car x))
(set! adj (+ adj 1))
; else
(set! nadj (+ nadj 1)))
; some other statements maybe...
))
Just another option that sometimes might come handy. Of course the most idiomatic Scheme code is using named let construct. It will also force you to refactor a spaghetti code that you might otherwise write using do. Don't. :)
Define a function sum, which takes two numbers, or two real functions, and returns their sum. E.g.
(sum 1 2) => 3
((sum cos exp) 0) => 2
I get that for the sum of two numbers the code would be the following:
(define sum (lambda (x y)
(+ x y)))
But what would be the code for the two real functions...? How would I do this? can anyone please help?
Also how would I do this:
Define a function sum-all which works like sum, but works on a list of numbers or a list of functions. Assume the list contains at least one element.
E.g.
(sum-all (list 1 2 3)) => 6
((sum-all (list cos sin exp)) 0) => 2
Note: this is not homework... I was going through a past midterm.
For the first part of your question, I'll have to agree with PJ.Hades that this is the simplest solution:
(define (sum x y)
(if (and (number? x) (number? y))
(+ x y)
(lambda (n)
(+ (x n) (y n)))))
For the second part, we can make good use of higher-order procedures for writing a simple solution that is a generalization of the previous one:
(define (sum-all lst)
(if (andmap number? lst)
(apply + lst)
(lambda (n)
(apply + (map (lambda (f) (f n)) lst)))))
In both procedures, I'm assuming that all the operands are of the same kind: they're either all-numbers or all-functions, as inferred from the sample code provided in the question.
Do you mean this?
(define (sum a b)
(if (and (number? a) (number? b))
(+ a b)
(lambda (x)
(+ (a x) (b x)))))
(define (sum lst)
(cond
[(empty? lst) 0]
[else (foldr + 0 lst)]))
((lambda (a b) (+ a b)) 4 5)
this how it is done using lambda.
using define we can write as follows
(define (sum a b) (+ a b))
I'm a little rusty with my Scheme, so perhaps there's a better way to do this, but you could do:
(define (sum-all lst)
(define (sum-funcs-helper funcs x)
(if (empty? funcs)
0
(+ ((car funcs) x)
(sum-funcs-helper (cdr funcs) x))))
(if (empty? lst)
0 ;; Beats me what this is supposed to return.
(if (number? (car lst))
(apply + lst)
(lambda (x) (sum-funcs-helper lst x)))))