Search code examples
juliajulia-jumpijulia-notebookjulia-studio

Is there any function such as repmat for struct in julia?


would you please help me. I want to produce a population of struct in Julia.In matalab,we can use repmat for a structure. but in Julia it is impossible. is there any function like repmat in Julia?

for example:

npop=20;
struct individual
    position
    cost
end

individual1=individual([],[])

repmat(individual1,npop,1)
repeat(individual1,npop,1)

repmat(individual1,npop,1)
ERROR: MethodError: no method matching repmat(::individual, ::Int64, ::Int64)
Closest candidates are:
  repmat(::Union{AbstractArray{T,1}, AbstractArray{T,2}} where T, ::Int64, ::Int64) at abstractarray
math.jl:311
  repmat(::Union{AbstractArray{T,1}, AbstractArray{T,2}} where T, ::Integer, ::Integer) at abstracta
rraymath.jl:334
  repmat(::AbstractArray{T,1} where T, ::Int64) at abstractarraymath.jl:325
  ...
Stacktrace:
 [1] macro expansion at C:\Users\admin\AppData\Local\JuliaPro-0.6.4.1\pkgs-0.6.4.1\v0.6\Atom\src\rep
l.jl:118 [inlined]
 [2] anonymous at .\<missing>:?

julia>

julia> repmat(individual1,npop,1)
ERROR: MethodError: no method matching repmat(::individual, ::Int64, ::Int64)
Closest candidates are:
  repmat(::Union{AbstractArray{T,1}, AbstractArray{T,2}} where T, ::Int64, ::Int64) at abstractarray
math.jl:311
  repmat(::Union{AbstractArray{T,1}, AbstractArray{T,2}} where T, ::Integer, ::Integer) at abstracta
rraymath.jl:334
  repmat(::AbstractArray{T,1} where T, ::Int64) at abstractarraymath.jl:325
  ...
Stacktrace:
 [1] macro expansion at C:\Users\admin\AppData\Local\JuliaPro-0.6.4.1\pkgs-0.6.4.1\v0.6\Atom\src\rep
l.jl:118 [inlined]
 [2] anonymous at .\<missing>:?

if loop is used it is possible

pop=individual([],[])
for i=2:npop

    pop=[pop;individual1]

end

and

julia> pop
20-element Array{individual,1}:
 individual(Any[], Any[])
 individual(Any[], Any[])
 individual(Any[], Any[])
 individual(Any[], Any[])
 individual(Any[], Any[])
 individual(Any[], Any[])
 individual(Any[], Any[])
 individual(Any[], Any[])
 individual(Any[], Any[])
 individual(Any[], Any[])
 individual(Any[], Any[])
 individual(Any[], Any[])
 individual(Any[], Any[])
 individual(Any[], Any[])
 individual(Any[], Any[])
 individual(Any[], Any[])
 individual(Any[], Any[])
 individual(Any[], Any[])
 individual(Any[], Any[])
 individual(Any[], Any[])

but I couldn't find a function like repmat in Julia.


Solution

  • If I understand what you want to achieve correctly (assuming you want to do a kind of ABM) this is the way to do it:

    [individual([],[]) for i in 1:npop]
    

    In this way every individual will be allocated separately (and this is probably what you want).

    As a side note it would be better to add types to position and cost for performance reasons. Here is an example assuming that position will be a vector of two element tuples containing a position and cost is a vector of floats:

    struct individual
        position::Vector{Tuple{Float64,Float64}}
        cost::Vector{Float64}
    end
    

    And then you should write:

    [individual(Tuple{Float64,Float64}[],Float64[]) for i in 1:npop]
    

    EDIT

    Note that struct in Julia is not mutable. This means that you cannot rebind the values that position and cost point to. Therefore you have two options.

    Option 1. Define a struct as mutable like this:

    mutable struct individual
        position
        cost
    end
    

    and then the code you have written will work.

    Option 2 Update without rebinding

    update a vector in a struct that is not mutable without rebinding it. E.g. (using your original definitions)

    pop = [individual([],[]) for i in 1:npop]
    for i=1:npop
        append!(pop[i].position, rand(0:1,10))
    end
    

    or simply initialize it as needed:

    pop = [individual(rand(0:1,10),[]) for i in 1:npop]
    

    As an additional comment please note that in Julia you generally do not need to make an adjoint as you did in (rand(0:1,10))'. Operating on vectors typically good enough. And in Option 2 (normal struct you would not be able to append 2-dimensional object to [] which is 1-dimensional).