Expressions

With StructuredOptimization.jl you can easily create mathematical expressions. Firstly, Variables must be defined: various Mappings can then be applied following the application of Functions and constraints to create the Terms that define the optimization problem.

Variables

Creating Variables

StructuredOptimization.VariableType
Variable([T::Type,] dims...)

Returns a Variable of dimension dims initialized with an array of all zeros.

Variable(x::AbstractArray)

Returns a Variable of dimension size(x) initialized with x

source
Note

StructuredOptimization.jl supports complex variables. It is possible to create them by specifying the type Variable(Complex{Float64}, 10) or by initializing them with a complex array Variable(randn(10)+im*randn(10)).

Utilities

Base.:~Function
~(x::Variable)

Returns the Array of the variable x

source
Base.sizeFunction

size(x::Variable, [dim...])

Like size(A::AbstractArray, [dims...]) returns the tuple containing the dimensions of the variable x.

source
Base.eltypeFunction

eltype(x::Variable)

Like eltype(x::AbstractArray) returns the type of the elements of x.

source

Summing expressions

Base.:+Function
+(ex1::AbstractExpression, ex2::AbstractExpression)

Add two expressions.

Examples

julia> x,y = Variable(5), Variable(5)
(Variable(Float64, (5,)), Variable(Float64, (5,)))

julia> ex1 = x+y

julia> z = Variable(2)
Variable(Float64, (2,))

julia> ex2 = randn(5,2)*z

Notice that in order for two expressions to be added toghether their associated AbstractOperator must have the same codomain:

julia> operator(ex1)
[I,I]  ℝ^5  ℝ^5 -> ℝ^5

julia> operator(ex2)
▒  ℝ^2 -> ℝ^5

julia> ex3 = ex1 + ex2

It is also possible to use broadcasted addition:

julia> z = Variable(1)
Variable(Float64, (1,))

julia> ex3.+z
source
+(ex::AbstractExpression, b::Union{AbstractArray,Number})

Add a scalar or an Array to an expression:

Example

julia> x = Variable(10)
Variable(Float64, (10,))

julia> ex = x+4

Notice that in order to add an array to ex, b must belong to the codomain of the associated AbstractOperator of ex.

julia> b = randn(10);

julia> size(b), eltype(b)
((10,), Float64)

julia> size(affine(ex),1), codomainType(affine(ex))
((10,), Float64)

julia> ex + b
source

Multiplying expressions

Base.:*Function
*(A::AbstractOperator, ex::AbstractExpression)

Multiply an 'AbstractExpressionby anAbstractOperator`.

Example

julia> A = FiniteDiff(Float64, (10,))
δx  ℝ^10 -> ℝ^9

julia> x = Variable(10);

julia> ex = A*x;

julia> B = DCT(9)
ℱc  ℝ^9 -> ℝ^9

julia> ex2 = B*ex;

julia> affine(ex2)
ℱc*δx  ℝ^10 -> ℝ^9
source
*(A::AbstractMatrix, ex::AbstractExpression)

Multiply an AbstractExpression by an AbstractMatrix.

julia> A = randn(10,5);

julia> x = Variable(5)
Variable(Float64, (5,))

julia> A*x

Other types of multiplications are also possible:

  • left array multiplication
julia> X = Variable(10,5)
Variable(Float64, (10, 5))

julia> X*randn(5,6)
  • scalar multiplication:
julia> π*X
  • elementwise multiplication:
julia> randn(10,5).*X
source
*(A::AbstractExpression, ex::AbstractExpression)

Multiply an AbstractExpression by another AbstractExpression.

Examples

julia> W1 = Variable(10,5)
Variable(Float64, (10, 5))

julia> W2 = Variable(5,15)
Variable(Float64, (5, 15))

julia> ex = W1*σ(W2);

julia> affine(ex)
I*σ  ℝ^(10, 5)  ℝ^(5, 15) -> ℝ^(10, 15)

.*(A::AbstractExpression, ex::AbstractExpression)

Elementwise multiplication between AbstractExpression (i.e. Hadamard product).

source

Mappings

As shown in the Quick tutorial guide it is possible to apply different mappings to the variables using a simple syntax.

Alternatively, as shown in Multiplying expressions, it is possible to define the mappings using AbstractOperators.jl and to apply them to the variable (or expression) through multiplication.

Basic mappings

Base.getindexFunction
getindex(x::AbstractExpression, dims...)

Slices the codomain of ex.

Example

julia> x = Variable(10)
Variable(Float64, (10,))

julia> getindex(x,1:4)

julia> X = Variable(10,4)
Variable(Float64, (10, 4))

