Andrè Casalis

Simulation models for economics

Project work on

"Dynamic discovery of static opinions"

 

Here you can find an introduction to the Dynamic discovery of static opinions application.

Full version, video demo

This video shows the full, R-empowered, model at work, but on this page you can also find a specific online applet. Read below to get further details.

R-less version applet

The applet requires Java 5 or higher. Java must be enabled in your browser settings. Mac users must have Mac OS X 10.4 or higher. Windows and Linux users may obtain the latest Java from Oracle's Java site.

powered by NetLogo

view/download model file: dynamic_discovery_of_static_opinions_r-less-version.nlogo

view/download full version R-empowered model file: dynamic_discovery_of_static_opinions.nlogo

Dynamic discovery of static opinions, R-less version

READ ME: WARNINGS

The original version of this model is empowered by the use of the statistical tool R. The online version you are seeing is restricted and modified so to avoid it and thus has some different features: see all the other information in this tab to get further details.
The full version (requiring R) of this model is available at http://eco83.econ.unito.it/terna/casalis/dynamic_discovery_of_static_opinions.nlogo
An online applet of this model, coming with a description and a commentary of the experiment results, can be found at http://eco83.econ.unito.it/terna/casalis/index.htm
To have an idea of how the full version would look like, you may want to refer to a demonstrative video: http://youtu.be/kIxF9pdna40

WHAT IS IT?

This model wants to explore the possibility of using a neural network, implementend in R, to create an artificial intelligence able to recognize the color of agents starting from their features, a list of properties some of which are determined on breed basis.

HOW IT WORKS

The agents roam the world exchanging information with each other. Every time a piece of knowledge is grabbed, it is stored in a common memory system, a matrix keeping track of the various contributions.
Each period, whose lenght is to be set by the user, the neural networks are instructed using the data since gathered and try to label every agent only looking at their properties.

Details on how a neural network actually works may be found at http://eco83.econ.unito.it/terna/simoec13/cmap/annBasics.pdf

R

This model requires R. As already said, a R-less version of the model is also available online here, but the best choice is to download (it’s free) and install R on your computer.

Details on how install R, Rserve and the Rserve extension for NetLogo are available at:

HOW TO USE IT

Basically, hit setup and then go.
Due to the number of possible options, there are quite a few controls customizable by the user, some exclusive to this verion, while others not available.

Available

R-less version only

Full version only

THINGS TO NOTICE

The green color is the residual case; this pushes up the total number of green predictions, along with their goodness.

THINGS TO TRY

DISCLAIMER: some unavailable in this R-less version

There are a lot of options: try them!
Also, experiment with number of relevant variables and with the weight reuse controls; if you are lucky, you may observe the arise of the absolute prejudice, a stable convergence to a certain good prediction ratio never changiong no matter how many data are added.

EXTENDING THE MODEL

Download the full version!

Modify the above mentioned forecast control to set a color actually forecasted only if the result predicted by the neural network is within a given confidence interval and keep track of the errors.

Use Monte-Carlo methods to determine the coefficient of relation between number of rows used and prediction goodness.

Implement a control for the R random seed.

Modify the kind of properties: no more binary values, go with Reals.

ONLINE PRESIDIA

This model has been published online at http://eco83.econ.unito.it/terna/casalis/index.htm, where an online R-less restricted version is available. A working full model video is also available on YouTube

CREDITS

A huge thank you has to go to my instructor and professor, Pietro Terna, without whom nothing of this project would ever saw the light.
He has his online fortress at http://web.econ.unito.it/terna/

COPYRIGHT AND LICENSE

Copyright 2013 Andrè Casalis

CC BY-NC-SA 3.0

This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.

CONTACTS

Andrè Casalis @ casalis.andre@gmail.com

CODE

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                               ;;
;; EXTENSION (rserve and matrix) ;;
;;                               ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

extensions[rserve matrix]


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                                            ;;
;; GLOBALS, BREEDS, TURTLES-OWN and LINKS-OWN ;;
;;                                            ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

