The New Decision Process Toolkit

Gerald H. Thomas, MSOE

ABSTRACT

We have created a decision process toolkit for analyzing a variety of decision processes. It is to be published by Wolfram Media, and is based on a field theory of games for multiple players called decision process theory. For now, the toolkit is limited to two-person processes. As input, it takes the process formulated as a classic two-person game, where each player has several intrinsic strategies. With the additional input of appropriate boundary conditions, the cultural and dynamic aspects are added by the user using the toolkit. The toolkit provides an analysis of the steady-state behavior of the process, as well as how it reacts to specific time dependent disruptions. This toolkit will be used as the basis for a course to be taught next Spring at MSOE. In this talk we illustrate the toolkit with the simple but informative game of tic-tac-toe.

Decision Process Toolkit

This talk draws from a forthcoming publiction from Wolfram Media, Thomas, Introduction to Decision Processing Engineering, which we refer to as the toolkit.

It makes use of Mathematica 12 NDSolve for convection type PDEs

To illustrate the toolkit, we have adapted the treatment to apply to the specific game of tic-tac-toe. Though very simple, the game has many strategies and we believe illustrates the possibilities of the approach, as well as the virtue of going to intrinsic strategies.

It is envisioned that student would do similar adaptations for processes of their choosing.

First, we highlight the basic steps of the toolkit:

Initializations (the under-the-hood work)

18.1.1 | Useful Methods

As we are building on the previous chapters, there are methods from there that will prove useful here. We use these aspects of game theory to build the attributes and boundary conditions for decision process theory.

hedge1Fn[g_]:=Table[1,{k,Length[g]}]
hedge2Fn[g_]:=Table[1,{k,Length[Transpose[g]]}]
toPos[g_]:=g-Min[g]+1
solP2[g_]:=LinearProgramming[hedge2Fn[g],toPos[-g],hedge1Fn[g]]
solP1[g_]:=LinearProgramming[hedge1Fn[g],toPos@Transpose@g,hedge2Fn[g]]

normStrategy[s_]:=If[Tr[s]≠0,s/Tr[s],"NA"]
gameValueP1[g_]:=1/solP1[g].hedge1Fn[g]+Min[g]-1
gameValueP2[g_]:=-1/solP2[g].hedge2Fn[g]-Min[-g]+1

It is useful to replicate the game matrix and strategic equilibrium as an antisymmetric matrix in the full space.

gToSymG[x_,y_,g_]:=ArrayFlatten[{{0,-Transpose[g],List/@y},{g,0,-List/@x},{-List@y,List@x,0}}]
pValuation2[g_]:=Transpose[g].normStrategy@solP1[g]
pValuation1[g_]:=g.normStrategy@solP2[g]
dptGame[g_,eScale_]:=gToSymG[pValuation1[g]/eScale,pValuation2[g]/eScale,g]

To obtain the streamlines from the previous section, we keep track of explicit payoff matrices for the theory, and associated constants needed.

dptPayoff1:=dptGame[gameMatrix1,valueScale]
dptPayoff2:=dptGame[gameMatrix2,valueScale]
compositePayoff:=e1 dptPayoff1+e2 dptPayoff2
compositePayoffEigenvalues:=Eigenvalues[compositePayoff.Inverse[metric]]

numberColumns[g_]:=Length@First@g
numberRows[g_]:=numberColumns@Transpose@g
numActiveStrategies:=numberColumns@gameMatrix+numberRows@gameMatrix
gab[g_]:=DiagonalMatrix@Join[Table[-1,{k,numActiveStrategies}],{1}]
metric:=gab[gameMatrix]

To compute the streamlines for the flows, we use NDSolve with the following variables for the preferences and the flows, along with the initial (boundary) condition. From the preference ySolution'[s] we compute the flows.

