TArray push in Turing.jl

Just trying to convert the “Infinite Mixture” tutorial example to work with bivariate (as opposed to univariate) clusters: https://turing.ml/dev/tutorials/6-infinitemixturemodel/

In the tutorial, one has:

    # Locations of the infinitely many clusters.
    μ = tzeros(Float64, 0)

and then applies push! as

# Create a new cluster?
        if z[i] > K
            push!(μ, 0.0)

I now have

   # bivariate case
   μ = tzeros(Float64, (0,2)) 
   ...  
   # Create a new cluster?
   if z[i] > K
      push!(μ, zeros(2)) 

I’m getting the following error:
MethodError: no method matching push!(::Array{Float64,2}, ::Array{Float64,1})
Closest candidates are:
push!(::Any, ::Any, !Matched::Any) at abstractarray.jl:2158
push!(::Any, ::Any, !Matched::Any, !Matched::Any…) at abstractarray.jl:2159
push!(!Matched::Array{Any,1}, ::Any) at array.jl:920

What’s the correct syntax to use here?
Thanks

Can you try something like

mu = TArray{TArray{Float64, 2}, 1}(undef, (0,2))

. . .
if z[i] > k
    push!(mu, tzeros(2))

No idea if this’ll work, can’t quite test it right now.

Doesn’t seem to work. I’m getting the following error message this time:

MethodError: no method matching TArray{TArray{Float64,2},1}(::UndefInitializer, ::Tuple{Int64,Int64})
Closest candidates are:
  TArray{TArray{Float64,2},1}(::Any, !Matched::Integer...) where {T, N} at C:\Users\.julia\packages\Libtask\Q1ugc\src\tarray.jl:36

FWIW, I’m using Turing.jl v0.12.0 and IJulia 1.21.2

Thnks

Try

mu = TArray{TArray{Float64, 1}, 1}(undef, 0)

if z[i] > K
    push!(mu, zeros(2)) 

Still doesn’t work.
So with:

μ = TArray{TArray{Float64, 1}, 1}(undef, 0)
...
if z[i] > K
            push!(μ, zeros(2))

I get error:

MethodError: Cannot `convert` an object of type Array{Float64,1} to an object of type TArray{Float64,1}
Closest candidates are:
  convert(::Type{T}, !Matched::T) where T<:AbstractArray at abstractarray.jl:14
  convert(::Type{T}, !Matched::Factorization) where T<:AbstractArray at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.4\LinearAlgebra\src\factorization.jl:55
  convert(::Type{T}, !Matched::T) where T at essentials.jl:171

If I replace push! with push!(μ, tzeros(2))
then the error message is:

MethodError: Cannot `convert` an object of type Float64 to an object of type TArray{Float64,1}
Closest candidates are:
  convert(::Type{T}, !Matched::T) where T<:AbstractArray at abstractarray.jl:14
  convert(::Type{T}, !Matched::Factorization) where T<:AbstractArray at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.4\LinearAlgebra\src\factorization.jl:55
  convert(::Type{T}, !Matched::T) where T at essentials.jl:171

Mistyped again. As indicated by the errors, this

push!(μ, zeros(2))

should be

push!(μ, tzeros(2))

Actually I tried that already, see the 2nd error message above. Still doesn’t work, mismatched type or something. Anything else to try?

Works for me:

julia> μ = TArray{TArray{Float64, 1}, 1}(undef, 0);

julia> push!(μ, tzeros(2));

Ah yes. This seems to work actually.

So here’s the bivariate version of the model:

@model infiniteGMM(x) = begin 
    
    # Hyper-parameters, i.e. concentration parameter and parameters of H.
    α = 1.0
    μ0 = [0.0, 0.0]
    σ0 = 1.0
    
    # Define random measure, e.g. Dirichlet process.
    rpm = DirichletProcess(α)
    
    # Define the base distribution, i.e. expected value of the Dirichlet process.
    H = MvNormal(μ0, σ0)
    
    # Latent assignment.
    z = tzeros(Int, length(x))
        
    # Locations of the infinitely many clusters.
    μ = TArray{TArray{Float64, 1}, 1}(undef, 0);

    for i in 1:length(x)
        
        # Number of clusters.
        K = maximum(z)
        nk = Vector{Int}(map(k -> sum(z .== k), 1:K))

        # Draw the latent assignment.
        z[i] ~ ChineseRestaurantProcess(rpm, nk)
        
        # Create a new cluster?
        if z[i] > K
            push!(μ, tzeros(2))
            # Draw location of new cluster.
            μ[z[i]] ~ H
        end
                
        # Draw observation.
        x[i] ~ MvNormal(μ[z[i]], 1.0)
    end
end

If I try to sample from it:

model = infiniteGMM(x);
chains = sample(model, MH(), 10);

I get the following error:

MethodError: Cannot `convert` an object of type Array{Float64,1} to an object of type TArray{Float64,1}
Closest candidates are:
  convert(::Type{T}, !Matched::T) where T<:AbstractArray at abstractarray.jl:14
  convert(::Type{T}, !Matched::Factorization) where T<:AbstractArray at 

Any ideas where this is coming from? Looks like again some dimensional/indexing mismatch.
I’m using a sample bivariate mixture as follows:

y1 = rand(MvNormal([1., 3.], 0.5), 250);
y2 = rand(MvNormal([-1., 0.], 0.5), 400);
x = reduce(hcat, [y1, y2])

Thanks

Please open an issue.