From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Damien Mattei Newsgroups: gmane.lisp.guile.user Subject: Re: matrix library? Date: Fri, 6 Oct 2023 19:23:10 +0200 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="34621"; mail-complaints-to="usenet@ciao.gmane.io" Cc: Nala Ginrut , guile-user To: tomas@tuxteam.de Original-X-From: guile-user-bounces+guile-user=m.gmane-mx.org@gnu.org Fri Oct 06 19:23:58 2023 Return-path: Envelope-to: guile-user@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1qooYQ-0008l1-2Z for guile-user@m.gmane-mx.org; Fri, 06 Oct 2023 19:23:58 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qooXv-0000W7-Pa; Fri, 06 Oct 2023 13:23:27 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qooXu-0000Vf-Gq for guile-user@gnu.org; Fri, 06 Oct 2023 13:23:26 -0400 Original-Received: from mail-ed1-x52d.google.com ([2a00:1450:4864:20::52d]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qooXs-0004Bk-3B for guile-user@gnu.org; Fri, 06 Oct 2023 13:23:26 -0400 Original-Received: by mail-ed1-x52d.google.com with SMTP id 4fb4d7f45d1cf-53627feca49so4073525a12.1 for ; Fri, 06 Oct 2023 10:23:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1696613002; x=1697217802; darn=gnu.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=nR0rDGS7lgpZbUgKXQU7tpTkk5HbDzQ+oqqHDgv6dqg=; b=aXTPLWFMslbY4huyFJhS/I9q1IxjH1bokW6CMag3ZGm9e9uFCCkm4wsXRucviY9+iB bJWG0N/WcO6ZKguZmq0mCINvKRiXNdn/S9mZ7loMrWtZe0xsz/3F5fcGjShrlqoBwWvz nhrZbcoVL+fiYMfxNh1UF/YxiaZq7pOL0sdWBoaFG6y/PRaNUpn7BKcyrdsXcT2/5meB Fm7vozt4jypm2kkrSSA8Rj9n6ZussNukuFxsa34wyEtau2IXPbY/IwMla3SB2ijna73y 5sSBYwfD4tfb0dm6w/qInvS+WZjYIgHBAl7gqlS9mKzIa5ZrhaEZ3VrRKn2aXcYiiuRN E/KA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1696613002; x=1697217802; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=nR0rDGS7lgpZbUgKXQU7tpTkk5HbDzQ+oqqHDgv6dqg=; b=RsvVAgb3Eau1a9F1zmIx10WIumz029BAlhZp5uAiA8OqUM5+1jcB3Ygk/2tAiPKuNU qDMBsMb0mjqMoRTR3Zj0Iib1MYwl+q/LwI+3bLSKGNrsTK6956WAwAhubFe1HwC343AX //zr2/mDscjaSQHxHrISiIAXAaypN3WtyHGrV+2GaUA+e5ffIV2kr6eMvEDZu4qGGnEP nPsZ9pPlAPDskn/COVjk8f4TjG+Xow/pOmQrdmw+lxlU0iqpOLPmG965T5Z+93BH4bbG pheX/FqrSodYnJWO5YuaM5JgoY3vY/6c8mqHPzKndd127O1yM4ljJHEpi7lH2YWn27mk bZKg== X-Gm-Message-State: AOJu0YyjwcYTEMHrZtWR+CtvZMlZUuz43vy2mHEqgTrML/fd9DJ7BEDr z94BWYEe2aGj8jy2jwIl2ka8HBfizwB5wTHPKRy0LAWUGFM= X-Google-Smtp-Source: AGHT+IFZEXIJLgcYSTptm8wLVAdpLlp1TZbm+ITYL3h5cFe5K7g0vntsmXVpZOSw1Yy3TB/U8/Ebg55+ashfTuR18tQ= X-Received: by 2002:a05:6402:1b05:b0:523:bfec:490f with SMTP id by5-20020a0564021b0500b00523bfec490fmr8208854edb.0.1696613001922; Fri, 06 Oct 2023 10:23:21 -0700 (PDT) In-Reply-To: Received-SPF: pass client-ip=2a00:1450:4864:20::52d; envelope-from=damien.mattei@gmail.com; helo=mail-ed1-x52d.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: guile-user@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: General Guile related discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guile-user-bounces+guile-user=m.gmane-mx.org@gnu.org Original-Sender: guile-user-bounces+guile-user=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.lisp.guile.user:19240 Archived-At: and the rest of code for multiplying a matrix and a vector: (define (vector->matrix-column v) (matrix (vector-map (lambda (i x) (make-vector 1 x)) v))) (define (matrix-column->vector Mc) {v <+ (matrix-v Mc)} (vector-map (lambda (i v2) {v2[0]}) v)) ;; scheme@(guile-user)> (define M1 (create-matrix-by-function (lambda (l c) (+ l c)) 2 3)) ;; scheme@(guile-user)> (matrix-v M1) ;; $1 =3D #(#(0 1 2) #(1 2 3)) ;; scheme@(guile-user)> {M1 * #(1 2 3)} ;; $2 =3D #(8 14) (define-method (* (M ) (v )) ;; args: matrix ,vector ; return vector {Mc <+ (vector->matrix-column v)} ;(display Mc) (matrix-column->vector {M * Mc})) ;; define getter,setter (define (matrix-ref M lin col) {v <+ (matrix-v M)} {v[lin][col]}) (define (matrix-set! M lin col x) {v <+ (matrix-v M)} {v[lin][col] <- x}) ;; > (overload-square-brackets matrix-ref matrix-set! (matrix? number? number?)) ;; > (overload-square-brackets matrix-line-ref (lambda (x) '()) (matrix? number?)) ;; > $ovrld-square-brackets-lst$ ;; '(((# #) (# . #)) ;; ((# # #) (# . #))) ;; > (define Mv (matrix #(#(1 2 3) #(4 5 6)))) ;; > Mv ;; # ;; > (find-getter-for-overloaded-square-brackets (list Mv 1)) ;; # ;; > {Mv[1 0]} ;; 4 ;; > {Mv[1]} ;; '#(4 5 6) ;; > {Mv[1][0]} ;; 4 ;; > (define (matrix-line-ref M lin) {v <+ (matrix-v M)} {v[lin]}) (define (matrix-line-set! M lin vect-line) {v <+ (matrix-v M)} {v[lin] <- vect-line}) this allow also to indexes matrix as it is possible in Python and C++ by overloading the [ ] operator for the new type : ;; overload [ ] (overload-square-brackets matrix-ref matrix-set! (matrix? number? number?)= ) (overload-square-brackets matrix-line-ref matrix-line-set! (matrix? number?= )) scheme@(guile-user)> (define M (create-matrix-by-function (lambda (l c) (+ l c)) 2 3)) scheme@(guile-user)> (matrix-v M) $1 =3D #(#(0 1 2) #(1 2 3)) scheme@(guile-user)> {M[1 2]} $2 =3D 3 scheme@(guile-user)> {M[1][2]} $3 =3D 3 scheme@(guile-user)> {M[1]} $4 =3D #(1 2 3) On Thu, Oct 5, 2023 at 4:47=E2=80=AFPM Damien Mattei wrote: > > that is: > > (define-method (* (M1 ) (M2 )) > > {(n1 p1) <+ (dim-matrix M1)} > {(n2 p2) <+ (dim-matrix M2)} > > (when {p1 =E2=89=A0 n2} (error "matrix.* : matrix product impossible, > incompatible dimensions")) > > {v1 <+ (matrix-v M1)} > {v2 <+ (matrix-v M2)} > > (define (res i j) > {sum <+ 0} > (for ({k <+ 0} {k < p1} {k <- k + 1}) > {sum <- sum + v1[i][k] * v2[k][j]})) > > {v <+ (create-vector-2d res n1 p2)} > ;(display "v=3D") (display v) (newline) > > (matrix v)) > > and the full code: > a matrix multiplication (could add + - but no needs in my code...) > with GOOPS and Scheme+ , without using the overload features of > scheme+ but the native ones of guile scheme: > > (define-module (matrix) > > #:use-module (oop goops) > > #:use-module ((guile) > #:select (*) > #:prefix orig:) > > ;;#:use-module ((srfi srfi-43)) ;; vector > > #:export ( > matrix? > matrix > matrix-v > create-matrix-by-function > dim-matrix) > > ) > > > (include "/Users/mattei/Dropbox/git/Scheme-PLUS-for-Guile/Scheme+.scm") > > (include "/Users/mattei/Dropbox/git/Scheme-PLUS-for-Guile/scheme-infix.sc= m") > > (include "/Users/mattei/Dropbox/git/Scheme-PLUS-for-Guile/assignment.scm"= ) > (include "/Users/mattei/Dropbox/git/Scheme-PLUS-for-Guile/apply-square-br= ackets.scm") > > (include "/Users/mattei/Dropbox/git/Scheme-PLUS-for-Guile/array.scm") > ;; must know <- from assignment > > > (define-class () > > (v #:accessor matrix-v > #:getter matrix-get-v > #:setter matrix-set-v! > #:init-keyword #:v) > > ) > > > (define-method (matrix vinit) > (make #:v vinit)) > > (define-method (matrix? obj) > (equal? (class-name (class-of obj)) (class-name ))) > > ;; (define M (create-matrix-by-function (lambda (l c) (+ l c)) 2 3)) > ;; $1 =3D #< 1078a0a70> > (define (create-matrix-by-function fct lin col) > (matrix (create-vector-2d fct lin col))) > > ;; return the line and column values of dimension > ;; scheme@(guile-user)> (dim-matrix M) > ;; $1 =3D 2 > ;; $2 =3D 3 > (define (dim-matrix M) > > (when (not (matrix? M)) > (error "argument is not of type matrix")) > > {v <+ (matrix-v M)} > {lin <+ (vector-length v)} > {col <+ (vector-length {v[0]})} > (values lin col)) > > > ;; scheme@(guile-user)> (define M1 (create-matrix-by-function (lambda > (l c) (+ l c)) 2 3)) > ;; scheme@(guile-user)> (define M2 (create-matrix-by-function (lambda > (l c) (- l c)) 3 2)) > ;; scheme@(guile-user)> (matrix-v M1) > ;; $2 =3D #(#(0 1 2) #(1 2 3)) > ;; scheme@(guile-user)> (matrix-v M2) > ;; $3 =3D #(#(0 -1) #(1 0) #(2 1)) > ;; (define M1*M2 {M1 * M2}) > ;; scheme@(guile-user)> (matrix-v M1*M2) > ;; $2 =3D #(#(5 2) #(8 2)) > > (define-method (* (M1 ) (M2 )) > > {(n1 p1) <+ (dim-matrix M1)} > {(n2 p2) <+ (dim-matrix M2)} > > (when {p1 =E2=89=A0 n2} (error "matrix.* : matrix product impossible, > incompatible dimensions")) > > {v1 <+ (matrix-v M1)} > {v2 <+ (matrix-v M2)} > > (define (res i j) > {sum <+ 0} > (for ({k <+ 0} {k < p1} {k <- k + 1}) > {sum <- sum + v1[i][k] * v2[k][j]})) > > {v <+ (create-vector-2d res n1 p2)} > ;(display "v=3D") (display v) (newline) > > (matrix v)) > > > and the test: > > (define M1 (create-matrix-by-function (lambda (l c) (+ l c)) 2 3)) > ;(define M2 (create-matrix-by-function (lambda (l c) (- l c)) 3 2)) > (matrix-v M1) > #(#(0 1 2) #(1 2 3)) > (matrix-v M2) > #(#(0 -1) #(1 0) #(2 1)) > (define M1*M2 {M1 * M2}) > (matrix-v M1*M2) > #(#(5 2) #(8 2)) > > additional function used: > > ;; create a vector of line and column with a function > (define (create-vector-2d fct lin col) > {v <+ (make-vector lin)} > ;;(display "ok") (newline) > (for ({l <+ 0} {l < lin} {l <- l + 1}) > {v[l] <- (make-vector col)} > (for ({c <+ 0} {c < col} {c <- c + 1}) > {v[l][c] <- (fct l c)})) > v) > > and a corrected version of : > > (define-syntax for > (lambda (stx) > (syntax-case stx () > ((kwd (init test incrmt) body ...) > (with-syntax ((BREAK (datum->syntax (syntax kwd) 'break)) > (CONTINUE (datum->syntax (syntax kwd) 'continue))) > (syntax > (call/cc > (lambda (escape) > (let-syntax ((BREAK (identifier-syntax (escape)))) > init > (let loop ((res 0)) ;; now we will return a result at > the end if no break but if we continue? what happens? > (if test > (begin > (call/cc > (lambda (next) > (set! res (let-syntax ((CONTINUE > (identifier-syntax (next)))) > (let () ;; allow definitions > body ...))))) > incrmt > (loop res)) > res) > )))) > ) ;; close syntax > > ))))) > > note that expression > > {sum <- sum + v1[i][k] * v2[k][j]} > > is expanded as: > > ($nfx$ sum <- sum + ($bracket-apply$ ($bracket-apply$ v1 i) k) * > ($bracket-apply$ ($bracket-apply$ v2 k) j)) > > which is not fast to evaluate,and slow down calculus on intensive > computation, as the infix precedence procedure is evaluated each time > ,even if it never change in the computation loop or never in program, > i'm working on an optimiser (written in scheme) of code before > evaluation , that modify the code (transform the infix expression with > precedence in prefix one definitively ) before it is passed to the > guile compiler.But it is another piece of code... > > On Wed, Oct 4, 2023 at 10:29=E2=80=AFPM Damien Mattei wrote: > > > > yes i will re-implement that from scratch because i can not find > > something easy in libraries to use. > > I already made it for Racket/Scheme+: > > (struct matrix-vect (v)) ;; matrix based on vector of vectors > > > > (define (create-matrix-vect-by-function fct lin col) > > (matrix-vect (create-vector-2d fct lin col))) > > > > > > ;; return the line and column values of dimension > > (define (dim-matrix-vect M) > > > > (when (not (matrix-vect? M)) > > (error "argument is not of type matrix")) > > > > {v <+ (matrix-vect-v M)} > > {lin <+ (vector-length v)} > > {col <+ (vector-length {v[0]})} > > (values lin col)) > > > > > > (define (multiply-matrix-matrix M1 M2) > > > > {(n1 p1) <+ (dim-matrix-vect M1)} > > {(n2 p2) <+ (dim-matrix-vect M2)} > > > > (when {p1 =E2=89=A0 n2} (error "matrix-by-vectors.* : matrix product > > impossible, incompatible dimensions")) > > > > {v1 <+ (matrix-vect-v M1)} > > {v2 <+ (matrix-vect-v M2)} > > > > (define (res i j) > > (for/sum ([k (in-range p1)]) > > {v1[i][k] * v2[k][j]})) > > > > {v <+ (create-vector-2d res n1 p2)} > > ;(display "v=3D") (display v) (newline) > > > > (matrix-vect v)) > > > > > > (define (vector->matrix-column v) > > (matrix-vect (vector-map (lambda (x) (make-vector 1 x)) > > v))) > > > > (define (matrix-column->vector Mc) > > {v <+ (matrix-vect-v Mc)} > > (vector-map (lambda (v2) {v2[0]}) > > v)) > > > > (define (multiply-matrix-vector M v) ;; args: matrix ,vector ; return = vector > > {Mc <+ (vector->matrix-column v)} > > ;(display Mc) > > (matrix-column->vector (multiply-matrix-matrix M Mc))) > > > > > > there should be no difference for computation in Guile ,just that i > > will use GOOPS instead of struct and that it should be a guile module > > written in scheme+ syntax.... > > see it when finished.... > > > > > > On Wed, Oct 4, 2023 at 8:28=E2=80=AFPM wrote: > > > > > > On Wed, Oct 04, 2023 at 05:42:10PM +0200, Damien Mattei wrote: > > > > thank you. i will try to find a simple example in. > > > > > > > > On Wed, Oct 4, 2023 at 1:36=E2=80=AFPM Nala Ginrut wrote: > > > > > > > > > > And I'd mention AIScm which bound tensorflow APIs. It needs more = love. > > > > > > > > > > https://wedesoft.github.io/aiscm/ > > > > > > > > > > > > > > > On Wed, Oct 4, 2023, 17:12 wrote: > > > > >> > > > > >> On Wed, Oct 04, 2023 at 08:46:02AM +0200, Damien Mattei wrote: > > > > >> > hello, > > > > >> > does anyone know if it exists a basic matrix library for Guile= ? > > > > >> > just need to multiply a matrix and a vector. > > > > >> > > > > >> Perhaps this thread from guile-user [1] has something for you > > > > >> > > > > >> Cheers > > > > >> > > > > >> [1] https://lists.gnu.org/archive/html/guile-user/2018-12/thread= s.html#00117 > > > > > > That all said, if your case doesn't get much hairier, > > > it is fairly easy to navigate with Guile's arrays: > > > > > > (define (dot v1 v2) > > > "The dot product of v1 and v2" > > > (let ((sum 0)) > > > (array-for-each > > > (lambda (x1 x2) > > > (set! sum (+ sum (* x1 x2)))) > > > v1 v2) > > > sum)) > > > > > > (define (row m i) > > > "The i-th row of m, as a vector" > > > (make-shared-array m (lambda (j) (list i j)) (car (array-dimensions= m)))) > > > > > > (define (mat* m v) > > > "Left multiply matrix m and vector v" > > > (let* ((height (cadr (array-dimensions m))) > > > (res (make-typed-array 'f64 0 height))) > > > (do ((i 0 (1+ i))) > > > ((>=3D i height)) > > > (array-set! res (dot (row m i) v) i)) > > > res)) > > > > > > > > > (define vec #1f64(1 2 1)) > > > (define mat #2f64((0.5 0.5 0) (0 0.5 0.5) (-0.5 0 0.5))) > > > > > > (mat* mat vec) > > > > > > =3D> (1.5 1.5 0) > > > > > > CAVEAT: only tested with this one example. Input value checking > > > left as an... > > > > > > Cheers > > > -- > > > t > > >