2009-07-15 13 views
28

Czy nie można stwierdzić, czy dwie funkcje są równoważne? Na przykład program piszący kompilator chce ustalić, czy dwie funkcje napisane przez programistę wykonują tę samą operację, jakich metod może użyć, aby ją wykreślić? A może możemy zrobić, aby dowiedzieć się, że dwie bazy TM są identyczne? Czy istnieje sposób na normalizację maszyn?Czy znalezienie równoważności dwóch funkcji jest nierozstrzygalne?

Edycja: Jeśli ogólny przypadek jest nierozstrzygalny, ile informacji trzeba mieć, aby móc poprawnie powiedzieć, że dwie funkcje są równoważne?

Odpowiedz

41

Biorąc pod uwagę dowolną funkcję, F określamy funkcję f” która zwraca na wejściu n jeśli f zatrzymywane na wejściu n. Teraz, dla pewnej liczby x zdefiniować funkcję g, które na wejściu n, powraca jeśli n = x, a poza tym wymaga F '(n).

przypadku równoważności funkcjonalnej były rozstrzygalne, następnie podejmowanie decyzji czy g jest identyczna F” decyduje f postojów na wejściu x. To by rozwiązało Halting problem. Powiązane z tą dyskusją jest Rice's theorem.

Wniosek: Równoważność funkcjonalna jest nierozstrzygalna.


Poniżej znajduje się dyskusja na temat ważności tego dowodu. Pozwólcie, że omówię, co robi dowód, i podam przykładowy kod w Pythonie.

  1. Dowód tworzy funkcję f” który na wejściu n zaczyna obliczenia f (n). Gdy ta obliczeniowy kończy f”zwraca 1. Zatem F '(n) = 1 IFF f postojów na wejściu n i f' nie zatrzyma na n IFF F nie robi "t. Pyton:

    def create_f_prime(f): 
        def f_prime(n): 
         f(n) 
         return 1 
        return f_prime 
    
  2. Następnie utworzyć funkcję g która przyjmuje n jako dane wejściowe i porównuje się pewną wartość x. Jeśli n = x, wówczas g (n) = g (x) = 1, w innym przypadku g (n) = f '(n). Pyton:

    def create_g(f_prime, x): 
        def g(n): 
         return 1 if n == x else f_prime(n) 
        return g 
    
  3. teraz trick jest to, że dla wszystkich N = X mamy że g (n) = f '(n)!. Ponadto wiemy, że g (x) = 1. Tak więc, jeśli g = f ', wówczas f' (x) = 1, a zatem f (x) zatrzymuje się. Podobnie, jeśli g! = F ' koniecznie musi być f' (x)! = 1, co oznacza, że ​​f (x) nie zatrzymuje się. Tak więc, decydowanie, czy g = f ' jest równoważne podejmowaniu decyzji, czy f zatrzymuje się na wejściu x. Korzystanie z nieco innej notacji dla powyższych dwóch funkcji, możemy podsumować to wszystko, co następuje:

    def halts(f, x): 
        def f_prime(n): f(n); return 1 
        def g(n): return 1 if n == x else f_prime(n) 
        return equiv(f_prime, g) # If only equiv would actually exist... 
    

Ja też wrzucić na ilustrację dowodu w Haskell (GHC wykonuje pewne wykrywanie pętli, a nie jestem pewien, czy wykorzystanie seq jest głupi dowód w tej sprawie, ale w każdym razie):

-- Tells whether two functions f and g are equivalent. 
equiv :: (Integer -> Integer) -> (Integer -> Integer) -> Bool 
equiv f g = undefined -- If only this could be implemented :) 

-- Tells whether f halts on input x 
halts :: (Integer -> Integer) -> Integer -> Bool 
halts f x = equiv f' g 
    where 
    f' n = f n `seq` 1 
    g n = if n == x then 1 else f' n 
+6

+1 za zgodę ze mną, ale z sexy matematyki. – chaos

+7

