Farmer Social Psychology (iEMSs2012)

Farmer Social Psychology (iEMSs2012) preview image

1 collaborator

Jm1_vsm James Millington (Author)

Tags

farmer social psychology 

Tagged by Qian li about 10 years ago

farming 

Tagged by James Millington over 12 years ago

psychology 

Tagged by James Millington over 12 years ago

social 

Tagged by James Millington over 12 years ago

Visible to everyone | Changeable by the author
Model was written in NetLogo 4.1.2 • Viewed 1499 times • Downloaded 63 times • Run 0 times
Download the 'Farmer Social Psychology (iEMSs2012)' modelDownload this modelEmbed this model

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


1. PURPOSE

This model is for the exploration of individuals_ self-identity change. The model is developed in the context of theory outlined in Stryker and Burke (2000) and Burton and Wilson (2006). In particular, it is intended to be used to examine and investigate questions regarding farmer self-identity, structure-agency, and the _temporal discordance_ in the transition towards a post-productivist agricultural regime (Burton and Wilson 2006).

2. ENTITITES, STATE VARIABLES, AND SCALES

The model represents agents that have a self-identity composed of four sub-identities in an identity standard; Producer, Diversifier, Conservationist and Agri-business. Each of these sub-identities has a salience towards the overall agent identity. The total salience for all four sub-identities equals 1.0 with values for each sub-identity denoting its relative importance towards overall agent identity. Salience values are held in a list named id-standard.

Agents express their identity through behaviours. Each behaviour represents a sub-identity, and hence there are four possible behaviours that agents can express. In the NetLogo version of the model these behaviours are manifested as patches that compose the agents _farm_ (an agentset named behaviours-expressed). The maximum number of expressed behaviours (i.e. patches) an agent can own is 20. The minimum number is given by minimum-behaviours (in version 1 this is uniform across all agents and has a default value of 10). Each patch has a behaviour variable which is the behaviour expressed it represents.

Agents monitor the difference between their identity, their expressed identity and the expressed identities of other agents in their social network. An agent_s expressed identity is represented as a standard, in the same format as id-standard and is named id-expressed. The social network is the set of agents that a given agent can observe the id-expressed of. The mean expressed identity of an agent_s social network is thus also represented as a standard, named id-expressed-social. The cumulative difference between id-standard and id-expressed is held in each timestep by the id-error-behaviour variable, and the cumulative difference between id-standard and id-expressed-social is held by the id-error-social variable. For an agent_s social network, the extent to which agents connected to a given agent are in turn linked to each other is enumerated by the agent_s cluster-coefficient.

At each timestep agents attempt to minimise id-error-behaviour or id-error-social depending on whether the agent was able to modify their expressed behaviours. Agents may not be able to modify their expressed behaviour because of resource constraints. These resource constraints are determined by the value agents can gain from expressing each behaviour (uniform across the simulated world), the costs of exhibiting behaviours (uniform across the simulated world), the yield agent-variable (can be uniform for all agents or vary across the simulated world) and whether an individual agent is able to express the Agri-business sub-identity (indicated by the available-A agent-variable). Together, for each agent the value of these variables determines how much profit and agent can turn in a given timestep and contributes to an agent_s wealth. If in anytime step an agent_s wealth becomes negative, they are removed from the simulation.

Representation of space and time are abstract and not intended to represent any real units.

3. PROCESS OVERVIEW AND SCHEDULING

In each timesteps agents execute the following steps:

i) Update behaviours-expressed;

ii) Update id-error-behaviour (as id-expressed may have changed in step i);

iii) Potentially add links to other agents who have changed their behaviour in a similar manner (in this timestep);

iv) Update id-expressed-social and id-error-social (as the social network, and the behaviours expressed by it, may have changed in step iii and step i respectively);

v) Adjust id-standard to reduce id-error-behaviour or id-error-social;

vi) Update id-error-behaviour (because id-standard may have changed in step v);

vii) Potentially remove links to agents that no longer share a similar identity (because id-standard may have changed in step v);

viii) Update id-error-social (because id-standard may have changed in v and social network may have changed in step vii).

Agents may update their behaviours-expressed (step i) using one of three strategies depending on their circumstances. First, agents may update behaviour to maximising profit. Second, agents may update their behaviour to minimise id-error-behaviour but ensuring that profit is > 0 (satisficing). Third, agents may update their behaviour to minimise id-error-behaviour with no regard for income (this third strategy is employed when values and costs are not represented in the model). If the Agri-business sub-identity has either the greatest or second-greatest value in an agent_s id-standard, the agent will maximise profit, otherwise the agent will satisfice. Profit is calculated as income _ costs. Income is set by the user and in the case of the Producer behaviour weighted (multiplied) by the yield of each agent. Costs are uniform for all behaviours (at 0.5 per expressed behaviour). In each timestep agents are able to make only a single behaviour change (i.e. change the behaviour of only one patch in behaviours-expressed). Agents identify the most appropriate combination of behaviours by evaluating all possible swaps in behaviour. Agents also consider removing an expressed behaviour, and consider adding a behaviour if able to express the Agri-business sub-identity (i.e. available-A is true). If no change improves profit or reduces id-error-behaviour (depending on the strategy), no changes in behaviour are made.

If a change in behaviour is made, agents must visit the meeting-point corresponding with the behaviour change they have made (if the user has set meeting-point? on). For example, if the agent has changed a Producer behaviour to a Conservationist behaviour, they must visit the conservationist meeting point. There is a single conservationist meeting point and a single diversifier meeting point in the simulated world. There may be a single or multiple producer meeting points (multiple if multiple-meeting-points? is set on). If there are multiple producer meeting points, they are positioned in each corner of the world and agents go to the meeting point nearest to them. While at the meeting point, agents make a reciprocal link with a randomly selected agent also at the meeting-point at that time (i.e. the agents each become a member of the other_s social network, step iii).

After updating id-expressed-social and id-error-social (step iv), agents adjust their id-standard to reduce id-error-behaviour or id-error-social (step v). If a change in behaviour was made (or no change was made because id-error-behaviour = 0 and profit > 0) id-standard is updated reduce id-error-social. However, if no change in behaviour was made (and id-error-behaviour > 0), id-standard is updated to reduce id-error-behaviour.

After updating id-error-behaviour (step vi, because id-standard may have changed in step v), agents potentially remove links to agents that no longer share a similar identity (because id-standard may have changed in step v). Agents cut outgoing links (to the agents they observe) if the most represented behaviour in the observed id-expressed is not also the highest salience in the observers_ id-standard or the most represented in their own id-expressed. Finally, agents update id-error-social (because id-standard may have changed in v and social network may have changed in step vii).

4. DESIGN CONCEPTS

Basic principles.

The basic principles underlying the design of agent identity and identity change can be found in Stryker and Burke_s (2000) review of identity theory. The motivation comes from the issues and hypothesised farmer self concepts discussed in Burton and Wilson (2006). In particular, the four identities represented here correspond to those discussed by Burton and Wilson (2006).

Burton and Wilson (2006, p. 96) discuss the difference between the importance of agency and structure for the P/PP/MF; "Human _agency_ (e.g. farmers in the context of our study) is, thereby, expressed through social systems (e.g. farming culture), beliefs, attitudes and identities (e.g. occupational or religious identities), while _structure_ is based on rules (e.g. agricultural policy; politics), resources (e.g. farmland) or other exogenous forces (e.g. the wider political economy of farming) influencing farmers_ actions and thought."

In this model, agency is represented through the expression of farming culture (farmers' identity standards and interaction and change in those standards) through abstract 'behaviours'. Structure can be represented by setting values for behaviours, specifying farmer yield values, or restricting what behaviours can be expressed by farmers.

Hence Burton and Wilson (p.97) argue that, "if the implied linearity in the P/PP/MF model was true (i.e. transition from productivism to post-productivism to multifunctional agricultural regimes as highlighted above), it could be hypothesised that both structure (e.g. agricultural policies, rural political economy) and agency (farmers_ identities and _farming culture_) would _move along_ the P/PP/MF spectrum at the same pace and in the same manner."

They therefore set out the following aims for their paper; "First, we wish to incorporate structure_ agency concepts into theorisations of agricultural change in order to plug the existing gap in our understanding of the postulated P/PP/MF transition. Second, using social psychology theory, we will investigate whether farming identities have moved towards _post-productivism_ or even _multifunctionalism_ in order to test the assumption that rural agency is moving according to the same patterns and pace as agricultural/rural structure."

The former aim is the basis of the modelling approach taken here. It is acknowledged that "it is difficult to predict if and how the seemingly entrenched productivist self-concepts of farmers in the UK (as well as in Europe, advanced economies as a whole, and even in economically less developed countries (cf. Wilson and Rigg, 2003)) are likely to change." (Burton and Wilson 2006, p.111) and prediction of this type is expressly not the objective of this modelling. Rather the objective is to explore dynamics and scales of potential change in self-concepts and expressed behaviours through the investigation of a logically rigorous representative framework (i.e. the simulation model).

Emergence.

Expressed behaviours and identity standards are expected to vary across the simulated world in response to variation in values, costs, social networking rules and yield distribution.

Adaptation.

Agents _adapt_ to their environment by modifying their identity standard and changing their expressed behaviour. In turn, this creates structure for other agents as they perceive the behaviour through their social network.

Objectives.

Agents aim to reduce their difference between their identity standard and both their expressed identity and the mean expressed identity of agents in their social network, while ensuring wealth does not become negative.

Learning.

Agents have no capacity to learn.

Prediction.

Agents have no capacity to predict future neighbours_ expressed behaviour or values and costs. Agents also have no memory about the past.

Sensing.

Agents are able to sense the id-expressed of their social network and the values different behaviours will accrue them.

Interaction.

Agents interact only by adding or removing one another from their social network, and then by observing the expressed identity of those agents within their social network.

Stochasticity.

When at meeting points, agents randomly select other agents at the meeting point to add to their social network. When checking if an expressed behaviour should be changed, behaviours are checked in a random order _ if two different behaviour changes result in the same id-error or profit the first change checked is retained.

Collectives.

Agents create their own social networks (other than their initial neighbours as specified by initial-social-network) _ the observations of the expressed identities of this social network in part influences agents_ identity standard and expressed identities.

Observation.

Data for all individual agents in the world can exported in each timestep by setting the export-turtle-data? switch to _on_. Fields in the data table exported are: tick (timestep), Agent (id number), id-error-behaviour, id-error-social, wealth, profit, yield, count-contacts (number of other agents in the agent_s social network), cluster-coeff (cluster coefficient), id-standard-P, id-standard-D, id-standard-C, id-standard-A, id-expressed-P, id-expressed-D, id-expressed-C, id-expressed-A, count-behaviours (total number of behaviours expressed), behaviour-available-P, behaviour-available-D, behaviour-available-C, behaviour-available-A. Data are exported to files named IdentityChange_AgentDataXX.csv, where XX is a unique id number. Files are in comma separated value format. Data in plots can also be exported at the end of a model run.

5. INITIALIZATION

At initialization, the number of agents created is set by the number-of-agents chooser. Each of these agents is assigned an id-standard and an agentset of behaviours-initial patches. Agents' id-standard can be uniform across all agents (set initial-standards chooser to _Homogeneous_ and set values for each behaviour using id-standard-X sliders), vary at random between agents (set initial-standards chooser to _Random_) or vary between agents using id-standard-X sliders as the mean of a normal distribution for random sampling (set initial-standards chooser to _Distribution_; standard deviations of distributions are 0.1 and if corresponding slider is set 0 that behaviour will always be zero in agents_ initial identity standard). Expressed behaviours of agents can be set to identically match their id-standard (i.e. minimise id-error, set expressed-matches-standard? to on). If expressed behaviours of agents do not match their id-standard, expressed behaviours can vary between agents in the same ways as initial identity standard by selecting the corresponding value in the initial-expressed chooser.

Agents_ yield values can be uniform across all agents with value 1.0 (set variable-yield? chooser to _No_), can be random between agents with values between 0.5 and 1.0 (set variable-yield? chooser to _Random_) or can be set according to the spatial distribution of yield across the world (set variable-yield? chooser to _From Map_). Four different spatial distributions of yield can be used: 1) spatially uniform with value 0.75 (set yield-map to _Uniform_), 2) continuously increase from a value of 0.5 at the far left of the world to a value of 1.0 at the far right of the world (no variation from top to bottom of the world, set yield-map to _Gradient_), 3) four different values (0.5, 0.66, 0.83 and 1.0) uniform within the four quadrants of the world (set yield-map to _Quadrant_), 4) four different values (0.5, 0.66, 0.83 and 1.0) alternating across a grid, of which each grid cell is 1/10th of the world width and world height (set yield-map to _Grid_). The spatial distribution of yield across the world can be viewed by setting display-yield? on and clicking the update-display button.

