(*******************************************************************
This file was generated automatically by the Mathematica front end.
It contains Initialization cells from a Notebook file, which
typically will have the same name as this file except ending in
".nb" instead of ".m".

This file is intended to be loaded into the Mathematica kernel using
the package loading commands Get or Needs.  Doing so is equivalent
to using the Evaluate Initialization Cells menu command in the front
end.

DO NOT EDIT THIS FILE.  This entire file is regenerated
automatically each time the parent Notebook file is saved in the
Mathematica front end.  Any changes you make to this file will be
overwritten.
***********************************************************************)









BeginPackage[
    "LocalInteractions`LocalInteractions`",
    {"JLink`","Statistics`ContinuousDistributions`","DiscreteMath`Combinatorica`",
      "Graphics`Colors`"}
    ];

AddToClassPath[$UserBaseDirectory];

Begin["`Private`"];
MakeUsageMessage[symbol_,
      string_]:=(symbol::usage=
        string<>" \!\(\*ButtonBox[\(More\[Ellipsis]\),ButtonStyle->\"AddOnsLink\",ButtonData:>\""<>
          ToString[symbol]<>"\"]\)");
End[];

Unprotect[
    AgentQ,
    Agents,
    ButtonPanel,
    BestResponse,
    ControlPanel,
    CreateButton,
    CreateProgressBar,
    Data,
    DeleteModel,
    DisplayPause,
    EditGraph,
    Evolve,
    ExtractGraph,
    Generations,
    GetAgent,
    GraphicsEngine,
    ImitateBestNeighbor,
    IncrementProgressBar,
    InitialStrategyDistribution,
    InteractionNeighborhood,
    InteractionNeighborhoodColor,
    InteractionNeighborhoodColor,
    InteractionNeighbors,
    LearningRule,
    LocalInteractionModel,
    ModelQ,
    Neighborhoods,
    NeighborhoodsToDraw,
    NeighborhoodStyle,
    NeighborhoodStyle,
    NumberOfAgents,
    ObservedStrategies,
    PayoffMatrix,
    PrisonersDilemma,
    RandomElement,
    RandomGenerator,
    RandomSeed,
    RandomStrategy,
    RasterLatticeRepresentation,
    Score,
    SetData,
    SetLearningRule,
    SetNextStrategy,
    SetStrategies,
    SetStrategy,
    ShowOptions,
    ShowVertexNumbers,
    ShowWindow,
    Strategies,
    Strategy,
    StrategyColors,
    StrategyDistribution,
    StrategyHistogram,
    StrategyLegend,
    ToColorArray,
    Undirected,
    UpdateDisplay,
    UpdateNeighborhood,
    UpdateNeighborhoodColor,
    UpdateNeighbors,
    UseInteractionNeighborhoodWeights,
    UseUpdateNeighborhoodWeights,
    Weight,
    WindowLabel
    ];



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[Data,
    "Data[agent] returns the data (a Mathematica expression) stored in the agent."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    InteractionNeighbors,
    "InteractionNeighbors[agent] returns the list of the interaction neighbors of agent."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[UpdateNeighbors,
    "UpdateNeighbors[agent] returns the list of the interaction neighbors of agent."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    Strategy,
    "Strategy[agent] returns the strategy of agent."];



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    Score,
    "Score[agent] returns the current score of agent. It is set to 0 at the start of every round of interaction."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[LearningRule,
    "LearningRule[agent] returns the learning rule of agent. It may be either a Java object or a Mathematica function symbol."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    PayoffMatrix,
    "PayoffMatrix[agent] returns the payoff matrix of agent."];



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    ObservedStrategies,
    "ObservedStrategies[agent] returns a list of the strategies observed by agent in the last round of interaction. A strategy is observed if and only if it was held by someone agent interacted with."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[SetNextStrategy,
    "SetNextStrategy[agent,nextStrategy] tells agent to adopt nextStrategy at the end of the next round of strategic updating."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    SetData,
    "SetData[agent,expr] changes the data stored in agent to expr. The variable expr can be any Mathematica expression, most commonly it is a list of values."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[SetLearningRule,
    "SetLearningRule[agent,lr] sets the learning rule of agent to lr. The learning rule lr can be either a Java object conforming to the LearningRule interface or a Mathematica function that takes an agent as its single argument."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    Strategies,
    "Strategies[m] returns the list of strategies for the model m. The ith strategy in the list is the strategy of the agent with index i in the model."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    StrategyHistogram,
    "StrategyHistogram[m] returns a list {c1, c2, ..., cN} where ci is the total number of individuals following strategy i in m."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    StrategyDistribution,
    "StrategyDistribution[m] returns a list {f1, f2, ..., fN} where fi is the fraction of individuals following strategy i in m."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[ToColorArray,
    "ToColorArray[m] returns a list {r1,r2,...,rN} of RGBColor directives where the ith RGBColor directive is the color used to represent the current strategy of agent i in m."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[PrisonersDilemma,
    "PrisonersDilemma[T,R,P,S] creates the payoff matrix {{{R, R},{S, T}}, {{T, S},{P, P}}}, which will have the form of the Prisoner's Dilemma provide that T>R>P>S and T+S/2<R."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    CreateProgressBar,
    "CreateProgressBar[i, label] displays a Java frame containing label and a progress bar with a maximum value of i. It returns the progress bar as a Java object, which may then be passed as the argument of IncrementProgressBar[bar]. When completed, the progress bar must be released by calling ReleaseJavaObject[bar]."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    IncrementProgressBar,
    "IncrementProgressBar[bar] increments the progress indicator bar by one."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[RandomElement,
    "RandomElement[list] selects a randomly chosen element from list."];



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[RandomStrategy,
    "RandomStrategy[i] selects a random strategy between {1,...,i}. It is defined simply as Random[Integer, {1,i}]"]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[ControlPanel,
    "ControlPanel[model, N] constructs a basic control panel for model, in which N strategies are present. The number of strategies N is used by the Reset Model button, which reinitializes the strategies of all agents according to a uniform distribution over {1,2,...,N}."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    ButtonPanel,
    "ButtonPanel[button1,button2,...] constructs a panel of buttons in which button1, button2,... are laid out horizontally."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[CreateButton,
    "CreateButton[l,f] creates a button having label l which, when pressed, invokes function f. CreateButton[m,l,f] creates a button having label l and function f whose ButtonData is set to m."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    GetAgent,
    "GetAgent[model,i] returns the ith agent of model."];



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    Agents,
    "Agents[model] returns a list of all agents in model. Agents[model,{i1,i2,...,iK}] returns a list of agents i1, i2,...,iK."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    AgentQ,
    "AgentQ[expr] gives True if expr is an agent, and False otherwise."];



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    ModelQ,
    "ModelQ[expr] gives True if expr is a model, and False otherwise."];



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    UpdateNeighborhood,
    "UpdateNeighborhood[model] gives the update neighborhood of model as a Combinatorica graph."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    InteractionNeighborhood,
    "InteractionNeighborhood[model] gives the interaction neighborhood of model as a Combinatorica graph."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    NumberOfAgents,
    "NumberOfAgents[model] gives the number of agents in model."];



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    RasterLatticeRepresentation,
    "RasterLatticeRepresentation[model,W] shows a 2d raster array representation of the agents in model, using W as the width of the raster array. Passing the option Show->False returns a graphics image."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[ExtractGraph,
    "ExtractGraph[model] gives a Combinatorica graph representing the current state of model, where the ith vertex is colored according to the currently held strategy of agent i."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    SetStrategy,
    "SetStrategy[agent,strategy] changes the current strategy of agent to strategy. Passing the option UpdateDisplay->False will cause the view (if shown) to not redraw itself after the change."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[SetStrategies,
    "SetStrategies[model,list] sets the strategies of the agents in model to the strategies specified in list. The length of list must equal the number of agents in the model. SetStrategies[model, s] sets the strategies of all agents in model to s. SetStrategies[{a1,a2,...,aK}, {s1,s2,...,sK}] sets the strategy of ai to si."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    Evolve,
    "Evolve[model] steps model forward one iteration."];



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    EditGraph,
    "EditGraph[g] opens up a Java graph editor for the graph g. To return the graph to Mathematica, copy the graph definition to the clipboard."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[StrategyLegend,
    "StrategyLegend[colors] displays a legend for colors using default labels 'Strategy 1', 'Strategy 2',.... StrategyLegend[colors,labels] displays a legend using the specified labels. The colors must be RGBColor graphics primitives."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    DeleteModel,
    "DeleteModel[m] deletes the model m, closes the view window (if it exists), and frees as many Java resources as possible."]\
;



LocalInteractions`LocalInteractions`Private`MakeUsageMessage[
    LocalInteractionModel,
    "LocalInteractionModel[opts] gives a local interaction model constructed according to the specified options."]\
;





Begin["`Private`"];







LocalInteractionModel::grapherr1="The object specified for the `1` is not a graph";

LocalInteractionModel::grapherr2="The interaction and update neighborhoods do not have the same number of vertices.";

LocalInteractionModel::colorerr1="The number of colors specified for strategies does not equal the total number of possible strategies.";

LocalInteractionModel::colorerr2="The list of colors specified for strategies contains items other than RGBColor expressions.";

LocalInteractionModel::ruleerr="Unrecognized LearningRule. Defaulting to ImitateBestNeighbor";

LocalInteractions::objecterr="Specified object not of type `1`";

Options[LocalInteractionModel]=
    {
      GraphicsEngine\[Rule]Java,
      InitialStrategyDistribution\[Rule]Uniform,
      InteractionNeighborhoodColor\[Rule]Black,
      LearningRule\[Rule]ImitateBestNeighbor,
      NeighborhoodsToDraw\[Rule]Automatic,
      NeighborhoodStyle\[Rule]Automatic,
      PayoffMatrix\[Rule]{{{2,1},{0,0}},{{0,0},{1,2}}},
      RandomGenerator\[Rule]Java,
      RandomSeed\[Rule]None,
      ShowVertexNumbers\[Rule]False,
      ShowWindow\[Rule]True,
      StrategyColors\[Rule]{Red,Green},
      UpdateNeighborhoodColor\[Rule]Blue,
      UseInteractionNeighborhoodWeights\[Rule]False,
      UseUpdateNeighborhoodWeights\[Rule]False,
      WindowLabel\[Rule]"Network model",
      InteractionNeighborhood\[RuleDelayed]GridGraph[10,10],
      UpdateNeighborhood\[RuleDelayed]RandomGraph[10,10]
      };

LocalInteractionModel[opts___]:=Module[
    (*Local variables*)
    {intNbhd,upNbhd,d,e,edgesWeighted,adjList,
      strategies,colors,numAgents,pm,pms,l,i,s,engine,numStrategies,lr,
      unColor,intColor,gr,nbhdsToDraw,nbhdStyle,showVNums,b1,b2,r,rg,sw,
      combGraphObject,intAndUpdateNbhdsTheSame},
    
    intAndUpdateNbhdsTheSame=False;
    
    (*Grab the defaults*)
    defaults=Options[LocalInteractionModel];
    intNbhd=InteractionNeighborhood/.{opts}/.defaults;
    
    (*Check that the interaction neighborhood is a graph*)
    
    If[Head[intNbhd]=!=Graph,
      Message[LocalInteractionModel::grapherr1,"interaction neighborhood"];
      Return[];
      ];
    
    (*Verify that the update neighborhood is a graph*)
    
    upNbhd=UpdateNeighborhood/.{opts};
    If[Head[upNbhd]=!=Graph&&upNbhd=!=UpdateNeighborhood,
      Message[LocalInteractionModel::grapherr1,"update neighborhood"];
      Return[];
      ];
    
    (*Determine what neighborhoods to draw*)
    
    nbhdsToDraw=NeighborhoodsToDraw/.{opts}/.defaults;
    If[upNbhd===UpdateNeighborhood,
      Module[{},
        upNbhd=intNbhd;
        intAndUpdateNbhdsTheSame=True;
        If[nbhdsToDraw===Automatic,
          nbhdsToDraw={Interaction}
          ]],
      Module[{},
        If[nbhdsToDraw===Automatic,
          nbhdsToDraw={Interaction,Update}]]
      ];
    
    (*Verify the number of nodes in each neighborhood agree*)
    
    If[V[intNbhd]\[NotEqual]V[upNbhd],
      Message[LocalInteractionModel::grapherr2];
      Return[];
      ];
    
    (*Check what random generator to use*)
    
    rg=RandomGenerator/.{opts}/.defaults;
    
    numAgents=V[intNbhd];
    If[rg===Mathematica,
      m=JavaNew["Model",numAgents,True],
      m=JavaNew["Model",numAgents,False]
      ];
    
    (*If a random seed was specified, 
      pass it to the model now before any random calls get made*)
    
    r=RandomSeed/.{opts}/.defaults;
    If[IntegerQ[r],m@setRandomSeed[r]];
    
    (*Now create the agents...do this after setting the seed in case the \
agent constructors make random calls.*)
    m@createAgents[];
    
    (*Set the learning rules*)
    lr=LearningRule/.{opts}/.defaults;
    
    JavaBlock[
      Module[{rule},
          Which[
            lr===ImitateBestNeighbor,
            rule=JavaNew["ImitateBestNeighbor"],
            
            lr===BestResponse,
            rule=JavaNew["BestResponse"],
            
            lr===ImitateBestAverageStrategy,
            rule=JavaNew["ImitateBestNormalizedScore"],
            
            lr===MoveTowardsBestNeighbor,
            rule=JavaNew["MoveTowardsBestNeighbor"],
            
            True,
            Module[{},
              Message[LocalInteractionModel::ruleerr];
              rule=JavaNew["ImitateBestNeighbor"];
              ]
            ];
          m@setLearningRule[rule];
          ];
      ];
    
    combGraphObject=BuildGraph[intNbhd];
    m@setInteractionNeighborhood[combGraphObject];
    
    edgesWeighted=UseInteractionNeighborhoodWeights/.{opts}/.defaults;
    WireInteractionNeighborhood[m,intNbhd];
    (*
      
      edgesWeighted=UseInteractionNeighborhoodWeights/.{opts}/.defaults;
      If[UndirectedQ[intNbhd],b1=1.0,b1=0.0];
      If[edgesWeighted,b2=1.0,b2=0.0];
      If[edgesWeighted,
        m@addEdgesToInteractionNeighborhood[
            MapThread[
              Function[{e,w},{e[[1]],e[[2]],w,b1,b2}],{Edges[intNbhd]-1,
                GetEdgeWeights[intNbhd]}]],
        m@wireInteractionNeighborhood[Edges[intNbhd]-1,UndirectedQ[intNbhd]]
        ];
      *)
    
    If[intAndUpdateNbhdsTheSame\[Equal]True,
      m@setUpdateNeighborhood[combGraphObject],
      JavaBlock[
        m@setUpdateNeighborhood[
            BuildGraph[upNbhd]
            ]
        ]
      ];
    ReleaseJavaObject[combGraphObject];
    
    edgesWeighted=UseUpdateNeighborhoodWeights/.{opts}/.defaults;
    WireUpdateNeighborhood[m,upNbhd];
    (*
      gr=MakeDirected[upNbhd,All];
      e=Edges[gr]-1;
      If[edgesWeighted,
        m@wireUpdateNeighborhoodWithProbabilities[
            MapThread[
              Function[{e,w},{e[[1]],e[[2]],w}],{e,GetEdgeWeights[gr]}]
            ],
        m@wireUpdateNeighborhood[e]
        ];
      *)
    
    (*
      
      This grabs one copy of the payoff matrix so that we can determine the \
number of strategies. 
          Actual assignment of the payoff matrix to individuals takes place \
later.
      *)
    pm=PayoffMatrix/.{opts}/.defaults;
    numStrategies=Length[pm];
    m@setNumberOfStrategies[numStrategies];
    
    strategies=InitialStrategyDistribution/.{opts}/.defaults;
    (*Construct the list of initial strategies*)
    If[strategies===Uniform,
      strategies=Table[Random[Integer,{1,numStrategies}],{i,numAgents}];
      ];
    
    strategies=strategies-1;
    If[StrategyListIsValidQ[strategies,numAgents,numStrategies],
      m@setStrategies[strategies],
      (*
        Strategy list isn't valid,so abort and complain. 
            Complaints notified by StrategyListIsValidQ
        *)
      ReleaseJavaObject[m];
      Return[];
      ];
    
    colors=StrategyColors/.{opts}/.defaults;
    s=numStrategies;
    If[colors===StrategyColors,
      colors=Table[RGBColor[(1.0/s)*i,(1.0/s)*i,(1.0/s)*i],{i,1,s}]
      ];
    
    If[Length[colors]\[NotEqual]numStrategies,
      Message[LocalInteractionModel::colorerr1];
      ReleaseJavaObject[m];
      Return[];
      ];
    
    If[And@@(Head[#1]===RGBColor&)/@colors,
      JavaBlock[
        colors=CreateJavaColor/@colors;
        m@setColors[colors]
        ],
      Message[LocalInteractionModel::colorerr2];
      ReleaseJavaObject[m];
      Return[];
      ];
    
    pms=Table[PayoffMatrix,{i,numAgents}]/.{opts}/.defaults;
    m@setPayoffMatrices[pms];
    gr=CreateNetworkGraph[intNbhd,upNbhd,nbhdsToDraw,opts];
    JavaBlock[
      m@setDisplayGraph[
          BuildGraph[NormalizeGraph[gr]]
          ]
      ];
    
    engine=GraphicsEngine/.{opts}/.defaults;
    l=WindowLabel/.{opts}/.defaults;
    sw=ShowWindow/.{opts}/.defaults;
    
    If[sw===True,
      m@createMainFrame[engine];
      If[RegisterShowVertexNumbersPreference[m,opts]===False,
        Return[]
        ];
      m@setLabel[l];
      m@showWindow[];
      ];
    Format[m]=
      "\[LeftGuillemet]\[ThinSpace]Local Interaction Model: "<>ToString[
          NumberOfAgents[m]]<>" agents, "<>ToString[numStrategies]<>
        " strategies\[ThinSpace]\[RightGuillemet]";
    Return[m]
    ]





MakeEdge[m_,e_,weight_,undirected_,weighted_]:=Module[{},
      m@addEdgeToInteractionNeighborhood[
          e[[1]]-1,
          e[[2]]-1,
          weight,
          undirected,
          weighted
          ]
      ];





Options[CreateNetworkGraph]={
      InteractionNeighborhoodColor\[Rule]Black,
      UpdateNeighborhoodColor\[Rule]Blue,
      NeighborhoodStyle\[Rule]Automatic
      };

CreateNetworkGraph[intNbhd_Graph,upNbhd_Graph,nbhdsToDraw_,opts___]:=
    
    Module[
      {intColor,unColor,nbhdStyle,gr,e,v,defaults},
      
      defaults=Options[CreateNetworkGraph];
      intColor=InteractionNeighborhoodColor/.{opts}/.defaults;
      unColor=UpdateNeighborhoodColor/.{opts}/.defaults;
      nbhdStyle=NeighborhoodStyle/.{opts}/.defaults;
      
      If[MemberQ[nbhdsToDraw,Interaction]\[And]MemberQ[nbhdsToDraw,Update],
        Which[
          nbhdStyle===Automatic,
          Module[{},
            e=CartesianProduct[
                Edges[MakeDirected[upNbhd]],{EdgeColor\[Rule]unColor}
                ];
            gr=AddEdges[SetGraphOptions[intNbhd,EdgeColor\[Rule]intColor],e]
            ],
          nbhdStyle===Directed,
          Module[{},
            e=CartesianProduct[
                Edges[MakeDirected[upNbhd]],{EdgeColor\[Rule]unColor}
                ];
            gr=MakeDirected[intNbhd];
            gr=AddEdges[SetGraphOptions[gr,EdgeColor\[Rule]intColor],e];
            ],
          nbhdStyle===Undirected,
          Module[{},
            e=CartesianProduct[
                Edges[MakeUndirected[upNbhd]],{EdgeColor\[Rule]unColor}
                ];
            gr=MakeUndirected[intNbhd];
            gr=AddEdges[SetGraphOptions[gr,EdgeColor\[Rule]intColor],e];
            ]
          ];
        Return[gr];
        ];
      
      If[MemberQ[nbhdsToDraw,Interaction]\[And]!MemberQ[nbhdsToDraw,Update],
        Module[{},
            Which[
              nbhdStyle===Automatic,
              gr=SetGraphOptions[intNbhd,EdgeColor\[Rule]intColor],
              nbhdStyle===Directed,
              
              gr=SetGraphOptions[MakeDirected[intNbhd],
                  EdgeColor\[Rule]intColor],
              nbhdStyle===Undirected,
              
              gr=SetGraphOptions[MakeUndirected[intNbhd],
                  EdgeColor\[Rule]intColor]
              ];
            Return[gr];
            ];
        ];
      
      If[!MemberQ[nbhdsToDraw,Interaction]\[And]MemberQ[nbhdsToDraw,Update],
        Module[{},
            Which[
              nbhdStyle===Automatic,
              gr=SetGraphOptions[upNbhd,EdgeColor\[Rule]unColor],
              nbhdStyle===Directed,
              
              gr=SetGraphOptions[MakeDirected[upNbhd],
                  EdgeColor\[Rule]unColor],
              nbhdStyle===Undirected,
              
              gr=SetGraphOptions[MakeUndirected[upNbhd],
                  EdgeColor\[Rule]unColor]
              ];
            Return[gr];
            ];
        ];
      
      If[!MemberQ[nbhdsToDraw,Interaction]\[And]!MemberQ[nbhdsToDraw,Update],
        gr=ChangeEdges[intNbhd,Edges[EmptyGraph[V[intNbhd]]]];
        Return[gr];
        ];
      ];







LocalInteractionModel::vertexnumerr="Option specified for ShowVertexNumbers was not True or False.";

RegisterShowVertexNumbersPreference[model_,opts___]:=
    Module[{defaults},
      defaults=Options[LocalInteractionModel];
      showVNums=ShowVertexNumbers/.{opts}/.defaults;
      Which[
        showVNums===True,model@showVertexNumbers[],
        showVNums===False,model@hideVertexNumbers[],
        True,(*Default condition... invoked only if ShowVertexNumbers is set \
to a meaningless condition.*)
        Module[{},
            ReleaseJavaObject[model];
            Message[LocalInteractionModel::vertexnumerr];
            Return[False];
            ];
        ];
      Return[True];
      ];







LocalInteractionModel::strategyerr1="The length of the vector specifying the initial strategy distribution (`1`) does not equal the number of agents in the model (`2`).";\
 

LocalInteractionModel::strategyerr2="The list of strategies `1` includes non-integer items.";

LocalInteractionModel::strategyerr3="The strategies appearing in the list do not all fall between 1 and `1`.";

StrategyListIsValidQ[l_List,numAgents_,numStrats_]:=Module[{len},
    len=Length[l];
    If[len\[NotEqual]numAgents,
      Message[LocalInteractionModel::strategyerr1,len,numAgents];
      Return[False];
      ];
    If[Apply[And,Map[IntegerQ,l]]\[NotEqual]True,
      Message[LocalInteractionModel::strategyerr2,l];
      Return[False]
      ];
    If[
      Apply[And,Map[(0\[LessEqual]#\[And]#\[LessEqual]numStrats)&,l]],
      Return[True],
      Module[{},
        Message[LocalInteractionModel::strategyerr3,numStrats];
        Return[False]
        ]
      ]
    ]



WireInteractionNeighborhood[m_,intNbhd_]:=
  Module[{edges,isDirectedList,isWeightedList,weightList,alist},
    edges=intNbhd\[LeftDoubleBracket]1\[RightDoubleBracket];
    isDirectedList=EdgeDirected/@edges;
    isWeightedList=EdgeWeighted/@edges;
    weightList=GetEdgeWeight/@edges;
    
    m@NEWWireInteractionNeighborhood[
        (First/@edges)-1,isDirectedList,isWeightedList,weightList
        ];
    
    (*
      alist={
          ChunkList[(First/@edges)-1],
          ChunkList[isDirectedList],
          ChunkList[isWeightedList],
          ChunkList[weightList]
          };
      
      MapThread[
        Function[{es,isDl,isWl,wL},
          m@NEWWireInteractionNeighborhood[es,isDl,isWl,wL];
          JavaGC[];
          ],alist
        ];
      *)
    ]



WireUpdateNeighborhood[m_,upNbhd_]:=
    Module[{edges,isDirectedList,isWeightedList,weightList,aList},
      edges=upNbhd\[LeftDoubleBracket]1\[RightDoubleBracket];
      isDirectedList=EdgeDirected/@edges;
      isWeightedList=EdgeWeighted/@edges;
      weightList=GetEdgeWeight/@edges;
      
      m@NEWWireUpdateNeighborhood[
          (First/@edges)-1,isDirectedList,isWeightedList,weightList
          ];
      
      (*
        alist={
            ChunkList[(First/@edges)-1],
            ChunkList[isDirectedList],
            ChunkList[isWeightedList],
            ChunkList[weightList]
            };
        
        MapThread[
          Function[{es,isDl,isWl,wL},
            m@NEWWireUpdateNeighborhood[es,isDl,isWl,wL];
            JavaGC[];
            ],alist
          ];
        *)
      ];







DeleteModel[m_?ModelQ]:=Module[{},
      m@hide[];
      ReleaseJavaObject[m]
      ];

DeleteModel[m___]:=Module[{},
      Scan[
        Function[x,x@hide[];ReleaseJavaObject[x]],
        {m}
        ]
      ];





StrategyLegend[l_List,labels_List]:=Module[{colors,g},
      colors=Table[
          FrameBox[
            StyleBox[
              AdjustmentBox["Stra",
                BoxMargins\[Rule]{{1,1},{1,1}}
                ],Background\[Rule]l[[i]],FontColor\[Rule]l[[i]]
              ],BoxMargins\[Rule]{{0,0},{0,0}}
            ],{i,1,Length[l]}];
      g=MapThread[
          {#1,#2}&,
          {colors,labels}
          ];
      Print[GridBox[g,ColumnAlignments\[Rule]Left]//DisplayForm]
      ];

StrategyLegend[l_List]:=Module[{colors,labels,g},
    labels=Table["Strategy "<>ToString[i],{i,1,Length[l]}];
    StrategyLegend[l,labels]//DisplayForm//Print
    ]





NormalizeGraph[g_Graph]:=Module[
    {v,h,w,g2},
    v=NormalizeVertices[Vertices[g]];
    w=Max[Map[First,v]];
    h=Max[Map[Last,v]];
    v=DilateVertices[
        TranslateVertices[v,{-w/2,-h/2}],3.7
        ];
    g2=ChangeVertices[g,v];
    Return[g2];
    ]







EditGraph[g_Graph]:=Module[{ge},
      ge=JavaNew["GraphEditor",NormalizeGraph[g]];
      ReleaseJavaObject[ge];
      ];





Options[Evolve]={
      UpdateDisplay\[Rule]True,
      DisplayPause\[Rule]0,
      Generations\[Rule]1
      };

Evolve[m_,opts___]:=Module[{defaults,disp,p,g},
      defaults=Options[Evolve];
      disp=UpdateDisplay/.{opts}/.defaults;
      p=DisplayPause/.{opts}/.defaults;
      g=Generations/.{opts}/.defaults;
      Do[
        If[disp===True,
          m@interact[],
          m@interact[False]
          ];
        Pause[p],{g}
        ];
      ];









GetEdgeWeight[{{_,_},___,EdgeWeight\[Rule]w_,___}]:=w;

GetEdgeWeight[{{_,_},___}]:=1.0;





GetEdgeColor[{{_,_},___}]:={0,0,0};

GetEdgeColor[{{_,_},___,EdgeColor\[Rule]RGBColor[r_,g_,b_],___}]:={r,g,b};

GetEdgeColor[{{_,_},___,EdgeColor\[Rule]GrayLevel[g_],___}]:={g,g,g};





EdgeWeighted[{{_,_},___,EdgeWeight\[Rule]w_,___}]:=True;

EdgeWeighted[{{_,_},___}]:=False;





EdgeDirected[{{_,_},___,EdgeDirection\[Rule]b_,___}]:=b;

EdgeDirected[{{_,_},___}]:=False;





BuildGraph[g_Graph]:=Module[{cg,e},
      cg=JavaNew["CombinatoricaGraph"];
      e=g\[LeftDoubleBracket]1\[RightDoubleBracket];
      cg@addVertices[Vertices[g]];
      If[M[g]\[NotEqual]0,
        cg@addEdges[Edges[g]];
        cg@changeEdgeWeightStatus[
            Map[EdgeWeighted,e]
            ];
        cg@changeEdgeWeights[
            Map[GetEdgeWeight,e]
            ];
        cg@changeEdgeColors[
            Map[GetEdgeColor,e]
            ];
        cg@changeEdgeDirectionStatus[
            Map[EdgeDirected,e]
            ];
        ];
      Return[cg]
      ];







SetStrategies::listlengtherr="The first and second lists are not of equal length.";

SetStrategies::liststrategyerr1="The second list is not a list of strategies (it has noninteger elements).";

SetStrategies::liststrategyerr2="The second list is not a list of strategies (it has integer elements less than or equal to 0).";

SetStrategies::liststrategyerr3="The strategy must be an integer greater than or equal to 0.";

SetStrategies::agentlisterr="The first list is not a list of Agent objects.";

Options[SetStrategies]={
      UpdateDisplay\[Rule]True
      };

SetStrategies[model_?ModelQ,l_List,opts___Rule]:=
  Module[{n,m,s,update,defaults},
    defaults=Options[SetStrategies];
    update=UpdateDisplay/.{opts}/.defaults;
    n=NumberOfAgents[model];
    s=model@getNumberOfStrategies[];
    If[StrategyListIsValidQ[l,n,s]===True,
      Module[{},
        model@setStrategies[l-1];
        If[update===True,
          model@updateDisplay[];
          ]
        ]
      ]
    ]

SetStrategies[model_?ModelQ,s_Integer,opts___Rule]:=
    Module[{n,m,defaults,update},
      n=NumberOfAgents[model];
      If[s\[LessEqual]0,
        Message[SetStrategies::liststrategyerr3];
        Return[];
        ];
      model@setStrategies[
          Table[s-1,{n}]
          ];
      
      defaults=Options[SetStrategies];
      update=UpdateDisplay/.{opts}/.defaults;
      If[update===True,
        model@updateDisplay[];
        ];
      ];

SetStrategies[l1_?VectorQ,l2_List,opts___Rule]:=
    
    Module[{defaults,update},
      If[Length[l1]\[NotEqual]Length[l2],
        Message[SetStrategies::listlengtherr];
        Return[];
        ];
      If[VectorQ[l2,IntegerQ]\[Equal]False,
        Message[SetStrategies::liststrategyerr1];
        Return[];
        ];
      If[VectorQ[l2,(#>0&)]\[Equal]False,
        Message[SetStrategies::liststrategyerr2];
        Return[];
        ];
      If[VectorQ[l1,AgentQ]\[Equal]False,
        Message[SetStrategies::agentlisterr];
        ];
      
      defaults=Options[SetStrategies];
      update=UpdateDisplay/.{opts}/.defaults;
      MapThread[
        Function[{a,s},a@setStrategyQuietly[s-1]],
        {l1,l2}
        ];
      If[update===True,
        m@updateDisplay[]
        ];
      ];

SetStrategies[l1_?VectorQ,i_Integer,opts___Rule]:=
    
    SetStrategies[l1,Table[i,{Length[l1]}],opts];





SetStrategy[agent_?AgentQ,s_?IntegerQ,opts___Rule]:=Module[{update},
      update=UpdateDisplay/.{opts};
      If[update===False,
        agent@setStrategyQuietly[s-1],
        agent@setStrategy[s-1]
        ];
      ];







CreateJavaColor[c_RGBColor]:=JavaNew["java.awt.Color",
    Floor[255*c\[LeftDoubleBracket]1\[RightDoubleBracket]],
    Floor[255*c\[LeftDoubleBracket]2\[RightDoubleBracket]],
    Floor[255*c\[LeftDoubleBracket]3\[RightDoubleBracket]]
    ]







ExtractGraph[m_]:=Module[{colors,g,v},
    JavaBlock[
      colors=ToColorArray[m];
      g=m@extractGraph[];
      v=Vertices[g,All];
      v=MapThread[Append[#1,VertexColor\[Rule]#2]&,{v,colors}];
      Return[ChangeVertices[g,v]];
      ]
    ]





Options[RasterLatticeRepresentation]={
      Show\[Rule]True,
      ShowOptions\[Rule]{AspectRatio\[Rule]Automatic}
      };

RasterLatticeRepresentation[m_,width_,opts___]:=Module[{s,defs,so},
      defs=Options[RasterLatticeRepresentation];
      Return[
        Graphics[
          RasterArray[
            Partition[ToColorArray[m],width]
            ],opts
          ]
        ]
      ];





NumberOfAgents[m_]:=m@getNumberOfAgents[]





InteractionNeighborhood[m_?ModelQ]:=
    m@sendInteractionNeighborhoodToMathematica[];





UpdateNeighborhood[m_?ModelQ]:=m@sendUpdateNeighborhoodToMathematica[];





ModelQ[m_]:=InstanceOf[m,"Model"];





AgentQ[a_]:=InstanceOf[a,"Agent"];







Agents[m_?ModelQ]:=m@getAgents[];



LocalInteractions::agentserr1="The list `1` of agent indexes contains noninteger items.";

LocalInteractions::agentserr2="Agent indexes for `1` must lie between 1 and `2`.";

Agents[m_?ModelQ,l_List]:=
    Module[{n,al},
      If[VectorQ[l,IntegerQ]\[Equal]False,
        Message[LocalInteractions::agentserr1,l];
        Return[];
        ];
      n=NumberOfAgents[m];
      If[Apply[And,Map[(1\[LessEqual]#\[And]#\[LessEqual]n)&,l]]\[Equal]
          False,
        Message[LocalInteractions::agentserr2,m,n];
        Return[];
        ];
      Return[Map[(Part[Agents[m],#])&,l]];
      ];





GetAgent[m_?ModelQ,i_Integer?Positive]:=Module[{n},
    n=NumberOfAgents[m];
    If[i>n,
      Message[LocalInteractions::agentserr2,m,n];
      Return[],
      Return[m@getAgent[i-1]]
      ]
    ]







Data[a_?AgentQ]:=a@getData[];





InteractionNeighbors[a_?AgentQ]:=a@getInteractionNeighbors[];





UpdateNeighbors[a_?AgentQ]:=a@getUpdateNeighbors[];







Strategy[a_?AgentQ]:=a@getStrategy[]+1;





Score[a_?AgentQ]:=a@getScore[];





LearningRule[a_?AgentQ]:=a@getLearningRule[];





PayoffMatrix[a_?AgentQ]:=a@getPayoffMatrix[]@getPayoffMatrix[];





ObservedStrategies[a_?AgentQ]:=a@strategiesIveSeen[];







SetNextStrategy[a_?AgentQ,s_Integer?Positive]:=a@setNextStrategy[s-1];





SetData[a_?AgentQ,e_]:=a@setData[e];





SetLearningRule[a_?AgentQ,e_]:=Module[{},
      If[InstanceOf[e,LoadJavaClass["LearningRule"]]\[Equal]True,
        a@setJavaLearningRule[e],
        a@setLearningRule[e];
        ]
      ];







Strategies[m_?ModelQ]:=m@getStrategies[]+1;





StrategyHistogram[m_?ModelQ]:=m@getStrategyTotals[];





StrategyDistribution[m_?ModelQ]:=m@getFrequencyDistribution[];





ToColorArray[model_?ModelQ]:=model@sendAgentColorsToMathematica[];







\!\(\*
  RowBox[{
    RowBox[{\(PrisonersDilemma[T_, R_, P_, S_]\), ":=", 
      RowBox[{"(", GridBox[{
            {\({R, R}\), \({S, T}\)},
            {\({T, S}\), \({P, P}\)}
            }], ")"}]}], ";"}]\)





CreateProgressBar[i_,t_]:=Module[{f,b,l},
      b=JavaNew["javax.swing.JProgressBar",0,i];
      JavaBlock[
        f=JavaNew["javax.swing.JFrame"];
        b@setString["0"];
        b@setStringPainted[True];
        l=JavaNew["javax.swing.JLabel",t];
        f@getContentPane[]@setLayout[JavaNew["java.awt.GridLayout",2,1]];
        f@getContentPane[]@add[l];
        f@getContentPane[]@add[b];
        f@pack[];
        f@setVisible[True];
        ];
      Return[b];
      ];





IncrementProgressBar[b_]:=Module[{v},
      v=b@getValue[]+1;
      b@setString[ToString[v]];
      b@setValue[v];
      ];





RandomElement[l_List]:=
    l[[Random[Integer,{1,Length[l]}]]];





RandomStrategy[numberOfStrategies_Integer]:=
    
    Random[Integer,{1,numberOfStrategies}];







ControlPanel[m_]:=Module[{numStrats},
      numStrats=m@getNumberOfStrategies[];
      ButtonPanel[
        CreateButton["Step 1",Evolve[m]&],
        CreateButton["Step 5",
          Evolve[m,Generations\[Rule]5,DisplayPause\[Rule].2]&],
        CreateButton["Step 10",
          Evolve[m,Generations\[Rule]10,DisplayPause\[Rule].2]&],
        CreateButton["Step 20",
          Evolve[m,Generations\[Rule]20,DisplayPause\[Rule].2]&],
        CreateButton["Reset model",
          ToExpression[
            ToString[
              StringForm[
                "Function[SetStrategies[m,
                Table[Random[Integer,{1,``}],{NumberOfAgents[m]}]
                ]]",numStrats
                ]
              ]
            ]
          ],
        CreateButton["Delete model",DeleteModel[m]&]
        ]
      ];

SetAttributes[ControlPanel,HoldFirst]





ButtonPanel[buttons___]:=
    Module[{},
      NotebookWrite[SelectedNotebook[],
        Cell[
          BoxData[
            GridBox[
              {{buttons}},
              RowSpacings\[Rule]0,ColumnSpacings\[Rule].25]],"Input"]
        ]
      ];





CreateButton[label_,f_]:=CreateButton[Null,label,f];

CreateButton[m_,label_,f_]:=ButtonBox[label,
      ButtonFunction\[RuleDelayed]f,
      ButtonEvaluator\[Rule]Automatic,
      ButtonData\[Rule]m,
      Active\[Rule]True];



ClearAttributes[ShowLabeledGraph,Protected];
ClearAttributes[ShowGraph,Protected];
ShowLabeledGraph[m_?JavaObjectQ]:=ShowLabeledGraph[ExtractGraph[m]];
ShowLabeledGraph[m_?JavaObjectQ,opts___]:=
    ShowLabeledGraph[ExtractGraph[m],opts];
ShowGraph[m_?JavaObjectQ]:=ShowGraph[ExtractGraph[m]];
ShowGraph[m_?JavaObjectQ,opts___]:=ShowGraph[ExtractGraph[m],opts];
SetAttributes[ShowLabeledGraph,Protected];
SetAttributes[ShowGraph,Protected];










ClearAttributes[AddEdge,Protected];
Options[AddEdge]={
      Weight\[Rule]None,
      Undirected\[Rule]True,
      Neighborhoods\[Rule]{Interaction,Update}
      };
SetAttributes[AddEdge,Protected];

ClearAttributes[AddEdge,Protected];

AddEdge::weighterr1="The specified edge weight is not a number.";
AddEdge::weighterr2="Edge weights must be between 0 and 1 inclusive.";
AddEdge::optionerr1="The Undirected option must be either True or False.";

AddEdge[m_?ModelQ,{one_,two_},opts___Rule]:=
  Module[{weight,undir,nbhds,useweight,defaults,isUndirected,isWeighted},
    defaults=Options[AddEdge];
    weight=Weight/.{opts}/.defaults;
    isWeighted=0.0;
    undir=Undirected/.{opts}/.defaults;
    nbhds=Neighborhoods/.{opts}/.defaults;
    
    (*Check for valid options*)
    
    If[undir\[Equal]True,isUndirected=1.0,isUndirected=0.0,
      Message[AddEdge::optionerr1];
      Return[]
      ];
    If[weight=!=None\[And]NumberQ[weight]\[Equal]False,
      Message[AddEdge::weighterr1];
      Return[],
      isWeighted=1.0
      ];
    If[(weight<0)\[Or](1<weight),
      Message[AddEdge;weighterr2];
      Return[]
      ];
    
    (*Add edge to specified neighborhoods*)
    
    If[MemberQ[nbhds,Interaction]\[Equal]True\[And]weight===None,
      m@addEdgeToInteractionNeighborhood[
          {one-1,two-1,1,isUndirected,isWeighted}
          ];
      m@addEdgeToGraphDisplay[one-1,two-1];
      ];
    If[MemberQ[nbhds,Interaction]\[Equal]True\[And]
        NumberQ[weight]\[Equal]True,
      m@addEdgeToInteractionNeighborhood[
          {one-1,two-1,weight,isUndirected,isWeighted}
          ];
      m@addEdgeToGraphDisplay[one-1,two-1];
      ];
    
    If[MemberQ[nbhds,Update]\[Equal]True\[And]weight===None,
      m@addEdgeToUpdateNeighborhood[one-1,two-1];
      ];
    If[MemberQ[nbhds,Update]\[Equal]True\[And]NumberQ[weight]\[Equal]True,
      m@addEdgeToUpdateNeighborhood[one-1,two-1,weight];
      ];
    ]

SetAttributes[AddEdge,Protected];







ClearAttributes[DeleteEdges,Protected];

DeleteEdges[m_?ModelQ,All]:=Module[{g,cg},
    (*Remove the edge information from agents*)
    m@deleteAllEdges[];
    (*
      
      Now remove the edges from the saved copies of the interaction and \
update neighborhoods
      *)
    JavaBlock[
      m@setInteractionNeighborhood[
          BuildGraph[
            Graph[{},
              InteractionNeighborhood[
                  m]\[LeftDoubleBracket]2\[RightDoubleBracket]]]
          ];
      m@setUpdateNeighborhood[
          
          BuildGraph[
            Graph[{},
              UpdateNeighborhood[
                  m]\[LeftDoubleBracket]2\[RightDoubleBracket]]]
          ];
      g=m@getDisplayGraph[];
      m@setDisplayGraph[
          BuildGraph[Graph[{},g\[LeftDoubleBracket]2\[RightDoubleBracket]]]
          ]
      ];
    m@updateDisplay[];
    ]

SetAttributes[DeleteEdges,Protected];







ReplaceEdges::nbhderr1="The specified `` neighborhood is not a graph.";

ReplaceEdges::nbhderr2="The number of vertices in the `` neighborhood does not equal the number of agents in the model.";\


ReplaceEdges::nbhderr3=
  "Too many neighborhoods were specified. You can either pass values for InteractionNeighborhood and/or UpdateNeighborhood, or a value for Neighborhood, but not both."



Options[ReplaceEdges]={
      UseInteractionNeighborhoodWeights\[Rule]False,
      UseUpdateNeighborhoodWeights\[Rule]False,
      NeighborhoodsToDraw\[Rule]{Interaction}
      };

ReplaceEdges[m_?ModelQ,opts___Rule]:=
    Module[{intG,upG,nbhdG,defaults,edgesWeighted,b1,b2,gr,g2,toDraw},
      defaults=Options[ReplaceEdges];
      intG=InteractionNeighborhood/.{opts};
      upG=UpdateNeighborhood/.{opts};
      nbhdG=Neighborhood/.{opts};
      toDraw=NeighborhoodsToDraw/.{opts}/.defaults;
      
      (*Verify both are graphs, if given*)
      
      If[intG=!=InteractionNeighborhood\[And]Head[intG]=!=Graph,
        Message[ReplaceEdges::nbhderr1,"interaction"];
        Return[];
        ];
      If[upG=!=UpdateNeighborhood\[And]Head[upG]=!=Graph,
        Message[ReplaceEdges::nbhderr1,"update"];
        Return[];
        ];
      If[nbhdG=!=Neighborhood\[And]Head[nbhdG]=!=Graph,
        Message[ReplaceEdges::nbhderr1,"interaction and update"];
        Return[];
        ];
      
      (*Verify each has right number of vertices, if given*)
      
      If[Head[intG]===Graph\[And]V[intG]\[NotEqual]NumberOfAgents[m],
        Message[ReplaceEdges::nbhderr2,"interaction"];
        Return[];
        ];
      If[Head[upG]===Graph\[And]V[upG]\[NotEqual]NumberOfAgents[m],
        Message[ReplaceEdges::nbhderr2,"update"];
        Return[];
        ];
      If[Head[nbhdG]===Graph\[And]V[nbhdG]\[NotEqual]NumberOfAgents[m],
        Message[ReplaceEdges::nbhderr2,"interaction and update"];
        Return[];
        ];
      
      (*If the Neighborhood option is specified, 
        it overrides all the others. Warn at the same time.*)
      
      If[Head[nbhdG]===
            Graph\[And](Head[intG]===Graph \[Or]Head[upG]===Graph),
        Message[ReplaceEdges::nbhderr3];
        Return[];
        ];
      
      m@deleteAllEdges[];
      
      If[Head[intG]===Graph,
        ReplaceInteractionNeighborhood[m,intG,opts],
        If[Head[nbhdG]===Graph,
          ReplaceInteractionNeighborhood[m,nbhdG,opts]
          ]
        ];
      
      If[Head[upG]===Graph,
        ReplaceUpdateNeighborhood[m,upG,opts],
        If[Head[nbhdG]===Graph,
          ReplaceUpdateNeighborhood[m,nbhdG,opts]
          ]
        ];
      
      If[Head[nbhdG]===Graph,
        gr=CreateNetworkGraph[nbhdG,nbhdG,toDraw,opts];
        ];
      
      If[intG===InteractionNeighborhood,
        intG=EmptyGraph[NumberOfAgents[m]]
        ];
      If[upG===UpdateNeighborhood,
        upG=EmptyGraph[NumberOfAgents[m]]
        ];
      If[Head[gr]=!=Graph,
        gr=CreateNetworkGraph[intG,upG,toDraw,opts]
        ];
      
      JavaBlock[
        m@setGraphAndReparse[
            BuildGraph[NormalizeGraph[gr]]
            ]
        ];
      
      m@updateDisplay[];
      ];





ReplaceInteractionNeighborhood[m_?ModelQ,g_Graph,opts___Rule]:=Module[
      {edgesWeighted,b1,b2,defaults},
      defaults=Options[ReplaceEdges];
      
      edgesWeighted=UseInteractionNeighborhoodWeights/.{opts}/.defaults;
      If[UndirectedQ[g],b1=1.0,b1=0.0];
      If[edgesWeighted,b2=1.0,b2=0.0];
      
      JavaBlock[
        m@setInteractionNeighborhood[
            BuildGraph[g]
            ]
        ];
      
      If[edgesWeighted,
        m@addEdgesToInteractionNeighborhood[
            MapThread[
              
              Function[{e,w},{e[[1]],e[[2]],w,b1,b2}],{Edges[g]-1,
                GetEdgeWeights[g]}
              ]
            ],
        m@wireInteractionNeighborhood[
            Edges[g]-1,UndirectedQ[g]
            ]
        ];
      ];





ReplaceUpdateNeighborhood[m_?ModelQ,g_Graph,opts___Rule]:=
    Module[{defaults,edgesWeighted,gr,es},
      
      defaults=Options[ReplaceEdges];
      edgesWeighted=UseUpdateNeighborhoodWeights/.{opts}/.defaults;
      
      gr=MakeDirected[g,All];
      es=Edges[gr]-1;
      
      JavaBlock[
        m@setUpdateNeighborhood[
            BuildGraph[g]
            ]
        ];
      
      If[edgesWeighted,m@wireUpdateNeighborhoodWithProbabilities[MapThread[
              Function[{e,w},{e[[1]],e[[2]],w}],
              {es,GetEdgeWeights[gr]}
              ]
            ],
        m@wireUpdateNeighborhood[es]
        ];
      ];



End[];
Protect[
    AgentQ,
    Agents,
    BestResponse,
    ButtonPanel,
    ControlPanel,
    CreateButton,
    CreateProgressBar,
    Data,
    DeleteModel,
    DisplayPause,
    EditGraph,
    Evolve,
    ExtractGraph,
    Generations,
    GetAgent,
    GraphicsEngine,
    ImitateBestNeighbor,
    IncrementProgressBar,
    InitialStrategyDistribution,
    InteractionNeighborhood,
    InteractionNeighborhoodColor,
    InteractionNeighborhoodColor,
    InteractionNeighbors,
    LearningRule,
    LocalInteractionModel,
    ModelQ,
    Neighborhoods,
    NeighborhoodsToDraw,
    NeighborhoodStyle,
    NeighborhoodStyle,
    NumberOfAgents,
    ObservedStrategies,
    PayoffMatrix,
    PrisonersDilemma,
    RandomElement,
    RandomGenerator,
    RandomSeed,
    RandomStrategy,
    RasterLatticeRepresentation,
    Score,
    SetData,
    SetLearningRule,
    SetNextStrategy,
    SetStrategies,
    SetStrategy,
    ShowOptions,
    ShowVertexNumbers,
    ShowWindow,
    Strategies,
    Strategy,
    StrategyColors,
    StrategyDistribution,
    StrategyHistogram,
    StrategyLegend,
    ToColorArray,
    Undirected,
    UpdateDisplay,
    UpdateNeighborhood,
    UpdateNeighborhoodColor,
    UpdateNeighbors,
    UseInteractionNeighborhoodWeights,
    UseUpdateNeighborhoodWeights,
    Weight,
    WindowLabel
    ];
EndPackage[];