3

I am having trouble understanding an error emerging from two consecutive while loops in a net logo project.

;;;;;;;;;;;;;;;;;;;;;;;;
;;; Global variables ;;;
;;;;;;;;;;;;;;;;;;;;;;;;

globals [it]              

;;;;;;;;;;;;;;;;;;;;;;
;;; Breedin agents ;;; 
;;;;;;;;;;;;;;;;;;;;;;

breed [houses house]
breed [firms firm]

;;;;;;;;;;;;;
;;; Setup ;;;
;;;;;;;;;;;;;

to setup
  clear-all
  reset-ticks
  create-firms F
  create-houses H          

  ;; sets position of the firms in the space for better visualisation

     set it 0
  while [it < F ]
  [ask firm it [
      set color yellow
      set heading it * 360 / F
      fd 5 
      ]  
  set it it + 1
  ]

;; sets position of the households in the space for better visualisation  

  set it 0
  while [it < H ]
  [ask house it [
      set color yellow
      set heading it * 360 / H
      fd 15
      ]    
  set it it + 1
  ]  

When I run the above code I get an error message

firm 0 is not a HOUSE
error while observer running HOUSE
  called by procedure SETUP
  called by Button 'Setup'

pointing at house it in the code.

Notice that when I only run the first while loop, everything works fine.

I guess there is something I do not understand in the use of while loops in net logo.

  • Why does the second while loop seem to consider that I am calling firms although I asked to call houses?
  • Is there a better way to implement while loops in net logo?

Many thanks in advance for you help

1 Answers1

3

What's happening?

who numbers in NetLogo are assigned from the same sequence for all turtles, independently of their breeds. If you do:

create-firms 1
create-houses 1

Then you will have firm 0 and house 1, which you could also address as turtles. For example, in the command center:

observer> show turtle 0
observer: (firm 0)
observer> show turtle 1
observer: (house 1)

It makes sense to have unique identifiers like that, because the breed of a turtle is a very transient thing. It can be changed:

observer> ask firm 0 [ set breed houses ]
observer> show turtle 0
observer: (house 0)

The turtle has kept its who number despite the change of breed.

Why does the second while loop seem to consider that I am calling firms although I asked to call houses?

What you are doing is the equivalent of taking turtle 0 (which is a firm) and trying to cast it to a house. This is why NetLogo complains that firm 0 is not a house.

A better way to do it

Is there a better way to implement while loops in net logo?

Yes: don't use while! More seriously: using while is most often unnecessary. There is usually a better way to do things.

Also, in general, don't use who numbers for anything. If you want to deal with many turtles at once, use a turtle set. If you want to keep track of a turtle, store the reference to it directly (e.g., set my-firm one-of firms). If you find yourself wanting to use the who number, take a step back and rethink about your problem: there is almost certainly another way.

You want to do something with all your houses? Just ask them!

ask houses [
  set color yellow
  fd 15
] 

There is one thing that the snippet above does not address, however: your requirement for evenly spaced turtles. But you can achieve this by using the create-ordered-<breeds> to create your turtles. With it, your entire setup becomes:

clear-all
create-ordered-firms F [
  set color yellow
  fd 15
]
create-ordered-houses H [
  set color yellow
  fd 15
]

But what if you really need an index?

But what if create-ordered-<breeds> did not exist, or if you wanted to do something similar that required some sort of index? You still don't need while: a combination of foreach and n-values will get you there:

create-houses H
(foreach sort houses n-values H [ ? * 360 / H ] [
  ask ?1 [
    set color yellow
    set heading ?2
    fd 15
  ]
])

(We use sort to turn the houses turtle set into a list, but [self] of houses works as well if you want them shuffled.)

That code may look weird at first, but it's actually a pretty common and useful pattern in NetLogo. It "zips" the thing you want to act on with the index that you want to assign to it. It also has a few nice advantages over a while loop: no "off by one" errors, no extra variable and no risk of forgetting to increment the counter or to accidentally mutate it.

Nicolas Payette
  • 14,847
  • 1
  • 27
  • 37