]> gitweb.factorcode.org Git - factor.git/blob - basis/math/matrices/matrices-tests.factor
factor: fix some spacing
[factor.git] / basis / math / matrices / matrices-tests.factor
1 ! Copyright (C) 2005, 2010, 2018, 2020 Slava Pestov, Joe Groff, and Cat Stevens.
2 USING: arrays assocs combinators.short-circuit grouping kernel
3 math math.statistics math.vectors sequences sequences.deep
4 tools.test ;
5 IN: math.matrices
6
7 <PRIVATE
8 : call-eq? ( obj quots -- ? )
9     [ call( x -- x ) ] with map all-eq? ; !  inline
10 PRIVATE>
11 ! ------------------------
12 ! predicates
13
14 { t } [ { }                 regular-matrix? ] unit-test
15 { t } [ { { } }             regular-matrix? ] unit-test
16 { t } [ { { 1 2 } }         regular-matrix? ] unit-test
17 { t } [ { { 1 2 } { 3 4 } } regular-matrix? ] unit-test
18 { t } [ { { 1 } { 3 } }     regular-matrix? ] unit-test
19 { f } [ { { 1 2 } { 3 } }   regular-matrix? ] unit-test
20 { f } [ { { 1 } { 3 2 } }   regular-matrix? ] unit-test
21
22
23 { t } [ { } square-matrix? ] unit-test
24 { t } [ { { 1 } } square-matrix? ] unit-test
25 { t } [ { { 1 2 } { 3 4 } } square-matrix? ] unit-test
26 { f } [ { { 1 } { 2 3 } } square-matrix? ] unit-test
27 { f } [ { { 1 2 } } square-matrix? ] unit-test
28
29 ! any deep-empty matrix is null
30 ! it doesn't make any sense for { } to be null while { { } } to be considered nonnull
31 { t } [ {
32     { }
33     { { } }
34     { { { } } }
35     { { } { } { } }
36     { { { } } { { { } } } }
37 } [ null-matrix? ] all?
38 ] unit-test
39
40 { f } [ {
41     { 1 2 }
42     { { 1 2 } }
43     { { 1 } { 2 } }
44     { { { 1 } } { 2 } { } }
45 } [ null-matrix? ] any?
46 ] unit-test
47
48 { t } [ 10 dup <zero-matrix> zero-matrix? ] unit-test
49 { t } [ 10 10 15 <simple-eye> zero-matrix? ] unit-test
50 { t } [ 0 dup <zero-matrix> null-matrix? ] unit-test
51 { f } [ 0 dup <zero-matrix> zero-matrix? ] unit-test
52 { f } [ 4 <identity-matrix> zero-matrix? ] unit-test
53 ! make sure we're not using the sum-to-zero strategy
54 { f } [ { { 0 -2 } { 1 -1 } } zero-matrix? ] unit-test
55 { f } [ { { 0 0 } { 1 -1 } } zero-matrix? ] unit-test
56 { f } [ { { 0 1 } { 0 -1 } } zero-matrix? ] unit-test
57
58 ! nth etc
59
60 { 3 } [ { 1 2 3 } 0 swap nth-end ] unit-test
61 { 2 } [ { 1 2 3 } 1 swap nth-end ] unit-test
62 { 1 } [ { 1 2 3 } 2 swap nth-end ] unit-test
63
64 [ { 1 2 3 } -1 swap nth-end ] [ bounds-error? ] must-fail-with
65 [ { 1 2 3 } 3 swap nth-end ] [ bounds-error? ] must-fail-with
66 [ { 1 2 3 } 4 swap nth-end ] [ bounds-error? ] must-fail-with
67
68 { { 0 0 1 } } [ { 0 0 0 } dup 1 0 rot set-nth-end ] unit-test
69 { { 0 2 0 } } [ { 0 0 0 } dup 2 1 rot set-nth-end ] unit-test
70 { { 3 0 0 } } [ { 0 0 0 } dup 3 2 rot set-nth-end ] unit-test
71
72 [ { 0 0 0 } dup 1 -1 rot set-nth-end ] [ bounds-error? ] must-fail-with
73 [ { 0 0 0 } dup 2 3 rot set-nth-end ] [ bounds-error? ] must-fail-with
74 [ { 0 0 0 } dup 3 4 rot set-nth-end ] [ bounds-error? ] must-fail-with
75
76 ! constructors
77
78 { {
79     { 5 5 }
80     { 5 5 }
81 } } [ 2 2 5 <matrix> ] unit-test
82 ! a matrix-matrix
83 { { {
84     { { -1 -1 } { -1 -1 } }
85     { { -1 -1 } { -1 -1 } }
86     { { -1 -1 } { -1 -1 } }
87 } {
88     { { -1 -1 } { -1 -1 } }
89     { { -1 -1 } { -1 -1 } }
90     { { -1 -1 } { -1 -1 } }
91 } } } [ 2 3 2 2 -1 <matrix> <matrix> ] unit-test
92
93 { {
94     { 5 5 }
95     { 5 5 }
96 } } [ 2 2 [ 5 ] <matrix-by> ] unit-test
97 { {
98     { 6 6 }
99     { 6 6 }
100 } } [ 2 2 [ 3 2 * ] <matrix-by> ] unit-test
101
102 { {
103     { 0 1 2 }
104     { 1 2 3 }
105 } } [ 2 3 [ + ] <matrix-by-indices> ] unit-test
106 { {
107     { 0 0 0 }
108     { 0 1 2 }
109     { 0 2 4 }
110 } } [ 3 3 [ * ] <matrix-by-indices> ] unit-test
111
112 { t } [ 3 3 <zero-matrix> zero-square-matrix? ] unit-test
113 { t } [ 3 <zero-square-matrix> zero-square-matrix? ] unit-test
114 { t f } [ 3 1 <zero-matrix> [ zero-matrix? ] [ square-matrix? ] bi ] unit-test
115
116 { {
117     { 1 0 0 }
118     { 0 2 0 }
119     { 0 0 3 }
120 } } [
121     { 1 2 3 } <diagonal-matrix>
122 ] unit-test
123
124 { {
125     { -11 0 0 0 }
126     { 0 -12 0 0 }
127     { 0 0 -33 0 }
128     { 0 0 0 -14 }
129 } } [ { -11 -12 -33 -14 } <diagonal-matrix> ] unit-test
130
131 { {
132     { 0 0 1 }
133     { 0 2 0 }
134     { 3 0 0 }
135 } } [ { 1 2 3 } <anti-diagonal-matrix> ] unit-test
136
137 { {
138     { 0 0 0 -11 }
139     { 0 0 -12 0 }
140     { 0 -33 0 0 }
141     { -14 0 0 0 }
142 } } [ { -11 -12 -33 -14 } <anti-diagonal-matrix> ] unit-test
143
144 { {
145     { 1 0 0 }
146     { 0 1 0 }
147     { 0 0 1 }
148 } } [
149     3 <identity-matrix>
150 ] unit-test
151
152 { {
153     { 2 0 0 }
154     { 0 2 0 }
155     { 0 0 2 }
156 } } [
157     3 3 0 2 <eye>
158 ] unit-test
159
160 { {
161     { 0 2 0 }
162     { 0 0 2 }
163     { 0 0 0 }
164 } } [
165     3 3 1 2 <eye>
166 ] unit-test
167
168 { {
169     { 0 0 0 0 }
170     { 2 0 0 0 }
171     { 0 2 0 0 }
172 } } [
173     3 4 -1 2 <eye>
174 ] unit-test
175
176
177 { {
178     { 1 0 0 }
179     { 0 1 0 }
180     { 0 0 1 }
181 } } [
182     3 3 0 <simple-eye>
183 ] unit-test
184
185 { {
186     { 0 1 0 }
187     { 0 0 1 }
188     { 0 0 0 }
189 } } [
190     3 3 1 <simple-eye>
191 ] unit-test
192
193 { {
194     { 0 0 0 }
195     { 1 0 0 }
196     { 0 1 0 }
197 } } [
198     3 3 -1 <simple-eye>
199 ] unit-test
200
201 { {
202     { 1 0 0 0 }
203     { 0 1 0 0 }
204     { 0 0 1 0 }
205 } } [
206     3 4 0 <simple-eye>
207 ] unit-test
208
209 { {
210     { 0 1 0 }
211     { 0 0 1 }
212     { 0 0 0 }
213     { 0 0 0 }
214 } } [
215     4 3 1 <simple-eye>
216 ] unit-test
217
218 { {
219     { 0 0 0 }
220     { 1 0 0 }
221     { 0 1 0 }
222     { 0 0 1 }
223 } } [
224     4 3 -1 <simple-eye>
225 ] unit-test
226
227 { {
228     { { 0 0 } { 0 1 } { 0 2 } }
229     { { 1 0 } { 1 1 } { 1 2 } }
230     { { 2 0 } { 2 1 } { 2 2 } }
231     { { 3 0 } { 3 1 } { 3 2 } }
232 } } [ { 4 3 } <coordinate-matrix> ] unit-test
233
234 { {
235     { 0 1 }
236     { 0 1 }
237 } } [ 2 <square-rows> ] unit-test
238
239 { {
240     { 0 0 }
241     { 1 1 }
242 } } [ 2 <square-cols> ] unit-test
243
244 { {
245     { 5 6 }
246     { 5 6 }
247 } } [ { 5 6 } <square-rows> ] unit-test
248
249 { {
250     { 5 5 }
251     { 6 6 }
252 } } [ { 5 6 } <square-cols> ] unit-test
253
254 {  {
255     { 1 }
256 } } [ {
257     { 1 2 }
258 } <square-rows> ] unit-test
259
260 {  {
261     { 1 2 }
262     { 3 4 }
263 } } [ {
264     { 1 2 5 }
265     { 3 4 6 }
266 } <square-rows> ] unit-test
267
268 {  {
269     { 1 2 }
270     { 3 4 }
271 } } [ {
272     { 1 2 }
273     { 3 4 }
274     { 5 6 }
275 } <square-rows> ] unit-test
276
277 { {
278     { 1 0 4 }
279     { 0 7 0 }
280     { 6 0 3 } }
281 } [ {
282     { 1 0 0 }
283     { 0 2 0 }
284     { 0 0 3 }
285 } {
286     { 0 0 4 }
287     { 0 5 0 }
288     { 6 0 0 }
289 }
290     m+
291 ] unit-test
292
293 { {
294     { 1 0 4 }
295     { 0 7 0 }
296     { 6 0 3 }
297 } } [ {
298     { 1 0 0 }
299     { 0 2 0 }
300     { 0 0 3 }
301 } {
302     { 0 0 -4 }
303     { 0 -5 0 }
304     { -6 0 0 }
305 }
306     m-
307 ] unit-test
308
309 { { 3 4 } } [ { { 1 0 } { 0 1 } } { 3 4 } mdotv ] unit-test
310 { { 4 3 } } [ { { 0 1 } { 1 0 } } { 3 4 } mdotv ] unit-test
311
312 { { { 6 } } } [ { { 3 } } { { 2 } } mdot ] unit-test
313 { { { 11 } } } [ { { 1 3 } } { { 5 } { 2 } } mdot ] unit-test
314
315 { { { 28 } } } [
316     { { 2 4 6 } }
317     { { 1 } { 2 } { 3 } }
318     mdot
319 ] unit-test
320
321 { 9 }
322 [ { { 2 -2 1 } { 1 3 -1 } { 2 -4 2 } } matrix-l1-norm ] unit-test
323
324 { 8 }
325 [ { { 2 -2 1 } { 1 3 -1 } { 2 -4 2 } } matrix-l-infinity-norm ] unit-test
326
327 { 2.0 }
328 [ { { 1 1 } { 1 1 } } matrix-l2-norm ] unit-test
329
330 { 10e-8 }
331 [
332   5.4772255
333   { { 1 2 } { 3 4 } } matrix-l2-norm
334 ] unit-test~
335
336 { 10e-6 }
337 [
338   36.94590
339   { { 1 2 } { 4 8 } { 16 32 } } matrix-l2-norm
340 ] unit-test~
341
342 ! equivalent to frobenius for p = q = 2
343 { 2.0 }
344 [ { { 1 1 } { 1 1 } } 2 2 matrix-p-q-norm ] unit-test
345
346 { 10e-7 }
347 [
348   33.456466
349   { { 1 2 } { 4 8 } { 16 32 } } 3 matrix-p-norm-entrywise
350 ] unit-test~
351
352 { { { -1 0 } { 0 0 } } }
353 [ { { -2 0 } { 0 0 } } matrix-normalize ] unit-test
354
355 { { { -1 0 } { 0 1/2 } } }
356 [ { { -2 0 } { 0 1 } } matrix-normalize ] unit-test
357
358 { t }
359 [ 3 3 <zero-matrix> dup matrix-normalize = ] unit-test
360
361 ! diagonals
362
363 ! diagonal getters
364 { { 1 1 1 1 } } [ 4 <identity-matrix> main-diagonal ] unit-test
365 { { 0 0 0 0 } } [ 4 <identity-matrix> anti-diagonal ] unit-test
366 { { 4 8 } } [ { { 4 6 } { 3 8 } } main-diagonal ] unit-test
367 { { 6 3 } } [ { { 4 6 } { 3 8 } } anti-diagonal ] unit-test
368 { { 1 2 3 } } [ { { 0 0 1 } { 0 2 0 } { 3 0 0 } } anti-diagonal ] unit-test
369 { { 1 2 3 4 } } [ { 1 2 3 4 } <diagonal-matrix> main-diagonal ] unit-test
370
371 ! transposition
372 { { 1 2 3 4 } } [ { 1 2 3 4 } <diagonal-matrix> transpose main-diagonal ] unit-test
373 { t } [ 50 <identity-matrix> dup transpose = ] unit-test
374 { { 4 3 2 1 } } [ { 1 2 3 4 } <anti-diagonal-matrix> transpose anti-diagonal ] unit-test
375
376 { {
377   { 1 4 7 }
378   { 2 5 8 }
379   { 3 6 9 }
380 } } [ {
381   { 1 2 3 }
382   { 4 5 6 }
383   { 7 8 9 }
384 } transpose ] unit-test
385
386 ! anti transposition
387 { { 1 2 3 4 } } [ { 1 2 3 4 } <anti-diagonal-matrix> anti-transpose anti-diagonal ] unit-test
388 { t } [ 50 <iota> <anti-diagonal-matrix> dup anti-transpose = ] unit-test
389 { { 4 3 2 1 } } [ { 1 2 3 4 } <diagonal-matrix> anti-transpose main-diagonal ] unit-test
390
391 { {
392   { 9 6 3 }
393   { 8 5 2 }
394   { 7 4 1 }
395 } } [ {
396   { 1 2 3 }
397   { 4 5 6 }
398   { 7 8 9 }
399 } anti-transpose ] unit-test
400
401 <PRIVATE
402 SYMBOLS: A B C D E F G H I J K L M N O P ;
403 PRIVATE>
404 { { {
405     { E F G H }
406     { I J K L }
407     { M N O P }
408 } {
409     { A B C D }
410     { I J K L }
411     { M N O P }
412 } {
413     { A B C D }
414     { E F G H }
415     { M N O P }
416 } {
417     { A B C D }
418     { E F G H }
419     { I J K L }
420 } } } [
421     4 {
422         { A B C D }
423         { E F G H }
424         { I J K L }
425         { M N O P }
426     } <repetition>
427     [ rows-except ] map-index
428 ] unit-test
429
430 { { { 2 } } } [ { { 1 } { 2 } } 0 rows-except ] unit-test
431 { { { 1 } } } [ { { 1 } { 2 } } 1 rows-except ] unit-test
432 { { } } [ { { 1 } }       0 rows-except ] unit-test
433 { { { 1 } } } [ { { 1 } } 1 rows-except ] unit-test
434 { {
435     { 2 7 12 2 } ! 0
436     { 1 3 3 5 }  ! 2
437 } } [ {
438     { 2 7 12 2 }
439     { 8 9 10 0 }
440     { 1 3 3 5 }
441     { 8 13 7 12 }
442 } { 1 3 } rows-except ] unit-test
443
444 { { {
445     { B C D }
446     { F G H }
447     { J K L }
448     { N O P }
449 } {
450     { A C D }
451     { E G H }
452     { I K L }
453     { M O P }
454 } {
455     { A B D }
456     { E F H }
457     { I J L }
458     { M N P }
459 } {
460     { A B C }
461     { E F G }
462     { I J K }
463     { M N O }
464 } } } [
465     4 {
466         { A B C D }
467         { E F G H }
468         { I J K L }
469         { M N O P }
470     } <repetition>
471     [ cols-except ] map-index
472 ] unit-test
473
474 { { } } [ { { 1 } { 2 } } 0 cols-except ] unit-test
475 { { { 1 } { 2 } } } [ { { 1 } { 2 } } 1 cols-except ] unit-test
476 { { } } [ { { 1 } }       0 cols-except ] unit-test
477 { { { 1 } } } [ { { 1 } } 1 cols-except ] unit-test
478 { { { 2 } { 4 } } } [ { { 1 2 } { 3 4 } } 0 cols-except ] unit-test
479 { { { 1 } { 3 } } } [ { { 1 2 } { 3 4 } } 1 cols-except ] unit-test
480 { {
481     { 2 12 }
482     { 8 10 }
483     { 1 3 }
484     { 8 7 }
485 } } [ {
486     { 2 7 12 2 }
487     { 8 9 10 0 }
488     { 1 3 3 5 }
489     { 8 13 7 12 }
490 } { 1 3 } cols-except ] unit-test
491
492 { { {
493     { F G H }
494     { J K L }
495     { N O P }
496 } {
497     { A C D }
498     { I K L }
499     { M O P }
500 } {
501     { A B D }
502     { E F H }
503     { M N P }
504 } {
505     { A B C }
506     { E F G }
507     { I J K }
508 } } } [
509     4 {
510         { A B C D }
511         { E F G H }
512         { I J K L }
513         { M N O P }
514     } <repetition>
515     [ dup 2array matrix-except ] map-index
516 ] unit-test
517
518 ! prepare for bracket hell
519 ! going to test the Matrix of Minors permutation strategy
520
521 ! going to test 1x2 inputs
522 ! the input had 2 elements, the output has 2 0-matrices across 2 arrays ;)
523 { { { { } { } } } } [ { { 1 2 } } matrix-except-all ] unit-test
524
525 ! any matrix with a 1 in its dimensions will give a void matrix output
526 { t } [ { { 1 2 } }     matrix-except-all null-matrix? ] unit-test
527 { t } [ { { 1 } { 2 } } matrix-except-all null-matrix? ] unit-test
528
529 ! going to test 2x2 inputs
530 ! these 1x1 output matrices have omitted a row and column from the 2x2 input
531
532 ! the input had 4 elements, the output has 4 1-matrices across 2 arrays
533 ! the permutations of indices 0 1 are: 0 0, 0 1, 1 0, 1 1
534 {
535     { ! output array
536         { ! item #1: excluding row 0...
537             { { 3 } } ! and col 0 = 0 0
538             { { 2 } } ! and col 1 = 0 1
539         }
540         { ! item #2: excluding row 1...
541             { { 1 } } ! and col 0 = 1 0
542             { { 0 } } ! and col 1 = 1 1
543         }
544     }
545 } [
546     ! the input to the function is a simple 2x2
547     { { 0 1 } { 2 3 } } matrix-except-all
548 ] unit-test
549
550 ! we are going to ensure that "duplicate" matrices are not omitted in the output
551 {
552     {
553         { ! item 1
554             { { 0 } }
555             { { 0 } }
556         }
557         { ! item 2
558             { { 0 } }
559             { { 0 } }
560         }
561     }
562 } [ { { 0 0 } { 0 0 } } matrix-except-all ] unit-test
563 ! the output only has elements from the input
564 { t } [ 44 <zero-square-matrix> matrix-except-all zero-matrix? ] unit-test
565
566 ! going to test 2x3 and 3x2 inputs
567 {
568     { ! output array
569         { ! excluding row 0
570             { { 2 } { 3 } } ! and col 0
571             { { 1 } { 2 } } ! and col 1
572         }
573         { ! excluding row 1
574             { { 1 } { 3 } } ! and col 0
575             { { 0 } { 2 } } ! and col 1
576         }
577         { ! excluding row 2
578             { { 1 } { 2 } } ! col 0
579             { { 0 } { 1 } } ! col 1
580         }
581     }
582 } [ {
583     { 0 1 }
584     { 1 2 }
585     { 2 3 }
586 } matrix-except-all ] unit-test
587
588 {
589     { ! output array
590         { ! excluding row 0
591             { { 2 3 } } ! col 0
592             { { 1 3 } } ! col 1
593             { { 1 2 } } ! col 2
594         }
595         { ! row 1
596             { { 1 2 } } ! col 0
597             { { 0 2 } } ! col 1
598             { { 0 1 } } ! col 2
599         }
600     }
601 } [ {
602     { 0 1 2 }
603     { 1 2 3 }
604 } matrix-except-all ] unit-test
605
606 ! going to test 3x3 inputs
607
608 ! the input had 9 elements, the output has 9 2-matrices across 3 arrays
609 ! every element from the input is represented 4 times in the output
610 ! the number of copies of each element found in the output is the side length of the next smaller square matrix
611 ! 3x3 input gives 4 copies of each element; (N-1) ^ 2 = 4 where N=3
612 ! the permutations of indices 0 1 2 are: 0 0, 0 1, 0 2; 1 0, 1 1, 1 2; 2 0, 2 1, 2 2
613 {
614     { ! output array
615         { ! item #1: excluding row 0...
616             { ! and col 0 = 0 0
617                 { 4 5 }
618                 { 7 8 }
619             }
620             { ! and col 1 = 0 1
621                 { 3 5 }
622                 { 6 8 }
623             }
624             { ! and col 2 = 0 2
625                 { 3 4 }
626                 { 6 7 }
627             }
628         }
629
630         { ! item #2: excluding row 1...
631             { ! and col 0 = 1 0
632                 { 1 2 }
633                 { 7 8 }
634             }
635             { ! and col 1 = 1 1
636                 { 0 2 }
637                 { 6 8 }
638             }
639             { ! and col 2 = 1 2
640                 { 0 1 }
641                 { 6 7 }
642             }
643         }
644
645         { ! item #2: excluding row 2...
646             { ! and col 0 = 2 0
647                 { 1 2 }
648                 { 4 5 }
649             }
650             { ! and col 1 = 2 1
651                 { 0 2 }
652                 { 3 5 }
653             }
654             { ! and col 2 = 2 2
655                 { 0 1 }
656                 { 3 4 }
657             }
658         }
659     }
660     t ! note this
661 } [ {
662     { 0 1 2 }
663     { 3 4 5 }
664     { 6 7 8 }
665 } matrix-except-all dup flatten sorted-histogram values
666     { [ length 9 = ] [ [ 4 = ] all? ] }
667     1&&
668 ] unit-test
669
670 ! going to test 4x4 inputs
671
672 ! don't feel like handwriting this right now, so a sanity check test instead
673 ! the input contains 4 rows and 4 columns for 16 elements
674 ! 4x4 input gives 9 copies of each element; (N-1) ^ 2 = 9 where N = 4
675 { t } [ {
676     { 0 1 2 3 }
677     { 4 5 6 7 }
678     { 8 9 10 11 }
679     { 12 13 14 15 }
680 } matrix-except-all flatten sorted-histogram values
681     { [ length 16 = ] [ [ 9 = ] all? ] }
682     1&&
683 ] unit-test