How to check if a relation represented as a matrix (list of lists) is antisymmetric? - matrix

How can I check if a relation represented as a matrix (list of lists) is antisymmetric?
For example, the function should return true for;
(antisymm ((1 1 0) (0 0 1) (0 0 0)))
Example:
(antisymm ((1 1 0) (0 0 1) (0 0 0))) returns #t
(antisymm ((1 1 0) (0 0 1) (0 1 0))) returns #f

If you are going to be dealing with matrices (or any data type) the first thing to do is to write some abstractions. Matrices are not lists of lists: they might be represented as lists of lists, but they're matrices.
So let's assume some abstractions which I will not write:
matrix-rows tells you how many rows a matrix has;
matrix-cols tells you how many columns a matrix has;
matrix-ref retrieves an element of a matrix.
I will also assume zero-based indexing (which is not what mathematicians assume).
You might also want a make-matrix function.
Then it is relatively easy to write a symmetry checker:
(define (symmetry-test? m symmetry-predicate?)
;; Zero-based indexing assumed
(define max-row (- (matrix-rows m) 1))
(define max-col (- (matrix-cols m) 1))
(cond
((not (= max-row max-col))
(error "not square"))
((= max-row 0)
;; 1x1 is symmetric by definition
#t)
(else
(let check ((row 1)
(col 0))
;; Note we need to check diagonal elts for skew case
(cond
((> col max-col)
#t)
((> col row)
(check (+ row 1) 0))
((symmetry-predicate? (matrix-ref m row col)
(matrix-ref m col row))
(check row (+ col 1)))
(else
#f))))))
And now
(define (matrix-symmetric? m)
;; a matrix is symmetric if a[r,c] = a[c,r] for all r, c
(symmetry-test? m =))
(define (matrix-skew? m)
;; a matrix is skew is a[r,c] = - a[c,r] for all r, c
(symmetry-test? m (λ (a b) (= a (- b)))))
For additional bonus points: why does this show that a list of lists is an absolutely terrible representation for a matrix?

Related

SICP Exercise 2.5 - How to represent negative numbers?

I'm currently reading the SICP, and working on Exercise 2.5 :
Exercise 2.5. Show that we can represent pairs of nonnegative integers using only numbers and arithmetic operations if we represent the pair a and b as the integer that is the product 2a3b. Give the corresponding definitions of the procedures cons, car, and cdr.
And I've found a code:
(define (my-cons a b)
(* (expt 2 a) (expt 3 b)))
(define (my-car x)
(define (car-iter x count)
(if (= 0 (remainder x 2))
(car-iter (/ x 2) (+ 1 count))
count))
(car-iter x 0))
(define (my-cdr x)
(define (cdr-iter x count)
(if (= 0 (remainder x 3))
(cdr-iter (/ x 3) (+ 1 count))
count))
(cdr-iter x 0))
My question is : What if the requirement of "Nonnegative integers" needs to be changed to "Accept both negative and nonnegative integers" ?
Example :
> (define x (my-cons 2 -5))
> (my-car x)
2
> (my-cdr x)
-5
How to modify the code? I can't figure it out.
Thank you. May you have a great day.
As amalloy said in a comment this is really a maths problem. This encoding works because of the fundamental theorem of arithmetic, which is that any positive natural number has a unique prime factorisation: every positive natural can be represented uniquely as the product of a number of primes raised to powers, where in particular 1 is the product of no primes.
So you could encode the sign of the integers using one or more additional prime factors (you only need one, in fact, as you can for instance write the thing as 2^a3^b5^s where s is an integer in [0,3] which encodes the signs of both elements).
An alternative way is simply to use the existing representation but to map the integers to the naturals. This is nice because it's a practical demonstration that there are no more integers than naturals. Such a map might be:
if i >= 0 then 2i.
otherswise -2i - 1.
It's easy to see that this is a one-to-one correspondence, and also that 0 maps to 0 (which makes 0 a nice value for nil).
Here are these maps, written (sorry) in typed Racket as I'm trying to work out if I can use it.
(define (Z->N (i : Integer)) : Natural
;; map an integer to a natural
(if (>= i 0)
(* i 2)
(- (* (- i) 2) 1)))
(define (N->Z (n : Natural)) : Integer
;; map the naturals into the integers
(let-values ([(q r) (quotient/remainder n 2)])
(if (zero? r)
q
(- (- q) 1))))
Now there is another problem with the implementation you have: it will happily handle numbers which are not of the form 2^a3^b, for instance anything which has other prime factors. The way to deal with that is to check that numbers are of that form when extracting the powers: in practice this means checking the number is of the form 2^a*3^b*1.
So the code below does this, as well as encoding integers as above. This again is in typed Racket (sorry, again), and it also makes use of multiple values and probably some other things which only exist in Racket.
(define (defactor (n : Natural) (p : Natural)) : (Values Natural Natural)
;; Given n and a factor p, return m where p does not divide m,
;; and j, the number of factors of p removed (so n = m*p^j)
(let df-loop ([m : Natural n]
[j : Natural 0])
(let-values ([(q r) (quotient/remainder m p)])
(if (zero? r)
(df-loop q (+ j 1))
(values m j)))))
(define (kar&kdr (k : Positive-Integer)) : (Values Integer Integer)
;; Given something which should be a kons, return its kar & kdr.
;; If it is not a kons signal an error
(let*-values ([(k2 encoded-kar) (defactor k 2)]
[(k23 encoded-kdr) (defactor k2 3)])
(unless (= k23 1)
(error 'kar&kdr "not a cons"))
(values (N->Z encoded-kar) (N->Z encoded-kdr))))
(define (kons (the-kar : Integer) (the-kdr : Integer)) : Positive-Integer
(* (expt 2 (Z->N the-kar))
(expt 3 (Z->N the-kdr))))
(define (kar (the-kons : Positive-Integer)) : Integer
(let-values ([(the-kar the-kdr) (kar&kdr the-kons)])
the-kar))
(define (kdr (the-kons : Positive-Integer)) : Integer
(let-values ([(the-kar the-kdr) (kar&kdr the-kons)])
the-kdr))
We can go a little further and define a representation of the empty list, which will be 0 and a way of making lists:
;;; since 2^a3^b is never zero, 0 is a good candidate for the empty
;;; list: 'kill' is a pun on 'nil'.
;;;
(define kill : Zero 0)
;;; And now we can write some predicates and a version of list.
;;; (kist 1 2 3) takes a very, very long time.
;;;
(define (kill? (x : Natural)) : Boolean
(zero? x))
(define (kons? (x : Natural)) : Boolean
(not (kill? x)))
(define (kist . (l : Integer *)) : Natural
(let kist/spread ((lt l))
(if (null? lt)
kill
(kons (first lt) (kist/spread (rest lt))))))
And now
> (define d (kons 123 -456))
> d
- : Integer [more precisely: Nonnegative-Integer]
51385665200410193914365219310409629004573395973849642473134969706165383608831740620563388986738635202925909198851954060195023302783671526117732269828652603388431987979605951272414330987611274752111186624164906143978901704325355283206259678088536996807776750955110998323447711166379786727609752016045005681785186498933895920793982869940159108073471074955985333560653268614500306816876936016985137986665262182684386364851688838680773491949813254691225004097103180392486216812280763694296818736638062547181764608
> (kar d)
- : Integer
123
> (kdr d)
- : Integer
-456
> (kdr (+ d 1))
kar&kdr: not a cons [,bt for context]
If you try to compute, say (kist 1 2 3) it will take a very, very long time.

Knuth-Morris-Pratt algorithm in Scheme

This is the code to calculate the failure function (how many steps we have to go back) in Scheme, when we use the Knuth-Morris-Pratt algorithm:
(define (compute-failure-function p)
(define n-p (string-length p))
(define sigma-table (make-vector n-p 0))
(let loop
((i-p 2)
(k 0))
(cond
((>= i-p n-p)
(vector-set! sigma-table (- n-p 1) k))
((eq? (string-ref p k)
(string-ref p (- i-p 1)))
(vector-set! sigma-table i-p (+ k 1))
(loop (+ i-p 1) (+ k 1)))
((> k 0)
(loop i-p (vector-ref sigma-table k)))
(else ; k=0
(vector-set! sigma-table i-p 0)
(loop (+ i-p 1) k))))
(vector-set! sigma-table 0 -1)
(lambda (q)
(vector-ref sigma-table q)))
But I do not understand the part when k > 0. Can someone explain it please?
I see you're confused with the syntax of a named let. This post does a good job explaining how it works, but perhaps an example with more familiar syntax will make things clearer. Take this code in Python, it adds all integers from 1 to 10:
sum = 0
n = 1
while n <= 10:
sum += n
n += 1
print(sum)
=> 55
Now let's try to write it in a recursive fashion, I'll call my function loop. This is completely equivalent:
def loop(n, sum):
if n > 10:
return sum
else:
return loop(n + 1, n + sum)
loop(1, 0)
=> 55
In the above example, the loop function implements an iteration, the parameter n is used to keep track of the current position, and the parameter sum accumulates the answer. Now let's write the exact same code, but in Scheme:
(let loop ((n 1) (sum 0))
(cond ((> n 10) sum)
(else (loop (+ n 1) (+ n sum)))))
=> 55
Now we've defined a local procedure called loop which is then automatically called with the initial values 1 and 0 for its parameters n and sum. When the base case of the recursion is reached, we return sum, otherwise we keep calling this procedure, passing updated values for the parameters. It's exactly the same as in the Python code! Don't be confused by the syntax.
In your algorithm, i-p and k are the iteration variables, which are initialized to 2 and 0 respectively. Depending on which condition is true, the iteration continues when we call loop again with updated values for i-p and k, or it ends when the case (>= i-p n-p) is reached, at this point the loop exits and the computed value is in the variable sigma-table. The procedure ends by returning a new function, referred to as the "failure function".

Blocked Matrix Multiplication

I am trying to create a function that performs blocked matrix multiplication in AllegroCL, but I keep getting array-index errors. I believe it is due to the indicies being 0-19 for a side of a 20 x 20 block matrix, but I'm unsure of how to fix it.
Error: Array index 20 too big for dimension 20 while accessing
#.
[condition type: type-error]
Any help or direction is much appreciated. Below is my code thus far.
(defun bmmul (A B)
(let* ((m (car (array-dimensions A)))
(n (cadr (array-dimensions A)))
(l (cadr (array-dimensions B)))
(u 0)
(C (make-array `(,m ,l) :initial-element 0)))
(loop for p from 0 to (- m n) do
(loop for i from (+ 0 1) to n do
(setf u (aref C i 0))
(loop for k from p to (- (+ p n) 1) do
(setf u (* (aref A i k) (aref B k 0))))
(setf (aref C i 0) u)))
C))
In general, when looping over an array index, you go :from 0 :below n, where n is the array dimension, so when the dimension is 20, the index goes from 0 up to and including 19.
Another problem seems to be that in the innermost loop, you want to incf, not setf. You also do not need a temporary variable (u) there, just incf the array cell directly.
Finally, I do not feel that you structured your loops correctly, I do not expect to see a hardcoded 0 index there. The innermost loop body should look like (incf (aref c i j) (* (aref a i k) (aref b k j))), regardless of whether you do ordinary or blocked multiplication.

function that calculates non-zero inputs of a vector

I'm new to scheme and having difficulty understanding vectors in scheme. I need to create a function that calculates the number of non-zero inputs in
a vector. I need to do this by not converting the vector into a list.
For exampl3.
(non-zero-dim #(3 0 2 4 0 2))
returns 4
My code so far is
(define non-zero-input
(lambda (vector)
(let ((size (vector-length vector)))
do ((position 0 (+ position 1))
(total 0
(if ((not (zero? vector-ref vector position)))
(+ total 1))
(((= position size) total)))))))
However I'm getting this error :do: bad syntax in: (do ((position 0 (+ position 1)) (total 0 (if ((not (zero? vector-ref vector position))) (+ total 1)) (((= position size) total))
How do i fix this error ?
Using the built-in procedures vector-length and vector-filter-not, you can simplify your function as:
(define (non-zero-dim vec)
(vector-length (vector-filter-not zero? vec)))
For example,
> (non-zero-dim #(3 0 2 4 0 2))
4
Some things to consider:
Keep track of your brackets. For example, (zero? vector-ref vector position) should be (zero? (vector-ref vector position)), whereby arity of zero? is one, and arity of vector-ref is two. Similarly with do ... vs. (do ... etc.
if statements must have an else clause (ie. (if condition then else)). For example, (if true 1) would fail, but (if true 1 2) would pass. Hence, (if ((not (zero? vector-ref vector position))) (+ total 1)) would fail.
The racket/vector package has vector-count, which returns the number of elements of a vector that satisfy a given predicate. This makes counting the non-zero values trivial:
#lang racket/base
(require racket/function racket/vector)
(define (non-zero-dim vec)
(vector-count (negate zero?) vec))
(println (non-zero-dim #(3 0 2 4 0 2)) ; 4

Writing a simple matrix class in common lisp for practice

Common lisp newbie. Writing lisp code is quite different from writing c++/java, as I wrote them before.
I am trying to write a simple matrix class in common lisp for practice. Some codes like that:
(defun make-matrix (row col)
(make-list row :initial-element (make-list col :initial-element nil)))
(defun init-matrix (matrix init-value)
(labels ((set-element-value (lst)
(if (and lst
(listp lst))
(mapcar #'set-element-value lst)
(setf lst init-value))))
(set-element-value matrix)))
(defun matrix+ (&rest matrices)
(apply #'mapcar (lambda (&rest rows)
(apply #'mapcar #'+ rows)) matrices))
My question is can I write a matrix+ accepting different number of arguments without 'apply', or in a better way ? In a way that lisp should be?
And how about the matrix*, can somebody show me some awesome code accepting arbitrary number of arguments in matrix* ? Thanks.
Common Lisp has n-dimensional arrays. I would use those for matrix operations.
See: MAKE-ARRAY, AREF, ...
Typically I would also then write a binary (taking two arguments) matrix operation. Use then REDUCE to operate over a list of matrices.
CL-USER > (make-array '(3 5) :initial-element 0)
#2A((0 0 0 0 0) (0 0 0 0 0) (0 0 0 0 0))
Above creates a 2-dimensional array of size 3x5 with 0 as initial content.
Matrix multiplication. I can't promise this is the best example possible, but it is really straight-forward. This is given you use arrays rather than lists. Also, of course, you can optimize for square matrices, or special cases, like identity matrices etc. But this is meant only to be simple, not efficient etc.
(defun matrix* (&rest matrices)
(assert (cdr matrices) nil
"You will achieve nothing by multiplying a single matrix.")
(reduce
#'(lambda (a b)
(assert (= (array-dimension a 0) (array-dimension b 1)) nil
"The number of rows in the first matrix should be the number ~
of columns in the second matrix")
(let ((result
(make-array
(list (array-dimension a 1) (array-dimension b 0))
:initial-element 0)))
(dotimes (i (array-dimension a 1) result)
(dotimes (j (array-dimension b 0))
(dotimes (k (array-dimension a 0))
(incf (aref result i j) (* (aref a k i) (aref b j k))))))))
matrices))
(format t "result: ~s~&" (matrix* #2A((1 2) (3 4)) #2A((5 6) (7 8))))
;; #2A((23 31) (34 46)) =
;; (1 * 5 + 3 * 6 = 23) (1 * 7 + 3 * 8 = 31)
;; (2 * 5 + 4 * 6 = 34) (2 * 7 + 4 * 8 = 46)

Resources