+1, ale to nasuwa kolejne pytanie: Jaki jest minimalny zestaw ograniczeń koniecznych, aby można było o tym decydować?Oczywiście, jeśli zestaw wejściowy jest zdefiniowany jako wystarczająco mały i wprowadzono ograniczenie czasu wykonania, obie funkcje mogą być brutalnie wymuszone. – l0b0

+0

"Kiedy jest coś równego jakiejś innej rzeczy" - www.math.harvard.edu/~mazur/preprints/when_is_one.pdf – nlucaroni

0

Można sprawdzić w swoim kompilatorze, czy są one "dokładnie" identyczne, jasne, ale ustalenie, czy zwracają identyczne wartości, byłoby trudne i czasochłonne. Musiałbyś zasadniczo wywołać tę metodę i wykonać jej rutynę na nieskończonej liczbie możliwych połączeń i porównać wartość z tą z innej rutyny.

Nawet gdybyś mógł to zrobić, musiałbyś wyjaśnić, jakie globalne wartości zmieniają się w funkcji, jakie obiekty zostały zniszczone/zmienione w funkcji, która nie ma wpływu na wynik.

Naprawdę można porównać tylko skompilowany kod. Więc skompiluj skompilowany kod do refaktora?

Wyobraź sobie czas działania podczas próby skompilowania kodu za pomocą "tego" kompilatora. Mógłbyś spędzić DUŻO czasu, odpowiadając na pytania: "bardzo pracochłonne kompilowanie ..." :)

+0

Jedynymi realnymi rozwiązaniami byłaby szklana skrzynia, w której występują dowódcy twierdzeń i tym podobne. Rozwiązanie brutalnej siły mogłoby zostać łatwo udaremnione przez parę funkcji, które nie zatrzymują się w przypadku niektórych przypadków. – BCS

2

W ogólnym przypadku nie można się zdecydować, czy dwie maszyny do obróbki mają zawsze takie samo wyjście dla identycznego wejścia. Ponieważ nie możesz nawet zdecydować, czy tm zatrzyma się na wejściu, nie widzę, jak powinno być możliwe podjęcie decyzji, czy zarówno zatrzymanie I wyprowadzenie tego samego wyniku ...

+1

To nie wystarczy. Może być możliwe pokazanie, że 2 funkcje spowodują ten sam efekt (w tym zatrzymanie lub nie) bez pokazywania czegokolwiek, co robią (udzielanie odpowiedzi, takich jak "obaj zwrócą ten sam wynik lub nie zatrzymają się, ale nie wiem które ") – BCS

7

Tak, jest to nierozstrzygalne. Jest to forma halting problem.

Należy zauważyć, że mam na myśli, że jest to nierozstrzygalne w ogólnym przypadku. Podobnie jak można określić zatrzymanie dla wystarczająco prostych programów, można określić równoważność dla wystarczająco prostych funkcji i nie jest wykluczone, że może to być przydatne dla aplikacji. Ale nie można stworzyć ogólnej metody określania równoważności dowolnych dwóch możliwych funkcji.

0

myślę, że jeśli pozwoli skutków ubocznych, można pokazać, że problem może być przekształcił w Post correspondence problem tak na ogół nie można pokazać, że dwie funkcje są nawet zdolny do posiadania tych samych efektów ubocznych.

4

Ogólny przypadek jest nierozstrzygalny według twierdzenia Rice'a, jak już powiedzieli inni (twierdzenia Rice zasadniczo mówią, że każda nietrywialna właściwość formalizmu pełnego Turinga jest nierozstrzygalna).

Istnieją szczególne przypadki, w których równoważność jest decydująca, najlepiej znanym przykładem jest prawdopodobnie równoważność automatów stanu skończonego. Jeśli dobrze pamiętam, równoważność automatów z przesunięciem jest już nierozstrzygalna poprzez redukcję do problemu korespondencji Post.

Aby udowodnić, że dwie podane funkcje są równoważne, wymagałoby się wprowadzenia jako dowodu równoważności w pewnym formalizmie, który następnie można sprawdzić pod kątem poprawności. Zasadnicze elementy tego dowodu to niezmienniki pętli, ponieważ nie można ich wyprowadzić automatycznie.

0

