Code Monkey home page Code Monkey logo

linear-algebra's Introduction

Contributors Forks Stargazers Issues MS-PL License LinkedIn


Logo

Lisp-Stat

An environment for statistical computing
Explore the docs »

Report Bug · Request Feature · Reference Manual

Table of Contents

  1. About the Project
  2. Getting Started
  3. Usage
  4. Roadmap
  5. Resources
  6. Contributing
  7. License
  8. Contact

About the Project

Lisp-Stat provides support for vectorized mathematical operations, and a comprehensive set of statistical methods that are implemented using the latest numerical algorithms. In addition, Common Lisp provides a dynamic programming environment (REPL), an excellent object-oriented facility (CLOS) and meta-object protocol (MOP).

Lisp-Stat is fully functional today, and most of the XLISP-STAT libraries can be ported with the aid of a compatibility package XLS-compat. This gives Lisp-Stat a leg up on ecosystem development.

Built With

Getting Started

To get a local copy up and running follow these steps:

Prerequisites

An ANSI Common Lisp implementation. Developed and tested with SBCL and CCL.

Note: CCL is in poor condition these days, and we no can longer support it due to some serious problem with numerical accuracy. See issue 390 for just one of the problems. A shame, because it's a great environment to work in.

Installation

Lisp-Stat is composed of several systems that are designed to be independently useful. So you can, for example, use select to obtain selections from two dimensional arrays without bringing in all of Lisp-Stat.

The easy way

Quicklisp has many dependencies, and the easiest way to load it is with a package manager, such as Quicklisp or CLPM. The install is a one-liner:

(clpm-client:sync :sources "clpi") ;sources may vary
(ql:quickload :lisp-stat)

From source

To make the system accessible to ASDF (a build facility, similar to make in the C world), clone the repository in a directory ASDF knows about. By default the common-lisp directory in your home directory is known. Create this if it doesn't already exist and then:

  1. Clone the repositories
cd ~/common-lisp && \
git clone https://github.com/Lisp-Stat/data-frame.git && \
git clone https://github.com/Lisp-Stat/dfio.git && \
git clone https://github.com/Lisp-Stat/special-functions.git && \
git clone https://github.com/Lisp-Stat/numerical-utilities.git && \
git clone https://github.com/Lisp-Stat/array-operations.git && \
git clone https://github.com/Lisp-Stat/documentation.git && \
git clone https://github.com/Lisp-Stat/distributions.git && \
git clone https://github.com/Lisp-Stat/plot.git && \
git clone https://github.com/Lisp-Stat/select.git && \
git clone https://github.com/Lisp-Stat/cephes.cl.git && \
git clone https://github.com/Symbolics/alexandria-plus && \
git clone https://github.com/Lisp-Stat/statistics.git && \
git clone https://github.com/Lisp-Stat/lla.git && \
git clone https://github.com/Lisp-Stat/smoothers && \
git clone https://github.com/Lisp-Stat/lisp-stat.git
  1. Reset the ASDF source-registry to find the new system (from the REPL)
    (asdf:clear-source-registry)
  2. Load the system
    (asdf:load-system :lisp-stat)

If you have installed the slime ASDF extensions, you can invoke this with a comma (',') from the slime REPL.

You'll need to use Quicklisp, CLPM or manually obtain the remaining third-party dependencies.

Running Tests

To run the lisp-stat tests, evaluate this form: (asdf:test-system :lisp-stat)

Usage

Create a data frame from a file named sg-weather.csv on the local disk:

