exponenta event banner

Приближение функций фиксированной точки

Когда библиотечная функция фиксированной точки не доступна приложения фиксированной точки требуют приближения функции. Часто, интерполированный ищут, таблица используется, чтобы сохранить приближение функции по заданной области.

В этом примере показано, как аппроксимировать функцию y = sin (2*pi*x) по заданному входному диапазону с помощью интерполяционной таблицы.

Смотрите также: FunctionApproximation. Проблема, FunctionApproximation. Опции

В этом примере вход использует 16-битный тип данных без знака, fixdt(0,16,16), и выход использует 16-битный тип данных со знаком, fixdt(1,16,14).

Цель этого примера состоит в том, чтобы создать приближение, которое является с точностью до 8 битов справа от двоичной точки. Это означает, что худшая ошибка случая должна быть меньше 2^ (-8).

Существует много наборов точек данных интерполяционной таблицы, которые удовлетворили бы этой цели. Различные реализации могут быть выбраны в зависимости от целей, таких как использование памяти и скорость расчета. Этот пример находит решение, которое удовлетворяет этой цели точности с минимальным количеством точек данных.

Аппроксимированная функция

Используйте FunctionApproximation.Options объект задать точность и ограничения размера слова.

options = FunctionApproximation.Options();
options.AbsTol = 2^-8;
options.RelTol = 0;
options.WordLengths = [8 16 32];
options.MemoryUnits = 'bytes';
options.OnCurveTableValues = true;

Задайте функцию, чтобы аппроксимировать и входные диапазоны и типы данных в FunctionApproximation.Problem объект.

functionToApproximate = @(x) sin(2*pi*x);

problem = FunctionApproximation.Problem(functionToApproximate, 'Options', options);
problem.InputTypes = numerictype(0,16,16);
problem.InputLowerBounds = 0;
problem.InputUpperBounds = 0.25;
problem.OutputType = numerictype(1,16,14);

% Create a LUT solution
solution = solve(problem);

% Change breakpoint specification to EvenPow2Spacing and create a LUT
% solution again
problem.Options.BreakpointSpecification = 'EvenPow2Spacing';
bestEvenPow2SpacingSolution = solve(problem);
|  ID | Memory (bytes) | Feasible | Table Size | Breakpoints WLs | TableData WL | BreakpointSpecification |             Error(Max,Current) | 
|   0 |     4.0000e+00 |        0 |          2 |               8 |            8 |             EvenSpacing |     3.906250e-03, 2.105137e-01 |
|   1 |     2.1000e+01 |        1 |         19 |               8 |            8 |             EvenSpacing |     3.906250e-03, 3.589720e-03 |
|   2 |     1.9000e+01 |        0 |         17 |               8 |            8 |             EvenSpacing |     3.906250e-03, 4.257483e-03 |
|   3 |     1.7000e+01 |        1 |         15 |               8 |            8 |             EvenSpacing |     3.906250e-03, 3.824648e-03 |
|   4 |     1.5000e+01 |        0 |         13 |               8 |            8 |             EvenSpacing |     3.906250e-03, 7.812500e-03 |
|   5 |     1.2000e+01 |        0 |         10 |               8 |            8 |             EvenSpacing |     3.906250e-03, 4.677033e-03 |
|   6 |     1.1000e+01 |        0 |          9 |               8 |            8 |             EvenSpacing |     3.906250e-03, 6.957420e-03 |
|   7 |     1.4000e+01 |        1 |         12 |               8 |            8 |             EvenSpacing |     3.906250e-03, 3.687388e-03 |
|   8 |     1.3000e+01 |        0 |         11 |               8 |            8 |             EvenSpacing |     3.906250e-03, 7.812500e-03 |
|   9 |     6.0000e+00 |        0 |          2 |              16 |            8 |             EvenSpacing |     3.906250e-03, 2.127109e-01 |
|  10 |     4.0000e+00 |        0 |          2 |               8 |            8 |             EvenSpacing |     3.906250e-03, 2.127109e-01 |
|  11 |     1.3000e+01 |        0 |          9 |              16 |            8 |             EvenSpacing |     3.906250e-03, 7.097083e-03 |
|  12 |     1.1000e+01 |        0 |          9 |               8 |            8 |             EvenSpacing |     3.906250e-03, 7.097083e-03 |
|  13 |     6.0000e+00 |        0 |          2 |               8 |           16 |             EvenSpacing |     3.906250e-03, 2.105137e-01 |
|  14 |     4.0000e+00 |        0 |          2 |               8 |            8 |         EvenPow2Spacing |     3.906250e-03, 2.105137e-01 |
|  15 |     1.1000e+01 |        0 |          9 |               8 |            8 |         EvenPow2Spacing |     3.906250e-03, 6.957420e-03 |
|  16 |     6.0000e+00 |        0 |          2 |              16 |            8 |         EvenPow2Spacing |     3.906250e-03, 2.105137e-01 |
|  17 |     1.3000e+01 |        0 |          9 |              16 |            8 |         EvenPow2Spacing |     3.906250e-03, 6.957420e-03 |
|  18 |     6.0000e+00 |        0 |          2 |               8 |           16 |         EvenPow2Spacing |     3.906250e-03, 2.105137e-01 |
|  19 |     8.0000e+00 |        0 |          2 |              16 |           16 |         EvenPow2Spacing |     3.906250e-03, 2.105137e-01 |
|  20 |     1.4000e+01 |        1 |          7 |               8 |            8 |          ExplicitValues |     3.906250e-03, 3.830054e-03 |

