Как я могу создать кусочную подставляемую функцию в MATLAB?

Попробуйте использовать COUNT в качестве аналитической функции в предложении ORDER BY:

SELECT name, ROW_NUMBER() OVER (PARTITION by name ORDER BY name) rn
FROM tbl_dup
ORDER BY COUNT(*) OVER (PARTITION BY name) DESC, rn;

enter image description here

[ 115] Демонстрация

7
задан gnovice 26 September 2010 в 04:04
поделиться

3 ответа

Вы действительно определили кусочную функцию с тремя точками разрыва, т. Е. В [0, 0,5, 1]. Однако вы не определили значение функции вне перерывов. (Кстати, я использовал здесь термин «разрыв», потому что мы действительно определяем простую форму сплайна, кусочно-постоянный сплайн. Я мог бы также использовать термин узел, еще одно распространенное слово в мире сплайнов. )

Если вы абсолютно уверены, что никогда не будете оценивать функцию за пределами [0,1], тогда проблем нет. Так что тогда просто определите кусочную функцию с ОДНОЙ точкой разрыва, при х = 0,5. Простой способ определить кусочно-постоянную функцию, подобную вашей, - использовать логический оператор. Таким образом, тест (x> 0.5) возвращает константу, либо 0, либо 1. Путем масштабирования и перевода этого результата, легко создать функцию, которая делает то, что вы хотите.

constfun = @(x) (x > 0.5)*2 - 1;

Встроенная функция делает то же самое, но встроенные функции ОЧЕНЬ медленны по сравнению с анонимной функцией. Я настоятельно рекомендую использовать анонимную форму. В качестве теста попробуйте следующее:

infun = inline('(x > 0.5)*2 - 1','x');
x = 0:.001:1;

tic,y = constfun(x);toc
Elapsed time is 0.002192 seconds.

tic,y = infun(x);toc
Elapsed time is 0.136311 seconds.

Да, для выполнения встроенной функции потребовалось значительно больше времени, чем для анонимной формы.

Проблема с простой кусочно-постоянной формой, которую я здесь использовал, заключается в том, что ее трудно расширить когда у вас есть больше точек останова. Например, предположим, что вы хотите определить функцию, которая принимает три разных значения в зависимости от того, в каком интервале находится точка? Хотя это можно сделать и с помощью творческого использования тестов, их тщательного перемещения и масштабирования, оно может стать неприятным. Например, как можно определить кусочную функцию, которая возвращает

-1 when x < 0,
2 when 0 <= x < 1,
1 when 1 <= x

. Одним из решений является использование единичной функции Хевисайда . Итак, во-первых, определите базовую единичную функцию Хевисайда.

H = @(x) (x >= 0);

Наша кусочная функция теперь получена из H (x).

P = @(x) -1 + H(x)*3 + H(x-1)*(-1);

Смотрите, что P (x) состоит из трех частей. Первый член - это то, что происходит для x ниже первой точки разрыва. Затем мы добавляем кусок, который действует выше нуля. Наконец, третий фрагмент добавляет еще одно смещение выше x == 1. Он достаточно легко наносится на график.

ezplot(P,[-3,3])

Более сложные сплайны легко генерируются с этого начала. Так что я назвал эту конструкцию снова сплайном. На самом деле, это то, к чему мы можем привести. На самом деле, это то, к чему это ведет. Сплайн является кусочной функцией, тщательно связанной между собой в виде списка узлов или точек разрыва. Сплайны, в частности, часто имеют определенные последовательности непрерывности, так, например, кубический сплайн будет дважды дифференцируемым (C2) через разрывы. Существуют также кусочно-кубические функции, которые являются только функциями C1. Моя точка зрения во всем этом заключается в том, что я описал простую начальную точку для формирования любой кусочной функции. Он работает довольно хорошо для полиномиальных сплайнов, хотя для выбора коэффициентов этих функций может потребоваться небольшая математика.

Другой способ создания этой функции - явный кусочно-полиномиальный. В MATLAB у нас есть малоизвестная функция mkpp. Попробуйте это ...

pp = mkpp([0 .5 1],[1;-1]);

Если бы у вас был набор инструментов для сплайнов, fnplt построит это непосредственно для вас. Предполагая, что у вас нет этого ТБ, сделайте следующее:

ppfun = @(x) ppval(pp,x);
ezplot(ppfun,[0 1])

Оглядываясь назад на вызов mkpp, все-таки это довольно просто. Первый аргумент - это список точек разрыва на кривой (в виде вектора ROW). Второй аргумент - это вектор COLUMN с кусочно-постоянными значениями, которые кривая примет в этих двух определенных интервалах между перерывами.

Несколько лет назад я опубликовал еще одну опцию, piecewise_eval . Его можно скачать с центрального обмена файлами MATLAB. Это функция, которая позволит пользователю задавать кусочную функцию исключительно в виде списка точек разрыва вместе с функциональными частями между этими перерывами. Таким образом, для функции с одним разрывом при x = 0,5 мы бы сделали это:

fun = @(x) piecewise_eval(x,0.5,{1,-1});

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

12
ответ дан 6 December 2019 в 07:52
поделиться

К сожалению, в MATLAB нет тернарного оператора, который бы упростил подобные вещи, но если немного расширить подход gnovice, вы можете создать анонимную функцию, например:

fh = @(x) ( 2 .* ( x <= 0.5 ) - 1 )

В В общем, анонимные функции более мощные, чем встроенные функциональные объекты, и позволяют создавать замыкания и т. д.

5
ответ дан 6 December 2019 в 07:52
поделиться

Если вы действительно хотите создать встроенную функцию (в отличие от анонимной функции ), то следующий способ, вероятно, будет самым простым:

f = inline('2.*(x <= 0.5)-1');

Однако, так как Как указывалось в других ответах, анонимные функции более широко используются и более эффективны:

f = @(x) (2.*(x <= 0.5)-1);
4
ответ дан 6 December 2019 в 07:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: