API Containers
Страница в процессе перевода. |
#
JuMP.Containers
— Module
Containers
Module defining the containers DenseAxisArray
and SparseAxisArray
that behaves as a regular AbstractArray
but with custom indexes that are not necessarily integers.
#
JuMP.Containers.AutoContainerType
— Type
AutoContainerType
Pass AutoContainerType
to container
to let the container type be chosen based on the type of the indices using default_container
.
#
JuMP.Containers.DenseAxisArray
— Method
DenseAxisArray(data::Array{T, N}, axes...) where {T, N}
Construct a JuMP array with the underlying data specified by the data
array and the given axes. Exactly N
axes must be provided, and their lengths must match size(data)
in the corresponding dimensions.
Example
julia> array = Containers.DenseAxisArray([1 2; 3 4], [:a, :b], 2:3)
2-dimensional DenseAxisArray{Int64,2,...} with index sets:
Dimension 1, [:a, :b]
Dimension 2, 2:3
And data, a 2×2 Matrix{Int64}:
1 2
3 4
julia> array[:b, 3]
4
#
JuMP.Containers.DenseAxisArray
— Method
DenseAxisArray{T}(undef, axes...) where T
Construct an uninitialized DenseAxisArray with element-type T
indexed over the given axes.
Example
julia> array = Containers.DenseAxisArray{Float64}(undef, [:a, :b], 1:2);
julia> fill!(array, 1.0)
2-dimensional DenseAxisArray{Float64,2,...} with index sets:
Dimension 1, [:a, :b]
Dimension 2, 1:2
And data, a 2×2 Matrix{Float64}:
1.0 1.0
1.0 1.0
julia> array[:a, 2] = 5.0
5.0
julia> array[:a, 2]
5.0
julia> array
2-dimensional DenseAxisArray{Float64,2,...} with index sets:
Dimension 1, [:a, :b]
Dimension 2, 1:2
And data, a 2×2 Matrix{Float64}:
1.0 5.0
1.0 1.0
#
JuMP.Containers.DenseAxisArrayKey
— Type
DenseAxisArrayKey
Structure to hold a DenseAxisArray key when it is viewed as key-value collection.
#
JuMP.Containers.NestedIterator
— Type
struct NestedIterator{T}
iterators::T # Tuple of functions
condition::Function
end
Iterators over the tuples that are produced by a nested for loop.
Construct a NestedIterator
using nested
.
Example
julia> iterators = (() -> 1:2, (i,) -> ["A", "B"]);
julia> condition = (i, j) -> isodd(i) || j == "B";
julia> x = Containers.NestedIterator(iterators, condition);
julia> for (i, j) in x
println((i, j))
end
(1, "A")
(1, "B")
(2, "B")
is the same as
julia> for i in iterators[1]()
for j in iterators[2](i)
if condition(i, j)
println((i, j))
end
end
end
(1, "A")
(1, "B")
(2, "B")
#
JuMP.Containers.NoDuplicateDict
— Type
struct NoDuplicateDict{K, V} <: AbstractDict{K, V}
dict::OrderedCollections.OrderedDict{K, V}
end
Same as OrderedCollections.OrderedDict{K, V}
but errors if constructed from an iterator with duplicate keys.
#
JuMP.Containers.SparseAxisArray
— Type
struct SparseAxisArray{T,N,K<:NTuple{N, Any}} <: AbstractArray{T,N}
data::OrderedCollections.OrderedDict{K,T}
end
N
-dimensional array with elements of type T
where only a subset of the entries are defined. The entries with indices idx = (i1, i2, ..., iN)
in keys(data)
has value data[idx]
.
Note that, as opposed to SparseArrays.AbstractSparseArray
, the missing entries are not assumed to be zero(T)
, they are simply not part of the array. This means that the result of map(f, sa::SparseAxisArray)
or f.(sa::SparseAxisArray)
has the same sparsity structure as sa
, even if f(zero(T))
is not zero.
Example
julia> using OrderedCollections: OrderedDict
julia> dict = OrderedDict((:a, 2) => 1.0, (:a, 3) => 2.0, (:b, 3) => 3.0)
OrderedDict{Tuple{Symbol, Int64}, Float64} with 3 entries:
(:a, 2) => 1.0
(:a, 3) => 2.0
(:b, 3) => 3.0
julia> array = Containers.SparseAxisArray(dict)
SparseAxisArray{Float64, 2, Tuple{Symbol, Int64}} with 3 entries:
[a, 2] = 1.0
[a, 3] = 2.0
[b, 3] = 3.0
julia> array[:b, 3]
3.0
#
JuMP.Containers.VectorizedProductIterator
— Type
struct VectorizedProductIterator{T}
prod::Iterators.ProductIterator{T}
end
A wrapper type for Iterators.ProuctIterator
that discards shape information and returns a Vector
.
Construct a VectorizedProductIterator
using vectorized_product
.
#
JuMP.Containers._explicit_oneto
— _Method
_explicit_oneto(error_fn, index_set)
If the index_set
matches the form of 1:N
, then return Base.OneTo(index_set)
.
#
JuMP.Containers._expr_is_splat
— _Method
_expr_is_splat(expr)
Return true
if expr
is a ...
expression (or an esc
'd one).
#
JuMP.Containers._extract_kw_args
— _Method
_extract_kw_args(args)
This function is deprecated. Use |
#
JuMP.Containers._get_arg
— _Method
_get_arg(args::Tuple, index::Tuple)
Return a tuple corresponding to tuple([arg[index] for arg in args]...)
in a type-stable way.
#
JuMP.Containers._parse_ref_sets
— _Method
_parse_ref_sets(expr::Expr)
Helper function for macros to construct container objects.
Takes an Expr
that specifies the container, for example, :(x[i=1:3,[:red,:blue],k=S; i+k <= 6])
, and returns:
-
index_vars
: Names for the index variables, for example,[:i, gensym(), :k]
. These may also be expressions, like:i, j
from a call like:(x[(i, j) in S])
. -
index_sets
: Sets used for indexing, for example,[1:3, [:red,:blue], S]
-
condition
: Expr containing any conditional imposed on indexing, or:()
if none is present
#
JuMP.Containers.add_additional_args
— Method
add_additional_args(
call::Expr,
args::Vector,
kwargs::Dict{Symbol,Any};
kwarg_exclude::Vector{Symbol} = Symbol[],
)
Add the positional arguments args
to the function call expression call
, escaping each argument expression.
This function is able to incorporate additional positional arguments to call
s that already have keyword arguments.
#
JuMP.Containers.build_error_fn
— Method
build_error_fn(macro_name, args, source)
Return a function that can be used in place of Base.error
, but which additionally prints the macro from which it was called.
#
JuMP.Containers.build_name_expr
— Method
build_name_expr(
name::Union{Symbol,Nothing},
index_vars::Vector,
kwargs::Dict{Symbol,Any},
)
Returns an expression for the name of a container element, where name
and index_vars
are the values returned by parse_ref_sets
and kwargs
is the dictionary returned by parse_macro_arguments
.
This assumes that the key in kwargs
used to over-ride the name choice is :base_name
.
Example
julia> Containers.build_name_expr(:x, [:i, :j], Dict{Symbol,Any}())
:(string("x", "[", string($(Expr(:escape, :i))), ",", string($(Expr(:escape, :j))), "]"))
julia> Containers.build_name_expr(nothing, [:i, :j], Dict{Symbol,Any}())
""
julia> Containers.build_name_expr(:y, [:i, :j], Dict{Symbol,Any}(:base_name => "y"))
:(string("y", "[", string($(Expr(:escape, :i))), ",", string($(Expr(:escape, :j))), "]"))
#
JuMP.Containers.build_ref_sets
— Method
build_ref_sets(error_fn::Function, expr)
This function is deprecated. Use parse_ref_sets
instead.
#
JuMP.Containers.container
— Method
container(f::Function, indices[[, ::Type{C} = AutoContainerType], names])
Create a container of type C
with index names names
, indices indices
and values at given indices given by f
.
If the method with names
is not specialized on Type{C}
, it falls back to calling container(f, indices, c)
for backwards compatibility with containers not supporting index names.
Example
julia> Containers.container((i, j) -> i + j, Containers.vectorized_product(Base.OneTo(3), Base.OneTo(3)))
3×3 Matrix{Int64}:
2 3 4
3 4 5
4 5 6
julia> Containers.container((i, j) -> i + j, Containers.vectorized_product(1:3, 1:3))
2-dimensional DenseAxisArray{Int64,2,...} with index sets:
Dimension 1, 1:3
Dimension 2, 1:3
And data, a 3×3 Matrix{Int64}:
2 3 4
3 4 5
4 5 6
julia> Containers.container((i, j) -> i + j, Containers.vectorized_product(2:3, Base.OneTo(3)))
2-dimensional DenseAxisArray{Int64,2,...} with index sets:
Dimension 1, 2:3
Dimension 2, Base.OneTo(3)
And data, a 2×3 Matrix{Int64}:
3 4 5
4 5 6
julia> Containers.container((i, j) -> i + j, Containers.nested(() -> 1:3, i -> i:3, condition = (i, j) -> isodd(i) || isodd(j)))
SparseAxisArray{Int64, 2, Tuple{Int64, Int64}} with 5 entries:
[1, 1] = 2
[1, 2] = 3
[1, 3] = 4
[2, 3] = 5
[3, 3] = 6
#
JuMP.Containers.container_code
— Method
container_code(
index_vars::Vector{Any},
indices::Expr,
code,
requested_container::Union{Symbol,Expr,Dict{Symbol,Any}},
)
Used in macros to construct a call to container
. This should be used in conjunction with parse_ref_sets
.
Arguments
-
index_vars::Vector{Any}
: a vector of names for the indices of the container. These may also be expressions, like:i, j
from a call like:(x[(i, j) in S])
. -
indices::Expr
: an expression that evaluates to an iterator of the indices. -
code
: an expression or literal constant for the value to be stored in the container as a function of the namedindex_vars
. -
requested_container
: passed to the third argument ofcontainer
. For built-in JuMP types, choose one of:Array
,:DenseAxisArray
,:SparseAxisArray
, or:Auto
. For a user-defined container, this expression must evaluate to the correct type. You may also pass thekwargs
dictionary fromparse_macro_arguments
.
In most cases, you should |
Example
julia> macro foo(ref_sets, code)
name, index_vars, indices =
Containers.parse_ref_sets(error, ref_sets)
@assert name !== nothing # Anonymous container not supported
container =
Containers.container_code(index_vars, indices, esc(code), :Auto)
return quote
$(esc(name)) = $container
end
end
@foo (macro with 1 method)
julia> @foo(x[i=1:2, j=["A", "B"]], j^i);
julia> x
2-dimensional DenseAxisArray{String,2,...} with index sets:
Dimension 1, Base.OneTo(2)
Dimension 2, ["A", "B"]
And data, a 2×2 Matrix{String}:
"A" "B"
"AA" "BB"
#
JuMP.Containers.default_container
— Function
default_container(indices)
If indices
is a NestedIterator
, return a SparseAxisArray
. Otherwise, indices
should be a VectorizedProductIterator
and the function returns Array
if all iterators of the product are Base.OneTo
and returns DenseAxisArray
otherwise.
#
JuMP.Containers.nested
— Method
nested(iterators...; condition = (args...) -> true)
Create a NestedIterator
.
Example
julia> iterator = Containers.nested(
() -> 1:2,
(i,) -> ["A", "B"];
condition = (i, j) -> isodd(i) || j == "B",
);
julia> collect(iterator)
3-element Vector{Tuple{Int64, String}}:
(1, "A")
(1, "B")
(2, "B")
#
JuMP.Containers.parse_macro_arguments
— Method
parse_macro_arguments(
error_fn::Function,
args;
valid_kwargs::Union{Nothing,Vector{Symbol}} = nothing,
num_positional_args::Union{Nothing,Int,UnitRange{Int}} = nothing,
)
Returns a Tuple{Vector{Any},Dict{Symbol,Any}}
containing the ordered positional arguments and a dictionary mapping the keyword arguments.
This specially handles the distinction of @foo(key = value)
and @foo(; key = value)
in macros.
An error is thrown if multiple keyword arguments are passed with the same key.
If valid_kwargs
is a Vector{Symbol}
, an error is thrown if a keyword is not in valid_kwargs
.
If num_positional_args
is not nothing, an error is thrown if the number of positional arguments is not in num_positional_args
.
#
JuMP.Containers.parse_ref_sets
— Method
parse_ref_sets(
error_fn::Function,
expr;
invalid_index_variables::Vector{Symbol} = Symbol[],
)
Helper function for macros to construct container objects.
This function is for advanced users implementing JuMP extensions. See |
Arguments
-
error_fn
: a function that takes aString
and throws an error, potentially annotating the input string with extra information such as from which macro it was thrown from. Useerror
if you do not want a modified error message. -
expr
: anExpr
that specifies the container, for example,:(x[i = 1:3, [:red, :blue], k = S; i + k <= 6])
Returns
-
name
: the name of the container, if given, otherwisenothing
-
index_vars
: aVector{Any}
of names for the index variables, for example,[:i, gensym(), :k]
. These may also be expressions, like:i, j
from a call like:(x[(i, j) in S])
. -
indices
: an iterator over the indices, for example,Containers.NestedIterator
Example
See container_code
for a worked example.
#
JuMP.Containers.rowtable
— Method
rowtable([f::Function=identity,] x; [header::Vector{Symbol} = Symbol[]])
Applies the function f
to all elements of the variable container x
, returning the result as a Vector
of NamedTuple
s, where header
is a vector containing the corresponding axis names.
If x
is an N
-dimensional array, there must be N+1
names, so that the last name corresponds to the result of f(x[i])
.
If header
is left empty, then the default header is [:x1, :x2, ..., :xN, :y]
.
A |
Example
julia> model = Model();
julia> @variable(model, x[i=1:2, j=i:2] >= 0, start = i+j);
julia> Containers.rowtable(start_value, x; header = [:i, :j, :start])
3-element Vector{@NamedTuple{i::Int64, j::Int64, start::Float64}}:
(i = 1, j = 1, start = 2.0)
(i = 1, j = 2, start = 3.0)
(i = 2, j = 2, start = 4.0)
julia> Containers.rowtable(x)
3-element Vector{@NamedTuple{x1::Int64, x2::Int64, y::VariableRef}}:
(x1 = 1, x2 = 1, y = x[1,1])
(x1 = 1, x2 = 2, y = x[1,2])
(x1 = 2, x2 = 2, y = x[2,2])
#
JuMP.Containers.vectorized_product
— Method
vectorized_product(iterators...)
Created a VectorizedProductIterator
.
Example
julia> iterator = Containers.vectorized_product(1:2, ["A", "B"]);
julia> collect(iterator)
2×2 Matrix{Tuple{Int64, String}}:
(1, "A") (1, "B")
(2, "A") (2, "B")
#
JuMP.Containers.@container
— Macro
@container([i=..., j=..., ...], expr[, container = :Auto])
Create a container with indices i
, j
, … and values given by expr
that may depend on the value of the indices.
@container(ref[i=..., j=..., ...], expr[, container = :Auto])
Same as above but the container is assigned to the variable of name ref
.
The type of container can be controlled by the container
keyword.
When the index set is explicitly given as |
Example
julia> Containers.@container([i = 1:3, j = 1:3], i + j)
3×3 Matrix{Int64}:
2 3 4
3 4 5
4 5 6
julia> I = 1:3
1:3
julia> Containers.@container(x[i = I, j = I], i + j);
julia> x
2-dimensional DenseAxisArray{Int64,2,...} with index sets:
Dimension 1, 1:3
Dimension 2, 1:3
And data, a 3×3 Matrix{Int64}:
2 3 4
3 4 5
4 5 6
julia> Containers.@container([i = 2:3, j = 1:3], i + j)
2-dimensional DenseAxisArray{Int64,2,...} with index sets:
Dimension 1, 2:3
Dimension 2, Base.OneTo(3)
And data, a 2×3 Matrix{Int64}:
3 4 5
4 5 6
julia> Containers.@container([i = 1:3, j = 1:3; i <= j], i + j)
SparseAxisArray{Int64, 2, Tuple{Int64, Int64}} with 6 entries:
[1, 1] = 2
[1, 2] = 3
[1, 3] = 4
[2, 2] = 4
[2, 3] = 5
[3, 3] = 6