Julia, run function multiple times, save results in array
Asked Answered
S

1

7

I am building a microsimulation model in Julia. I have built the structure of my function and it runs great for for 1 "person". I'd like to write the script to run 100000+ people through the model and save the results in one location.

Eventually I'd like to execute this in parallel.

Below I have included a simple working version of the code with dummy probabilities.

using Distributions

# Microsim function
function  MicroSim(start_age, stages)
  stage = 0
  age = start_age

  # Set all trackers to 0
  Death_tracker = 0
  Disease_tracker = 0

  # While loop
  while stage <= stages
    age = age

    ###########################################################
    # Probability of Death
    pD = 0.02

    if age == 100
      pD = 1.0
    else
      pD = pD
    end

    # Coin flip
    dist_pD = Bernoulli(pD)
    Died = rand(dist_pD, 1)

    if Died == [1]
      Death_tracker = 1
      # death tracker loop break
      if Death_tracker == 1
        # println("I died")
        break
      end
    else
      Death_tracker = Death_tracker
    end
    ###########################################################

  # Update age and stage
  age = age + 1
  stage = stage + 1

  end

return age, Death_tracker

end


MicroSim(18,100)
Shillong answered 21/7, 2016 at 22:53 Comment(1)
can't you loop the function many times? for i in 1:100 println(MicroSim(18,100)) endUhlan
B
9

You are looking for the functions map and pmap (for parallelization). I've simplified your function to give a more minimal working example. (in the future, please see this link for guidance on creating such minimal examples in your questions).

map takes a function (that you specify) and applies it to all of the elements in an array. If your function takes multiple arguments (as yours does), then you simply feed map multiple successive arrays. map then returns a new array with the results of all your functions.

function MicroSim(start_age, stages)
    return rand(start_age), rand(stages)
end

Start_Ages = [10, 20, 15]
Stages = [1, 4, 5]

Results = map(MicroSim, Start_Ages, Stages)

If you want to parallelize things, there are just three simple adjustments. 1. use the addprocs() function to add however many additional processes you want. 2. use the @everywhere macro when declaring your function so that your worker processes also have access to it. 3. use the function pmap instead of map:

addprocs(2)

@everywhere begin
    function MicroSim(start_age, stages)
        return rand(start_age), rand(stages)
    end
end

Results = pmap(MicroSim, Start_Ages, Stages)
Batik answered 21/7, 2016 at 23:42 Comment(4)
Thank you for this answer. The map function is applying the correct elements and producing results, but everything is being stored in a vector where each element is a tuple. Is there any easy way to convert this to an array?Shillong
@Shillong Right now, your function is outputting a tuple. If you put brackets around your return value then it will output an array. Then, you can use BigArray = vcat(results...) to turn it into a single array, one row for each run of your simulation.Batik
@MichaelOhlrogge That's perfect. Thank you very much for your help.Shillong
@TasosPapastylianou Potentially. It doesn't hurt to try it out and do some speed tests. Generally, vectorization doesn't do so well performance wise in Julia, but there are always exceptions.Batik

© 2022 - 2024 — McMap. All rights reserved.