goal-seeking-boids

goal-seeking-boids preview image

1 collaborator

Army_coat_pix R. Wade Schuette (Author)

Tags

goal-seeking 

Tagged by R. Wade Schuette about 3 years ago

Visible to everyone | Changeable by the author
Model was written in NetLogo 6.2.0 • Viewed 194 times • Downloaded 46 times • Run 0 times
Download the 'goal-seeking-boids' modelDownload this modelEmbed this model

Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)


Comments and Questions

Please start the discussion about this model! (You'll first need to log in.)

Click to Run Model

;; MODEL NAME:   goal-seeking-boids-v2-1py
;; DATE:  written 14-Nov-2019
;; HISTORY:
;;       01-Feb-2011  uploaded first version to modeling commons
;;                    latest version updated 1-Feb-2021 at 6:28 AM CST (Chicago time zone )
;;       14-Oct-2021  Modified to allow rerunning random-seed values.
;;                    Tests for running netlogo-web. If local, allows importing landscape and saving snapshots
;;                    added "maxwealth" and "stepsize" to turtles-own variables
;;
;;  TRANSIENT Work in process
;;      *  migrate local-gorup-horizon to all instances of everyone, wej ust put it in everyone uphill
;;      *  correction for angles near 360 has only been applied to every plus uphill case
;; known bugs:
;;  *  prints stopped when all turtles succeeded twice in output
;;  *  on stop for everyone,  neither of the plots are accurate, and the last 45 or so never are caught
;;  *  motion can get locked up in a corner


 ;;============ UN-comment the next line if you are running locally! =================
 ; extensions [view2.5d]
 ;; ==================================================================================

globals [


  stop-now?        ;; stop flag for subroutines to back up to the go command
  patch-count      ;; for this size display
  on-peak-count    ;; number of turtles on the peak
  peak-height      ;; height of highest patch
  my-center        ;; weighted centroid of all the agents, or possibly of VISIBLE nearby agents
  timestamp        ;; updated date-and-time to show on interface, only updated when taking snapshot
  stop-at-tick     ;; stop run when ticks >= stop-at-tick
  filechoice       ;; imported landscape jpg file name, if any

  ;; global variables defined by the interface controls
  ;; note - these are NOT cleared by "clear-globals" or "clear-all"
  ;; ===============================================
  ;; randomseed   ;; ( added 13-Oct-2021 )
  ;; number-of-hits
  ;; turtle-count
  ;; rule-to-use
  ;; leave-a-trail?
  ;; run-title
  ;; turtle-color
  ;; turtle-shape
  ;; landscape-source
  ;; noise?
  ;; noise-size
  ;; noise-density
  ;; group-weight
  ;; timestamp
  ;; braking-pct   ( insert a wait X seconds into the end of the go loop for fine tuning)

;;; ============== automater's globals begin ====================
;  working-directory   ;; the operating system working directory
;  command-file        ;; where the commands will be read from
;  output-file         ;; optional, where output from the go step can be written
;  log-file            ;; a log of what commands were executed
;  run-title           ;; whatever you want to name this run
;  show-commands-as-run?        ;; controls whether you want to see commands as they are run
;  use-sample-input-file?       ;; if true, generates a file called test-01-input.txt to use
;                               ;; as input for this model.
;                               ;; This will destroy an existing file of that name!
;;; ================ automater's globals end =====================


]

turtles-own[
  maxwealth ;; maximum wealth turtle has ever seen - 10/13/21
  wealth    ;; just equal to the pcolor of the patch the turtle is on
  prior-wealth ;; wealth before this latest step
  on-peak?
  old-heading  ;; actually exponentially smoothed history of prior headings
  inertia      ;;  [0,1], turtle specific, weight of old-heading in updated heading, defaults to zero
  empathy      ;;  [0,1] actually misnamed to be shorter, susceptibility to group peer pressure
  step-size-multiplier    ;;  10/13/21
  good-step-count ;; counts number of steps with improving height
  my-heading-uphill ;; before step
  my-heading-group  ;; before step
]

patches-own [
  height
  basepcolor
]

to setup

      if ( netlogo-web? = false )
       [
      print "\n ================================== \n If you get an error that VIEW2.5:PATCH-VIEW is undefined, \n  uncomment out the EXTENSION definition in the first line of actual code \n ================================== \n";
       ]


   let mystr88 "Test"

    if  ( netlogo-web? = false )
  [
     run " view2.5d:patch-view  mystr88  [ [the-patch] -> [height] of the-patch ] "
     run " view2.5d:set-z-scale mystr88  zfactor "
  ]

  ;; we persist randomseed across runs by putting the prior value in the "local" variable "oldseed"
  ;; but if that has never been set, we need to set it as well.

  clear-all
  if (reuse-seed? = false ) [ set randomseed  ( random 999999 )  ]
  ;; note, if randomseed is not reset above, the value from the interface input box will persist
  random-seed randomseed

  set timestamp date-and-time
  set stop-now? false

 ;; no-display  ( won't work over the web ! )
  if landscape-source = "generated" [make-landscape  ]
  if landscape-source = "imported"  [import-landscape]
  make-turtles
;;  display( won't work over the web ! )
  set my-center (patch 0 0)   ;; weighted centroid of the agents, dynamically updated
  ;;======================================= automaters commands begin
  ;; setup-automater
  ;;======================================= automaters commands end
  prepare-outputs
  set stop-at-tick max-ticks ;; stop normally if time is reached

  ask patches [ set basepcolor pcolor ]
  ask patches [ ifelse  ( count turtles-here > 0 ) [ set pcolor green][set pcolor basepcolor]]
  reset-ticks
end 

to prepare-outputs  ;; called once during setup
  ;; select external log and output files here, if any

  ;; write experiment title and date to output area

  output-print run-title
  output-print timestamp  ;; set at start of run, not output date-and-time !
  output-print " "
  output-print (word "turtle-count: " turtle-count)
  output-print (word "rule-to-use: " rule-to-use)
  output-print (word "landscape: " landscape-source)

  if (landscape-source = "imported")
    [output-print (word "file: " filechoice)]

  ;; other experimental settings could be output here
  output-print "  "

  ;; write column headers to the output area

     (if-else
       rule-to-use = "single: wander"              [ output-print (word "turtle "   " ticks "   )  ]
       rule-to-use = "single: go-uphill"           [ output-print (word "turtle "   " ticks "    )  ]
       rule-to-use = "single: find-everyone"       [ output-print (word "turtle "   " ticks "   " group-weight: "   )  ]
       rule-to-use = "pair: uphill with inertia"   [ output-print (word "turtle "   " ticks "   " inertia "  )  ]
       rule-to-use = "pair: uphill with everyone"  [ output-print (word "turtle "   " ticks "   " group-weight "  )  ]
       rule-to-use = "triple: use all three"       [ output-print (word "turtle "   " ticks "   " group-weight "   " inertia "   )  ]
        ; else commands
    [ error (word " unexpected rule-to-use choice: " rule-to-use) ]
   )
end 

to import-landscape  ;; only if local. Won't compile in netlogo-web.
  ifelse ( netlogo-web? = false )
  [
    let msg1 "starting runstring"
    let msg2 " no file selected! "
    let msg3 "Importing image file "
    let msg4 " failed, so generating the image locally"
    let msg5 "generated"
    let msg6 "You asked to import this landscape file: "
    let runstring
       ( word
           " print msg1 "
           " set filechoice user-file "
           " if-else filechoice = false "
           "  [ "
           "     print msg2 "
           "     print (word  msg3 user-file msg4)  "
           "     set landscape-source msg5  "
           "     make-landscape "
           "  ]  "
           "  [  "
           "     print (word msg6 filechoice)     "
           "    import-pcolors filechoice  "
           "    ask  max-one-of patches [pcolor] [set peak-height pcolor]  "
           "    ask patches [ set height pcolor] "
           " ] "
       )
    run runstring
  ]
  [ print "Landscapes can only be imported if this model is downloaded and run locally! "]
end 

to trackwho
  inspect turtle monturtle
end 

to go

    ask patches [ ifelse  ( count turtles-here    > 0 ) [ set pcolor green][set pcolor basepcolor]]
    let mystr88 "Test"

    if  ( netlogo-web? = false )
  [
    run "view2.5d:set-z-scale mystr88 zfactor"
    run "view2.5d:update-all-patch-views"
  ]

  ;; WARNING -- this will not print final output if stopped by interface
  if stop-now? [ print "Stop was requested by a subroutine" stop ]

  if ticks > stop-at-tick [wrap-up-run stop]  ;; prevent runaway models from consuming computer time

  if all? turtles [on-peak?]
  [    wrap-up-run stop ]

  move-turtles
    if stop-now? [ print "Stop was requested by a subroutine." stop ]
    if stop-now? [ error "stop was requested but failed" ]
  update-status

  if braking-pct > 0 [ wait ( braking-pct / 100) ]  ;; slowdown despite top master speed switch

  tick
end 

to wrap-up-run ;; wrap up the entire run
  ;; this is a place-holder
  ;; print "any wrapping up will go here", such as writing output to a file

  if (ticks >= stop-at-tick) [
    print (word "stopped at time limit, ticks = " ticks)
    output-print (word "stopped at time limit, ticks = " ticks)
  ]

  if (stop-now?)   [
    print (word "stopped unexpectedly, ticks = " ticks)
    output-print (word "stopped unexpectedly, ticks = " ticks)
  ]

   if-else (all? turtles [on-peak?])  [
    print (word "stopped when all turtles succeeded, ticks = " ticks)
    output-print (word "stopped when all turtles succeeded, ticks = " ticks)
   ]
   [
    print ( word "count of turtles not yet on the peak: " count turtles with [on-peak? = false] )
    output-print ( word "count of turtles not yet on the peak: " count turtles with [on-peak? = false] )
   ]

   ;; for inertia plot, set the time to 100 and plot the straglers
      if   rule-to-use = "pair: uphill with inertia"   [

            set-current-plot "inertia-influence"
            ;;plotxy inertia ticks

             ask turtles with [on-peak? = false ]
            [
                 let cluster-show 98 + random-float 2
                 plotxy inertia cluster-show  ;
                 output-print   (word   " ? " "        " cluster-show )
            ]
    ]

  ;; for group plot, set the time to 100 and plot the straglers
     if   rule-to-use = "pair: uphill with everyone"   [

            set-current-plot "social-influence"

            ask turtles with [on-peak? = false ]
               [
                  let cluster-show2 98 + random-float 2
                  plotxy empathy cluster-show2 ;
                  output-print   (word   " ? " "        " cluster-show2  "       " 1.0 " (forced) "       )
               ]

       ]
end 

to update-status

 set on-peak-count count turtles with [on-peak?]

;; ======================================================= automater code begins
;;   file-open output-file
;;   file-print (word "turtles on peak: " on-peak-count)
;;======================================================== automater code ends
end 

to-report local-group-center ;; for each agent, vision limited by horizon ( or links ? )
   ;; side-effect:  this sets the global variable my-center
  let sumx 0
  let sumy 0
  let sumx-wealth 0
  let sumy-wealth 0

  let numnearby count turtles with [ (distance myself  )  < horizon]
  print ( word "nearby turtle count " numnearby)
  ask turtles with [ (distance myself  )  < horizon]   [
    set sumx sumx +(pxcor * wealth)
    set sumx-wealth sumx-wealth + wealth

    set sumy sumy +(pycor * wealth)
    set sumy-wealth sumy-wealth + wealth
  ]

  ;; at set-up avoid division by zero
  if-else ( sumx-wealth > 0 )
  [ set sumx sumx / sumx-wealth
    set sumy sumy / sumy-wealth]
  [ set sumx 0  set sumy 0 ]       ;; put centroid in the center on first pass

  report (patch sumx sumy)

  ;report (list sumx sumy)
end 

to-report centroid      ;; compute center of the swarm, weighted by wealth

  ;; side-effect:  this sets the global variable my-center
  let sumx 0
  let sumy 0
  let sumx-wealth 0
  let sumy-wealth 0

  ask turtles [
    set sumx sumx +(pxcor * wealth)
    set sumx-wealth sumx-wealth + wealth

    set sumy sumy +(pycor * wealth)
    set sumy-wealth sumy-wealth + wealth
  ]

  ;; at set-up avoid division by zero
  if-else ( sumx-wealth > 0 )
  [ set sumx sumx / sumx-wealth
    set sumy sumy / sumy-wealth]
  [ set sumx 0  set sumy 0 ]       ;; put centroid in the center on first pass

  set my-center (patch sumx sumy)

  report (list sumx sumy)
end 

; =========== turtle movement commands ===============

to wrap-up-step  ;;    Utility, called by every rule, in every step, in a turtle context
    set wealth height ;   transfer patch parameter to a turtle parameter

    ;; This output relies on the various move steps ONLY being called for
    ;; turtles that were not already at peak height.  Otherwise, this
    ;; will generate way too much output!!

    if  height = peak-height   ;; did we just reach the peak?
      [
        set on-peak? true
        set color green
        set label ""

       (if-else
          rule-to-use = "single: wander"              [ output-print (word   who "        " ticks                        )  ]
          rule-to-use = "single: go-uphill"           [ output-print (word   who "        " ticks                        )  ]
          rule-to-use = "single: find-everyone"       [ output-print (word   who "        " ticks  "       " group-weight    )  ]
          rule-to-use = "pair: uphill with inertia"
        [
            output-print (word   who "        " ticks  "       " inertia         )
            set-current-plot "inertia-influence"
            set-current-plot-pen "default"
            plotxy inertia ticks
        ]
          rule-to-use = "pair: uphill with everyone"
        [
          output-print (word   who "        " ticks  "       " group-weight    )
          set-current-plot "social-influence"
          set-current-plot-pen "default"
          plotxy empathy ticks
        ]
          rule-to-use = "triple: use all three"
         [
            output-print (word   who "        " ticks  "       " group-weight "       " inertia )
            set-current-plot "inertia-influence"
            set-current-plot-pen "default"
            plotxy inertia ticks

            set-current-plot "social-influence"
            set-current-plot-pen "default"
            plotxy empathy ticks
        ]
           ; else commands
          [ error (word " unexpected rule-to-use choice: " rule-to-use) ] )
      ]
end 

to go-wander

    ask turtles with [not on-peak?] [

      set heading heading + random 45
      set heading heading - random 45

      step-or-reverse ( 1 )

      ;;set wealth height
      wrap-up-step
   ]
end 

to step-or-reverse [ size-of-step ]

         set prior-wealth height
         if-else  can-move? size-of-step  [forward (size-of-step * step-size-multiplier)][ set heading heading + 180 forward ( size-of-step * step-size-multiplier) ]

         ifelse ( dynamic-speed? = true )
  [
         ;; following variable step-size control is experimental 14-Oct-2021
         set wealth height
         if ( wealth > maxwealth) [ set maxwealth wealth ]
         ifelse ( wealth > prior-wealth )
             [
                  if ( good-step-count < 0) [set good-step-count 0]
                  set good-step-count ( good-step-count + 1 )
             ]
             [
                    if ( good-step-count > 0) [set good-step-count 0]
                    set good-step-count ( good-step-count - 1 )
             ]
         set step-size-multiplier ( 1 +  ( good-step-count / 5 ) )
         if ( step-size-multiplier > 5 ) [ set step-size-multiplier 5]
         if ( step-size-multiplier < 0.2) [ set step-size-multiplier 0.2 ]
  ]
  [ set step-size-multiplier 1 ]
end 

to-report uphill-heading
    ;; heading is in degrees , 0 to 360
    ;; hard-codes a search radius

    let search-radius 2.5

   ;; ask turtles with [not on-peak?] [
        let old-patch patch-here
        let neighborhood patches with [ distance myself < search-radius ]
        let target max-one-of neighborhood [height ]
        face target             ;; WARNING -- side-effect
        report heading
   ;; ]
end 

to go-uphill
     ;; hard-codes a step size
     let step-size 1

     ask turtles with [not on-peak?] [
     set heading uphill-heading

     step-or-reverse ( 1 )

      wrap-up-step
      ]
end 

to go-find-everyone  ;;  centroid and my-center needs to be refactored

   ;; first, comput the  weighted centroid of all the turtles
   let new-centroid (list 0 0)
   set new-centroid centroid  ;; sets global my-center as side-effect
                              ;; computes new-centroid but only uses the side effect
                              ;; WARNING -- twisted way of simply setting my-center

   ask turtles with [not on-peak?] [

       ;; let old-patch patch-here ;; obsolete??
       face my-center
       step-or-reverse ( 1 )
       wrap-up-step
   ]
end 

to go-uphill-inertia   ;; draft

    ask turtles with [not on-peak?] [

         set label inertia

         let old-patch patch-here ;;  used????

         let heading-uphill uphill-heading

         set heading ( inertia * old-heading) + (1 - inertia) * heading-uphill
         step-or-reverse ( 1 )
         set old-heading heading ;;   this is a turtle-own variable
         wrap-up-step

    ]
end 

to go-use-all-rules    ;; runs but not validated, not even one full walk-through

    ;; first, compute the  weighted centroid of all the turtles
   let new-centroid (list 0 0)
   if ticks > 1 [ set new-centroid centroid ]  ;; can't run on first tick because weath is zero and get division error
   ;;  type "centroid is " show new-centroid

  ask turtles with [not on-peak?] [

    let old-patch patch-here

    ;; let's find what heading goes uphill

    let target max-one-of neighbors [height]
    face target
    let heading-uphill heading

    ;; ok soften that with inertia

           set heading-uphill ( inertia * old-heading) + (1 - inertia) * heading-uphill

         set old-heading heading ;;   this is a turtle-own variable


    face my-center
    let heading-group heading

    set heading (empathy)*(heading-group) + (1 - empathy)*(heading-uphill)
   ;; set heading (group-weight)*(heading-group) + (1 - group-weight)*(heading-uphill)


    step-or-reverse ( 1 )
    set old-heading heading ;;   this is a turtle-own variable

    wrap-up-step
  ]
end 

to go-uphill-everyone  ;;draft

   ;; first, comput the  weighted centroid of all the turtles
   let new-centroid (list 0 0)
   if ticks > 1 [ set new-centroid centroid ]  ;; can't run on first tick because weath is zero and get division error
   ;;  type "centroid is " show new-centroid

  ask turtles with [not on-peak?] [

    let old-patch patch-here

    ;; let's find what heading goes uphill

    let target max-one-of neighbors [height]
    face target
    let heading-uphill heading

    ifelse ( limit-horizon? = true ) [ face local-group-center ] [ face my-center]
    face my-center  ;; <&&&&&&&&&&&&&&&&&&&&&& if we limit horizon I think it can create polarization , split up groups.
    let heading-group heading

    set  my-heading-uphill heading-uphill
    set  my-heading-group heading-group


    if (( heading-uphill > 270) and ( heading-group < 90 )) [ set heading-uphill ( heading-uphill - 360 ) ]
    if (( heading-uphill < 90 ) and ( heading-group > 270 )) [ set heading-group ( heading-group - 360 ) ]


    set heading (empathy)*(heading-group) + (1 - empathy)*(heading-uphill)
   ;; set heading (group-weight)*(heading-group) + (1 - group-weight)*(heading-uphill)


    step-or-reverse ( 1 )
    wrap-up-step

   ]
end 

;================end of turtle movement commands =======

to snapshot   ;;  save a picture of the whole interface to disk,   bare bones draft only
  ;; ask for a file-name
  ;; This should set a directory and base file name then increment a number add .jpg and save silently
  set timestamp date-and-time

  ifelse ( netlogo-web? = true )
  [
      print " export snapshot only works locally "
  ]
  [
     run "export-interface user-new-file"
  ]

  ;; UNCOMMENT the next line to save a snapshot of the image to disk only works locally won't compile netlogo web
  ;; export-interface user-new-file
  ;; print OK
end 

to apologize
  print " that function is not yet working!"
  set stop-now? true
end 

to move-turtles

  if-else leave-a-trail? [ ask turtles [ pen-down ]]   [ ask turtles [ pen-up ]]

  (if-else
  rule-to-use = "single: wander"              [ go-wander          ]
  rule-to-use = "single: go-uphill"           [ go-uphill          ]
  rule-to-use = "single: find-everyone"       [ go-find-everyone   ]
  rule-to-use = "pair: uphill with inertia"   [ go-uphill-inertia  ]
  rule-to-use = "pair: uphill with everyone"  [ go-uphill-everyone ]
  rule-to-use = "triple: use all three"       [ go-use-all-rules   ]
   ; else commands
    [ error (word " unexpected rule-to-use choice: " rule-to-use) ]
   )

  ;;set stop-now? false
end 

to make-landscape
  set patch-count count  patches;
  ask patch -7 -4  [set pcolor 125]  ;; always make at least one hill
  if number-of-hills >= 2 [  ask patch  3 6  [set pcolor 95] ]
  if number-of-hills >= 3 [  ask patch  7 -5  [set pcolor 75] ]

  repeat 15 [ diffuse pcolor 1]  ;; smooth that out somewhat

    if noise?
  [ ask N-of (  noise-density * patch-count) patches [set pcolor pcolor + noise-size]  ]

   repeat 2 [ diffuse pcolor 1]  ;; smooth the noise

  ask  max-one-of patches [pcolor] [set peak-height pcolor]
  ask patches [ set height pcolor]
  ask patches [ set pcolor scale-color red height 0 peak-height ]
end 

to make-turtles

  ; set the turtle color from the user menu
  let use-color green  ;; default
  if turtle-color = "green" [ set use-color green ]
  if turtle-color = "white" [ set use-color white ]
  if turtle-color = "black" [ set use-color black ]
  if turtle-color = "red"   [ set use-color red ]


   create-turtles turtle-count [      ;;  turtle-count is set by a slider
     setxy random-xcor random-ycor
     set on-peak? FALSE
     set color use-color
     set size 2
     set shape turtle-shape
     set wealth 0
     set maxwealth 0
     set good-step-count 0
     set   step-size-multiplier 1.0

    if-else ( randomize-inertia? )  [
      set inertia precision (random-float 1) 2
    ]
    [ set inertia inertia-static ]

     if-else ( randomize-group-weight? )
      [set empathy precision (random-float 1) 2 ]                ;; set to random uniform on [0,1]
      [set empathy group-weight]                                 ;; set in slider
  ]
end 

to help
  ;; UNCOMMENT this section if you have a help file on your local PC

;if-else file-exists? "help-for-goals.txt"
;  [
;    file-open "help-for-goals.txt"
;    while [not file-at-end? ]
;    [print file-read-line]
;    file-close
;  ]
;  [
    print "The help file 'help-for-goals.txt' was not found!"
;  ]
end 

There are 10 versions of this model.

Uploaded by When Description Download
R. Wade Schuette over 2 years ago try again hide view2.5 from web Download this version
R. Wade Schuette over 2 years ago adapted so view2d is hidden to web Download this version
R. Wade Schuette over 2 years ago fixed some headings, add horizon, track Download this version
R. Wade Schuette over 2 years ago removed python, added set rand seed Download this version
R. Wade Schuette over 2 years ago added python to persist random seed Download this version
R. Wade Schuette about 3 years ago commented out local-only code Download this version
R. Wade Schuette about 3 years ago removed export interface option on web Download this version
R. Wade Schuette about 3 years ago removed background image impoort for web Download this version
R. Wade Schuette about 3 years ago removed display comamnds Download this version
R. Wade Schuette about 3 years ago Initial upload Download this version

Attached files

File Type Description Last updated
goal-seeking-boids.png preview Preview for 'goal-seeking-boids' about 3 years ago, by R. Wade Schuette Download

This model does not have any ancestors.

This model does not have any descendants.