matrixnetlogoadjacency-matrixedge-list

Using a link agentset that has link weights to create an adjacency matrix in NetLogo


My understanding is that a link agentset is roughly equivalent to an edge list. In this case, I have links (3 breeds of them, but I think that's irrelevant) that have a variable, weight, that can be anywhere from 0 to 1. I'd like to store each link agentset data in its own adjacency matrix at the end of each tick. Meaning, each link weight becomes an entry in a row and column based on the end1 and end2 turtles. I think an actual matrix (a matrix extension object) would be the best in this case, because then it's easy to manipulate for outputting to behaviorspace or whatever.

Is there an elegant way to do this?


Solution

  • The simplest way I can think of to do this relies on turtle who numbers (although you could use some other identifier for your end1 and end2 turtles), so I'm a little wary of it. If you are comfortable in python or R you may be better off simply reporting a nested list (something like [[ weight turtle i turtle j ] ... ] and processing after the fact- you can track turtles as row / column names in either of those or similar environments. However, here is one in-NetLogo approach that may suit your needs:

    extensions [ matrix ]
    globals [ matrix-list ]
    links-own [ weight ]
    
    to setup 
      ca
      ask n-of 5 patches [ sprout 1 ]
      ask turtles [    
        create-links-to n-of 2 other turtles [
          set weight precision random-float 1 3
          set color weight * 100
        ]
      ]
      set matrix-list ( list report-matrix )
      reset-ticks
    end
    
    to go
      ask links [ 
        set weight precision ( weight + random-float 0.2 - 0.1 ) 3 
        if weight < 0 [ set weight 0 ]
        if weight > 1 [ set weight 1 ]
      ]
      set matrix-list lput report-matrix matrix-list
      tick
    end
    
    to-report report-matrix
      let n-cr count turtles
      let new-mat matrix:make-constant n-cr n-cr -1
      ask links [
        let from-t [who] of end1
        let to-t [who] of end2
        matrix:set new-mat from-t to-t weight    
      ]
      report new-mat 
    end
    

    setup builds a toy world and stores the first matrix in matrix-list- something like:

    observer> print matrix:pretty-print-text last matrix-list
    [[    -1  0.606  0.337     -1     -1 ]
     [    -1     -1     -1  0.478  0.271 ]
     [    -1     -1     -1  0.129  0.493 ]
     [    -1  0.897     -1     -1  0.076 ]
     [ 0.817  0.714     -1     -1     -1 ]]
    

    Each run of go randomly alters the weights of each link, but keeps the location in the matrix the same- after running go once:

    observer> print matrix:pretty-print-text last matrix-list
    [[    -1  0.692  0.284     -1     -1 ]
     [    -1     -1     -1  0.503  0.367 ]
     [    -1     -1     -1  0.123  0.571 ]
     [    -1  0.856     -1     -1      0 ]
     [ 0.756  0.761     -1     -1     -1 ]]
    

    twice:

    [[    -1  0.753  0.275     -1     -1 ]
     [    -1     -1     -1   0.51   0.35 ]
     [    -1     -1     -1  0.111  0.497 ]
     [    -1   0.95     -1     -1  0.039 ]
     [ 0.852  0.845     -1     -1     -1 ]]
    

    Hopefully that gets you pointed in the right direction!