Skip to content
Simple demo project and overview for Nifty
Swift
Branch: master
Clone or download
Latest commit 4346baa Feb 1, 2017
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.gitignore update to new demo Nov 22, 2016
LICENSE ignore build files Jul 21, 2016
Package.swift update to new demo Nov 22, 2016
README.md Update documentation Jan 23, 2017
main.swift Update banner Feb 2, 2017

README.md

Nifty Demo

License

Here's a simple example of Nifty in action!

Overview

Fundamental Types

Nifty offers three fundamental types of data structures: vectors, matrices, and tensors, with various initializers for each. For example,

var v = Vector([2.34, 6, 0.000000034, 67.234, 98456456.234])

var M = Matrix([[276.0251,  498.3641,  751.2671], 
                [679.7027, -959.7440,  255.0951],
                [655.0980, -340.3857,  505.9571]])
                
var T = Tensor([3, 1, 3], [0.0, 0.1, 0.2, 1.0, 1.1, 1.2, 2.0, 2.1, 2.2])

Each type provides methods for cleanly displaying the data it contains. For example, calling print(v) displays,

<2.34   6   3.4E-8   67.234   9.846E7>

calling print(M) displays,

R0:   276.025    498.364   751.267
R1:   679.703   -959.744   255.095
R2:   655.098   -340.386   505.957

and calling print(T) displays,

[..., ..., 0]:
R0:   0.0
R1:   1.0
R2:   2.0

[..., ..., 1]:
R0:   0.1
R1:   1.1
R2:   2.1

[..., ..., 2]:
R0:   0.2
R1:   1.2
R2:   2.2

By default, the data is rounded to keep the display compact, but the settings can be adjusted for each instance. Additionally, each can be set to have a name displayed along with the contents,

M.name = "MyNiftyMatrix"
M.showName = true

Now, calling print(M) displays,

MyNiftyMatrix:
R0:   276.025    498.364   751.267
R1:   679.703   -959.744   255.095
R2:   655.098   -340.386   505.957

Nifty fundamental structures are all zero-indexed, stored in row-major order, and can be easily indexed, subscripted, and sliced. For example,

V[3] = 3.0

M[0] = 0.1
M[4] = 1.1
M[8] = 2.2

M[0,1] = 0.1
M[1,1] = 1.1
M[2,2] = 2.2

M[1...2,1...2] = Matrix(2, [11,12,21,22]) 

let t = T[0, 0, 0..<3]

Most of the functionality provided by Nifty is based on these fundamental types, which usually contain floating-point numbers. However, all of the fundamental types are generic and can contain any type of values. For example,

let Ms = Matrix(2, 4, value: "X")

creates a 2-by-4 string matrix containing the letter "X" in each cell, which displays as,

R0:   X   X   X   X
R1:   X   X   X   X
Linear Algebra

Nifty provides a variety of linear algebra functions, mainly operating on Matrix<Double> types.

Here's an example of how we could invert a matrix, using both the function inv() and the ~ prefix operator (Nifty provides symbolic operators for a variety of common math functions):

let Mi = ~M 
let _  = inv(M)

Here, we'll use Nifty to solve the system of equations A*x = B for x:

let A = Matrix<Double>([[21,  3,  4,  4, 17],
                        [23,  7, 25, 11,  1],
                        [ 4, 14, 24, 23, 22],
                        [23, 24, 13, 20, 24],
                        [16, 25, 21, 24, 17]], name: "A")

let B = Matrix<Double>([[18, 21, 11, 13,  7],
                        [ 1, 18, 10, 12, 17],
                        [ 7,  8, 20, 17, 17],
                        [ 2, 24, 20, 18,  5],
                        [ 3,  1,  5, 19,  3]], name: "B")

let x = A-/B   // or, mldivide(A, B)

Calling print(x) displays the following (note that the output matrix was given a name based on the inputs' names and the transform applied--all Nifty functions do this by default!):

mldivide(A, B):
R0:    4.45782   -5.77337   -5.80571    1.63021   -2.26439
R1:   -12.5532    17.9503     16.122   -3.95338    5.81648
R2:   -10.5024    16.5735    15.0794   -3.31092     6.6158
R3:       23.1   -36.2762   -32.3031    7.87055   -12.7877
R4:   -5.19676    9.83532     9.0264   -1.62428    3.63471

There is a lot more linear algebra functionality in Nifty--check out the demo code for further examples or the Nifty documentation for a complete listing.

Random Numbers

Nifty also provides a variety of easy-to-use random number functions. For example, creating a 6-by-3 matrix of random whole numbers between 35 and 110:

let Ri = randi(6, 3, min: 35, max: 110)

Or creating a list of 5 random vectors from a multivariate normal distribution:

let mu      = Vector([2.0,3.0], name: "μ")       
let sigma   = Matrix<Double>([[1,1.5],[1.5,3.0]], name: "Σ")
let vectors = mvnrnd(mu: mu, sigma: sigma, cases: 5)
Timing

Nifty makes timing code snippets particularly easy. MATLAB users will be familiar with tic and toc, which start a stopwatch, and return the time on the stopwatch, respectively. For example,

tic()
let Z = randi(500, 500, min: -999, max: 999)
toc()

displays the number of seconds it took to generate Z. Times are by default in seconds, but the default can be overridden to provide the ellapsed time in the desired units. For example,

tic()
let Zi = inv(Z)
toc(.ms)

displays the ellapsed time in milliseconds. Rather than displaying the time, the result can be stored to a variable. For example,

tic()
let _ = Z * Zi
let time = toc(returning: .minutes)

Running the Demo

Getting Nifty running is easy; follow the steps below:

  • Clone this repository

  • Make sure you've met the requirements for Nifty

  • Open a terminal inside your local copy of this repository

  • Run swift build. You should see the package manager cloning into various repositories to gather the needed packages, compiling, and then linking.

  • Once the build has completed, execute .build/debug/Nifty-demo to run the demo!

    Look here if you get linker errors while building

You can’t perform that action at this time.