globals
[ ;; Counters of rows used for each matrix
  greenFromGreenRows
  greenFromRedRows
  redFromRedRows
  redFromGreenRows
  
  ;; Fixed dimensions of matrix (to be computed)
  greenMatDim
  redMatDim
  
  ;; Percentages of correct predictions (showed in interface)
  greenCorrectPredictionsOfGreen
  greenCorrectPredictionsOfRed
  redCorrectPredictionsOfGreen
  redCorrectPredictionsOfRed
  
  ;; Number of properties of each agent
  numberOfProperties
  
  ;; Matrices of observations (created over-dimensioned and filled step by step)
  redFromRedInfo
  redFromGreenInfo
  greenFromRedInfo
  greenFromGreenInfo
  
  ;; Coefficient used to sed the time interval
  timeControl
  
  ;; Once user-input, now only for code consistency
  reuse-red-weights?
  reuse-green-weights?
] 

breed[reds aRed]      
breed[greens aGreen]

turtles-own[properties seenByGreen seenByRed] ;; Vector of properties and how the agent is seen by the collective intelligencies.
links-own[index value] ;; The position and the value of the information exchanged


;;;;;;;;;;;;;;;;;;;;;;; 
;;                   ;;
;; STARTUP PROCEDURE ;;
;;                   ;;
;;;;;;;;;;;;;;;;;;;;;;;

to startup
  set rnd-seed new-seed
end


;;;;;;;;;;;;;;;;;;;;; 
;;                 ;;
;; SETUP PROCEDURE ;;
;;                 ;;
;;;;;;;;;;;;;;;;;;;;;

to setup
  ca
  if (new-seed-on-setup?) [ set rnd-seed new-seed ]
  if (abs rnd-seed) > 2147483648 [ set rnd-seed new-seed ]  ;; Check the value of the random seed: if out of limits, choose a proper value.
  random-seed rnd-seed             ;; Seed the random number generator.
  ;if (not rserve-init) [ stop ]    ;; Clean connect to R (reset memory, clean all weights) and stop if Rserve is not running NOT USED IN THIS ONLINE VERSION
  set timeControl        1         ;; Used in the GO procedure
  set numberOfProperties 10        ;; Default, modify the parameter to increase the vector
  make-agents    ;; Create agents
  init-matrices  ;; Create matrices full of -1
  reset-ticks
end


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Internal SETUP procedures ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

to init-matrices ;; Create the oversized matrices (to be able to fill them, rather than inserting new rows)   
  set greenMatDim  round (count greens * 20)  ;Dimension of the matrices
  set redMatDim    round (count reds * 20)
  
  set greenFromGreenRows  0    ;; Counters: 0 by default, but clearer and also
  set redFromGreenRows    0    ;; getting rid of problems when "resetup" the model.
  set greenFromRedRows    0
  set redFromRedRows      0
 
;;    Name of the matrix    full of constants  num of rows      num of columns      constant
  set greenFromGreenInfo  matrix:make-constant  greenMatDim  (numberOfProperties + 1)   -1   
  set redFromGreenInfo    matrix:make-constant  greenMatDim  (numberOfProperties + 1)   -1
  set greenFromRedInfo    matrix:make-constant  redMatDim    (numberOfProperties + 1)   -1 
  set redFromRedInfo      matrix:make-constant  redMatDim    (numberOfProperties + 1)   -1
end

to-report rserve-init ;; A clean connection to R (clearing all variables).
  if rserve:isConnected [rserve:close]  ;; No error if Rserve not running
  carefully [ rserve:init 6311 "localhost" ] [user-message "Rserve is not running!" report false] ;; Catch the error, return false ad stop the setup.
  rserve:clear      ;; Clear all the variables (if we want to reuse weights, the matrices from the previous running have to be deleted).
  rserve:eval "library(nnet)" ;; Load the library only once, here.
  report true  ;; All went well.
end

