6

Given a turtle-set nodes, I want to find all links that have both ends in nodes. The best I've come up with so far is:

link-set [ my-links with [ member? other-end nodes ] ] of nodes

This does exactly what I want. However, since member? runs in linear time for non-breed sets, this is O(n*n*d) (where d is the max degree of the nodes and n is the number of nodes). I could improve it using a hash set, but that would require either abusing the table extension, finding a third-party extension, or making my own. I could also create a sorted list of the who numbers of the nodes, and then perform binary search on it to get down to O(n * log(n) * d), but I'm hoping for a simpler answer. Any ideas?

Bryan Head
  • 12,360
  • 5
  • 32
  • 50
  • I wonder if the first time you use `member?` on an agentset, a hash set should automatically be constructed and cached behind the scenes. The first `member?` call would only be slower by a constant factor, and then subsequent calls would be asymptotically faster. – Seth Tisue Aug 16 '14 at 23:54
  • In my case, its using a different agenset on each `member?` call, so it wouldn't really help here. But that's an interesting idea. – Bryan Head Aug 17 '14 at 14:55
  • Huh? It looks to me like you're calling `member?` over and over on the same set, namely `nodes`. – Seth Tisue Aug 17 '14 at 15:40
  • Oh woops, sorry, you're totally right. Got confused with the larger context of my problem. – Bryan Head Aug 17 '14 at 18:35

1 Answers1

7

Here is a wacky idea:

links-own [ i ]

to-report links-between [ nodes ]
  ask links [ set i 0 ]
  ask nodes [ ask my-links [ set i i + 1 ] ]
  report links with [ i = 2 ]
end

It's not the most elegant thing in the world, but it is simple enough and, I believe, only O(n*d).

Nicolas Payette
  • 14,847
  • 1
  • 27
  • 37
  • Perfect! That's pretty damn clever, Nicolas. Too bad it requires a `links-own`, but such is life. This took my network generation model down from 20000ms for 1000 iterations to 700ms. For the record, if `nodes` have a relatively small number of links between them, this can be improved by using `let possible-links link-set [my-links] of nodes`, and replacing the references to `links` with `possible-links`. This would bring it down from O(n*d + l) (where l is total number of links) to O(n*d). In my case, it didn't help, but might in others' situations. – Bryan Head Aug 16 '14 at 16:34
  • Links also own `label`, so, if not otherwise in use, one could use label in place of i, though it would require cleaning up label afterwards with `ask links [ set label "" ]`. – TurtleZero Aug 18 '14 at 19:52
  • @TurtleZero, that's a neat trick (and I never thought of that before). But I think I'd rather bite the bullet and create a `-own` variable. Using something for a different purpose than the originally intended one always carries a tiny risk (even if it's not otherwise in use). In the case of `label`, it could be that you later decide to switch to Continuous updates and you now get a flicker. Or that you later decide that you want actual labels in your model but this code interferes with them. No big deal, in either case, but I felt compelled to point it out nonetheless. – Nicolas Payette Aug 18 '14 at 20:58