You might be right. I previously coded a simple simulation similar to what 
you described. In this  simulation,  individuals were stored in a vector 
and their properties were represented as integers (e.g. recovered: 3, 
infected: 1, not infected: 0 etc.). I used an adjacency matrix to represent 
the social network through which the infection spread probabilistically 
between connected individuals.  This approach works fine as long as the 
properties are mutually exclusive. My goal was to explore more flexible 
data structures for scaling up the simulation to something more complex. 
It's certainly possible a better approach exists. Without many agent based 
models available in Julia, its hard for me to know what the best approach 
might be. 

On Saturday, June 4, 2016 at 8:16:27 PM UTC-4, David P. Sanders wrote:
>
>
>
> El sábado, 4 de junio de 2016, 18:18:00 (UTC-4), Christopher Fisher 
> escribió:
>>
>> Ok. I didn't anticipate this would be a drawn out process.  I just Ford's 
>> suggestion fixed the issue of changing values but recreated the problem of 
>> accessing an individual's information like so:  population[2] . 
>> population[:,2] did not work either. I tried other changes to the syntax 
>> but to no avail. It fails at the last line.  Any ideas would be 
>> appreciated. 
>>
>> type Person
>>     infected::Bool
>>     vaccinated::Bool
>>     dead::Bool
>>     history::Vector{Int}
>> end
>>
>> type Population <: AbstractArray
>>     individuals::Vector{Person}
>>     
>> end
>>
>>
>> Population() = Population(Person[])
>> Base.push!(p::Population, x::Person) = push!(p.individuals, x)
>>
>>
>> function Base.getindex(pop::Population, field::Symbol)
>>     [getfield(x, field) for x in pop.individuals]
>> end
>>
>> setindex!(p::Population, value, field::Symbol, index...) = 
>> p.individuals[index...].(field) = value
>> getindex(p::Population, field::Symbol, index...) = 
>> p.individuals[index...].(field)
>>
>> Base.show(io::IO, p::Person) = print(io, "Person(infected=", p.infected, 
>> ", vaccinated=", p.vaccinated, ", dead=", p.dead, ", history=", p.history)
>>
>>
>> population = Population()
>> push!(population, Person(true, false, true, [3,4,5]))
>> push!(population, Person(false, true, false, Int64[3,4,5]))
>>
>> #Show that it works
>> population[:infected]
>> population[:infected,1]
>> population[2]
>>
>
> The syntax `population[x]` calls  `getindex(population, x)`.
> You are using two different *types* of object x here: integers and symbols.
> If you really want to do this, you would thus need to define both
>
> getindex(p::Population, n::Integer)
>
> to return the nth individual,
>
> and
>
> getindex(p::Population, s::Symbol)
>
> to return the list of those with status s.
>
> However, this does not seem like a very good idea to me.
>
> What it sounds like you want to do is something like "find the first 
> healthy individual and infect it".
> For this, you are better off writing a function called something like 
> infect!(p::Population)
> which will choose an individual to infect. 
>
> If you are planning to make this into an individual-based simulator, then 
> you probably want to go back
> to just thinking of a vector of individuals, and maintain separately a 
> list of those which are currently infected for example.
> Even though this will be extra book-keeping when an individual becomes 
> infected or stops being infected, it will almost certainly
> be much faster. 
>
> I suggest you try fleshing out your model a bit just thinking of functions 
> that operate on the population as I have suggested.
>
>  
>
>>
>> LoadError: MethodError: `size` has no method matching size(::Population)
>> Closest candidates are:
>>   size(::Any, !Matched::Integer, !Matched::Integer, !Matched::Integer...)
>> while loading In[1], in expression starting on line 36
>>
>>  in getindex at abstractarray.jl:488
>>
>>
>>
>> On Saturday, June 4, 2016 at 3:11:18 PM UTC-4, Ford O. wrote:
>>>
>>> I would like to discourage you from passing symbols as an array index 
>>> but I guess you gonna do it anyway...
>>>
>>>
>>> So if you really want it, here it is:
>>> setindex!(p::Population, value, field::Symbol, index...) = p.individuals
>>> [index...].(field) = value
>>> getindex(p::Population, field::Symbol, index...) = p.individuals[index
>>> ...].(field)
>>>
>>> Usage
>>> population[:infected, 1]
>>> population[:infected, 1] = false
>>>
>>>
>>>
>>>
>>> On Saturday, June 4, 2016 at 2:19:02 PM UTC+2, Christopher Fisher wrote:
>>>>
>>>> I was wondering if someone would be willing to help me with creating 
>>>> user-defined types. I've been using Julia for about two years now but I am 
>>>> new to the idea of creating custom types. I'm trying to create a 
>>>> population 
>>>> of agents/individuals in a simple epidemiological simulation. I would like 
>>>> the population of individuals to be structured as a  2 dimensional array 
>>>> with rows as individuals and columns as properties. This would be somewhat 
>>>> similar to a DataFrame, but potentially more flexible. I want to be able 
>>>> to 
>>>> index an individual like so: population[1]. This woud list all of the 
>>>> information for individual 1.  I would also like to be able to look at an 
>>>> attribute across individuals: population.infected or 
>>>> population[:infected]. 
>>>> At the same time, I would like to have to flexibility of using an array to 
>>>> keep track of individuals: typeof(population.history[1]) is 
>>>> Array{Int64,1}. 
>>>> Based on existing documentation and examples, I have only been able to 
>>>> create individuals but cannot figure out how to create a population as 
>>>> described above:
>>>>
>>>> type Person
>>>>     infected::Int64
>>>>     vaccinated::Int64
>>>>     dead::Int64
>>>>    history::Array{Int64,1}
>>>> end
>>>>
>>>> Any help would be greatly appreciated. 
>>>>
>>>

Reply via email to