to make-agents
  let numOfGreens ifelse-value (isRandom?)       ;; The total number of turtles is set by user and then 
  [round (howManyTurtles * random-float 1)]      ;; => randomly set the number of green turtles
  [ round (howManyTurtles * greenTurtlesQuota)]  ;; => OR the "set quota" slider is used.
  
  let numOfReds howManyTurtles - numOfGreens     ;; Red turtles number is found by subtraction.
  set-default-shape turtles "person"             ;; They are all Gallifreyans!
  make-reds numOfReds
  make-greens numOfGreens 
end

to make-reds [n]
  create-reds n 
  [ ;; Set color, put randomly in the space e create the properties.
    set color red
    setxy random-xcor random-ycor
    create-properties
    ; On-Line version code only
    set seenByRed ifelse-value (random-float 1 < reds-see-red) [red][green]
    set seenByGreen ifelse-value (random-float 1 < greens-see-red) [red][green]
  ]   
end

to make-greens [n]
  create-greens n 
  [ ;; Set color, put randomly in the space e create the properties.
    set color green
    setxy random-xcor random-ycor
    create-properties
    ; On-Line version code only
    set seenByRed ifelse-value (random-float 1 < reds-see-green) [green][red]
    set seenByGreen ifelse-value (random-float 1 < greens-see-green) [green][red]
  ]   
end

to create-properties  ;; TURTLE ENVIRONMENT: create the vector of properties of each agent
  set properties []      ;; Turtle-own variable
  let numOfRelevant   0 
  let valueOfRelevant 0
  
  ifelse (color = red)                   ;; Determine how many relevant variables there are (on breed basis)  
  [ set numOfRelevant howManyRelevantR ]
  [
    set numOfRelevant howManyRelevantG
    set valueOfRelevant 1                ;; Greens have 1 as relevant value, reds 0 (the default value)
  ] 
  
  repeat (numberOfProperties - numOfRelevant) [ set properties lput (random 2) properties ] ;; Non relevant properties set radomly 
  repeat numOfRelevant [set properties fput valueOfRelevant properties]  ;; Relevant ones setting.
end


;;;;;;;;;;;;;;;;;;
;;              ;;
;; GO PROCEDURE ;;
;;              ;;
;;;;;;;;;;;;;;;;;;

to go 
  move            ;; Simple as it looks like.
  check-neighbors ;; Creation of links conveying data. 
  update-agents   ;; Reading links and updating matrices
  tick
  if (ticks = timeControl * timeInterval)  ;; Check if the time interval is that to map agents.
  [
    set timeControl timeControl + 1
    ;map-world  ;; Internal procedure: map all agents. NOT CALLED IN THE ONLINE VERSION
    stop
  ]
end

to move
  ask turtles[ rt random 360 fd 1 ]
end


;;;;;;;;;;;;;;;;;;;;;;;;;;
; Internal GO procedures ;
;;;;;;;;;;;;;;;;;;;;;;;;;;

to check-neighbors ;; Create links to communicate with other turtles
  ask turtles with [other turtles-here != nobody]
  [ ;; Only the turtles with other agents on the same patch
    let tmpIndex random (numberOfProperties) ;; Return a number [0, numberOfProperties -1]; it's an index, so it's all good.
    let tmpValue item tmpIndex properties    ;; The value in that position.
    create-links-to (other turtles-here)     ;; The same value communicated to all the other agents
    [
      set color [color] of myself  ;; For clarity sake 
      set index tmpIndex           ;; Link-own attribute
      set value tmpValue           ;; Link-own attribute
    ]
  ]
  check-matrices  ;; Prudential control on limit number of rows used
end

