If I switch to turtle/patch context and do something like "set pcolor green", in what order do they execute the commands? I tested it out with a wait in there to see if there was an obvious pattern, but couldn't notice any. Is there any difference between that and ask?
I doubt it's completely random, though. How's it actually being handled behind the stage?
It's random--about as random as things get in computer programming, I believe. The NetLogo User Manual says:
An agentset is not in any particular order. In fact, it's always in a random order. And every time you use it, the agentset is in a different random order. This helps you keep your model from treating any particular turtles, patches or links differently from any others (unless you want them to be). Since the order is random every time, no one agent always gets to go first.
I just looked quickly at AgentSet.java in the source code for a recent version of NetLogo (5.0.2), it and looks to me like the order is randomized using a Mersenne Twister algorithm, which is usually considered to be quite good for randomization.
If you want the turtles/patches/links in a particular order, you can use sort, or select elements using e.g. with, or convert the agentset into a list using [self] of <agentset>, for example.
Related
Any tips on how to model agent behaviour in an environment where two sets of rules apply simultaneously.
Specifically, what I am looking to simulate is a situation where an Agent operates under a specific set of rules, such as an employee-employer relationship, but at the same time, operates on perhaps different "informal" rules, such as an employee-employee relationship. Effectively there are two network structures in place, but the agent operates in both structures.
Any example models out there that I could take a look at?
(This is a model design question, not programming, so it probably belongs on the NetLogo user group instead of here.)
My colleague and I wrote a book on modeling decisions that are tradeoffs between competing objectives, in ABMs. It's focus is on ecology but the concepts could be useful for you.
The basic idea is to come up with an objective function that includes both "sets of rules" as you call them. Perhaps something like maximizing your relations with fellow employees without getting fired by the employer. Then build very simple models of how decisions affect the mechanisms that drive co-worker relations, probability of getting fired, etc. It's not simple, but it's very powerful and flexible. You won't find a simple approach that's very general.
The fun part is trying different variations and comparing how they work.
https://press.princeton.edu/books/paperback/9780691195285/modeling-populations-of-adaptive-individuals
Maybe I’m under-thinking this, but..I would encode both (all) sets of rules, and have the agent execute those rules as appropriate.
So, how to choose and execute rules?
Per social interaction:
Execute one behavior randomly based on which relationships are present
Choose one or more behaviors, as #1 and execute all of them in a specific order
As above, but execute behaviors in random order
For all possible behaviors, assign a probability based on whatever factors (number of role-members present, utility, consequence, etc l) Choose and execute one behavior randomly based on that probability (roulettes-wheel selection)
Choose more than one… execute in fixed or random order
Proportionate to the value of a “social-competence” property, Select a number of possible behaviors as #4. Then randomly select one of those to execute.
Here’s a code-segment example of #6
;; list of possible reactions
;; these are variables or reporters that report
;; an anonymous command that executes the behavior
Let action-list (list
boss-action
employee-action
coworker-action
peer-action
)
;; measure social situation
;; list of values from reporters
;; these are reporters that return a value
;; based on, for example, how many of that type of
;; relationship are present.
Let choice-list ( list
( probability-of-doing-boss-behavior )
( probability-of-employee-behavior )
( probability-of-coworker-behavior )
( probability-of-peers-behavior )
)
;; think about situation, choose possible actions,
;; as many times as social-competence allows.
;; roulette-wheel should return the index of the selected action
Let reaction-list (n-values social-competence
[ -> roulette-wheel choice-list ] )
;; choose an action from those options
Let action-index one-of reaction-list
;; execute that action
Run item action-index action-list
The same result as a single combined objective function might be a physics type model where the result of any single set of rules is a vector of some strength pushing ("nudging"?) the agent in some direction. Then you could have as many sets of rules as you want, each contributing it's own vector of force, and the final result would be a resultant combined net force and subsequent Newtonian F=m*a or rearranging acceleration = ( vector sum of forces )/mass.
I'm trying to imagine how I respond when the expectations of different groups I belong to clash, and whether a linear sum vector model describes it. I recall in college when I couldn't resolve Catholic support for the Vietnam War and "Kill for Christ" was a tongue-in-cheek slogan. I think in that case the "forces" didn't cancel out -- they resulted in ABANDONING membership in one of the groups to reduce cognitive dissonance. So, not a linear sum of zero in that case.
Another unstable human approach might be to keep going back and forth when two forces attempting to dominate behavior conflict -- first going with one a few steps then feeling guilty and going the other way a few steps. So which one dominates at any given step might depend on one's recent path and history and which one you "owed" something to. Or imagine being married to two people and trying to keep both of them happy. Maybe you partition space and Monday-Tuesday-Wednesday you keep one happy and Thursday-Friday-Saturday you keep the other happy and Sunday you go fishing.
I would like to track the path of a wallet stolen by a thief. The model should create a network of thieves, each of them with their own bags where they put the stolen objects (I am setting this objects - wallets - as self).
Let suppose that thief1 has in his own bag [wallet1 wallet2 wallet4] and his neighbour has [wallet1 wallet3] as wallet1 was added in his own bag.
If the neighbour with bag [wallet1 wallet3] wants to pick randomly one of the two items to return to the police, for example wallet1 (and this can be done using [let picked_wallet one-of turtle-set my-bag]), how can I add a 'tag' or something that can tell me that the first thief to stole that wallet was the thief1?
globals [this-wallet]
breed[thieves thief]
thieves-own [my-bag wallet-id]
to setup
clear-all
create-thieves 5
ask thieves [ set my-bag [] create-links-to other thieves ]
ask one-of thieves [ set this-wallet self set my-bag fput self my-bag ask link-neighbors [set my-bag fput this-wallet my-bag print "Neighbours " show my-bag ]]
ask one-of thieves [ set this-wallet self set my-bag fput self my-bag ask link-neighbors [set my-bag fput this-wallet my-bag print "Neighbours " show my-bag ]]
ask thieves [show link-neighbors show my-bag]
reset-ticks
end
In response to your comment on my last answer, here's a new answer.
Well, a virus problem is different from a wallet problem and needs different data structures.
Still, viral transmission can be modeled as a series of transactions, so the idea of using a global master list of transactions to keep track of what has gone on is still a workable approach.
You COULD also keep a list on each agent of who they got a virus from and when, but it would be redundant with a single master list -- you can simply filter the master list of transactions by agent to see exactly the same information as what you are trying to keep in many lists at the agent level. I'm not sure why you do not like that approach.
Keeping one list is much cleaner than keeping many lists. Any question you could ask agents-with-lists you could also answer by searching the global list.
It would make sense to have a little redundancy for viewing what is going on and for simplifying the ASK command you will use to spread the virus -- so you could store at the agent level whether the agent is currently-infected? and color-code infected agents to tell them apart from never-infected agents and fully-recovered? agents and dead? agents.
Even that could be reduced to a single status variable with legitimate values of "healthy" "infected" and "recovered" and a single is-immune-now? flag. That would be enough to figure out who is contagious, who is infected, who could possibly become infected, who has recovered, who has died, etc.
Of course, if you are playing epidemiologist and trying to track down where the infection came from ( "patient zero") you COULD add a variable showing for each person WHO they got infected BY and when and write some long recursive code to trace back step by step where that linked-list started. OR, you could just get the same answer in a simple single filtering pass of the master list of who infected whom and when.
Maybe doing this the easy way is "cheating" and you want to play doctor instead of God and you want to show how it could possibly be tracked back one step at a time? Or you want to show how an epidemiologist might go to a lot of effort to build a "tree" diagram showing where the infection started and how it spread down different branches?
That's an INTERESTING problem but it is not the question you asked.
If you want to find the ultimate-source-turtle for an item in a list, you need to modify your data-structure. One way ( the hard way ) to do that would be to store more information in each turtle's list -- so at the time the virus is added to the list you ALSO add a timestamp and a source-turtle. Possibly you could store this information as triplets in a list such as [ source-agent-id tick-acquired virus-type ] and so each agent would have a list of such triplet-lists. That could work. That's one way to do it.
That would require that you add some complexity to the process that puts the virus on their list. It would have to build a list of the 3 items and put that list onto the target my-list of any agent it infected. ( In your case the virus seems to be 100% contagious and anyone with it gives it to everyone else! )
So your ASK-TURTLES logic would be a little bit more complicated. You could manage the complexity by having little to-report routines that packed the triplet-list or unpacked it.
OR, with fewer lists to manage, you could have your ASK-TURTLES logic store a series of transactions, that you could code as 4-item lists: [ source-id target-id virus-type tick-infected ] and store that in a master list-of-lists in a global variable. You still might want to set the target-turtle's variables of "status" and "immune-now?" at the time you are infecting the next agent to simplify identifying which turtles are contagious and which turtles are immune to simplify the next go step where you would ask turtles who are contagious to infect turtles who are not immune and are within a given radius, etc.
You asked
how can I add a 'tag' or something that can tell me that the first
thief to stole that wallet was the thief1?
I'm not clear about what operation corresponds to "stealing a wallet". Is the agent doing the stealing the one who puts the wallet on someone's list? Or the one whose list it gets put on?
In your example you have two different people with "wallet1" on their list, so I'm also not clear about who "has" the wallet. How can one wallet be two places at once? In fact it's more than two places, when it's put on one thieves list, it's put on every thieve's list. What is that operation supposed to represent? Is that "stealing"?
Are you trying to figure out which of the many copies of wallet1 got put on any agent's list first in time? Of course that's a little hard because agent sets are always processed in a random order, so the code you show gives no clue to who got it first.
What I'm suggesting is that the data-structure you have doesn't seem to do a good job of representing real-world operations, and if this doesn't confuse the current question of who got the wallet put on their list first, which is what I think you're asking, it will surely confuse other questions down the road. The operation you show for updating the lists makes it impossible to determine which thief got it first.
It certainly confuses me. I think your coding would be much easier if there was only ever one copy of wallet1 in existence, and it was only on one agent's list at a time, and the agent's list was only one entry long, and you had a "steal-wallet" procedure that removed a wallet from one agent's list and put it on exactly one different agent's list. Then it would be clear what time that happened.
Or are these lists supposed to represent knowledge one agent has about the existence of the wallet? Or do they represent all wallets that ever existed owned by anyone over all historical time, in which case the "same" wallet might appear many different times, each time representing a different owner, and even the same wallet and the same owner might be stolen and stolen back multiple times so even that pair of facts (wallet-id and new-owner) would not be unique.
For one thing, if everyone is going to end up with identical lists, then find some place to put the list once and be done with it -- don't give everyone a copy when one copy will do. The list doesn't even need to be owned by anyone -- it can simply be a global variable. That would simplify a lot. Then you only have one wallet, and each time it changes owner you can make an entry in the master-list.
What should the entry have in it? Certainly not the wallet itself, because that CAN be passed around. Probably you need a sublist that describes the transaction that just took place, so you would need a sublist containing [wallet-id, last-owner-id, current-owner-id, time-it-changed-hands] as the entries in the master global list.
From that you could at least conceptually be able to reconstruct who had the list first, second, third, .. or last, who has it now, anything you wanted. Or if you always did "lput" to put the latest event as the last item on the list, then you wouldn't even need the time-stamp, unless you lose information by sorting the list, because the first owner would be the first entry on the list that had that wallet-id. Problem solved, in concept. Still you might want to sort the list someday, so having the timestamp on it would allow you to recover the order later if you wanted to.
In conclusion of all that discussion, my suggestion to finding out who had wallet1 first would be this:
* get rid of the my-lists on every agent entirely.
Work with a single list defined as a global.
treat wallets as if they are real and only have one copy of a wallet at any one time.
define procedures "steal-wallet", "create-wallet" and "destroy-wallet" that move the wallet from one owner to another, and record the transaction as a sublist of 4 facts in the master list. The master list would be a list of lists then.
the master list might be named "transactions" because that's what it records.
then, conceptually, you would have all the information you need to answer any question about the life-history of a wallet or the life-history of a thief. You wouldn't have to maintain 20 different copies of the same information.
and it would be easy to look at all the thieves and see which one had the wallet, without needing to look at the transaction list. ( although, that information would correspond to the last entry in the transaction list about that wallet.)
Or -- maybe I totally misunderstand what these lists represent.
Passing the ball ( or wallet ) back to you.
I'd be interested to know what strategies people are using to work backwards from the results of a model (from observed emergent behaviour) to try to answer the question: what is it about individual turtles that has led to this macro behaviour?
Are you asking, "How can you guess what rules govern agents [turtles], given the macro-level behavior?"? Or are you asking, "Given that you have the source code, how to do you figure out what it is about the source that generates the macro-level behavior?"?
Answering the first question is very hard, often. I don't have suggestions.
Answering the second can be hard, too.
One strategy is to experiment with different initial configurations, or experiment with different rules in agents [turtles]. If you have no guesses about what to vary, make arbitrary choices at first, until you begin to have guesses, or even vague intuitions. Then vary the code in ways that will explore whether your guesses are correct, and in ways that will allow you to refine your guesses. This strategy won't always work.
Perhaps it might be useful to try to think through how you could generate the macro-level behavior, if that's what you wanted to produce. You might not have any idea of what an answer might be--this would amount to answering the first question above--but if you do, it might lead to guesses that you could use for the preceding strategy.
I do this when I am debugging because sometimes I get unexpected macro-behaviour and I need to determine whether it is real or an error. Typically what I would do is set the random seed then look at which agents are involved in the behaviour and when (ticks in NetLogo) it occurs. I would then rerun the model and stop it a few ticks beforehand and inspect the agents that I know are going to be involved in the behaviour to see if there's something unusual about them or their environment. Macro behaviour typically occurs because of the interactions of agents, environment and events so I am trying to determine WHAT those elements are, before seeking to explain how they combine to create the behaviour. Once that's done, I can usually trace the code (dropping in a print statement and inspecting the relevant agents) to work out how it occurred.
I read about how FoundationDB does its network testing/simulation here: http://www.slideshare.net/FoundationDB/deterministic-simulation-testing
I would like to implement something very similar, but cannot figure out how they actually did implement it. How would one go about writing, for example, a C++ class that does what they do. Is it possible to do the kind of simulation they do without doing any code generation (as they presumeably do)?
Also: How can a simulation be repeated, if it contains random events?? Each time the simulation would require to choose a new random value and thus be not the same run as the one before. Maybe I am missing something here...hope somebody can shed a bit of light on the matter.
You can find a little bit more detail in the talk that went along with those slides here: https://www.youtube.com/watch?v=4fFDFbi3toc
As for the determinism question, you're right that a simulation cannot be repeated exactly unless all possible sources of randomness and other non-determinism are carefully controlled. To that end:
(1) Generate all random numbers from a PRNG that you seed with a known value.
(2) Avoid any sort of branching or conditionals based on facts about the world which you don't control (e.g. the time of day, the load on the machine, etc.), or if you can't help that, then pseudo-randomly simulate those things too.
(3) Ensure that whatever mechanism you pick for concurrency has a mode in which it can guarantee a deterministic execution order.
Since it's easy to mess all those things up, you'll also want to have a way of checking whether determinism has been violated.
All of this is covered in greater detail in the talk that I linked above.
In the sims I've built the biggest issue with repeatability ends up being proper seed management (as per the previous answer). You want your simulations to give different results only when you supply a different seed to your random number generators than before.
After that the biggest issue I've seen seems tends to be making sure you don't iterate over collections with nondeterministic ordering. For instance, in Java, you'd use a LinkedHashMap instead of a HashMap.
I am new to NetLogo and I have some questions about the following piece of code:
people-own [
walker-type ;; can be "cautious", "adaptive" or "reckless"
walked-through-red?
own-profit
adaptive-threshold-time-gained
adaptive-threshold-time-gained-people-crossing
adaptive-gone-reckless
cooldown
]
With an OO background, I see this as some kind of enumeration of the properties of an object (the people breed). You can clearly see that there are three types of people: cautious walkers, adaptive walkers and reckless walkers. Also, the properties beginning with adaptive (adaptive-threshold-time-gained and such) have only meaning when the current person is adaptive.
I would expect that there is some way to express this more elegantly. In an OO programming language you would use inheritance to create three subclasses (one for each walker-type), but for so far I know that doesn't exist in NetLogo.
What is the recommended way of expressing this?
Lack of inheritance (perhaps as sub-breeds) is a serious limitation of NetLogo, although in the end it has only occasionally mattered to me. There are a couple possible work-arounds, depending on the application.
If you just want some different data attributes, and the related types are the only turtles in the simulation, you can have turtles-own the common characteristics and have breeds-own only the type specific characteristics.
If the data attributes are all shared but the behavior differs, you can create your own agentsets (in your case, subsets of people) and call different procedures on each agent set (or write procedures that branch on a member? test). Unfortunately, these agentsets will have to be explicitly augmented if any new members are created, so you lose that nice "special agentset" feature of breeds.
hth.