blob: cb68d33f4f1fa60e854e441a162caefa8961ca62 (
plain)
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
|
classdef InformedMinCoeff < handle
% InformedMinCoeff
% Toggles taps based on the available "Error Budget" (Slack).
%
% Logic:
% 1. Calculate Error Limit (half distance between Dlevs).
% 2. Calculate Current Max Error.
% 3. Slack = Limit - Current.
% 4. Turn off smallest taps as long as sum(|Tap| * 0.5) < Slack.
% 5. Wait for LMS to adapt, then repeat.
properties
WaitCycles % How many iterations to wait between updates
IterationCounter % Internal counter
ReloadPeriod
CurrentMask % The currently active mask
MaxInputVal % Worst case input assumption (0.5)
MaxCycleError
end
methods
function obj = InformedMinCoeff(LMSUpdateObj)
obj.IterationCounter = 0;
obj.ReloadPeriod = 5;
obj.MaxInputVal = 0.5;
obj.MaxCycleError = 0;
obj.WaitCycles = obj.ReloadPeriod * LMSUpdateObj.WindowSize;
tapCount = LMSUpdateObj.NumPreTaps + 1 + LMSUpdateObj.NumPostTaps;
obj.CurrentMask = ones(1, tapCount);
end
function mask = GetFFETapsMask(obj, lmsObj)
% Only update logic if adaptation is active
if lmsObj.Adapting == 0
mask = obj.CurrentMask;
return;
end
% Determine Current Max Error (From the latest window)
maxStepError = max(abs(lmsObj.ErrorVec));
if maxStepError > obj.MaxCycleError
obj.MaxCycleError = maxStepError;
end
currentMaxError = obj.MaxCycleError;
obj.IterationCounter = obj.IterationCounter + 1;
if obj.IterationCounter < obj.WaitCycles
mask = obj.CurrentMask;
return;
end
% Error Tolerance = min(distance_between_dlevs) / 2
dlevs = sort([lmsObj.Dlev_m0p5, lmsObj.Dlev_m0p16, lmsObj.Dlev_0p16, lmsObj.Dlev_0p5]);
maxAcceptableError = min(diff(dlevs)) / 2;
slack = maxAcceptableError - currentMaxError;
% Determine Taps to Turn Off
if slack <= 0
% Negative or zero slack: Cannot turn off anything.
% Ideally, we should turn everything ON to recover.
mask = obj.CurrentMask;
else
% Get magnitude of current taps
absTaps = abs(lmsObj.TapWeights);
% Sort taps to find candidates (smallest first)
% We need original indices to create the mask later
[sortedVals, originalIndices] = sort(absTaps, 'ascend');
accumulatedErrorCost = 0;
tapsToDisableIndices = [];
for k = 1:length(sortedVals)
% Calculate worst-case error contribution of this tap
% ErrorDelta = |Coeff * MaxInput|
cost = sortedVals(k) * obj.MaxInputVal;
if (accumulatedErrorCost + cost) < slack
% We can afford to turn this off
accumulatedErrorCost = accumulatedErrorCost + cost;
tapsToDisableIndices(end+1) = originalIndices(k);
else
% Cannot afford any more
break;
end
end
% Create new mask
newMask = ones(size(lmsObj.TapWeights));
newMask(tapsToDisableIndices) = 0;
% Force Main Cursor (Max Tap) to stay ON for safety
[~, maxIdx] = max(absTaps);
newMask(maxIdx) = 1;
obj.CurrentMask = newMask;
end
% Reset Counter and return
obj.MaxCycleError = 0;
obj.IterationCounter = 0;
mask = obj.CurrentMask;
end
end
end
|