Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Julia's multi-dimensional array


May 14, 2021 Julia


Table of contents


Multi-dimensional array

An array is a collection of objects that exist in a multi-dimensional grid. T ypically, an array contains an object of any Any For most calculations, array objects are generally more specific Float64 Int32

For performance reasons, Julia doesn't want to write the program as a quantitative form.

In Julia, arguments are passed to a function by reference. J ulia's library function does not modify the input passed to it. When the user writes code, if you want to do similar functions, pay attention to copy the input first.

Array

The underlying function

Function Description
eltype(A) The type of element in A
length(A) The number of elements in A
ndims(A) A There are several dimensions
nnz(A) A The number of non-zero elements
size(A) Returns a multiple group of dimensions with an element of A
size(A,n) A The length on a dimension
stride(A,k) On dimension k, the linear index distance of the adjacent element (in memory).
strides(A) Returns a multigroup whose elements are linear index distances on each dimension, adjacent elements (in memory).

Construction and initialization

The dims... can be neither a single multiple group of dimensions nor a set of values when a dimension is a variable parameter.

Function Description
Array(type, dims...) A dense array that has not been initialized
cell(dims...) Un initialized cell arrays (heterogeneous arrays)
zeros(type, dims...) | a full 0 array of the specified type. If type is not type the default Float64
zeros(A) full 0 array, with the same element type and size as A .
ones(type, dims...) | 1 array of the specified type. If type is not type the default Float64
ones(A) 1 array, with the same element type and size as A .
trues(dims...) | The true Bool full true
falses(dims...) | Bool Bool false false
reshape(A, dims...) Arrange the data in the array by the specified dimension
copy(A) | Copy A
deepcopy(A) | Copy A recursively copy its elements
similar(A, element_type, dims...) The property is the same un initialized array as the input array (dense, sparse, etc.), but indicates the element type and dimension.
The second and third parameters can be omitted, omitting element types A default to A
reinterpret(type, A) The binary data is the same array as the input array, but indicates the element type
rand(dims) | A random array of Float64 types that are independently and evenly distributed on the .0,1
randn(dims) | A random array of independent normals of the Float64 type with an average of 0 and a standard deviation of 1
eye(n) | n x n unit matrix
eye(m, n) | m x n unit matrix
linspace(start, stop, n) | A linear stop n elements from start to stop
fill!(A, x) | Fill array x with the value A
fill(x, dims) | Create an array of specified sizes and fill x

Connection

You can connect arrays in any dimension using the following functions:

Function Describe
cat(k, A...) | Connect the input n-d array on the k dimension
vcat(A...) | cat(1, A...) A short history of
hcat(A...) | cat(2, A...) A short history of

The measured values passed to these functions are treated as a meta-array.

Cascading is so common that special syntax has been designed for them:

Said Call
[A B C ...] | hcat
[A, B, C, ...] | vcat
[A B; C D; ...] | hvcat

hvcat cascading on one-dimensional (using a sign interval) or on two-dimensional (using space intervals).

Comprehensions

Comprehensions are used to construct arrays. Its syntax is similar to the collection markup method in mathematics:

    A = [ F(x,y,...) for x=rx, y=ry, ... ]

F(x,y,...) V alue is x y and so on. T he values of these variables can be any 1:n but in most cases they use a range object similar to 2:(n-1) or an array explicitly indicated as similar to [1.2, 3.4, 5.7] The result is an N-dimensional dense array.

The following example calculates the weighted average of the current element and the left and right neighbor element on dimension 1:

    julia> const x = rand(8)
    8-element Array{Float64,1}:
     0.843025
     0.869052
     0.365105
     0.699456
     0.977653
     0.994953
     0.41084
     0.809411

    julia> [ 0.25*x[i-1] + 0.5*x[i] + 0.25*x[i+1] for i=2:length(x)-1 ]
    6-element Array{Float64,1}:
     0.736559
     0.57468
     0.685417
     0.912429
     0.8446
     0.656511

Note: In the example above, x a constant because Julia's type inference is not good for a very large number of global variables.

You can explicitly indicate its type before comprehension. T o avoid declaring x as a constant in the previous example, but still make sure that the result type Float64 write this:

    Float64[ 0.25*x[i-1] + 0.5*x[i] + 0.25*x[i+1] for i=2:length(x)-1 ]

Using braces instead of square brackets, you can reduce it to Any types:

    julia> { i/2 for i = 1:3 }
    3-element Array{Any,1}:
     0.5
     1.0
     1.5

Index

The common syntax for index n-dimensional array A is:

    X = A[I_1, I_2, ..., I_n]

Where I_k can be:

  1. Scalar
  2. Meets : a:b , a:b:c format Range
  3. Any integer vector, including an empty vector []
  4. Boolean value vector