var:=Table[Subscript[y, k][s],{k,numActiveStrategies+1}]
flow[s_]:=Table[Subscript[y, k]'[s],{k,numActiveStrategies+1}]
covariantV[s_]:=metric.flow[s]

initializedDisruptiveFlow:=disruptiveFlow/√(disruptiveFlow.metric.disruptiveFlow)
boundaryEquations:=Join[Table[flow[0][[k]]==initializedDisruptiveFlow[[k]],{k,numActiveStrategies+1}],Table[Subscript[y, k][0]==0,{k,numActiveStrategies+1}]]

flowEquations:=Table[covariantV'[s][[k]]==(compositePayoff.flow[s])[[k]],{k,numActiveStrategies+1}]

flowSolution[s_]:=ySolution'[s];
covariantFlowSolution[s_]:=metric.flowSolution[s];

strategyString1:=Table[StringJoin["P1S",ToString[k]],{k,numberRows[gameMatrix]}]
colors1:=Table[RGBColor[0,(k-1)/(numberRows[gameMatrix]-1),1-(k-1)/(numberRows[gameMatrix]-1)],{k,numberRows[gameMatrix]}]
strategyString2:=Table[StringJoin["P2S",ToString[k]],{k,numberColumns[gameMatrix]}]
colors2:=Table[RGBColor[1,(k-1)/numberColumns[gameMatrix],0],{k,numberColumns[gameMatrix]}]
strategyString:=Join[strategyString2,strategyString1]
strategyColors:=Join[colors2,colors1]
allStrategyString:=Join[strategyString,{"time"}]
allStrategyColors:=Join[strategyColors,{Purple}]

flowPlot:=Plot[Evaluate[flowSolution[s]],{s,0,sMax},AxesLabel->Automatic,PlotLegends->allStrategyString,PlotStyle->allStrategyColors,PlotLabel->"flows",ImageSize->Medium]
flowCorrelationPlots:=TableForm[Table[ParametricPlot[{flowSolution[s][[k]],flowSolution[s][[j]]},{s,0,sMax},PlotStyle->Table[allStrategyColors[[k]],{i,numActiveStrategies-k}],PlotLabel->"V^a vs V^b",AxesLabel->{strategyString[[k]],strategyString[[j]]},AspectRatio->1,ImageSize->Small]/.Line[x_]:>{Arrowheads[{0.07,0.07,0.07,0.07,0.07}],Arrow[x]},{k,numActiveStrategies-1},{j,k+1,numActiveStrategies}]]
preferencePlot:=Plot[Evaluate[ySolution[s]],{s,0,sMax},AxesLabel->Automatic,PlotLegends->allStrategyString,PlotStyle->allStrategyColors,PlotLabel->"preferences", ImageSize->Medium]
preferenceTimePlots:=ParametricPlot[Evaluate[{ySolution[s][[-1]],#}&/@ySolution[s][[;;numActiveStrategies]]],{s,0,sMax},PlotStyle->strategyColors,AspectRatio->1/4,AxesLabel->{"time","strategies"},PlotLegends->strategyString,ImageSize->Medium]

betaFlow:=Plot[Evaluate[flowSolution[s]/flowSolution[s][[-1]]],{s,0,sMax},AxesLabel->Automatic,PlotLegends->Join[strategyString2,strategyString1,{"time"}],PlotStyle->Join[colors2,colors1,{Purple}],PlotLabel->"beta"]
uChoiceFlow:=Plot[Tr[uChoice.flowSolution[s]],{s,0,sMax},AxesLabel->Automatic,PlotStyle->{Thick,Red},PlotLabel->"relative player effort flow"]
rChoiceFlow:=Plot[Tr[rChoice.flowSolution[s]],{s,0,sMax},AxesLabel->Automatic,PlotStyle->{Thick,Blue},PlotLabel->"total player effort flow"]
ruPhaseSpacePlot:=ParametricPlot[{Tr[uChoice.flowSolution[s]],Tr[rChoice.flowSolution[s]]},{s,0,sMax},PlotLabel->"relative flow vs total player flow",AxesLabel->{"du/ds","dr/ds"},PlotStyle->{Thick,Red}]/.Line[x_]:>{Arrowheads[{0.07,0.07,0.07,0.07,0.07}],Arrow[x]}

playerOne[g_]:=DiagonalMatrix@Join[Table[0,{k,numberColumns[g]}],Table[1,{k,numberRows[g]}],{0}]
playerTwo[g_]:=DiagonalMatrix@Join[Table[1,{k,numberColumns[g]}],Table[0,{k,numberRows[g]}],{0}]
one:=playerOne[gameMatrix]
two:=playerTwo[gameMatrix]
rChoice:=(one+two)/Tr[one+two]
uChoice:=one/Tr[one]-two/Tr[two]

18.1.2 | Stress Constraint Useful Methods

γjkMetric:=Table[ γjk[j,k],{j,2},{k,2}]/.Flatten@Table[γjk[k,j]-> γjk[j,k],{j,2},{k,j+1,2}]
gυυpMetric:=Table[ gυυp[j,k],{j,numActiveStrategies},{k,numActiveStrategies}]/.Flatten@Table[gυυp[k,j]-> gυυp[j,k],{j,numActiveStrategies},{k,j+1,numActiveStrategies}]
fullMetric:=Join[Table[Join[γjkMetric[[j]],{0},Table[0,{k,numActiveStrategies}]],{j,2}],
{Join[Table[0,{j,2}],{gοο},Table[0,{k,numActiveStrategies}]]},
Table[Join[Table[0,{j,3}],gυυpMetric[[k]]],{k,numActiveStrategies}]]
upperFullMetric:=fullMetric/.{γjk->γjkUpper,gυυp->gυυpUpper,gοο->gοοUpper}

ujkTransformation:=IdentityMatrix[2]vLowerο vUpperο
uυυpTransformation:=IdentityMatrix[numActiveStrategies]vLowerο vUpperο
uTransformation:=Join[Table[Join[ujkTransformation[[j]],{-vLowerο vInactiveUpper[j]},Table[0,{k,numActiveStrategies}]],{j,2}],{Join[Table[vUpperο vInactiveLower[k],{k,2}],{vLowerο vUpperο},Table[vUpperο vActiveLower[j],{j,numActiveStrategies}]]},Table[Join[Table[0,{j,2}],{-vLowerο vActiveUpper[k]},Table[uυυpTransformation[[k]][[j]],{j,numActiveStrategies}]],{k,numActiveStrategies}]]

wjkTransformation:=IdentityMatrix[2]vLowerο vUpperο
wυυpTransformation:=IdentityMatrix[numActiveStrategies]vLowerο vUpperο
wTransformation:=Join[Table[Join[wjkTransformation[[j]],{- vInactiveLower[j] vUpperο},Table[0,{k,numActiveStrategies}]],{j,2}],{Join[Table[vLowerο vInactiveUpper[k],{k,2}],{vLowerο vUpperο},Table[vLowerο vActiveUpper[j],{j,numActiveStrategies}]]},Table[Join[Table[0,{j,2}],{-vActiveLower[k] vUpperο },Table[uυυpTransformation[[k]][[j]],{j,numActiveStrategies}]],{k,numActiveStrategies}]]

inactiveFlowUpper:=Table[vInactiveUpper[j],{j,2}]
activeFlowUpper:=Table[vActiveUpper[j],{j,numActiveStrategies}]
timeFlowUpper:={vUpperο}
fullFlowUpper:=Join[inactiveFlowUpper,timeFlowUpper,activeFlowUpper]
inactiveFlowLower:=Table[vInactiveLower[j],{j,2}]
activeFlowLower:=Table[vActiveLower[j],{j,numActiveStrategies}]
timeFlowLower:={vLowerο}
fullFlowLower:=Join[inactiveFlowLower,timeFlowLower,activeFlowLower]
transformUpperToLower:=Rule@@@Transpose@{fullFlowUpper,Inverse[fullMetric].fullFlowLower}
transformLowerToUpper:=Rule@@@Transpose@{fullFlowLower,fullMetric.fullFlowUpper}

flowNormalization:=vLowerο ->( 1-Sum[vInactiveLower[j] vInactiveUpper[j],{j,2}]-Sum[vActiveLower[k] vActiveUpper[k],{k,numActiveStrategies}])/vUpperο 
alternateFlowNormalization:=gοο->(( 1-fullFlowUpper.fullMetric.fullFlowUpper)/(vUpperο^2))+gοο 
alternateUpperFlowNormalization:=gοοUpper->(( 1-fullFlowUpper.fullMetric.fullFlowUpper)/(vLower^2))+gοοUpper 
spaceAlternateFlowNormalization:=vActiveUpper[1]->(( 1-fullFlowLower.fullFlowUpper)/(vActiveLower[1]))+vActiveUpper[1] 
spaceSpaceFlowNormalization:={vActiveLower[1] vActiveUpper[1]-> -fullFlowLower.fullFlowUpper+1+vActiveLower[1] vActiveUpper[1]}

inactiveTimeProjectionRestFrame:=DiagonalMatrix[Join[{0,0},{1},Table[0,{j,numberColumns[gameMatrix]}],Table[0,{k,numberRows[gameMatrix]}]]]
inactivePlayerOneProjectionRestFrame:=DiagonalMatrix[Join[{1,0},{0},Table[0,{j,numberColumns[gameMatrix]}],Table[0,{k,numberRows[gameMatrix]}]]]
inactivePlayerTwoProjectionRestFrame:=DiagonalMatrix[Join[{0,1},{0},Table[0,{j,numberColumns[gameMatrix]}],Table[0,{k,numberRows[gameMatrix]}]]]

activeTimeProjectionRestFrame:=DiagonalMatrix[Join[{0,0},{1},Table[0,{j,numberColumns[gameMatrix]}],Table[0,{k,numberRows[gameMatrix]}]]]
activePlayerOneProjectionRestFrame:=DiagonalMatrix[Join[{0,0},{0},Table[0,{j,numberColumns[gameMatrix]}],Table[1,{k,numberRows[gameMatrix]}]]]
activePlayerTwoProjectionRestFrame:=DiagonalMatrix[Join[{0,0},{0},Table[1,{j,numberColumns[gameMatrix]}],Table[0,{k,numberRows[gameMatrix]}]]]

inactiveTimeProjection:=Simplify[Simplify[Inverse[uTransformation].inactiveTimeProjectionRestFrame.uTransformation]/.flowNormalization]
inactivePlayerOneProjection:=Simplify[Simplify[Inverse[uTransformation].inactivePlayerOneProjectionRestFrame.uTransformation]/.flowNormalization]
inactivePlayerTwoProjection:=Simplify[Simplify[Inverse[uTransformation].inactivePlayerTwoProjectionRestFrame.uTransformation]/.flowNormalization]

activeTimeProjection:=Simplify[Simplify[Inverse[wTransformation].activeTimeProjectionRestFrame.wTransformation]/.flowNormalization]
activePlayerOneProjection:=Simplify[Simplify[Simplify[Inverse[wTransformation].activePlayerOneProjectionRestFrame.wTransformation]/.flowNormalization]/.spaceSpaceFlowNormalizationTwo]
activePlayerTwoProjection:=Simplify[Simplify[Simplify[Inverse[wTransformation].activePlayerTwoProjectionRestFrame.wTransformation]/.flowNormalization]/.spaceSpaceFlowNormalizationOne]

inactiveTimeOwnershipTensor:=Simplify[Simplify[Transpose[inactiveTimeProjection].fullMetric.inactiveTimeProjection]/.alternateFlowNormalization]
inactivePlayerOneOwnershipTensor:=Simplify[Simplify[Transpose[inactivePlayerOneProjection].fullMetric.inactivePlayerOneProjection]/.alternateFlowNormalization]
inactivePlayerTwoOwnershipTensor:=Simplify[Simplify[Transpose[inactivePlayerTwoProjection].fullMetric.inactivePlayerTwoProjection]/.alternateFlowNormalization]
CovariantTimeOwnershipTensor:=inactiveTimeOwnershipTensor

activeTimeOwnershipTensor:=Simplify[Simplify[Transpose[activeTimeProjection].fullUpperMetric.activeTimeProjection]/.spaceSpaceFlowNormalizationTwo]/.metricFlowNormalization
activePlayerOneOwnershipTensor:=Simplify[Simplify[Transpose[activePlayerOneProjection].fullUpperMetric.activePlayerOneProjection]/.metricFlowNormalization]
activePlayerTwoOwnershipTensor:=Simplify[Simplify[Transpose[activePlayerTwoProjection].fullUpperMetric.activePlayerTwoProjection]/.metricFlowNormalization]
covariantTimeOwnershipTensor:=fullMetric.activeTimeOwnershipTensor.fullMetric
covariantActivePlayerOneOwnershipTensor:=fullMetric.activePlayerOneOwnershipTensor.fullMetric
covariantActivePlayerTwoOwnershipTensor:=fullMetric.activePlayerTwoOwnershipTensor.fullMetric

activeInactivePlayerOneOwnershipTensor:=Simplify[Transpose[activePlayerOneProjection].inactivePlayerOneProjection]/.spaceSpaceFlowNormalizationTwo
activeInactivePlayerTwoOwnershipTensor:=Simplify[Transpose[activePlayerTwoProjection].inactivePlayerTwoProjection]/.spaceSpaceFlowNormalizationOne
covariantActiveInactivePlayerOneOwnershipTensor:=fullMetric.activeInactivePlayerOneOwnershipTensor
covariantActiveInactivePlayerTwoOwnershipTensor:=fullMetric.activeInactivePlayerTwoOwnershipTensor

inactiveActivePlayerOneOwnershipTensor:=Simplify[Transpose[inactivePlayerOneProjection].activePlayerOneProjection]/.spaceSpaceFlowNormalizationTwo
inactiveActivePlayerTwoOwnershipTensor:=Simplify[Transpose[inactivePlayerTwoProjection].activePlayerTwoProjection]/.spaceSpaceFlowNormalizationOne
covariantInactiveActivePlayerOneOwnershipTensor:=inactiveActivePlayerOneOwnershipTensor.fullMetric
covariantInactiveActivePlayerTwoOwnershipTensor:=inactiveActivePlayerTwoOwnershipTensor.fullMetric

covariantPlayerOneOwnershipTensor:=inactivePlayerOneOwnershipTensor+covariantActivePlayerOneOwnershipTensor+ covariantActiveInactivePlayerOneOwnershipTensor+covariantInactiveActivePlayerOneOwnershipTensor
covariantPlayerTwoOwnershipTensor:=inactivePlayerTwoOwnershipTensor+covariantActivePlayerTwoOwnershipTensor+ covariantActiveInactivePlayerTwoOwnershipTensor+covariantInactiveActivePlayerTwoOwnershipTensor

flatInactiveMetric:=-IdentityMatrix[2]
flatActiveMetric:=-IdentityMatrix[numActiveStrategies]
flatTimeMetric:=1
setInactiveFlatMetric:=Rule@@@Transpose@{Flatten@Table[γjk[j,k],{j,2},{k,2}],Flatten@flatInactiveMetric}
setActiveFlatMetric:=Rule@@@Transpose@{Flatten@Table[gυυp[j,k],{j,numActiveStrategies},{k,numActiveStrategies}],Flatten@flatActiveMetric}
setTimeFlatMetric:={gοο-> flatTimeMetric}
setFullFlatMetric:=Join[setInactiveFlatMetric,setActiveFlatMetric,setTimeFlatMetric]
flatMetric:=fullMetric/.setFullFlatMetric
restFrameFlatMetric:=Transpose[Inverse[uTransformation]].flatMetric.Inverse[uTransformation]

upperFlatInactiveMetric:=Inverse@flatInactiveMetric
upperFlatActiveMetric:=Inverse@flatActiveMetric
upperFlatTimeMetric:=1/flatTimeMetric
setUpperInactiveFlatMetric:=Rule@@@Transpose@{Flatten@Table[γjkUpper[j,k],{j,2},{k,2}],Flatten@upperFlatInactiveMetric}
setUpperActiveFlatMetric:=Rule@@@Transpose@{Flatten@Table[gυυpUpper[j,k],{j,numActiveStrategies},{k,numActiveStrategies}],Flatten@upperFlatActiveMetric}
setUpperTimeFlatMetric:={gοοUpper-> upperFlatTimeMetric}
setFullUpperFlatMetric:=Join[setUpperInactiveFlatMetric,setUpperActiveFlatMetric,setUpperTimeFlatMetric]
upperFlatMetric:=upperFullMetric/.setFullUpperFlatMetric

restFrameFlatMetricValue:=(restFrameFlatMetric/.setFullFlatMetric)/.setAllFlow

setInactiveUpperFlow:=Rule@@@Transpose@{inactiveFlowUpper,{-1/2,-1/2}}
setInactiveLowerFlow:=Rule@@@Transpose@{inactiveFlowLower,((inactiveFlowLower/.transformLowerToUpper)/.setInactiveFlatMetric)/.setInactiveUpperFlow}
setActiveUpperFlow:=Rule@@@Transpose@{activeFlowUpper,Table[1/10,{k,numActiveStrategies}]}
setActiveLowerFlow:=Rule@@@Transpose@{activeFlowLower,((activeFlowLower/.transformLowerToUpper)/.setActiveFlatMetric)/.setActiveUpperFlow}

setActiveFlow:=Join[setActiveUpperFlow,setActiveLowerFlow]
setInactiveFlow:=Join[setInactiveUpperFlow,setInactiveLowerFlow]
setFlow:=Join[setActiveFlow,setInactiveFlow]
setTimeUpperFlow:={vUpperο-> Sqrt[((1-inactiveFlowLower.inactiveFlowUpper-activeFlowLower.activeFlowUpper)/.flowNormalization)/.setFlow]}
setTimeLowerFlow:={vLowerο-> vUpperο}/.setTimeUpperFlow
setTimeFlow:=Join[setTimeUpperFlow,setTimeLowerFlow]
setAllFlow:=Join[setFlow,setTimeFlow]

fullUpperMetric:=upperFullMetric
flatUpperMetric:=upperFlatMetric
setFullFlatUpperMetric:=setFullUpperFlatMetric
setFlatFrameUpperFlow := Rule @@@ Transpose@{fullFlowUpper, (fullFlowUpper /. transformUpperToLower) /. setFullFlatUpperMetric}
uRestFrameFlatMetric := Transpose[Inverse[uTransformation]].flatMetric.Inverse[uTransformation]
uRestFrameFlatMetricValue:=(uRestFrameFlatMetric/.setFullFlatMetric)/.setAllFlow
wRestFrameFlatUpperMetric := Transpose[Inverse[wTransformation]].flatUpperMetric.Inverse[wTransformation]
wRestFrameFlatUpperMetricValue:=(wRestFrameFlatUpperMetric/.setFullFlatMetric)/.setAllFlow

inactivePlayerOneOwnershipFlowRestFrame:=fullFlowLower.inactivePlayerOneProjectionRestFrame/( vUpperο vLowerο)
activePlayerOneOwnershipFlowRestFrame:=fullFlowUpper.activePlayerOneProjectionRestFrame/(vUpperο vLowerο)
inactivePlayerTwoOwnershipFlowRestFrame:=fullFlowLower.inactivePlayerTwoProjectionRestFrame/( vUpperο vLowerο)
activePlayerTwoOwnershipFlowRestFrame:=fullFlowUpper.activePlayerTwoProjectionRestFrame/(vUpperο vLowerο)
inactiveTimeOwnershipFlowRestFrame:=fullFlowLower.inactiveTimeProjectionRestFrame/( vUpperο vLowerο)
activeTimeOwnershipFlowRestFrame:=fullFlowUpper.activeTimeProjectionRestFrame/( vUpperο vLowerο)

inactivePlayerOneOwnershipFlow:=Simplify[inactivePlayerOneOwnershipFlowRestFrame.uTransformation]
inactivePlayerTwoOwnershipFlow:=Simplify[inactivePlayerTwoOwnershipFlowRestFrame.uTransformation]
inactiveTimeOwnershipFlow:=Simplify[inactiveTimeOwnershipFlowRestFrame.uTransformation]
activePlayerOneOwnershipFlow:=Simplify[activePlayerOneOwnershipFlowRestFrame.wTransformation]
activePlayerTwoOwnershipFlow:=Simplify[activePlayerTwoOwnershipFlowRestFrame.wTransformation]
activeTimeOwnershipFlow:=Simplify[activeTimeOwnershipFlowRestFrame.wTransformation]

spaceSpaceFlowNormalizationOne:={vActiveLower[numberColumns[gameMatrix]+1] vActiveUpper[numberColumns[gameMatrix]+1]->-fullFlowLower.fullFlowUpper+1+vActiveLower[numberColumns[gameMatrix]+1] vActiveUpper[numberColumns[gameMatrix]+1]}
spaceSpaceFlowNormalizationTwo:={vActiveLower[1] vActiveUpper[1]-> -fullFlowLower.fullFlowUpper+1+vActiveLower[1] vActiveUpper[1]}
spaceSpaceUpperFlowNormalization:={vActiveLower[2] vActiveUpper[2]-> -fullFlowLower.fullFlowUpper+1+vActiveLower[2] vActiveUpper[2]}
metricFlowNormalization:=gοοUpper vLowerο^2->1- Simplify[fullFlowLower.fullUpperMetric.fullFlowLower ]+gοοUpper vLowerο^2
spaceSpaceFlowNormalizationFour:={vActiveLower[4] vActiveUpper[4]-> -fullFlowLower.fullFlowUpper+1+vActiveLower[4] vActiveUpper[4]}

transformLowerToUpper2:=Rule@@@Transpose@{fullFlowLower,Inverse[fullUpperMetric].fullFlowUpper}
transformUpperToLower2:=Rule@@@Transpose@{fullFlowUpper,fullUpperMetric.fullFlowLower}

gυυpUpperMetric:=gυυpMetric/.{gυυp->gυυpUpper}

stressOne:=flatUpperMetric.(covariantPlayerOneOwnershipTensor/.setAllFlow/.setFullFlatMetric/.setFullFlatUpperMetric).flatUpperMetric
stressTwo:=flatUpperMetric.(covariantPlayerTwoOwnershipTensor/.setAllFlow/.setFullFlatMetric/.setFullFlatUpperMetric).flatUpperMetric

flowMixingFactor:=Simplify[activePlayerOneOwnershipFlow.flatMetric.activePlayerTwoOwnershipFlow]

stressOneSubspace[f_]:=Join[{Join[{f[[1]][[1]]},Table[f[[1]][[k]],{k,2+1+numberColumns[gameMatrix]+1,2+1+numberColumns[gameMatrix]+numberRows[gameMatrix]}]]},Table[Join[{f[[j]][[1]]},Table[f[[j]][[k]],{k,2+1+numberColumns[gameMatrix]+1,2+1+numberColumns[gameMatrix]+numberRows[gameMatrix]}]],{j,2+1+Tr[two]+1,2+1+numberColumns[gameMatrix]+numberRows[gameMatrix]}]]
stressTwoSubspace[f_]:=Join[{Join[{f[[2]][[2]]},Table[f[[2]][[k]],{k,2+1+1,2+1+Tr[two]}]]},Table[Join[{f[[j]][[2]]},Table[f[[j]][[k]],{k,2+1+1,2+1+numberColumns[gameMatrix]}]],{j,2+1+1,2+1+numberColumns[gameMatrix]}]]

ellipsoidOne[ev_,f_]:=-Expand[ev.stressOneSubspace[f].ev]
ellipsoidTwo[ev_,f_]:=-Expand[ev.stressTwoSubspace[f].ev]

playerEllipses:=Row@{Plot3D[Evaluate[z/.playerOneEllipse[x,y]],{x,-2,2},{y,-2,2},PlotStyle->{Blue,Opacity[.2]},PlotLabel->"Player One Ellipse",AxesLabel->strategyString1,BoxRatios->{1,1,1},ImageSize->Medium]," \t ",
Plot3D[z/.playerTwoEllipse[x,y],{x,-2,2},{y,-2,2},PlotStyle->{Red,Opacity[.2]},PlotLabel->"Player Two Ellipse",AxesLabel->strategyString2,BoxRatios->{1,1,1},ImageSize->Medium ]}

oneActiveSpace:=Transpose[one[[1;;-2]]][[1;;-2]]
twoActiveSpace:=Transpose[two[[1;;-2]]][[1;;-2]]
activeFlowProduct:=Table[vActiveUpper[j]vActiveUpper[k],{j,numActiveStrategies},{k,numActiveStrategies}]
perfectFluidForm:=gυυpUpperMetric-activeFlowProduct

tInactiveStress:={{γjkMetric[[1]][[1]]-vInactiveLower[1]^2,0},{0,γjkMetric[[2]][[2]]-vInactiveLower[2]^2}}
tInactiveStressOne:=γjkMetric[[1]][[1]]-vInactiveLower[1]^2
tInactiveStressTwo:=γjkMetric[[2]][[2]]-vInactiveLower[2]^2
tActiveStressOne:=oneActiveSpace.perfectFluidForm.oneActiveSpace
tActiveStressTwo:=twoActiveSpace.perfectFluidForm.twoActiveSpace
tInactiveActiveStressOne:=-vInactiveLower[1]Table[vActiveUpper[k],{k,numActiveStrategies}].oneActiveSpace
tInactiveActiveStressTwo:=-vInactiveLower[2]Table[vActiveUpper[k],{k,numActiveStrategies}].twoActiveSpace

directEllipsoidOneGeneralFrame[z_,vector_]:=Expand[-vector.(tActiveStressOne/.setAllFlow/.setFullFlatUpperMetric).vector-2z (tInactiveActiveStressOne/.setAllFlow).vector-z^2 tInactiveStressOne/.setAllFlow/.setFullFlatMetric]
directEllipsoidTwoGeneralFrame[z_,vector_]:=Expand[-vector.(tActiveStressTwo/.setAllFlow/.setFullFlatUpperMetric).vector-2z (tInactiveActiveStressTwo/.setAllFlow).vector-z^2 tInactiveStressTwo/.setAllFlow/.setFullFlatMetric]

directPlayerEllipses:=Row@{Plot3D[Evaluate[z/.directPlayerOneEllipse[x,y]],{x,-2,2},{y,-2,2},PlotStyle->{Blue,Opacity[.2]},PlotLabel->"Player One Ellipse",AxesLabel->strategyString1,BoxRatios->{1,1,1},ImageSize->Medium]," \t ",
Plot3D[z/.directPlayerTwoEllipse[x,y],{x,-2,2},{y,-2,2},PlotStyle->{Red,Opacity[.2]},PlotLabel->"Player Two Ellipse",AxesLabel->strategyString2,BoxRatios->{1,1,1},ImageSize->Medium ]}

ψJOneInactive :=Simplify[vInactiveLower[1]vInactiveFlowUpper[1]]
ψJTwoInactive :=Simplify[vInactiveLower[2]vInactiveFlowUpper[2]]
ψJOneActive :=activeFlowUpper.oneActiveSpace.activeFlowLower
ψJTwoActive :=activeFlowUpper.twoActiveSpace.activeFlowLower
ψJOne:=ψJOneInactive+ψJOneActive
ψJTwo:=ψJTwoInactive+ψJTwoActive

tInactiveOneTimeStress:=(vInactiveLower[1] (ψJOne-1)+γjkMetric[[1]][[2]]vInactiveFlowUpper[2])/vUpperο
tInactiveTwoTimeStress:=(vInactiveLower[2] (ψJTwo-1)+γjkMetric[[2]][[1]]vInactiveFlowUpper[1])/vUpperο

tActiveOneTimeStress:=(activeFlowUpper.oneActiveSpace (ψJOne-1)+oneActiveSpace.gυυpUpperMetric.twoActiveSpace.activeFlowLower)/vUpperο
tActiveTwoTimeStress:=(activeFlowUpper.twoActiveSpace (ψJTwo-1)+twoActiveSpace.gυυpUpperMetric.oneActiveSpace.activeFlowLower)/vUpperο

tActiveTimeTimeStressOne:=(activeFlowLower.oneActiveSpace.gυυpUpperMetric.oneActiveSpace.activeFlowLower+vInactiveFlowUpper[1]γjkMetric[[1]][[1]]vInactiveFlowUpper[1]-ψJOne ^2)/vUpperο^2
tActiveTimeTimeStressTwo:=(activeFlowLower.twoActiveSpace.gυυpUpperMetric.twoActiveSpace.activeFlowLower+vInactiveFlowUpper[2]γjkMetric[[2]][[2]]vInactiveFlowUpper[2]-ψJTwo ^2)/vUpperο^2

18.1.3 | Owner Stream Useful Methods

Here we capture the methods that we needed in Chap. 6, starting with the variables for the PDE.

Needs["NDSolve`FEM`"]

activeOwnerFlows[s1_,s2_]:=Table[Symbol["uUpper"<>ToString[k]][s1,s2],{k,numActiveStrategies+1}]
inactiveOwnerFlows[s1_,s2_]:=Table[Symbol["uILower"<>ToString[k]][s1,s2],{k,2}]

activeOwnerPreferences[s1_,s2_]:=Table[Symbol["y"<>ToString[k]][s1,s2],{k,numActiveStrategies+1}]
ds1ActiveOwnerPreferences[s1_,s2_]:=D[activeOwnerPreferences[s1,s2],s1]
ds2ActiveOwnerPreferences[s1_,s2_]:=D[activeOwnerPreferences[s1,s2],s2]

variableList[s1_,s2_]:=Join[activeOwnerPreferences[s1,s2],activeOwnerFlows[s1,s2],inactiveOwnerFlows[s1,s2],ds1ActiveOwnerPreferences[s1,s2],ds2ActiveOwnerPreferences[s1,s2]]

The flow and preference equations are given next, assuming a flat metric. These equations will be updated in later chapters to include the frame and stress dependent effects. The introduction of the Laplacian is done to generate well behaved solutions. The two parameters, ϵV and ϵY, should not significantly impact the accuracy of the solution.

ϵV:=10^-10
ϵY:=10^-10
activeOwnerPreferencesToFlow[s1_,s2_]:=Table[D[activeOwnerPreferences[s1,s2][[k]],s1]+D[activeOwnerPreferences[s1,s2][[k]],s2]+Inactive[Div][ϵY Inactive[Grad][activeOwnerPreferences[s1,s2][[k]],{s1,s2}],{s1,s2}],{k,numActiveStrategies+1}]
activeStreamlineAcceleration[s1_,s2_]:=Table[D[activeOwnerFlows[s1,s2][[k]],s1]+D[activeOwnerFlows[s1,s2][[k]],s2]+Inactive[Div][ϵV Inactive[Grad][activeOwnerFlows[s1,s2][[k]],{s1,s2}],{s1,s2}],{k,numActiveStrategies+1}]
inactiveStreamlineAccelerations[s1_,s2_]:=Table[D[inactiveOwnerFlows[s1,s2][[k]],s1]+D[inactiveOwnerFlows[s1,s2][[k]],s2]+Inactive[Div][ϵV Inactive[Grad][inactiveOwnerFlows[s1,s2][[k]],{s1,s2}],{s1,s2}],{k,2}]
activeOwnershipOneAcceleration[s1_,s2_]:=D[activeOwnerFlows[s1,s2],s1].one
activeOwnershipTwoAcceleration[s1_,s2_]:=D[activeOwnerFlows[s1,s2],s2].two
inactiveOwnershipOneAcceleration[s1_,s2_]:={D[inactiveOwnerFlows[s1,s2],s1][[1]],0}
inactiveOwnershipTwoAcceleration[s1_,s2_]:={0,D[inactiveOwnerFlows[s1,s2],s2][[2]]}

(*pathLengthSquaredDeviation[s1_,s2_]:=numActiveUpperFlows[s1,s2].metric.numActiveUpperFlows[s1,s2]+numInactiveLowerFlows[s1,s2].Inverse[γjkMetric/.setFullFlatMetric].numInactiveLowerFlows[s1,s2]-1.*)
pathLengthDeviationPlot:=Plot3D[Evaluate@pathLengthSquaredDeviation[s1,s2],{s1,s2}∈Ω,AxesLabel->{Subscript[s,1],Subscript[s,2]},PlotRange->Full,ImageSize->Large,PlotLabel->StringJoin["pathLengthSquared ","(s1,s2)"]]

ownershipCompositePayoff[s1_,s2_]:=inactiveOwnerFlows[s1,s2][[1]] dptPayoff1+inactiveOwnerFlows[s1,s2][[2]] dptPayoff2
ownershipPayoffForce[s1_,s2_]:=ownershipCompositePayoff[s1,s2].activeOwnerFlows[s1,s2]
totalOwnershipActiveForces[s1_,s2_]:=ownershipPayoffForce[s1,s2].Inverse[metric]
totalOwnershipInactiveForces[s1_,s2_]:={0,0}

preferenceToFlowEquations:=Equal@@@Transpose@{activeOwnerPreferencesToFlow[s1,s2],activeOwnerFlows[s1,s2]}
activeFlowToAccelerationEquations:=(Equal@@@Transpose@{activeStreamlineAcceleration[s1,s2],totalOwnershipActiveForces[s1,s2]})
inactiveFlowToAccelerationEquations:=Equal@@@Transpose@{inactiveStreamlineAccelerations[s1,s2],totalOwnershipInactiveForces[s1,s2]}
pdeEquations[s1_,s2_]:=Join[preferenceToFlowEquations,activeFlowToAccelerationEquations,inactiveFlowToAccelerationEquations]

We next set the boundary conditions for active and inactive flows. At this stage, we are not solving for the market bias μ.

initialTimeEntitlementFlow[s1_,s2_]:=Sqrt[1.0-entitlementFlow1.metric.one.entitlementFlow1-entitlementFlow2.metric.two.entitlementFlow2-boundaryInactiveOwnerFlows[s1,s2].flatInactiveMetric.boundaryInactiveOwnerFlows[s1,s2]]
time:=one+two+metric
entitlementFlow[s1_,s2_]:=entitlementFlow1 Diagonal[one] + entitlementFlow2 Diagonal[two]+initialTimeEntitlementFlow[s1,s2] Diagonal[time]

rVariable[sJ_]:=Table[rJ[k][sJ],{k,numActiveStrategies+1}]
boundaryS1[s1_]:=NDSolveValue[Join[Equal@@@Transpose@{D[rVariable[sJ],sJ],entitlementFlow[sJ,0]},Table[rVariable[0][[k]]==0,{k,numActiveStrategies+1}]],rVariable[sJ],{sJ,0,size}]/.{sJ->s1}
boundaryS2[s2_]:=NDSolveValue[Join[Equal@@@Transpose@{D[rVariable[sJ],sJ],entitlementFlow[0,sJ]},Table[rVariable[0][[k]]==0,{k,numActiveStrategies+1}]],rVariable[sJ],{sJ,0,size}]/.{sJ->s2}
initEntitlementPreference[s1_,s2_]:=boundaryS1[s1].(one+time)+boundaryS2[s2].(two+time)-Diagonal[time](s1+s2)initialTimeEntitlementFlow[0,0]/2

boundaryActiveOwnerFlows[s1_,s2_]:=entitlementFlow[s1,s2] 
boundaryActiveOwnerPreferences[s1_,s2_]:=initEntitlementPreference[s1,s2]

activeOwnershipFlowBoundaryEquations:=(Equal@@@Transpose@{activeOwnerFlows[s1,s2], boundaryActiveOwnerFlows[s1,s2]})
inactiveOwnershipFlowBoundaryEquations:=Equal@@@Transpose@{inactiveOwnerFlows[s1,s2], boundaryInactiveOwnerFlows[s1,s2]}
activeOwnershipPreferenceBoundaryEquations:=Equal@@@Transpose@{activeOwnerPreferences[s1,s2], boundaryActiveOwnerPreferences[s1,s2]}
totalOwnershipBoundaryEquations:=Join[activeOwnershipFlowBoundaryEquations,inactiveOwnershipFlowBoundaryEquations,activeOwnershipPreferenceBoundaryEquations]

For visualizations based on solutions to the PDE, we introduce the numerical values of the various functions.

yNumPreferences[s1_,s2_]:=Table[ownershipStreamlines[s1,s2][[k]],{k,numActiveStrategies+1}]
numActiveUpperFlows[s1_,s2_]:=Table[ownershipStreamlines[s1,s2][[k]],{k,numActiveStrategies+2,2numActiveStrategies+2}]
numInactiveLowerFlows[s1_,s2_]:=Table[ownershipStreamlines[s1,s2][[k]],{k,2numActiveStrategies+3,2numActiveStrategies+4}]
ds1yNumPreferences[s1_,s2_]:=Table[ownershipStreamlines[s1,s2][[k]],{k,2numActiveStrategies+5,3numActiveStrategies+5}]
ds2yNumPreferences[s1_,s2_]:=Table[ownershipStreamlines[s1,s2][[k]],{k,3numActiveStrategies+6,4numActiveStrategies+6}]

We provide visualization plots that illustrate the results of the model calculations.

ownershipPreferencePlots:=Row@Table[Plot3D[Evaluate@yNumPreferences[s1,s2][[k]],{s1,s2}∈Ω,AxesLabel->{Subscript[s, 1],Subscript[s, 2]},PlotRange->Full,Mesh->15,MeshStyle->{Blue,Red},PlotLabel->StringJoin["Preferences: ",allStrategyString[[k]],"(s1,s2)"]],{k,numActiveStrategies+1}]

ownershipDs1PreferencePlots:=Table[Plot3D[Evaluate@ds1yNumPreferences[s1,s2][[k]],{s1,s2}∈Ω,AxesLabel->{Subscript[s, 1],Subscript[s, 2]},PlotRange->Full,Mesh->15,MeshStyle->{Blue,Red},PlotLabel->StringJoin["Ds1Preferences: ",allStrategyString[[k]],"(s1,s2)"]],{k,numActiveStrategies+1}]

ownershipDs2PreferencePlots:=Table[Plot3D[Evaluate@ds2yNumPreferences[s1,s2][[k]],{s1,s2}∈Ω,AxesLabel->{Subscript[s, 1],Subscript[s, 2]},PlotRange->Full,Mesh->15,MeshStyle->{Blue,Red},PlotLabel->StringJoin["Ds2Preferences: ",allStrategyString[[k]],"(s1,s2)"]],{k,numActiveStrategies+1}]

ds1OffEffortTwoGradientPlot:=Plot3D[Tr[two.ds1yNumPreferences[s1,s2]],{s1,s2}∈Ω,AxesLabel->{Subscript[s, 1],Subscript[s, 2]},PlotRange->Full,Mesh->15,MeshStyle->{Blue,Red},PlotLabel->"Dr2/Ds1",PlotLegends->LineLegend[{Blue,Red},{s1,s2}]]
ds2OffEffortOneGradientPlot:=Plot3D[Tr[one.ds2yNumPreferences[s1,s2]],{s2,s1}∈Ω,AxesLabel->{Subscript[s, 2],Subscript[s, 1]},PlotRange->Full,Mesh->15,MeshStyle->{Red,Blue},PlotLabel->"Dr1/Ds2"]
dsJOffEffortGradientPlot:=Row@{ds2OffEffortOneGradientPlot,ds1OffEffortTwoGradientPlot}

ds1OnEffortOneGradientPlot:=Plot3D[Tr[one.ds1yNumPreferences[s1,s2]],{s2,s1}∈Ω,AxesLabel->{Subscript[s, 2],Subscript[s, 1]},PlotRange->Full,Mesh->15,MeshStyle->{Red,Blue},PlotLabel->"Dr1/Ds1"]
ds2OnEffortTwoGradientPlot:=Plot3D[Tr[two.ds2yNumPreferences[s1,s2]],{s1,s2}∈Ω,AxesLabel->{Subscript[s, 1],Subscript[s, 2]},PlotRange->Full,Mesh->15,MeshStyle->{Blue,Red},PlotLabel->"Dr2/Ds2",PlotLegends->LineLegend[{Blue,Red},{s1,s2}]]
dsJOnEffortGradientPlot:=Row@{ds1OnEffortOneGradientPlot,ds2OnEffortTwoGradientPlot}

contravariantActiveFlowPlots:=Row@Table[Plot3D[Evaluate@numActiveUpperFlows[s1,s2][[k]],{s1,s2}∈Ω,AxesLabel->{Subscript[s, 1],Subscript[s, 2]},PlotRange->Full,Mesh->15,MeshStyle->{Blue,Red},PlotLabel->StringJoin["Upper Flows: ",allStrategyString[[k]],"(s1,s2)"]],{k,numActiveStrategies+1}]

covariantInactiveFlowPlots:=Row@Table[Plot3D[Evaluate@numInactiveLowerFlows[s1,s2][[k]],{s1,s2}∈Ω,AxesLabel->{Subscript[s, 1],Subscript[s, 2]},PlotRange->Full,Mesh->15,MeshStyle->{Blue,Red},PlotLabel->StringJoin["Covariant Flow V: ",{"Blue","Red"}[[k]],"(s1,s2)"]],{k,2}]

ownerStreamPlot:=StreamPlot[Evaluate@{Tr[numActiveUpperFlows[s1,s2].one],Tr[numActiveUpperFlows[s1,s2].two]},{s1,s2}∈Ω,Mesh->50,MeshStyle->Orange,FrameLabel->{"s1","s2"},PlotLabel->"{Vr1,Vr2} Contravariant Stream  Vectors",ImageSize->Large,BaseStyle->{FontWeight->"Bold"},StreamScale->.1,StreamStyle->Black]

activeStrategyPlot:=Manipulate[Plot[Evaluate[numActiveUpperFlows[s+u,s-u][[1;;-2]]],{s,0,sMax},PlotStyle->allStrategyColors,PlotLegends->allStrategyString,PlotLabel->"Contravariant Active Flows",AxesLabel->{"s",Automatic}],{{u,0},-size,size}]

activePreferencePlot:=Manipulate[Plot[Evaluate[yNumPreferences[s+u,s-u]],{s,0,sMax},PlotStyle->allStrategyColors,PlotLegends->allStrategyString,PlotLabel->"Contravariant Active Preferences",AxesLabel->{"s",Automatic}],{{u,0},-size,size}]

neutralBehaviorPlot:=Plot[Evaluate[numActiveUpperFlows[s,s][[1;;-2]]],{s,0,sMax},PlotStyle->allStrategyColors,PlotLegends->allStrategyString,PlotRange->Full,PlotLabel->"Contravariant Active Flows",AxesLabel->{"s",Automatic}]

inactiveFlowPlot:=Manipulate[Plot[Evaluate[numInactiveLowerFlows[s+u,s-u]],{s,0,sMax},PlotStyle->{Blue,Red},PlotLegends->{"Blue","Red"},PlotLabel->"Covariant Inactive Flows",AxesLabel->{"s",Automatic}],{{u,0},-size,size}]

bcDensityPlots:=Row@{DensityPlot[boundaryInactiveOwnerFlows[s1,s2][[1]],{s1,0,size},{s2,0,size},PlotLabel-> "Blue",FrameLabel->Automatic,PlotLegends->Automatic,ImageSize->Small],DensityPlot[boundaryInactiveOwnerFlows[s1,s2][[2]],{s1,0,size},{s2,0,size},PlotLabel->"Red",FrameLabel->Automatic,PlotLegends->Automatic,ImageSize->Small]}

Here we consider visualizations of the variables as functions of the player and total efforts.

effortOne[s1_,s2_]:=Tr[one.yNumPreferences[s1,s2]]
effortTwo[s1_,s2_]:=Tr[two.yNumPreferences[s1,s2]]
effortTotal[s1_,s2_]:=effortOne[s1,s2]+effortTwo[s1,s2]

effortStreamPlot:=ParametricPlot[Evaluate@{effortOne[s1,s2],effortTwo[s1,s2]},{s1,s2}∈Ω,Mesh->10,MeshStyle->{{Blue,Thick},{Red,Thick}},FrameLabel->{"r1","r2"},PlotLabel->"Effort Stream Contours",ImageSize->Large,BaseStyle->{FontWeight->"Bold"},PlotStyle->Yellow,PlotLegends->LineLegend[{Blue,Red},{s1,s2}]]

streamOne[s1_,s2_]:=Tr[one.numActiveUpperFlows[s1,s2]]
streamTwo[s1_,s2_]:=Tr[two.numActiveUpperFlows[s1,s2]]
streamTotalPlayer[s1_,s2_]:=streamOne[s1,s2]+streamTwo[s1,s2]

playerStreamPlot:=Row@{Plot3D[streamOne[s1,s2],{s2,s1}∈Ω,PlotRange->Full,AxesLabel->{"s2","s1"},PlotLabel->"Vr1(s1,s2 )",BoxRatios->{1,1,1},Mesh->15,MeshStyle->{Red,Blue}],Plot3D[streamTwo[s1,s2],{s1,s2}∈Ω,PlotRange->Full,AxesLabel->{"s1","s2"},PlotLabel->"Vr2(s1,s2 )",BoxRatios->{1,1,1},Mesh->15,MeshStyle->{Blue,Red},PlotLegends->LineLegend[{Blue,Red},{s1,s2}]]}
playerTotalStreamPlot:=Plot3D[streamTotalPlayer[s1,s2],{s1,s2}∈Ω,PlotRange->Full,AxesLabel->{"s1","s2"},PlotLabel->"Vr(s1,s2 )",BoxRatios->{1,1,1},Mesh->15,MeshStyle->{Blue,Red},PlotLegends->LineLegend[{Blue,Red},{s1,s2}],ImageSize->Medium]

playerOneStreamParametricPlot:=ParametricPlot3D[Evaluate@{effortTwo[s1,s2],effortOne[s1,s2],streamOne[s1,s2]},{s1,s2}∈Ω,PlotRange->Full,AxesLabel->{"r2","r1"},PlotLabel->"Vr1( r1(s1,s2), r2(s1,s2) )",BoxRatios->{1,1,1},Mesh->15,MeshStyle->{Blue,Red}]
playerTwoStreamParametricPlot:=ParametricPlot3D[Evaluate@{effortOne[s1,s2],effortTwo[s1,s2],streamTwo[s1,s2]},{s1,s2}∈Ω,PlotRange->Full,AxesLabel->{"r1","r2"},PlotLabel->"Vr2( r1(s1,s2), r2(s1,s2) )",BoxRatios->{1,1,1},Mesh->15,MeshStyle->{Blue,Red},PlotLegends->LineLegend[{Blue,Red},{s1,s2}]]
playerTotalStreamParametricPlot:=ParametricPlot3D[Evaluate@{effortOne[s1,s2],effortTwo[s1,s2],streamTotalPlayer[s1,s2]},{s1,s2}∈Ω,PlotRange->Full,AxesLabel->{"r1","r2"},PlotLabel->"Vr( r1(s1,s2), r2(s1,s2) )",BoxRatios->{1,1,1},Mesh->15,MeshStyle->{Blue,Red},PlotLegends->LineLegend[{ Blue,Red},{s1,s2}],ImageSize->Medium]
playerStreamParametricPlot:=Row@{playerOneStreamParametricPlot,playerTwoStreamParametricPlot}

integralStreams:=Row@{ParametricPlot3D[Evaluate@{effortTwo[s1,s2],effortOne[s1,s2],s1},{s1,s2}∈Ω,PlotRange->Full,AxesLabel->{"r2","r1"},PlotLabel->"s1(r1,r2)",BoxRatios->{1,1,1},Mesh->15,MeshStyle->{Blue,Red}],ParametricPlot3D[Evaluate@{effortOne[s1,s2],effortTwo[s1,s2],s2},{s1,s2}∈Ω,PlotRange->Full,AxesLabel->{"r1","r2"},PlotLabel->"s2(r1,r2)",BoxRatios->{1,1,1},Mesh->15,MeshStyle->{Blue,Red},PlotLegends->LineLegend[{Blue,Red},{s1,s2}]]}

dsJOffEffortGradientParametricPlot:=Row@{ParametricPlot3D[Evaluate@{effortTwo[s1,s2],effortOne[s1,s2],Tr[one.ds2yNumPreferences[s1,s2]]},{s1,s2}∈Ω,PlotRange->Full,AxesLabel->{"r2","r1"},PlotLabel->"Dr2/Ds1",BoxRatios->{1,1,1},Mesh->15,MeshStyle->{Blue,Red}],ParametricPlot3D[Evaluate@{effortOne[s1,s2],effortTwo[s1,s2],Tr[two.ds1yNumPreferences[s1,s2]]},{s1,s2}∈Ω,PlotRange->Full,AxesLabel->{"r1","r2"},PlotLabel->"Dr1/Ds2",BoxRatios->{1,1,1},Mesh->15,MeshStyle->{Blue,Red},PlotLegends->LineLegend[{Blue,Red},{s1,s2}]]}

dsJOnEffortGradientParametricPlot:=Row@{ParametricPlot3D[Evaluate@{effortTwo[s1,s2],effortOne[s1,s2],Tr[one.ds1yNumPreferences[s1,s2]]},{s1,s2}∈Ω,PlotRange->Full,AxesLabel->{"r2","r1"},PlotLabel->"Dr1/Ds1",BoxRatios->{1,1,1},Mesh->15,MeshStyle->{Blue,Red}],ParametricPlot3D[Evaluate@{effortOne[s1,s2],effortTwo[s1,s2],Tr[two.ds2yNumPreferences[s1,s2]]},{s1,s2}∈Ω,PlotRange->Full,AxesLabel->{"r1","r2"},PlotLabel->"Dr2/Ds2",BoxRatios->{1,1,1},Mesh->15,MeshStyle->{Blue,Red},PlotLegends->LineLegend[{Blue,Red},{s1,s2}]]}

18.1.4 | Network Useful Methods

Here we capture the methods needed in Chap. 7, including refinements of methods from previous methods to better model or display the owner streams. Here we plot the owner streams.

playerEffortStreamPlot:=StreamPlot[Evaluate@{effortOne[s1,s2],effortTwo[s1,s2]},{s1,s2}∈Ω,Mesh->50,MeshStyle->Orange,StreamStyle->Blue,FrameLabel->{"s1","s2"},PlotLabel->"{r1,r2} Player Effort Streams",ImageSize->Large]

Here we update the Valuation Gradient Law to allow for non-VGL contributions.

vglModel[s1_,s2_,range_]:=Tanh[ (s1-s2)/range]
boundaryInactiveOwnerFlows[s1_,s2_]:={e1 vglModel[s1,s2,inactiveRangeOne]+nonVGLModelOne[s1,s2] ,e2 vglModel[s1,s2,inactiveRangeTwo]+nonVGLModelTwo[s1,s2]}

To see the consequences of these new changes we need plots of the inactive flows.

plotInactiveFlowOneAgainstPlayerEffort:=ParametricPlot3D[Evaluate@{effortOne[s1,s2],effortTwo[s1,s2],numInactiveLowerFlows[s1,s2][[1]]},{s1,s2}∈Ω,BoxRatios->{1, 1, 1},AxesLabel->{"r1","r2","V1"},PlotLabel->"Covariant Inactive Flow",Mesh->10,MeshStyle->{Blue,Red}]
plotInactiveFlowTwoAgainstPlayerEffort:=ParametricPlot3D[Evaluate@{effortOne[s1,s2],effortTwo[s1,s2],numInactiveLowerFlows[s1,s2][[2]]},{s1,s2}∈Ω,BoxRatios->{1, 1, 1},AxesLabel->{"r1","r2","V2"},PlotLabel->"Covariant Inactive Flow",Mesh->10,MeshStyle->{Blue,Red}]

inactiveStreamPlot:=StreamPlot[Evaluate@{numInactiveLowerFlows[s1,s2][[1]],numInactiveLowerFlows[s1,s2][[2]]},{s1,s2}∈Ω,Mesh->50,MeshStyle->Orange,StreamStyle->Black,FrameLabel->{"s1","s2"},PlotLabel->"{InactiveV1,InactiveV2} Covariant Inactive Stream  Vectors",ImageSize->Large,BaseStyle->{FontWeight->"Bold"}]

We gain insight into the network behaviors by defining a type of “compression” and “shear” and providing their plots.

flowCompression[s1_,s2_]:=streamOne[s1,s2]-streamTwo[s1,s2]
flowShear1[s1_,s2_]:=numActiveUpperFlows[s1,s2].one-Tr[numActiveUpperFlows[s1,s2].one]/Tr[one] Diagonal[one]
flowShear2[s1_,s2_]:=numActiveUpperFlows[s1,s2].two-Tr[numActiveUpperFlows[s1,s2].two]/Tr[two] Diagonal[two]
flowShear[s1_,s2_]:=flowShear1[s1,s2]+flowShear2[s1,s2]

playerCompressionPlot:=Plot3D[flowCompression[s1,s2],{s1,s2}∈Ω,PlotLabel->"Player Compression",AxesLabel->{"s1","s2"},ImageSize->Medium]
playerShearPlots:=Table[Plot3D[Evaluate@flowShear[s1,s2][[k]],{s1,s2}∈Ω,PlotLabel->StringJoin["Player Shear: ",allStrategyString[[k]]],AxesLabel->{"s1","s2"},Mesh->10,MeshStyle->{Blue,Red}],{k,numActiveStrategies}]

We also now allow additional types of changes to the active flows. Before we considered only entitlement flows; this is now generalized.

entitlementFlow1:=First@NullSpace@dptGame[gameMatrix1,valueScale]
entitlementFlow2:=First@NullSpace@dptGame[gameMatrix2,valueScale]
nonEntitlementFlow1[s1_,s2_]:=Table[0,{k,numActiveStrategies+1}]
nonEntitlementFlow2[s1_,s2_]:=Table[0,{k,numActiveStrategies+1}]

With these generalizations, we have to update the way we compute the initial active flow boundary conditions and make the corresponding update to our computation of the preference boundary conditions.

initialTotalActiveFlow1[s1_,s2_]:=(entitlementFlow1+nonEntitlementFlow1[s1,s2]).one
initialTotalActiveFlow2[s1_,s2_]:=(entitlementFlow2+nonEntitlementFlow2[s1,s2]).two
time:=one+two+metric
(*initialTimeFlow[s1_,s2_]:=Sqrt[1.0-initialTotalActiveFlow1[s1,s2].metric.one.initialTotalActiveFlow1[s1,s2]-initialTotalActiveFlow2[s1,s2].metric.two.initialTotalActiveFlow2[s1,s2]-boundaryInactiveOwnerFlows[s1,s2].flatInactiveMetric.boundaryInactiveOwnerFlows[s1,s2]]Diagonal[time]*)
initialActiveFlow[s1_,s2_]:=initialTotalActiveFlow1[s1,s2]+initialTotalActiveFlow2[s1,s2]+initialTimeFlow[s1,s2]

(* rVariable[sJ_]:=Table[rJ[k][sJ],{k,numActiveStrategies+1}]
boundaryS1[s1_]:=NDSolveValue[Join[Equal@@@Transpose@{D[rVariable[sJ],sJ],initialActiveFlow[sJ,0]},Table[rVariable[0][[k]]==0,{k,numActiveStrategies+1}]],rVariable[sJ],{sJ,0,size}]/.{sJ->s1}
boundaryS2[s2_]:=NDSolveValue[Join[Equal@@@Transpose@{D[rVariable[sJ],sJ],initialActiveFlow[0,sJ]},Table[rVariable[0][[k]]==0,{k,numActiveStrategies+1}]],rVariable[sJ],{sJ,0,size}]/.{sJ->s2}
initPreference[s1_,s2_]:=boundaryS1[s1].(one+time)+boundaryS2[s2].(two+time)-Diagonal[time](s1+s2)initialTimeFlow[0,0]/2 *)

boundaryActiveOwnerFlows[s1_,s2_]:=initialActiveFlow[s1,s2] 
boundaryActiveOwnerPreferences[s1_,s2_]:=initPreference[s1,s2]

18.1.5 | Utility Gradients Useful Methods

Using the harmonic gauge, we compute the inactive compression scalar and its gradient in terms of the time compression ν(y) and the active compression scalar Φ(y). We can use the helper function in practice to provide the specific form of the input gradients for a given model.

gaugeΘ[s1_,s2_]:=ΘBase+(gaugeν[s1,s2]+(numActiveStrategies-2)gaugeΦ[s1,s2])/2
gradientGaugeΘ[s1_,s2_]:=(gradientGaugeν[s1,s2]+(numActiveStrategies-2)gradientGaugeΦ[s1,s2])/2

prefySymbolic:=Table[Subscript[y,k],{k,numActiveStrategies+1}]
symbolicToOwnerPreferences:=Rule@@@Transpose@{prefySymbolic,activeOwnerPreferences[s1,s2]}
scalarP[pref_]:=0
scalar[s1_,s2_]:=scalarP[activeOwnerPreferences[s1,s2]]
gradientScalar[s1_,s2_]:=Table[D[scalarP[prefySymbolic],Subscript[y, k]],{k,numActiveStrategies+1}]/.symbolicToOwnerPreferences

Given the gauge scalars as functions of the integral owners streams, we update our definition of the utility metrics, ignoring inactive shear, along with the various methods that use them.

Since we replace the flat inactive metric with a constant reduced inactive metric, we will need the following.

reducedInactiveMetric:=inputInactiveMetric/Sqrt[Det[inputInactiveMetric]]
inverseReducedInactiveMetric:=Inverse[reducedInactiveMetric]
ΘBase:=Log[Det[inputInactiveMetric]]/4

To compute the forces we insert the flat active and time metrics, along with the reduced inactive metric, each multiplied by their appropriate scalar factors (e^(2Φ)), (e^(2ν)) and (e^(2Θ)) respectively. We make the associated changes for the inverse metric contributions.

These changes require updates to the way in which we compute the preference boundary conditions. We change slightly the way we do the spatial components.

rVariable[sJ_]:=Table[rJ[k][sJ],{k,numActiveStrategies}]
boundaryS1[s1_]:=NDSolveValue[Join[Equal@@@Transpose@{D[rVariable[sJ],sJ],(initialTotalActiveFlow1[sJ,0].one)[[1;;-2]]},Table[rVariable[0][[k]]==0,{k,numActiveStrategies}]],rVariable[sJ],{sJ,0,size}]/.{sJ->s1}
boundaryS2[s2_]:=NDSolveValue[Join[Equal@@@Transpose@{D[rVariable[sJ],sJ],(initialTotalActiveFlow2[0,sJ].two)[[1;;-2]]},Table[rVariable[0][[k]]==0,{k,numActiveStrategies}]],rVariable[sJ],{sJ,0,size}]/.{sJ->s2}

We update the way we compute the initial time component of flow using the following rule based on the above spatial values of the preferences on the boundary.

boundaryPreferenceRule[s1_,s2_]:=Rule@@@Transpose[{activeOwnerPreferences[s1,s2][[1;;-2]],boundaryS1[s1]+boundaryS2[s2]}]

This leads to a new expression for the contravariant time flow.

initialTimeFlow[s1_,s2_]:=(Exp[-gaugeν[s1,s2]]Sqrt[1.0+Exp[2gaugeΦ[s1,s2]]initialTotalActiveFlow1[s1,s2].initialTotalActiveFlow1[s1,s2]+Exp[2gaugeΦ[s1,s2]]initialTotalActiveFlow2[s1,s2].initialTotalActiveFlow2[s1,s2]-Exp[-2gaugeΘ[s1,s2]]boundaryInactiveOwnerFlows[s1,s2].inverseReducedInactiveMetric.boundaryInactiveOwnerFlows[s1,s2]]Diagonal[time])/.boundaryPreferenceRule[s1,s2]

We use this expression to compute the time preference.

boundaryT1[s1_]:=NDSolveValue[{D[tVariable[sJ],sJ]==initialTimeFlow[sJ,0][[-1]],tVariable[0]==0},tVariable[sJ],{sJ,0,size}]/.{sJ->s1}
boundaryT2[s2_]:=NDSolveValue[{D[tVariable[sJ],sJ]==initialTimeFlow[0,sJ][[-1]],tVariable[0]==0},tVariable[sJ],{sJ,0,size}]/.{sJ->s2}
initTimePreference[s1_,s2_]:=boundaryT1[s1]+boundaryT2[s2]-(s1+s2)initialTimeFlow[0,0][[-1]]/2

We recompute the new preference vector on the boundary.

initPreference[s1_,s2_]:=Join[boundaryS1[s1]+boundaryS2[s2],{initTimePreference[s1,s2]}]

boundaryPreferencePlots:=Table[Plot3D[Evaluate@initPreference[s1,s2][[k]],{s1,s2}∈Ω,AxesLabel->{Subscript[s, 1],Subscript[s, 2]},PlotRange->Full,Mesh->15,MeshStyle->{Blue,Red},PlotLabel->StringJoin["Boundary Preferences: ",allStrategyString[[k]],"(s1,s2)"]],{k,numActiveStrategies+1}]

We make changes to the appropriate terms for computing forces using frame dependencies. For now, we also introduce an approximation to the exponential functions that appear using a small field approximation. This is done to accommodate the current version of NDSolve as well as our approach of solving the equations using the addition of small Laplacian terms in the equation for smoothing.

ownershipCompositePayoff[s1_,s2_]:=inactiveOwnerFlows[s1,s2][[1]] dptPayoff1+inactiveOwnerFlows[s1,s2][[2]] dptPayoff2+Exp[2gaugeν[s1,s2]] activeOwnerFlows[s1,s2][[-1]]seasonalInputPayoff
ownershipPayoffForce[s1_,s2_]:=ownershipCompositePayoff[s1,s2].activeOwnerFlows[s1,s2]
totalOwnershipActiveForces[s1_,s2_]:=Join[-ownershipPayoffForce[s1,s2][[1;;-2]]Exp[-2gaugeΦ[s1,s2]],Exp[-2gaugeν[s1,s2]]{ownershipPayoffForce[s1,s2][[-1]]}]+gradientGaugeActiveForces[s1,s2]
totalOwnershipInactiveForces[s1_,s2_]:={0,0}

gradientGaugeActiveForces[s1_,s2_]:=Join[-2 activeOwnerFlows[s1,s2][[1;;-2] ]activeOwnerFlows[s1,s2].gradientGaugeΦ[s1,s2]
,{-2 activeOwnerFlows[s1,s2][[-1]]activeOwnerFlows[s1,s2].gradientGaugeν[s1,s2] }]-Exp[2gaugeν[s1,s2]-2gaugeΦ[s1,s2]] activeOwnerFlows[s1,s2][[-1]]^2 gradientGaugeν[s1,s2]+activeOwnerFlows[s1,s2][[1;;-2]].activeOwnerFlows[s1,s2][[1;;-2]]gradientGaugeΦ[s1,s2]-Simplify[inactiveOwnerFlows[s1,s2].inverseReducedInactiveMetric.inactiveOwnerFlows[s1,s2]]Exp[-2gaugeΘ[s1,s2]-2gaugeΦ[s1,s2]]gradientGaugeΘ[s1,s2]

numericalPreferenceRule[s1_,s2_]:=Rule@@@Transpose[{activeOwnerPreferences[s1,s2],yNumPreferences[s1,s2]}]

numGaugeν[s1_,s2_]:=gaugeν[s1,s2]/.numericalPreferenceRule[s1,s2]
numGaugeΦ[s1_,s2_]:=gaugeΦ[s1,s2]/.numericalPreferenceRule[s1,s2]
numGaugeΘ[s1_,s2_]:=gaugeΘ[s1,s2]/.numericalPreferenceRule[s1,s2]
numGradientGaugeν[s1_,s2_]:=gradientGaugeν[s1,s2]
numGradientGaugeΦ[s1_,s2_]:=gradientGaugeΦ[s1,s2]
numGradientGaugeΘ[s1_,s2_]:=gradientGaugeΘ[s1,s2]

pathLengthSquaredDeviation[s1_,s2_]:=-numActiveUpperFlows[s1,s2][[1;;-2]].numActiveUpperFlows[s1,s2][[1;;-2]]Exp[2numGaugeΦ[s1,s2]]+numActiveUpperFlows[s1,s2][[-1]]numActiveUpperFlows[s1,s2][[-1]]Exp[2numGaugeν[s1,s2]]+numInactiveLowerFlows[s1,s2].inverseReducedInactiveMetric.numInactiveLowerFlows[s1,s2]Exp[-2numGaugeΘ[s1,s2]]-1.

ParametricPlayerCompressionPlot:=ParametricPlot3D[{Tr[yNumPreferences[s1,s2].one]/Tr[one],Tr[yNumPreferences[s1,s2].two]/Tr[two],flowCompression[s1,s2]},{s1,s2}∈Ω,Mesh->20,MeshStyle->{Blue,Red},AxesLabel->{"r1","r2","cFlow"},PlotLabel->"Parametric Values of Player Compression Flow vs r1 andr2",BoxRatios->{1,1,1},PlotRange->Full,ImageSize->Medium]

baseMixingAngle[g_]:=ArcTan[Eigensystem[g][[2]][[2]][[1]],-Eigensystem[g][[2]][[2]][[2]]]
baseDiagonalValues[g_]:=Eigenvalues[g]
σBase:=(1/4)(Log[-baseDiagonalValues[reducedInactiveMetric][[1]]]-Log[-baseDiagonalValues[reducedInactiveMetric][[2]]])
θBase:=baseMixingAngle[reducedInactiveMetric]

unitValue[g_]:=g 0+1
seasonalGameMatrix:= 0unitValue[gameMatrix]

seasonalInputPayoff:=gToSymG[pValuation1[seasonalGameMatrix]0,pValuation2[seasonalGameMatrix]0,seasonalGameMatrix]

totalOwnershipInactiveForces[s1_,s2_]:={0,0}

18.1.6 | Contextual Accelerations

We will need the numerical values for the contextual scalars.

numScalarϕ1[s1_,s2_]:=scalarϕ1[s1,s2]/.numericalPreferenceRule[s1,s2]
numScalarϕ2[s1_,s2_]:=scalarϕ2[s1,s2]/.numericalPreferenceRule[s1,s2]
numGradientScalarϕ1[s1_,s2_]:=gradientScalarϕ1[s1,s2]/.numericalPreferenceRule[s1,s2]
numGradientScalarϕ2[s1_,s2_]:=gradientScalarϕ2[s1,s2]/.numericalPreferenceRule[s1,s2]

There will be updates to the acceleration equations

ϵV:=10^-10
ϵY:=10^-10
activeOwnerPreferencesToFlow[s1_,s2_]:=Table[D[activeOwnerPreferences[s1,s2][[k]],s1]+D[activeOwnerPreferences[s1,s2][[k]],s2]+Inactive[Div][ϵY Inactive[Grad][activeOwnerPreferences[s1,s2][[k]],{s1,s2}],{s1,s2}],{k,numActiveStrategies+1}]
activeStreamlineAcceleration[s1_,s2_]:=Table[D[activeOwnerFlows[s1,s2][[k]],s1]+D[activeOwnerFlows[s1,s2][[k]],s2]+activeContextualAcceleration[s1,s2][[k]]+Inactive[Div][ϵV Inactive[Grad][activeOwnerFlows[s1,s2][[k]],{s1,s2}],{s1,s2}],{k,numActiveStrategies+1}]
inactiveStreamlineAccelerations[s1_,s2_]:=Table[D[inactiveOwnerFlows[s1,s2][[k]],s1]+D[inactiveOwnerFlows[s1,s2][[k]],s2]+inactiveContextualAcceleration[s1,s2][[k]]+Inactive[Div][ϵV Inactive[Grad][inactiveOwnerFlows[s1,s2][[k]],{s1,s2}],{s1,s2}],{k,2}]
activeOwnershipOneAcceleration[s1_,s2_]:=D[activeOwnerFlows[s1,s2],s1].one
activeOwnershipTwoAcceleration[s1_,s2_]:=D[activeOwnerFlows[s1,s2],s2].two
inactiveOwnershipOneAcceleration[s1_,s2_]:={D[inactiveOwnerFlows[s1,s2],s1][[1]],0}
inactiveOwnershipTwoAcceleration[s1_,s2_]:={0,D[inactiveOwnerFlows[s1,s2],s2][[2]]}

activeContextualAcceleration[s1_,s2_]:=activeOwnershipOneAcceleration[s1,s2]scalarϕ1[s1,s2]+activeOwnershipTwoAcceleration[s1,s2]scalarϕ2[s1,s2]
inactiveContextualAcceleration[s1_,s2_]:=inactiveOwnershipOneAcceleration[s1,s2]scalarϕ1[s1,s2]+inactiveOwnershipTwoAcceleration[s1,s2]scalarϕ2[s1,s2]

contextualScalarPlot:=Row@{Plot3D[numScalarϕ1[s1,s2],{s1,s2}∈Ω,AxesLabel->Automatic,PlotLabel->"ϕ1",PlotRange->Full],Plot3D[numScalarϕ2[s1,s2],{s1,s2}∈Ω,AxesLabel->Automatic,PlotLabel->"ϕ2",PlotRange->Full]}

In this chapter, we discuss games with a single strategy. We go back and update our color assignments to allow for that, since they were written assuming each player had at least two strategies.

colors1:=Table[RGBColor[0,(k-1)/(numberRows[gameMatrix]),1-(k-1)/(numberRows[gameMatrix])],{k,numberRows[gameMatrix]}]
strategyString2:=Table[StringJoin["P2S",ToString[k]],{k,numberColumns[gameMatrix]}]
colors2:=Table[RGBColor[1,(k-1)/numberColumns[gameMatrix],0],{k,numberColumns[gameMatrix]}]

18.1.7 | Cultural Sources

We add the market capital as a new variable to our equations. We need an initial value, which is based on the base market overhead. We update the variable list and the accelerations accordingly.

baseMarketOverhead:=5
baseMarketCapital:=Log[baseMarketOverhead]
marketCapitalOnBoundary[s1_,s2_]:=baseMarketCapital

contextualFractionOne:=1/100
contextualFractionTwo:=1/100
baseContextualStressOne:=contextualFractionOne (Tr[one]+Tr[two])/Tr[one]
baseContextualStressTwo:=contextualFractionTwo (Tr[one]+Tr[two])/Tr[two]
baseContextualStressAverage:=(baseContextualStressOne Tr[one]+ baseContextualStressTwo Tr[two])/(Tr[one]+Tr[two])

boundaryMarketCapital[s1_,s2_]:={marketCapital[s1,s2]==marketCapitalOnBoundary[s1,s2]}

variableList[s1_,s2_]:=Join[activeOwnerPreferences[s1,s2],activeOwnerFlows[s1,s2],inactiveOwnerFlows[s1,s2],ds1ActiveOwnerPreferences[s1,s2],ds2ActiveOwnerPreferences[s1,s2],{marketCapital[s1,s2]}]

marketCapitalAcceleration[s1_,s2_]:=D[marketCapital[s1,s2],s1]+D[marketCapital[s1,s2],s2]+Inactive[Div][ϵU Inactive[Grad][marketCapital[s1,s2],{s1,s2}],{s1,s2}]

marketCapitalSources[s1_,s2_]:=streamCompressionFactor[s1,s2]
marketCapitalEquation:={marketCapitalAcceleration[s1,s2]==marketCapitalSources[s1,s2]}

There are various source contributions to the longitudinal and transverse flows. Some of these we incorporate into the acceleration terms, which depend on the market capital.

activeContextualAcceleration[s1_,s2_]:=activeOwnershipOneAcceleration[s1,s2]Exp[-marketCapital[s1,s2]]scalarϕ1[s1,s2]+activeOwnershipTwoAcceleration[s1,s2]Exp[-marketCapital[s1,s2]]scalarϕ2[s1,s2]-timeStreamFactor[s1,s2]Diagonal[time]inverseCovariantTimeFlow[s1,s2]
inactiveContextualAcceleration[s1_,s2_]:=inactiveOwnershipOneAcceleration[s1,s2]Exp[-marketCapital[s1,s2]]scalarϕ1[s1,s2]+inactiveOwnershipTwoAcceleration[s1,s2]Exp[-marketCapital[s1,s2]]scalarϕ2[s1,s2]

We update the dynamic equations and boundary conditions based on our new inputs.

preferenceToFlowEquations:=Equal@@@Transpose@{activeOwnerPreferencesToFlow[s1,s2],activeOwnerFlows[s1,s2]}
activeFlowToAccelerationEquations:=(Equal@@@Transpose@{activeStreamlineAcceleration[s1,s2],totalOwnershipActiveForces[s1,s2]})
inactiveFlowToAccelerationEquations:=Equal@@@Transpose@{inactiveStreamlineAccelerations[s1,s2],totalOwnershipInactiveForces[s1,s2]}
pdeEquations[s1_,s2_]:=Join[preferenceToFlowEquations,activeFlowToAccelerationEquations,inactiveFlowToAccelerationEquations,marketCapitalEquation]

activeOwnershipFlowBoundaryEquations:=(Equal@@@Transpose@{activeOwnerFlows[s1,s2], boundaryActiveOwnerFlows[s1,s2]})
inactiveOwnershipFlowBoundaryEquations:=Equal@@@Transpose@{inactiveOwnerFlows[s1,s2], boundaryInactiveOwnerFlows[s1,s2]}
activeOwnershipPreferenceBoundaryEquations:=Equal@@@Transpose@{activeOwnerPreferences[s1,s2], boundaryActiveOwnerPreferences[s1,s2]}
totalOwnershipBoundaryEquations:=Join[activeOwnershipFlowBoundaryEquations,inactiveOwnershipFlowBoundaryEquations,activeOwnershipPreferenceBoundaryEquations,boundaryMarketCapital[s1,s2]]

There are numerical values that may be of interest and useful as inputs for plots.

numMarketCapital[s1_, s2_] := ownershipStreamlines[s1, s2][[4 numActiveStrategies + 7]]
numMarketBias[s1_,s2_]:=Exp[numMarketCapital[s1,s2]]

marketCapitalPlot:=Plot3D[numMarketCapital[s1,s2],{s1,s2}∈Ω,PlotRange->Full,AxesLabel->{"s1","s2"},PlotLabel->"Market Capital",PlotRange->Full]

marketBiasPlot:=Plot3D[numMarketBias[s1,s2],{s1,s2}∈Ω,PlotRange->Full,AxesLabel->{"s1","s2"},PlotLabel->"Market Bias",PlotRange->Full]

The forces can be separated into those that appear as accelerations on the left-hand-side of the equations and sources on the right-hand-side. These are the sources on the right-hand-side.

ownershipInactiveContextualGradientForce[s1_,s2_]:={-inactiveOwnerFlows[s1,s2][[1]]gradientScalarϕ1[s1,s2].one.activeOwnerFlows[s1,s2]Exp[-marketCapital[s1,s2]],-inactiveOwnerFlows[s1,s2][[2]]gradientScalarϕ2[s1,s2].two.activeOwnerFlows[s1,s2]Exp[-marketCapital[s1,s2]]}
totalOwnershipInactiveForces[s1_,s2_]:=ownershipInactiveContextualGradientForce[s1,s2]-inactiveOwnerFlows[s1,s2]streamCompressionFactor[s1,s2]

activeContextualGradientFrame[s1_,s2_]:=Exp[-marketCapital[s1,s2]] scalarϕ1[s1,s2](gradientGaugeΦ[s1,s2].one(Exp[-2gaugeΦ[s1,s2]](Tr[one]-2)+activeOwnerFlows[s1,s2].one.activeOwnerFlows[s1,s2])-2activeOwnerFlows[s1,s2].one activeOwnerFlows[s1,s2].one.gradientGaugeΦ[s1,s2])+Exp[-marketCapital[s1,s2]] scalarϕ2[s1,s2](gradientGaugeΦ[s1,s2].two(Exp[-2gaugeΦ[s1,s2]](Tr[two]-2)+activeOwnerFlows[s1,s2].two.activeOwnerFlows[s1,s2])-2activeOwnerFlows[s1,s2].two activeOwnerFlows[s1,s2].two.gradientGaugeΦ[s1,s2])+timeContextualCouplingGradients[s1,s2]Diagonal[time]+timeAccelerationSourceGradients[s1,s2]Diagonal[time]+timeAccelerationFrameGradients[s1,s2]Diagonal[time]+Exp[-marketCapital[s1,s2]]scalarϕ2[s1,s2]gradientGaugeΦ[s1,s2].one(Tr[two]Exp[-2gaugeΦ[s1,s2]]+activeOwnerFlows[s1,s2].two.activeOwnerFlows[s1,s2])+Exp[-marketCapital[s1,s2]]scalarϕ1[s1,s2]gradientGaugeΦ[s1,s2].two(Tr[one]Exp[-2gaugeΦ[s1,s2]]+activeOwnerFlows[s1,s2].one.activeOwnerFlows[s1,s2])

ownershipActiveContextualGradientForce[s1_,s2_]:=-Exp[-marketCapital[s1,s2]](Exp[-2gaugeΦ[s1,s2]]gradientScalarϕ1[s1,s2].one+activeOwnerFlows[s1,s2].one.gradientScalarϕ1[s1,s2]activeOwnerFlows[s1,s2].one)-Exp[-marketCapital[s1,s2]](Exp[-2gaugeΦ[s1,s2]]gradientScalarϕ2[s1,s2].two+activeOwnerFlows[s1,s2].two.gradientScalarϕ2[s1,s2]activeOwnerFlows[s1,s2].two)+activeContextualGradientFrame[s1,s2]

ownershipCompositePayoff[s1_,s2_]:=inactiveOwnerFlows[s1,s2][[1]] dptPayoff1+inactiveOwnerFlows[s1,s2][[2]] dptPayoff2+Exp[2gaugeν[s1,s2]] activeOwnerFlows[s1,s2][[-1]]seasonalInputPayoff
ownershipPayoffForce[s1_,s2_]:=ownershipCompositePayoff[s1,s2].activeOwnerFlows[s1,s2]
totalOwnershipActiveForces[s1_,s2_]:=Join[-ownershipPayoffForce[s1,s2][[1;;-2]]Exp[-2gaugeΦ[s1,s2]],Exp[-2gaugeν[s1,s2]]{ownershipPayoffForce[s1,s2][[-1]]}]+gradientGaugeActiveForces[s1,s2]+ownershipActiveContextualGradientForce[s1,s2]-activeOwnerFlows[s1,s2] streamCompressionFactor[s1,s2]

streamCompressionFactor[s1_,s2_]:=-Exp[-2gaugeΘ[s1,s2]]inactiveOwnerFlows[s1,s2].inverseReducedInactiveMetric.inactiveContextualAcceleration[s1,s2]+Exp[2gaugeΦ[s1,s2]]activeOwnerFlows[s1,s2].(one+two).activeContextualAcceleration[s1,s2]+Exp[-2gaugeΘ[s1,s2]]inactiveOwnerFlows[s1,s2].inverseReducedInactiveMetric.ownershipInactiveContextualGradientForce[s1,s2]-Exp[2gaugeΦ[s1,s2]]activeOwnerFlows[s1,s2].(one+two).ownershipActiveContextualGradientForce[s1,s2]+timeStreamFactor[s1,s2]+Exp[2gaugeν[s1,s2]]activeOwnerFlows[s1,s2].time.ownershipActiveContextualGradientForce[s1,s2]

For the time component of the acceleration, we need the following.

scalarψ1[s1_,s2_]:=Exp[-2gaugeΘ[s1,s2]]inactiveOwnerFlows[s1,s2][[1]](inverseReducedInactiveMetric.inactiveOwnerFlows[s1,s2])[[1]]-Exp[2gaugeΦ[s1,s2]]activeOwnerFlows[s1,s2].one.activeOwnerFlows[s1,s2]
scalarψ2[s1_,s2_]:=Exp[-2gaugeΘ[s1,s2]]inactiveOwnerFlows[s1,s2][[2]](inverseReducedInactiveMetric.inactiveOwnerFlows[s1,s2])[[2]]-Exp[2gaugeΦ[s1,s2]]activeOwnerFlows[s1,s2].two.activeOwnerFlows[s1,s2]
scalarψJ[s1_,s2_]:={scalarψ1[s1,s2],scalarψ2[s1,s2]}

numScalarψ1[s1_,s2_]:=Exp[-2numGaugeΘ[s1,s2]]numInactiveLowerFlows[s1,s2][[1]](inverseReducedInactiveMetric.numInactiveLowerFlows[s1,s2])[[1]]-Exp[2numGaugeΦ[s1,s2]]numActiveUpperFlows[s1,s2].one.numActiveUpperFlows[s1,s2]
numScalarψ2[s1_,s2_]:=Exp[-2numGaugeΘ[s1,s2]]numInactiveLowerFlows[s1,s2][[2]](inverseReducedInactiveMetric.numInactiveLowerFlows[s1,s2])[[2]]-Exp[2numGaugeΦ[s1,s2]]numActiveUpperFlows[s1,s2].two.numActiveUpperFlows[s1,s2]

plotψJ:=Row@{Plot3D[numScalarψ1[s1,s2],{s1,s2}∈Ω,AxesLabel->Automatic,PlotLabel->"ψ1(s1,s2)"],Plot3D[numScalarψ2[s1,s2],{s1,s2}∈Ω,AxesLabel->Automatic,PlotLabel->"ψ2(s1,s2)"]}

The time sources depend on the time stream factor and a specific form for the inverse of the covariant time flow.

timeStreamFactor[s1_,s2_]:=Exp[-marketCapital[s1,s2]]scalarϕ1[s1,s2](1-scalarψ1[s1,s2])D[activeOwnerFlows[s1,s2][[-1]],s1]inverseTimeFlow[s1,s2]+Exp[-marketCapital[s1,s2]]scalarϕ2[s1,s2](1-scalarψ2[s1,s2])D[activeOwnerFlows[s1,s2][[-1]],s2]inverseTimeFlow[s1,s2]

inverseCovariantTimeFlow[s1_,s2_]:=activeOwnerFlows[s1,s2][[-1]]/(1-Exp[-2gaugeΘ[s1,s2]]inactiveOwnerFlows[s1,s2].inverseReducedInactiveMetric.inactiveOwnerFlows[s1,s2]+Exp[2gaugeΦ[s1,s2]]activeOwnerFlows[s1,s2].(one+two).activeOwnerFlows[s1,s2])
inverseTimeFlow[s1_,s2_]:=Exp[2gaugeν[s1,s2]]inverseCovariantTimeFlow[s1,s2]

There are then a number of sources to include from the time accelerations.

timeAccelerationFrameGradients[s1_,s2_]:=-2Exp[-marketCapital[s1,s2]]inverseCovariantTimeFlow[s1,s2](Exp[-2gaugeΘ[s1,s2]]inactiveOwnerFlows[s1,s2][[1]](inverseReducedInactiveMetric.inactiveOwnerFlows[s1,s2])[[1]]activeOwnerFlows[s1,s2].one.gradientGaugeΘ[s1,s2]+Exp[2gaugeΦ[s1,s2]]activeOwnerFlows[s1,s2].one.activeOwnerFlows[s1,s2]activeOwnerFlows[s1,s2].one.gradientGaugeΦ[s1,s2])-2Exp[-marketCapital[s1,s2]]inverseCovariantTimeFlow[s1,s2](Exp[-2gaugeΘ[s1,s2]]inactiveOwnerFlows[s1,s2][[2]](inverseReducedInactiveMetric.inactiveOwnerFlows[s1,s2])[[2]]activeOwnerFlows[s1,s2].two.gradientGaugeΘ[s1,s2]+Exp[2gaugeΦ[s1,s2]]activeOwnerFlows[s1,s2].two.activeOwnerFlows[s1,s2]activeOwnerFlows[s1,s2].two.gradientGaugeΦ[s1,s2])

timeContextualCouplingGradients[s1_,s2_]:=-Exp[-marketCapital[s1,s2]]inverseCovariantTimeFlow[s1,s2]((1-scalarψ1[s1,s2])activeOwnerFlows[s1,s2].one.gradientScalarϕ1[s1,s2]+(1-scalarψ2[s1,s2])activeOwnerFlows[s1,s2].two.gradientScalarϕ2[s1,s2])

timeAccelerationSourceGradients[s1_,s2_]:=(scalarϕ1[s1,s2](Exp[-2gaugeΘ[s1,s2]]D[inactiveOwnerFlows[s1,s2][[1]],s1](inverseReducedInactiveMetric.inactiveOwnerFlows[s1,s2])[[1]]+Exp[-2gaugeΘ[s1,s2]]inactiveOwnerFlows[s1,s2][[1]](inverseReducedInactiveMetric.D[inactiveOwnerFlows[s1,s2],s1])[[1]]-2Exp[2gaugeΦ[s1,s2]]D[activeOwnerFlows[s1,s2],s1].one.activeOwnerFlows[s1,s2])+scalarϕ2[s1,s2](Exp[-2gaugeΘ[s1,s2]]D[inactiveOwnerFlows[s1,s2][[2]],s2](inverseReducedInactiveMetric.inactiveOwnerFlows[s1,s2])[[2]]+Exp[-2gaugeΘ[s1,s2]]inactiveOwnerFlows[s1,s2][[2]](inverseReducedInactiveMetric.D[inactiveOwnerFlows[s1,s2],s2])[[2]]-2Exp[2gaugeΦ[s1,s2]]D[activeOwnerFlows[s1,s2],s2].two.activeOwnerFlows[s1,s2]))inverseCovariantTimeFlow[s1,s2]Exp[-marketCapital[s1,s2]]

18.1.8 | Bonding, Valuation and Payoff Sources

For the bonding effects, we need the input compression scalar fields. We provide plots for each of them.

gaugeScalarPlots:=Row@{Plot3D[numGaugeν[s1,s2],{s1,s2}∈Ω,AxesLabel->Automatic,PlotLabel->"ν(s1,s2)",PlotRange->Full],Plot3D[numGaugeΦ[s1,s2],{s1,s2}∈Ω,AxesLabel->Automatic,PlotLabel->"Φ(s1,s2)",PlotRange->Full],Plot3D[numGaugeΘ[s1,s2],{s1,s2}∈Ω,AxesLabel->Automatic,PlotLabel->"Θ(s1,s2)",PlotRange->Full]}

The player valuation effects depend on evaluating new sources. These are interactions of the player valuation field with the contextual couplings.

activeSourceZ5[s1_,s2_]:=Exp[-marketCapital[s1,s2]]Exp[-2gaugeν[s1,s2]]scalarϕ1[s1,s2]inactiveOwnerFlows[s1,s2][[1]]time.dptPayoff1.one.activeOwnerFlows[s1,s2]+Exp[-marketCapital[s1,s2]]Exp[-2gaugeν[s1,s2]]scalarϕ2[s1,s2]inactiveOwnerFlows[s1,s2][[2]]time.dptPayoff2.two.activeOwnerFlows[s1,s2]

activeSourceZ21[s1_,s2_]:=Exp[-marketCapital[s1,s2]]Exp[-2gaugeΦ[s1,s2]]inverseCovariantTimeFlow[s1,s2](dptPayoff1.Diagonal[time]scalarϕ1[s1,s2](inactiveOwnerFlows[s1,s2][[1]]scalarψ1[s1,s2]-reducedInactiveMetric[[1]][[1]](inverseReducedInactiveMetric.inactiveOwnerFlows[s1,s2])[[1]])+dptPayoff2.Diagonal[time]scalarϕ2[s1,s2](inactiveOwnerFlows[s1,s2][[2]]scalarψ2[s1,s2]-reducedInactiveMetric[[2]][[2]](inverseReducedInactiveMetric.inactiveOwnerFlows[s1,s2])[[2]]))

The player payoff and seasonal payoff fields also require new sources, that interact with the contextual couplings.

activeSourceZ22[s1_,s2_]:=-Exp[-marketCapital[s1,s2]]Exp[-2gaugeΦ[s1,s2]](scalarϕ1[s1,s2]inactiveOwnerFlows[s1,s2][[1]](one+two).dptPayoff1.one.activeOwnerFlows[s1,s2]+scalarϕ2[s1,s2]inactiveOwnerFlows[s1,s2][[2]](one+two).dptPayoff2.two.activeOwnerFlows[s1,s2])

activeSourceZ23[s1_,s2_]:=-Exp[-marketCapital[s1,s2]]Exp[-2gaugeΦ[s1,s2]]inverseTimeFlow[s1,s2](scalarϕ1[s1,s2](1-scalarψ1[s1,s2])seasonalInputPayoff.one.activeOwnerFlows[s1,s2]+scalarϕ2[s1,s2](1-scalarψ2[s1,s2])seasonalInputPayoff.two.activeOwnerFlows[s1,s2])

The bonding effects are interactions between the compression scalars and the contextual scalars. We separate out the contribution we have computed earlier.

(e^(-(Subscript[μ, C])))((Subscript[Z, 1f])^(υ[J]))=(e^(-(Subscript[μ, C])))(∂_(υ[J]))Φ(∑_K)(Subscript[φ, K])(((Subscript[n, K])−2(Subscript[δ, JK]))(e^(−2Φ))+(∑_(υ'[K]))((Overscript[V, ¯])^(υ'[K]))((Overscript[V, ¯])^(υ'[K])))−2(e^(-(Subscript[μ, C])))(Subscript[φ, J])((Overscript[V, ¯])^(υ[J]))((Overscript[V, ¯])^(υ'[J]))(∂_(υ'[J]))Φ

activeSourceZ1f[s1_,s2_]:=Exp[-marketCapital[s1,s2]] scalarϕ1[s1,s2](gradientGaugeΦ[s1,s2].one(Exp[-2gaugeΦ[s1,s2]](Tr[one]-2)+activeOwnerFlows[s1,s2].one.activeOwnerFlows[s1,s2])-2activeOwnerFlows[s1,s2].one activeOwnerFlows[s1,s2].one.gradientGaugeΦ[s1,s2])+Exp[-marketCapital[s1,s2]] scalarϕ2[s1,s2](gradientGaugeΦ[s1,s2].two(Exp[-2gaugeΦ[s1,s2]](Tr[two]-2)+activeOwnerFlows[s1,s2].two.activeOwnerFlows[s1,s2])-2activeOwnerFlows[s1,s2].two activeOwnerFlows[s1,s2].two.gradientGaugeΦ[s1,s2])+Exp[-marketCapital[s1,s2]]scalarϕ2[s1,s2]gradientGaugeΦ[s1,s2].one(Tr[two]Exp[-2gaugeΦ[s1,s2]]+activeOwnerFlows[s1,s2].two.activeOwnerFlows[s1,s2])+Exp[-marketCapital[s1,s2]]scalarϕ1[s1,s2]gradientGaugeΦ[s1,s2].two(Tr[one]Exp[-2gaugeΦ[s1,s2]]+activeOwnerFlows[s1,s2].one.activeOwnerFlows[s1,s2])

Along with that earlier contribution, we also have the two new contributions.

activeSourceZ31[s1_,s2_]:=Exp[-marketCapital[s1,s2]]Exp[-2gaugeΦ[s1,s2]]gradientGaugeΘ[s1,s2](scalarϕ1[s1,s2](inverseReducedInactiveMetric[[1]][[1]]reducedInactiveMetric[[1]][[1]]-Exp[-2gaugeΘ[s1,s2]]inactiveOwnerFlows[s1,s2][[1]]inverseReducedInactiveMetric[[1]][[1]]inactiveOwnerFlows[s1,s2][[1]])+scalarϕ2[s1,s2](inverseReducedInactiveMetric[[2]][[2]]reducedInactiveMetric[[2]][[2]]-Exp[-2gaugeΘ[s1,s2]]inactiveOwnerFlows[s1,s2][[2]]inverseReducedInactiveMetric[[2]][[2]]inactiveOwnerFlows[s1,s2][[2]]))

(e^(-(Subscript[μ, C])))((Subscript[Z, 3.2])^(υ[J]))=(1/(((Overscript[V, ¯])^ο)(Subscript[(Overscript[V, ¯]), ο])))(e^(-(Subscript[μ, C])))(∂_(υ[J]))ν(∑_K)(Subscript[φ, K])(−(∑_(υ'[K]))((Overscript[V, ¯])^(υ'[K]))((Overscript[V, ¯])^(υ'[K]))+(e^(−2Φ))(e^(−2Θ))(Subscript[(Overscript[γ, ˜]), KK])(((((Overscript[γ, ˜])^(Kj))(Subscript[V, j])))^2)−(e^(−2Φ))((Subscript[ψ, K])^2))

activeSourceZ32[s1_,s2_]:=Exp[-marketCapital[s1,s2]]inverseCovariantTimeFlow[s1,s2]inverseTimeFlow[s1,s2]gradientGaugeν[s1,s2](scalarϕ1[s1,s2](-activeOwnerFlows[s1,s2].one.activeOwnerFlows[s1,s2]+Exp[-2gaugeΦ[s1,s2]]Exp[-2gaugeΘ[s1,s2]]reducedInactiveMetric[[1]][[1]](inverseReducedInactiveMetric.inactiveOwnerFlows[s1,s2])[[1]]^2-Exp[-2gaugeΦ[s1,s2]]scalarψ1[s1,s2]^2)+scalarϕ2[s1,s2](-activeOwnerFlows[s1,s2].two.activeOwnerFlows[s1,s2]+Exp[-2gaugeΦ[s1,s2]]Exp[-2gaugeΘ[s1,s2]]reducedInactiveMetric[[2]][[2]](inverseReducedInactiveMetric.inactiveOwnerFlows[s1,s2])[[2]]^2-Exp[-2gaugeΦ[s1,s2]]scalarψ2[s1,s2]^2))

These contributions update the ownership active contextual gradient force as well as the active contextual gradient frame. Based on the previous subsection, these new effects will automatically be added to the stream compression factor.

ownershipActiveContextualGradientForce[s1_,s2_]:=-Exp[-marketCapital[s1,s2]](Exp[-2gaugeΦ[s1,s2]]gradientScalarϕ1[s1,s2].one+activeOwnerFlows[s1,s2].one.gradientScalarϕ1[s1,s2]activeOwnerFlows[s1,s2].one)-Exp[-marketCapital[s1,s2]](Exp[-2gaugeΦ[s1,s2]]gradientScalarϕ2[s1,s2].two+activeOwnerFlows[s1,s2].two.gradientScalarϕ2[s1,s2]activeOwnerFlows[s1,s2].two)+activeContextualGradientFrame[s1,s2]+activeSourceZ5[s1,s2]+activeSourceZ21[s1,s2]+activeSourceZ22[s1,s2]+activeSourceZ23[s1,s2]

activeContextualGradientFrame[s1_,s2_]:=activeSourceZ1f[s1,s2]+timeContextualCouplingGradients[s1,s2]Diagonal[time]+timeAccelerationSourceGradients[s1,s2]Diagonal[time]+timeAccelerationFrameGradients[s1,s2]Diagonal[time]+activeSourceZ31[s1,s2]+activeSourceZ32[s1,s2]

The following are useful plots of the sum and difference of the covariant inactive flows that were not included previously.

sumAndDifferenceCovariantInactiveFlowPlots:=Row@{Plot3D[(numInactiveLowerFlows[s1,s2][[1]]+numInactiveLowerFlows[s1,s2][[2]]),{s1,s2}∈Ω,PlotLabel->"e1(s1,s2)+e2(s1,s2)",AxesLabel->Automatic],Plot3D[(numInactiveLowerFlows[s1,s2][[1]]-numInactiveLowerFlows[s1,s2][[2]]),{s1,s2}∈Ω,PlotLabel->"e1(s1,s2)-e2(s1,s2)",AxesLabel->Automatic]}

18.1.9 | Harmonic Disruptions

To compute the harmonic disruptions, we express the compression scalars in terms of appropriate variables for the harmonic equation. We translate this into the format we have used for the compression scalars. However, to be consistent with the definition for  (Subscript[r, J]) used in the discussion for disruptions, we redefine the efforts for player one and two scaled by the number of player strategies.

effortOne[s1_,s2_]:=Tr[one.yNumPreferences[s1,s2]]/Tr[one]
effortTwo[s1_,s2_]:=Tr[two.yNumPreferences[s1,s2]]/Tr[two]
effortTotal[s1_,s2_]:=Tr[one]effortOne[s1,s2]+Tr[one]effortTwo[s1,s2]

We translate the player efforts (Subscript[r, J]) into the basis (Subscript[(OverBar[r]), J])=(Sqrt[(Subscript[n, J])])(Subscript[r, J]) that makes the Laplacian diagonal.

rToRBar:={r1-> rBar1/Sqrt[Tr[one]],r2-> rBar2/ Sqrt[Tr[two]]}
rToPref:={r1->Tr[pref.one]/Tr[one],r2->Tr[pref.two]/Tr[two]}
gaugeνRBar[rBar1_,rBar2_]:=gaugeνR[r1,r2]/.rToRBar
gaugeΦRBar[rBar1_,rBar2_]:=gaugeΦR[r1,r2]/.rToRBar

harmonicEquation[ω_,w_]:=Laplacian[w[rBar1,rBar2],{rBar1,rBar2}]+w[rBar1,rBar2](Exp[-2gaugeνR[rBar1,rBar2]+2gaugeΦR[rBar1,rBar2]]-seasonalPayoffConstant^2(rBar1^2+rBar2^2)/4)ω^2-I ω  seasonalPayoffConstant (rBar1 D[w[rBar1,rBar2],rBar2]-rBar2 D[w[rBar1,rBar2],rBar1])==0

We solve for the harmonic behavior of the scalar as a function of the input frequency and Dirichlet condition value.

harmonicScalar[w_]:=ParametricNDSolveValue[{harmonicEquation[ω,w],DirichletCondition[w[rBar1,rBar2]==harmonicBoundaryCondition,True]},{w[rBar1,rBar2],D[w[rBar1,rBar2],rBar1],D[w[rBar1,rBar2],rBar2]},{rBar1,rBar2}∈ΩHarmonic,{ω},MaxSteps-> ∞]

The harmonic boundary condition is a function of the player efforts (Subscript[r, J]). We set it as part of our boundary conditions and transform it to the diagonal basis.

harmonicBoundaryCondition:=harmonicBoundaryFunction[r1,r2]/.rToRBar

We get a sense of the solutions by plotting the harmonic scalar for  typical values.

harmonicScalarPlot[maxω_]:=Manipulate[Row@{Plot3D[Evaluate@Re@harmonicScalar[w][ω][[1]],{rBar1,rBar2}∈ΩHarmonic,PlotRange->Full,AxesLabel->{"r1bar1","rbar2"},PlotLabel->"Re Harmonic Scalar"],Plot3D[Evaluate@Im@harmonicScalar[w][ω][[1]],{rBar1,rBar2}∈ΩHarmonic,PlotRange->Full,AxesLabel->{"r1bar1","rbar2"},PlotLabel->"Im Harmonic Scalar"]},{{ω,maxω/5},0,maxω}]

harmonicListFrequencyPlot[maxω_]:=Row@{ListPlot[Table[{maxω k/100,Re@harmonicScalar[w][maxω k/100][[1]]/.{rBar1->middleHarmonicr1,rBar2->middleHarmonicr2}},{k,0,100}],AxesLabel->{"ω","Re harmonic scalar"}],ListPlot[Table[{maxω k/100,Im@harmonicScalar[w][maxω k/100][[1]]/.{rBar1->middleHarmonicr1,rBar2->middleHarmonicr2}},{k,0,100}],AxesLabel->{"ω","Im harmonic scalar"}]}
harmonicFrequencyPlot[maxω_]:=Re@{Plot[Abs@harmonicScalar[w][ω1][[1]]/.{rBar1->middleHarmonicr1,rBar2->middleHarmonicr2},{ω1,0,maxω},AxesLabel->{"ω","Re harmonic scalar"}],Plot[Im@harmonicScalar[w][ω1][[1]]/.{rBar1->middleHarmonicr1,rBar2->middleHarmonicr2},{ω1,0,maxω},AxesLabel->{"ω","Im harmonic scalar"}]}

The diagonal basis efforts are expressed in terms of the owner streams.

rBar1Num[s1_,s2_]:=Tr[one.yNumPreferences[s1,s2]]/Sqrt[Tr[one]]
rBar2Num[s1_,s2_]:=Tr[two.yNumPreferences[s1,s2]]/Sqrt[Tr[two]]

harmonicPreferencesNum[rBar1_,rBar2_]:=numHarmonicScalar[rBar1,rBar2][[1]]
harmonicPreferencesDr1Num[rBar1_,rBar2_]:=numHarmonicScalar[rBar1,rBar2][[2]]
harmonicPreferencesDr2Num[rBar1_,rBar2_]:=numHarmonicScalar[rBar1,rBar2][[3]]

harmonicPreferenceStream[s1_,s2_]:=harmonicPreferencesNum[rBar1Num[s1,s2],rBar2Num[s1,s2]]
reHarmonicPreferenceStream[s1_,s2_]:=Re@harmonicPreferencesNum[rBar1Num[s1,s2],rBar2Num[s1,s2]]
imHarmonicPreferenceStream[s1_,s2_]:=Im@harmonicPreferencesNum[rBar1Num[s1,s2],rBar2Num[s1,s2]]
wHarmonic1[s1_,s2_]:=harmonicPreferencesDr1Num[rBar1Num[s1,s2],rBar2Num[s1,s2]]Tr[one.numActiveUpperFlows[s1,s2]]/Sqrt[Tr[one]]+harmonicPreferencesDr2Num[rBar1Num[s1,s2],rBar2Num[s1,s2]]Tr[two.numActiveUpperFlows[s1,s2]]/Sqrt[Tr[two]]
wHarmonic2[s1_,s2_]:=I ωSample harmonicPreferenceStream[s1,s2] numActiveUpperFlows[s1,s2][[-1]]
reWHarmonic[s1_,s2_]:=Re[wHarmonic1[s1,s2]+wHarmonic2[s1,s2]]
imWHarmonic[s1_,s2_]:=Im[wHarmonic1[s1,s2]+wHarmonic2[s1,s2]]
harmonicPhase[s1_,s2_]:=ArcTan[reWHarmonic[s1,s2],imWHarmonic[s1,s2]]180/Pi
harmonicIPhase[s1_,s2_]:=ArcTan[-imWHarmonic[s1,s2],reWHarmonic[s1,s2]]180/Pi

harmonicPreferenceStreamPlot:=Row@{Plot3D[reHarmonicPreferenceStream[s1,s2],{s1,s2}∈Ω,PlotRange->Full,AxesLabel->Automatic,PlotLabel->"Re harmonic preference stream"],Plot3D[imHarmonicPreferenceStream[s1,s2],{s1,s2}∈Ω,PlotRange->Full,AxesLabel->Automatic,PlotLabel->"Im harmonic preference stream"]}
reHarmonicFlowPlot:=Plot3D[reWHarmonic[s1,s2],{s1,s2}∈Ω,PlotRange->Full,AxesLabel->Automatic,PlotLabel->"Re Harmonic Flow Scalar"]
imHarmonicFlowPlot:=Plot3D[imWHarmonic[s1,s2],{s1,s2}∈Ω,PlotRange->Full,AxesLabel->Automatic,PlotLabel->"Im Harmonic Flow Scalar"]
harmonicPhasePlot:=Plot3D[harmonicPhase[s1,s2],{s1,s2}∈Ω,AxesLabel->Automatic,PlotLabel->"Harmonic W Phase (degrees)",PlotRange->Full]
harmonicIPhasePlot:=Plot3D[harmonicIPhase[s1,s2],{s1,s2}∈Ω,AxesLabel->Automatic,PlotLabel->"Harmonic i W Phase (degrees)",PlotRange->Full]
harmonicFlowPlots:=Row@{reHarmonicFlowPlot,imHarmonicFlowPlot}

harmonicEigenSystem:=NDEigensystem[{-Exp[2gaugeνRBar[rBar1,rBar2]-2gaugeΦRBar[rBar1,rBar2]]Laplacian[w[rBar1,rBar2],{rBar1,rBar2}],DirichletCondition[w[rBar1,rBar2]==0,True]},w,{rBar1,rBar2}∈ΩHarmonic,10]

18.1.10 | Mechanisms

In general, in this subsection, we are not updating the decision process toolkit (Secs. 15.1.1-15.1.9), but mainly adding enhancements for display and understanding of the various mechanisms that are in the toolkit.

harmonicFlowManipulatePlot[maxω_]:=Manipulate[{ωSample:=ω,numHarmonicScalar[rBar1_,rBar2_]=harmonicScalar[w][ωSample]};harmonicFlowPlots,{{ω,maxω/2},1,maxω}]

Here are some tools for the inertial mechanisms; specifically the market bias.

parametricMarketBiasPlot:=ParametricPlot3D[{effortOne[s1,s2],effortTwo[s1,s2],numMarketBias[s1,s2]},{s1,s2}∈Ω,PlotRange->Full,AxesLabel->{"r1","r2","μ"},PlotLabel->"Market Bias",BoxRatios->{1,1,1},Mesh->15,MeshStyle->{Blue,Red}]

parametricEngagementSumAndDifferencePlot:=Row@{ParametricPlot3D[{effortOne[s1,s2],effortTwo[s1,s2],numInactiveLowerFlows[s1,s2][[1]]+numInactiveLowerFlows[s1,s2][[2]]},{s1,s2}∈Ω,PlotRange->Full,AxesLabel->{"r1","r2","e1+e2"},PlotLabel->"Inactive Sum",BoxRatios->{1,1,1},Mesh->15,MeshStyle->{Blue,Red}],ParametricPlot3D[{effortOne[s1,s2],effortTwo[s1,s2],numInactiveLowerFlows[s1,s2][[1]]-numInactiveLowerFlows[s1,s2][[2]]},{s1,s2}∈Ω,PlotRange->Full,AxesLabel->{"r1","r2","e1-e2"},PlotLabel->"Inactive Difference",BoxRatios->{1,1,1},Mesh->15,MeshStyle->{Blue,Red}]}

parametricTimeFlowPlot:=ParametricPlot3D[{effortOne[s1,s2],effortTwo[s1,s2],numActiveUpperFlows[s1,s2][[-1]]},{s1,s2}∈Ω,PlotRange->Full,AxesLabel->{"r1","r2","V"},PlotLabel->"Time Flow",BoxRatios->{1,1,1},Mesh->15,MeshStyle->{Blue,Red}]

parametricStrategyFlowPlot[k_]:=ParametricPlot3D[{effortOne[s1,s2],effortTwo[s1,s2],numActiveUpperFlows[s1,s2][[k]]},{s1,s2}∈Ω,PlotRange->Full,AxesLabel->{"r1","r2","V"},PlotLabel->StringJoin["Flows: ",allStrategyString[[k]]],BoxRatios->{1,1,1},Mesh->15,MeshStyle->{Blue,Red}]

parametricPreferencePlot[k_]:=ParametricPlot3D[{effortOne[s1,s2],effortTwo[s1,s2],yNumPreferences[s1,s2][[k]]},{s1,s2}∈Ω,PlotRange->Full,AxesLabel->{"r1","r2","y"},PlotLabel->StringJoin["Preferences: ",allStrategyString[[k]]],BoxRatios->{1,1,1},Mesh->15,MeshStyle->{Blue,Red}]

Here are tools that may be used to study gradient effects. In particular we define the market overhead and average contextual stress along with useful plots.

marketCapitalBoundaryPlot:=Plot3D[marketCapitalOnBoundary[s1,s2],{s1,s2}∈Ω,AxesLabel->Automatic,PlotLabel->"Market Capital on Boundary"]

numAverageContextualStress[s1_,s2_]:=(numScalarϕ1[s1,s2]Tr[one]+numScalarϕ2[s1,s2]Tr[two])/numActiveStrategies
numMarketOverhead[s1_,s2_]:=numMarketBias[s1,s2]/numAverageContextualStress[s1,s2]
numMarketOverheadPlot:=Plot3D[numMarketOverhead[s1,s2],{s1,s2}∈Ω,AxesLabel->Automatic,PlotLabel->"Market Overhead",PlotRange->Full]
numAverageStressPlot:=Plot3D[numAverageContextualStress[s1,s2],{s1,s2}∈Ω,AxesLabel->Automatic,PlotLabel->"Average Contextual Stress",PlotRange->Full]

parametricMarketOverheadPlot:=ParametricPlot3D[{effortOne[s1,s2],effortTwo[s1,s2],numMarketOverhead[s1,s2]},{s1,s2}∈Ω,PlotRange->Full,AxesLabel->{"r1","r2","α"},PlotLabel->"Market Overhead",BoxRatios->{1,1,1},Mesh->15,MeshStyle->{Blue,Red}]

parametricAverageStressPlot:=ParametricPlot3D[{effortOne[s1,s2],effortTwo[s1,s2],numAverageContextualStress[s1,s2]},{s1,s2}∈Ω,PlotRange->Full,AxesLabel->{"r1","r2","α"},PlotLabel->"Average Stress",BoxRatios->{1,1,1},Mesh->15,MeshStyle->{Blue,Red}]

To make the discussions uniform, it is useful to define peak focus and periodic focus functions. We note that a valley focus function is the negative of the peak focus function. Use of these functions is certainly optional in practice.

contextualPeak[x_]:=Exp[-x^2]-1

contextualPeriodic[x_]:=Cos[Pi x]-1

In picking non-entitlement flows, it is convenient to have a (k^th) strategy chooser.

kthStrategyOne[k_]:=Join[Table[0,{j,numberColumns@gameMatrix}],Table[If[j==k,1,0],{j,numberRows@gameMatrix}],{0}]
kthStrategyTwo[k_]:=Join[Table[If[j==k,1,0],{j,numberColumns@gameMatrix}],Table[0,{j,numberRows@gameMatrix}],{0}]

For seasonal variations that are consistent with our assumptions on external time dependent forces, we use the following definitions.

seasonalPayoffConstant:=0
seasonalGameMatrix:=unitValue[gameMatrix] seasonalPayoffConstant/Sqrt[Tr[one]Tr[two]]

To better visualize the owner streams for each player, we compute the player streams based on the first two strategies of each player.

playerStreamlinePlots:=Row@{ParametricPlot3D[Evaluate@{yNumPreferences[s1,s2][[3]],yNumPreferences[s1,s2][[4]],s2},{s1,s2}∈Ω,PlotRange->Full,AxesLabel->{"y3","y4","s2"},PlotLabel->"Player One Streamlines",BoxRatios->{1,1,1},Mesh->15,MeshStyle->{Blue,Red}],ParametricPlot3D[Evaluate@{yNumPreferences[s1,s2][[3]],yNumPreferences[s1,s2][[4]],s1},{s1,s2}∈Ω,PlotRange->Full,AxesLabel->{"y1","y2","S1"},PlotLabel->"Player Two Streamlines",BoxRatios->{1,1,1},Mesh->15,MeshStyle->{Blue,Red},PlotLegends->LineLegend[{Blue,Red},{s1,s2}]]}

flowStreamPlot:=ParametricPlot[Evaluate@{streamOne[s1,s2]/Tr[one],streamTwo[s1,s2]/Tr[two]},{s1,s2}∈Ω,Mesh->10,MeshStyle->{{Blue,Thick},{Red,Thick}},FrameLabel->{"Vr1","Vr2"},PlotLabel->"Flow Stream Contours",ImageSize->Medium,BaseStyle->{FontWeight->"Bold"},PlotStyle->Yellow,PlotLegends->LineLegend[{Blue,Red},{s1,s2}]]

18.1.11 | Useful Short-List of Game Interactions

As examples of the games we have in mind, we take from our previous chapters our list of sample games.

rspGame:={{0,1,-1},{-1,0,1},{1,-1,0}}

rspNZSGame:={{0,2,-1},{-1,0,1},{1,-1,0}}

baseGame:={{7,1,3,0,2},{0,1,6,4,2},{1,2,0,5,5}}

morra:={{0,2,2,-3,0,0,-4,0,0},{-2,0,0,0,3,3,-4,0,0},{-2,0,0,-3,0,0,0,4,4},{3,0,3,0,-4,0,0,-5,0},{0,-3,0,4,0,4,0,-5,0},{0,-3,0,0,-4,0,5,0,5},{4,4,0,0,0,-5,0,0,-6},{0,0,-4,5,5,0,0,0,-6},{0,0,-4,0,0,-5,6,6,0}}

theDate:={{1/3,0,-(1/3)},{0,2/3,1/3},{1/3,-(1/3),1}}

colonelBlotto:={{4,2,1,0},{1,3,0,-1},{-2,2,2,-2},{-1,0,3,1},{0,1,2,4}}

catMouse:={{0,0,0,1,0,0,0,1},{0,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,0},{1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1},{0,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,0},{1,0,0,0,1,0,0,0}}

prisonersDilemma:={{-(1/10),-1},{0,-(9/10)}}

chicken1:={{-10,1},{-1,0}} (* row labels are "crash" and "swerve" *)
chicken2:=-Transpose[chicken1]

econChicken1:= {{0,4},{1,3}} (* row labels are "crash" and "swerve" *)
econChicken2:=-Transpose[econChicken1]

hornsGame:={{0,2,2,0,0,0,0,0,0},{0,0,0,0,3,3,0,0,0},{0,0,0,0,0,0,0,4,4},{3,0,3,0,0,0,0,0,0},{0,0,0,4,0,4,0,0,0},{0,0,0,0,0,0,5,0,5},{4,4,0,0,0,0,0,0,0},{0,0,0,5,5,0,0,0,0},{0,0,0,0,0,0,6,6,0}}

attackDefenseBlue:={{4,1},{3,4}}
attackDefenseRed:=attackDefenseBlue

drinkingGame:= {{55,10},{10,110}}

stagHare:={{3,0},{2,1}} (* row labels are "stag" and "hare" *)

tragedyOfCommons:={{100, 70}, {140, 80}} (*fishing example, 1 fish, 2 fish options *)

ticTacToeGame:={{0,1,0,1,0,1,0,1,0},{0,0,0,1,1,0,1,1,0},{0,1,0,1,1,1,1,1,1},{0,1,0,0,0,1,1,0,1},{0,1,1,1,0,1,1,1,1},{0,0,1,1,0,0,0,1,1},{0,1,1,1,1,1,0,1,1},{0,1,1,0,1,1,0,0,0},{0,1,1,1,1,1,1,1,0}}
ticTacToeSubGame[num_] := ticTacToeGame[[1 ;; num]]

flipChicken1:=-Transpose@econChicken1+4   (* row labels are "crash" and "swerve" *)
flipChicken2:=-Transpose@flipChicken1   (* row labels are "crash" and "swerve" *)

pureEffortGame[n_]:=Table[1,{j,n},{k,n}]

voterGame:={{1}}

Cultural Transaction Model (the tic tac toe game)

WolframAlpha["Tic Tac Toe"]

We convert the game of moves in tic-tac-toe to 9 intrinsic strategies for X and 9 intrinsic strategies for O.

This can be further simplified: X, who moves first has only three distinguishable choices

O, who moves second, has 9 choices

Game Transactions

We identify three distinct parts of game interactions: player payoffs, the seasonal payoffs and utility scalars. The player payoffs (and the player valuations) are determined in part based on standard game theory analysis. The seasonal payoffs and utility scalars are aspects of the frame of reference, and may be present whenever we can establish frame dependent phenomena. We examine these possibilities below for the game tic-tac-toe. An essential part of our approach is that these various scalars and payoffs are fields that vary over time and over the space of intrinsic choices. The analysis thus uses classic PDEs, which because of the payoffs, are convective in nature.

18.3.1 | Player Payoffs

We start with a standard formulation of the game in terms of the instrinsic strategies.the game interaction consists of the decision process theory games for each player. The resultant streamlines in time form a useful comparison with the owner streams we shall compute later, which include the cultural constraints and vary over both space and time.

Clear[gameMatrix]
playerIncentive=-1/50
MatrixForm@ticTacToeSubGame[3]
gameMatrix=8ticTacToeSubGame[3]/10+playerIncentive
MatrixForm[gameMatrix1=gameMatrix]
MatrixForm[gameMatrix2=gameMatrix]
strategyString1={"X1","X2","X3"}
strategyString2={"O1","O2","O3","O4","O5","O6","O7","O8","O9"}
e1=-1/2
e2=-1/2
valueScale=20
sMax=20
disruptiveFlow=First@NullSpace@compositePayoff+ {0,1,0,0,1/10,1/10,0,1/10,1/10,1,0,0,0}/valueScale
ySolution[s_]=NDSolveValue[Join[flowEquations,boundaryEquations],var,{s,0,sMax},MaxSteps->Infinity]
flowPlot

For streamlines, we obtain linear, harmonic contributions or exponential contributions depending on the eigenvalues of the composite payoff.

Eigenvalues[compositePayoff.metric]//N

The behavior changes if we add a constant to the game matrix. For this talk we have taken the incentive to be one.

MatrixForm[gameMatrix=8ticTacToeSubGame[3]/10+playerIncentive]

With these considerations we have identified the player payoffs and the corresponding entitlement flows, which are the corresponding null space vectors of the player payoffs.

entitlementFlow1:=First@NullSpace@dptGame[gameMatrix1,valueScale]
entitlementFlow2:=First@NullSpace@dptGame[gameMatrix2,valueScale]
MatrixForm[dptPayoff1]
entitlementFlow1
MatrixForm[dptPayoff2]
entitlementFlow2

As expected, we see the ideal choices. It is interesting to note that the composite payoff has several equilibria as do the individual player payoffs.

NullSpace@compositePayoff
NullSpace@dptGame[gameMatrix1,valueScale]
NullSpace@dptGame[gameMatrix2,valueScale]

MatrixForm@compositePayoff

18.3.2 | Harmonic Mesh Region

To include the spatial variations, we express our seasonal payoffs and utility scalars in terms of the underlying region for the player efforts (Subscript[r, J]). For time dependent disruptions, we need to specify this region: we work in the following harmonic mesh region.

size:=sMax
harmonicSize:=0.1 size/3
harmonicBoundaryFunction[r1_,r2_]:=1.0
harmonicMesh:=harmonicSize^2/1000
minHarmonicr1:=-0.2Sqrt[Tr[one]]harmonicSize
minHarmonicr2:=-0Sqrt[Tr[two]]harmonicSize
maxHarmonicr1:=Sqrt[Tr[one]]harmonicSize
maxHarmonicr2:=Sqrt[Tr[two]]harmonicSize
middleHarmonicr1:=(maxHarmonicr1+minHarmonicr1)/2
middleHarmonicr2:=(maxHarmonicr2+minHarmonicr2)/2
Ω1Harmonic:=Rectangle[{minHarmonicr1,minHarmonicr2},{maxHarmonicr1,maxHarmonicr2}]
ΩHarmonic:=ToElementMesh[Ω1Harmonic,MaxCellMeasure->harmonicMesh]
ΩHarmonic["Wireframe"]

We transform this region to conform to the harmonic wave equation we utilize for time dependent disruptions. Because the definitions of the harmonic variables (Subscript[(OverBar[r]), J])=(Sqrt[(Subscript[n, J])]) are scaled by the number of strategies, a rectangular mesh of size harmonicSize is scaled accordingly. We use here an initial estimate based on what we have observed in our previous examples; this number may be changed as needed.

18.3.3 | Seasonal Payoffs (Subscript[f, υυ'])

Given our current understanding of the game of tic-tac-toe, there are no obvious seasonal effects, so in this talk, we take the default of zero seasonal payoff.

seasonalPayoffConstant:=.0
seasonalGameMatrix:=unitValue[gameMatrix] seasonalPayoffConstant/Sqrt[Tr[one]Tr[two]]
MatrixForm@seasonalGameMatrix
MatrixForm@seasonalInputPayoff

Of course, with a little thought, it might occur to us how such seasonal effectrs might exist.

18.3.4 | Utility Scalars ν, Φ, Θ, and Reduced Metric (Subscript[(OverTilde[γ]), jk])

For the  game of tic-tac-toe, we see no obvious time or space compressions, so in this talk we set these to zero.

νInput[r1_,r2_]:=-0(Cos[5Pi(r1-r2)/harmonicSize]+1.)/(5Pi)^2
Plot3D[ νInput[r1,r2],{r1,r2}∈ΩHarmonic,AxesLabel->Automatic,PlotLabel->"νInput(r1,r2)",PlotRange->Full]

There are no additional scalar effects that are immediately apparent, so the default values for the scalar fields are determined.

gaugeνR[r1_,r2_]:=νInput[r1,r2]
scalarP[pref_]:=Evaluate[gaugeνR[r1,r2]/.rToPref]
gaugeν[s1_,s2_]=scalar[s1,s2]
gradientGaugeν[s1_,s2_]=gradientScalar[s1,s2]
gaugeΦR[r1_,r2_]:=0(r1-r2)/harmonicSize
scalarP[pref_]:=Evaluate[gaugeΦR[r1,r2]/.rToPref]
gaugeΦ[s1_,s2_]=scalar[s1,s2]
gradientGaugeΦ[s1_,s2_]=gradientScalar[s1,s2]
inputInactiveMetric:={{-1,0},{0,-1}}
MatrixForm@reducedInactiveMetric
{ΘBase,σBase,StringJoin[ToString[θBase/Degree],"∘"]}
gradientGaugeΘ[s1,s2]

Cultural Constraints (boundary conditions etc.)

We get a snapshot view of the player payoff contribution by looking at their streamline behaviors. The player flows are harmonic, so we expect harmonic behavior in the player flow correlations. The effort for each player grows, so we expect this growth in the player effort correlation.

sTemp=sMax
sMax=10sTemp;
ySolution[s_]=NDSolveValue[Join[flowEquations,boundaryEquations],var,{s,0,sMax},MaxSteps->Infinity];
Row@{ParametricPlot[Evaluate@{Tr[flowSolution[s].one]/Tr[one],Tr[flowSolution[s].two]/Tr[two]},{s,0,sMax},AxesLabel->{"Vr1","Vr2"},PlotLabel->"Player Flow Correlation",ImageSize->Automatic,BaseStyle->{FontWeight->"Bold"},PlotStyle->Blue],ParametricPlot[Evaluate@{Tr[ySolution[s].one]/Tr[one],Tr[ySolution[s].two]/Tr[two]},{s,0,sMax},AxesLabel->{"r1","r2"},PlotLabel->"Player Effort Correlation",ImageSize->Automatic,BaseStyle->{FontWeight->"Bold"},PlotStyle->Blue]}
sMax=sTemp;

We set the mesh region for the owner streams, which is then used to solve the two-dimensional PDEs associated with the conservation laws. If we had three players, we would need to extend our results to allow three-dimensional PDEs. Next we address the boundary conditions for the inertial constraints (Subscript[μV, μ])(Subscript[V, ν]), consisting of the time eigenvectors (Subscript[V, μ])  and the time eigenvalue μ of the cultural constraint (Subscript[T, μν])=(Subscript[μV, μ])(Subscript[V, ν])+(Subscript[p, μν]). We then address the boundary conditions for the contextual constraints (Subscript[p, μν]), which in the player ownership model are set by the contextual scalars (Subscript[ϕ, J]).

Each of the inertial constraint factors in (Subscript[μV, μ])(Subscript[V, ν]) are dynamic. These reflect cultural constraints because we must pick boundary values for each of these; the boundary values result from processes outside of our region of interest. Nevertheless, their values determine key properties of the solution. Therefore, we pay attention to what these initial values might represent.

Similarly, the contextual scalars, though not dynamic, again represent properties of processes outside our region of interest. So we pay attention to what these scalars represent.

18.4.1 | Player Owner Streams and Mesh Region

A natural aspect of our approach is to consider the player streamlines: the streamlines for each player in their subspace. These are the integral stream curves (Subscript[s, J]).  They provide a two-dimensional picture that allows us to see more clearly any convection effects generated by the new dynamics. We maintain the practical advantage that streamlines have: the dimension of the plots does not go up if we increase the number of strategies of a player.

For the tic-tac-toe decision process, we have a 12-dimensional space. For a first approach to such processes, we believe it is insightful  to solve the PDEs using some notion of streamlines. To extract useful information about the player ownership, we go beyond the idea of streamlines to owner streams (Subscript[s, J]). For systems with only two players, the PDEs will be of dimension-2 for all models. We envision that this could be extended to three person games, which would be PDEs of dimension-3, again for all models.

To get the owner streams for two players, we impose the condition that the boundary be a square Ω, with a size set by sMax. To smooth the solutions of the PDE, we use three small parameters, ϵU, ϵV and ϵY as discussed in Chaps. 10-11. What we have found in practice is that when it appears that we have to change these parameters, it is probably because the convection effects are too strong; we have found that a better alternative is to back away from that choice of parameters, since what we may be seeing is the onset of chaotic behavior.

mesh:=size^2/500
Ω1:=Rectangle[{0,0},{size,size}]
Ω:=ToElementMesh[Ω1,MaxCellMeasure->mesh]
Ω["Wireframe"]
ϵU:=10^-10
ϵV:=10^-10
ϵY:=10^-10

18.4.2 | Inactive Flow Boundary Conditions

The boundary condition for the inactive flow determines the strength of the acceleration generated by the corresponding player payoff. It is set outside of the region of interest. Each player acts as if this information were known to them (Chap. 3). The inactive flows (Subscript[V, k]) are the player engagements (Subscript[e, k]). Our current default values are set by the Gradient Valuation Law, where we pick the engagements to be equal. For non-zero-sum games, we choose equal and opposite in sign.

For zero-sum games such as tic-tac-toe, we choose equal values and equal signs.

We now consider what might happen if we move away from the default values. Even if we keep these VGL choices, we have the option to include non-VGL effects as well. We start with the VGL boundary conditions we have used these before and adopt them with the following choices for the inactive ranges.

vglModel[s1_,s2_,range_]:=0.75 Tanh[ (s1-s2)/range]
inactiveRangeOne:=sMax/2
inactiveRangeTwo:=sMax/2
nonVGLModelOne[s1_,s2_]:=0
nonVGLModelTwo[s1_,s2_]:=0

Plot3D[vglModel[s1,s2,sMax/2],{s1,s2}∈Ω]

The ranges are such that for large owner stream values (Subscript[s, J]) the VGL model function above becomes 1.

Since the boundary conditions are the sum of the VGL and nonVGL contributions, we consider each contribution in turn, starting with the VGL contribution.

boundaryInactiveOwnerFlows[s1,s2]

The VGL model reflects the flows we might expect from the player valuations based on a full solution to the equations. Since the full solution closes the loop, we note that the full solution considers it is equally useful to consider the flows as generating the player valuations. Modest changes to the inactive flow boundary conditions might make only negligible changes to the player valuations and so might be considered.

In the full theory, some boundary condition changes make no changes to the player valuations. In particular, adding a constant amount, the static player engagement, on the boundary will not change the field inside. We have seen that a constant generates a non-zero composite payoff, so we expect this to make a difference in the neutral payoff. We choose trial values for the static player engagements.

nonVGLModelOne[s1_,s2_]:=0.25 e1
nonVGLModelTwo[s1_,s2_]:=0.25 e2 
boundaryInactiveOwnerFlows[s1,s2]

We envision two distinct engagement contributions: the static player engagement above and the dynamic player engagement generated from VGL. The relative size of these effects determine the neutral behavior.

18.4.3 | Active Flow Boundary Conditions

The active strategy flow tracks how we make decisions, so the boundary conditions reflect how we constrain such decisions based on processes outside of our region of interest. Our default boundary conditions included a more general framework that consisted of entitlement flows and non-entitlement flows.

entitlementFlow1:=0First@NullSpace@dptGame[gameMatrix1,valueScale]
entitlementFlow2:=0First@NullSpace@dptGame[gameMatrix2,valueScale]
nonEntitlementFlow1[s1_,s2_]:=Table[0,{k,numActiveStrategies+1}]
nonEntitlementFlow2[s1_,s2_]:=Table[0,{k,numActiveStrategies+1}]
entitlementFlow1
entitlementFlow2
nonEntitlementFlow1[s1,s2]
nonEntitlementFlow2[s1,s2]

The boundary conditions are determined by the sum of the entitlement flow and non-entitlement flow contributions. Our default values reflect our starting point that the boundary reflects choices a player picks based on their internal view of the decision process. The entitlement flows are in the null space of their decision process payoff matrix and represent a rational approach.

However, we also allow for non-rational behavior. We start out with zero.

nonEntitlementFlow1[s1_,s2_]:=Table[If[k==10||k==11||k==12,1/(3valueScale),0],{k,numActiveStrategies+1}]+Diagonal[time]
nonEntitlementFlow2[s1_,s2_]:=Table[If[k<=9,k/(90valueScale)+1/(9valueScale),0],{k,numActiveStrategies+1}]+Diagonal[time]
nonEntitlementFlow1[s1,s2]
nonEntitlementFlow2[s1,s2]

In setting the value, we compare with the entitlement values and construct a model based on how we view the relative strength of the rational versus the irrational behavior.

18.4.4 | Market  Bias μ

Our initial default values for the market overhead was based on an assumption that the market bias and the contextual scalars were constant for each player and so the ratio α, the market overhead, was also constant. The dynamic equations are independent of whatever scale we pick for the average contextual scalar. So, we assume it is unity and the market overhead and market bias are the same. A high market overhead means that the inertial constraints dominate; a low market overhead means that the contextual constraints dominate. Our initial default values are somewhere in between.

baseMarketOverhead:=4
marketCapitalOnBoundary[s1_,s2_]:=baseMarketCapital

Why would we pick something other than default values? The market bias measures where we expect the player efforts to peak. For each player, the contextual scalar indicates the importance of ownership. In both cases, these scalars may deviate from being constant.

We discuss the market bias first, assuming constants for the contextual scalars. The default value indicates that both inertial and ownership are comparable and the inertial is spread equally over the player preferences: all efforts are equally probable.

There might be market disruptions in which the play varies as player effort increases. We have settled on a market focus on the boundary that favors equal player efforts on the main diagonal, (Subscript[s, 1])=(Subscript[s, 2]).

marketDisruption[x_]:=0.5 Cos[5Pi x]Log[1.05]
marketCapitalOnBoundary[s1_,s2_]:=Log[baseMarketOverhead]+marketDisruption[(s1-s2)/size]
Plot[marketDisruption[x],{x,-1,1}]

As a consequence, away from the main diagonal, we will have less market overhead and so player ownership will be stronger.

This argument seems plausible for the game of chicken. When player efforts are disparate, one player is governed more by their sense of ownership and hence by the effects of the contextual tensor (Subscript[p, μν]), which is set by the contextual scalar (Subscript[ϕ, J]). On the diagonal, what matters more will be the inertial behavior as determined by the payoffs and frame dependencies set by the compression scalars.

18.4.5 | Contextual Scalars

The concept of player ownership is not part of the active geometry we are focused on in the decision process. It is nevertheless a key part of decisions. We believe it is not a symmetry of the metric but a constraint that reflects a dynamic symmetry of how decisions are made. Each player believes that they own a set choices which are isotropic: no choice is preferred over the other in a frame in which all active and inactive flows are zero.

If player ownership is small, we then have only the inertial constraints that we have already considered: the paths are geodesics based on the geometry of the utility metric. The geodesics are computed based on the frame of reference, which we model with the utility scalars ν, Φ, Θ, and the seasonal vector potentials (Subscript[a, υ]). Furthermore, we influence the behaviors by our initial conditions on the market bias μ along with the inactive and active flows (Subscript[V, k]) and (V^υ) respectively.

If player ownership is not small, we have a more complicated version of the perfect fluid in the study of fluids. In fluids, the perfect fluid reflects a dynamic symmetry in the sense that in the rest frame, the fluid stresses are isotropic. We have taken the same idea for decisions and argued that whatever contextual stresses exist that might influence decisions, they are isotropic in the appropriate frame (Chap. 4).

Just as in perfect fluids, there are parameters, the contextual scalar stresses (Subscript[ϕ, J]), which we can choose as model builders. These might be constants or functions of the preferences. If we limit the functionality to only the player efforts, we still have many possibilities. We might have a peak function for each scalar.

We choose the scale to be consistent with the way we have set the constant value; we imagine the maximum to be at the origin and set below by our baseContextualStress. The sign of the gradient makes a difference in the amount of convection and the convergence.

contextualFractionOne:=1/3
contextualFractionTwo:=2/3
gaugeϕ1[r1_,r2_]:=baseContextualStressOne  (1- 0.0Sin[5Pi r1/harmonicSize])
scalarP[pref_]:=Evaluate[gaugeϕ1[r1,r2]/.rToPref]
scalarϕ1[s1_,s2_]=scalar[s1,s2]
gradientScalarϕ1[s1_,s2_]=gradientScalar[s1,s2]
gaugeϕ2[r1_,r2_]:=baseContextualStressTwo  (1- 0.0Sin[5Pi r2/harmonicSize])
scalarP[pref_]:=Evaluate[gaugeϕ2[r1,r2]/.rToPref]
scalarϕ2[s1_,s2_]=scalar[s1,s2]
gradientScalarϕ2[s1_,s2_]=gradientScalar[s1,s2]

Away from the origin, the contextual stress would become smaller in value. Our initial thought is to assume the scalars are functions of the relative efforts. So, along the main diagonal, the stresses will be specified by our parameters and the relative weight between inertial and contextual is set by the market overhead parameter. Far from the diagonal, the contextual stresses would be smaller and therefore inertial effects might be relatively bigger.

It should be emphasized that our goal here is to explore the consequences of these model choices an how they might be reflect in the data. Our goal here is to build a model that is fairly complete in that it has multiple aspects which interact non-linearly.

Some Q & A (the toolkit, Chap. 2)

Why are the flows positive and negative and how do they relate to game theory strategies?

The resultant flows we identify are an extension of the strategies used in game theory. Here, they are not normalized. They can also be positive or negative. They generate the strategic preferences (y^a), which we interpret as related to the effort (x^( a)) to carry out a particular strategy: (y^a)=ln (x^( a)). This identification gives specific meaning to positive and negative preferences as well as positive and negative flows. Decisions are made as the result of actions that require effort, which we consider to be positive.

When Is gameMatrix2=-Transpose@gameMatrix?

Not always, as this choice does not always make sense. However, for games such as the prisoner’s dilemma, we assume that each player plays the same strategy and so from their viewpoint, sees the same game. We write the game matrix from the perspective of player 1, who sees the negative of the utilities as seen by player 2 and whose row strategies will be player 2’s column strategies.

For zero-sum games, the two player matrices should be the same, so the above is not true.

Is there a maximum speed for information flow?

Yes, we may call this the utility speed. As an example, consider a unit of biologic speed, the Eye-Blink:    For the sake of discussion,  take 1 Eye-Blink to be ⅓ second. As an alternate think of the value 1 person has per hour. We might use as a basis, the software development value (say) of $100/hour. Comparing the two, this implies one Eye-Blink is valued at 1 cent.

What units do we use to measure value?

We start with a unit of time, be it a day, a week or a generation. We then use the utility speed above, which is the maximum value that might be obtained in one unit of time: this is the maximum rate generation or flow possible. We take the units such that this is one. Thus if the time interval were one year, the total effort might by 100 staff-years. This would be 1 unit. The actual value obtained in 1 time interval would be a fraction of this of magnitude less than 1. An actual decision process would be expressed in these units.

Since we depart from game theory, how do we determine the actual value of a game?

The elements of the game matrix determine both the game value and the harmonic scale(s). If we disrupt the system, we can measure the harmonic scale and hence infer the size of the game matrix elements. We measure when a known value is created after one period. An example would be a software project during the testing cycle. After each iteration, one determines the value of the product based on the percentage of tests passed. This interval might be, for example, 6 months. This gives us the time.

How do we determine the valueScale?

Using the previous example, the valueScale is determined by how many iterations are needed to get the desired value, say 95% pass rate. If there are many defects, this might take 4 passes, if the first pass rate was 50%.  The valueScale in this case would be 4. Note that we have set the valueScale to be the same for each player purely for convenience. In general, there will be a valueScale for each player. Thus each player may view different iterations for themselves and other players; moreover these views may be seen as different for each player.

How are the payoff fields related to the harmonic and value scales?

The underlying theory says that the rate of change of the flow is determined by an equation that is similar to that in physics for a charged particle in an electromagnetic field: (Subscript[(OverDot[V]), m])=(Subscript[e, k])(Subscript[(F^k), mn])(V^n)+(Subscript[e, k])(Subscript[(F^k), mο]). The first term generates rotations based on the spatial components of the payoff field. The second term is a gradient field, which is determined by the ratio of the game value and the valueScale: (v/valueScale).

Tic-Tac-Toe using the toolkit, Chap. 18

Solutions and Basic Analysis

With our initializations and models that include the appropriate boundary conditions,  we solve the PDEs and display their baseline behaviors that we  use to compare.

18.5.1 | Solutions

We use NDSolve to obtain the solutions for the ownership model.

ownershipStreamlines[s1_,s2_]=NDSolveValue[{pdeEquations[s1,s2],DirichletCondition[totalOwnershipBoundaryEquations,s1==0||s2==0]},variableList[s1,s2],{s1,s2}∈Ω,MaxSteps-> ∞];

The solution obtained is in the form of a list, ownershipStreamlines[s1,s2], from which we extract the specific functions that relate to the preferences, flows and gradients.

Manipulate[MatrixForm@Chop@{yNumPreferences[s1,s2],numActiveUpperFlows[s1,s2],numInactiveLowerFlows[s1,s2],ds1yNumPreferences[s1,s2],ds2yNumPreferences[s1,s2]},{s1,0,size},{s2,0,size}]

We check our solution against the path length deviation. Within the numerical accuracy of the solution, including our treatment of convective PDE, it should be zero.

pathLengthDeviationPlot

We do the check, since for sufficiently complicated models, we may lose accuracy

For time dependent harmonic solutions, it is efficient to evaluate the numerical values of the harmonic preferences using Evaluate. We do different cases by setting the frequency and evaluating numHarmonicScalar. Here is an example.

ωSample:=1.0
numHarmonicScalar[rBar1_,rBar2_]=harmonicScalar[w][ωSample];

As with owner streams above, when we need to compute the harmonic preferences and their derivatives for any other numerical value of the frequency, we update numHarmonicScalar.

As part of our basic analysis, we look at the owner stream for the time component (y^ο)(s,s) along the diagonal and the streamline from Sec. 18.3 and see that they are almost identical, which is a consistency check on our approach.

Plot[{yNumPreferences[s,s][[-1]],ySolution[s][[-1]]},{s,0,sMax},PlotLegends->{"Owner Streams","Streamline"},PlotStyle->{Solid,Dashed},ImageSize->Medium,AxesLabel->{"s",Automatic}]

18.5.2 | Basic Analysis: Owner Streams

In Secs. 18.2-18.4 we defined the model. We now check basic attributes to confirm our expectations for the model based on a sensitivity analysis of the model.

In checking the attributes, note that the results for the various flows and preferences are in terms of the integral stream efforts (Subscript[s, J]), which are expressed in terms of the player efforts (Subscript[r, J])=(∑_(υ∈o[J]))(y^υ). We visualize this relationship by plotting the integral streams parametrically against the player efforts.

The streamlines in fluids because we can envision them as smoke trails; the smoke follows the streams. We do the same thing with player ownership by looking at the player subspace and envision we track the progress of the player preference along the stream. For blue, the player one streamline is the progress of two preferences (y^10) and (y^11) as we change the owner stream (Subscript[s, 1]).

playerStreamlinePlots

We do this for different values of red’s stream (Subscript[s, 2]). We do the similar plot for the player stream for red. For tic-tac-toe, we plot the first two strategies. When we restrict to the player subspace, the player streams give qualitative insight similar to streamlines in fluids. In this case, we see that the streams represent a flow consistent with our past observations of payoff convection.

We have used the integral stream plots as a way to see the convection for any two player game.

integralStreams

By now, we expect to see evidence of payoff convection, which is a circular motion or the start of same. In flow equations, one associates circular motion with the convection that occurs due to heat. For this reason we have named the phenomena here similarly.

18.5.3 | Basic Analysis: Stream Correlations

Another plot that we have found useful when doing sensitivity analysis, is the effort stream correlation plot, since parameter changes often make distinctive changes here.

effortStreamPlot

We see two distinctive effects. We have static player engagements with the nonVGL boundary conditions. We have further impacted the payoff convection with our non-entitlement flows in which both players choose each strategy equally.

Another insightful correlation plot is the owner stream plot, which plots the vector flow in the integral owner stream space. When the forces are strong enough, it shows vortices.

ownerStreamPlot

We see the start of vortex type motion. We also see that the flow is no longer along the diagonal. If we can plot the empirical version of this plot, we would hope to learn something about the possible underlying dynamics.

A different perspective of this phenomenon is the flow stream correlation plot.

flowStreamPlot

We compare this to the plots for streamlines, here restricted to the current value of sMax. We see that the owner stream behavior is much more complex. Part of the complexity we ascribe to the presence of contextual scalars, which blur the streamlines.

Row@{ParametricPlot[Evaluate@{Tr[flowSolution[s].one]/Tr[one],Tr[flowSolution[s].two]/Tr[two]},{s,0,sMax},AxesLabel->{"Vr1","Vr2"},PlotLabel->"Player Flow Correlation",ImageSize->Automatic,BaseStyle->{FontWeight->"Bold"},PlotStyle->Blue],ParametricPlot[Evaluate@{Tr[ySolution[s].one]/Tr[one],Tr[ySolution[s].two]/Tr[two]},{s,0,sMax},AxesLabel->{"r1","r2"},PlotLabel->"Player Effort Correlation",ImageSize->Automatic,BaseStyle->{FontWeight->"Bold"},PlotStyle->Blue]}

18.5.4 | Basic Analysis: Market Bias and Inactive Flows

Though we have a more direct understanding of the effect in terms of the player efforts  (Subscript[r, J]), it is also useful to plot variables using integral owner streams  (Subscript[s, J]). If we suspect strong payoff convection effects we can always  return to parametric plots of the player efforts. We do this for the market bias, inactive flows and active flows.

Let’s start with the market bias/market capital and inactive owner streams, which now include all sources.

Row@{marketBiasPlot,numAverageStressPlot}
covariantInactiveFlowPlots

The market bias has a locked behavior along the diagonal, which is a consequence of the boundary condition we imposed.

18.5.5 | Basic Analysis: Neutral Behavior

The neutral behavior is a generalization of the Nash equilibrium to dynamics. We see in this plot the result of our assumptions about the relative strengths of the static player engagements and the dynamic player engagements. For “O”, there are no forces to change O1 or O3: these are equilibrium choices. The other strategies for “O” do oscillate with relatively large amplitudes, somewhat masking the equilibrium choices. For “X”, we see that X3 becomes the winner, with oscillation forces for the other two strategies generated by the non equilibrium values.

neutralBehaviorPlot

18.5.6 | Basic Analysis: Active Owner Flow

The active flow owner stream variations show structure when plotted against the integral owner streams (Subscript[s, 1]) and (Subscript[s, 2]). We see the increased structure due to our addition of a static player engagement contribution.

contravariantActiveFlowPlots

18.5.7 | Basic Analysis: Active Preferences

The owner stream view of the active ownership preferences tells a related story.

ownershipPreferencePlots

18.5.8 | Basic Analysis: Contextual Scalars

We currently have no gradient contribution to the contextual scalars.

contextualScalarPlot

Interacting Mechanisms

We look at a number of different plots that go above and beyond the basic analysis to study the impacts of the various possible interacting mechanisms.

The market bias and average stress parametric plots illustrate the interaction of the inertial and contextual constraints.

(*Row@{parametricMarketBiasPlot,parametricAverageStressPlot}*)

The interacting dynamics change the market bias. We see that away from the diagonal, we go to a flat but not symmetric value for the market bias.The market overhead matches the bias since we have added only small gradient changes to the contextual scalars.

The inactive plots also exhibit small changes, which are enhanced by looking at the sum and difference plots as well as the inactive stream plot.

sumAndDifferenceCovariantInactiveFlowPlots
inactiveStreamPlot

It appears that the inactive flows have structure near the diagonal, which is no longer along (Subscript[s, 1])=(Subscript[s, 2]). We see this behavior in more detail using Manipulate for the behaviors along constant u=(Subscript[s, 1])-(Subscript[s, 2]). This is similar to the result we would expect for the market bias μ along the streamline.

inactiveFlowPlot

The plot illustrates a conservation law that holds for the inactive flows and shows that different values of (Subscript[s, 1])-(Subscript[s, 2]) may yield different values for the inactive flows. The scale will be set by the player engagements, which determine the boundary condition based on the static and dynamic player engagements.

The active strategy behaviors along the diagonals, u=(Subscript[s, 1])-(Subscript[s, 2]), indicate the interaction between the static and dynamic player engagements. We clearly see that along the main diagonal (u=(Subscript[s, 1])-(Subscript[s, 2])=0), we get the neutral behavior that is not the same as the streamline solutions in Sec. 18.3.1 based on the composite payoff.

activeStrategyPlot

We have picked up some of the composite payoff effect with the dynamic player engagement contribution. As we move away from the diagonal, we get behaviors similar to the streamline from the composite payoff.

The parametric version of the active flows as functions of the player efforts tells the complimentary story.

(*Row@Table[parametricStrategyFlowPlot[k],{k,numActiveStrategies}]*)

We get a spectrum of behaviors that span what one player thinks is happening to what the other player thinks is happening, including their irrational behaviors on the boundary. We see this in the preference plot as well.

activePreferencePlot

Time Harmonic Solutions

If we disrupt the system at some initial moment in time, that disruption will propagate through the system at the maximum propagation speed (we have used units so that that speed is 1). We analyze the general time disruption as a superposition of harmonic disruptions (the toolkit, Chap. 16). For harmonic disruptions for tic-tac-toe, we have the harmonic preference and flow plots for any sample frequency. Since there are no seasonal payoffs, the imaginary component of the harmonic preference scalar is zero.

ωSample:=2.6
numHarmonicScalar[rBar1_,rBar2_]=harmonicScalar[w][ωSample];
harmonicPreferenceStreamPlot
harmonicFlowPlots
(*harmonicPhasePlot*)

Typical values of the harmonic scalar for different frequencies are given. We recall that the shapes are related to the eigenvectors of the associated Laplacian, which are determined by the size of the region.

harmonicScalarPlot[10]

There will be shape changes and resonance structures in these solutions. 
To see this, we plot the amplitudes as a function of frequency at some “typical” middle values for (Subscript[(OverBar[r]), J]). The resonant shapes we display are not dependent on these middle values.

middleHarmonicr1
middleHarmonicr2
harmonicListFrequencyPlot[5]

To view the time dependence, we make an animation plot. For the player preferences, we do this for a fixed strategy and frequency. Here we assume for simplicity, that the harmonic contributions are the same for every preference.

ωTime:=2.6
vectorAmplitudeP:=.2 Diagonal[one+two]
kStrategy=10;
nTime=50;
numHarmonicScalar[rBar1_,rBar2_]=harmonicScalar[w][ωTime];
harmonicWave[s1_,s2_,t_]=yNumPreferences[s1,s2]+Im[vectorAmplitudeP  harmonicPreferenceStream[s1,s2]Exp[I ωTime t]];
myGraphP=Table[Plot3D[harmonicWave[s1,s2,(i-1) 2Pi/((nTime-1)ωTime)][[kStrategy]],{s1,s2}∈Ω,AxesLabel->Automatic,PlotRange->{Automatic,Automatic,{-3,3}},PlotLabel->StringJoin["preference((Subscript[s, 1]),(Subscript[s, 2]),t=",ToString[(i-1) 2.Pi/((nTime-1)ωTime)],"): ",strategyString[[kStrategy]],", ω= ",ToString[ωTime]],ImageSize->Large],{i,nTime}];
Manipulate[myGraphP[[i]],{{i,1,"time"},1,nTime,1}]

We obtain standing waves that are like heart beats for each preference. The corresponding animations can be done for the strategic flows.

(*ωTime:=2.6
vectorAmplitudeV:=.2 Diagonal[one+two]
kStrategy=3;
nTime=50;
numHarmonicScalar[rBar1_,rBar2_]=harmonicScalar[w][ωTime];
harmonicFlowWave[s1_,s2_,t_]=numActiveUpperFlows[s1,s2]+Re[vectorAmplitudeV (reWHarmonic[s1,s2]+I imWHarmonic[s1,s2])Exp[I ωTime t]];
myGraphV=Table[Plot3D[harmonicFlowWave[s1,s2,(i-1) 2Pi/((nTime-1)ωTime)][[kStrategy]],{s1,s2}∈Ω,AxesLabel->Automatic,PlotRange->{Automatic,Automatic,Automatic},PlotLabel->StringJoin["(V^υ)(((Subscript[s, 1]),(Subscript[s, 2]),t=",ToString[(i-1) 2.Pi/((nTime-1)ωTime)],"): ",strategyString[[kStrategy]],", ω= ",ToString[ωTime]],ImageSize->Large],{i,nTime}];
Manipulate[myGraphV[[i]],{{i,1,"time"},1,nTime,1}]*)

To get a global view of all of the strategy flows, we make an animation of the neutral behaviors. We choose different weights and phases for each strategy direction.

(*ωTime:=2.6
oneComplex:= Table[Exp[I Pi (k-1)/Tr[one]],{k,Tr[one]}]
twoComplex:= Table[Exp[I Pi (k-1)/Tr[two]],{k,Tr[two]}]
vectorAmplitudeNB:=Join[0.025twoComplex,-0.05oneComplex,{0}]
nTime=50;
numHarmonicScalar[rBar1_,rBar2_]=harmonicScalar[w][ωTime];
harmonicFlowWaveNB[s1_,s2_,t_]=numActiveUpperFlows[s1,s2]+Re[vectorAmplitudeNB (reWHarmonic[s1,s2]+I imWHarmonic[s1,s2])Exp[I ωTime t]];
myGraphNeutralBehavior=Table[Plot[Evaluate@harmonicFlowWaveNB[s,s,(i-1) 2Pi/((nTime-1)ωTime)][[1;;-2]],{s,0,size},PlotStyle->allStrategyColors[[1;;-2]],AxesLabel->Automatic,PlotRange->{Automatic,Automatic},PlotLabel->StringJoin["Neutral Behavior Plot: t=",ToString[(i-1) 2.Pi/((nTime-1)ωTime)]," , ω= ",ToString[ωTime]],ImageSize->Medium,PlotLegends->allStrategyString[[1;;-2]]],{i,nTime}];
Manipulate[myGraphNeutralBehavior[[i]],{{i,1,"time"},1,nTime,1}]*)

We expect that time disruptions will tell us a great deal about the “size” of the region as well as the underlying dynamics.

Highlights: Analysis of Tic-Tac-Toe

Effort Streams: conservation laws and payoffs generate convection behaviors: turbulence and “cyclones”

effortStreamPlot

Neutral Behaviors: It is unfounded that with random input, steady-state behaviors will always settle down to the Nash equilibrium, though in this case it appears likely for X but not for O

neutralBehaviorPlot

Animation of a time dependent disruption: external harmonic forces generate standing waves, whose structure reflects the underlying dynamics

Manipulate[myGraphP[[i]],{{i,1,"time"},1,nTime,1}]

Conclusions

The steps here are what we expect a student to do: we have highlighted only a few of these steps

This approach will be trialed in Spring 2020 at MSOE

Basic Ideas from the Decision Process Toolkit

Dynamic Behavior is based on fields and is “Optimal” (uses shortest path concept--generalizes max-min of game theory)

Players/Agents are isometries: part of the geometry, generate payoffs

Steady-State Generalizes Static Behavior (time isometry): it is dynamic

harmonic inputs generate resonances

Strategic Ownership is Cultural: What we own is a constraint set by all the players

Part of the dynamics, an isotropy but not an isometry, the appearance of neutrality, that we have choice

For example, the language framing the available options imposes cultural constraints

What we see is both both cultural and inertial (including payoffs)

We can extrapolate the “here” and “now” into the future over wider reaches of space.