Czy nie można stwierdzić, czy dwie funkcje są równoważne?

Nie. Możliwe jest, że dwie funkcje są równoważne. Jeśli masz f (x), wiesz, że f (x) jest równoważne f (x).

Jeśli pytanie brzmi "możliwe jest określenie, czy f (x) i g (x) są równoważne z f i g będącymi dowolną funkcją i dla wszystkich funkcji g i f", wówczas odpowiedź brzmi "nie".

Jednakże, jeśli pytanie brzmi "czy kompilator może ustalić, że jeśli f (x) i g (x) są równoważne, że są one równoważne?", To odpowiedź brzmi "tak", jeśli są one równoważne zarówno w przypadku efektów wyjściowych, jak i skutków ubocznych i kolejność efektów ubocznych. Innymi słowy, jeśli jeden jest przekształceniem drugiego, który zachowuje zachowanie, to kompilator o wystarczającej złożoności powinien być w stanie go wykryć. Oznacza to również, że kompilator może przekształcić funkcję f w bardziej optymalną i równoważną funkcję g, z określoną definicją równoważną. Jeszcze bardziej zabawne staje się, gdy f zawiera nieokreślone zachowanie, ponieważ wtedy g może również zawierać niezdefiniowane (ale inne) zachowanie!

+0

Uważam, że twoje trzecie twierdzenie jest fałszywe. Myślę, że nie istnieje żadne ogólne rozwiązanie, aby udowodnić, że dwie funkcje są równoważne, ponieważ istnieją przekonujące argumenty (patrz odpowiedź Stephan202), że może to wymagać rozwiązania problemu zatrzymania. – BCS

+0

Nie powiedziałem tego, ale stackoverflow zjadł moją dłuższą odpowiedź. Ograniczałem problem, aby udowodnić, że dwie funkcje, które są równoważne, można wykryć jako równoważne. Składanie COMDAT używane przez linker MSVC właśnie to robi. – MSN

2

To zależy od tego, co masz na myśli przez "funkcję".

Jeśli funkcje, o których mówisz, mają gwarancję zakończenia - na przykład, ponieważ są napisane w języku, w którym kończą się wszystkie funkcje - i działają w domenach skończonych, są "łatwe" (chociaż może to nadal potrwać bardzo, bardzo długi czas): dwie funkcje są równoważne wtedy i tylko wtedy, gdy mają tę samą wartość w każdym punkcie wspólnej domeny.

Jest to tak zwana "ekstensjonalna" równoważność, aby odróżnić ją od równoważności syntaktycznej lub "intensywnej". Dwie funkcje są ekwiwalentne w stosunku do siebie, jeśli są one w swej istocie równoważne, ale konwersja nie zachodzi.

(Wszystkie pozostałe osoby powyżej zauważyć, że jest nierozstrzygalny w ogólnym przypadku są dość poprawne, oczywiście, jest to dość rzadkością - a zazwyczaj nieciekawe w praktyce. - szczególny przypadek)

+0

Więc jeśli chcemy porównać dwie funkcje "total" (te, które zatrzymują się na każdym wejściu) i zwrócić tak, jeśli pasują do każdego wejścia, nie ma inaczej. Jak udowodnić, że ten problem jest nierozstrzygalny (jest)? – mercury0114

+0

Jeśli w domenie jest skończenie wiele wejść, a obie funkcje zatrzymują się dla nich wszystkich i masz decydującą kontrolę równości dla kodomain, to po prostu wypróbuj obie funkcje na wszystkich wejściach i porównaj wyjścia. –

+0

Co, jeśli istnieje nieskończenie wiele wejść? – mercury0114

2

Należy pamiętać, że problem zatrzymania jest rozstrzygalny dla automatów o liniowym ograniczeniu. Prawdziwe komputery są zawsze ograniczone, a programy dla nich zawsze będą wracały do ​​poprzedniej konfiguracji po wystarczająco wielu krokach. Jeśli używasz nieokreślonego (wyimaginowanego) komputera do śledzenia konfiguracji, możesz wykryć tę pętlę i wziąć ją pod uwagę.

Powiązane problemy