to check-matrices
  if (    ;; Control on number of rows already used plus the relevant number of links. 
          ;; Strictly right only if the probability of communication is 1, otherwise prudential.
    (greenFromRedRows +   count (links with [([color] of end2)  = red and color = green])      >= redMatDim - 1) or
    (redFromRedRows +     count (links with [([color] of end2)  = red and color = red])        >= redMatDim - 1) or
    (greenFromGreenRows + count (links with [([color] of end2)  = green and color = green])    >= greenMatDim - 1) or
    (redFromGreenRows +   count (links with [([color] of end2)  = green and color = red])      >= greenMatDim - 1))
  [       ;; Sort of clear-all routine. 
    ;map-world                  ;; To not waste data, use them to map a last time the agents. NOT USED IN THIS ONLINE VERSION
    reset-ticks                 ;; Reset the ticks counter 
    set timeControl          1  ;; Reset the cycle counter
    set greenFromRedRows     0  ;; Reset all counters.
    set redFromRedRows       0
    set greenFromGreenRows   0
    set redFromGreenRows     0
    set greenFromGreenInfo  matrix:plus-scalar (matrix:times-scalar  greenFromGreenInfo 0) -1   ;; Multiply each element times 0 and subtract 1:  
    set redFromGreenInfo    matrix:plus-scalar (matrix:times-scalar  redFromGreenInfo   0) -1   ;; i.e. reset all the values in each matrix to -1
    set greenFromRedInfo    matrix:plus-scalar (matrix:times-scalar  greenFromRedInfo   0) -1 
    set redFromRedInfo      matrix:plus-scalar (matrix:times-scalar  redFromRedInfo     0) -1 
  ]
end

to update-agents    ;; Read links and update the matrices.
  ask turtles with [count my-in-links > 0]
  [ ;; All turtles with incoming links.
    let comm-prob ifelse-value (color = red) [red-comm-prob] [green-comm-prob]   ;; Set the relevant value of communication probability.
    while [count my-in-links > 0] 
    [ ;; Cycle all the links of each turtle.
      let aLinkToMe one-of my-in-links         ;; Select a link.    
      let otherIndex  [index]   of aLinkToMe   ;; Extract the index of the property of the other turtle.
      let otherValue  [value]   of aLinkToMe   ;; Extract the value of the property of the other turtle.
      let otherColor  [color]   of aLinkToMe   ;; Extract the color of the other turtle.
      let myValue item otherIndex properties   ;; The value of the same-index agent property. 
      if ((random-float 1) < comm-prob) [ update-memory otherIndex otherValue otherColor ]  ;; Call the instructions to update memory.
      ask aLinkToMe [ die ]   ;; Delete the link and start over (if there are more of them).
    ] ;; End while
  ]   ;; End ask
end
  
to update-memory [otherIndex otherValue otherColor]
  let dataMatrix ""
  let numOfObs 0    ;; Number of rows used.
  
  ifelse otherColor = color   ;; link color = agent color => info are about the same breed
  [
    ifelse color = red
    [set dataMatrix redFromRedInfo set numOfObs redFromRedRows]  
    [set dataMatrix greenFromGreenInfo set numOfObs greenFromGreenRows]
  ]
  [                           ;; link color != agent color => info about other breed
    ifelse color = red
    [set dataMatrix greenFromRedInfo set numOfObs greenFromRedRows]
    [set dataMatrix redFromGreenInfo set numOfObs redFromGreenRows]
  ]
  
  ;; List of all the agents contributing to the matrix
  let allIDs reverse ( matrix:get-column dataMatrix numberOfProperties )
  
  ;; The row number of agent's last contribution
  let myLastIndex ifelse-value (position who allIDs != false) [length allIDs - 1 - (position who allIDs)] [""] 
  
  ;; The row-values of agent last contribution
  let myLastRow ifelse-value (myLastIndex != "") [matrix:get-row dataMatrix myLastIndex] [""]
  
  ;; Value in to-be-updated position
  let myLastValue ifelse-value (myLastRow != "") [item otherIndex myLastRow] [""]
  
  ifelse ( (myLastIndex = "") or   ;; No row to update at all OR already updated (so, not -1) with a different value 
         ( (myLastValue != -1 ) and (myLastValue != otherValue) ) )
  [
    let tmpResults (fill-new-row myLastRow otherIndex otherValue dataMatrix numOfObs) ;; Reporter: report a list [updatedMatrix updatedCounter]
    set dataMatrix  first tmpResults   ;; Get the filled matrix
    set numOfObs    last  tmpResults   ;; Get the updated counter
  ] 
  [ matrix:set dataMatrix myLastIndex otherIndex otherValue ] ;; Update last row with the new value, no new row inserted.
 
   ifelse otherColor = color  
  [                    ;; link color = agent color => info about same breed
    ifelse color = red
    [set redFromRedInfo dataMatrix set redFromRedRows numOfObs]
    [set greenFromGreenInfo dataMatrix set greenFromGreenRows numOfObs]
  ]  
  [                    ;; link color != agent color => info about other breed
    ifelse color = red
    [set greenFromRedInfo dataMatrix set greenFromRedRows numOfObs]
    [set redFromGreenInfo dataMatrix set redFromGreenRows numOfObs]
  ]