The dimensions of the result X are (length(I_1), length(I_2), ..., length(I_n)) and the value at the index (i_1, i_2, ..., i_n) is A[I_1[i_1], I_2[i_2], ..., I_n[i_n]] D imension information that is affixed to the standard index after it is discarded. F or example, A[I, 1] (length(I),) . T he Boolean value vector is first find by the find function. The length of the dimension indexed by the Boolean vector is the number of true values in the vector.

The index syntax getindex

    X = getindex(A, I_1, I_2, ..., I_n)

For example:

    julia> x = reshape(1:16, 4, 4)
    4x4 Array{Int64,2}:
     1  5   9  13
     2  6  10  14
     3  7  11  15
     4  8  12  16

    julia> x[2:3, 2:end-1]
    2x2 Array{Int64,2}:
     6  10
     7  11

n:n-1 are sometimes used to indicate that the mutual index n-1 n For example, the searchsorted custom to point out that the value of the insertion point is not in the sorted array:

    julia> a = [1,2,5,6,7];

    julia> searchsorted(a, 3)
    3:2

Assignment

The common syntax for assigning values to n-dimensional array A is:

    A[I_1, I_2, ..., I_n] = X

Where I_k may be:

  1. Scalar
  2. Meets : a:b , a:b:c format Range
  3. Any integer vector, including an empty vector []
  4. Boolean value vector

If X is an array, its dimensions should (length(I_1), length(I_2), ..., length(I_n)) and A i_1, i_2, ..., i_n at i_n are overstritten as X[I_1[i_1], I_2[i_2], ..., I_n[i_n]] If X not an array, its value is written to all the A is referenced.

The Boolean value vector used for the index is getindex (converted by the find function first).

Index assignment syntax is equivalent to setindex!

      setindex!(A, X, I_1, I_2, ..., I_n)

For example:

    julia> x = reshape(1:9, 3, 3)
    3x3 Array{Int64,2}:
     1  4  7
     2  5  8
     3  6  9

    julia> x[1:2, 2:3] = -1
    -1

    julia> x
    3x3 Array{Int64,2}:
     1  -1  -1
     2  -1  -1
     3   6   9

To quantify operators and functions

Arrays support the following operators. Element-by-element operations should use binary operators with a point-by-point (element-by-element) version.

  1. One dollar: - , + , !
  2. Binary: + - * .* / ./ \ .\ ^ .^ div mod
  3. Comparison: .== , .!= , .< , .<= , .> , .>=
  4. One-dollar boolean value or bit operation: ~
  5. Binary Boolean value or bit operation: & , | , $

Some operators that do not have a "point" (element-by-element) operation are used when an argument is a measure. These operators have * / , \ bit-by-bit operators.

Note that a comparison == such as an operation is an operation on the entire array, and it gives a Boolean return value. Bit-by-bit comparisons use point operators.

The following built-in functions are also quantified, i.e. the functions are element-by-element:

    abs abs2 angle cbrt
    airy airyai airyaiprime airybi airybiprime airyprime
    acos acosh asin asinh atan atan2 atanh
    acsc acsch asec asech acot acoth
    cos  cospi cosh  sin  sinpi sinh  tan  tanh  sinc  cosc
    csc  csch  sec  sech  cot  coth
    acosd asind atand asecd acscd acotd
    cosd  sind  tand  secd  cscd  cotd
    besselh besseli besselj besselj0 besselj1 besselk bessely bessely0 bessely1
    exp  erf  erfc  erfinv erfcinv exp2  expm1
    beta dawson digamma erfcx erfi
    exponent eta zeta gamma
    hankelh1 hankelh2
     ceil  floor  round  trunc
    iceil ifloor iround itrunc
    isfinite isinf isnan
    lbeta lfact lgamma
    log log10 log1p log2
    copysign max min significand
    sqrt hypot

Note the max min max minimum maximum which is to operate on multiple arrays to find the maximum minimum of the elements corresponding to each array, and minimum, which is to find the maximum minimum value of the array on an array.

Julia @vectorize_1arg and @vectorize_2arg two macros that are used to quantify any single or two parameters, respectively. E ach macro receives two arguments, the type of function argument and the function name. For example:

    julia> square(x) = x^2
    square (generic function with 1 method)

    julia> @vectorize_1arg Number square
    square (generic function with 4 methods)

    julia> methods(square)
    # 4 methods for generic function "square":
    square{T<:Number}(::AbstractArray{T<:Number,1}) at operators.jl:359
    square{T<:Number}(::AbstractArray{T<:Number,2}) at operators.jl:360
    square{T<:Number}(::AbstractArray{T<:Number,N}) at operators.jl:362
    square(x) at none:1

    julia> square([1 2 4; 5 6 7])
    2x3 Array{Int64,2}:
      1   4  16
     25  36  49

Broadcasting

