0

I have two populations Pop1 of N1 agents and Pop2 of N2 agents. SIR Infection dynamics is taking place within Pop1 and Pop2. Now at each time step, a randomly chosen agent is removed from Pop1 and added to Pop2 and vice versa. Removed agent could be in S or I or R state and it preserves its state when added to another Pop. The code is bit lengthy so I i pasted it in pastebin http://pastebin.com/PdmJTUhs.

In my code 'oAgent' is the randomly chosen agent which is being removed from Pop1 or Pop2. Now the state (S=0 or I=1 or R=2) of oAgent is returned by class method set_state(self, oAgent)

def set_state(self, oAgent):
    if SW_SIR.oAgent in self.sAgent:
        return (0)
    if SW_SIR.oAgent in self.iAgent:
        return (1)
    if SW_SIR.oAgent in self.rAgent:
        return (2)

In my code class Pop1_SW and Pop2_SW are class objects for Pop1 and Pop2 respectively. The state of oAgent of Pop1 is the state of the agent which is being added in Pop2, and vice versa. Now Pop1_SW should get state2(which is state of oAgent of Pop1) as an input parameter, and Pop2_SW should get state1(which is state of oAgent of Pop2).

So my question is how can I assign properly the state for the removed and added agents ? Problem is where inside the class oAgent should be defined and how outside the class its state should be the input for another class object ?

My code runs fine for a SIR dynamics for a single Population. I have added three methods set_state(), removingAgents() and addingAgents for two Populations, which are the cause of error.

6
  • 2
    Your question would get more attention of you include a minimal example depicting where you're having problems Commented Aug 30, 2014 at 11:03
  • 1
    You'll need to explain in much more detail exactly what is wrong with your code: What happens, what is expected to happen, what behaviour you want that you don't currently have. Commented Aug 30, 2014 at 11:04
  • To kick things off, the indentation is wrong in your pastebin paste. You have a required argument m to your class constructor that you do not use - and your random choice of oAgent should be within the range of whatever length is of your populations. Commented Aug 30, 2014 at 11:15
  • @BurhanKhalid I totally agree with you oAgent=random.choice(len(sAgent)+len(iAgent)+len(rAgent)). But could you suggest where in the class I should define it. I have defined it as a class variable. I can fix argument m and indentation but still my problem is not resolved Commented Aug 30, 2014 at 11:29
  • You could define oAgent as a @property of your class: @property def oAgent(self): return ... Commented Aug 30, 2014 at 11:46

2 Answers 2

1
  1. set_state is a really bad name, it does'nt set anything, get_state better...
  2. in all your return parameter the () have no purpose, for a python programmer it's even worst: at first glance it's seems you will return a tuple but it's not.

I think you should probably do a dedicate function "pick an agent" who choose and remove an agent and return you directly the index and the state.

For exemple you add this method:

def pick_an_agent(self):
    """Randomly choose an agent, remove it from population and return it
    with it's state."""

    agent_id = random.choice(self.sAgent + self.iAgent + self.rAgent)  # Choose directly an existing agent, doesn't care about population size and id range.
    state = self.get_state(agent_id)
    self.removeAgent(agent_id)
    return (agent_id, state)

This function return directly the agent number and the state. So you do

agent_id, state = Pop1.pick_an_agent()
Pop2.addingAgent(agent_id, state)

The other problem you will have is the fact you use an integer as id for your agent generated using range. So in you first population N=20 you have agent with id 0 to 19, and in you second population N=10 you have agent with id 0 to 9. If you move an agent from one population to the other you have id collision !

So you need to create your agent with unique id. For this you can use a counter and get N element from it (replace the agents = range(N) in your init function)

So you add:

...
import itertools
...

class SW_SIR:
    agent_id_generator = itertools.count()  # Create a counter starting at 0. It's a class attribute, so all SW_SIR will use the same

    def __init__(self, beta, gamma, S, I, m):
        ...
        agents = list(itertools.islice(self.agent_id_generator, N))  # It's get the next N elements of the counter, so you get unique id between agent in using the class SW_SIR
Sign up to request clarification or add additional context in comments.

Comments

1

Do you really need the random agent stored? I assume your logic is:

  1. Create two populations P and P' of size n.
  2. For each population, set at random state of member to one of S, I or R.
  3. Pick random member from population P and P' and swap them.
  4. Repeat step #3 for a determined time period.
  5. Analyze members for S, I or R state after period is finished.

In all of that, you don't need to store the random agent anywhere. You just need to fetch it and then swap the members around.

  1. Initialize the class with populations P and P'.

  2. "Infect" your members with state of S, I or R at random.

  3. Create a method that swaps members. It doesn't return anything, simply shuffles the lists, pops from one and appends to the other. You simply call this function at each "tick" of your time interval. This method could look like:

    def cross_pollinate(self):
       random.shuffle(self.pop_a)
       random.shuffle(self.pop_b)
       a = self.pop_a.pop()
       b = self.pop_b.pop()
       self.pop_a.append(b)
       self.pop_b.append(a)
    

2 Comments

In it's code, the "agent" are just an id. The state of the agent is determine by which list the id is keep. But yes an object 'Agent' with a state are more simple on some points.
@Cld Thanks a lot for suggestion. It is much simpler approach. I have a doubt about #3 step. Each of P and P' have certain connectivity between their agents following Erdos_Renyi random graph. So when I remove an agent from say P, the connections of that agent are lost. And when I add a new agent in P that would be the last one, it randomly connects to any agents in P. All after that SIR dynamics takes place. So if I follow you those connectivity changes won't take place. Am I right ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.