I have two turtle breeds (products
and consumers
) each with a 3-dimension list that defines their needs
(consumers) and their attributes
(products).
What I'd like is to have each consumer (i) look for a product that satisfies all their needs and create a link with them. If that product does not exist, I'd like them to (ii) drop the one need with the lowest value and look for a product that satisfies the other two. If that product does not exist, then I want them to (iii) look for another one that only satisfies the need with the highest value.
So say that consumer 20
has needs [0.2 0.5 0.3]
. If they find a product
whith exactly the same list of attributes [0.2 0.5 0.3]
I want the link to take place. If there's no such product then I want the consumer to ignore the lowest value (0.2
in the example) and look for a product that has attributes [xx 0.5 0.3]
, where xx
stands for "whatever".
Using examples from elsewhere here in SO, I have cobbled up the following code that (almost!) does the first part of the trick (i), but can't manage to do (ii) and (iii) despite multiple efforts. Would anyone have an indea on how to do this?
breed [consumers consumer]
breed [products product]
consumers-own [
needs
]
products-own [
attributes
number-buyers
]
to setup
ca
create-consumers 100 [ setxy random-xcor random-ycor]
create-products 100 [ setxy random-xcor random-ycor]
set-default-shape consumers "person"
set-default-shape products "box"
ask consumers [
set needs n-values 3 [ precision (random-float 1) 1 ]
]
ask products [
set attributes n-values 3 [ precision (random-float 1) 1 ]
]
reset-ticks
end
to go
buy
tick
end
to buy
ask links [ die ]
ask consumers [
carefully [ create-link-with one-of products with [reduce and (map = attributes [ needs ] of myself)] ] [ show "how do I find a sub-optimal product by ignoring my need with the lowest value ?" ]
]
ask products [
set number-buyers count link-neighbors
]
end
You are overthinking the full match - just check if the two lists are the same. However, the almost match is a bit more complicated. Here is a complete example model that finds the position in the list of the lowest and then checks that the other items are the same.
breed [consumers consumer]
breed [products product]
consumers-own [
needs
]
products-own [
attributes
number-buyers
]
to setup
clear-all
ask patches [set pcolor white]
create-consumers 10
[ setxy random-xcor random-ycor
set shape "person"
set color blue
set needs n-values 3 [ one-of [1 2 3] ]
]
create-products 10
[ setxy random-xcor random-ycor
set shape "box"
set color red
set attributes n-values 3 [ one-of [1 2 3] ]
]
reset-ticks
end
to go
ask consumers [buy]
tick
end
to buy ; set up as turtle procedure for testing purposes
ask my-links [ die ]
let candidates products with [attributes = [needs] of myself]
ifelse any? candidates
[ create-link-with one-of candidates ]
[ type self type " attributes: " type needs print " no matches"
let lowpoint position (min needs) needs ; note will take first if two equal min
set candidates products with
[ ((item 0 attributes = item 0 [needs] of myself) or lowpoint = 0) and
((item 1 attributes = item 1 [needs] of myself) or lowpoint = 1) and
((item 2 attributes = item 2 [needs] of myself) or lowpoint = 2)
]
ifelse any? candidates
[ create-link-with one-of candidates ]
[ print "no almost-match available" ]
]
end
I created the agentset (called candidates) of potential products to link to and then created the link. This makes the code much more readable. It also allows the if any?
construction if no matches were found. And it also makes it easier to debug because you can put print statements reporting numbers of matches and similar. I recommend that you always do this if you are applying some sort of condition that restricts the choices.
Also, you have a three item list with 10 possible values for each item. This means there will be 1000 combinations. You only have 100 consumers and 100 products, so matching will be fairly rare.