Я работаю над проектом 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]
?