May 14, 2021 Julia
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.
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). |
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
|
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 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
The common syntax for index n-dimensional array A is:
X = A[I_1, I_2, ..., I_n]
Where I_k can be:
:
a:b
,
a:b:c
format
Range
[]
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
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:
:
a:b
,
a:b:c
format
Range
[]
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
Arrays support the following operators. Element-by-element operations should use binary operators with a point-by-point (element-by-element) version.
-
,
+
,
!
+
-
*
.*
/
./
\
.\
^
.^
div
mod
.==
,
.!=
,
.<
,
.<=
,
.>
,
.>=
~
&
,
|
,
$
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
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.
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.308912 … 0.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.74485 … 0.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
A sparse matrix is a matrix whose elements are mostly 0.
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).
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
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.
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 . .
|