0

An error occurs in NetLogo with the code below. What I would like to do is for each turtle to check the nearest turtle and calculate the distance between myself (turtle) and its nearest turtle.

If the distance is below 8, the turtle is unsatisfied and otherwise, the turtle becomes satisfied. The unsatisfied turtles die.

At some point, it occurs that there is only one turtle around so the 'nearest' turtle is a nobody. It can not calculate the distance to a turtle that doesnt exist. I understand what goes wrong and I tried to solve it with a piece of code that sets the turtles' satisfaction on 0 (true) if there is no one around. But I still got the message: distance expected input to be an agent but got nobody instead..

Can you see what goes wrong?

ask turtles [ let nearest min-one-of turtles [ distance myself ] 
    ifelse nearest = nobody 
    [ set satisfaction 1 ]
    [ ifelse distance nearest < 8 [ set satisfaction 0] [ set satisfaction 1 ] ] ]
desertnaut
  • 57,590
  • 26
  • 140
  • 166
loet23
  • 21
  • 2

2 Answers2

1

Finding the nearest other turtle is a common and surprisingly tricky problem in NetLogo; we need a primitive "nearest" that does it. Meanwhile we cover it in Sect. 11.2 of our textbook.

You have two problems:

First "min-one-of turtles [distance myself]" will always produce a distance of zero because the nearest turtle is always the turtle executing the statement. You need "min-one-of (other turtles) [distance myself]"

Second, it's not clear to me why you are getting the error but you could prevent it by enclosing the whole statement inside an if statement:

ask turtles [ if any? other turtles [ let nearest ...

Steve Railsback
  • 1,251
  • 6
  • 7
  • Thank you Steven for your answer! It makes sense that the turtle always calculates the distance to itself, so I changed that in the code and it makes it already better. However, the error still occurs when I would like to calculate the distance when there is no other turtle around. That is obvious, but I thought i implemented a line of code that when the 'nearest' is nobody, the turtle is automatically satisfied. If I i provide my improved lines of code, can you see what goes wrong? – loet23 Feb 20 '21 at 09:38
  • I am using NetLogo 6.0.4 by the way, is this something that could cause the problem? – loet23 Feb 20 '21 at 10:38
1

Please edit your question rather than provide follow up as answers.

The problem is that you have got your satisfaction values confused. You state that 0 means satisfied in the question text, but then assign 1 if nearest != nobody (that is, there is another agent). So your code jumps to the distance calculation block when the nearest != nobody is false or equivalently when the nearest is actually nobody. All of this can be avoided by using true and false, which would make your code much easier to read and less susceptible to errors. It's not essential, but NetLogo convention has a ? at the end of variable names that are used for boolean (true/false) variables.

So, rewriting your code so it can stand alone and ditching the 0/1, dumping the negative test (which is confusing) and reversing the final assignment, it looks like this:

turtles-own [satisfied?]

to testme
  clear-all
  create-turtles 20
  [ setxy random-xcor random-ycor
  ]
  ask turtles
  [ if any? other turtles 
    [ let nearest min-one-of (other turtles) [distance myself] 
      ifelse nearest = nobody
      [ set satisfied? true ]
      [ ifelse distance nearest < 8 
        [ set satisfied? false ]
        [ set satisfied? true ] 
      ]
    ]
  ]
  type "satisfied turtles: " print count turtles with [satisfied?]
end

I have also reformatted the code so you can see where your ifelse structures operate. It is now also clear that no value is assigned to satisfied? if there's only one turtle, so the value will stay as the default of 0.

So a better version would look like:

ask turtles
[ ifelse any? other turtles 
  [ let nearest min-one-of (other turtles) [distance myself]
    ifelse distance nearest < 8 
    [ set satisfied? false ]
    [ set satisfied? true ] 
  ]
  [ set satisfied? true
  ]
]

That can be done in a single statement (and I have expressed it positively instead of negatively because that is more natural to read, so also see the new not statement):

to testme
  clear-all
  create-turtles 1
  [ setxy random-xcor random-ycor
  ]
  ask turtles
  [ ifelse not any? other turtles or
           distance min-one-of (other turtles) [distance myself] > 8
    [ set satisfied? true ]
    [ set satisfied? false ] 
  ]
  type "satisfied turtles: " print count turtles with [satisfied?]
end

You need to have the clauses ordered so that it checks the any? first. This should have been achieved by the nested ifelse in your attempted solution except that you had the test reversed.

JenB
  • 17,620
  • 2
  • 17
  • 45
  • thank you so much for this detailed answer! I implemented the last piece of code you suggested in my model and it works the way I want it to be working! Thank you very much. – loet23 Feb 21 '21 at 10:05