Initially, the wealth variable of agents has a value 25, and profit, income and costs have values of zero.

Agents_ initial social networks can contain all other agents in the world (set initial-social-network chooser to _All_), can contain a random selection of agents, the number of which is sampled from normal distribution with mean of five and standard deviation of two (set initial-social-network chooser to _Random_), or can be limited to only immediate neighbours in space, either the eight in the Moore neighbourhood (set initial-social-network chooser to _Moore Neighbours_) or the four in the von Neumann neighbourhood (set initial-social-network chooser to _vonNeumann Neighbours_). Agents_ social networks can be shown on the world by setting the show-links? switch on and the show-agent-links slider to the value of the number-of-agents. To view the links of a single agent, change the show-agent-links slider value to the id of the desired agent.

Next, for each agent, id-expressed, id-expressed-social, id-error-behaviour, id-error-social, and cluster-coefficient are calculated. Values of last-id-error-social and last-id-error-behaviour are set to zero. Agents_ behaviours-available are set for all four behaviours from the available-X sliders if the use-values? switch is off. If use-values? is on, the available-A slider is used to set the agri-business behaviour only.

If the scenarios-from-file? switch is on input data are read from file (see below) and corresponding values set for the first timestep.

6. INPUT DATA

Users can specify input files for scenarios of values through time or behaviour availability through time and between agents. To use these set scenario-from-file? on. If use-values? is on file provided must be for values with filename in the format ValuesScenarioXX.txt where XX is the value specified by the scenario-id slider. If use-values? is false scenarios are for behaviours available and b-a_uniformAgents and b-a_uniformTime switches are used. If b-a_uniformAgents is on, file behaviours-available_uniformAgentsXX.txt will be used; if b-a_uniformTime is on, file behaviours-available_uniformTimeXX.txt will be used; if both are off, behaviours-available_allXX.txt will be used (in each case XX is specified by the scenario-id slider). Examples of the format each of these files should take can be found at http://www.landscapemodelling.net

7. REFERENCES

Burton, R.J.F. and G.A. Wilson (2006) Injecting social psychology theory into conceptualisations of agricultural agency: Towards a post-productivist farmer self-identity? Journal of Rural Studies 22 95_115

Stryker S. and P.J. Burke (2000) The Past, Present, and Future of an Identity Theory Social Psychology Quarterly 63(4) 284-297

Comments and Questions

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

