© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 1 październik 2004 Konstrukcja systemów obiektowych i rozproszonych Wykładowca:

Slides:



Advertisements
Podobne prezentacje
Sieci powiązań JM 1.
Advertisements

Metody badania stabilności Lapunowa
Rekurencja 1 Podprogram lub strukturę danych nazywamy rekurencyjną, (recursive subprogram, recursive data structure) jeżeli częściowo składa się z samej.
Programowanie obiektowe
Grażyna Mirkowska PJWSTK 15 listopad 2000
Wykład 10 Metody Analizy Programów Specyfikacja Struktur Danych
Wykład 6 Najkrótsza ścieżka w grafie z jednym źródłem
Programowanie I Rekurencja.
© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 3, Folia 1 październik 2004 Konstrukcja systemów obiektowych i rozproszonych Wykładowca:
PROGRAMOWANIE STRUKTURALNE
ALGORYTM Co to jest algorytm?
Badania operacyjne. Wykład 2
Elementarne struktury danych Piotr Prokopowicz
Ciągi de Bruijna generowanie, własności
Metoda pierwszeństwa operatorów
Domknięcie przechodnie (również) w bazach danych
PySBQL Język zapytań dla obiektowych baz danych. Aplikacje bazodanowe Główny nurt budowania aplikacji opiera się na połączeniu: SQL JDBC Java Jak wyświetlić
ZŁOŻONOŚĆ OBLICZENIOWA
Materiały do zajęć z przedmiotu: Narzędzia i języki programowania Programowanie w języku PASCAL Część 7: Procedury i funkcje © Jan Kaczmarek.
Materiały do zajęć z przedmiotu: Narzędzia i języki programowania Programowanie w języku PASCAL Część 8: Wykorzystanie procedur i funkcji © Jan Kaczmarek.
Algorytm Rochio’a.
Metody Sztucznej Inteligencji w Sterowaniu 2009/2010 Metoda propagacji wstecznej Dr hab. inż. Kazimierz Duzinkiewicz, Katedra Inżynierii Systemów Sterowania.
Wykład 2: Upraszczanie, optymalizacja i implikacja
BD-LAB6 Wojciech Pieprzyca
Instrukcja skoku GO TO etykieta Np. GO TO 100 ….. 100WRITE (*,*) Przeskok do instrukcji 100 Uwaga! NIE WOLNO skakać do wnętrzna złożonych instrukcji warunkowych.
Projektowanie i programowanie obiektowe II - Wykład II
Dr Anna Kwiatkowska Instytut Informatyki
Metody matematyczne w Inżynierii Chemicznej
Podstawy programowania
Podstawy programowania II
POJĘCIE ALGORYTMU Pojęcie algorytmu Etapy rozwiązywania zadań
O relacjach i algorytmach
Podstawy układów logicznych
Automatyczne dereferencje w języku SBQL
o granicy funkcji przy obliczaniu granic Twierdzenia
Podstawy programowania
Metody Lapunowa badania stabilności
Obserwatory zredukowane
MECHANIKA 2 Wykład Nr 11 Praca, moc, energia.
Systemy wspomagania decyzji
Modelowanie i Identyfikacja 2011/2012 Metoda propagacji wstecznej Dr hab. inż. Kazimierz Duzinkiewicz, Katedra Inżynierii Systemów Sterowania 1 Warstwowe.
Języki i środowiska programowania systemów rozproszonych, Wykład 09, Slajd Języki i środowiska programowania systemów rozproszonych Wykładowca:
Języki i środowiska programowania systemów rozproszonych, Wykład 07, Slajd Języki i środowiska programowania systemów rozproszonych Wykładowca:
Języki i środowiska programowania systemów rozproszonych, Wykład 12, Slajd Języki i środowiska programowania systemów rozproszonych Wykładowca:
Języki i środowiska programowania systemów rozproszonych, Wykład 05, Slajd Języki i środowiska programowania systemów rozproszonych Wykładowca:
Algorytmy.
Rozwiązanie zadań do zaliczenia I0G1S4 // indeks
Wybrane zagadnienia relacyjnych baz danych
Sterowanie – metody alokacji biegunów II
Programowanie obiektowe 2013/2014
ZWIĄZKI MIĘDZY KLASAMI KLASY ABSTRAKCYJNE OGRANICZENIA INTERFEJSY SZABLONY safa Michał Telus.
Podstawy Techniki Cyfrowej
ZAPIS BLOKOWY ALGORYTMÓW
Obliczalność czyli co da się policzyć i jak Model obliczeń maszyna licznikowa dr Kamila Barylska.
Programowanie strukturalne i obiektowe C++
Model obiektowy bazy danych
Treści multimedialne - kodowanie, przetwarzanie, prezentacja Odtwarzanie treści multimedialnych Andrzej Majkowski informatyka +
Wspomaganie Decyzji IV
Projektowanie obiektowe. Przykład: Punktem wyjścia w obiektowym tworzeniu systemu informacyjnego jest zawsze pewien model biznesowy. Przykład: Diagram.
Warstwowe sieci jednokierunkowe – perceptrony wielowarstwowe
Zarządzanie projektami
Pojęcia podstawowe c.d. Rachunek podziałów Elementy teorii grafów
Algorytmy. Co to jest algorytm? Przepis prowadzący do rozwiązania zadania.
Temat: Tworzenie bazy danych
Elementy cyfrowe i układy logiczne
Efektywność algorytmów
Konstrukcja systemów obiektowych i rozproszonych
Haskell Składnia funkcji.
POJĘCIE ALGORYTMU Wstęp do informatyki Pojęcie algorytmu
Zapis prezentacji:

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 1 październik 2004 Konstrukcja systemów obiektowych i rozproszonych Wykładowca: Kazimierz Subieta Polsko-Japońska Wyższa Szkoła Technik Komputerowych, Warszawa Instytut Podstaw Informatyki PAN, Warszawa Wykład 1: Tranzytywne domknięcia i równania stałopunktowe

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 2 październik 2004 Zawartość wykładu Tranzytywne domknięcie w SBQL. Równania stałopunktowe w SBQL. Związek z dedukcyjnymi bazami danych. Optymalizacja układu równań stałopunktowych.

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 3 październik 2004 Rekurencyjne lub sieciowe struktury danych Dla niektórych aplikacji przetwarzane struktury danych mają organizację rekurencyjną (hierarchiczną) lub tworzą sieci z pętlami, np. BOM (Bill-Of-Material), który działa na hierarchii części pewnego wyrobu (np. samochodu lub samolotu); Drzewa genealogiczne, zależności rodzinne; Zależności giełdowe (udziały spółek w innych spółkach); Różne typy sieci (transportowa, kolejowa, telekomunikacyjna, gazowa, wodociągowa, kanalizacyjna, kablowa, itd.); Metadane, np. Interface Repository standardu CORBA Repozytoria konfiguracji oprogramowania; itd. Dla takich aplikacji typowe operatory z języków zapytań (selekcja, projekcja, złączenie, kwantyfikatory) są niewystarczające. Za słaba jest algebra relacji, za słaby jest standardowy SQL. Konieczne są specjalne operatory, m.in. tranzytywne domknięcia.

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 4 październik 2004 Przykłady zapytań z tranzytywnym domknięciem Dla hierarchii część-podczęść: Jaka jest całkowita masa silnika?, Ile nakrętek M10 wchodzi w skład jednego samochodu? Dla drzewa genealogicznego: Podaj wszystkich żyjących obecnie moich kuzynów, dowolnie odległych w drzewie genealogicznym. Dla sieci połączeń lotniczych: Podaj połączenie pomiędzy Plovdiv (Bulgaria) a Seattle (USA) o minimalnym koszcie (lub minimalnym czasie lotu); Dla pliku XML: Podaj ścieżkę tagów prowadzących do danej z wartością Malcolm McLaren. Dla tego rodzaju zapytań niektóre systemy wprowadzają specjalne (niestandardowe) rozszerzenia SQL, np. klauzula connect by w systemie Oracle lub operator union all w systemie IBM DB2. Złożoność i uniwersalność zapytań jest poważnym problemem

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 5 październik 2004 Pojęcie tranzytywnego domknięcia Pochodzi z teorii relacji lub teorii grafów. Jeżeli relacja binarna R ma postać R = {,,,...} to tranzytywne domknięcie relacji R, zapisywane jako R*, zawiera parę, jeżeli istnieje dowolnie długi ciąg c1, c2, c3,..., cn taki, że a = c1, b = cn i dla i = 1,2,3,... n-1 zachodzi R. Innymi słowy, dwa węzły grafu skierowanego należą do tranzytywnego domknięcia, jeżeli pomiędzy nimi jest połączenie.

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 6 październik 2004 Ortogonalność tranzytywnego domknięcia Tranzytywne domknięcie musi być przystosowane do pozostałych operatorów języka zapytań i musi być ortogonalne do tych operatorów, czyli umożliwiające dowolne kombinacje tego operatora z innymi konstrukcjami języka. Naiwne potraktowanie tego operatora może wprowadzić niepotrzebne ograniczenia, uniemożliwiając zadawanie istotnych zapytań. Jest to przypadek rozwiązań tego operatora znanych z systemów relacyjnych – z reguły nieortogonalnych, przez co: mało uniwersalnych (nie dających możliwości zadawania wielu zapytań); trudnych do objaśnienia dla nowicjuszy; trudnych do użycia; trudnych do optymalizacji. Zadaniem postawionym przy projektowaniu i realizacji języka SBQL było doprowadzenie tego operatora do takiej uniwersalności, o ktorej można byłoby powiedzieć więcej się nie da. Jednocześnie chodziło o koncepcyjną prostotę.

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 7 październik 2004 Relacja będąca podstawą tranzytywnego domknięcia Są dwie możliwości: Relacja taka jest dana explicite jako zapamiętana struktura danych: Skończona liczba węzłów grafu, Wiele zadań jest nierealizowalna, Łatwiej optymalizowalna. Relację tę wylicza się w locie poprzez zapytanie, w miarę potrzeby, przy wyliczaniu tranzytywnego domknięcia: Potencjalnie nieskończona liczba węzłów grafu, Znacznie większa uniwersalność, Mogą być trudności z optymalizacją (ale nie na pewno). Wiele prac teoretycznych,zakłada, że ta relacja jest zadana wyłącznie w strukturze danych, czyli godzi się na wymienione wady. W drugim przypadku dla już wyliczonego elementu c i wyliczamy poprzez zapytanie kolejny element c i+1 taki, że należą do tranzytywnego domknięcia tej relacji; to postępowanie kontynuujemy dla c i+1, itd. Istotna jest także prosta składnia i semantyka tego operatora, umożliwiająca łatwe zrozumienie sytuacji, w których może być użyty, oraz sposobów jego użycia.

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 8 październik 2004 Tranzytywne domknięcie w SBQL W tym wykładzie nie będziemy szczegółowo omawiać rozwiązań tranzytywnego domknięcia w Oracle i DB2. Dla większości zapytań są one koszmarne. Ich uniwersalność jest bardzo słaba, szczególnie w Oracle. Zajmiemy się natomiast sposobem (składnią i semantyką) tego operatora w SBQL. Dopasowując je do już wprowadzonego (w poprzednim semestrze) stylu definiowania operatorów SBQL. Tranzytywne domknięcie w SBQL jest nowym operatorem niealgebraicznym, na wzór już wprowadzonych operatorów niealgebraicznych. Implementacja (bez optymalizacji) jest przez to dziecinnie łatwa. Niżej zdefiniujemy je w najbardziej ogólnej postaci, w której operator ten może działać nie na zapamiętanym, lecz na wyliczonym grafie, zaś kolejny element domknięcia jest wyliczany w locie.

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 9 październik 2004 Składnia i semantyka dla M0 Składnia: zapytanie ::= zapytanie close by zapytanie Semantyka: Zapytanie q1 close by q2 jest ewaluowane w sposób następujący: Ewaluuje się zapytanie q1, które powinno zwrócić bag; jak zwykle, zapamiętuje się go na wierzchołku QRES. Nazwijmy ten element stosu T. Dla każdego elementu r należącego do T wykonuje się następujące kroki: Oblicza się nested(r) i rezultat jest wkładany na wierzchołek ENVS; Ewaluuje się q2, które powinno zwrócić bag z elementami zgodnymi typologicznie z elementami zwróconymi przez q1; wynik q2 jest zapamiętany na wierzchołku QRES. Istotny moment: wszystkie elementy bagu zwróconego przez q2 dostawia się (sumuje mnogościowo) z T (gdzie zapamiętany był rezultat q1). Usuwa się wierzchołek QRES; Usuwa się wszystkie sekcje ENVS włożone w pierwszym kroku. W ten sposób elementy zwrócone przez q2 znajdą się w T, a wobec tego będą po jakimś czasie elementami r przetwarzanymi przez ww. kroki. Początkowy stan T, w którym ulokowany był wynik q1, będzie więc rozrastał się w kolejnych krokach o kolejne wyniki q2, aż do momentu, kiedy dla ostatniego przetwarzanego elementu bagu T zapytanie q2 zwróci pusty bag. W końcu wierzchołek QRES będzie zawierał wynik tranzytywnego domknięcia.

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 10 październik 2004 Semantyka i implementacja Inne (denotacyjne) sformułowanie opisanego wyżej procesu ma postać równania stałopunktowego T = q1 T. q2 startujemy od T = do najbliższego punktu stałego Można go także przedstawić w postaci nieskończonej iteracji: T = q1 q1.q2 q1.q2.q2 q1.q2.q2.q2... która oczywiście zakończy się, gdy któryś z kolejnych członów zwróci. Implementacja: operator close by jest tak samo skomplikowany jak operator kropki. Implementacja bez optymalizacji jest banalna. Pokażemy na przykładach, że mimo banalnej implementacji jest to operator bardzo uniwersalny, znacznie poszerzający moc języka zapytań. Operator można w sposób naturalny rozszerzyć na modele M1-M3. Przy pewnym skomplikowaniu zapytań jest to operator dość trudny – pytanie tylko, czy jest jakiś łatwiejszy sposób

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 11 październik 2004 Schemat (uproszczony) modelu BOM Schemat opisuje powiązanie pomiędzy częściami i podczęściami. Każda podczęść może wchodzić do wielu nadczęści. Każda część jest charakteryzowana przez atrybut nazwa oraz rodzaj, który może przyjąć dwie wartości: detal dla części elementarnych i agregat dla części złożonych. Atrybuty kosztDet - koszt detalu - i masaDet – masa detalu - występują wtedy, gdy atrybut rodzaj ma wartość detal. Jeżeli atrybut rodzaj przyjmuje wartość agregat, to występują atrybuty kosztMont – koszt montażu oraz masaMont – przyrost masy w wyniku montażu. Każda część będąca agregatem składa się z pewnej liczby podczęści, co jest odnotowane w atrybucie złożonym składnik. Składnik zawiera pointer prowadziDo, prowadzący do właściwej części będącej składnikiem danego agregatu. Część[0..*] nazwa rodzaj kosztDet[0..1] masaDet[0..1] kosztMont[0..1] masaMont[0..1] składnik[0..*] ilość prowadziDo

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 12 październik 2004 Pragmatyka - Przykład 1 Podaj wszystkie podczęści składające się na część o nazwie silnik: Podzapytanie (Część where nazwa = silnik) zwraca referencję do obiektu Część o nazwie silnik. Operator close by wstawia na stos bindery do wszystkich atrybutów tego obiektu, wśród nich wiele binderów o nazwie składnik; tyle, ile silnik zawiera bezpośrednich podczęści. Na tym stosie działa podzapytanie (składnik.prowadziDo.Część), zwracając referencje do bezpośrednich składników silnika. Zostaną one następnie ulokowane w tym samym miejscu stosu QRES, gdzie umieszczona była referencja do obiektu silnik; wobec czego po jakimś czasie będą tak samo przetworzone przez to podzapytanie. Proces domykania zakończy się, gdy rekurencyjnie przetworzone będą przez to podzapytanie wszystkie składniki części silnik, bezpośrednie lub pośrednie. Funkcja distinct usuwa zdublowane referencje (pojawiające się wskutek zrostów w drzewie specyfikacji wyrobu). distinct((Część where nazwa = silnik) close by (składnik.prowadziDo.Część))

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 13 październik 2004 Pragmatyka - Przykład 2 i 3 Podaj wszystkie części elementarne składające się na część o nazwie silnik: Podaj wszystkie części składające się na część o nazwie silnik, wraz z ich ilością: Zapytanie przed close by zwraca strukturę składającą się z referencji do obiektu silnika oraz liczby 1 nazwanej ile; jest to rodzaj pseudozmiennej (w istocie jest to utworzenie bindera), która dla każdej podczęści silnika będzie wyznaczać jej ilość. Po close by nawigujemy do obiektu składnik, wyznaczając dalej część wchodzącą w skład silnika oraz ilość nazwaną ile, będąca iloczynem ilości nadczęści (poprzednie ile) i ilości bieżącej podczęści. distinct((Część where nazwa = silnik) close by (składnik.prowadziDo.Część)) where rodzaj = detal ((Część where nazwa = silnik), (1 as ile)) close by (składnik.(( prowadziDo.Część), (ile * ilość) as ile))

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 14 październik 2004 Przykład 4 Poprzedni wynik nie sumuje ilości identycznych podczęści. Aby to zrobić, należy rozbudować to zapytania wprowadzając w odpowiedni sposób funkcję agregowaną sum, np. poprzez wyrażenie: Pierwsze dwie linie zawierają poprzednie zapytanie używające operatora close by, z tym, że referencja do obiektu Część została nazwana x. Trzecia linia bierze cały wynik tego zapytania i nazywa go wszystkieCzęściSilnika. Operator kropki w tej linii powoduje, że cały nazwany w ten sposób wynik znajdzie się na wierzchołku ENVS. Czwarta linia usuwa zdublowane referencje, wyznaczając w ten sposób wszystkie różne części silnika, nazywając je y. Operator kropki w tej linii uruchamia pętlę po y (po kolekcji części silnika bez duplikatów), umieszczając w każdej iteracji binder y(iczęść) na wierzchołku ENVS. Ostatnia linia ustala wynik: referencje do części i sumę ilości poszczególnych części we wszystkich składowych silnika. ((((Część where nazwa = silnik) as x, (1 as ile)) close by (składnik.((prowadziDo.Część) as x, (ile*ilość) as ile))) group as wszystkieCzęściSilnika). ((distinct(wszystkieCzęściSilnika.x) as y). (y, sum((wszystkieCzęściSilnika where x = y).ile)))

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 15 październik 2004 Przykład 5 Podaj koszt i masę części o nazwie silnik. Uwzględnij koszty i masy wszystkich części detalicznych silnika, przyrosty kosztu i masy związane z montażem agregatów oraz atrybut ilość określający, ile razy dana część wchodzi jako składnik do agregatu. ((((Część where nazwa = silnik) as x, (1 as ile)) close by (składnik.((prowadziDo.Część) as x, (ile*ilość) as ile))) group as wszystkieCzęściSilnika). (wszystkieCzęściSilnika.( if x.rodzaj = detal then ((ile * x.koszt) as k, (ile * x.masa) as m) else ((ile * x.kosztMont) as k, (ile * x.masaMont) as m))) group as przyrostyKosztuMasy). (sum(przyrostyKosztuMasy.k) as kosztSilnika, sum(przyrostyKosztuMasy.m) as masaSilnika)

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 16 październik 2004 Przykład 6 W obiekcie a jest przechowywana liczba; sformułować zapytanie w SBQL obliczające pierwiastek kwadratowy z a. Wykorzystamy w tym celu równanie stałopunktowe x = (a/x + x)/2, startując od x = 1 i wykonując 5 iteracji. Na początku ustawiamy wartości początkowe x oraz licznika na 1. W drugiej linii obliczamy formułę równania, podstawiając ją na x, i zwiększamy licznik o 1. Jeżeli ten licznik przekroczy 5, to warunek where powoduje, że operator close by kończy akcję. Podzapytanie w drugiej linii zwraca więc 5 par struct{ x(przybliżenie pierwiastka), licznik(liczba)}. Najlepszym przybliżeniem jest oczywiście para, gdzie wartość licznika jest 5, i ta wartość x jest wybrana przez podzapytanie z trzeciej linii. ((1 as x, 1 as licznik) close by (((a/x + x)/2 as x, licznik+1 as licznik) where licznik 5). (x where licznik = 5)

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 17 październik 2004 Zalety i wady operatora close by Ostatnie trzy zapytania pokazują możliwości tranzytywnego domknięcia: przy jego pomocy możemy prowadzić złożone obliczenia w grafie, liczyć pierwiastek kwadratowy, itd. Powstaje pytanie, gdzie jest granica mocy obliczeniowej tej prostej i banalnej w implementacji konstrukcji? Odpowiedź na to zapytanie, sformułowana przez matematyków, być może byłaby nietrywialna, ale dla nas jest mało interesująca. Nas interesują granice możliwości pragmatycznej operatora, tj. na ile będzie wygodny dla programistów. Ostatnie zapytania prowadzą do negatywnego wniosku. Zapytania są zbyt złożone dla powszechnego programisty aplikacyjnego, a wobec tego ten sposób formułowania obliczeń może nie być zaakceptowany. Odczytanie znaczenia zapytań po jakimś czasie od ich napisania sprawia trudności, a należy pamiętać (zgodnie ze starym powiedzeniem), że program pisze się raz, a czyta się 50 razy. Stąd operator close by jest akceptowalny w wersji prostej, a może być kontrowersyjny przy użyciu jego pełnej mocy.

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 18 październik 2004 Inne warianty tranzytywnego domknięcia (1) Operator leaves by pozwala na domknięcie tranzytywne podobne do close by, ale który pozostawia tylko liście domykanego grafu, usuwając w locie węzły pośrednie. To powoduje, że operator jest szybszy, a poza tym znaczna liczba zapytań ulega skróceniu. Podaj wszystkie części elementarne składające się na część o nazwie silnik: distinct((Część where nazwa = silnik) leaves by (składnik.prowadziDo.Część)) Oblicz pierwiastek kwadratowy z a: ((1 as x, 1 as licznik) leaves by (((a/x + x)/2 as x, licznik+1 as licznik) where licznik 5). x Niestety, nie jest pewne, że ten operator jest akceptowalny dla programisty.

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 19 październik 2004 Inne warianty tranzytywnego domknięcia (2) Powodem wprowadzenia dalszych wariantów operatora, nazwanych close distinct by oraz leaves distinct by, są problemy obliczeniowe. Jeżeli domykany graf ma cykle, tj. q2 zwróci w pewnym momencie element, który już wcześniej był zwrócony przez q2, to proces nigdy się nie skończy. Ustalenie tego faktu podczas wykonywania close by jest trudne, ponieważ wymagałoby stwierdzania przy każdym elemencie zwracanym przez q2, czy taki element nie był już wcześniej zwrócony, co obniżyłoby sprawność do stanu nieakceptowalnego. Operator close distinct by tym różni się od close by, że w każdym obrocie pętli iteracyjnej automatycznie usuwa duplikaty. Efektywna implementacja tego operatora polega na tym, że wspomniany wyżej zbiór T trzyma się w postaci posortowanej. Elementy zwrócone przez q2 są zawsze wstawiane w odpowiednie miejsca posortowanego zbioru, dzięki czemu można łatwo i szybko stwierdzić, że element jest duplikatem i pominąć go w dalszym przetwarzaniu.

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 20 październik 2004 Przykład 7 Oblicz pierwiastek kwadratowy z a; wynik należy podać z dokładnością do piątego miejsca po przecinku. (1 as x) leaves distinct by ((integerOf( * (a/x + x)/2) / ) as x) Zrezygnowaliśmy z licznika iteracji; obliczenia zakończą się, gdy kolejne przybliżenia x nie będą się dalej różnić.

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 21 październik 2004 Równania stałopunktowe w SBQL Równania stałopunktowe typu x = f(x) (których rozwiązaniem jest tzw. najmniejszy punkt stały, least fixed point) oraz układy takich równań są przedmiotem licznych teorii w matematyce między innymi z tego powodu, że są dobrym środkiem formalnego opisu semantyki mechanizmów rekurencyjnych, np. semantyki rekurencyjnych procedur. W językach zapytań pojawiły się one z powodu ich własności pragmatycznych. Okazało się, że mogą być efektywnie zastosowane przez użytkownika lub programistę do formułowania tranzytywnych domknięć. Jest to niekiedy wygodniejsze i czytelniejsze, a ponadto, równania takie są znacznie bardziej uniwersalne niż tranzytywne domknięcia. W istocie, przedstawione przez nas zapytanie q1 close by q2 sprowadza się do równania stałopunktowego T = q1 T.q2. Możemy formułować zapytania w postaci T = q(T), gdzie q jest dowolnym zapytaniem odwołującym się do T, co pozwoli na zadawanie zapytań niewyrażalnych przez tranzytywne domknięcia.

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 22 październik 2004 Oczekiwania dotyczące równań stałopunktowych Wielu specjalistów uważa, że są one w stanie wyrażać w prosty sposób tzw. reguły biznesowe (business rules). Jest to naciągane i wątpliwe, Takie równania mogą być środkiem rozwiązania pewnych rekurencyjnych problemów. Równania te realizują paradygmat bardzo podobny do tego, który nosi nazwę dedukcyjnych baz danych (lub Datalogu). Podkreśla się przy tym często związki z logiką matematyczną, ukoronowaniem maszynowej inteligencji (zdaniem pseudo-teoretycznych demagogów). Związek dedukcyjnych baz danych z logiką matematyczną jest drugorzędny. Równania stałopunktowe można budować praktycznie w oparciu o dowolny paradygmat, włączając algebrę relacji, SQL, OQL i oczywiście SBQL. Programowanie pewnych rekurencyjnych zadań poprzez reguły mające postać równań stałopunktowych może być ważne z powodów pragmatycznych, Natomiast zastosowanie w tym kontekście logiki matematycznej jest kompletnie nieważne - nie oferuje ona w istocie nic więcej poza (kontrowersyjną) składnią.

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 23 październik 2004 Składnia równań stałopunktowych Składniowo, układ równań stałopunktowych należałoby zamknąć pewnymi nawiasami, aby je wyróżnić wśród innych elementów języka. Podana niżej składnia jest przykładowa. rule (x1, x2, x3,...) { x1 :- q1(x1, x2, x3,...); x2 :- q2(x1, x2, x3,...); x3 :- q3(x1, x2, x3,...);... } Nazwy x1, x2, x3,... mogą być dowolnie wybrane przez programistę. q1, q2, q3,... są zapytaniami SBQL zależnymi od nazw x1, x2, x3,..., przy czym w danym zapytaniu te nazwy nie muszą wystąpić. To samo dotyczy nagłówka rule: niektóre nazwy spośród x1, x2, x3,... mogą nie wystąpić, ale musi wystąpić co najmniej jedna. Kolejność równań xi :- qi(x1, x2, x3,...) jest dowolna. W równaniach wybraliśmy symbol :- inny niż =, ponieważ semantyka tej równości jest specyficzna, bardziej przypominająca podstawienie.

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 24 październik 2004 Semantyka równań stałopunktowych Rezultatem jest struktura struct{ x1(bag1), x2(bag2), x3(bag3),...}, gdzie bag1, bag2, bag3,... są bagami wyliczonymi przez zapytania q1, q2, q3,... (odpowiednio). Wyliczenie polega na procesie iteracyjnym, w którym na początku wszystkim nazwom x1, x2, x3,... przypisuje się pusty bag. Następnie liczy się q1, q2, q3,..., uzyskując w ten sposób następne wartości x1, x2, x3,.... Proces ten jest powtarzany aż do momentu osiągnięcia punktu stałego, tj. takich wartości bag1, bag2, bag3,... podstawionych pod x1, x2, x3,..., że kolejne wyliczenie q1, q2, q3,... nie przyniesie ich zmiany. Implementacja tego procesu jest bardzo prosta. Optymalizacja w ogólnym przypadku może być bardzo trudna, stąd mogą pojawić się zasadnicze problemy z wydajnością (powód dla którego dedukcyjne bazy danych nie przebiły się do praktyki)

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 25 październik 2004 Przykłady z BOM Podaj wszystkie części składające się na silnik (ewentualnie z duplikatami). rule(Elem) { Elem :- (Część where nazwa = silnik) (Elem.składnik.prowadziDo.Część);} Podaj części detaliczne silnika, z usunięciem duplikatów: distinct( rule(Elem) { Elem :- (Część where nazwa = silnik) (Elem.składnik.prowadziDo.Część);}.Elem) where rodzaj = detal

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 26 październik 2004 Przykład z drzewem genealogicznym Obiekty Osoba mają atrybuty nazwisko, rokUr (rok urodzenia), żyje (z wartością boolowską) oraz są powiązane związkami rodzinnymi matka, ojciec, syn, córka, zaimplementowanymi jako obiekty pointerowe umieszczone wewnątrz obiektów Osoba. Podaj nazwisko i rok urodzenia wszystkich żyjących kuzynów Kowalskiego, którzy są od niego młodsi: rule(młodszyŻyjącyKuzyn){ kto :- Osoba where nazwisko = Kowalski; przodek :- kto przodek.(matka ojciec).Osoba; kuzyn :- przodek kuzyn.(syn córka).Osoba; żyjącyKuzyn :- distinct( kuzyn where żyje ); młodszyŻyjącyKuzyn :- ((żyjącyKuzyn as z) where kto as k (z.rokUr > k.rokUr)).z; }. młodszyŻyjącyKuzyn. (nazwisko, rokUr)

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 27 październik 2004 Optymalizacja Przy naiwnej ewaluacji w podanym poprzednio układzie równań zmienne kto, przodek, kuzyn, żyjącyKuzyn, młodszyŻyjącyKuzyn będą ewaluowane wielokrotnie, tyle razu, ile potrzeba do osiągnięcia punktu stałego. Dla dużych drzew genealogicznych może to być nawet miliony razy. Tymczasem jest oczywiste, że np. zmienną kto można wyliczyć tylko raz, gdyż za każdym następnym razem jej wartość się nie zmieni. Istotą metody optymalizacji jest ustalenie kolejności wyliczania zmiennych w taki sposób, aby każda z nich była liczona minimalną liczbę razy. W tym celu buduje się graf zależności pomiędzy zmiennymi ustalający, która zmienna korzysta z której. Mając taki graf można bardzo łatwo wyznaczyć kolejność ewaluacji zmiennych.

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 28 październik 2004 Graf zależności między zmiennymi młodszyŻyjącyKuzyn żyjącyKuzyn kuzynprzodekkto Start Stop Dla tego grafu wyraźnie widać optymalną kolejność obliczania zmiennych. W ogólnym przypadku problem może być nietrywialny. Szczęśliwie, tego rodzaju ogólny przypadek istnieje prawie wyłącznie w urojeniach pseudo-teoretyków.

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 29 październik 2004 Zbieżność układu równań stałopunktowych Można bez trudu podać taki układ równań, który nigdy nie osiągnie punktu stałego, tj. będzie w istocie nieskończoną pętlą. Co więcej, niektóre operatory są w tym względzie niebezpieczne, tj. nie dają gwarancji, że układ równań się nie zapętli. Powszechnie znanym takim operatorem jest operator negacji. Umotywował on wielu specjalistów z zakresu programowania w logice do specjalnych badań (owocujących w dalsze pojęcia, takie jak stratyfikacja). Negacja jest jednak tylko jednym z wielu operatorów powodujących, że układ równań może nie być zbieżny do punktu stałego. Przykładowo, to samo może spowodować funkcja sinus lub operator minus. Koncentrowanie się logików na operatorze negacji przypomina pieczołowite łatanie jednej dziury w przeciekającym dachu, w którym jest tysiąc dziur. Jest bardzo wątpliwe, że ten problem nie doczeka się skutecznego środka teoretycznego, wobec czego pozostaje tylko środek klasyczny, czyli testowanie.

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 1, Folia 30 październik 2004 Podsumowanie Rekurencyjne lub sieciowe struktury danych wymagają specjalnych operatorów w językach zapytań. Klasyczne operatory są niewystarczające. Komercyjne systemy oferują rozszerzenia SQL o specjalne klauzule lub operatory. Mają jednak niewystarczająca moc i są trudne w użyciu. Paradygmat dedukcyjnych baz danych proponuje środki oparte na programowaniu w logice. Są one jednak z wielu względów wadliwe. W SBQL przewidziano dwa środki: tranzytywne domknięcia (operator niealgebraiczny close by) oraz równania stałopunktowe. Oba te środki są dość łatwe w implementacji i użyciu. SBQL oferuje także procedury, metody, funkcje i perspektywy, które również mogą być rekurencyjne i użyte do programowania zadań rekurencyjnych. Wiele zadań rekurencyjnych może być także rozwiązana poprzez zamianę rekurencji na iterację. Programy stają się jednak przez to znacznie dłuższe, mniej czytelne i trudniejsze do zmian.