Справка по API контейнеров
#
JuMP.Containers
— Module
Containers
Модуль, в котором определены контейнеры DenseAxisArray
и SparseAxisArray
, подобные обычным массивам AbstractArray
, но с пользовательскими индексами, которые не обязательно являются целыми числами.
#
JuMP.Containers.AutoContainerType
— Type
AutoContainerType
Передайте AutoContainerType
в container
, чтобы тип контейнера выбирался на основе типа индексов с использованием default_container
.
#
JuMP.Containers.DenseAxisArray
— Method
DenseAxisArray(data::Array{T, N}, axes...) where {T, N}
Создает массив JuMP с базовыми данными, указанными в массиве data
, и заданными осями. Необходимо передать ровно N
осей, а их длины должны соответствовать size(data)
в соответствующих измерениях.
Пример
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
Создает неинициализированный массив DenseAxisArray с типом элементов T
, индексируемый по заданным осям.
Пример
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
Структура для хранения ключа DenseAxisArray, когда он рассматривается как коллекция ключей и значений.
#
JuMP.Containers.NestedIterator
— Type
struct NestedIterator{T}
iterators::T # Tuple of functions
condition::Function
end
Итераторы по кортежам, создаваемым вложенным циклом for.
Итератор NestedIterator
создается с помощью nested
.
Пример
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")
равносильно
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
Действует аналогично OrderedCollections.OrderedDict{K, V}
, но выдает ошибку при создании на основе итератора с повторяющимися ключами.
#
JuMP.Containers.SparseAxisArray
— Type
struct SparseAxisArray{T,N,K<:NTuple{N, Any}} <: AbstractArray{T,N}
data::OrderedCollections.OrderedDict{K,T}
end
N
-мерный массив с элементами типа T
, в котором определено лишь подмножество элементов. Элементы с индексами idx = (i1, i2, ..., iN)
в keys(data)
имеют значение data[idx]
.
Обратите внимание, что, в отличие от SparseArrays.AbstractSparseArray
, отсутствующие элементы не считаются zero(T)
; они просто не входят в массив. Это означает, что результат вызова map(f, sa::SparseAxisArray)
или f.(sa::SparseAxisArray)
имеет ту же структуру разреженности, что и sa
, даже если f(zero(T))
не равно нулю.
Пример
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
Тип-оболочка для Iterators.ProuctIterator
, который игнорирует информацию о форме и возвращает Vector
.
Итератор VectorizedProductIterator
создается с помощью vectorized_product
.
#
JuMP.Containers._explicit_oneto
— _Method
_explicit_oneto(error_fn, index_set)
Если index_set
соответствует форме 1:N
, возвращается Base.OneTo(index_set)
.
#
JuMP.Containers._expr_is_splat
— _Method
_expr_is_splat(expr)
Возвращает значение true
, если expr
— это выражение ...
(или esc
).
#
JuMP.Containers._extract_kw_args
— _Method
_extract_kw_args(args)
Эта функция является нерекомендуемой. Используйте вместо нее |
#
JuMP.Containers._get_arg
— _Method
_get_arg(args::Tuple, index::Tuple)
Возвращает кортеж, который соответствует tuple([arg[index] for arg in args]...)
, но стабилен по типу.
#
JuMP.Containers._parse_ref_sets
— _Method
_parse_ref_sets(expr::Expr)
Вспомогательная функция для макросов, позволяющая создавать объекты-контейнеры.
Принимает выражение Expr
, которое определяет контейнер, например :(x[i=1:3,[:red,:blue],k=S; i+k <= 6])
, и возвращает следующие значения:
-
index_vars
: имена переменных индексов, например[:i, gensym(), :k]
.
Это также могут быть выражения, например :i, j
из такого вызова, как :(x[(i, j) in S])
.
-
index_sets
: множества, используемые для индексирования, например[1:3, [:red,:blue], S]
. -
condition
: выражение, содержащее все условия, налагаемые на индексирование, или:()
,
если таковых нет.
#
JuMP.Containers.add_additional_args
— Method
add_additional_args(
call::Expr,
args::Vector,
kwargs::Dict{Symbol,Any};
kwarg_exclude::Vector{Symbol} = Symbol[],
)
Добавляет позиционные аргументы args
в выражение вызова функции call
, экранируя каждое выражение аргумента.
Эта функция может включать дополнительные позиционные аргументы для вызовов call
, которые уже содержат именованные аргументы.
#
JuMP.Containers.build_error_fn
— Method
build_error_fn(macro_name, args, source)
Возвращает функцию, которую можно использовать вместо Base.error
, но которая дополнительно выводит макрос, из которого она была вызвана.
#
JuMP.Containers.build_name_expr
— Method
build_name_expr(
name::Union{Symbol,Nothing},
index_vars::Vector,
kwargs::Dict{Symbol,Any},
)
Возвращает выражение для имени элемента контейнера, где name
и index_vars
— значения, возвращаемые parse_ref_sets
, а kwargs
— словарь, возвращаемый parse_macro_arguments
.
Предполагается, что ключ в kwargs
, используемый для переопределения выбранного имени, — это :base_name
.
Пример
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)
Эта функция является нерекомендуемой. Используйте вместо нее parse_ref_sets
.
#
JuMP.Containers.container
— Method
container(f::Function, indices[[, ::Type{C} = AutoContainerType], names])
Создает контейнер типа C
с именами индексов names
, индексами indices
и значениями по индексам, определяемыми функцией f
.
Если метод с names
не специализирован для Type{C}
, по умолчанию вызывается container(f, indices, c)
для обратной совместимости с контейнерами, не поддерживающими имена индексов.
Пример
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}},
)
Используется в макросах для построения вызова container
. Следует использовать в сочетании с parse_ref_sets
.
Аргументы
-
index_vars::Vector{Any}
: вектор имен индексов контейнера. Это также могут быть выражения, например:i, j
из такого вызова, как:(x[(i, j) in S])
. -
indices::Expr
: выражение, результатом вычисления которого является итератор индексов. -
code
: выражение или литеральная константа для значения, которое будет сохранено в контейнере как функция именованногоindex_vars
. -
requested_container
: передается в третьем аргументеcontainer
. Для встроенных типов JuMP выберите:Array
,:DenseAxisArray
,:SparseAxisArray
или:Auto
. Для пользовательского контейнера результат вычисления этого выражения должен иметь правильный тип. Можно также передать словарьkwargs
изparse_macro_arguments
.
В большинстве случаев перед передачей кода в |
Пример
julia> macro foo(ref_sets, code)
name, index_vars, indices =
Containers.parse_ref_sets(error, ref_sets)
@assert name !== nothing # Анонимный контейнер не поддерживается
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)
Если indices
— это объект NestedIterator
, возвращает SparseAxisArray
. В противном случае indices
должно быть объектом VectorizedProductIterator
, и эта функция возвращает Array
, если все итераторы произведения равны Base.OneTo
, или DenseAxisArray
в противном случае.
#
JuMP.Containers.nested
— Method
nested(iterators...; condition = (args...) -> true)
Создает объект NestedIterator
.
Пример
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,
)
Возвращает кортеж Tuple{Vector{Any},Dict{Symbol,Any}}
, содержащий упорядоченные позиционные аргументы и словарь, в котором сопоставляются именованные аргументы.
В частности, служит для различения @foo(key = value)
и @foo(; key = value)
в макросах.
При передаче нескольких именованных аргументов с одинаковым ключом выдается ошибка.
Если valid_kwargs
— это объект Vector{Symbol}
, при отсутствии именованного аргумента в valid_kwargs
выдается ошибка.
Если значение num_positional_args
отлично от nothing, при отсутствии числа позиционных аргументов в num_positional_args
выдается ошибка.
#
JuMP.Containers.parse_ref_sets
— Method
parse_ref_sets(
error_fn::Function,
expr;
invalid_index_variables::Vector{Symbol} = Symbol[],
)
Вспомогательная функция для макросов, позволяющая создавать объекты-контейнеры.
Эта функция предназначена для опытных пользователей, реализующих расширения JuMP. Дополнительные сведения см. в описании метода |
Аргументы
-
error_fn
: функция, которая принимаетString
и выдает ошибку; входная строка может быть аннотирована дополнительной информацией, например именем макроса, из которого была выдана ошибка. Чтобы не изменять сообщение об ошибке, используйтеerror
. -
expr
: выражениеExpr
, которое определяет контейнер, например:(x[i = 1:3, [:red, :blue], k = S; i + k <= 6])
.
Возвращаемые значения
-
name
: имя контейнера, если оно задано; в противном случаеnothing
. -
index_vars
: векторVector{Any}
имен переменных индексов, например
[:i, gensym(), :k]
. Это также могут быть выражения, например :i, j
из такого вызова, как :(x[(i, j) in S])
.
-
indices
: итератор по индексам, например
Пример
Рабочий пример см. в описании метода container_code
.
#
JuMP.Containers.rowtable
— Method
rowtable([f::Function=identity,] x; [header::Vector{Symbol} = Symbol[]])
Применяет функцию f
ко всем элементам контейнера переменных x
, возвращая результат в виде вектора Vector
кортежей NamedTuple
, где header
— это вектор с соответствующими именами осей.
Если x
— это N
-мерный массив, то имен должно быть N+1
, чтобы последнее имя соответствовало результату f(x[i])
.
Если аргумент header
пустой, то заголовок по умолчанию будет [:x1, :x2, ..., :xN, :y]
.
Вектор |
Пример
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...)
Создает объект VectorizedProductIterator
.
Пример
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])
Создает контейнер с индексами i
, j
, … и значениями, задаваемыми выражением expr
, которые могут зависеть от значения индексов.
@container(ref[i=..., j=..., ...], expr[, container = :Auto])
То же, что и выше, но контейнер присваивается переменной с именем ref
.
Типом контейнера можно управлять с помощью именованного аргумента container
.
Когда множество индексов явно задано как |
Пример
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