Click to Run Model

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                                                                              ;;
;;                Agricultural Identity Change, February 2012                   ;;
;;                                                                              ;;
;;  Code licenced by James D.A. Millington (http://www.landscapemodelling.net)  ;;
;;  under a Creative Commons Attribution-Noncommercial-Share Alike 3.0          ;;
;;  Unported License (see http://creativecommons.org/licenses/by-nc-sa/3.0/)    ;;
;;                                                                              ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



;;This model version accompanies and is described in Millington [2012] Using social psychology theory for modelling farmer decision-making,
;;International Environmental Modelling and Software Society (iEMSs) 2012 International Congress on Environmental Modelling and Software
;;Managing Resources of a Limited Planet, Sixth Biennial Meeting, Leipzig, Germany, R. Seppelt, A.A. Voinov, S. Lange,  D. Bankamp  (Eds.)
;;http://www.iemss.org/society/index.php/iemss-2012-proceedings
;;That document also contains an ODD description of the model.


  
  
globals 
[
  turtle-output-filename         ;filename for turtle-data output file
  values-scenario-filename       ;filename for values scenario file 
  behaviours-scenario-filename   ;filename for behaviours scenario file
  interface-filename             ;filename to output screenshot of interface to

  scenario-values-provided       ;number of timesteps (ticks) values have been provided for (so simulation stops if necessary)
  values-scenario-list           ;list of lists - for each timestep (ticks) a list of values for P D and C

  line-drawer                    ;a single use line-painter turtle for drawing boundary of 'farm' 
  
  production-meeting-points      ;patch where turtles move after adding a P behaviour - will potentially meet new contacts here
  conservation-meeting-point     ;patch where turtles move after adding a C behaviour - will potentially meet new contacts here
  diversification-meeting-point  ;patch where turtles move after adding a D behaviour - will potentially meet new contacts here 
  
  added-conservation             ;turtle-set containing turtles to sent to conservation-meeting-point
  added-production               ;turtle-set containing turtles to sent to production-meeting-point
  added-diversification          ;turtle-set containing turtles to sent to diversification-meeting-point
  
  network-density                ;density of social network
  mean-cluster-coefficient       ;mean cluster coefficients of all turtles
]

turtles-own 
[   
  id-standard              ;list containing 4 values (salience of each identity)
                           ;position 0 = id P (producer)
                           ;position 1 = if D (diversifier)
                           ;position 2 = id C (conservationsist)
                           ;position 3 = id A (agri-business)
  
  id-error-behaviour       ;difference between current id-expressed and id-standard - cumulative difference between salience for each identity 
  last-id-error-behaviour  ;id-error-behaviour in previous tick
     
  id-error-social          ;difference between current my id-standard and my social network's mean expressed behaviour - cumulative difference between salience for each identity 
  last-id-error-social     ;id-error-behaviour-social in previous tick 
  
  behaviour-change         ;has expressed behaviours changed this timestep? (true/false)
  behaviours-expressed     ;list of patches containing my expressed behaviours (list not agentset so that can be ordered)
  id-expressed             ;list containing proportion of each expressed behaviour (to compare to id-standard)
 
  behaviours-available     ;list of available behaviours for this tick
  behaviours-available-lists ;list of lists of behaviours available for agents
  minimum-behaviours       ;the minimum number of behaviours I can express
  
  id-expressed-social      ;mean of expressed behaviours of contacts (list of proportions, one for each behaviour)
  
  homestead                ;location where agent 'lives'
  yield                    ;weight for value returned from value-P (i.e. value = yield * value-P)
  income                   ;income in this timestep
  wealth                   ;current wealth accumulated
  profit                   ;profit for this timestep (should equal income - costs)
  costs                    ;costs for this timestep 
  have-visited-meeting-point? ;did I visit a meeting point this timestep (true/false)
  cluster-coefficient      ;my cluster coefficient
  
  neighbours-list          ;holds id of original neighbours for Moore and vonThunen social networks (so they can be prevented from being removed)
  
]

patches-own 
[ 
  behaviour    ;behaviour I am expressing
  agent-who    ;who of turtle I belong to
  patch-yield  ;as for turtle variable 'yield' - in some setup instances the agent gets their yield value from their homestead patch
]

breed [ line-painters line-painter ] ;for drawing the 'farm' boundary

line-painters-own [ lp_who ]         ;for drawing the 'farm' boundary

to setup
 
 ca 
 clear-output
 
 random-seed seed
 
 ask patches 
 [ 
   set pcolor white 
   set agent-who nobody
   set behaviour nobody
 ]
 
 check-sliders
 check-behaviours-available
 setup-filenames
  
 setup-yield
 setup-turtles 

 draw-behaviours-boundaries
 
 ask turtles 
 [ 
   set-id-expressed-social
   calc-cluster-coefficient 
 ]
 
 setup-meeting-points 
  
 if(scenario-from-file? = true and use-values? = true)
 [
   type "Reading data from file..."
   read-values-from-file
   update-values-from-file
   set scenario-values-provided length values-scenario-list 
   print "done."
 ]
 
 
 re-display
 do-plots
end 

to go
  
  set added-conservation nobody
  set added-production nobody
  set added-diversification nobody
  ask turtles [ set have-visited-meeting-point? false ]  
  
  ask turtles 
  [ 
    set-behaviour
    set-id-error-behaviour 
  ]
    
  if(count turtles = 0) [ stop ] ;turtles are killed in set-behaviour if wealth < 0 so check here if there are any turtles to simulate
      
  if(meeting-point?)
  [
    ;visiting meeting points if agents have changed behaviour
    visit-meeting-point added-production 0
    visit-meeting-point added-diversification 1
    visit-meeting-point added-conservation 2
  ]
  
  calc-network-density
  ask turtles [ calc-cluster-coefficient ]
  
  ask turtles
  [  
    if(scenario-from-file? and not b-a_uniformTime and use-values? = false) [ set-year-behaviours-available ] ;if behaviours-available set by user and changes in time (uniform across agents or not), update for this year
    
    set-id-expressed-social
    set-id-error-social
    
    set-id-change
    
    set-id-error-behaviour
  ]    

  ask turtles 
  [ 
    if(remove-contacts? = true ) [ remove-contacts ] 
    set-id-error-social
  ]
    
  re-display  
  do-plots
   
  ;initial data output
  if(ticks = 0 and export-data? = true) [ export-turtle-data turtle-output-filename ]
  
  tick
  
  ;read next year's values if necessary
  if(scenario-from-file? = true and use-values? = true) 
  [ 
    if(ticks = scenario-values-provided) [ stop ]
    update-values-from-file 
  ]
 
  ;data output
  if(export-data? = true) [ export-turtle-data turtle-output-filename]  
end 

to setup-turtles
 
 ;distribute turtles in the world 
 let side sqrt(number-of-agents)  ;number of turtles on one side of the grid
 
 let odd false
 if(side mod 2 > 0) [ set odd true ]
 
  while[count turtles < number-of-agents]
  [    
    let my-xcor 0
    let my-ycor 0
    
    ;odd sides
    let gap-x ((world-width / 2) - 1 ) * (1 / ((side / 2) + 0.5)) ;this is the gap in pixels between each turtle on each side of the grid
    let gap-y ((world-height / 2) - 1 ) * (1 / ((side / 2) + 0.5)) 

    let half-side floor(side / 2)
    let this-x -1 * half-side
    let this-y -1 * half-side
    
    ;grid turtle locations 
    while[this-x <= half-side]  ;iterate through the positions on the grid
    [
      while[this-y <= half-side]
      [
        
        if(odd = true or (odd = false and this-y != 0 and this-x != 0))   ;skip central row if side is even
        [  
          ;work out the co-ordinates of that location
          set my-xcor floor(gap-x * this-x)
          set my-ycor floor(gap-y * this-y)
          
          ask patches with [pxcor = my-xcor and pycor = my-ycor]
          [
            sprout 1
            [
              set shape "circle"
              set color black
            ]
          ]
        ]
     
        set this-y this-y + 1
      ]
      
      set this-x this-x + 1
      set this-y -1 * half-side
    ]
  ]
    
 
  ;assign turtle attributes 
  ask turtles
  [
    set homestead patch-here
    ifelse(variable-yield? = "Random") ;between 0.5 and 1.0
    [
      set yield random-float 0.49
      set yield precision (yield + 0.5) 2
    ]
    [
      ifelse(variable-yield? = "No")
      [ set yield 1 ]
      [ set yield [patch-yield] of homestead ] ;else variable-yield? = "From Map" 
    ]
    
    set wealth 25
    set profit 0
    set income 0
    set costs 0
        
    set have-visited-meeting-point? false
    
    set neighbours-list []
    
    set minimum-behaviours  10
    let my-behaviours-initial minimum-behaviours  ;local variable that holds the number of initial behaviours given A-prop - updated below if > 10
    
    ;set intitial id-standard 
    
    if(initial-standards = "Homogeneous")
    [
      ;all agents should have the same id-standard, as specified by sliders
    
      set id-standard []
      set id-standard fput id-standard-A id-standard ;id A (position 3 in id-standard)
      set id-standard fput id-standard-C id-standard ;id C (position 2 in id-standard)
      set id-standard fput id-standard-D id-standard ;id D (position 1 in id-standard)
      set id-standard fput id-standard-P id-standard ;id P (position 0 in id-standard)
      
    ]
    
    if(initial-standards = "Random")
    [
      ;id-standards vary between agents randomly     
      set id-standard random-props      
    ]
    
    
    if(initial-standards = "Distribution")
    [
      ;Set id-standard values based on normal distribution with mean from slider (id-standard-x) and sd = 0.1 (if mean = 0, value will always = 0)
      set id-standard distribution-props  id-standard-P id-standard-D id-standard-C id-standard-A 
    ]
        
      
    ;create behaviours-expressed patch-set
    set behaviours-expressed patches with[ 
      (pxcor >= [xcor] of myself - 2) and 
      (pxcor <= [xcor] of myself + 2) and 
      (pycor < [ycor] of myself) and
      (pycor >= [ycor] of myself - 4)  ]
    
    ask behaviours-expressed
    [ 
      set agent-who [who] of myself 
      set behaviour nobody  ;initial behaviour is nothing
    ]
    
    ;sort across then down for display (i.e. first patch is top left, last is bottom right)
    set behaviours-expressed sort-by [[pxcor] of ?1 < [pxcor] of ?2] behaviours-expressed
    set behaviours-expressed sort-by [[pycor] of ?1 > [pycor] of ?2] behaviours-expressed
    
    ifelse(expressed-matches-standard? = true)
    [
      ;initial expressed-behaviour should reflect initial id-standard as closely as possible
      ;calculate how many behaviours should be expressed (i.e. patches assigned) in total given proportion for Agri-business
      
      if(item 3 id-standard > 0) ;position 3 in id-standard is A
      [
        set my-behaviours-initial calc-my-behaviours-initial item 3 id-standard my-behaviours-initial
      ]
      
      ;once total number of behaviours is calculated calculate how many (patches) should be in each of the remaining behaviours
      let sum-CDP (item 2 id-standard + item 1 id-standard + item 0 id-standard)
      let count-C round (my-behaviours-initial * (item 2 id-standard / sum-CDP))
      let count-D round (my-behaviours-initial * (item 1 id-standard / sum-CDP))
      let count-P round (my-behaviours-initial * (item 0 id-standard / sum-CDP))
      
      set-initial-behaviours my-behaviours-initial count-C count-D count-P
    ]
  
    
    [  
      ;else initial expressed-behaviour is independent of id-standard
      
      if(initial-expressed = "Homogeneous")
      [
        ;all agents have same initial expressed-behaviours as specified by sliders
        
        ;calculate how many behaviours should be expressed (i.e. patches assigned) in total given proportion for Agri-business
        set my-behaviours-initial calc-my-behaviours-initial expressed-A my-behaviours-initial
                      
        ;once total number of behaviours is calculated calculate how many (patches) should be in each of the remaining behaviours
        let sum-CDP (expressed-C + expressed-D + expressed-P)
        let count-C round (my-behaviours-initial * (expressed-C / sum-CDP))
        let count-D round (my-behaviours-initial * (expressed-D / sum-CDP))
        let count-P round (my-behaviours-initial * (expressed-P / sum-CDP))
        
        set-initial-behaviours my-behaviours-initial count-C count-D count-P
        
      ] 
      
      
      if(initial-expressed = "Distribution")
      [
        ;set initial expressed behaviours based on normal distribution with mean from slider (id-standard-x) and sd = 0.1 (if mean = 0, value will always = 0)
        let props []
        
        set props distribution-props expressed-P expressed-D expressed-C expressed-A 
 
        let randP item 0 props
        let randD item 1 props
        let randC item 2 props
        let randA item 3 props
 
        set my-behaviours-initial calc-my-behaviours-initial randA my-behaviours-initial
        
        ;once total number of behaviours is calculated calculate how many (patches) should be in each of the remaining behaviours
        let sum-CDP (randC + randD + randP)
        let count-C round (my-behaviours-initial * (randC / sum-CDP))
        let count-D round (my-behaviours-initial * (randD / sum-CDP))
        let count-P round (my-behaviours-initial * (randP / sum-CDP))
 
        set-initial-behaviours my-behaviours-initial count-C count-D count-P
      ]
      
     
      if(initial-expressed = "Random")
      [
        ;generate random proportions for standard
        let props random-props
        
        let randP item 0 props
        let randD item 1 props
        let randC item 2 props
        let randA item 3 props
         
        set my-behaviours-initial calc-my-behaviours-initial randA my-behaviours-initial
        
        let sum-CDP (randC + randD + randP)
        let count-C round (my-behaviours-initial * (randC / sum-CDP))
        let count-D round (my-behaviours-initial * (randD / sum-CDP))
        let count-P round (my-behaviours-initial * (randP / sum-CDP))
        
        set-initial-behaviours my-behaviours-initial count-C count-D count-P
      ]
    ]
    
    set-id-error-behaviour ;also calculates id-expressed
    
  ]
  
  set-social-network 

  ask turtles 
  [ 
    set-id-expressed-social
    set-id-error-social 
  ]
  
  ;if behaviours-available to be set from file, do so here
  if(scenario-from-file? = true and use-values? = false) 
  [ 
    type "Reading data from file..."
    read-behaviours-available-from-file 
    ask turtles 
    [ 
      set-year-behaviours-available 
      if(empty? behaviours-available) [ user-message word "No behaviours-available data for turtle" who ]
    ]
    print "done."    
  ]
     
  ;if behaviours-available to be set randomly, do so here
  if(scenario-from-file? = false and use-values? = false) [ if(use-values? = false) [ set-random-behaviours ] ]
  
  if(use-values? = true) 
  [ 
    ask turtles 
    [ 
      let rand random-float 1
      ifelse(rand < available-A) 
      [ set behaviours-available [ 1 1 1 1 ] ]
      [ set behaviours-available [ 1 1 1 0 ] ]
    ]
  ]
end 

to set-social-network
 
 ;setup the inital social network
 
 if(initial-social-network = "All")
 [
   ;all turtles link to all other turtles
   ask turtles
   [
     create-links-to other turtles
   ]
 ]
 
 
 if(initial-social-network = "Random")
 [
   ;turtles randomly link to other turtles
   ask turtles
   [
     let rand random-normal 5 2
     if(rand < 0) [ set rand 0 ]
     set rand round rand
     create-links-to n-of rand other turtles
   ]
 ]

 
 
 

 if(initial-social-network = "Moore Neighbours" or initial-social-network = "vonNeumann Neighbours")
 [
   
   ;this is somewhat inelegant but needed because the grid agents are created on is not a perfectly uniform lattice with uneven spaces within the grid (if even number of agents)
   ;essentially, we find the nearest agents up, down, right and left of the agent
   ;then we ask the neighbours down and up to find the nearest neighbout on their left and right

   ask turtles
   [
     let upN nobody
     let downN nobody
     let leftN nobody
     let rightN nobody
     let DcornerL nobody
     let DcornerR nobody
     let UcornerL nobody
     let UcornerR nobody
     
     if (any? turtles with [ycor > [ycor] of myself])
     [ set upN min-one-of turtles with [ xcor = [xcor] of myself and ycor > [ycor] of myself ] [distance myself ] ]
     
     if (any? turtles with [ycor < [ycor] of myself])
     [ set downN min-one-of turtles with [ xcor = [xcor] of myself and ycor < [ycor] of myself ] [distance myself ] ]
     
     if (any? turtles with [xcor < [xcor] of myself])
     [ set leftN min-one-of turtles with [ ycor = [ycor] of myself and xcor < [xcor] of myself ] [distance myself ] ]
     
     if (any? turtles with [xcor > [xcor] of myself])
     [ set rightN min-one-of turtles with [ ycor = [ycor] of myself and xcor > [xcor] of myself ] [distance myself ] ]
     
     if(initial-social-network = "Moore Neighbours")
     [
       if(downN != nobody)
       [
         ask downN 
         [
           if (any? turtles with [xcor < [xcor] of myself])
           [ set DcornerL min-one-of turtles with [ ycor = [ycor] of myself and xcor < [xcor] of myself ] [distance myself ] ]
           
           if(any? turtles with [xcor > [xcor] of myself])  
           [ set DcornerR min-one-of turtles with [ ycor = [ycor] of myself and xcor > [xcor] of myself ] [distance myself ] ]
         ]
       ]
       
       if(upN != nobody)
       [
         ask upN
         [
           if (any? turtles with [xcor < [xcor] of myself])
           [ set UcornerL min-one-of turtles with [ ycor = [ycor] of myself and xcor < [xcor] of myself ] [distance myself ] ]
           
           if(any? turtles with [xcor > [xcor] of myself])  
           [ set UcornerR min-one-of turtles with [ ycor = [ycor] of myself and xcor > [xcor] of myself ] [distance myself ] ]
         ]
       ]
       
       create-links-to (turtle-set upN downN leftN rightN DcornerL DcornerR UcornerL UcornerR)
       ask out-link-neighbors [ set neighbours-list fput [who] of myself neighbours-list ]
     ]
     
     if(initial-social-network = "vonNeumann Neighbours") 
     [ 
       create-links-to (turtle-set upN downN leftN rightN) 
       ask out-link-neighbors [ set neighbours-list fput [who] of myself neighbours-list ]
     ]
   ]
 ]
 
 ask turtles
 [
   if(not any? out-link-neighbors) [ create-link-to one-of other turtles ]
 ]
 
 if(show-links? = false) [ ask links [ set hidden? true ] ]
 
 calc-network-density
end  

to-report calc-my-behaviours-initial [ randA my-behaviours-initial ]
  
  ;calculate how many expressed behaviours additional to my-behaviours-initial are needed to best match randA proportion
  
  if(randA > 0)
  [
    let a 1
    let y a / 12
    let min-diffc sqrt((randA - y) ^ 2)
    
    let found false
    
    while[not found]
      [
        set a a + 1
        
        set y (a / (10 + (2 * a)))
        let diffc sqrt((randA - y) ^ 2)
        ifelse(diffc > min-diffc)
          [ 
            set my-behaviours-initial (minimum-behaviours + a - 1)
            set found true
          ]  
          [ set min-diffc diffc ]
      ]
  ]
  
  report my-behaviours-initial
end 

to visit-meeting-point [ agents location]
  
  ;move turtles to the appropriate meeting point (where they may potentially make contacts)
  ;agents is and agent-set and location is the behaviour meeting point to move those agents to
  
  if(agents != nobody and count agents > 1)
  [
    ifelse(location = 0)
    [  
      ;is there more than one production meeting point? (yes if this is an agentset, no if only a single patch)
      ifelse(is-agentset? production-meeting-points) 
      [
        ask agents 
        [ 
          let nearest min-one-of production-meeting-points [distance myself]
          move-to nearest 
          set have-visited-meeting-point? true 
        ]
      ]      
      [  
        ask agents 
        [ 
          move-to production-meeting-points 
          set have-visited-meeting-point? true 
        ]
      ]
      
      ask agents [ make-contacts-at-meeting-point ]      
      ask agents [ move-to homestead ] ;agents should have moved home already, but just in case 
    ]
  
    [
      if(location = 1)
      [
        ask agents 
        [ 
          move-to diversification-meeting-point
          set have-visited-meeting-point? true 
        ]
      ]
      
      if(location = 2)
      [
        ask agents 
        [ 
          move-to conservation-meeting-point
          set have-visited-meeting-point? true 
        ]
      ]
      
      ask agents [ make-contacts-at-meeting-point ]      
      ask agents [ move-to homestead ] ;agents should have moved home already, but just in case 
    ]    
  ]
end 

to make-contacts-at-meeting-point
  
  ;assumes we are asking turtles at a given meeting point (patch) and makes connections between agents at that patch
  
  if(any? other turtles-here)
  [
    let new-contact one-of other turtles-here
    
    if(out-link-neighbors != nobody)
      [
        if(not member? new-contact out-link-neighbors)
          [
            create-link-to new-contact
            create-link-from new-contact
            ask new-contact [ move-to homestead ] ;we only want to add a single contact in each visit so move turtles home after connecting
            move-to homestead
          ]
      ]
  ]  
end 

to-report intersect [ a b ]
   
   ;reports a turtle-set of turtles that are found in both agentset a and agentset b
   
   set a sort a
   set b sort b
   let c []
   while [ not (empty? a or empty? b ) ]
   [ if-else first a < first b
     [ set a but-first a
     ]
     [ if-else first a > first b
       [ set b but-first b
       ]
       [ set c fput first a c
         set a but-first a
         set b but-first b
       ]
     ]
   ]
   report (turtle-set c)
end 

to-report distribution-props [ mean-P mean-D mean-C mean-A ]
  
  ;sets proportions based on normal distribution with mean values provided and sd = 0.1 (if mean = 0, value will always = 0)
      
  let randA random-normal mean-A 0.1
  if(randA < 0 or mean-A = 0) [ set randA 0 ]
  if(randA > 0.35) [ set randA 0.35 ] ;with initial-behaviours = 10 and max allow expressed behaviours = 20, max prop A can take is 0.33
  set randA (round (randA * 20)) / 20 ;round to 0.05
  set randA precision randA 2
  
  let randP random-normal mean-P 0.1
  if(randP < 0 or mean-P = 0) [ set randP 0 ]
  set randP (round (randP * 20)) / 20 ;round to 0.05
  set randP precision randP 2
  
  
  let randD random-normal mean-D 0.1
  if(randD < 0 or mean-D = 0) [ set randD 0 ]
  set randD (round (randD * 20)) / 20 ;round to 0.05
  set randD precision randD 2
  
  let randC 1 - randA - randP - randD
  if(randC < 0 or mean-C = 0) [ set randC 0 ]
  set randC (round (randC * 20)) / 20 ;round to 0.05
  set randC precision randC 2
    
  
  ;sum of standard may be greater than 1, so reduce total by reducing individual values in random order
  while[ (randP + randD + randC + randA) > 0.99 ] ;use 0.99 because of internal NetLogo rounding error
    [
      let r random 4
      if(r = 0 and randP >= 0.05) [ set randP randP - 0.05 set randP (round (randP * 20)) / 20] ;round to 0.05]
      if(r = 1 and randD >= 0.05) [ set randD randD - 0.05 set randD (round (randD * 20)) / 20] ;round to 0.05]
      if(r = 2 and randC >= 0.05) [ set randC randC - 0.05 set randC (round (randC * 20)) / 20] ;round to 0.05]  
      if(r = 3 and randA >= 0.05 and randA != 0.35) [ set randA randA - 0.05 set randA (round (randA * 20)) / 20] ;round to 0.05]  
    ]                 
  
  ;sum of standard may be less than 1, so increase total by increasing individual values in random order
  while[ (randP + randD + randC + randA) < 0.99 ]
    [
      let r random 4
      if(r = 0 and mean-P != 0) [ set randP randP + 0.05 set randP (round (randP * 20)) / 20] ;round to 0.05]
      if(r = 1 and mean-D != 0) [ set randD randD + 0.05 set randD (round (randD * 20)) / 20] ;round to 0.05]
      if(r = 2 and mean-C != 0) [ set randC randC + 0.05 set randC (round (randC * 20)) / 20] ;round to 0.05]  
      if(r = 3 and randA != 0 and randA < 0.30) [ set randA randA + 0.05 set randA (round (randA * 20)) / 20] ;round to 0.05]
    ]
  
  let props []
  
  set props fput randA props
  set props fput randC props
  set props fput randD props
  set props fput randP props
  
  report props
