I'm trying to get more speed out of a little quadratic solver by using optimizations and fixnums. Here's my code:
1: (defun solve-x (d)
2: (declare (optimize (speed 3))
3: (type fixnum d))
4: (let ((x 1) (y 1))
5: (declare (type fixnum x y))
6: (loop while (/= (- (* x x) (* d y y)) 1) do
7: (if (> (- (* x x) (* d y y)) 1)
8: (incf y)
9: (incf x)))
10: (list x y)))
The SBCL compiler seems to have trouble optimizing lines 6 and 7 correctly. I'm getting lots of warnings like this one:
forced to do GENERIC-- (cost 10)
unable to do inline fixnum arithmetic (cost 2) because:
The first argument is a (INTEGER 1 21267647932558653957237540927630737409), not a FIXNUM.
The second argument is a (INTEGER
-98079714615416886892398913872502479823289163909206900736
98079714615416886871131265939943825866051622981576163327), not a FIXNUM.
The result is a (VALUES
(INTEGER
-98079714615416886871131265939943825866051622981576163326
98079714615416886913666561805061133780526704836837638145)
&OPTIONAL), not a (VALUES FIXNUM &REST T).
unable to do inline (signed-byte 64) arithmetic (cost 5) because:
The first argument is a (INTEGER 1 21267647932558653957237540927630737409), not a (SIGNED-BYTE
64).
The second argument is a (INTEGER
-98079714615416886892398913872502479823289163909206900736
98079714615416886871131265939943825866051622981576163327), not a (SIGNED-BYTE
64).
The result is a (VALUES
(INTEGER
-98079714615416886871131265939943825866051622981576163326
98079714615416886913666561805061133780526704836837638145)
&OPTIONAL), not a (VALUES (SIGNED-BYTE 64) &REST T).
etc.
Don't know, where to continue. I already tried to insert 'the fixnum' around multiplications, divisions and subtractions, but it only got worse.
Any ideas, how to make this fast?
If you're sure that the numbers will not overflow at any point, you can add (SAFETY 0) to the optimizations. Also add (THE FIXNUM ...) around the calculations to tell SBCL that you want the result to be treated as a fixnum. The three argument * should be split to two separate calls.
Your code is currently calculating (- (* x x) (* d y y)) twice in the loop. You should assign it to a variable instead. Also notice that since only X or Y changes in the loop, it's unnecessary to calculate the other part again (I don't know what those calculations are, so I just called them FOO, BAR and QUUX).
(defun solve-x (d)
(declare (optimize (speed 3) (safety 0) (debug 0))
(type fixnum d))
(let ((x 1) (y 1))
(declare (type fixnum x y))
(loop with foo of-type fixnum = (* x x)
with bar of-type fixnum = (* (the fixnum (* d y)) y)
for quux of-type fixnum = (- foo bar)
while (/= quux 1)
do (if (> quux 1)
(setf y (1+ y)
bar (* (the fixnum (* d y)) y))
(setf x (1+ x)
foo (* x x))))
(list x y)))
To avoid having to write the formulas twice, you could use the #n= reader macro. X and Y can also be moved to the parameter list as &AUX variables to get rid of the LET and second DECLARE.
(defun solve-x (d &aux (x 1) (y 1))
(declare (optimize (speed 3) (safety 0) (debug 0))
(type fixnum d x y))
(loop with foo of-type fixnum = #1=(* x x)
with bar of-type fixnum = #2=(* d (the fixnum (* y y)))
for quux of-type fixnum = (- foo bar)
while (/= quux 1)
do (if (> quux 1)
(setf y (1+ y)
bar #2#)
(setf x (1+ x)
foo #1#)))
(list x y))
Since X and Y always increase by one, you could avoid some multiplication by incrementing the previous value.
(defun solve-x (d &aux (x 1) (y 1))
(declare (optimize (speed 3) (safety 0) (debug 0))
(type fixnum d x y))
(loop with foo of-type fixnum = 1
with bar of-type fixnum = d
for quux of-type fixnum = (- foo bar)
while (/= quux 1)
do (if (> quux 1)
(setf bar (+ bar (the fixnum (* d y)))
y (1+ y)
bar (+ bar (the fixnum (* d y))))
(setf foo (+ foo x)
x (1+ x)
foo (+ foo x))))
(list x y))
The problem is that fixnum is not a very useful type. In particular, if a and b are fixnums then (* a b) may well not be: consider (* most-positive-fixnum most-positive-fixnum): this is not a fixnum.
So what you need to do is declare the arguments to have good types: in particular types which are enough smaller than a fixnum that the arithmetic will not overflow into bignums. Assuming you're using a 64-bit platform this is reasonably easy.
I don't know how large those numbers can get in your application but by declaring them to be (signed-byte 31) can result in another 25-ish % speed gain.
(deftype int31 (&optional (bits 31)) `(signed-byte ,bits))
(defun solve-x (d &aux (x 1) (y 1))
(declare (optimize (speed 3) (safety 0) (debug 0))
(type int31 d x y))
(loop with foo of-type int31 = 1
with bar of-type int31 = d
for quux of-type int31 = (- foo bar)
while (/= quux 1)
do (if (> quux 1)
(setf bar (+ bar (the int31 (* d y)))
y (1+ y)
bar (+ bar (the int31 (* d y))))
(setf foo (+ foo x)
x (1+ x)
foo (+ foo x))))
(list x y))
Related
I'm having a trouble with some Common Lisp code. I have two functions similars to the functions below:
(defun recursive-func (func lst num)
(let ((test
(some-func func
(first lst)
(first (rest lst))
num))
(next
(recursive-func func
(rest lst)
num)))
(cond ((null (rest lst)) nil)
((null test) next)
(t (cons test next)))))
(defun some-func (func a b num)
(if (> a b)
nil
(funcall func a b num)))
When the list has only one element I want recursive-func return nil, but it doesn't and calls some-func generating a evaluation abort because b is nil. Here is a trace of execution:
CL-USER> (recursive-func #'(lambda(x y z) (+ x y z)) '(1 2 3 4 5) 5)
0: (RECURSIVE-FUNC #<FUNCTION (LAMBDA (X Y Z)) {10035F6ABB}> (1 2 3 4 5) 5)
1: (SOME-FUNC #<FUNCTION (LAMBDA (X Y Z)) {10035F6ABB}> 1 2 5)
1: SOME-FUNC returned 8
1: (RECURSIVE-FUNC #<FUNCTION (LAMBDA (X Y Z)) {10035F6ABB}> (2 3 4 5) 5)
2: (SOME-FUNC #<FUNCTION (LAMBDA (X Y Z)) {10035F6ABB}> 2 3 5)
2: SOME-FUNC returned 10
2: (RECURSIVE-FUNC #<FUNCTION (LAMBDA (X Y Z)) {10035F6ABB}> (3 4 5) 5)
3: (SOME-FUNC #<FUNCTION (LAMBDA (X Y Z)) {10035F6ABB}> 3 4 5)
3: SOME-FUNC returned 12
3: (RECURSIVE-FUNC #<FUNCTION (LAMBDA (X Y Z)) {10035F6ABB}> (4 5) 5)
4: (SOME-FUNC #<FUNCTION (LAMBDA (X Y Z)) {10035F6ABB}> 4 5 5)
4: SOME-FUNC returned 14
4: (RECURSIVE-FUNC #<FUNCTION (LAMBDA (X Y Z)) {10035F6ABB}> (5) 5)
5: (SOME-FUNC #<FUNCTION (LAMBDA (X Y Z)) {10035F6ABB}> 5 NIL 5)
; Evaluation aborted on #<TYPE-ERROR expected-type: NUMBER datum: NIL>.
I hope someone would can help me, thanks.
The bindings in let are evaluated first, and only then you perform the tests in the cond.
You need only change a bit:
(defun recursive-func (func list num)
(if (null (rest list))
nil
(let ((test (some-func func
(first list)
(first (rest list))
num))
(next (recursive-func func
(rest list)
num)))
(cond ((null test) next)
(t (cons test next))))))
Note that the cond could also be written:
(if test (cons test next) next)
With your example:
(recursive-func (lambda (x y z) (+ x y z))
'(1 2 3 4 5)
5)
=> (8 10 12 14)
Alternatively, here is how you could decompose the task (in the REPL):
> (maplist (lambda (list)
(list
(first list)
(second list)))
'(1 2 3 4 5))
=> ((1 2) (2 3) (3 4) (4 5) (5 NIL))
Prefer SECOND instead of (first (rest ...)).
The last result is bound in the REPL to the variable *. Remove the last (useless) pair with BUTLAST:
(butlast *)
=> ((1 2) (2 3) (3 4) (4 5))
Then, for each couple in this list, call your function -- here it is just +. Notice the use of DESTRUCTURING-BIND:
(mapcar (lambda (list)
(destructuring-bind (a b) list
(+ a b 5)))
*)
=> (8 10 12 14)
So, basically, your function can be written as:
(defun map-pair-funcall (function list number)
(mapcar (lambda (pair)
(destructuring-bind (a b) pair
(funcall function a b number)))
(butlast (maplist (lambda (list)
(list (first list) (second list)))
list))))
And thus:
(map-pair-funcall #'+ '(1 2 3 4 5) 5)
=> (8 10 12 14)
Edit:
I missed the case where the supplied function might return NIL. Wrap the form calling mapcar by (remove NIL (mapcar ...)) to filter that out.
You can perform all that in one iteration by using MAPCON. The function iterates over sublists, and concatenates the resulting lists. The function being called should thus return list, and when you return NIL, the result are simply discarded.
Let's define ensure-list (or use the one from Alexandria):
(defun ensure-list (expr)
(if (listp expr) expr (list expr)))
The function wraps the returned value in a list, except if it is already a list (in particular, NIL). And then, the function is defined as follows:
(defun map-pair-funcall (function list number)
(mapcon (lambda (list)
(and (second list)
(ensure-list (funcall function
(first list)
(second list)
number))))
list))
You could also LOOP:
(defun map-pair-funcall (function list number)
(loop
for (a b) on list
for result = (and b (funcall function a b number))
when result
collect result))
I'm a newbie to scheme programming and I was writing small codes when I encountered the following issue and couldn't reason about it satisfactorily.
(define (at_i lst i)
(if (eq? i 0)
(car lst)
(at_i (cdr lst)
(- i 1) )))
Evaluation of (at_i '(1 2 3 4) 0) returns 1.
Now lets define same procedure with a lambda syntax.
(define (at_i lst i)
(lambda (vec x)
(if (eq? x 0)
(car vec)
(at_i (cdr vec)
(- x 1) )))
lst i)
But now Evaluation of (at_i '(1 2 3 4) 0) returns 0, which is not in the list and in general, it returns element at index-1.
I don't understand why this is happening.
Note: I just realized its not returning element at index - 1 but the index itself. The reason for this has been well explained below by #Renzo. Thanks!
First, you should indent properly the code if you intend to learn the language, since code indentation is very important to understand programs in Scheme and Lisp-like languages.
For instance, your function correctly indented is:
(define (at_i lst i)
(lambda (vec x)
(if (eq? x 0)
(car vec)
(at_i (cdr vec) (- x 1))))
lst
i)
From this you can see that you are defining the function at_i exactly as before in terms of a function with two parameters (lst and i), and whose body is constitued by three expressions: the first lambda (vec x) ... (- x 1)))), which is an (anonymous) function (lambda) which is not called or applied, the second, which is the first parameter lst, and finally the third which is the second parameter i. So, when the function at_i is called with two arguments, the result is the evaluation of the three expressions in sequence, the first two values are discarded (the function and the value of lst), and the result is the value of the second parameter i. This is reason for which the result of (at_i '(1 2 3 4) 0) is 0, since it is the value of i.
A proper redefinition of the function in lambda form would be the following, for instance:
(define at_i
(lambda (vec x)
(if (eq? x 0)
(car vec)
(at_i (cdr vec) (- x 1)))))
(at_i '(1 2 3 4) 0) ;; => 1
in which you can see that the name at_i, through the define, is associated to a two parameter function which calculates correctly the result.
eq? is memory object equality. Only some Scheme implementations interpret (eq? 5 5) as #t. Use = for numbers, eqv? for values, and equal? for collections.
(define (index i xs) ; `index` is a partial function,
(if (= i 0) ; `i` may go out of range
(car xs)
(index (- i 1) ; Tail recursion
(cdr xs) )))
Your second function returns the index because you missed parenthesis around the lambda's application. It should be
(define (index i xs)
((lambda (i' xs')
(if (= i' 0)
(car xs')
(index (- i' 1) ; Not tail-recursive
(cdr xs') )))
i xs))
But this is verbose and differs semantically from the first formulation.
You say you are defining the "same procedure with a lambda syntax", but you are not. That would be (define at_i (lambda lst i) ...). Instead, you are effectively saying (define (at_i lst i) 1 2 3), and that is 3, of course.
In your particular case, you defined the procedure at_i to return (lambda (vec x) ...), lst and i. Now, if you call (at_i '(1 2 3 4) 0), the procedure will return 0, since that is the value of i at this point.
I am having some trouble here, and hopefully you guys can help.
Basically, what I am trying to do is overload the + sign in racket so that it will add two vectors instead of two numbers. Also, I want to keep the old + operator so that we can still use it. I know this is supposed to work in scheme, so I was told I needed to use module* to do it in racket. I am still not entirely sure how it all works.
Here is what I have so far:
#lang racket
(module* fun scheme/base
(define old+ +)
(define + new+)
(define (new+ x y)
(cond ((and (vector? x) (vector? y))
(quatplus x y))
(else (old+ x y))))
(define (quatplus x y)
(let ((z (make-vector 4)))
(vector-set! z 0 (old+ (vector-ref x 0) (vector-ref y 0)))
(vector-set! z 1 (old+ (vector-ref x 1) (vector-ref y 1)))
(vector-set! z 2 (old+ (vector-ref x 2) (vector-ref y 2)))
(vector-set! z 3 (old+ (vector-ref x 3) (vector-ref y 3)))
z)))
But it doesn't seem to do anything at all. If anyone knows anything about this I would be very appreciative.
Thank you.
How I would do this is to use the except-in and rename-in specs for require:
#lang racket/base
(require (except-in racket + -)
(rename-in racket [+ old+] [- old-]))
(define (+ x y)
(cond [(and (vector? x) (vector? y))
(quatplus x y)]
[else (old+ x y)]))
(define (quatplus x y)
(vector (+ (vector-ref x 0) (vector-ref y 0))
(+ (vector-ref x 1) (vector-ref y 1))
(+ (vector-ref x 2) (vector-ref y 2))
(+ (vector-ref x 3) (vector-ref y 3))))
(+ (vector 1 2 3 4) (vector 1 2 3 4))
;; => #(2 4 6 8)
You could also use prefix-in with only-in, which would be more convenient if you had many such functions to rename:
(require (except-in racket + -)
(prefix-in old (only-in racket + -)))
A few points:
I had quatplus simply return a new immutable vector (instead of using make-vector and set!). It's simpler and probably faster.
Racket's + accepts any number of arguments. Maybe yours should?
As written, your new + will fail for the combination of a non-vector and a vector. You probably want to fix that:
(+ 1 (vector 1 2 3 4))
; +: contract violation
; expected: number?
; given: '#(1 2 3 4)
; argument position: 1st
; other arguments...:
; 1
You can use Scheme encapsulation to accomplish your needs as:
(import (rename (rnrs) (+ numeric+)))
(define +
(let ((vector+ (lambda (v1 v2) (vector-map numeric+ v1 v2)))
(list+ (lambda (l1 l2) (map numeric+ l1 l2)))
;; …
)
(lambda (a b)
(cond ((and (vector? a) (vector? b)) (vector+ a b))
((and (list? a) (list? b)) (list+ a b))
;; …
(else (numeric+ a b))))))
and if you wanted to work the addition to any depth, this should work:
(define +
(letrec ((vector+ (lambda (v1 v2) (vector-map any+ v1 v2)))
(list+ (lambda (l1 l2) (map any+ l1 l2)))
(any+ (lambda (a b)
(cond ((and (vector? a) (vector? b)) (vector+ a b))
((and (list? a) (list? b)) (list+ a b))
;; …
(else (numeric+ a b))))))
any+))
See:
> (+ (vector (list 1 2) 3) (vector (list 11 12) 13))
#((12 14) 16)
I am trying to solve some maximum/minimum problems using Z3 SMT-LIB online.
One example is:
Find two nonnegative numbers whose sum is 9 and so that the product of one number and the square of the other number is a maximum.
After many attempts the following code was constructed
(define-fun f ((x Real) (y Real)) Real
(if (not (= y 0.0))
(* y (^ x (- y 1)))
0.0))
(declare-const x Real)
(declare-const y Real)
(declare-const z Real)
(declare-const v Real)
(simplify (* x (^ (- 9 x) 2)) :som true)
(assert (= y (* 81.0 (f x 1))))
(assert (= z (* 18.0 (f x 2))))
(assert (= v (f x 3)))
(assert (= z (+ y v )))
(assert (not (= x 0)))
(assert (not (= x 9)))
(set-option :pp-decimal true)
(apply (then simplify solve-eqs))
(check-sat)
(get-model)
The output is:
(+ (* 81.0 x) (* (- 18.0) x x) (* x x x))
(goals
(goal (= (* 36.0 x) (+ (* 81.0 (^ x 0.0)) (* 3.0 (^ x 2.0))))
(not (= x 0.0))
(not (= x 9.0))
:precision precise :depth 2) )
sat
(model
(define-fun x () Real 3.0)
(define-fun v () Real 27.0)
(define-fun z () Real 108.0)
(define-fun y () Real 81.0) )
Run this example online here
Please let me know if you have a more efficient code for this problem. Many thanks.
I have the following function that given an expression, executes it :
(define (foo exp0) exp0)
If I do the following:
(define x 5)
(foo (+ x 4))
(foo (* x 2))
display(x)
I would like for display(x) to display 18. Basically, how can I assign the value of the given expression back to the given variable?
First, the foo procedure is simply returning the parameter, it's not "executing" it. Answering your question, here's how you can reassign a value in Scheme:
(define x 5)
(set! x (+ x 4))
(set! x (* x 2))
(display x)
But to tell the truth, that style of programming (mutating variables) is frowned upon in Scheme. I believe this is more idiomatic:
(let* ((x 5)
(y (+ x 4))
(z (* y 2)))
(display z))
You can indeed write such a macro, if you can guarantee that the variable you're updating is always the first operand:
(define-syntax foo
(syntax-rules ()
((foo (op var arg ...))
(set! var (op var arg ...)))))