end

to-report fill-new-row [myLastRow otherIndex otherValue dataMatrix numOfObs]

  if (myLastRow != "") 
  [     ;; There is a previous contribution, so I copy those values in the new used row.  
   while [length myLastRow > 0]  
   [    ;; I update each value of the new row with the last values
     let tmpIndex (numberOfProperties + 1) - (length myLastRow)  ;; Iterate from 0 to 10 (because with length 0 while-cycle skips)
     matrix:set dataMatrix numOfObs tmpIndex (first myLastRow)   ;; Update the value with the first element of the list.
     set myLastRow butfirst myLastRow                            ;; Get rid of the first element of the list.
   ] ;; End while
  ]  ;; End if
  ;; There is no a previous row to copy, I just fill-in a new one from scratch
  matrix:set dataMatrix numOfObs otherIndex otherValue   ;; Update the property of interest.
  matrix:set dataMatrix numOfObs numberOfProperties who  ;; Update the id of the agent (superflous if the new row is the copy of a previous row.)
  
  report list dataMatrix (numOfObs + 1)         ;; Report the values as a list.
end


;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                        ;;
;; SEGREGATION PROCEDURES ;;
;;                        ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  
to move-from-different   ;; Agents want to put space between them and those they see as different
  let greenTurtlesToBeMoved greens with [ any? (other turtles with [seenByGreen != green] in-radius 3) ]  ;; Greens seeing reds near them.
  let redTurtlesToBeMoved reds with [ any? (other turtles with [seenByRed != red] in-radius 3) ]          ;; Reds seeing greens near them.
  let turtlesToBeMoved (turtle-set greenTurtlesToBeMoved redTurtlesToBeMoved)      ;; Create a unique agentset

  let i 0   ;; Safety switch: if there are labelling errors, the while cycle would be and infinite loop.
  while [count turtlesToBeMoved > 0 and i < 1000][
    ask turtlesToBeMoved
    [
      let otherTurtle ifelse-value (color = green)
      [ one-of other turtles in-radius 3 with [seenByGreen != green] ]
      [ one-of other turtles in-radius 3 with [seenByRed != red] ]
      if (otherTurtle != nobody) [ face otherTurtle rt 180 fd 1 ]    ;; Face the opposte direction of one of the unwanted turtles and go away.
    ] ;; End ask
    set greenTurtlesToBeMoved greens with [ any? (other turtles with [seenByGreen != green] in-radius 3) ] 
    set redTurtlesToBeMoved reds with [ any? (other turtles with [seenByRed != red] in-radius 3) ]
    set turtlesToBeMoved (turtle-set greenTurtlesToBeMoved redTurtlesToBeMoved)      ;; Update the set of unhappy turtles.
    set i i + 1  ;; Rise the loop counter
  ] ;; End while
 print (word "Happy agents are the " ( (precision ((howManyTurtles - count turtlesToBeMoved) / howManyTurtles) 2) * 100 ) "% of the total")  ;; To have an idea.