Best Solution
|  ID | Memory (bytes) | Feasible | Table Size | Breakpoints WLs | TableData WL | BreakpointSpecification |             Error(Max,Current) |
|   7 |     1.4000e+01 |        1 |         12 |               8 |            8 |             EvenSpacing |     3.906250e-03, 3.687388e-03 |

|  ID | Memory (bytes) | Feasible | Table Size | Breakpoints WLs | TableData WL | BreakpointSpecification |             Error(Max,Current) | 
|   0 |     4.0000e+00 |        0 |          2 |               8 |            8 |         EvenPow2Spacing |     3.906250e-03, 2.105137e-01 |
|   1 |     3.5000e+01 |        1 |         33 |               8 |            8 |         EvenPow2Spacing |     3.906250e-03, 3.848536e-03 |
|   2 |     1.9000e+01 |        0 |         17 |               8 |            8 |         EvenPow2Spacing |     3.906250e-03, 4.257483e-03 |
|   3 |     1.1000e+01 |        0 |          9 |               8 |            8 |         EvenPow2Spacing |     3.906250e-03, 6.957420e-03 |
|   4 |     6.0000e+00 |        0 |          2 |              16 |            8 |         EvenPow2Spacing |     3.906250e-03, 2.105137e-01 |
|   5 |     2.1000e+01 |        0 |         17 |              16 |            8 |         EvenPow2Spacing |     3.906250e-03, 4.257483e-03 |
|   6 |     1.3000e+01 |        0 |          9 |              16 |            8 |         EvenPow2Spacing |     3.906250e-03, 6.957420e-03 |
|   7 |     6.0000e+00 |        0 |          2 |               8 |           16 |         EvenPow2Spacing |     3.906250e-03, 2.105137e-01 |
|   8 |     2.0000e+01 |        0 |          9 |               8 |           16 |         EvenPow2Spacing |     3.906250e-03, 4.856432e-03 |

Best Solution
|  ID | Memory (bytes) | Feasible | Table Size | Breakpoints WLs | TableData WL | BreakpointSpecification |             Error(Max,Current) |
|   1 |     3.5000e+01 |        1 |         33 |               8 |            8 |         EvenPow2Spacing |     3.906250e-03, 3.848536e-03 |

Исследуйте решения

%The software returns several implementations that meet the requirements
%specified in the |FunctionApproximation.Problem| and
%|FunctionApproximation.Options| objects. You can explore these different
%implementations.

feasibleSolutions = solution.FeasibleSolutions;
tableDataVec = [feasibleSolutions.TableData];
evenSpacingSolutions = find([tableDataVec.IsEvenSpacing]);
unevenSpacingSolutions = find(~[tableDataVec.IsEvenSpacing]);

evenSolutionsMemoryUsage   = arrayfun(@(x) x.totalMemoryUsage(), feasibleSolutions(evenSpacingSolutions));
unevenSolutionsMemoryUsage = arrayfun(@(x) x.totalMemoryUsage(), feasibleSolutions(unevenSpacingSolutions));

bestEvenSpacingSolution  = feasibleSolutions(evenSpacingSolutions(evenSolutionsMemoryUsage == min(evenSolutionsMemoryUsage)));
bestUnevenSpacingSolution = feasibleSolutions(unevenSpacingSolutions(unevenSolutionsMemoryUsage == min(unevenSolutionsMemoryUsage)));

xeven = bestEvenSpacingSolution.TableData.BreakpointValues{1};
yeven = bestEvenSpacingSolution.TableData.TableValues;

xuneven = bestUnevenSpacingSolution.TableData.BreakpointValues{1};
yuneven = bestUnevenSpacingSolution.TableData.TableValues;

