From outdoor to screen i wrote today an infix version of the program Conway's Game of Life that was in pyffi-test :
the 2 versions are here: test-numpy-game-of-life+.rkt
#lang reader SRFI-105 ; you can use SRFI-105 or SRFI-110
(module numpy-game-of-life racket/base
(require (rename-in Scheme+
(for for+)
(:= :=s)
(-> s->)))
(require pyffi pyffi/numpy)
(require "pyffi-infix+.rkt")
;;; Conway's Game of Life
(initialize) ; handles `main` and `builtins`
(import-numpy)
; ; load the `numpy` module
; ; import and initialize numpy before
; ; running the delayed initializers
(finish-initialization) ; run delayed setters
(define Z (numpy.array '[[0 0 0 0 0 0]
[0 0 0 1 0 0]
[0 1 0 1 0 0]
[0 0 1 1 0 0]
[0 0 0 0 0 0]
[0 0 0 0 0 0]]))
;; The matrix has a border consisting of zeros.
;; This makes it easier to apply the rules without worrying about special case.
;; We do not want to show the border however, so we use `show` to display the
;; the inner parts of our matrix.
(define (show A)
; remove outer border
; for each row, display it
(for ([i (len A)])
(displayln (numpy.ndarray.tolist {A[i]} #;(ref A i) )))
(newline))
'Z
(show Z)
'Z.T
(show (.T Z))
'Z
(show Z)
;; def compute_neigbours(Z):
;; shape = len(Z), len(Z[0])
;; N = [[0,]*(shape[0]) for i in range(shape[1])]
;; for x in range(1,shape[0]-1):
;; for y in range(1,shape[1]-1):
;; N[x][y] = Z[x-1][y-1]+Z[x][y-1]+Z[x+1][y-1] \
;; + Z[x-1][y] +Z[x+1][y] \
;; + Z[x-1][y+1]+Z[x][y+1]+Z[x+1][y+1]
;; return N
;; (define (compute-neighbours Z)
;; ;; (displayln (list (list 'len len)
;; ;; (list 'numpy.array numpy.array)))
;;
;; (define shape (vector (len Z) (len (ref Z 0))))
;; (define N (numpy.array
;; (for/list ([i (ref shape 1)])
;; (mul '(0) (ref shape 0)))))
;; (for*/list ([x (in-range 1 (- (ref shape 0) 1))]
;; [y (in-range 1 (- (ref shape 1) 1))])
;; (define-values (x- x+) (values (- x 1) (+ x 1)))
;; (define-values (y- y+) (values (- y 1) (+ y 1)))
;; (:= N [x y] (+ (ref Z x- y-) (ref Z x y-) (ref Z x+ y-)
;; (ref Z x- y ) (ref Z x+ y)
;; (ref Z x- y+) (ref Z x y+) (ref Z x+ y+))))
;; N)
(define (compute-neighbours Z)
;; (displayln (list (list 'len len)
;; (list 'numpy.array numpy.array)))
(define shape (vector (len Z) (len {Z[0]})))
(define N (numpy.array
(for/list ([i {shape[1]}])
{'(0) * shape[0]})))
(for*/list ([x (in-range 1 {shape[0] - 1})]
[y (in-range 1 {shape[1] - 1})])
{(x- x+) <- (values (x - 1) (x + 1))}
{(y- y+) <- (values (y - 1) (y + 1))}
;; {N[x y] <- (+ Z[x- y-] Z[x y-] Z[x+ y-]
;; Z[x- y] Z[x+ y]
;; Z[x- y+] Z[x y+] Z[x+ y+])})
;; ; this syntax also works:
{N[x y] <- Z[x- y-] + Z[x y-] + Z[x+ y-]
+ Z[x- y] + Z[x+ y]
+ Z[x- y+] + Z[x y+] + Z[x+ y+]})
N)
(show (compute-neighbours Z))
;; ;; def iterate(Z):
;; ;; N = compute_neighbours(Z)
;; ;; for x in range(1,shape[0]-1):
;; ;; for y in range(1,shape[1]-1):
;; ;; if Z[x][y] == 1 and (N[x][y] < 2 or N[x][y] > 3):
;; ;; Z[x][y] = 0
;; ;; elif Z[x][y] == 0 and N[x][y] == 3:
;; ;; Z[x][y] = 1
;; ;; return Z
;; (define (iterate Z)
;; (define N (compute-neighbours Z))
;; (define shape (vector (len Z) (len (ref Z 0))))
;; (for* ([x (in-range 1 (- (ref shape 0) 1))]
;; [y (in-range 1 (- (ref shape 1) 1))])
;; (cond [(and (= (ref Z x y) 1) (or (< (ref N x y) 2) (> (ref N x y) 3)))
;; (:= Z [x y] 0)]
;; [(and (= (ref Z x y) 0) (= (ref N x y) 0))
;; (:= Z [x y] 1)]))
;; Z)
(define (iterate Z)
(define N (compute-neighbours Z))
(define shape (vector (len Z) (len {Z[0]})))
(for* ([x (in-range 1 {shape[0] - 1})]
[y (in-range 1 {shape[1] - 1})])
(cond [{Z[x y] = 1 and (N[x y] < 2 or N[x y] > 3)}
{Z[x y] <- 0}]
[{Z[x y] = 0 and N[x y] = 0}
{Z[x y] <- 1}]))
Z)
(show Z)
(void (for ([i 4]) (iterate Z)))
(show Z)
)
it uses also this file: pyffi/pyffi-tests/tests/pyffi-infix+.rkt at main · damien-mattei/pyffi · GitHub
#lang reader SRFI-105
(module pyffi-infix racket/base
(provide *
numpy-array?
ndarray-line-ref
ndarray-line-set!
set)
(require (rename-in Scheme+
(:= :=s) ; for compatibility with pyffi
(-> s->)))
(require pyffi
pyffi/numpy
;pyffi/numpy-core
)
;(set-environment-variables) ; do not know what it does?
(initialize)
(display "initialize passed") (newline)
;(display "initialize passed") (newline)
(import-numpy)
(display "import-numpy passed") (newline)
;; 2 methods below seems to work
;(post-initialize)
;(display "post-initialize passed") (newline)
(finish-initialization)
(display "finish-initialization passed") (newline)
;(declare-special-prefix numpy)
(import numpy)
; getter for ndarray line
(define (ndarray-line-ref A lin)
(numpy.take A (numpy.array (list lin)) #:axis 0))
; setter for ndarray line
(define (ndarray-line-set! A lin vect-line)
{shp <- (numpy.shape A)}
{size-col <- shp[0]}
(numpy.put_along_axis A
(numpy.full (pytuple size-col 1)
(numpy.array (list lin)))
vect-line
0))
; predicate for ndarray
(define (numpy-array? A)
(builtins.isinstance A (builtins.type (numpy.array '(0)))))
;; > {Z[2]}
;; ($bracket-apply$ Z 2)
;; (obj "ndarray" : array([[0, 0, 0, 1, 0, 0]]))
;; {Z[2] <- (numpy.array '[[0 -7 0 0 0 0]])}
;;(overload-square-brackets ndarray-line-ref ndarray-line-set! (numpy-array? number?))
;; to be compatible with game of life original program i will use instead of above overloading this below:
;; the difference is only returning [x y z ...] instead of [[x y z ...]]
(overload-square-brackets ref ndarray-line-set! (numpy-array? number?))
(define-overload-existing-operator *)
(overload-existing-operator * mul (list? number?))
(define (set A x y val)
(:= A [x y] val))
;; example:
;; {N[x y] <- Z[x- y-] + Z[x y-] + Z[x+ y-]
;; + Z[x- y] + Z[x+ y]
;; + Z[x- y+] + Z[x y+] + Z[x+ y+]}
(overload-square-brackets ref set (numpy-array? number? number?))
)
I wish you all a sunny week-end.