end

to move-to-similar   ;; Run to turtles seen as similars 
  let greenTurtlesToBeMoved greens with [ not any? (other turtles with [seenByGreen = green] in-radius 1) ]  ;; Lonely greens
  let redTurtlesToBeMoved reds with [ not any? (other turtles with [seenByRed = red] in-radius 1) ]          ;; Lonely reds
  let turtlesToBeMoved (turtle-set greenTurtlesToBeMoved redTurtlesToBeMoved)      ;; Create a unique agentset

  let i 0   ;; Safety switch: if there are labelling errors, the while cycle would be and infinite loop.
  while [count turtlesToBeMoved > 0 and i < 1000][
   ask turtlesToBeMoved
   [
     let otherTurtle ifelse-value (color = green)
     [ min-one-of other (turtles with [seenByGreen = green]) [distance myself] ]
     [ min-one-of other (turtles with [seenByRed = red]) [distance myself] ]
     if (otherTurtle != nobody) [ face otherTurtle fd 1 ]    ;; Face the nearest seen-as-similar turtle and move towards it. 
   ] ;; End ask
   set greenTurtlesToBeMoved greens with [ not any? (other turtles with [seenByGreen = green] in-radius 1) ] 
   set redTurtlesToBeMoved reds with [ not any? (other turtles with [seenByRed = red] in-radius 1) ]
   set turtlesToBeMoved (turtle-set greenTurtlesToBeMoved redTurtlesToBeMoved)
   set i i + 1  ;; Rise the loop counter
 ] ;; End while
end


;;; ALL THE CODE BELOW IS UNUSED IN THIS ONLINE REDUCED VERSION OF THE MODEL

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                                         ;;
;; INTERNAL: R-RELATED CODE AND PROCEDURES ;;
;;                                         ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

to map-world  ;; Instrumental, call the breed-specific update procedures and update the monitors.
  if(redFromRedRows > 0) and (greenFromRedRows > 0) [ redBreed-mapping ]         ;; Useful if the probability of communicate is very low and
  if (greenFromGreenRows > 0) and (redFromGreenRows > 0) [ greenBreed-mapping ]  ;; the time-span minimum: a matrix may have zero contributions
  update-percentages
end


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Find weights for each breed ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

to find-red-weights
  ;; Transform matrices in lists
  let tmpRedFromRed      matrix:to-column-list (matrix:submatrix redFromRedInfo      0 0 redFromRedRows numberOfProperties) 
  let tmpGreenFromRed    matrix:to-column-list (matrix:submatrix greenFromRedInfo    0 0 greenFromRedRows numberOfProperties) 
  
  rserve:putlist   "redFromRed" tmpRedFromRed
  rserve:putlist   "greenFromRed" tmpGreenFromRed
  ;; Break in two steps the creation of the input matrix.
  rserve:eval      "redInput1 <- matrix(unlist(greenFromRed), ncol=10)"
  rserve:eval      "redInput2 <- matrix(unlist(redFromRed), ncol=10)"
  rserve:eval      "redInput <- rbind(redInput1, redInput2)"
  rserve:eval      ( word "redOutput <- cbind(c(rep(c(1,0)," greenFromRedRows "),rep(c(0,1)," redFromRedRows ")))" )
  rserve:eval      "redOutput <- matrix(redOutput,ncol=2,byrow=TRUE)"
  ;; Implement the reuse of weights.
  let tmpCodeStr1 ""
  let tmpCodeStr2 "redWeights <- nnet(x=redInput, y=redOutput, size=6, maxit=1000, trace=FALSE)"
  let tmpCodeStr3 ""
  
  if (reuse-red-weights?)
  [   ;; Create a control in R, so that even the first cycle is fine (because there are no old weights).
    set tmpCodeStr1 "if(exists('redWeights')) { redWeights <- nnet(x=redInput, y=redOutput, Wts=redWeights$wts, size=6, maxit=1000, trace=FALSE) }else{"
    set tmpCodeStr3 "}"
  ]
  rserve:eval (word tmpCodeStr1 tmpCodeStr2 tmpCodeStr3)  ;; Create the weights -red breed.
