diff options
Diffstat (limited to 'TapTogglingAlgos/InformedMinCoeff.m')
| -rw-r--r-- | TapTogglingAlgos/InformedMinCoeff.m | 109 |
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 |
