Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
151 views
in Technique[技术] by (71.8m points)

social networking - NetLogo Efficient way to create fixed number of links

I have about 5000 agents (people) in my model. I want to give them an arbitrary number of friends and have reciprocal but random pairing. So if person A chooses person B then person B also chooses person A. My code works fine, but is fairly slow. I will likely want to increase both the number of friends and the number of people in the future. Any quicker suggestions?

ask people
[ let new-links friends - count my-links
  if new-links > 0
  [ let candidates other people with [ count my-links < friends ]
    create-links-with n-of min (list new-links count candidates) candidates
    [ hide-link ]
  ]
]

Note that friends is a global variable in the above code, but my eventual code will probably generalise to have wanted-number-of-friends as an attribute of people.

EDITED Added if new-links > 0 condition so that the nested ask is avoided when no candidates need to be found. This improved speed but still not really scaleable.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Great question. This is actually quite challenging to optimize. The problematic line is:

let candidates other people with [ count my-links < friends ]

This is slow because it has every agent checking with every other agent. With 5000 agents, that's 25,000,000 checks! Unfortunately, there isn't really a good way to optimize this particular line without some fancy data structures.

Fortunately, there is a solution that generalizes really well to generating any degree distribution in the network (which it sounds like that's what you ultimately want). Unfortunately, the solution doesn't translate super well to NetLogo. Here it is though:

  let pairs [] ;; pairs will hold a pairs of turtles to be linked
  while [ pairs = [] ] [ ;; we might mess up creating these pairs (by making self loops), so we might need to try a couple of times
    let half-pairs reduce sentence [ n-values friends [ self ] ] of turtles ;; create a big list where each turtle appears once for each friend it wants to have
    set pairs (map list half-pairs shuffle half-pairs) ;; pair off the items of half-pairs with a randomized version of half-pairs, so we end up with a list like: [[ turtle 0 turtle 5 ] [ turtle 0 turtle 376 ] ... [ turtle 1 turtle 18 ]]
    ;; make sure that no turtle is paired with itself
    if not empty? filter [ first ? = last ? ] pairs [
      set pairs []
    ]
  ]
  ;; now that we have pairs that we know work, create the links
  foreach pairs [
    ask first ? [
      create-link-with last ?
    ]
  ]

It doesn't matter if friends here is a global or a turtle variable. The amount of time this takes depends on the number of times that it needs to try making pairs, which is random. Experimenting, I found that it was usually about 3 seconds with 5000 agents, each with degree 5. This is compared to about 60 seconds on my machine with your original way of doing this (which, for what it's worth, is the way I would recommend when using fewer agents).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...