julia> X[:,1:3]
source
Base.reshapeFunction
reshape(x::AbstractExpression, dims...)

Reshapes the codomain of the expression.

Example

julia> A,b = randn(10,3), randn(10);

julia> reshape(A*x-b,2,5)
source

DSP mappings

AbstractFFTs.fftFunction
fft(x::AbstractExpression)

Applies the Fourier transform. See documentation for Base.fft and AbstractOperator.DFT.

Example

julia> x = Variable(10)
Variable(Float64, (10,))

julia> ex = fft(x)

julia> operator(ex)
ℱ  ℝ^10 -> ℂ^10
source
AbstractFFTs.ifftFunction
ifft(x::AbstractExpression)

Applies the inverse Fourier transform. See documentation for Base.ifft and AbstractOperator.IDFT.

Example

julia> x = Variable(10)
Variable(Float64, (10,))

julia> ex = ifft(x)

julia> operator(ex)
ℱ⁻¹  ℝ^10 -> ℂ^10
source
AbstractFFTs.rfftFunction
rfft(x::AbstractExpression, [, dims] )

Applies the Fourier transform exploiting the conjugate symmetry. See documentation for Base.rfft and AbstractOperator.RDFT.

Example

julia> x = Variable(10)
Variable(Float64, (10,))

julia> ex = rfft(x)

julia> operator(ex)
ℱ  ℝ^10 -> ℂ^6
source
AbstractFFTs.irfftFunction
irfft(x::AbstractExpression, d, [, dims] )

Applies the inverse Fourier transform exploiting the conjugate symmetry.

d must indicate the length of the real codomain.

See documentation for Base.irfft and AbstractOperator.IRDFT.

Example

julia> x = Variable(Complex{Float64}, 10)
Variable(Float64, (10,))

julia> ex = irfft(x,19)

julia> operator(ex)
ℱ⁻¹  ℂ^10 -> ℝ^19
source
FFTW.dctFunction
dct(x::AbstractExpression)

Applies the discrete cosine transform. See documentation for Base.dct and AbstractOperator.DCT.

Example

julia> x = Variable(10)
Variable(Float64, (10,))

julia> ex = dct(x)

julia> operator(ex)
ℱc  ℝ^10 -> ℝ^10
source
FFTW.idctFunction
idct(x::AbstractExpression)

Applies the inverse discrete cosine transform. See documentation for Base.idct and AbstractOperator.IDCT.

Example

julia> x = Variable(10)
Variable(Float64, (10,))

julia> ex = idct(x)

julia> operator(ex)
ℱc⁻¹  ℝ^10 -> ℝ^10
source
DSP.convFunction
conv(x::AbstractExpression, h::AbstractVector)

Perform discrete convolution with h. See documentation for Base.conv and AbstractOperator.Conv.

Example

julia> x = Variable(10)
Variable(Float64, (10,))

julia> ex = conv(x, randn(5))

julia> operator(ex)
★  ℝ^10 -> ℝ^14
source
DSP.xcorrFunction
xcorr(x::AbstractExpression, h::AbstractVector)

Performs the cross correlation of the codomain of ex with h. See documentation for Base.xcorr and AbstractOperator.Xcorr.

Example

julia> x = Variable(10)
Variable(Float64, (10,))

julia> ex = xcorr(x, randn(5))

julia> operator(ex)
◎  ℝ^10 -> ℝ^19
source
DSP.filtFunction
filt(x::AbstractExpression, b::AbstractVector, [a::AbstractVector])

Filter with the finite impulse response (FIR) b. Alternatively infinite impulse responses filters (IIR) can be used as well by specifying the coefficients a.

See documentation for Base.filt and AbstractOperator.Filt.

Example

julia> x = Variable(10)
Variable(Float64, (10,))

julia> ex = filt(x, [1.;0.;0.],[1.;0.;1.])

julia> operator(ex)
IIR  ℝ^10 -> ℝ^10

julia> ex = filt(x, [1.;0.;0.])

julia> operator(ex)
FIR  ℝ^10 -> ℝ^10
source
StructuredOptimization.mimofiltFunction
mimofilt(X::AbstractExpression, B::Vector{AbstractVector}, [A::Vector{AbstractVector}])

Multiple-input multiple-output filter: like filt but allows for multipule inputs.

\[\mathbf{y}_i = \sum_{j = 1}^{M} \mathbf{h}_{i,j} * \mathbf{x}_j\]

where $\mathbf{y}_i$ and $\mathbf{x}_j$ are the $i$-th and $j$-th columns of the output Y and input X matrices respectively.

