Haukland
Haukland

Reputation: 755

Accessing owned traits in netlogo with nested ask

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

Answers (2)

Nicolas Payette
Nicolas Payette

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

JenB
JenB

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

Related Questions