Юлия: Создание AbstractArray с ограничениями на значения - PullRequest
1 голос
/ 15 марта 2020

Я работаю над проектом Julia, для которого требуются матрицы, удовлетворяющие ограничению trace-one. Чтобы не проверять, являются ли матрицы trace-one на входах и выходах многочисленных функций, я хотел бы создать новую структуру данных, которая неявно содержит это ограничение.

В моем рабочем примере я определил структуру TraceOne, которая выдает ошибку, если трасса не равна единице.

struct TraceOne
    M :: Matrix{Complex{Float64}}
    TraceOne(M) = (tr(M) == 1) ? new(M) : throw(DomainError(M, "Matrix M is not trace-one."))
end

A = TraceOne([0.1 0.5;0.3 0.9])

Однако я хотел бы избежать доступа матрица trace-one с ключом A.M возвращает [0.1 0.5;0.3 0.9].

В качестве альтернативы я попытался создать struct, который является подтипом AbstractMatrix, но не могу получить значения AbstractMatrix для правильной инициализации.

struct TraceOne2 <: AbstractMatrix{Complex{Float64}}
    M :: Matrix{Complex{Float64}}
    Base.size(T::TraceOne2) = size(T.M)
    Base.getindex(T::TraceOne2, I::Vararg{Int,2}) = getindex(T.M, size(T.M)...)
    Base.setindex!(T::TraceOne2, v, I::Vararg{Int,2}) = (T.M[I] = v)
    TraceOne2(M) = (tr(M) == 1) ? new(M) : throw(DomainError(M, "Matrix M is not trace-one."))
end

B = TraceOne2([0.1 0.5;0.3 0.9])

Когда я запускаю этот код, я обнаруживаю, что B равно [0.9 0.9;0.9 0.9]. Все элементы B инициализируются значением (2,2), индексом входного массива.

Как изменить struct TraceOne2 ... end так, чтобы полученная матрица B была инициализирована как [0.1 0.5;0.3 0.9]?

1 Ответ

0 голосов
/ 15 марта 2020

Измените эту функцию с:

Base.getindex(T::TraceOne2, I::Vararg{Int,2}) = getindex(T.M, size(T.M)...)
Base.setindex!(T::TraceOne2, v, I::Vararg{Int,2}) = (T.M[I] = v)

на:

Base.getindex(T::TraceOne2, I::Vararg{Int,2}) = getindex(T.M, I...)
Base.setindex!(T::TraceOne2, v, I::Vararg{Int,2}) = (T.M[I...] = v)
...