Reputation: 3
Suppose that each node is assigned a list, such as [1 0 0 1] (nodes-own variable 'state'). I'm trying to compare the lists of two connected nodes to decide how much they agree, then for a given node decide which of the connected nodes has the most similar state to its own. Ultimately I want to have the nodes update their values for another variable ('answer', which is 1 or 0) to be the same as the answer of the closest matching node.
To compare the lists of two nodes, I wanted to subtract them and take the absolute value, and set it as an 'agreement' score for the link connecting the two. So for the subtraction, I tried:
ask links [
let subtracted-list (map - state of end1 state of end2) ...]
but I'm getting a runtime error here that says "- expected input to be a number but got the list instead". I was going to then similarly use map to take the absolute value of the resulting list and take a sum, but I seem to be stuck here and can't figure out what's going wrong.
Edit:
I've tried to incorporate the suggestions but for some reason I still can't get it to work. Here is the code:
breed [nodes node]
nodes-own [state]
links-own [agreement-score]
to setup
clear-all
set-default-shape nodes "circle"
ask patches [ set pcolor black ]
repeat num-nodes [ make-node ]
create-network
distribute-state
repeat 100 [ layout ]
reset-ticks
end
;; Distributing state values to each node (ex. [0 1 0 0 1 0 0 1])
to distribute-state
ask nodes [
set state (list n-values num-state-elem [random 2])
]
end
;; Network formation - Preferential attachment from the Models Library
to make-node
create-nodes 1 [
rt random-float 360
fd max-pxcor
set size 1.5
]
end
to create-network
let partner nobody
let first-node one-of nodes
let second-node one-of nodes with [self != first-node]
ask first-node [ create-link-with second-node [ set color white ] ]
let new-node one-of nodes with [not any? link-neighbors]
while [new-node != nobody] [
set partner find-partner
ask new-node [ create-link-with partner [ set color white ] ]
layout
set new-node one-of nodes with [not any? link-neighbors]
]
end
to update-color
end
;; Go procedures
to go
ask links [calculate-agreement-score]
ask nodes [update-color]
tick
end
to calculate-agreement-score
ask links [
set agreement-score bit-difference [state] of end1 [state] of end2
]
end
to-report bit-difference [#list1 #list2]
let subtraction (map - #list1 #list2)
report reduce + map abs subtraction
end
;; Making the network
to-report find-partner
let pick random-float sum [count link-neighbors] of (nodes with [any? link-neighbors])
let partner nobody
ask nodes
[if partner = nobody
[ ifelse count link-neighbors > pick
[ set partner self]
[ set pick pick - (count link-neighbors)]
]
]
report partner
end
to layout
layout-spring (nodes with [any? link-neighbors]) links 0.4 6 1
end
This is still giving me the same error message: "- expected input to be a number but got the list [1 0 1 1 1 1 0 0 1 0] instead."
Upvotes: 0
Views: 302
Reputation: 17678
These sorts of questions are much easier to answer if you give some example inputs and expected output to reduce ambiguities. However, I think that your problem is simply that you did not use [] to extract the state value. Have a look at this complete model:
turtles-own [state]
to testme
clear-all
create-turtles 2
[ set state []
repeat 4 [set state lput one-of [0 1] state]
show state
]
type "subtraction is: " print (map - [state] of turtle 0 [state] of turtle 1)
end
Since you want to compare this subtraction over multiple pairs of nodes (or actually the sum of the absolute differences), it is best to set it up as a reporter. That way, you can then use the results of the reporter as the input to a min-one-of
statement.
turtles-own [state]
to testme
clear-all
create-turtles 2
[ set state []
repeat 4 [set state lput one-of [0 1] state]
show state
]
type "subtraction is: " print (map - [state] of turtle 0 [state] of turtle 1)
type "difference is: " print bit-difference [state] of turtle 0 [state] of turtle 1
end
to-report bit-difference [#list1 #list2]
let subtraction (map - #list1 #list2)
report reduce + map abs subtraction
end
Note that I have used # to start the argument names, this is a personal convention, but I think makes the code easier to understand as you can see what is being passed to the reporter procedure. Note also that this could be done as a single line if you don't care about readability:
report reduce + map abs (map - #list1 #list2)
This also answers how to extend your code to do the sum of absolute differences if you don't want to use the reporter procedure version:
let bitdiff reduce + map abs (map - [state] of end1 [state] of end2)
Upvotes: 2