The filters $\mathbf{h}_{i,j}$ can be represented either by providing coefficients B and A (IIR) or B alone (FIR). These coefficients must be given in a Vector of Vectors.

For example for a 3 by 2 MIMO system (i.e. size(X,2) == 3 inputs and size(Y,2) == 2 outputs) B must be:

B = [b11, b12, b13, b21, b22, b23]

where bij are vector containing the filter coeffients of h_{i,j}.

See documentation of AbstractOperator.MIMOFilt.

source
StructuredOptimization.zeropadFunction
zeropad(x::AbstractExpression, zp::Tuple)

Performs zeropadding:

\[zp(\mathbf{x}) = [\mathbf{x}, 0, \dots, 0 ]^T\]

where zp is a tuple containing the number of nonzero elements that are added in each dimension.

See documentation of AbstractOperator.ZeroPad.

source

Finite differences mappings

StructuredOptimization.finitediffFunction
finitediff(X::AbstractExpression, dir = 1)

Performs the discretized gradient over the specified direction dir obtained using forward finite differences.

Example

julia> X = Variable(10,10)
Variable(Float64, (10,10))

julia> ex = finitediff(X)

julia> operator(ex)
δx  ℝ^(10, 10) -> ℝ^(9, 10)

julia> ex = finitediff(X,2)

julia> operator(ex)
δy  ℝ^(10, 10) -> ℝ^(10, 9)
source
StructuredOptimization.variationFunction
variation(X::AbstractExpression)

Returns the variation of X using forward finite differences. Specifically if X is in ℝ^(n, m) the codomain of variation(X) will consist of ℝ^(n*m,2), having in the $i$-th column the vectorized gradient over the $i$-th direction.

See documentation of AbstractOperator.Variation.

Example

julia> X = Variable(4,5,6)
Variable(Float64, (4,5,6))

julia> ex = variation(X)

julia> operator(ex)
Ʋ  ℝ^(4, 5, 6) -> ℝ^(120, 3)
source

Nonlinear mappings

Base.sinFunction
sin(x::AbstractExpression)

Sine function:

\[\sin( \mathbf{x} )\]

See documentation of AbstractOperator.Sin.

source
Base.cosFunction
cos(x::AbstractExpression)

Cosine function:

\[\cos( \mathbf{x} )\]

See documentation of AbstractOperator.Cos.

source
Base.atanFunction
atan(x::AbstractExpression)

Inverse tangent function:

\[\tan^{-1}( \mathbf{x} )\]

See documentation of AbstractOperator.Atan.

source
Base.tanhFunction
tanh(x::AbstractExpression)

Hyperbolic tangent function:

\[\tanh ( \mathbf{x} )\]

See documentation of AbstractOperator.Tanh.

source
Base.expFunction
exp(x::AbstractExpression)

Exponential function:

\[e^{ \mathbf{x} }\]

See documentation of AbstractOperator.Exp.

source
StructuredOptimization.powFunction
pow(x::AbstractExpression, n)

Elementwise n-th power of x:

\[x_i^{n} \ \forall \ i = 0,1, \dots\]

See documentation of AbstractOperator.Pow.

source
StructuredOptimization.sigmoidFunction
sigmoid(x::AbstractExpression, γ = 1.0)

σ(x::AbstractExpression, γ = 1.0)

Sigmoid function:

\[\sigma(\mathbf{x}) = \frac{1}{1+e^{-\gamma \mathbf{x} } }\]

See documentation of AbstractOperator.Sigmoid.

source

Utilities

It is possible to access the variables, mappings and displacement of an expression. Notice that these commands work also for the Terms described in Functions and constraints.

StructuredOptimization.variablesFunction
variables(ex::Expression)

Returns a tuple containing the Variables of expression ex.

Example

julia> x,y = Variable(2),Variable(2);

julia> ex = x+y;

julia> variables(ex)
(Variable(Float64, (2,)), Variable(Float64, (2,)))
source
StructuredOptimization.operatorFunction
operator(ex::Expression)

Returns the AbstractOperator of expression ex.

Example

julia> x = Variable(3)
Variable(Float64, (3,))

julia> ex = fft(x);

julia> operator(ex)
ℱ  ℝ^3 -> ℂ^3
source
AbstractOperators.displacementFunction
displacement(ex::Expression)

Returns the displacement of expression ex.

Example

julia> x = Variable(3)
Variable(Float64, (3,))

julia> ex = fft(x)+[1.+im*2.;0.;3.+im*4];

julia> displacement(ex)
3-element Array{Complex{Float64},1}:
1.0+2.0im
0.0+0.0im
3.0+4.0im
source