end 

to-report random-props
   
  ;generate random proportions for a standard [i.e. list of three values, all 0-1]
          
  let randA random-float 0.35 ;with initial-behaviours = 10 and max allow expressed behaviours = 20, max prop A can take is 0.33
  let rand-order shuffle [ "p" "d" "c" ]
  
  ;because total of standard must equal one, after the first value has been set, later values must be scaled
  let randP 0
  let randD 0
  let randC 0
  
  let randFirst 0
  let randSecond 0
  let randThird 0
  
  set randFirst random-float (1 - randA)
  set randSecond random-float (1 - randA - randFirst)
  set randThird 1 - randA - randFirst - randSecond
  
  ;randomly assign the three random values to P D and C - could make this code more efficient in future
  ifelse(item 0 rand-order = "p") 
    [ set randP randFirst ]
    [ ifelse(item 0 rand-order = "d") 
      [ set randD randFirst ]
      [ set randC randFirst ]
    ]
  
  ifelse(item 1 rand-order = "p") 
    [ set randP randSecond ]
    [ ifelse(item 1 rand-order = "d") 
      [ set randD randSecond ]
      [ set randC randSecond ]
    ]
  
  ifelse(item 2 rand-order = "p") 
    [ set randP randThird ]
    [ ifelse(item 2 rand-order = "d") 
      [ set randD randThird ]
      [ set randC randThird ]
    ]
     
   let props []     
   set props fput precision randA 3 props
   set props fput precision randC 3 props
   set props fput precision randD 3 props
   set props fput precision randP 3 props
   
   report props
end  

to set-initial-behaviours [my-behaviours-initial count-C count-D count-P]
  
  ;used in initial agent setup to assign expressed-behaviours given counts of patches 
  
  ;if total behaviours is too large because of rounding, randomly reduce
  while[(count-C + count-D + count-P) > my-behaviours-initial]
  [
    let rand random 3 
    if(rand = 0) [ set count-C count-C - 1 ]
    if(rand = 1) [ set count-D count-D - 1 ]
    if(rand = 2) [ set count-P count-P - 1 ]
  ]
  
  
  ;if total behaviours is too small because of rounding, randomly increase
  while[(count-C + count-D + count-P) < my-behaviours-initial]
  [
    let rand random 3 
    if(rand = 0) [ set count-C count-C + 1 ]
    if(rand = 1) [ set count-D count-D + 1 ]
    if(rand = 2) [ set count-P count-P + 1 ]
  ]
  
  ;now assign these number of patches to behaviours-expressed 
  let counter-C 0
  let counter-D 0
  let counter-P 0
  foreach behaviours-expressed
  [
    ifelse(counter-C < count-C)
      [
        ask ? [ set behaviour 2 ]
        set counter-C counter-C + 1
      ]        
    
      [
        ifelse(counter-D < count-D)
        [
          ask ? [ set behaviour 1 ]
          set counter-D counter-D + 1
        ] 
        
        [
          if(counter-P < count-P)
          [
            ask ? [ set behaviour 0 ]
            set counter-P counter-P + 1
          ]
        ]
      ]   
  ]
end 

to display-behaviours

  ;display behaviours-expressed in uniform manner for all turtles for easier visual comparison 
    
  set behaviours-expressed patch-set behaviours-expressed
  ask behaviours-expressed [ set pcolor white ] ;first re-set colour of all patches
  
  ;create an ordered list of the behaviours
  let ordered-behaviour [behaviour] of behaviours-expressed with [ behaviour != nobody ] 
  set ordered-behaviour sort-by [?1 < ?2] ordered-behaviour 
  
  
  ;loop through behaviours spatially applying behaviours from ordered list in turn 
  ;so from top left to bottom right, producer behavours will always be shown first, then D, then C
  let o 0
  let max-o ((length ordered-behaviour) - 1)
  let j ycor - 1 
  
  while[j >= ycor - 4]
  [ 
    let i xcor - 2
    
    while[i <= xcor + 2]
    [
      let b nobody
      if(o <= max-o)
      [ set b item o ordered-behaviour ]
      
      ask behaviours-expressed with [pxcor = i and pycor = j] [ set behaviour b ]
      
      set o o + 1
      set i i + 1
    ]
    
    set j j - 1
  ]
  
  ;now set colours
  ask behaviours-expressed with [ behaviour != nobody ] 
  [ 
    if(behaviour = 0) [ set pcolor yellow ]
    if(behaviour = 1) [ set pcolor grey ]
    if(behaviour = 2) [ set pcolor green ]
  ]
  
  ;if using behaviours available, make the patches on either side of the turtle indicate whether a behaviour is available or not (white if not available)
  ifelse(use-values? = false)
  [
    ;set colours of representative behaviours-available patches
    ifelse(item 0 behaviours-available = 1) 
    [ ask patches with [pxcor = [xcor] of myself - 2 and pycor = [pycor] of myself] [ set pcolor yellow ] ] 
    [ ask patches with [pxcor = [xcor] of myself - 2 and pycor = [pycor] of myself] [ set pcolor white ] ] 
    
    ifelse(item 1 behaviours-available = 1) 
    [ ask patches with [pxcor = [xcor] of myself - 1 and pycor = [pycor] of myself] [ set pcolor grey ] ]
    [ ask patches with [pxcor = [xcor] of myself - 1 and pycor = [pycor] of myself] [ set pcolor white ] ]
    
    ifelse(item 2 behaviours-available = 1) 
    [ ask patches with [pxcor = [xcor] of myself + 1 and pycor = [pycor] of myself] [ set pcolor green ] ]
    [ ask patches with [pxcor = [xcor] of myself + 1 and pycor = [pycor] of myself] [ set pcolor white ] ]
    
    ifelse(item 3 behaviours-available = 1) 
    [ ask patches with [pxcor = [xcor] of myself + 2 and pycor = [pycor] of myself] [ set pcolor blue ] ]
    [ ask patches with [pxcor = [xcor] of myself + 2 and pycor = [pycor] of myself] [ set pcolor white ] ]
  ]
  [
    ;if using values show if agribusiness is available
    ifelse(item 3 behaviours-available = 1) 
    [ ask patches with [pxcor = [xcor] of myself + 2 and pycor = [pycor] of myself] [ set pcolor blue ] ]
    [ ask patches with [pxcor = [xcor] of myself + 2 and pycor = [pycor] of myself] [ set pcolor white ] ]
  ]  
end 

to-report hierarchy-position [ id standard ]
  
  ;reports where id is in the hierarchy for standard. 0 = top, 3 = bottom
  let counter 0
  
  if(id != 0) [ if(item id standard < item 0 standard) [ set counter counter + 1 ]]
  if(id != 1) [ if(item id standard < item 1 standard) [ set counter counter + 1 ]]
  if(id != 2) [ if(item id standard < item 2 standard) [ set counter counter + 1 ]]
  if(id != 3) [ if(item id standard < item 3 standard) [ set counter counter + 1 ]]

  report counter
end 

