1

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
lomper
  • 379
  • 1
  • 12
  • How is the value determined? for example, are the needs ordered by value (to the consumer), or is the value stored in the 3D list, or do the items have externally set values? Also, please show an example consumer list and an example products attributes so we can see the data structures. Your code also includes characteristics, purchase-intention, but they are not described in your question. – JenB Sep 17 '19 at 07:23
  • Hi @JenB, thank you! I have added all relevant parts of the code (should be self-conmtained) and made sure it is coherent in terms of the names I give to variables. Hope it's clearer now! – lomper Sep 17 '19 at 12:31
  • Sorry, I still don't understand. Each consumer has a list with 3 values from the set {0.0, 0.1, ... 0.9} and each product has a similar list of attributes. You want the consumer to create a link with a product that meets its needs but you don't explain or give example. Do you mean that the value at item 0 for product is at least equal to the value of item 0 for needs, and so on for other items in the list? Then drop the lowest number if you can't find, and match only on the other two values in the list? – JenB Sep 17 '19 at 13:03
  • Yes, that sounds much like what I am after, only that I want that the value for ``item 0`` (and the others) to be exactly the same... Come to think about it, I realise that ``create-link-with one-of products with [reduce and (map = attributes [ needs ] of myself)]`` does not exactly do this since the ``reduce`` bit could give a different combination that gives the same resulting number... I have added an example to the question hoping that it makes it clearer, but don't hesitate to ask for more details :) – lomper Sep 17 '19 at 13:15

1 Answers1

1

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.

JenB
  • 17,620
  • 2
  • 17
  • 45
  • Brilliant, thanks very much. I had tried doing this without ``map`` and ``reduce`` but could never get the right syntax. Agree though that the code is more intuitive and easier to debug. Point taken on the possible combinations! – lomper Sep 17 '19 at 16:32