2

I'm trying to put together a "social network" of sorts in NetLogo. A group of people of different age groups who are connected by links.

I'm having trouble with how to put it together because I'm still not fully familiar with some parts of NetLogo's syntax. I only started using breeds in my code in the last week and I haven't fully worked them out yet. Or I'm over complicating them, I'm not sure.

The relevant code is below with the function in question being the "create-network" one. I need to ask each agent (there will be about 800 in total) to connect to a certain amount of each type of other agent (so long as that other agent isn't full up). If the turtle is of the breed toddler for example it will have 10 links in total, 5 of which are to other toddlers, 2 to children, 2 to adults and 1 to over45s. If the first node is a toddler and it connects to an adult, I will need to decrement the number of toddlers that the adult node will try to connect to when I get to it too, if that makes sense.

I can't work out how to ask the current turtle what breed it is, so that I can link to the right amount of the right breeds. If anyone could help me out I'd be insanely grateful. This is only a small section of the code but its been driving me crazy for days now

Every time I try something it results in errors and I'm all out of ideas and the will to live. Thanks so much in advance for your time. Even if you have any thoughts on a better algorithm but not code it would be very welcome too

breed [toddlers toddler]
breed [children child]
breed [adults adult]
breed [over45s over45]

globals
[
  num-nodes
]

toddlers-own
[
  tod-total-connections
  tod-tods
  tod-children
  tod-adults
  tod-over45s
]

children-own
[
  child-total-connections
  child-tods
  child-children
  child-adults
  child-over45s
]

adults-own
[
  adult-total-connections
  adult-tods
  adult-children
  adult-adults
  adult-over45s
]

over45s-own
[
  over45-total-connections
  over45-tods
  over45-children
  over45-adults
  over45-over45s
]


to generate
  clear-all
  create-toddlers num-toddlers
  create-children num-children
  create-adults num-adults
  create-over45s num-over45
  create-network
  setup
  reset-ticks
end

to setup 
  ask turtles
    [reset-node]
  ask links
    [set color gray + 1.5]
  ask adults
    [set shape "circle"
      set size 4]
  ask toddlers
    [set shape "face happy"
      set size 4]
  ask over45s
    [set shape "triangle"
      set size 4]


  ;;INITIALISE BREEDS

  ;;Initialise Toddlers
  ask toddlers [set total-connections 10]
  ask toddlers [set tod-tods 5]
  ask toddlers [set tod-children 2]
  ask toddlers [set tod-adults 2]
  ask toddlers [set tod-over45s 1]

  ;;Initialise Children
  ask children [set total-connections 17]
  ask children [set child-tods 3]
  ask children [set child-children 8]
  ask children [set child-adults 5]
  ask children [set child-over45s 1]

  ;;Initialise Adults
  ask adults [set total-connections 13]
  ask adults [set adult-tods 1]
  ask adults [set adult-children 3]
  ask adults [set adult-adults 6]
  ask adults [set adult-over45s 3]

  ;;Initialise Over45s
  ask over45s [set total-connections 12]
  ask over45s [set over45-tods 1]
  ask over45s [set over45-children 1]
  ask over45s [set over45-adults 5]
  ask over45s [set over45-over45s 5]



  ;; Layout turtles:
  layout-circle (sort turtles) max-pxcor - 8
  ask turtles
  [
    facexy 0 0
    if who mod 2 = 0 [fd 4]
  ]
  display
end


;; THIS IS THE PROBLEM FUNCTION
to create-network
  let q 0
  let n 0
   while [q < count turtles]
  [
    let m 1
    while [m < count turtles]
        [
           make-link-between turtle n
                  turtle ((n + m) mod count turtles)
           set m m + 1 
;;results in a fully connected network which I don't want
         ]  
     set n n + 1
     set q q + 1
  ]

end


;; connects the two nodes
to make-link-between [node1 node2]
  ask node1 [
    create-link-with node2
      [ set color gray + 1.5]
  ]
end

I'm also wondering whether it would be possible have a function to "pause" the links between agents. For example to turn off a number of or all of the links between children. I know that links have a tie-mode attribute but I'm not sure that this is able to do this. From what I read it seems to be more about holding moving agents together? Could I use untie as a way to turn off the link but to have a it still present?

Edit: Hide link may be more appropriate. How to hide the right links is the next thing

4

1 回答 1

3

First, let's get this out of the way:

I can't work out how to ask the current turtle what breed it is

Turtles have a breed variable.

But I think that, more generaly, you haven't yet come to terms with the NetLogo way of doing things. Your code is very imperative, using while loops and indexes. You should avoid addressing turtles by their who numbers (though your own layout code might be a rare exception to that). NetLogo is all about lists, agentsets, and (when possible) functional transformations.

Anyway, here is what I think is a better approach to your problem. The trickiest bit is how reverse-num-connexions is computed, but trying to figure out how it works should be an excellent exercise for learning how to deal with lists.

Also, notice that it's possible that a turtle does not end of with the desired number of connexions because all of its targets are maxed out. It will depend on your population ratios.

breed [ toddlers toddler ]
breed [ children child ]
breed [ adults adult ]
breed [ over45s over45 ]

to setup
  clear-all
  create-toddlers 200
  create-children 200
  create-adults 200
  create-over45s 200
  create-network
  reset-ticks
end

to create-network

  let connexions (list
    (list toddlers toddlers 5)
    (list toddlers children 2)
    (list toddlers adults 2)
    (list toddlers over45s 1)
    (list children toddlers 3)
    (list children children 8)
    (list children adults 5)
    (list children over45s 1)
    (list adults toddlers 1)
    (list adults children 3)
    (list adults adults 6)
    (list adults over45s 3)
    (list over45s toddlers 1)
    (list over45s children 1)
    (list over45s adults 5)
    (list over45s over45s 5)
  )

  foreach connexions [
    let source-breed item 0 ?
    let target-breed item 1 ?
    let num-connexions item 2 ?
    let reverse-num-connexions item 2 first filter [
      item 0 ? = target-breed and item 1 ? = source-breed
    ] connexions
    ask source-breed [
      repeat num-connexions [
        let possible-targets other target-breed with [
          (not member? myself link-neighbors) and
          (count link-neighbors with [ breed = source-breed ] < reverse-num-connexions)
        ]
        let target one-of possible-targets
        if target != nobody [ create-link-with target ]
      ]
    ]
  ]

end

reverse-num-connexions explanation (edit)

Let's say we are traversing our list of numbers of connexions, and we get to [toddlers adults 2]. That says that each toddler should have connexions to 2 adults. But if we look further down the list, we see that adults should be connected to no more than 1 toddler: [adults toddlers 1]. This number (1) is what we are trying to extract for storing as reverse-num-connexions.

The first thing to do is finding the right sublist. This will be the one where the "source" and "target" breeds are the inverse from the current one. The expression filter [ item 0 ? = target-breed and item 1 ? = source-breed ] connexions will return a list with only that sublist: [[adults toddlers 1]]. To extract it, we use first, which gives us just the sublist: [adults toddlers 1]. Now, we want the last item of that sublist, which is item 2. This will give us the 1 that we were after.

于 2013-08-14T14:42:57.987 回答