Reputation: 755
This is what i want to do:
patches-own[
trait1
trait2
trait3
]
let similarityCounter 0
ask one-of patches[
ask one-of neighbors[
**for-each trait[
if neighborTrait = patchTrait**[
set similarityCounter (similarityCounter + 1)
]
]
]
]
The part between ** is what I'm unsure about. How does one iterate over the patch-own parameters and compare between patch and neighbor?
Upvotes: 1
Views: 89
Reputation: 14972
I really like Jen's answer, but just for fun, I'd like to provide an alternative way to approach the problem that uses Jen's idea of treating true
as 1
and false
as 0
.
But first, I think that, depending on the rest of your model, it could have been a good idea for you to store your traits directly in a list instead of separate variables. In programming, having variable names with a numeric suffix like trait1
, trait2
, etc. is usually a hint that a list should be used instead.
Nevertheless, we will leave your general design alone for now and just provide a small function that makes it easy to package your traits into a list:
to-report traits ; patch reporter
report (list trait1 trait2 trait3)
end
Once you have that, you can write something like [ traits ] of one-of patches
to get a list of the patche's traits.
Now let's attack the problem of turning true
and false
into ones and zeros in a similar way. It's true that NetLogo doesn't provide that conversation automatically (which I think is a good thing) but it's easy to write our own function for that:
to-report bool-to-int [ yes? ]
report ifelse-value yes? [ 1 ] [ 0 ]
end
We are now ready to write our main function. We will use Jen's approach of mapping over the =
operator to convert our lists of traits to a list of boolean (i.e., true
/false
) values, and we will then use map
again to convert that list into a list of 1
and 0
. Once we have that, all that is left is to sum
it! Here we go:
to-report similarity-with [ other-patch ] ; patch reporter
report sum map bool-to-int (map = traits [ traits ] of other-patch)
end
Having that reporter makes it really easy to get the similarity between two patches. You can now say things like:
print [ similarity-with one-of neighbors ] of one-of patches
Notice how I have approached the problem by building small pieces that be combined together. I really like this way of proceeding: it allows me to concentrate on one part of the problem at a time, but it's also more easy to test and results in code that I find very readable. NetLogo's to-report
procedures are a great tool to achieve that kind of modularity.
Upvotes: 2
Reputation: 17678
How about you create a list for each patch of their trait values and count matches in the two lists? It would looks something like this.
to testme
let similarityCounter 0
ask one-of patches
[ let mytraits (list trait1 trait2 trait3)
let theirtraits [(list trait1 trait2 trait3)] of one-of neighbors
set similarityCounter length filter [ xx -> xx ] (map = mytraits theirtraits)
]
end
The final line is a little dense. What it does is compare the two lists of traits using the map
function with the =
operator, which will return a list of true
and false
values indicating whether that specific trait matches. The filter
then creates a list of just the true
values and the length
counts the number of those true
values.
Unfortunately, NetLogo doesn't do the trick of treating a true
as 1 and false
as 0 that you see in some languages, so you can't simply sum
the match results list.
Upvotes: 3