-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAgent.m
135 lines (111 loc) · 5.01 KB
/
Agent.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
classdef Agent < handle
% Agent for doing flood experiments
% works with new MemoryModule abstract class
% and MemoryTimeline class
%
% note that Agent constructor must be called with a
% - MemoryModule constructor
% - number of units and number of timesteps passed in
properties (Constant)
baselineAlpha = 0.05; % alpha storage for each pattern in time
baselineNoiseCost = 0.1; % random noise to fill costs so it's not just 0
end
properties
M; % Memory module
T; % ExperientialTimeline (includes past and future)
wHA; % weight matrix from H to A
nU, nT; % units and timesteps
timelineEvents = {};
% ImposeFlood TS alpha cost
% RemindFlood TS floodTS reminderAlpha costDelta
end
methods
function self = Agent(memorymodule_constructor, nU, nT, varargin)
self.M = memorymodule_constructor(nU);
self.M.FLAG_keepTrackOfPatterns = false; % for speed - they are all in the MemoryTimeline anyway
self.T = MemoryTimeline(self.M, 'nT', nT, varargin{:});
self.nU = self.T.nU;
self.nT = self.T.nT;
self.baselineStore();
end
function AddEventToList(self, E)
self.timelineEvents{end+1} = E;
end
function PrintEventList(self)
for iE = 1:length(self.timelineEvents)
disp(self.timelineEvents{iE});
end
end
function baselineStore(self)
fn = sprintf('%s-BaselineStore.mat', self.M.myName);
if ~exist(fn, 'file')
error('Must initialize matrix with stable state');
else
self.M.InitializeMatrix(fn);
self.wHA = self.baselineNoiseCost * randn(1,self.nU) / self.nU;
end
end
% ---
% run timeline
function [A,R,M] = runTimeline(self, varargin)
% A is asset cost at time t
% R is memory of asset cost given recall of M
% M is correlation with old memory
floodTS = 0; % if nonzero, then is number of trial to compare to
process_varargin(varargin);
A = nan(self.nT,1);
R = nan(self.nT,1);
M = nan(self.nT,1);
eventTS = cellfun(@(x) x{2}, self.timelineEvents, 'UniformOutput', true); % get times to act
for iT = 1:self.nT
%if mod(iT,100)==1, fprintf('!'); elseif mod(iT,10)==1, fprintf('.'); end
f = find(iT==eventTS);
if ~isempty(f)
for iF = 1:length(f)
feval(self.timelineEvents{f(iF)}{1}, self.timelineEvents{f(iF)}{2:end});
end
end
P = self.T.GetPattern(iT);
self.M.AddOnePattern(P, self.baselineAlpha);
P0 = self.M.Recall(P);
A(iT) = self.wHA * P0;
if floodTS
[M(iT), R(iT)] = self.TestRecall(iT, floodTS); %#ok<*UNRCH>
end
end
end
% -- events
function ImposeFlood(self, TS, alpha, cost)
% TS = timestamp ("time of the flood")
% alpha = salience
% cost = experienced cost
P = self.T.GetPattern(TS);
self.M.AddOnePattern(P, alpha);
self.wHA = self.wHA + P'.*cost/self.M.nU;
end
function RemindFlood(self, TS, floodTS, alpha, delta) % alpha is change in salience, delta is change in cost
P_recalled = self.RecallFlood(TS, floodTS);
self.M.AddOnePattern(P_recalled, alpha);
rememberedCost = self.wHA * P_recalled;
self.wHA = self.wHA + delta * P_recalled'.*rememberedCost/self.M.nU;
end
function P_recalled = RecallFlood(self, now, then)
P_then = self.T.GetPattern(then);
P_mix = P_then;
P_mix(self.T.martingaleUnits) = zeros(1, self.T.nM);
P_recalled = self.M.Recall(P_mix);
end
function P_recalled = RecallMix(self, now, then)
P_now = self.T.GetPattern(now);
P_then = self.T.GetPattern(then);
P_mix = [P_now(self.T.martingaleUnits); P_then(self.T.featureUnits)];
P_recalled = self.M.Recall(P_mix);
end
function [rememory, recalledCost] = TestRecall(self, now, then)
% recall flood
P_recalled = RecallFlood(self, now, then);
rememory = self.M.PatternSimilarity(P_recalled, self.T.GetPattern(then));
recalledCost = self.wHA * P_recalled;
end
end
end