summaryrefslogtreecommitdiff
path: root/TapTogglingAlgos/InformedMinCoeff.m
diff options
context:
space:
mode:
Diffstat (limited to 'TapTogglingAlgos/InformedMinCoeff.m')
-rw-r--r--TapTogglingAlgos/InformedMinCoeff.m109
1 files changed, 109 insertions, 0 deletions
diff --git a/TapTogglingAlgos/InformedMinCoeff.m b/TapTogglingAlgos/InformedMinCoeff.m
new file mode 100644
index 0000000..cb68d33
--- /dev/null
+++ b/TapTogglingAlgos/InformedMinCoeff.m
@@ -0,0 +1,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 \ No newline at end of file