pnowack
pnowack

Reputation: 101

Netlogo & Levelspace: how to pass strings between two child-models?

I have three models: Parent, Child1, Child2.

Child1 generates strings which must then be passed to Child2 for further processing. The strings are generated on the fly when Child1 is executing. Whenever a new string is generated it must be sent immediately to Child2. Sometimes 2 or more strings are generated at the same time (by different agents), and then those 2 or more strings must be sent at the same time (ie. within the same tick).

One solution is to skip the parent model and let Child1 become the Parent-model, which has then access to Child 2. However, that would complicate Child1 as it would then include all the required LevelSpace code. Furthermore the two children models must be useable on their own. The two models are used for educational purposes, and the students should not see the LevelSpace code. Hence the Parent model.

Another solution is to let the Parent model continuously poll the Child 1 model to ask for new strings. Not very pretty. Not very efficient.

So basically I'm looking for some shared memory and/or event functionality in LevelSpace :-)

By the way the strings represent DNA, RNA, etc. and we're illustrating transcription and translation of strings etc.

Any ideas?

Thanks, Palle

Upvotes: 4

Views: 167

Answers (2)

Bryan Head
Bryan Head

Reputation: 12580

Jasper wrote a really nice solution, though it does rely on behavior that isn't supposed to work. Another way to do it is to have child1 collect the strings as it runs in a global variable. e.g.

Child 1 code:

globals [ strings ]

to go
  set strings []
  ask turtles [
    set strings lput (word "hello from turtle " who) strings
  ]
  tick
end

Then have child2 accept a list of strings in its go method

Child 2 code:

to go [ strings ]
  ; do stuff with the strings
end

Then the parent passes the list between them:

Parent code:

to go
  ls:ask child1 [ go ]
  ls:let child1-strings [ strings ] ls:of child1
  ls:ask child2 [ go child1-strings ]
  tick
end

Upvotes: 3

Jasper
Jasper

Reputation: 2780

It is definitely not conventional NetLogo code, but the callback method seems like it works okay, at least for this simple example. You do need to complicate the child models a little bit to add the run callback statement, but it could result in cleaner code overall than the polling method depending on the use case.

Parent model:

extensions [ ls ]

globals [ child1 child2 ]

to setup
  ls:reset
  (ls:create-models 1 "LS callback child.nlogo" [ [id] -> set child1 id ])
  (ls:create-models 1 "LS callback child.nlogo" [ [id] -> set child2 id ])
  ls:ask ls:models [
    child-setup
  ]
  ; here we set the callback for the child models
  ; we could set the callback for just `child1` instead of all `ls:models`
  ls:assign ls:models callback [ [id message] -> alert id message ]
  ls:assign child1 id child1
  ls:assign child2 id child2
end

to go
  ls:ask ls:models [
    child-go
  ]
end

; In this case our callback is simple, just taking the caller id
; and a message.  We could add more parameters for it if we want to
to alert [id message]
  show (word id ": " message)
  ; this is just to show that we can use the callback to update
  ; the state of one of the other models
  if id = 0 [
    ls:ask child2 [ set some-val (some-val + 1) ]
  ]
end

Child model:

globals [ id callback some-val ]

to child-setup
  set some-val 0
  ; set the callback to an "empty" procedure so we don't have to check
  ; if it is set while we run the go method.
  set callback [ [model-id message] -> ]
end

to child-go
  if random 10 < 3 [
    (run callback id (word "child alert: " some-val))
  ]
end

Sample output:

observer: "1: child alert: 0"
observer: "1: child alert: 0"
observer: "1: child alert: 0"
observer: "0: child alert: 0"
observer: "1: child alert: 1"
observer: "0: child alert: 0"
observer: "1: child alert: 2"
observer: "1: child alert: 2"
observer: "0: child alert: 0"
observer: "1: child alert: 3"
observer: "1: child alert: 3"
observer: "1: child alert: 3"
observer: "0: child alert: 0"
observer: "1: child alert: 4"
observer: "0: child alert: 0"
observer: "1: child alert: 5"
observer: "1: child alert: 5"
observer: "0: child alert: 0"
observer: "1: child alert: 6"

Every time the child1 model runs the callback, the alert procedure increments the some-val global in child2.

Upvotes: 1

Related Questions