Twardość obliczeniowa „prawdziwych” programów komputerowych

10

Często słyszałem, jak mówiono, że nie można napisać programu do wychwytywania błędów w przeglądarce internetowej, edytorze tekstu lub systemie operacyjnym z powodu twierdzenia Rice'a: każda właściwość semantyczna dla języka pełnego Turinga jest nierozstrzygalna.

Nie jestem jednak pewien, w jakim stopniu dotyczy to rzeczywistego programu, takiego jak systemy operacyjne. Czy tego typu programy wymagają pełnej siły kompletności Turinga? Czy istnieją prostsze modele obliczeń (takie jak PR), w których można pisać te aplikacje? Jeśli tak, to w jakim stopniu umożliwia to rozstrzygalność poprawności programu?

David Harris
źródło
nie można sprawdzić nietrywialnych uniwersalnych właściwości (np. coś zachowuje się dla wszystkich danych wejściowych) znacznie słabszych modeli, np. nie można sprawdzić, czy dwie obliczalne TM TM obliczają tę samą funkcję (chociaż zatrzymanie jest dla nich rozstrzygalne, ponieważ polytime TM zawsze zatrzymuje się). Z drugiej strony, jeśli domena wejść jest ograniczona, możesz sprawdzić niektóre właściwości w niektórych modelach, np. Program nie ulega awarii na danych wejściowych o rozmiarze mniejszym niż 1000, przynajmniej teoretycznie (w praktyce może to być trudne).
Kaveh
pytanie
Artem Kaznatcheev

Odpowiedzi:

14

Z pewnością możesz pisać programy, które wychwytują błędy - istnieje duża i aktywna społeczność ludzi, którzy piszą programy, które właśnie to robią. Jednak twierdzenie Rice'a powstrzymuje cię od napisania łapaczy błędów, które są zarówno solidne, jak i kompletne (tzn. Łapią wszystkie błędy pewnej klasy bez fałszywych alarmów).

To powiedziawszy, naiwne ograniczenia modelu obliczeniowego nie pomagają w znacznym stopniu poprawić praktyczności analizy programu. Powodem jest to, że można uzyskać programy, które robią „prawie to samo”, obracając pętle while

while P do 
   C

w pętle for z dużą stałą iteracji:

for i = 0 to BIGNUM do 
  if P then 
    C
  else
    break

Teraz ten program nie potrzebuje nawet pełnej siły prymitywnej rekurencyjnej (ponieważ pętla for może zostać rozwinięta w makro w ogromną zagnieżdżoną instrukcję if-then-else), ale w większości praktycznych przypadków będzie zachowywać się tak samo jak poprzednio. Zauważ, że pomaga to w rozstrzygalności teoretycznej - program jest całkowity, więc możesz odpowiadać na pytania, uruchamiając program i sprawdzając, co się stanie. To nie jest to, czego tak naprawdę chcemy, aby uzyskać odpowiedzi szybciej niż uruchomienie programu - wprowadzone sztuczne zakończenie nie pomaga w praktyce analizie programu, ponieważ błędy występują z powodu błędów w prawdziwej logice programu, a my nie „ w ogóle tego dotknąłem.

ϵ0

Neel Krishnaswami
źródło
Co rozumiesz przez „ten program nie jest nawet prymitywny rekurencyjny”?
Ryan Williams
@RyanWilliams prawdopodobnie tylko dlatego, że można go napisać w systemie, który pozwala na mniej niż pełną gamę prymitywnych funkcji rekurencyjnych, na przykład programy, które wymagają wyraźnych granic (czasu kompilacji) w pętlach.
cody
Możesz makro rozwinąć pętle, pozostawiając ci program rozgałęziający (tj. Tylko z „jeśli-to-jeszcze” i sekwencyjną kompozycją).
Neel Krishnaswami
Być może łatwiej byłoby powiedzieć coś takiego: „ten program nie potrzebuje nawet pełnej siły prymitywnej rekurencji”.
Maks.
@Max: sugestia zaakceptowana!
Neel Krishnaswami
5

Ponieważ pytałeś o poprawność programów w prawdziwych programach, takich jak systemy operacyjne, możesz być zainteresowany projektem seL4 ( czasopismo , pdf , konferencja ).

Zespół NICTA wziął mikrojądro trzeciej generacji z 8700 liniami C i 600 liniami asemblera wdrożonymi zgodnie ze abstrakcyjną specyfikacją w Haskell. Dostarczyli formalny, sprawdzony maszynowo dowód (w Isabelle / HOL), że wdrożenie jest ściśle zgodne ze specyfikacją. Dowodzi to, że ich program nie zawiera błędów.

Podobnie jak problem zatrzymania, chociaż nie można go ogólnie rozwiązać, można go rozwiązać w określonych przypadkach. W tym przypadku, chociaż nie możesz udowodnić, że dowolny kod C jest wolny od błędów, mogliby to zrobić w przypadku mikrojądra seL4.