(defparameter *df*
	(read-csv #P"LS:DATA;sg-weather.csv"))

For more examples, please refer to the Documentation.

Roadmap

See the open issues for a list of proposed features (and known issues).

Resources

This system is part of the Lisp-Stat project; that should be your first stop for information. Also see the community page for more information.

Contributing

Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are greatly appreciated. Please see CONTRIBUTING for details on the code of conduct, and the process for submitting pull requests.

License

Distributed under the MS-PL License. See LICENSE for more information.

Contact

Project Link: https://github.com/lisp-stat/lisp-stat

linear-algebra's People

Contributors

beberman avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar

linear-algebra's Issues

Develop backend dispatch pattern

One of the things we're going to need is a good pattern for dispatching to various backends. Here's one possible pattern that I used for a scatterplot smoother:

 ;; What about the case where both lla and linear-algebra are loaded?
		    beta #+lla (lla:solve A b)
			 #+linear-algebra (linear-algebra:solve A b)
		         #-(or lla linear-algebra) (solve-matrix (aops:stack-cols A b))

As I start to use it, I think it's more of an anti-pattern because:

  • It doesn't easily handle the case where I might want multiple back-ends in one application (is this an edge case?)
  • It is only evaluated at compile-time, so if I want to change I need to recompile
  • It sort of abuses *features* in a non-specific way I don't like

I know that MGL-MAT has a way to automatically dispatch methods depending on whether BLAS or CUDA are available. Generally his architecture seems similar to that of linear-algebra, with various 'kernels' (lisp, CUDA, BLAS) that are operated on by lisp code. It might be worth studying.

Consolidate floating-point and num-utils

linear-algebra has a dependency on floating-point, where float-equal has an overlap in functionality with numerical-utilities num=.

Looking at the code,%float-equal is much like num= with *epsilon* replaced by *tolerance*, with the exception that num= works on vectors and arrays. However the definitions of error are different. In num=:

(<= (abs (- a b)) (* (max 1 (abs a) (abs b)) tolerance))

and in %float-equal:

(defun %relative-error (exact approximate)
  "Return the relative error of the numbers."
  (abs
   (if (or (zerop exact) (zerop approximate))
       (- exact approximate)
       (/ (- exact approximate) exact))))

Perhaps someone with more recent experience here can weigh in on whether or not these are actually equivalent? By my reading they are for all practical purposes.

Advantages, as I see them for num=:

  • Works on rational types as well as vectors and arrays
  • Tested rather extensively during the development of the special-functions system
  • Requires less rework; no one is currently using floating-point

Advantages for floating-point:

  • Documented reference Numerical Algorithms with C

Finally, looking at the exports for float-point:

(defpackage :floating-point
  (:use :common-lisp)
  (:nicknames :fp)
  ;; Control parameters
  (:export :*epsilon* :*significant-figures*)
  ;; Constants
  (:export :pi/2)
  ;; Error analysis
  (:export :default-epsilon
           :relative-error)
  ;; Floating point predicates
  (:export :float-equal
	   :sigfig-equal))

I can't see anything there that num= doesn't give us, so I'm inclined to suggest we archive floating-point and use num= as a 'standard' for linear-algebra. There's a few bits and pieces that would be nice to move to numerical-utilities, like constants.lisp and the epsilon stuff, but none of that is critical. If it turns out something is missing, then we can move it to num= right away.

Thoughts? Comments? Did I miss something?

Refactor unary-operations

unary-operations implements the norm functions, but in a rather clumsy way. Refactor this using existing utilities.

Style warnings in loop

When doing a fresh compile, 7 style warnings are generated:

 caught STYLE-WARNING:
;   The binding of SB-C::Y is not a REAL:
;    NIL
;   See also:
;     The SBCL Manual, Node "Handling of Types"

They don't affect the test results, but it would be nice to eliminate them.

Update testing framework

lisp-unit is abandoned (?) and we should consider moving it to something like cl-unit2, both as an exercise to learn linear-algebra better, but also to bring all the dependencies to supported versions and, finally, to 'standardise' on a single test framework throughout the ecosystem (the Lisp-Stat ecosystem).

As far as I can tell this is a search-and-replace operation, as the systems (lisp-unit and cl-unit) are rather similar, and at the same time standardising on the numeric equality predicate (see issue #3).

make-matrix fails on upper-triangular matrix

Commit 8c9271f re-enabled tests for triangular-matrix types, and exposed a bug in make-matrix. Here is one of the failing tests:

  (let ((matrix (make-matrix 10 10 :matrix-type 'upper-triangular-matrix :initial-element 1.0)))
    (assert-true (matrixp matrix))
    (assert-true (typep matrix 'upper-triangular-matrix))
    (assert-num= matrix (upper-triangular-array))) ; failure is here

Looking at the compared values:

LS-USER> (linear-algebra-test::upper-triangular-array)
#2A((1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0)
    (0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0)
    (0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0)
    (0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0)
    (0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0)
    (0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0)
    (0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0)
    (0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0)
    (0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0)
    (0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0))

That is a correct upper-triangular-matrix.

LS-USER> (linear-algebra:make-matrix 10 10 :matrix-type 'linear-algebra:upper-triangular-matrix :initial-element 1.0)
#<LINEAR-ALGEBRA:UPPER-TRIANGULAR-MATRIX {102D7167C3}>
LS-USER> (linear-algebra::contents *)
#2A((1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0)
    (1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0)
    (1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0)
    (1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0)
    (1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0)
    (1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0)
    (1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0)
    (1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0)
    (1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0)
    (1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0))

but make-matrix returns an array of all ones.

@beberman, is this something you can look into?

Refactor binary-operations

This consists of:

  1. Developing a high level generic API based on numpy's linear algebra operations. Best location is probably array-operations
  2. Implement them in lisp by refactoring or replacing the existing functions

Then implement the same in LLA so the API's match.

Underlying data structure

If we are going to refactor to use the builtin vector method then I would consider doing a full refactor of all the underlying classes in this system.

The system should support arbitrary tensors of any number of dimensions if you want to make this useful for more general computations.

The system should also support a wider class of specific matrix types - in particular diagonal, tridiagonal, upper tridiagonal etc.

My suggestion would be that the underlying type be based on vector for storage, a permutation operator that can be bound, and a ref that takes an index list.

So
(defclass tensor ()
((data - as a vector)
(dimensions - list)
(permutation - a list of integers or nil)))

Then a core reference function
(defmethod ref ((index ref) (tensor tensor))
which checks if permutation is nil/ non nil. If nil it just computes the required offset into the data given the dimensions and the index

If non-nil it first applies the permutation to the index then computes the offset.

For specialized matrixes we override this function and return 0 if the index is outside the range.

So then matrix is just
(defclass matrix (tensor)
)

with
(defgeneric make-matrix (&key &otherkeys)
(:method (&key row column) building a default)
(:method (&key row column type) building a specific type))

(defmethod transpose ((m matrix))
; this just sets the permutation to nil if it exists otherwise it sets it to '(1 0))
)

Then the generic matrix multiplies will work with all types if it uses ref underneath and specialized ones can be written to minimize the lookups as needed.

Review specialised matrix types

The system includes several specialised matrix types:

  • hermitian
  • square
  • symmetric
  • triangular

There are also existing versions of these matrix types in numerical-utilities. IMO, the implementation in numerical-utilities far outclass those in linear-algebra. The only thing missing from them is a lisp-based solver, which linear-algebra does have. There are LAPACK solvers in LLA, for those specialised matrices though.

This issue is to track a review of both of these and (probably) figure out a way to implement the solve function on the matrix implementations in numerical-utilities. An alternative may be to say that we're not going to implement a lisp based solver. I have used the gauss solver in an implementation of lowess, and find the speed very slow. This might be the reason that a lisp-based solver was never implemented for the specialised types in numerical-utilities.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.