to-report calc-swapped-profit [a b]
  
  ;returns income if swapping from behaviour a to behaviour b
  
  ;first check if behaviour can be added (i.e. if A is available) or removed (i.e. number of behaviours expressed is not already a minimum
  ifelse((a = nobody and item 3 behaviours-available != 1) or (b = nobody and count behaviours-expressed with [behaviour != nobody] = minimum-behaviours))  
  [ report profit ]
  [
    let p 0
    
    ifelse(a = b or not any? behaviours-expressed with [behaviour = a]) [ report profit ] ;no point in checking swapping same behaviours!
    [
      ask one-of behaviours-expressed with [ behaviour = a ] [ set behaviour b ]
      set p precision ((calc-income-from-behaviours behaviours-expressed) - (calc-costs-from-behaviours behaviours-expressed)) 2
      ask one-of behaviours-expressed with [behaviour = b ] [ set behaviour a ]  ;switch back to previous behaviour
      report p
    ]
  ]
end 

to-report calc-swapped-error [a b id-error]
  
  ;returns id-error if swapping from behaviour a to behaviour b (does not consider income)
  
  ;first check if behaviour can be added (i.e. if A is available) or removed (i.e. number of behaviours expressed is not already a minimum
  ifelse((a = nobody and item 3 behaviours-available != 1) or (b = nobody and count behaviours-expressed with [behaviour != nobody] = minimum-behaviours))  
  [ report id-error ]
  [
    let ie 0
    
    ifelse(item b behaviours-available != 1 or not any? behaviours-expressed with [behaviour = a]) [ report id-error ] ;if these behaviours are not available
    [
      ifelse(a = b) [ report id-error ] ;no point in checking swapping same behaviours!
      [
        ask one-of behaviours-expressed with [ behaviour = a ] [ set behaviour b ]
        let dummy-standard calc-standard-from-behaviours behaviours-expressed ;calculate the standard from this new behaviour set
        set ie precision compare-standards dummy-standard id-standard 2
        ask one-of behaviours-expressed with [behaviour = b ] [ set behaviour a ]  ;switch back to previous behaviour
        report ie
      ]
    ]
  ]
end 

to-report calc-swapped-error-profit [a b id-error]
  
  ;if swapping from behaviour a to behaviour b does not decrease profit returns id-error for newly swapped behaviours
  ;else returns original id-error
  
  ;first check if behaviour can be added (i.e. if A is available) or removed (i.e. number of behaviours expressed is not already a minimum
  ifelse((a = nobody and item 3 behaviours-available != 1) or (b = nobody and count behaviours-expressed with [behaviour != nobody] = minimum-behaviours))  
  [ report id-error ]
  [  
    let ie 0
    
    ifelse(a = b or not any? behaviours-expressed with [behaviour = a]) [ report id-error ] ;no point in checking swapping same behaviours!
    [
      ask one-of behaviours-expressed with [ behaviour = a ] [ set behaviour b ]
      let p (calc-income-from-behaviours behaviours-expressed) - (calc-costs-from-behaviours behaviours-expressed)
      
      ifelse(p > profit)
      [     
        let dummy-standard calc-standard-from-behaviours behaviours-expressed ;calculate the standard from this new behaviour set
        set ie precision compare-standards dummy-standard id-standard 2
        ask one-of behaviours-expressed with [behaviour = b ] [ set behaviour a ]  ;switch back to previous behaviour
        report ie
      ]
      [ 
        ask one-of behaviours-expressed with [behaviour = b ] [ set behaviour a ]  ;switch back to previous behaviour
        report id-error 
      ]
    ]
  ]
end 

to-report calc-added-profit [b]
  
  ;returns profit if adding behaviour b
  
  ifelse(item 3 behaviours-available != 1)  ;first check if behaviour can be added (i.e. if A is available)
  [ report profit ]
  [
    let p 0
    
    ifelse(not any? behaviours-expressed with [behaviour = nobody]) [ report profit ] ;no point in checking if we can't add a behaviour!
    [
      ask one-of behaviours-expressed with [ behaviour = nobody ] [ set behaviour b ]
      set p precision ((calc-income-from-behaviours behaviours-expressed) - (calc-costs-from-behaviours behaviours-expressed)) 2
      ask one-of behaviours-expressed with [behaviour = b ] [ set behaviour nobody ]  ;switch back to previous behaviour
      report p
    ]
  ]
end 

to-report calc-added-error-profit[b id-error]
  
  ;if adding behaviour b does not decrease profit returns id-error for newly added behaviours-expressed 
  ;else returns original id-error
  
  ifelse(item 3 behaviours-available != 1)  ;first check if behaviour can be added (i.e. if A is available)
  [ report id-error]
  [
    let ie 0
  
    ifelse(not any? behaviours-expressed with [behaviour = nobody]) [ report id-error ] ;no point in checking if we can't add a behaviour!
    [
      ask one-of behaviours-expressed with [ behaviour = nobody ] [ set behaviour b ]
      let p (calc-income-from-behaviours behaviours-expressed) - (calc-costs-from-behaviours behaviours-expressed)
      
      ifelse(p > profit)
      [
        let dummy-standard calc-standard-from-behaviours behaviours-expressed ;calculate the standard from this new behaviour set
        set ie precision compare-standards dummy-standard id-standard 2
        ask one-of behaviours-expressed with [behaviour = b ] [ set behaviour nobody ]  ;switch back to previous behaviour
        report ie
      ]
      [ 
        ask one-of behaviours-expressed with [behaviour = b ] [ set behaviour nobody ]  ;switch back to previous behaviour
        report id-error 
      ] 
    ]
  ]
end  

to-report calc-added-error[b id-error]
  
  ;returns id-error if adding behaviour b (does not consider income)
  ifelse(item 3 behaviours-available != 1)  ;first check if behaviour can be added (i.e. if A is available)
  [ report id-error]
  [
    let ie 0
    
    ifelse(item b behaviours-available != 1) [ report id-error ] ;if this behaviour is not available or no behaviours can be added
    [
      ifelse(not any? behaviours-expressed with [behaviour = nobody]) [ report id-error ] ;no point in checking if we can't add a behaviour!
      [
        ask one-of behaviours-expressed with [ behaviour = nobody ] [ set behaviour b ]
        let dummy-standard calc-standard-from-behaviours behaviours-expressed ;calculate the standard from this new behaviour set
        set ie precision compare-standards dummy-standard id-standard 2
        ask one-of behaviours-expressed with [behaviour = b ] [ set behaviour nobody ]  ;switch back to previous behaviour
        report ie
      ]
    ]
  ]
end       

to set-maximised-behaviour
  
  ;set behaviour to maximise profit
  
  let target-behaviour 0
  let swapped []
  let add -1
  
  let hpP hierarchy-position 0 id-standard
  let hpD hierarchy-position 1 id-standard
  let hpC hierarchy-position 2 id-standard
  
  ifelse(profit < 0) 
  [ set target-behaviour -1 ] ;swap to whichever behaviour maximises income
  [
    ;otherwise we are maximising because A is in top two of id-standard. find other behaviour in top two to aim to add (0 is already set)
    if(hpD < hpP and hpD < hpC) [ set target-behaviour 1 ] ;do not set as target if not higher ranked than both other behaviours (might be equal)
    if(hpC < hpP and hpC < hpD) [ set target-behaviour 2 ] 
  ]
  
  let my-value-P (value-P * yield)
  
  let ordered-values []
  if(any? behaviours-expressed with [behaviour = 2]) [ set ordered-values fput value-C ordered-values ] ;only add behaviours to the list if they are available
  if(any? behaviours-expressed with [behaviour = 1]) [ set ordered-values fput value-D ordered-values ]
  if(any? behaviours-expressed with [behaviour = 0]) [ set ordered-values fput my-value-P ordered-values ]
  
  set ordered-values sort-by [?1 < ?2] ordered-values ;lowest value is in position 0, highest in position 2
    
  ;if there is a target behaviour, check if swapping lowest expressed non-target value behaviour for target or adding target would increase profit
  ifelse(target-behaviour >= 0)
  [
    let lowest-value-behaviour 0
    let swapped-profit -999
    
    if(not empty? ordered-values)
    [
      let found false
      foreach(ordered-values)
      [        
        if(? = my-value-P and target-behaviour != 0 and found = false)
        [ 
          set lowest-value-behaviour 0 
          set found true
        ]
        if(? = value-D and target-behaviour != 1 and found = false) 
        [ 
          set lowest-value-behaviour 1 
          set found true
        ]
        if(? = value-C and target-behaviour != 2 and found = false) 
        [ 
          set lowest-value-behaviour 2 
          set found true
        ]
      ]
      
      set swapped-profit calc-swapped-profit lowest-value-behaviour target-behaviour 
      if(swapped-profit > profit) 
      [ 
        set swapped fput target-behaviour swapped
        set swapped fput lowest-value-behaviour swapped
        set add -1
      ] 
    ]
    
    ;check adding target behaviour
    let added-profit calc-added-profit target-behaviour 
    if(added-profit > swapped-profit and added-profit > profit) 
    [ 
      set swapped []
      set add target-behaviour
    ]
  ]
  
  
  ;otherwise, if no target behaviour, check if swapping lowest value behaviour for any other behaviour or adding a non-lowest value behaviour would increase profit
  [
    ;for comments on how this 'else' section works see set-ideal-behaviour
    let a 0
    let b 0
    let swapped-profit -999
    let best-profit profit
    
    let check-order [ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]                ;generate randomly ordered list in which to check behaviour changes
    set check-order shuffle check-order
    let divisor sqrt(length check-order)
    
    foreach(check-order)
    [
      
      set a int(? / divisor)
      if((remainder ? divisor) = 0 ) [ set a a - 1 ]
      
      set b (remainder ? divisor) - 1
      if((remainder ? divisor) = 0) [ set b divisor - 1 ] 
      
      if(a != b)
      [
        if(a = 4) [ set a nobody ]
        if(b = 4) [ set b nobody ]
        set swapped-profit calc-swapped-profit a b
        if(swapped-profit > best-profit) 
        [ 
          set swapped []
          set swapped fput b swapped
          set swapped fput a swapped
          set add -1
          set best-profit swapped-profit
        ]
      ]
      
    ]
  ]
  
  ifelse(empty? swapped)
  [
    ifelse(add > -1) 
    [ add-behaviour add ]
    [  ] ;nothing improved profit
  ]
  [
    ifelse(add > -1)
    [ show "Error: cannot both add and swap behaviours" ]
    [ swap-behaviours item 0 swapped item 1 swapped ]
  ]
end 

to add-behaviour [add]
  
  ;changes a behaviour expressed patch behaviour from nobody to add (with error check for availability of patches with behaviour = nobody)
  
  ifelse(any? behaviours-expressed with [behaviour = nobody])
  [
    ask one-of behaviours-expressed with [behaviour = nobody] [ set behaviour add ]
  ]
  [ show "Error: could not add behavour - behaviours already full"]
end 

to set-ideal-behaviour [ check-profit ]
  
  ;set behaviour to minimise id-error
  ;when check-profit is true, selected behavour must ensure profit does not drop below zero for the timestep
  ;when check-profit is false, profit is not considered but availability is

  let a 0
  let b 0
  let swapped-error 100 ;initial dummy value
  let best-error id-error-behaviour
  let swapped [] ;if not empty at end of this procedure, values in here will be used to swap a patch's behaviour
      
  ;generate randomly ordered list in which to check behaviour changes
  ;by including 'no expressed behaviour' (nobody) in this list we can also automatically check adding and removing behaviours
  ;with four possible behaviours (P C D and none) we have 16 potential different swap combinations (including swapping to same behaviour, we'll check for that below)
  ;each number corresponds to a swap combination
  let check-order [ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ]                
  set check-order shuffle check-order
  let divisor sqrt(length check-order)
  
  ;iterate through the random order of swaps to check 
  foreach(check-order)
  [
    ;for this swap combination id set a and b
    set a int(? / divisor)
    if((remainder ? divisor) = 0 ) [ set a a - 1 ]
    
    set b (remainder ? divisor) - 1
    if((remainder ? divisor) = 0) [ set b divisor - 1 ] 
    
    ;no point in checking if no difference in what we're swapping FROM to what we're swapping TO
    if(a != b)
    [   
      if(a = 4) [ set a nobody ]
      if(b = 4) [ set b nobody ] 
      
      ifelse(check-profit = true)
      [ set swapped-error calc-swapped-error-profit a b id-error-behaviour ]
      [ set swapped-error calc-swapped-error a b id-error-behaviour ]
      
      ;if swapping the behaviour improves error, replace the swapped list
      if(swapped-error < best-error) 
      [ 
        set swapped []
        set swapped fput b swapped
        set swapped fput a swapped
        set best-error swapped-error
      ]
    ]
   ]     

  if(not empty? swapped) [ swap-behaviours item 0 swapped item 1 swapped ]
end 

to swap-behaviours [ a b]
  
  ;selects a random patch with behaviour = a and changes it to behaviour b (with error check)
  
  ifelse(any? behaviours-expressed with [behaviour = a])
  [
    ask one-of behaviours-expressed with [behaviour = a] [ set behaviour b ]
  ]
  [ show "Error: cannot swap behaviours because FROM behaviour is not in behaviours-expressed" ]
end  

to set-behaviour

  ;turtles may potentially change the behaviour of one expressed-behaviours patch in a given timestep
    
  set behaviour-change false ;indicates whether an expressed behaviour has changed this timestep

  let initial-behaviours get-behaviours-from-patches behaviours-expressed
  
  ;if values should be considered
  ifelse(use-values?)
  [  
    ;check if agri-business is in top two places of salience hierarchy - 
    ;if so look to maximise profit with other behaviour in top two regardless of matching id-standard
    ;otherwise satisfice (i.e. if income is greater than min reqd, match behaviour to id-standard (but check change doesn't drop income below min reqd), otherwise increase income
    
    let maximiser false
    if((hierarchy-position 3 id-standard) < 2 and item 3 id-standard != 0) [ set maximiser true ]
    
    set income precision calc-income-from-behaviours behaviours-expressed 2
    set costs precision calc-costs-from-behaviours behaviours-expressed 2
    set profit precision (income - costs) 2
    if(profit < 0) [ set maximiser true ]
    
    ifelse(maximiser = true) 
    [ set-maximised-behaviour ]  ;profit maximisation
    [ set-ideal-behaviour true ] ;satisfice (i.e. ensure profit sufficient to live on but also consider identity)     
    
    
    set income precision calc-income-from-behaviours behaviours-expressed 2
    set costs precision calc-costs-from-behaviours behaviours-expressed 2
    set profit precision (income - costs) 2
    set wealth precision (wealth + profit) 2
    
    if(wealth < 0) ;if wealth < 0, kill the agent 
    [
      ask behaviours-expressed [ set behaviour nobody ]
      display-behaviours
      die
    ]
    
  ]
  
  ;else, if values should not be considered, do not consider income
  [ set-ideal-behaviour false ] ;consider only identity
 
  ;check how behaviours have changed so that agents visit correct meeting-points (if there are multiple)
  let current-behaviours get-behaviours-from-patches behaviours-expressed 
  
  if(compare-behaviours initial-behaviours current-behaviours 0) 
  [ 
    set added-production (turtle-set self added-production) ;add self to list of turtles which have added production behaviour
    set behaviour-change true
  ]
  if(compare-behaviours initial-behaviours current-behaviours 1) 
  [ 
    set added-diversification (turtle-set self added-diversification)  ;add self to list of turtles which have added diversification behaviour
    set behaviour-change true
  ]
  if(compare-behaviours initial-behaviours current-behaviours 2)  
  [ 
    set added-conservation (turtle-set self added-conservation)  ;add self to list of turtles which have added conservation behaviour
    set behaviour-change true
  ]   
end 

to-report compare-behaviours [ oldList newList number ]
  
  ;returns true if more instances of number are found in newList than oldList (otherwise returns false)
  
  let reporter false
  
  if(member? number newList)
  [
    ifelse(member? number oldList)
    [
      let oldCount 0
      let newCount 0
      
      foreach oldList [ if(? = number) [ set oldCount oldCount + 1 ] ]
      
      foreach newList [ if(? = number) [ set newCount newCount + 1 ] ]         
      
      if(newCount > oldCount) [ set reporter true ]
    ]
    
    [ set reporter true ] ;if a member of new list but not old list MUST be greater count!
  ]
  
  report reporter
end 

to-report get-behaviours-from-patches [ behaviour-patches ]
  
  ;converts behaviours in an agentset to a behaviours in a list
  
  let behaviour-list []
  ask behaviour-patches [ set behaviour-list fput behaviour behaviour-list ]
  report behaviour-list  
end 

to-report calc-standard-from-behaviours [ behaviours ]
  
  ;calculates and returns the proportions of the different elements of behaviours
  
  let standard [ ]

  let denom count behaviours with [behaviour != nobody]
  
  set denom (denom + (denom - minimum-behaviours))
  
  set standard fput ((count behaviours with [behaviour != nobody] - minimum-behaviours) / denom) standard
  set standard fput ((count behaviours with [behaviour = 2]) / denom) standard  
  set standard fput ((count behaviours with [behaviour = 1]) / denom) standard
  set standard fput ((count behaviours with [behaviour = 0]) / denom) standard

  report standard 
end 

to-report calc-income-from-behaviours [ behaviours ]

  ;calculate the income from behaviours given the corresponding values and yield

  let temp-income 0
  
  ask behaviours
  [
    if(behaviour = 0) [ set temp-income temp-income + (value-P * [yield] of myself) ]
    if(behaviour = 1) [ set temp-income temp-income + value-D ]  
    if(behaviour = 2) [ set temp-income temp-income + value-C ]
  ]
  
  report temp-income
end 

to-report calc-costs-from-behaviours [ behaviours ]
  
  ;calculate the cost of exhbiting the current set of behaviours (currently simply 0.5 for each expressed behaviour)
  
  let temp-costs 0
  set temp-costs (count behaviours with [behaviour != nobody]) / 2
  report temp-costs
end 

to set-id-error-behaviour
  
  ;calculates difference between agents' id-standard and their expressed behaviour
  
  set last-id-error-behaviour id-error-behaviour
  set id-error-behaviour 0
  
  let temp-behaviours-expressed patch-set behaviours-expressed
    
  let denom count temp-behaviours-expressed with [behaviour != nobody]
  set denom (denom + (denom - minimum-behaviours))
  
  set id-expressed []  
  
  set id-expressed fput precision ((count temp-behaviours-expressed with [behaviour != nobody] - minimum-behaviours) / denom) 3 id-expressed 
  set id-expressed fput precision ((count temp-behaviours-expressed with [behaviour = 2]) / denom) 3 id-expressed
  set id-expressed fput precision ((count temp-behaviours-expressed with [behaviour = 1]) / denom) 3 id-expressed
  set id-expressed fput precision ((count temp-behaviours-expressed with [behaviour = 0]) / denom) 3 id-expressed
  
  set id-error-behaviour compare-standards id-expressed id-standard
end 

to set-id-error-social
  
  ;calculates difference between agents' id-standard and mean-behaviours
  
  set last-id-error-social id-error-social
  set id-error-social 0
  set id-error-social compare-standards id-standard id-expressed-social  
end 

to-report compare-standards [standardA standardB]
  
  ;calculates cumulative difference between elements in standardA and standardB
  
  let counter 0
  let diffc 0
   while[counter < (length standardA)]
   [
     set diffc diffc + sqrt(((item counter standardA) - (item counter standardB)) ^ 2)
     set counter counter + 1
   ]
   
   set diffc precision diffc 2
   
   report diffc
end 

to set-id-change
  
  ;update id-standard to better match expressed-behaviour or mean (social) behaviours
  
  let unit-change 0.01 ;amount to change id-standard by
  
  let check-social false
  if(behaviour-change = true or id-error-behaviour <= unit-change) [ set check-social true ] ;if behaviour changes this timestep or my id-error-behaviour is minimised) match id-standard to mean behaviours
     
  let temp-behaviours-expressed patch-set behaviours-expressed
  
    
  let current-min-standard id-standard       ;current-min-standard holds the standard that currently minimises standard-error
  let dummy-standard id-standard             ;dummy-standard holds the current standard being checked
    
  let standard-error 0   
  ifelse(check-social = true)
  [ set standard-error compare-standards id-expressed-social id-standard ] ;check social
  [ set standard-error compare-standards id-expressed id-standard  ]   ;check personal 
    
  let min-standard-error standard-error                   ;standard-error is the error for current-min-standard 
    
  
  ;for info on how check-order is used, see comments in set-ideal-behaviour
  let check-order [ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ] ;total number of 2by2 combinations for four options (P C D A)
  set check-order shuffle check-order
  let divisor sqrt(length check-order) ;needed to set i and j below

  ;loop to find change in id-standard that minimises ere
  ;two loops (mirrored changes) as each behaviour could be increased or decreased    
  let this-loop 0  
  while[this-loop < 2]
  [ 
    foreach(check-order)
    [
      let i int(? / divisor)
      if((remainder ? divisor) = 0 ) [ set i i - 1 ]
      
      let j (remainder ? divisor) - 1
      if((remainder ? divisor) = 0) [ set j divisor - 1 ] 
      
       if(i != j)
       [
          let i-value 0
          let j-value 0
          
          ;first loop i is +ve change and j -ve    
          if(this-loop = 0)
          [
            set i-value item i id-standard + unit-change
            set j-value item j id-standard - unit-change
          ]
          
          ;second loop i is -ve change and j +ve
          if(this-loop = 1)
          [
            set i-value item i id-standard - unit-change
            set j-value item j id-standard + unit-change
          ]
          
          set i-value precision i-value 2
          set j-value precision j-value 2
          
          if(i-value >= 0 and j-value >= 0)
          [
              
            set dummy-standard replace-item i dummy-standard i-value 
            set dummy-standard replace-item j dummy-standard j-value 
            
            ifelse(check-social = true)
            [ set standard-error compare-standards id-expressed-social dummy-standard ]
            [ set standard-error compare-standards id-expressed dummy-standard  ]   
            
            if(swap-errors? standard-error min-standard-error)
            [
              set current-min-standard dummy-standard
              set min-standard-error standard-error
            ]            
          ]            
          set dummy-standard id-standard
       ]
    ]
     
    set this-loop this-loop + 1
  ]
    
  set id-standard current-min-standard   
end 

to-report swap-errors? [errorA errorB]
  
  ;report true if errorA < errorB, else report false
  
  let swap false
  
  if(errorA < errorB) [ set swap true ]

  report swap
end 

to set-id-expressed-social
  
  ;calculates mean expressed-behaviour standard for all agents
  
  set id-expressed-social [ 0 0 0 0 ] 
  
  let tot-expressed-behaviours 0 ;total of all turtle expressed behaviours
  let temp-tot-behaviours [ 0 0 0 0 ]    
  
  ifelse(any? out-link-neighbors) 
  [
    ask out-link-neighbors
    [
      set behaviours-expressed patch-set behaviours-expressed
      
      let tempP count behaviours-expressed with [behaviour = 0]
      let tempD count behaviours-expressed with [behaviour = 1]
      let tempC count behaviours-expressed with [behaviour = 2]  
      let tempA count behaviours-expressed with [behaviour != nobody ] - minimum-behaviours ;A is given by the number of patches with an expressed behaviour > 10
      
      set tot-expressed-behaviours tot-expressed-behaviours + tempP + tempD + tempC + tempA
      
      set tempP tempP + item 0 temp-tot-behaviours
      set tempD tempD + item 1 temp-tot-behaviours
      set tempC tempC + item 2 temp-tot-behaviours
      set tempA tempA + item 3 temp-tot-behaviours
      
      set temp-tot-behaviours fput tempA temp-tot-behaviours
      set temp-tot-behaviours fput tempC temp-tot-behaviours
      set temp-tot-behaviours fput tempD temp-tot-behaviours
      set temp-tot-behaviours fput tempP temp-tot-behaviours
    ]
    
    set id-expressed-social replace-item 0 id-expressed-social ((item 0 temp-tot-behaviours) / tot-expressed-behaviours)
    set id-expressed-social replace-item 1 id-expressed-social ((item 1 temp-tot-behaviours) / tot-expressed-behaviours)
    set id-expressed-social replace-item 2 id-expressed-social ((item 2 temp-tot-behaviours) / tot-expressed-behaviours)
    set id-expressed-social replace-item 3 id-expressed-social ((item 3 temp-tot-behaviours) / tot-expressed-behaviours)
    
    set id-expressed-social replace-item 0 id-expressed-social precision (item 0 id-expressed-social) 2
    set id-expressed-social replace-item 1 id-expressed-social precision (item 1 id-expressed-social) 2
    set id-expressed-social replace-item 2 id-expressed-social precision (item 2 id-expressed-social) 2
    set id-expressed-social replace-item 3 id-expressed-social precision (item 3 id-expressed-social) 2
  ]
  [ set id-expressed-social id-standard ]
end 

to draw-behaviours-boundaries
  
  ;draws a line around each turtles's behaviours-expressed patches 
  ;code after David O'Sullivan
  
  create-line-painters 1 [ ;; make the global line-drawer turtle
    set color black
    set hidden? true
    set pen-size 1
    set lp_who 1
  ]
  
  set line-drawer line-painters with [lp_who = 1 ]
  
  ask patches [
    ask neighbors4 with [agent-who != [agent-who] of myself] [
      draw-edge-between self myself
    ]
  ]
  ask line-painters [ die ]
end 

to draw-edge-between [p1 p2]
  
  ;drawing the farm boundary - code after David O'Sullivan
  
  ask line-drawer 
  [
    move-to p1
    face p2
    fd 0.5
    lt 90
    fd 0.4999
    rt 180
    pd
    fd 0.99998
    pu
  ]
end 

to do-plots

  ;update plots

  set-current-plot "Behaviours"
  
  set-current-plot-pen "Producer"
  let p 0
  ask turtles [ set p p + (count behaviours-expressed with [behaviour = 0]) ]  
  plot p
  
  set-current-plot-pen "Conservationist"
  let c 0
  ask turtles [ set c c + (count behaviours-expressed with [behaviour = 2]) ]  
  plot c
  
  set-current-plot-pen "Diversifier"
  let d 0
  ask turtles [ set d d + (count behaviours-expressed with [behaviour = 1]) ]  
  plot d
  
  set-current-plot-pen "Agri-business"
  let a 0
  ask turtles [ set a a + ((count behaviours-expressed with [ behaviour != nobody ] ) - minimum-behaviours ) ]  
  plot a
  
   
  
  set-current-plot "Mean ID Standard"
  set-current-plot-pen "Producer"
  set p 0
  ask turtles [ set p p + item 0 id-standard ]  
  plot p / (count turtles)
  
  set-current-plot-pen "Diversifier"
  set d 0
  ask turtles [ set d d + item 1 id-standard ]  
  plot d / (count turtles)
  
  set-current-plot-pen "Conservationist"
  set c 0
  ask turtles [ set c c + item 2 id-standard ]  
  plot c / (count turtles)
  
  set-current-plot-pen "Agri-business"
  set a 0
  ask turtles [ set a a + item 3 id-standard ]  
  plot a / (count turtles)
  
  ;plot deprecated  
  ;set-current-plot "Count Max ID Standard"
  ;set-current-plot-pen "Producer"
  ;set p 0
  ;ask turtles 
  ;[ if(hierarchy-position 0 id-standard = 0) [ set p p + 1 ] ] 
  ;plot p
  
  ;set-current-plot-pen "Diversifier"
  ;set d 0
  ;ask turtles [ if(hierarchy-position 1 id-standard = 0) [  set d d + 1] ] 
  ;plot d
  
  ;set-current-plot-pen "Conservationist"
  ;set c 0
  ;ask turtles [ if(hierarchy-position 2 id-standard = 0) [ set c c + 1 ] ] 
  ;plot c
  
  ;set-current-plot-pen "Agri-business"
  ;set a 0
  ;ask turtles [ if(hierarchy-position 3 id-standard = 0) [ set a a + 1 ] ] 
  ;plot a
  ;--end plot deprecated
    
  set-current-plot "Identity Error"
  set-current-plot-pen "behaviour"
  let ie 0
  ask turtles [ set ie ie + id-error-behaviour ]
  set ie ie / count turtles
  plot ie
  set-current-plot-pen "social"
  set ie 0
  ask turtles [ set ie ie + id-error-social ]
  set ie ie / count turtles
  plot ie
  
  
  set-current-plot "Values"
  set-current-plot-pen "Producer"
  plot value-P
  set-current-plot-pen "Conservationist"
  plot value-C
  set-current-plot-pen "Diversifier"
  plot value-D
  
  
  set-current-plot "Contacts"
  let ccounts []
  ask turtles
  [
    set ccounts fput (count out-link-neighbors) ccounts
  ]
  histogram ccounts

  set-current-plot "cluster"
  let cc []
  ask turtles
  [
    set cc fput cluster-coefficient cc
  ]
  histogram cc
  set mean-cluster-coefficient mean cc
end 

to export-turtle-data [ filename ]
  
  ;export all turtle data to file
  
  with-local-randomness ;so that runs do not differ for same seed regardless of whether data is exported
  [
    
    file-open filename
    
    if(ticks = 0)
    [
      file-print date-and-time
      file-print "Tick,Agent,id-error-behaviour,id-error-social,wealth,profit,yield,count-contacts,cluster-coeff,id-standard-P,id-standard-D,id-standard-C,id-standard-A,id-expressed-P,id-expressed-D,id-expressed-C,id-expressed-A,count-behaviours,behaviour-available-P,behaviour-available-D,behaviour-available-C,behaviour-available-A"
    ]
    
    ask turtles
    [
      file-type ticks
      file-type ","
      file-type who
      file-type ","
      file-type id-error-behaviour
      file-type ","
      file-type id-error-social
      file-type ","
      file-type wealth
      file-type ","
      file-type profit
      file-type ","
      file-type yield
      file-type ","
      file-type count my-out-links
      file-type ","
      file-type cluster-coefficient
      file-type ","
      
      foreach id-standard [ file-type precision ? 2 file-type "," ]
      
      foreach id-expressed [ file-type precision ? 2 file-type "," ]
      
      let sum-behaviours 0
      ask behaviours-expressed [ if([behaviour] of self != nobody) [set sum-behaviours sum-behaviours + 1 ] ]
      
      file-type sum-behaviours
      
      foreach behaviours-available [ file-type "," file-type ? ]
      
      file-print ""     
    ]
    
    file-close
  ]  
end 

to check-sliders

 ;check that initial-id-standard and initial-expressed sliders sum to 1.0
  
  if(initial-standards = "Homogeneous" or initial-standards = "Distribution")
 [
   let sum-standards id-standard-P + id-standard-A + id-standard-D + id-standard-C
   if(sum-standards <= 0.96 or sum-standards >= 1.04) ;to avoid internal netLogo rounding where sum = 0.999999
   [
     user-message ("Sum of id-standard sliders must = 1. Please amend")
     stop
   ]
 ]
 
 if(initial-expressed = "Homogeneous" or initial-expressed = "Distribution")
 [
   let sum-expressed expressed-P + expressed-A + expressed-D + expressed-C
   if(sum-expressed <= 0.96 or sum-expressed >= 1.04) ;to avoid internal netLogo rounding where sum = 0.999999
   [
     user-message ("Sum of behaviours-expressed sliders must = 1. Please amend")
     stop
   ]
 ]
end 

to read-behaviours-available-from-file
 
 
 ask turtles [ set behaviours-available-lists [] ]
  
  ;if variable in time, input file must include data for year 0!
 file-close-all 
 
 file-open behaviours-scenario-filename
 
 let header file-read-line      ;read first line headers
 let counter 0
 
 while [not file-at-end?]
 [
   set counter 0
   
   while[counter < count turtles]
   [
     let turtle-id 0
     if(not b-a_uniformAgents) [ set turtle-id file-read ] ;there will be no agent id if behaviours-available are uniform for all agents
     
     let data-list []   
     set data-list file-read
     
     ifelse(b-a_uniformAgents)
     [
       ask turtles 
       [
         ;if data are uniform across all agents, just get this data-list (line of the input file) once and copy for all turtles
         add-available-behaviours-list data-list
       ]
     ]
     
     [
       ask turtle turtle-id
       [
         ;otherwise only add this data-list (line of the input file) for the appropriate agent
         add-available-behaviours-list data-list
         set counter counter + 1
       ]
     ]
   ]
 ]
   
 file-close 

 ;at this point behaviours-available lists have been read for all timesteps, but because a stack has been used (fput) data are in reverse order
 ;remove-ticks-from-behaviours-available-lists reverses lists to they are back in order of input file (at the same time as removing ticks from the sub-lists)
 ask turtles 
 [
   set behaviours-available-lists reverse-list-of-lists behaviours-available-lists true
 ]
end 

to read-values-from-file
  
 ;if variable in time, input file must include data for year 0!
 file-close-all 
 
 file-open values-scenario-filename
 
 set values-scenario-list []
 let header file-read-line      ;read first line headers
  
 while [not file-at-end?]
 [
   let data-list []   
   set data-list file-read
   set values-scenario-list fput data-list values-scenario-list
 ]
   
 file-close 

 set values-scenario-list reverse-list-of-lists values-scenario-list true
 
 print values-scenario-list
end 

to update-values-from-file
  
  ;get values from list of values initially read during setup
  
  let temp-values first values-scenario-list
  
  set value-P item 0 temp-values
  set value-D item 1 temp-values
  set value-C item 2 temp-values
  
  set values-scenario-list but-first values-scenario-list ;remove these value ready for next timestep
end 

to add-available-behaviours-list [ data-list ]
  
  ;get available behaviours from list (with check that tick values are sequential)
  
  if(not empty? behaviours-available-lists) ;if not first addition, check data is for subsequent tick
  [
    let this-tick first data-list
  
    let check-list first behaviours-available-lists  
    let check-tick first check-list
    
    if(this-tick - check-tick != 1)
    [
      ifelse(b-a_uniformAgents) 
      [ user-message (word "Error in behaviours-available file: ticks not in sequence (uniformAgents) at tick" this-tick) ]
      [ user-message (word "Error in behaviours-available file: ticks not in sequence for turtle " who " at tick" this-tick) ]
      stop
    ]
  ]
  
  ;push the new list  
  set behaviours-available-lists fput data-list behaviours-available-lists
end 

to-report reverse-list-of-lists [ list-of-lists remove-first-item ]

  ;this function takes a list of lists, optionally removes the first item from each sub-list, and reverses orders of the lists
  ;e.g. when remove-first-item = true input: [[ 1 2 3 4 ] [ 4 3 2 1 ] [ 5 6 7 8 ]] output: [[ 6 7 8 ] [ 3 2 1 ] [ 2 3 4 ]]
  ;e.g. when remove-first-item = false input: [[ 1 2 3 4 ] [ 4 3 2 1 ] [ 5 6 7 8 ]] output: [[ 5 6 7 8 ] [ 4 3 2 1 ] [ 1 2 3 4 ]]
 
  let temp-lists []  ;temp list of lists (will replace original with this list after all ticks have been removed)
    
  foreach(list-of-lists)
  [
    let this-list ?  ;get the list (which includes tick in position 0)
    
    if(remove-first-item = true) [ set this-list but-first this-list ]  ;pop first element (e.g. remove the tick)
    
    set temp-lists fput this-list temp-lists  ;add (push) the new list with tick removed to temp list of list
  ]
    
  report temp-lists
end 

to set-year-behaviours-available

  ;if behaviours available are specified by file, this procedure gets the behaviours available for this timestep

  if(empty? behaviours-available-lists) 
  [
    user-message word "Error in behaviours-available file: no data for this tick (turtle" who 
    stop
  ] 

  set behaviours-available first behaviours-available-lists
  set behaviours-available-lists but-first behaviours-available-lists ;once we have read the data for this timestep, remove from the list
end 

to check-behaviours-available
  
  ;checks logic of behaviours-available switches. see user-message below

  if(scenario-from-file? = true and use-values? = false)
  [
    if(b-a_uniformTime and b-a_uniformAgents) [ user-message "Both b-a_uniformTime and b-a_uniformAgents cannot be 'on'." ]
    stop
  ]
end 

to set-random-behaviours

  ;randomly distribute available behaviours between turtles
  
  ask turtles [ set behaviours-available [ 0 0 0 0 ] ]
    
  let P-agents (available-P * count turtles)
  let D-agents (available-D * count turtles)
  let C-agents (available-C * count turtles)
  let A-agents (available-A * count turtles)    
  
  ask n-of P-agents turtles [ set behaviours-available replace-item 0 behaviours-available 1 ]
  ask n-of D-agents turtles [ set behaviours-available replace-item 1 behaviours-available 1 ]
  ask n-of C-agents turtles [ set behaviours-available replace-item 2 behaviours-available 1 ]
  ask n-of A-agents turtles [ set behaviours-available replace-item 3 behaviours-available 1 ]
end 

to calc-network-density
  
  ;calculates network density (proportion of links given maximum number possible)
  
  set network-density 0
  
  let all-links 0

  ask turtles [ set all-links all-links + count out-link-neighbors ]
  
  let max-links count turtles * (count turtles - 1)
  
  set network-density all-links / max-links
end 

to calc-cluster-coefficient

  ;calculates cluster coefficient for a turtle
  ;method after that described in Hamill and Gilbert (2009) http://jasss.soc.surrey.ac.uk/12/2/3.html

  let cc []
 
  let contacts-list sort out-link-neighbors
  
  ifelse(any? out-link-neighbors)
  [ 
    ask out-link-neighbors
    [
      let c-contacts-list sort out-link-neighbors
      let overlap count-duplicates contacts-list c-contacts-list
      
      ifelse(overlap > 0)
      [ set cc fput (overlap / ((length contacts-list) - 1)) cc ]
      [ set cc fput 0 cc ]
    ]
    
    set cluster-coefficient precision mean cc 2
  ]
  [ set cluster-coefficient 0 ]
end 

to-report count-duplicates [ listA listB ]
  
  ;report number of time a value in listA appears in listB
  
  let duplicates 0
  
  foreach listA
  [
    if(member? ? listB) [ set duplicates duplicates + 1 ]
  ]
  
  report duplicates
end 

to setup-meeting-points

  ;set appropriate patches to meeting points and change colour of patch

  if(meeting-point?)
  [
    ifelse(multiple-meeting-points?)
    [
      let tleft patches with [ pxcor = min-pxcor and pycor = max-pycor]
      let tright patches with [ pxcor = max-pxcor and pycor = max-pycor]
      let bleft patches with [ pxcor = min-pxcor and pycor = min-pycor]
      let bright patches with [ pxcor = max-pxcor and pycor = min-pycor]
      
      set production-meeting-points (patch-set tleft tright bleft bright)
      ask production-meeting-points [ set pcolor yellow ]
    ]
    
    [
      set production-meeting-points patch 0 0
      ask production-meeting-points [ set pcolor yellow ]
    ]
    
    set diversification-meeting-point patch -1 0
    ask diversification-meeting-point [ set pcolor grey ]
    
    set conservation-meeting-point patch 1 0
    ask conservation-meeting-point [ set pcolor green ] 
  ]
end 

to remove-contacts
  
  ;remove links between agents if your most salient behaviour (in id-standard) differs from their top behaviour expressed (but NOT if you also have that behaviour as top expressed)
  
  let most-similar nobody
  
  if(any? out-link-neighbors)
  [ 
    let idP hierarchy-position 0 id-standard
    let idD hierarchy-position 1 id-standard
    let idC hierarchy-position 2 id-standard
    let idA hierarchy-position 3 id-standard
    
    let eP hierarchy-position 0 id-expressed
    let eD hierarchy-position 1 id-expressed
    let eC hierarchy-position 2 id-expressed
    let eA hierarchy-position 3 id-expressed
        
    let kill false
    
    ask out-link-neighbors
    [
        let P hierarchy-position 0 id-expressed
        let D hierarchy-position 1 id-expressed
        let C hierarchy-position 2 id-expressed
        let A hierarchy-position 3 id-expressed
          
        if(idP <= 0 or P <= 0) ;if P is in top position of either agent's hierarchy, check it is in same position (don't kill if lower salience sub-identities do not have identical rank)
        [ 
          if(idP != P and eP != 0) [ set kill true ] 
        ]  
         
        if(idD <= 0 or D <= 0) 
        [ 
          if(idD != D and eD != 0) [ set kill true ] 
        ]  
          
        if(idC <= 0 or C <= 0) 
        [ 
          if(idC != C and eC != 0) [ set kill true ] 
        ]  
        
        if(idA <= 0 or A <= 0) 
        [ 
          if(idA != A and eA != 0) [ set kill true ] 
        ]  
          
        
        if(can-ignore-neighbours? = false ) ;do not kill direct (in space) neighbours 
        [ 
          if(not empty? neighbours-list) 
          [ 
            if(member? [who] of myself neighbours-list) [ set kill false ] 
          ]
        ]
        
        
        if(kill = true) 
        [ 
          if(in-link-from myself != nobody) [ ask in-link-from myself [die] ]
          if(out-link-to myself != nobody) [ ask out-link-to myself [die] ]
        ]    
    ]
  ]
end 

to setup-yield
  
  ;sets patch-yield in setup (later is used to set turtle yield when variable-yield? = "From Map")
  
  ifelse(variable-yield? = "From Map") 
  [
    if (yield-map = "Gradient") [ask patches [ set patch-yield 0.75 + ( pxcor / (max-pxcor * 4) ) ]] ;gradient of yield from low to high (left to right) with mean 0.75
    if (yield-map = "Uniform") [ask patches [ set patch-yield 0.75 ]] ;all patches have patch-yield = 0.75
    if (yield-map = "Quarters")  ;split world into four quarters - all patches within a quarter have uniform patch-yield
    [
      ask patches 
      [ 
        if (pxcor <= 0 and pycor <= 0) [ set patch-yield 0.5 ]
        if (pxcor > 0 and pycor <= 0) [ set patch-yield 0.66 ]
        if (pxcor <= 0 and pycor > 0) [ set patch-yield 0.83 ]
        if (pxcor > 0 and pycor > 0) [ set patch-yield 1 ]
      ]
    ]
    
    if (yield-map = "Grid")  ;split world into 10 by 10 grid of patches - patches within each grid cell have uniform patch-yield with one of four values
    [
      let square (world-width - 1) / 10
      let min-x min-pxcor
      let min-y min-pycor
      let max-x min-x + square 
      let max-y min-y + square
      
      let counter 0 
      
      ;loop thtough grid setting patch-yield
      while[min-x < max-pxcor]
      [
        while[min-y < max-pycor]
        [
          ask patches with [ pxcor >= min-x and pxcor < max-x and pycor >= min-y and pycor < max-y]
          [
            if(counter = 0) [ set patch-yield 0.5 ]
            if(counter = 1) [ set patch-yield 0.66 ]
            if(counter = 2) [ set patch-yield 0.83 ]
            if(counter = 3) [ set patch-yield 1 ]
          ]
          
          set counter counter + 1
          if(counter = 4) [ set counter 0 ]
          
          set min-y max-y
          set max-y min-y + square
        ]
        
        set min-y min-pycor
        set max-y min-y + square
      
        set min-x max-x
        set max-x min-x + square
      ]      
    ]
     
  ]  
  
  [ask patches [ set patch-yield 1 ]] ;if turtles do not set their yield from the map, set patch-yield for all patches to 1 
end 

to re-display
  
  ;reset the display of the world
  
  ;show patch yield or behaviour?
  ifelse(display-yield? = false)
  [
    ask patches [ set pcolor white ]
    ask turtles [ display-behaviours st ]   
    
    if(meeting-point? = true)
    [
      ask production-meeting-points [ set pcolor yellow ]
      ask diversification-meeting-point [ set pcolor grey ]
      ask conservation-meeting-point [ set pcolor green ]
    ]
    
    ;show links?  
    ifelse(show-links? = false)
    [ ask links [ set hidden? true ] ]
    [ 
      ifelse(show-agent-links < number-of-agents) ;if show-agent-links slider is set to greater than number of turtles, all links are shown, otherwise just the specific turtle 
      [
        ask links [ set hidden? true ]
        ask turtles with [ who = show-agent-links ] [ ask my-out-links [ set hidden? false ] ] 
      ]
      [ ask links [ set hidden? false ] ]
      
    ]
  ]
  [
    ask turtles
    [
      ht
      ask links [ set hidden? true ]
    ]
    
    ask patches [ set pcolor scale-color yellow patch-yield 0.5 1 ]
  ]
end 

to setup-filenames
  
  ;use next-index procedure to check if file exists
  
  let prefix "IdentityChange_AgentData"
  let suffix ".csv"
  let index next-index prefix suffix
  set turtle-output-filename (word prefix index suffix)
  
  set prefix "ValuesScenario"
  set suffix ".txt"
  set values-scenario-filename (word prefix scenario-id suffix)
  
  set prefix "IdentityChange_Interface"
  set suffix ".png"
  set index next-index prefix suffix
  set interface-filename (word prefix index suffix)

  if(b-a_uniformAgents) [ set prefix "behaviours-available_uniformAgents"]
  if(b-a_uniformTime) [ set prefix "behaviours-available_uniformTime" ]
  if(not b-a_uniformTime and not b-a_uniformAgents) [ set prefix "behaviours-available_all" ]
  
  set suffix ".txt"
  set behaviours-scenario-filename (word prefix scenario-id suffix)
end 

to-report next-index [ prefix suffix ]
  
  ;find the first value that can be used to create a unique filename using prefic and suffix
  ;after James Steiner (I believe)
  
  let index 0
  let filename (word prefix index suffix )
  while [ file-exists? filename ]
  [ 
    set index index + 1
    set filename (word prefix index suffix )
  ]
  report index
end 

There is only one version of this model, created over 12 years ago by James Millington.

Attached files

File Type Description Last updated
Farmer Social Psychology (iEMSs2012).png preview Preview for 'Farmer Social Psychology (iEMSs2012)' over 11 years ago, by James Millington Download
iEMSs12ExampleScenarios.zip data Example scenarios for use with the model over 11 years ago, by James Millington Download

This model does not have any ancestors.

This model does not have any descendants.