Artem Kaznatcheev
źródło
Zauważ, że kod certyfikowany jest nadal podatny na błędy w specyfikacji, więc możesz tylko powiedzieć, że kod jest wolny od błędów w stosunku do specyfikacji.
nponeccop
@nponeccop zdecydowanie jest prawdą, ale kiedy zaczniesz wątpić w specyfikację, zaczniesz też naprawdę zacierać niesławną linię cech błędów. Aby nazwać coś „błędem”, musisz mieć na uwadze jakąś ukrytą specyfikację, uchwycenie intuicji za taką niejawną specyfikacją zaczyna się naprawdę głęboko przekopywać, dopóki nie trafisz na pytania dotyczące podstaw filozofii matematyki (w stylu Brouwera vs. Hilberta) .
Artem Kaznatcheev
Przez „specyfikację” rozumiałem specyfikację formalną, tj. Formalne twierdzenia, które udowodnisz. Nadal możesz popełniać błędy, przekształcając swoje wymagania tekstowe w twierdzenia. Jedyne, co otrzymujesz dzięki certyfikacji, to redukcja zaufanej bazy kodów (powinieneś ufać tylko swoim twierdzeniom, a nie kodowi lub dowodom) i zgodność kodu z twoimi twierdzeniami.
nponeccop
Oto cytat ze strony seL4: „Kod C mikrojądra seL4 poprawnie implementuje zachowanie opisane w jego abstrakcyjnej specyfikacji i nic więcej”.
nponeccop
2

Pytania, które zadajesz, są zupełnie inne.

Nie jestem jednak pewien, w jakim stopniu dotyczy to rzeczywistego programu, takiego jak systemy operacyjne. Czy tego typu programy wymagają pełnej siły kompletności Turinga?

Kompletowanie modelu obliczeniowego Turinga zajmuje bardzo niewiele. Na przykład różne modele z licznikami mogą symulować maszyny Turinga. Jeśli uważasz, że twoje oprogramowanie wymaga więcej niż dwóch liczników, którymi możesz dowolnie manipulować, używasz kompletnego języka Turinga. Chociaż liczby całkowite maszyny są ograniczone apriori, struktury danych alokowane na stercie zwykle nie są. Jeśli twoje oprogramowanie potrzebuje list, drzew i innych dynamicznie przydzielanych danych, używasz kompletnego języka Turinga.

Czy istnieją prostsze modele obliczeń (takie jak PR), w których można pisać te aplikacje? Jeśli tak, to w jakim stopniu umożliwia to rozstrzygalność poprawności programu?

Należy pamiętać, że nie chcemy sprawdzać arbitralnych właściwości naszego oprogramowania. Sprawdzanie bardzo specyficznych, wąskich właściwości (brak przepełnienia bufora, brak dereferencji wskaźnika zerowego, brak nieskończonych pętli itp.) Znacznie poprawia jakość i użyteczność oprogramowania. Teoretycznie takie problemy są nadal nierozstrzygalne. W praktyce skupienie się na określonych właściwościach pozwala nam odkryć strukturę w naszych programach, którą często możemy wykorzystać do rozwiązania problemu.

W szczególności możesz zmodyfikować swoje pierwotne pytanie na

Czy istnieje abstrakcja mojego oprogramowania, którą mogę efektywnie analizować w modelu niekompletnym Turinga?

Abstrakcja to model, który obejmuje zachowanie oryginalnego oprogramowania i prawdopodobnie wiele dodatkowych zachowań. Istnieją modele, takie jak maszyny z jednym licznikiem lub systemy wypychające, które nie są kompletne w Turinga i które możemy analizować. Standardowym podejściem do weryfikacji programu za pomocą zautomatyzowanych narzędzi jest zbudowanie abstrakcji w takim modelu i sprawdzenie go algorytmicznie.

Istnieją aplikacje, w których ludzie dbają o wyrafinowane właściwości swojego sprzętu lub oprogramowania. Firmy sprzętowe chcą, aby ich układy poprawnie wdrażały algorytmy arytmetyczne, firmy motoryzacyjne i awioniczne chcą certyfikowanego oprogramowania. Jeśli to takie ważne, lepiej wykorzystać (wyszkolonego) człowieka.

Vijay D.
źródło
Myślę, że odpowiedziałeś na przeciwne pytanie, a mianowicie czy edytor tekstu może być w Turingu kompletny? Przy odpowiedniej obsłudze rejestrów tak jest. Niemniej jednak możliwe jest narzucenie zasad manipulacji rejestrami, aby pokonać kompletność Turinga. Moje pytanie brzmi: ile można praktycznie zaprogramować w tych wąskich ograniczeniach.
David Harris
Odpowiadałem na pytanie, czy pisanie systemów operacyjnych i innego oprogramowania wymaga kompletnego języka programowania Turinga. Jeśli potrzebujesz wielu liczników lub nieograniczonych struktur danych, będziesz potrzebować kompletnego języka programowania Turinga.
Vijay D
@Vijay: nie, to nie jest prawda. Istnieje wiele teorii typów (np. Agda i Coq), które są niezwykle ekspresyjne i nie pozwalają na nieograniczoną rekurencję.
Neel Krishnaswami
@Neel: Aby wyjaśnić, mówię tylko o kompletności Turinga. Czy w tych teoriach nie można symulować maszyny Turinga?
Vijay D
Zgadza się - nie są kompletne w Turingu. W logice konstruktywnej kompletność Turinga pozwala na zaprogramowanie analogu paradoksu Russella.
Neel Krishnaswami