Czy istnieje sposób na porównanie dwóch funkcji równości? Na przykład: (λx.2*x) == (λx.x+x)
powinien zwrócić wartość true, ponieważ są one oczywiście równoważne.Jak porównać dwie funkcje równoważności, jak w (λx.2 * x) == (λx.x + x)?
Odpowiedz
to całkiem dobrze wiadomo, że ogólna równość funkcja jest nierozstrzygalny w ogóle, więc trzeba wybrać podzbiór problemu, który Cię interesuje Można rozważyć niektóre z tych rozwiązań cząstkowych.
- Presburger arithmetic jest rozstrzygającym fragmentem logiki pierwszego rzędu + arytmetyki.
- Pakiet universe oferuje funkcje kontroli równości dla wszystkich funkcji z skończoną domeną.
- Możesz sprawdzić, czy twoje funkcje są równe na całej masie wejść i traktować to jako dowód równości na nieprzetestowanych wejściach; sprawdź QuickCheck.
- Twórcy SMT dokładają wszelkich starań, czasami odpowiadając "nie wiem" zamiast "równy" lub "nie równy". Istnieje kilka powiązań z rozwiązaniami SMT w hakowaniu; Nie mam wystarczającego doświadczenia, aby zaproponować najlepszy, ale Thomas M. DuBuisson sugeruje sbv.
- Istnieje zabawna linia badań nad decydowaniem o równości funkcji i innych rzeczach na kompaktowych funkcjach; podstawy tego badania opisano w poście na blogu Seemingly impossible functional programs. (Zwróć uwagę, że zwartość jest bardzo silnym i bardzo subtelnym warunkiem!) Nie jest to funkcja spełniająca większość funkcji Haskell.)
- Jeśli wiesz, że twoje funkcje są liniowe, możesz znaleźć podstawę dla przestrzeni źródłowej; wtedy każda funkcja ma unikalną reprezentację macierzy.
- Możesz spróbować zdefiniować własny język ekspresji, udowodnić, że równoważność jest decydująca dla tego języka, a następnie osadzić ten język w Haskell. Jest to najbardziej elastyczny, ale także najtrudniejszy sposób na osiągnięcie postępu.
Czy jesteś pewien, że szuka on nie tylko sbv czy quickcheck? Z SBV: 'prove $ \ (x :: SInt32) -> 2 * x. == x + x' daje' Q.E.D' –
@ ThomasM.DuBuisson Świetna sugestia! Dodam to do odpowiedzi. –
Naprawdę szukałem głębszego przeglądu problemu, dokładnie tego, co podał Daniel. – MaiaVictor
Oprócz praktycznych przykładów podanych w innej odpowiedzi, wybierzmy podzestaw funkcji wyrażalnych w typowym rachunku lambda; możemy również pozwolić na typy produktów i sum. Chociaż sprawdzenie, czy dwie funkcje są równe, może być tak proste jak applying them to a variable and comparing results, nie możemy zbudować funkcji równości within the programming language itself.
ETA: λProlog to logiczny język programowania służący do manipulowania (typem lambda) funkcjami.
+1 Świetne linki! – luqui
Mówisz: "sprawdzenie, czy dwie funkcje są równe, może być tak proste, jak zastosowanie ich do zmiennej i porównanie wyników". Jednak trudno mi w to uwierzyć; jako prosty przykład, czy to naprawdę potwierdziłoby równość '(\ x -> 2 * x) == (\ x -> x * 2)'? –
"(\ x -> 2 * x) == (\ x -> x * 2)" nie jest koniecznie prawdziwe, zależy od tego, jak interpretujesz "*" i "2". Na przykład, możesz zdefiniować "==" na warunkach naziemnych, aby być modulo tożsamościowym jakiś system przepisywania terminu. – lukstafi
Minęły 2 lata, ale chcę dodać małą uwagę na to pytanie. Pierwotnie zapytałem, czy jest jakiś sposób, aby stwierdzić, czy (λx.2*x)
jest równa . Dodawania i mnożenia na X-rachunku można zdefiniować jako:
add = (a b c -> (a b (a b c)))
mul = (a b c -> (a (b c)))
Teraz, jeśli znormalizować następujących warunkach:
add_x_x = (λx . (add x x))
mul_x_2 = (mul (λf x . (f (f x)))
Otrzymasz:
result = (a b c -> (a b (a b c)))
Dla obu programów. Ponieważ ich normalne formy są równe, oba programy są oczywiście równe. Chociaż to nie działa w ogóle, działa w praktyce na wielu warunkach. (λx.(mul 2 (mul 3 x))
i (λx.(mul 6 x))
oba mają takie same zwykłe formularze, na przykład.
Istnieje technika o nazwie "superkompilacja" (polecam [this] (http://community.haskell.org/~ndm/temp/supero.pdf) paper). Wydaje mi się, że dojrzały superkompilator może zunifikować twoje funkcje, nawet jeśli są one zdefiniowane przez rekursję i dopasowanie do wzorca. – user3237465
To jest nierozstrzygalny w ogóle, ale dla odpowiedniego podzbioru, można rzeczywiście zrobić to dzisiaj skutecznie używając rozwiązują SMT:
$ ghci
GHCi, version 8.0.1: http://www.haskell.org/ghc/ :? for help
Prelude> :m Data.SBV
Prelude Data.SBV> (\x -> 2 * x) === (\x -> x + x :: SInteger)
Q.E.D.
Prelude Data.SBV> (\x -> 2 * x) === (\x -> 1 + x + x :: SInteger)
Falsifiable. Counter-example:
s0 = 0 :: Integer
uzyskać szczegółowe informacje, patrz: https://hackage.haskell.org/package/sbv
W języku z obliczeń symbolicznych jak Mathematica:
lub C# z computer algebra library:
MathObject f(MathObject x) => x + x;
MathObject g(MathObject x) => 2 * x;
{
var x = new Symbol("x");
Console.WriteLine(f(x) == g(x));
}
Powyższe wyświetla "Prawda" na konsoli.
Ale jednak '(x \ [funkcja] x + x) == (y \ [funkcja] 2 y)' jest czymś, czego nawet nie próbuje. – tfb
Udowodnienie, że dwie funkcje są sobie równe, jest ogólnie nierozstrzygalne, ale nadal można udowodnić funkcjonalną równość w szczególnych przypadkach, tak jak w pytaniu.
Oto próbka dowód w Lean
def foo : (λ x, 2 * x) = (λ x, x + x) :=
begin
apply funext, intro x,
cases x,
{ refl },
{ simp,
dsimp [has_mul.mul, nat.mul],
have zz : ∀ a : nat, 0 + a = a := by simp,
rw zz }
end
można zrobić to samo w inny sposób zależny od języka pisanego, takich jak Coq, Agda, Idris.
Powyższe ma charakter taktyczny. Rzeczywista definicja foo
(dowód), który pobiera generowany jest dość kęs być napisane ręcznie:
def foo : (λ (x : ℕ), 2 * x) = λ (x : ℕ), x + x :=
funext
(λ (x : ℕ),
nat.cases_on x (eq.refl (2 * 0))
(λ (a : ℕ),
eq.mpr
(id_locked
((λ (a a_1 : ℕ) (e_1 : a = a_1) (a_2 a_3 : ℕ) (e_2 : a_2 = a_3), congr (congr_arg eq e_1) e_2)
(2 * nat.succ a)
(nat.succ a * 2)
(mul_comm 2 (nat.succ a))
(nat.succ a + nat.succ a)
(nat.succ a + nat.succ a)
(eq.refl (nat.succ a + nat.succ a))))
(id_locked
(eq.mpr
(id_locked
(eq.rec (eq.refl (0 + nat.succ a + nat.succ a = nat.succ a + nat.succ a))
(eq.mpr
(id_locked
(eq.trans
(forall_congr_eq
(λ (a : ℕ),
eq.trans
((λ (a a_1 : ℕ) (e_1 : a = a_1) (a_2 a_3 : ℕ) (e_2 : a_2 = a_3),
congr (congr_arg eq e_1) e_2)
(0 + a)
a
(zero_add a)
a
a
(eq.refl a))
(propext (eq_self_iff_true a))))
(propext (implies_true_iff ℕ))))
trivial
(nat.succ a))))
(eq.refl (nat.succ a + nat.succ a))))))
Dlaczego upadek? – MaiaVictor
- 1. Jak porównać x i y w F #?
- 2. Jak uzyskać x 2 x = 8000?
- 3. Jak porównać dwie daty?
- 4. Jak sformatować etykietę zaznaczenia osi X w formacie 2^x?
- 5. Jak "odzyskać" 3-wymiarowych (2 x 2 x 2) array (sześcian) z 3 dwie macierze wymiarowych (twarze kostki)
- 6. jak porównać dwie mapy skrótów?
- 7. Jak porównać funkcje Pythona pod względem wydajności?
- 8. Jak porównać dwie tablice obiektów?
- 9. Jak porównać dwie bazy danych?
- 10. Jak porównać dwie zmienne CGSize?
- 11. Jak porównać dwie daty w php
- 12. Uproszczenie if (x == 1 || x == 2)
- 13. Pisanie modułu dla Pythona 2.x i 3.x
- 14. Jak porównać dwie daty w Objective-C
- 15. Jak porównać dwie listy w Haskell?
- 16. Jak porównać dwie wartości podwójne w Javie?
- 17. Jak uruchomić dwie funkcje jednocześnie?
- 18. Jak naprawić różnicę w zachowaniu activesupport 3.0.0 porównać do 2.x?
- 19. Jak wstawić dwie osie X w Matlabie na wykresie
- 20. tworząc dwie funkcje porównania?
- 21. Jak porównać dwie złożone struktury danych?
- 22. JavaFX 2.x TableView lokalizacja
- 23. Scala forall, aby porównać dwie listy?
- 24. porównaj dwie funkcje: :: funkcja
- 25. Jak porównać dwie wartości ciągu jako liczby całkowite?
- 26. spark.sql.crossJoin.enabled dla Spark 2.x
- 27. Jak porównać 2 tablice danych
- 28. Jak porównać 2 ciągi alfabetycznie
- 29. Jak porównać dwie listy: <String>?
- 30. Dlaczego (1/2) * x różni się od 0,5 * x?
Czy naprawdę potrzebujesz funkcji arytmetycznych lub są po prostu ciekawi porównanie funkcji? W tym drugim przypadku spójrz na normalizację w typach lambda. – lukstafi
@lukstafi po prostu ciekawy, ale przyjrzę się temu. – MaiaVictor
Twoje połączenie "ale" jest nie na miejscu, powinno raczej być "takie". ;-) – lukstafi