xpow2 = bestEvenPow2SpacingSolution.TableData.BreakpointValues{1};
ypow2 = bestEvenPow2SpacingSolution.TableData.TableValues;

Сравните использование памяти

Сравните память, используемую интерполяционными таблицами.

memoryValues = [...
    totalMemoryUsage(bestEvenPow2SpacingSolution), ...
    totalMemoryUsage(bestEvenSpacingSolution), ...
    totalMemoryUsage(bestUnevenSpacingSolution)];

figure();
xTickLabels = {'Even pow2 spacing \newline(fastest)','Even spacing \newline(faster)','Uneven spacing \newline(fast)'};
hMemory = bar(memoryValues);
title('Comparison of memory usage obtained by different \newline breakpoint specification options');
hMemory.Parent.XTickLabel = xTickLabels;
hMemory.Parent.XTickLabelRotation = 45;
hMemory.Parent.YLabel.String = 'Memory (bytes)';
hMemory.Parent.Box = 'on';
hMemory.Parent.YGrid = 'on';

Объем памяти, используемый таблицами, использующими даже интервал и неравномерный интервал, является тем же самым, но число точек отличается. Это вызвано тем, что при хранении точек останова для таблиц, использующих даже интервал, только, первая точка и интервал хранятся. В отличие от этого все точки останова хранятся для таблиц с помощью неравномерного интервала.

Даже хранилища разрядки pow2 более чем удваивают точки, сохраненные для того, чтобы даже расположить с интервалами. С точки зрения использования памяти, даже pow2 интервал наименее оптимально для этой функции. Однако расчеты для даже pow2 интервал выполняются с помощью арифметических сдвигов вместо умножения, которое может привести к более быстрым временам выполнения.

Сравните решения исходной функции

Сравните решение, использующее даже pow2 располагающий с интервалами к исходной функции.

[~, hEvenPow2Spacing] = compare(bestEvenPow2SpacingSolution);
hEvenPow2Spacing.Children(4).Title.String = [hEvenPow2Spacing.Children(4).Title.String ' (Even pow2 spacing)'];

Сравните решение, использующее даже располагающий с интервалами к исходной функции.

[~, hEvenSpacing] = compare(bestEvenSpacingSolution);
hEvenSpacing.Children(4).Title.String = [hEvenSpacing.Children(4).Title.String ' (Even spacing)'];

Сравните решение с помощью неравномерного интервала для исходной функции.

[~, hUnevenSpacing] = compare(bestUnevenSpacingSolution);
hUnevenSpacing.Children(4).Title.String = [hUnevenSpacing.Children(4).Title.String ' (Uneven spacing)'];

Используйте приближение в модели Simulink®

Можно использовать это приближение непосредственно в Simulink® Lookup Table (n-D) блок.

modelName = 'fxpdemo_approx';
open_system(modelName)

modelWorkspace = get_param(modelName, 'ModelWorkspace');

modelWorkspace.assignin('xevenFirstPoint'     , xeven(1)  );
modelWorkspace.assignin('xevenSpacing'        , diff(xeven(1:2))  );
modelWorkspace.assignin('yeven'               , yeven  );
modelWorkspace.assignin('TableDTeven'         , bestEvenSpacingSolution.TableData.TableDataType      );
modelWorkspace.assignin('BreakpointDTeven'    , bestEvenSpacingSolution.TableData.BreakpointDataTypes);

modelWorkspace.assignin('xuneven'             , xuneven);
modelWorkspace.assignin('yuneven'             , yuneven);
modelWorkspace.assignin('TableDTuneven'       , bestUnevenSpacingSolution.TableData.TableDataType      );
modelWorkspace.assignin('BreakpointDTuneven'  , bestUnevenSpacingSolution.TableData.BreakpointDataTypes);

modelWorkspace.assignin('xpow2FirstPoint'     , xpow2(1)  );
modelWorkspace.assignin('xpow2Spacing'        , diff(xpow2(1:2))  );
modelWorkspace.assignin('ypow2'               , ypow2  );
modelWorkspace.assignin('TableDTpow2'         , bestEvenPow2SpacingSolution.TableData.TableDataType      );
modelWorkspace.assignin('BreakpointDTpow2'    , bestEvenPow2SpacingSolution.TableData.BreakpointDataTypes);

set_param(modelName, 'Dirty', 'off');

Сводные данные

Идеальная функция и эти три приближения используются в модели fxpdemo_approx. Если вам установили Simulink® Coder™, можно сгенерировать код для модели. Если встроенные параметры будут включены, сгенерированный код покажет большие различия в КПД в реализации неравномерно расположенного с интервалами, равномерно распределенного, и степень 2 интервалов.

sim(modelName)

Очистка

close_system(modelName, 0);