Равны ли две функции?

[Edit]

общий вопрос кажется невероятно трудным для решения. Вот значительно ограниченный версия этого вопроса.


как определить равенство функций?

допустим, у нас есть

function f() {
    // black box code.
}

function g() {
    // black box code.
}

мы берем математическое определение функции. Так что

if for all x in domain, f(x) === g(x) then f === g

  • как мы обрабатываем Домены?
  • как мы можем в противном случае определите, если f === g

проверки по исходному коду глупо, потому что

function f(i) {
     return i % 2;
}

function g(i) {
     var returnVal = i % 2;
     return returnVal;
}

это obvouisly равны. Это тривиальные примеры, но вы можете представить, что более сложные функции равны, но не равны источнику.

вы можете предположить, что f и g не имеют никаких побочных эффектов, о которых мы заботимся.


[Edit]

как отметил @Pointy, вероятно, лучше всего ограничить домен. Вместо того, чтобы функция равенства пыталась угадать домен, пользователь функции равенства должен предоставить домен.

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

просто проблема, которую мы можем предположить, что домен-это множество всех целых чисел или подмножество этого, поэтому нам нужна функция:

function equal (f, g, domain) {

}

структура домена не имеет значения и может быть сделана, чтобы сделать проблему как легко по возможности. Вы также можете предположить, что f и g действуйте красиво на домене целых чисел и не сбой и ожог.

вы можете предположить, что f и g стой!

снова @Pointy указывает на хороший пример недетерминированных функций

что если мы ограничиваем f & g детерминированности.

5 ответов


Это невозможно в соответствии с теорема Райса:

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

Если вы ограничиваете область функций конечной, то вы можете тривиально проверить, если ∀x: f(x) = g (x) с помощью грубой силы, но это невозможно с бесконечной областью.


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

Это связано с тем, что проблема, которую вы пытаетесь решить, эквивалентна проблема останова.(источник; Страница 4)

конечно, вы можете сделать эвристику для этого, но всегда будут случаи, когда они не смогут определить это.

Если вы сузить ее для остановки функций в ограниченной области по-прежнему нетривиально быстро определить. Если предположить, что входные данные лежат в {1,..., n} и выход лежит в {1,..., m}, есть mn возможные функции (для каждого входа есть n возможных выходов). Если вы пробуете k точек, вы сужаете его и делаете вероятность того, что они равны больше, но все еще есть m(n-k) различные функции он может быть. Таким образом, вы можете определить, является ли это возможных что они все равно достаточно быстро, но чтобы быть уверенным, вам придется проверить все N возможных входных значений.

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

кроме того, если область не конечна,теорема Райса предотвращает существование такого алгоритма.


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

function a(n) {
  var today = new Date();
  if (today.getFullYear() === 2012 && today.getMonth() === 1 && today.getDate() === 3)
    return 0;
  return n * n;
}

эта функция выглядит очень похоже на

function b(n) { return n * n; }

за исключением 3 февраля 2012 года, когда он будет выглядеть точно так же:

function c(n) { return 0; }

Если вы действительно говорите о практической части недвижимого программное обеспечение для выполнения такого анализа, и если вы действительно не имеете большого контроля над деталями функций, которые будут протестированы, это кажется невозможным. Возможно, вы можете построить набор "правил", которым должны следовать функции, но даже при этом перспектива определения равенства без тестирования каждого значения в домене кажется довольно отдаленной.

редактировать - Я просто подумал: что если две функции возвращают функции? Теперь, чтобы определить, f ==g, вы сначала должны выяснить, возвращаются ли функции f (n) для всех n равны функциям, возвращаемым g (n) для всех n. Хм...


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


системы проверки доказательств, такие как Coq и Agda может быть в состоянии сделать то, что вы ищете.