Sometimes you want to binaryly binary the arrays of different dimensions, such as increasing the amount to each column of the matrix. The inefficient way is to copy the vector into a matrix of the same dimension:

    julia> a = rand(2,1); A = rand(2,3);

    julia> repmat(a,1,3)+A
    2x3 Array{Float64,2}:
     1.20813  1.82068  1.25387
     1.56851  1.86401  1.67846

When the dimensions are large, the efficiency is low. Julia broadcast function that extends the dimensions of the array parameters to match the corresponding dimensions of another array without the need for additional memory, and then calls the specified binary functions on an element-by-element basis:

    julia> broadcast(+, a, A)
    2x3 Array{Float64,2}:
     1.20813  1.82068  1.25387
     1.56851  1.86401  1.67846

    julia> b = rand(1,2)
    1x2 Array{Float64,2}:
     0.867535  0.00457906

    julia> broadcast(+, a, b)
    2x2 Array{Float64,2}:
     1.71056  0.847604
     1.73659  0.873631

Element-by-element operators, such .+ . . . .* broadcast if necessary. The broadcast! also available to clearly indicate the broadcast_getindex and broadcast_setindex! can broadcast index values before the index.

Realize

Julia's underlying array type is the abstract type AbstractArray{T,N} where the dimension N the element type is T AbstractVector AbstractMatrix 1D and 2D alias, respectively.

AbstractArray type contains any array-like type, and its implementation will be very different from the usual array. F or example, any AbstractArray{T,N} should have at least size(A) (return Int multiple groups), getindex(A,i) getindex(A,i1,...,iN) T and a variable array should be able setindex! 。 T hese operations require time complexity or O(1) complexity at near constants, otherwise some array functions are particularly slow. The specific type also similar(A,T=eltype(A),dims=size(A)) to allocate a copy.

DenseArray an abstract AbstractArray that should include all arrays on the regular offset of memory, so it can be passed externally to the C and Fortran functions on this memory layout.
The subsype should provide a stride(A,k) that returns the dimension k of the i 1 adding 1 to the given dimension k should increase the i in getindex(A,i) stride(A,k) k If a pointer conversion method is convert(Ptr{T},A) the memory layout should correspond to these extensions in the same way.

Array{T,N} is DenseArray where elements are stored in column order (see Code Performance Optimization for details). Vector and Matrix alias for 1 and 2D, respectively.

SubArray a AbstractArray which is indexed by reference rather than replication. S ubArray is SubArray which is getindex (using arrays and a set of index parameters). sub T he result of getindex but its data remains in place. sub sub saves the index vector of the input in the SubArray object, which will be used to indirectly index the original array.

StridedVector StridedMatrix defined for convenience. By passing Array SubArray Julia can make large-scale calls to BLAS and LAPACK functions, improving the efficiency of memory requests and replication.

The following example calculates the QR decomposition of a small block in a large array without constructing a temporary variable and calling the appropriate LAPACK function directly.

    julia> a = rand(10,10)
    10x10 Array{Float64,2}:
     0.561255   0.226678   0.203391  0.3089120.750307  0.235023   0.217964
     0.718915   0.537192   0.556946  0.996234      0.666232  0.509423   0.660788
     0.493501   0.0565622  0.118392  0.493498      0.262048  0.940693   0.252965
     0.0470779  0.736979   0.264822  0.228787      0.161441  0.897023   0.567641
     0.343935   0.32327    0.795673  0.452242      0.468819  0.628507   0.511528
     0.935597   0.991511   0.571297  0.744850.84589   0.178834   0.284413
     0.160706   0.672252   0.133158  0.65554       0.371826  0.770628   0.0531208
     0.306617   0.836126   0.301198  0.0224702     0.39344   0.0370205  0.536062
     0.890947   0.168877   0.32002   0.486136      0.096078  0.172048   0.77672
     0.507762   0.573567   0.220124  0.165816      0.211049  0.433277   0.539476

    julia> b = sub(a, 2:2:8,2:2:4)
    4x2 SubArray{Float64,2,Array{Float64,2},(StepRange{Int64,Int64},StepRange{Int64,Int64})}:
     0.537192  0.996234
     0.736979  0.228787
     0.991511  0.74485
     0.836126  0.0224702

    julia> (q,r) = qr(b);

    julia> q
    4x2 Array{Float64,2}:
     -0.338809   0.78934
     -0.464815  -0.230274
     -0.625349   0.194538
     -0.527347  -0.534856

    julia> r
    2x2 Array{Float64,2}:
     -1.58553  -0.921517
      0.0       0.866567

Sparse matrix

A sparse matrix is a matrix whose elements are mostly 0.

Column Compression (CSC) storage

In Julia, the sparse matrix uses column compression (CSC) format. T he type of Julia sparse matrix is SparseMatrixCSC{Tv,Ti} where Tv the type of non-zero element, Ti is the Ti type, which stores column pointers and row indexes:

    type SparseMatrixCSC{Tv,Ti<:Integer} <: AbstractSparseMatrix{Tv,Ti}
        m::Int                  # Number of rows
        n::Int                  # Number of columns
        colptr::Vector{Ti}      # Column i is in colptr[i]:(colptr[i+1]-1)
        rowval::Vector{Ti}      # Row values of nonzeros
        nzval::Vector{Tv}       # Nonzero values
    end

Column compression storage makes it easy to access elements of sparse matrices simply and quickly by column, but is slower by row. Inserting non-zero values into operations such as CSC structures is slow because in a sparse matrix, the elements behind the inserted elements are shifted one by one.

If the data you get from elsewhere is stored in CSC format and you want to read it in Julia, make sure that its serial number starts at 1. T he row index values in each column should be in order. If your SparseMatrixCSC unsorted row index values, the quickest way to sort them is to transtounce them twice.

Sometimes, some SparseMatrixCSC and later operations are convenient. Base is allowed in Base (but there is no guarantee that these zero values will remain in the operation). T hese stored zeros are considered non-zero values by many functions. nnz function returns the number of elements stored in the sparse data structure, including the zeros stored. To get an accurate number of non-zero elements, countnz which checks the values of each element one by one (so its time complexity is no longer constant, but is directly related to the number of elements).

Construct a sparse matrix

The dense matrix has zeros and the sparse matrix corresponds to the function, which can be prefixed sp before the function name: eye

    julia> spzeros(3,5)
    3x5 sparse matrix with 0 Float64 entries:

    julia> speye(3,5)
    3x5 sparse matrix with 3 Float64 entries:
            [1, 1]  =  1.0
            [2, 2]  =  1.0
            [3, 3]  =  1.0

sparse is a more common method of constructing sparse matrices. I t enters row I column index vector J and non-zero value vector V sparse(I,J,V) a sparse matrix that satisfies S[I[k], J[k]] = V[k]

    julia> I = [1, 4, 3, 5]; J = [4, 7, 18, 9]; V = [1, 2, -5, 3];

    julia> S = sparse(I,J,V)
    5x18 sparse matrix with 4 Int64 entries:
            [1 ,  4]  =  1
            [4 ,  7]  =  2
            [5 ,  9]  =  3
            [3 , 18]  =  -5

The sparse is findn input when constructing the sparse matrix:

    julia> findn(S)
    ([1,4,5,3],[4,7,9,18])

    julia> findnz(S)
    ([1,4,5,3],[4,7,9,18],[1,2,3,-5])

Another way to construct a sparse matrix is to use sparse to convert a dense matrix to a sparse matrix:

    julia> sparse(eye(5))
    5x5 sparse matrix with 5 Float64 entries:
            [1, 1]  =  1.0
            [2, 2]  =  1.0
            [3, 3]  =  1.0
            [4, 4]  =  1.0
            [5, 5]  =  1.0

You can dense full function to do the inverse. issparse be used to check if the matrix is sparse:

    julia> issparse(speye(5))
    true

Sparse matrix operations

The arithmetic of dense matrices can also be used on sparse matrices. I t is a costly resource to assign the sparse matrix. In most cases, it findnz to convert (I,J,V) perform operations (I,J,V) and finally refactor the sparse matrix.

Dense matrix and sparse matrix function correspondence

The following table lists the functions of the built-in sparse matrix and their corresponding dense matrices. Typically, a function of a sparse matrix either returns the S as the input sparse matrix S, d as the odds that each element of the matrix is d

See the stdlib-sparse section of the standard library documentation.

Sparse matrix Dense matrix Description
spzeros(m,n) zeros(m,n) Construct a full 0 matrix of m x n (spzeros (m,n) is an empty matrix)
spones(S) ones(m,n) The constructed full 1 matrix is different from the dense version, and spones are as sparse as S
speye(n) eye(n) Construct a unit matrix of m x n
full(S) sparse(A) Convert to sparse and dense matrices
sprand(m,n,d) rand(m,n) The random matrix constructed m-by-n (with a dense density of d) is distributed evenly with the non-zero elements of the independent distribution within
sprandn(m,n,d) randn(m,n) The random matrix constructed m-by-n (with a density of d) independently distributes non-zero elements that meet the standard normal (Gauss) distribution
sprandn(m,n,d,X) randn(m,n,X) Constructing a random matrix of m-by-n (with a density of d) independently distributes non-zero elements that meet the X distribution. (Distributions extension package required)
sprandbool(m,n,d) randbool(m,n) Construct a random matrix of m-by-n (with a dense density of d), and the chance of a non-zero Bool element is . . . 元素的概率为 *d* ( in randbool . .