pRNG system needed which is a standalone, thread/parallel-safe, and limited depends
[CommonLispStat.git] / TODO.lisp
blobdb329d316d1009bb85e8d06aa31cc22cdeebe7d9
1 ;;; -*- mode: lisp -*-
3 ;;; Time-stamp: <2009-04-13 12:14:44 tony>
4 ;;; Creation: <2008-09-08 08:06:30 tony>
5 ;;; File: TODO.lisp
6 ;;; Author: AJ Rossini <blindglobe@gmail.com>
7 ;;; Copyright: (c) 2007-2008, AJ Rossini <blindglobe@gmail.com>. BSD.
8 ;;; Purpose: Stuff that needs to be made working sits inside the
9 ;;; progns... This file contains the current challenges to
10 ;;; solve, including a description of the setup and the work
11 ;;; to solve....
13 ;;; What is this talk of 'release'? Klingons do not make software
14 ;;; 'releases'. Our software 'escapes', leaving a bloody trail of
15 ;;; designers and quality assurance people in its wake.
17 ;;; SET UP
19 (in-package :cl-user)
20 ;;(asdf:oos 'asdf:load-op 'lisp-matrix)
21 ;;(asdf:oos 'asdf:compile-op 'lispstat)
22 ;;(asdf:oos 'asdf:load-op 'lispstat)
24 (in-package :lisp-stat-unittests)
26 ;; tests = 78, failures = 7, errors = 15
27 (run-tests :suite 'lisp-stat-ut)
28 (describe (run-tests :suite 'lisp-stat-ut))
30 ;; FIXME: Example: currently not relevant, yet
31 ;; (describe (lift::run-test :test-case 'lisp-stat-unittests::create-proto
32 ;; :suite 'lisp-stat-unittests::lisp-stat-ut-proto))
34 (describe 'lisp-stat-ut)
36 (in-package :ls-user)
38 (progn ;; FIXME: Regression modeling (some data future-ish)
40 (defparameter *m*
41 (regression-model (list->vector-like iron) ;; BROKEN
42 (list->vector-like absorbtion))
43 "holding variable.")
45 (defparameter *m-fit*
46 (fit-model *m*))
48 (estimates *m-fit*)
49 (covariation-matrix *m-fit*)
51 (defparameter *m3*
52 (regression-model (listoflists->matrix-like (list iron aluminum))
53 (list->vector-like absorbtion) :print nil))
54 (defparameter *m3-fit*
55 (fit-model *m3*))
59 #+nil
60 (progn ;; FIXME: Need to clean up data examples, licenses, attributions, etc.
61 ;; The following breaks because we should use a package to hold
62 ;; configuration details, and this would be the only package outside
63 ;; of packages.lisp, as it holds the overall defsystem structure.
64 (load-data "iris.lsp") ;; (the above partially fixed).
65 (variables)
66 diabetes )
69 (progn ;; dataframe
71 (describe (lift::run-tests :suite 'lisp-stat-ut-dataframe))
72 (lift::run-tests :suite 'lisp-stat-ut-dataframe)
74 (describe
75 (lift::run-test
76 :test-case 'lisp-stat-unittests::create-proto
77 :suite 'lisp-stat-unittests::lisp-stat-ut-proto))
79 (defparameter *my-df-1*
80 (make-instance 'dataframe-array
81 :storage #2A((1 2 3 4 5)
82 (10 20 30 40 50))
83 :doc "This is an interesting dataframe-array"
84 :case-labels (list "x" "y")
85 :var-labels (list "a" "b" "c" "d" "e")))
87 (setf (dfref *my-df-1* 0 0) -1d0)
91 (make-dataframe #2A((1 2 3 4 5)
92 (10 20 30 40 50)))
94 (make-dataframe (rand 4 3))
97 (equalp (dataset
98 (make-instance 'dataframe-array
99 :storage #2A(('a 'b)
100 ('c 'd))))
101 #2A(('a 'b)
102 ('c 'd)) )
104 (equalp (dataset
105 (make-instance 'dataframe-array
106 :storage #2A((1 2)
107 (3 4))))
108 #2A((1 2)
109 (3 4)))
111 (equalp (dataset
112 (make-instance 'dataframe-array
113 :storage #2A((1d0 2d0)
114 (3d0 4d0))))
115 #2A((1d0 2d0)
116 (3d0 4d0)))
119 (defparameter *my-df-1*
120 (make-dataframe #2A((1 2 3 4 5)
121 (10 20 30 40 50))
122 :caselabels (list "x" "y")
123 :varlabels (list "a" "b" "c" "d" "e")
124 :doc "This is an interesting dataframe-array"))
126 (caselabels *my-df-1*)
127 (varlabels *my-df-1*)
130 (defparameter *my-df-2*
131 (make-instance 'dataframe-array
132 :storage
133 (make-array-from-listoflists
134 (cybertiggyr-dsv::load-escaped
135 "/media/disk/Desktop/sandbox/CLS.git/Data/example-mixed.csv"))
136 :doc "This is an interesting dataframe-array"))
137 #| :case-labels (list "x" "y")
138 :var-labels (list "a" "b" "c" "d" "e")
144 (progn ;; Data setup
146 (describe 'make-matrix)
148 (defparameter *indep-vars-2-matrix*
149 (make-matrix (length iron) 2
150 :initial-contents
151 (mapcar #'(lambda (x y)
152 (list (coerce x 'double-float)
153 (coerce y 'double-float)))
154 iron aluminum)))
157 (defparameter *dep-var*
158 (make-vector (length absorbtion)
159 :type :row
160 :initial-contents
161 (list
162 (mapcar #'(lambda (x) (coerce x 'double-float))
163 absorbtion))))
165 (make-dataframe *dep-var*)
166 (make-dataframe (transpose *dep-var*))
168 (defparameter *dep-var-int*
169 (make-vector (length absorbtion)
170 :type :row
171 :element-type 'integer
172 :initial-contents (list absorbtion)))
175 (defparameter *xv+1a*
176 (make-matrix
178 :initial-contents #2A((1d0 1d0)
179 (1d0 3d0)
180 (1d0 2d0)
181 (1d0 4d0)
182 (1d0 3d0)
183 (1d0 5d0)
184 (1d0 4d0)
185 (1d0 6d0))))
187 (defparameter *xv+1b*
188 (bind2
189 (ones 8 1)
190 (make-matrix
192 :initial-contents '((1d0)
193 (3d0)
194 (2d0)
195 (4d0)
196 (3d0)
197 (5d0)
198 (4d0)
199 (6d0)))
200 :by :column))
202 (m= *xv+1a* *xv+1b*) ; => T
204 (princ "Data Set up"))
209 (progn
210 ;; REVIEW: general Lisp use guidance
212 (fdefinition 'make-matrix)
213 (documentation 'make-matrix 'function)
215 #| Examples from CLHS, a bit of guidance.
217 ;; This function assumes its callers have checked the types of the
218 ;; arguments, and authorizes the compiler to build in that assumption.
219 (defun discriminant (a b c)
220 (declare (number a b c))
221 "Compute the discriminant for a quadratic equation."
222 (- (* b b) (* 4 a c))) => DISCRIMINANT
223 (discriminant 1 2/3 -2) => 76/9
225 ;; This function assumes its callers have not checked the types of the
226 ;; arguments, and performs explicit type checks before making any assumptions.
227 (defun careful-discriminant (a b c)
228 "Compute the discriminant for a quadratic equation."
229 (check-type a number)
230 (check-type b number)
231 (check-type c number)
232 (locally (declare (number a b c))
233 (- (* b b) (* 4 a c)))) => CAREFUL-DISCRIMINANT
234 (careful-discriminant 1 2/3 -2) => 76/9
242 (progn ;; FIXME: read data from CSV file. To do.
245 ;; challenge is to ensure that we get mixed arrays when we want them,
246 ;; and single-type (simple) arrays in other cases.
249 (defparameter *csv-num*
250 (cybertiggyr-dsv::load-escaped
251 #p"/media/disk/Desktop/sandbox/CLS.git/Data/example-numeric.csv"
252 :field-separator #\,
253 :trace T))
255 (nth 0 (nth 0 *csv-num*))
257 (defparameter *csv-num*
258 (cybertiggyr-dsv::load-escaped
259 #p"/media/disk/Desktop/sandbox/CLS.git/Data/example-numeric2.dsv"
260 :field-separator #\:))
262 (nth 0 (nth 0 *csv-num*))
265 ;; The handling of these types should be compariable to what we do for
266 ;; matrices, but without the numerical processing. i.e. mref, bind2,
267 ;; make-dataframe, and the class structure should be similar.
269 ;; With numerical data, there should be a straightforward mapping from
270 ;; the data.frame to a matrix. With categorical data (including
271 ;; dense categories such as doc-strings, as well as sparse categories
272 ;; such as binary data), we need to include metadata about ordering,
273 ;; coding, and such. So the structures should probably consider
275 ;; Using the CSV file:
277 (defun parse-number (s)
278 (let* ((*read-eval* nil)
279 (n (read-from-string s)))
280 (if (numberp n) n)))
282 (parse-number "34")
283 (parse-number "34 ")
284 (parse-number " 34")
285 (parse-number " 34 ")
287 (+ (parse-number "3.4") 3)
288 (parse-number "3.4 ")
289 (parse-number " 3.4")
290 (+ (parse-number " 3.4 ") 3)
292 (parse-number "a")
294 ;; (coerce "2.3" 'number) => ERROR
295 ;; (coerce "2" 'float) => ERROR
297 (defparameter *csv-num*
298 (cybertiggyr-dsv::load-escaped
299 #p"/media/disk/Desktop/sandbox/CLS.git/Data/example-numeric.csv"
300 :field-separator #\,
301 :filter #'parse-number
302 :trace T))
304 (nth 0 (nth 0 *csv-num*))
306 (defparameter *csv-num*
307 (cybertiggyr-dsv::load-escaped
308 #p"/media/disk/Desktop/sandbox/CLS.git/Data/example-numeric2.dsv"
309 :field-separator #\:
310 :filter #'parse-number))
312 (nth 0 (nth 0 *csv-num*))
314 ;; now we've got the DSV code in the codebase, auto-loaded I hope:
315 cybertiggyr-dsv:*field-separator*
316 (defparameter *example-numeric.csv*
317 (cybertiggyr-dsv:load-escaped "Data/example-numeric.csv"
318 :field-separator #\,))
319 *example-numeric.csv*
321 ;; the following fails because we've got a bit of string conversion
322 ;; to do. 2 thoughts: #1 modify dsv package, but mucking with
323 ;; encapsulation. #2 add a coercion tool (better, but potentially
324 ;; inefficient).
325 #+nil(coerce (nth 3 (nth 3 *example-numeric.csv*)) 'double-float)
327 ;; cases, simple to not so
328 (defparameter *test-string1* "1.2")
329 (defparameter *test-string2* " 1.2")
330 (defparameter *test-string3* " 1.2 ")
334 #+nil
335 (progn ;; experiments with GSL and the Lisp interface.
336 (asdf:oos 'asdf:load-op 'gsll)
337 (asdf:oos 'asdf:load-op 'gsll-tests)
339 ;; the following should be equivalent
340 (setf *t1* (LIST 6.18d0 6.647777777777779d0 6.18d0))
341 (setf *t2* (MULTIPLE-VALUE-LIST
342 (LET ((VEC
343 (gsll:make-marray 'DOUBLE-FLOAT
344 :INITIAL-CONTENTS '(-3.21d0 1.0d0 12.8d0)))
345 (WEIGHTS
346 (gsll:MAKE-MARRAY 'DOUBLE-FLOAT
347 :INITIAL-CONTENTS '(3.0d0 1.0d0 2.0d0))))
348 (LET ((MEAN (gsll:MEAN VEC)))
349 (LIST (gsll:ABSOLUTE-DEVIATION VEC)
350 (gsll:WEIGHTED-ABSOLUTE-DEVIATION VEC WEIGHTS)
351 (gsll:ABSOLUTE-DEVIATION VEC MEAN))))))
352 (eql *t1* *t2*)
354 ;; from (gsll:examples 'gsll::numerical-integration) ...
355 (gsll:integration-qng gsll::one-sine 0.0d0 PI)
357 (gsll:defun-single axpb (x) (+ (* 2 x) 3)) ;; a<-2, b<-3
358 (gsll:integration-qng axpb 1d0 2d0)
360 (let ((a 2)
361 (b 3))
362 (defun-single axpb2 (x) (+ (* a x) b)))
363 (gsll:integration-qng axpb2 1d0 2d0)
365 ;; BAD
366 ;; (gsll:integration-qng
367 ;; (let ((a 2)
368 ;; (b 3))
369 ;; (defun-single axpb2 (x) (+ (* a x) b)))
370 ;; 1d0 2d0)
372 ;; right, but weird expansion...
373 (gsll:integration-qng
374 (let ((a 2)
375 (b 3))
376 (defun axpb2 (x) (+ (* a x) b))
377 (gsll:def-single-function axpb2)
378 axpb2)
379 1d0 2d0)
381 ;; Linear least squares
383 (gsll:gsl-lookup "gsl_linalg_LU_decomp") ; => gsll:lu-decomposition
384 (gsll:gsl-lookup "gsl_linalg_LU_solve") ; => gsll:lu-solve
389 #+nil
390 (progn ;; philosophy time
392 (setf my-model (model :name "ex1"
393 :data-slots (list w x y z)
394 :param-slots (list alpha beta gamma)
395 :math-form (regression-model :formula '(= w (+ (* beta x)
396 (* alpha y)
397 (* gamma z)
398 normal-error))
399 :centrality 'median ; 'mean
402 #| or:
403 #R"W ~ x+ y + z "
406 (setf my-dataset (statistical-table :table data-frame-contents
407 :metadata (list (:case-names (list ))
408 (:var-names (list ))
409 (:documentation "string of doc"))))
411 (setf my-analysis (analysis
412 :model my-model
413 :data my-dataset
414 :parameter-map (pairing (model-param-slots my-model)
415 (data-var-names my-dataset))))
417 ;; ontological implications -- the analysis is an abstract class of
418 ;; data, model, and mapping between the model and data. The fit is
419 ;; the instantiation of such. This provides a statistical object
420 ;; computation theory which can be realized as "executable
421 ;; statistics" or "computable statistics".
422 (setf my-analysis (analyze my-fit
423 :estimation-method 'linear-least-squares-regression))
425 ;; one of the tricks here is that one needs to provide the structure
426 ;; from which to consider estimation, and more importantly, the
427 ;; validity of the estimation.
430 (setf linear-least-squares-regression
431 (estimation-method-definition
432 :variable-defintions ((list
433 ;; from MachLearn: supervised,
434 ;; unsupervised
435 :data-response-vars list-drv ; nil if unsup
437 :param-vars list-pv
438 :data-predictor-vars list-dpv
439 ;; nil in this case. these
440 ;; describe "out-of-box" specs
441 :hyper-vars list-hv))
442 :form '(regression-additive-error
443 :central-form (linear-form drv pv dpv)
444 :error-form 'normal-error)
445 :resulting-decision '(point-estimation interval-estimation)
446 :philosophy 'frequentist
447 :documentation "use least squares to fit a linear regression
448 model to data."))
450 (defparameter *statistical-philosophies*
451 '(frequentist bayesian fiducial decision-analysis)
452 "can be combined to build decision-making approaches and
453 characterizations")
455 (defparameter *decisions*
456 '(estimation selection testing)
457 "possible results from a...")
458 ;; is this really true? One can embedded hypothesis testing within
459 ;; estimation, as the hypothesis estimated to select. And
460 ;; categorical/continuous rear their ugly heads, but not really in
461 ;; an essential way.
463 (defparameter *ontology-of-decision-procedures*
464 (list :decisions
465 (list :estimation
466 (list :point
467 (list :maximum-likelihood
468 :minimum-entropy
469 :least-squares
470 :method-of-moments)
471 :interval
472 (list :maximum-likelihood
474 :testing
475 (list :fisherian
476 :neyman-pearson
477 (list :traditional
478 :bioequivalence-inversion)
479 :selection
480 (list :ranking
481 :top-k-of-n-select))
482 :parametric
483 :partially-parametric))
484 "start of ontology"))
487 ;;;; LM
489 (progn
491 (defparameter *y*
492 (make-vector
494 :type :row
495 :initial-contents '((1d0 2d0 3d0 4d0 5d0 6d0 7d0 8d0))))
498 (defparameter *xv+1*
499 (make-matrix
501 :initial-contents '((1d0 1d0)
502 (1d0 3d0)
503 (1d0 2d0)
504 (1d0 4d0)
505 (1d0 3d0)
506 (1d0 5d0)
507 (1d0 4d0)
508 (1d0 6d0))))
511 ;; so something like (NOTE: matrices are transposed to begin with, hence the incongruety)
512 (defparameter *xtx-2* (m* (transpose *xv+1*) *xv+1*))
513 ;; #<LA-SIMPLE-MATRIX-DOUBLE 2 x 2
514 ;; 8.0d0 28.0d0
515 ;; 28.0d0 116.0d0>
517 (defparameter *xty-2* (m* (transpose *xv+1*) (transpose *y*)))
518 ;; #<LA-SIMPLE-VECTOR-DOUBLE (2 x 1)
519 ;; 36.0d0
520 ;; 150.0d0>
522 (defparameter *rcond-2* 0.000001)
523 (defparameter *betahat-2* (gelsy *xtx-2* *xty-2* *rcond-2*))
524 ;; *xtx-2* => "details of complete orthogonal factorization"
525 ;; according to man page:
526 ;; #<LA-SIMPLE-MATRIX-DOUBLE 2 x 2
527 ;; -119.33147112141039d0 -29.095426104883202d0
528 ;; 0.7873402682880205d0 -1.20672274167718d0>
530 ;; *xty-2* => output becomes solution:
531 ;; #<LA-SIMPLE-VECTOR-DOUBLE (2 x 1)
532 ;; -0.16666666666668312d0
533 ;; 1.333333333333337d0>
535 *betahat-2* ; which matches R, see below
537 (documentation 'gelsy 'function)
540 ;; (#<LA-SIMPLE-VECTOR-DOUBLE (2 x 1)
541 ;; -0.16666666666668312 1.333333333333337>
542 ;; 2)
544 ;; ## Test case in R:
545 ;; x <- c( 1.0, 3.0, 2.0, 4.0, 3.0, 5.0, 4.0, 6.0)
546 ;; y <- c( 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0)
547 ;; lm(y~x)
548 ;; ## => Call: lm(formula = y ~ x)
550 ;; Coefficients: (Intercept) x
551 ;; -0.1667 1.3333
553 ;; summary(lm(y~x))
554 ;; ## =>
556 ;; Call:
557 ;; lm(formula = y ~ x)
559 ;; Residuals:
560 ;; Min 1Q Median 3Q Max
561 ;; -1.833e+00 -6.667e-01 -3.886e-16 6.667e-01 1.833e+00
563 ;; Coefficients:
564 ;; Estimate Std. Error t value Pr(>|t|)
565 ;; (Intercept) -0.1667 1.1587 -0.144 0.89034
566 ;; x 1.3333 0.3043 4.382 0.00466 **
567 ;; ---
568 ;; Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
570 ;; Residual standard error: 1.291 on 6 degrees of freedom
571 ;; Multiple R-squared: 0.7619, Adjusted R-squared: 0.7222
572 ;; F-statistic: 19.2 on 1 and 6 DF, p-value: 0.004659
576 ;; which suggests one might do (modulo ensuring correct
577 ;; orientations). When this is finalized, it should migrate to
578 ;; CLS.
582 (defparameter *n* 20) ; # rows = # obsns
583 (defparameter *p* 10) ; # cols = # vars
584 (defparameter *x-temp* (rand *n* *p*))
585 (defparameter *b-temp* (rand *p* 1))
586 (defparameter *y-temp* (m* *x-temp* *b-temp*))
587 ;; so Y=Xb + \eps
588 (defparameter *rcond* (* (coerce (expt 2 -52) 'double-float)
589 (max (nrows *x-temp*) (ncols *y-temp*))))
590 (defparameter *orig-x* (copy *x-temp*))
591 (defparameter *orig-b* (copy *b-temp*))
592 (defparameter *orig-y* (copy *y-temp*))
594 (defparameter *lm-result* (lm *x-temp* *y-temp*))
595 (princ (first *lm-result*))
596 (princ (second *lm-result*))
597 (princ (third *lm-result*))
598 (v= (third *lm-result*)
599 (v- (first (first *lm-result*))
600 (first (second *lm-result*))))
605 ;; Some issues exist in the LAPACK vs. LINPACK variants, hence R
606 ;; uses LINPACK primarily, rather than LAPACK. See comments in R
607 ;; source for issues.
610 ;; Goal is to start from X, Y and then realize that if
611 ;; Y = X \beta, then, i.e. 8x1 = 8xp px1 + 8x1
612 ;; XtX \hat\beta = Xt Y
613 ;; so that we can solve the equation W \beta = Z where W and Z
614 ;; are known, to estimate \beta.
616 ;; the above is known to be numerically instable -- some processing
617 ;; of X is preferred and should be done prior. And most of the
618 ;; transformation-based work does precisely that.
620 ;; recall: Var[Y] = E[(Y - E[Y])(Y-E[Y])t]
621 ;; = E[Y Yt] - 2 \mu \mut + \mu \mut
622 ;; = E[Y Yt] - \mu \mut
624 ;; Var Y = E[Y^2] - \mu^2
627 ;; For initial estimates of covariance of \hat\beta:
629 ;; \hat\beta = (Xt X)^-1 Xt Y
630 ;; with E[ \hat\beta ]
631 ;; = E[ (Xt X)^-1 Xt Y ]
632 ;; = E[(Xt X)^-1 Xt (X\beta)]
633 ;; = \beta
635 ;; So Var[\hat\beta] = ...
636 ;; (Xt X)
637 ;; and this gives SE(\beta_i) = (* (sqrt (mref Var i i)) adjustment)
640 ;; from docs:
642 (setf *temp-result*
643 (let ((*default-implementation* :foreign-array))
644 (let* ((m 10)
645 (n 10)
646 (a (rand m n))
647 (x (rand n 1))
648 (b (m* a x))
649 (rcond (* (coerce (expt 2 -52) 'double-float)
650 (max (nrows a) (ncols a))))
651 (orig-a (copy a))
652 (orig-b (copy b))
653 (orig-x (copy x)))
654 (list x (gelsy a b rcond))
655 ;; no applicable conversion?
656 ;; (m- (#<FA-SIMPLE-VECTOR-DOUBLE (10 x 1))
657 ;; (#<FA-SIMPLE-VECTOR-DOUBLE (10 x 1)) )
658 (v- x (first (gelsy a b rcond))))))
661 (princ *temp-result*)
663 (setf *temp-result*
664 (let ((*default-implementation* :lisp-array))
665 (let* ((m 10)
666 (n 10)
667 (a (rand m n))
668 (x (rand n 1))
669 (b (m* a x))
670 (rcond (* (coerce (expt 2 -52) 'double-float)
671 (max (nrows a) (ncols a))))
672 (orig-a (copy a))
673 (orig-b (copy b))
674 (orig-x (copy x)))
675 (list x (gelsy a b rcond))
676 (m- x (first (gelsy a b rcond)))
678 (princ *temp-result*)
681 (defparameter *xv*
682 (make-vector
684 :type :row ;; default, not usually needed!
685 :initial-contents '((1d0 3d0 2d0 4d0 3d0 5d0 4d0 6d0))))
687 (defparameter *y*
688 (make-vector
690 :type :row
691 :initial-contents '((1d0 2d0 3d0 4d0 5d0 6d0 7d0 8d0))))
693 ;; so something like (NOTE: matrices are transposed to begin with, hence the incongruety)
694 (defparameter *xtx-1* (m* *xv* (transpose *xv*)))
695 (defparameter *xty-1* (m* *xv* (transpose *y*)))
696 (defparameter *rcond-in* (* (coerce (expt 2 -52) 'double-float)
697 (max (nrows *xtx-1*)
698 (ncols *xty-1*))))
700 (defparameter *betahat* (gelsy *xtx-1* *xty-1* *rcond-in*))
702 ;; (#<LA-SIMPLE-VECTOR-DOUBLE (1 x 1)
703 ;; 1.293103448275862>
704 ;; 1)
706 ;; ## Test case in R:
707 ;; x <- c( 1.0, 3.0, 2.0, 4.0, 3.0, 5.0, 4.0, 6.0)
708 ;; y <- c( 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0)
709 ;; lm(y~x-1)
710 ;; ## =>
711 ;; Call:
712 ;; lm(formula = y ~ x - 1)
714 ;; Coefficients:
715 ;; x
716 ;; 1.293
718 (first *betahat*))
722 #+nil
723 (progn
725 (asdf:oos 'asdf:load-op 'cl-plplot)
727 (plot-ex))
731 (type-of #2A((1 2 3 4 5)
732 (10 20 30 40 50)))
734 (type-of (rand 10 20))
736 (typep #2A((1 2 3 4 5)
737 (10 20 30 40 50))
738 'matrix-like)
740 (typep (rand 10 20) 'matrix-like)
742 (typep #2A((1 2 3 4 5)
743 (10 20 30 40 50))
744 'array)
746 (typep (rand 10 20) 'array)