end

to find-green-weights
  ;; Transform matrices in lists
  let tmpGreenFromGreen  matrix:to-column-list (matrix:submatrix greenFromGreenInfo  0 0 greenFromGreenRows numberOfProperties)  
  let tmpRedFromGreen    matrix:to-column-list (matrix:submatrix redFromGreenInfo    0 0 redFromGreenRows numberOfProperties) 

  rserve:putlist   "greenFromGreen" tmpGreenFromGreen
  rserve:putlist   "redFromGreen" tmpRedFromGreen
  ;; Break in two steps the creation of the input matrix.
  rserve:eval      "greenInput1 <- matrix(unlist(greenFromGreen), ncol=10)"
  rserve:eval      "greenInput2 <- matrix(unlist(redFromGreen), ncol=10)"
  rserve:eval      "greenInput <- rbind(greenInput1, greenInput2)"
  rserve:eval      ( word "greenOutput <- cbind(c(rep(c(1,0)," greenFromGreenRows "),rep(c(0,1)," redFromGreenRows ")))" )
  rserve:eval      "greenOutput <- matrix(greenOutput,ncol=2,byrow=TRUE)"
  ;; Implement the reuse of weights.
  let tmpCodeStr1 ""
  let tmpCodeStr2 "greenWeights <- nnet(x=greenInput, y=greenOutput, size=6, maxit=1000, trace=FALSE)"
  let tmpCodeStr3 ""
  
  if (reuse-green-weights?)
  [   ;; Create a control in R, so that even the first cycle is fine (because there are no old weights).
    set tmpCodeStr1 "if(exists('greenWeights')) { greenWeights <- nnet(x=greenInput, y=greenOutput, Wts=greenWeights$wts, size=6, maxit=1000, trace=FALSE) }else{ "
    set tmpCodeStr3 "}"
  ]
  rserve:eval (word tmpCodeStr1 tmpCodeStr2 tmpCodeStr3)  ;; Create the weights -green breed.
end 


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Map the agents on breed basis ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

to redBreed-mapping
  find-red-weights
  ask turtles
  [
    rserve:putlist "tmpToBePredicted" properties
    let tmpRes rserve:get "predict(redWeights, unlist(tmpToBePredicted))"     ;; Predict and get the result.
    set seenByRed ifelse-value ((first tmpRes) < (last tmpRes)) [red][green]  ;; Store the result in the "As Reds see me" attribute.
    ;set seenByRed "tmpRes"  
  ]
end

to greenBreed-mapping
  find-green-weights
  ask turtles
  [
    rserve:putlist "tmpToBePredicted" properties
    let tmpRes rserve:get "predict(greenWeights, unlist(tmpToBePredicted))"     ;; Predict and get the result.
    set seenByGreen ifelse-value ((first tmpRes) < (last tmpRes)) [red][green]  ;; Store the result in the "As Greens see me" attribute.
    ;set seenByRed "tmpRes"  
  ]
end


;;;;;;;;;;;;;;;;;;;
; Update monitors ;
;;;;;;;;;;;;;;;;;;;
 
to update-percentages ;; % of correct predictions for each breed.
  set greenCorrectPredictionsOfGreen  (count greens  with [color = seenByGreen])  /  (count greens)  * 100
  set greenCorrectPredictionsOfRed    (count reds    with [color = seenByGreen])  /  (count reds)    * 100
  set redCorrectPredictionsOfGreen    (count greens  with [color = seenByRed])    /  (count greens)  * 100
  set redCorrectPredictionsOfRed      (count reds    with [color = seenByRed])    /  (count reds)    * 100
end



;;;;;;;;;;;;;;;;;
;; END OF CODE ;;
;;;;;;;;;;;;;;;;;