2018 ZV tételek kidolgozások

This commit is contained in:
TMD44
2021-06-13 13:29:22 +02:00
parent fdf04680b1
commit 5c037b86c8
479 changed files with 12744 additions and 7 deletions

291
.gitignore vendored Normal file
View File

@@ -0,0 +1,291 @@
__latexindent_temp.*
## Core latex/pdflatex auxiliary files:
*.aux
*.lof
*.log
*.lot
*.fls
*.out
*.toc
*.fmt
*.fot
*.cb
*.cb2
.*.lb
## Intermediate documents:
*.dvi
*.xdv
*-converted-to.*
# these rules might exclude image files for figures etc.
# *.ps
# *.eps
# *.pdf
## Generated if empty string is given at "Please type another file name for output:"
.pdf
## Bibliography auxiliary files (bibtex/biblatex/biber):
*.bbl
*.bcf
*.blg
*-blx.aux
*-blx.bib
*.run.xml
## Build tool auxiliary files:
*.fdb_latexmk
*.synctex
*.synctex(busy)
*.synctex.gz
*.synctex.gz(busy)
*.pdfsync
## Build tool directories for auxiliary files
# latexrun
latex.out/
## Auxiliary and intermediate files from other packages:
# algorithms
*.alg
*.loa
# achemso
acs-*.bib
# amsthm
*.thm
# beamer
*.nav
*.pre
*.snm
*.vrb
# changes
*.soc
# comment
*.cut
# cprotect
*.cpt
# elsarticle (documentclass of Elsevier journals)
*.spl
# endnotes
*.ent
# fixme
*.lox
# feynmf/feynmp
*.mf
*.mp
*.t[1-9]
*.t[1-9][0-9]
*.tfm
#(r)(e)ledmac/(r)(e)ledpar
*.end
*.?end
*.[1-9]
*.[1-9][0-9]
*.[1-9][0-9][0-9]
*.[1-9]R
*.[1-9][0-9]R
*.[1-9][0-9][0-9]R
*.eledsec[1-9]
*.eledsec[1-9]R
*.eledsec[1-9][0-9]
*.eledsec[1-9][0-9]R
*.eledsec[1-9][0-9][0-9]
*.eledsec[1-9][0-9][0-9]R
# glossaries
*.acn
*.acr
*.glg
*.glo
*.gls
*.glsdefs
*.lzo
*.lzs
# uncomment this for glossaries-extra (will ignore makeindex's style files!)
# *.ist
# gnuplottex
*-gnuplottex-*
# gregoriotex
*.gaux
*.glog
*.gtex
# htlatex
*.4ct
*.4tc
*.idv
*.lg
*.trc
*.xref
# hyperref
*.brf
# knitr
*-concordance.tex
# TODO Uncomment the next line if you use knitr and want to ignore its generated tikz files
*.tikz
*-tikzDictionary
# listings
*.lol
# luatexja-ruby
*.ltjruby
# makeidx
*.idx
*.ilg
*.ind
*.ist
# minitoc
*.maf
*.mlf
*.mlt
*.mtc[0-9]*
*.slf[0-9]*
*.slt[0-9]*
*.stc[0-9]*
# minted
_minted*
*.pyg
# morewrites
*.mw
# newpax
*.newpax
# nomencl
*.nlg
*.nlo
*.nls
# pax
*.pax
# pdfpcnotes
*.pdfpc
# sagetex
*.sagetex.sage
*.sagetex.py
*.sagetex.scmd
# scrwfile
*.wrt
# sympy
*.sout
*.sympy
sympy-plots-for-*.tex/
# pdfcomment
*.upa
*.upb
# pythontex
*.pytxcode
pythontex-files-*/
# tcolorbox
*.listing
# thmtools
*.loe
# TikZ & PGF
*.dpth
*.md5
*.auxlock
# todonotes
*.tdo
# vhistory
*.hst
*.ver
# easy-todo
*.lod
# xcolor
*.xcp
# xmpincl
*.xmpi
# xindy
*.xdy
# xypic precompiled matrices and outlines
*.xyc
*.xyd
# endfloat
*.ttt
*.fff
# Latexian
TSWLatexianTemp*
## Editors:
# WinEdt
*.bak
*.sav
# Texpad
.texpadtmp
# LyX
*.lyx~
# Kile
*.backup
# gummi
.*.swp
# KBibTeX
*~[0-9]*
# TeXnicCenter
*.tps
# auto folder when using emacs and auctex
./auto/*
*.el
# expex forward references with \gathertags
*-tags.tex
# standalone packages
*.sta
# Makeindex log files
*.lpz
# xwatermark package
*.xwm
# REVTeX puts footnotes in the bibliography by default, unless the nofootinbib
# option is specified. Footnotes are the stored in a file with suffix Notes.bib.
# Uncomment the next line to have this generated file ignored.
#*Notes.bib

9
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,9 @@
{
"recommendations": [
"james-yu.latex-workshop",
"torn4dom4n.latex-support",
"tecosaur.latex-utilities",
"nickfode.latex-formatter",
"coenraads.bracket-pair-colorizer-2"
]
}

11
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,11 @@
{
"files.autoSave": "afterDelay",
"editor.tabSize": 4,
"editor.insertSpaces": true,
"latex-workshop.view.pdf.viewer": "tab",
"latex-workshop.latex.autoClean.run": "onBuilt",
"latex-workshop.latex.autoBuild.run": "onSave",
"[latex]": {
"editor.defaultFormatter": "James-Yu.latex-workshop"
},
}

View File

@@ -0,0 +1,165 @@
\documentclass[margin=0px]{article}
\usepackage{listings}
\usepackage[utf8]{inputenc}
\usepackage{graphicx}
\usepackage{float}
\usepackage[a4paper, margin=0.7in]{geometry}
\usepackage{amsthm}
\usepackage{amssymb}
\usepackage{amsmath}
\usepackage{fancyhdr}
\usepackage{setspace}
\onehalfspacing
\newenvironment{tetel}[1]{\paragraph{#1 \\}}{}
\pagestyle{fancy}
\lhead{\it{PTI BSc Záróvizsga tételek}}
\rhead{1. Függvények határértéke, folytonossága}
\title{\textbf{{\Large ELTE IK - Programtervező Informatikus BSc} \vspace{0.2cm} \\ {\huge Záróvizsga tételek}} \vspace{0.3cm} \\ 1. Függvények határértéke, folytonossága}
\author{}
\date{}
\begin{document}
\maketitle
\begin{tetel}{Függvények határértéke, folytonossága}
Függvények határértéke, folytonossága. Kompakt halmazon folytonos függvények tulajdonságai: Weierstrass-tétel, Bolzano-tétel. A hatványsor fogalma, Cauchy-Hadamard-tétel, analitikus függvények.
\end{tetel}
\section{Függvények határértéke}
Adott $f \in \mathbb{K}_{1} \to \mathbb{K}_{2}, a \in \mathcal{D}'_{f}$ (torlódási pont). Az $f$ függvénynek az $a$ helyen van határértéke, ha $\exists A \in \overline{\mathbb{K}}_{2}$, ahol $\overline{\mathbb{K}} = \mathbb{C} \vee \mathbb{R} \vee +\infty \vee -\infty$, amelyre tetszőleges $K(A) \subset \mathbb{K}_{2}$ környezetet is véve megadható az $a$-nak egy alkalmas $k(a) \subset \mathbb{K}_{1}$ környezete, amellyel $f[(k(a) \backslash \{a\}) \cap \mathcal{D}_{f}] \subset K(A)$ teljesül. \\
Másképp: $f(x) \in K(A), (a \neq x \in k(a) \cap \mathcal{D}_{f})$. \\
Ekkor az egyértelműen létező $A \in \overline{\mathbb{K}}_{2}$ számot vagy valamelyik végtelent az $f$ függvény $a$ helyen vett határértékének nevezzük. \\
Jelölés: $\lim\limits_{x \to a}{f(x)} = \lim\limits_{a}{f} = A$
\subsection{Torlódási pont}
$A \subset \mathbb{K}$, ekkor az $\alpha \in \overline{\mathbb{K}}$ torlódási pontja az $A$ halmaznak, ha bármely $K(\alpha)$ környezetre $(K(\alpha) \backslash \{\alpha\}) \cap A \neq \emptyset$. \\
Egyenlőtlenségekkel: $A \subset \mathbb{K}$, ekkor $\alpha \in \mathbb{K}$ szám torlódási pontja az $A$ halmaznak, ha $\forall \varepsilon > 0$ esetén $\exists x \in A$, hogy $0 < |x-\alpha| < \varepsilon$.
\subsection{Környezet}
$A \subset \mathbb{K}, a \in A, r > 0: K_{r}(a) = K(a) = \{x \in A: |x-a| < r\}$.
\subsection{Függvény}
$\emptyset \neq A, B$ halmazok, $f \subset A \times B$ reláció. Valamely $x \in A$ elemre legyen $f_{x} := \{y \in B: (x,y) \in f\}$. $f$ reláció függvény, ha $\forall x \in A$-ra az $f_{x}$ halmaz legfeljebb egy elemű.
\section{Függvények folytonossága}
Az $f \in \mathbb{K}_{1} \to \mathbb{K}_{2}$ függvény az $a \in \mathcal{D}_{f}$ pontban folytonos, ha $\forall \varepsilon > 0$ számhoz megadható olyan $\delta > 0$ szám, amellyel bármely $x \in \mathcal{D}_{f}, |x-a| < \delta$ esetén $|f(x)-f(a)| < \varepsilon$. \\
Jelölés: $f \in \mathcal{C}\{a\}$, ha $\forall x \in \mathcal{D}_{f} : f \in \mathcal{C}\{x\}$, akkor $f \in \mathcal{C}$.
\section{Összefüggés határérték és folytonosság között}
Legyen $f \in \mathbb{K}_{1} \to \mathbb{K}_{2}, a \in \mathcal{D}_{f} \cap \mathcal{D}'_{f}$. Ekkor $f \in \mathcal{C}\{a\} \iff \lim\limits_{a}{f} = f(a)$.
\section{Fogalmak}
\subsection{Kompakt halmaz}
$A \subset \mathbb{K}$ kompakt, ha bármely $(x_{n}): \mathbb{N} \to A$ sorozatnak van olyan $(x_{\nu_{n}})$ részsorozata, amely konvergens és $\lim{(x_{\nu_{n}})} \in A$. \\
Ekkor $A$ korlátos és zárt.
\subsection{Konvergens}
Egy $x = (x_{n}) : \mathbb{N} \to \mathbb{K}$ számsorozatot konvergensnek nevezünk, ha $\exists \alpha \in \mathbb{K}, \forall \varepsilon > 0, \exists N \in \mathbb{N}, \forall n \in \mathbb{N}, n > N : |x_{n}-\alpha| < \varepsilon$. \\
$\alpha$ az $x$ sorozat határértéke.
\subsection{Korlátos}
Sorozatra: $x_{n}$ korlátos $\Rightarrow \exists \nu : x \circ \nu$ konvergens \\
Halmazra: $\emptyset \neq A \subset \mathbb{K}$ korlátos, ha $\exists q \in \mathbb{R} : |x| \leq q, (x \in A)$
\subsection{Zárt halmaz}
Komplementere nyílt halmaz.
\subsection{Nyílt halmaz}
$A$ nyílt halmaz $\iff \forall a \in A, \exists K(a): K(a) \subset A$, vagyis az $A$ halmaz minden pontja belső pont.
\section{Heine-tétel {\large (opcionális)}}
Ha az $f \in \mathbb{K}_{1} \to \mathbb{K}_{2}$ függvény folytonos és $\mathcal{D}_{f}$ kompakt, akkor $f$ egyenletesen folytonos.
\subsection{Egyenletesen folytonos}
$f \in \mathbb{K}_{1} \to \mathbb{K}_{2}$ függvény egyenletesen folytonos, ha $\forall \varepsilon > 0, \exists \delta > 0 : |f(x)-f(t)| < \varepsilon, (x,t \in \mathcal{D}_{f}, |x-t| < \delta)$.
\section{Weierstrass-tétel}
Tegyük fel, hogy az $f \in \mathbb{K} \to \mathbb{R}$ függvény folytonos és $\mathcal{D}_{f}$ kompakt. Ekkor az $\mathcal{R}_{f}$ értékkészletnek van legnagyobb és legkisebb eleme $(\exists \max{\mathcal{R}_{f}}, \exists \min{\mathcal{R}_{f}})$.
\section{Bolzano-tétel}
Tegyük fel, hogy valamely $-\infty < a < b < +\infty$ esetén az $f:[a,b] \to \mathbb{R}$ függvény folytonos, és $f(a) \cdot f(b) < 0$ (ellenkező előjelű). \\
Ekkor van olyan $\xi \in (a,b)$, amelyre $f(\xi) = 0$.
\section{A hatványsor fogalma}
Legyen adott az $a \in \mathbb{K}$ középpont és az $(a_{n}): \mathbb{N} \to \mathbb{K}$ együttható-sorozat, továbbá ezek segítségével tekintsük az alábbi függvényeket: $f_{n}(t) := a_{n}(t-a)^{n}, (t \in \mathcal{D} := \mathbb{K}, n \in \mathbb{N})$. Ekkor a $\sum{(f_{n})}$ függvénysort hatványsornak nevezzük.
\subsection{Sorozat}
Az $f$ függvényt sorozatnak nevezzük, ha $\mathcal{D}_{f} = \mathbb{N}$.
\subsection{Függvénysorozat, függvénysor}
$(f_{n})$ sorozat függvénysorozat, ha $\forall n \in \mathbb{N}$ esetén $f_{n}$ függvény, és valamilyen $\mathcal{D} \neq \emptyset$ halmazzal $\mathcal{D}_{f_{n}} = \mathcal{D}, (n \in \mathbb{N})$. \\
Ha a szóban forgó $(f_{n})$ függvénysorozatra $\mathcal{R}_{f_{n}} \subset \mathbb{K}, (n \in \mathbb{N})$ is igaz, akkor az $(f_{n})$ függvénysorozat által meghatározott $\sum{(f_{n})}$ függvénysor a következő függvénysorozat: $\sum{(f_{n})} := (\sum\limits_{k=0}^{n}{f_{k}})$.
\section{Cauchy--Hadamard-tétel}
Tegyük fel, hogy az $(a_{n}) : \mathbb{N} \to \mathbb{K}$ sorozat esetén létezik a $\lim{(\sqrt[n]{|a_{n}|})}$ határérték, és legyen
$$ r := \left\{\begin{array} {lr}
+\infty & ha \lim{(\sqrt[n]{|a_{n}|})} = 0 \\
\dfrac{1}{\lim{(\sqrt[n]{|a_{n}|})}} & ha \lim{(\sqrt[n]{|a_{n}|})} > 0
\end{array}\right.$$
$r$-t a konvergenciasugárnak nevezzük.
Ekkor bármely $a \in \mathbb{K}$ mellett a $\sum{(a_{n}(t-a)^{n})}$ hatványsorról a következőket mondhatjuk:
\begin{enumerate}
\item Ha $r > 0$, akkor minden $x \in \mathbb{K}, |x-a| < r$ helyen a $\sum{(a_{n}(t-a)^{n})}$ hatványsor az $x$ helyen abszolút konvergens.
\item Ha $r < +\infty$, akkor tetszőleges $x \in \mathbb{K}, |x-a| > r$ mellett a $\sum{(a_{n}(t-a)^{n})}$ hatványsor az $x$ helyen divergens.
\end{enumerate}
\subsection{Abszolút konvergens}
A $\sum\limits_{n=1}^{\infty}{a_{n}}$ végtelen sort abszolút konvergensnek nevezzük, ha a $\sum\limits_{n=1}^{\infty}{|a_{n}|}$ sor konvergens.
\subsection{Divergens}
Ha a $\lim\limits_{n \to \infty}{a_{n}}$ nem létezik, vagy nem véges, akkor a $\sum{a_{n}}$ végtelen sor divergens.
\subsection{Cauchy--Hadamard-tételből következik}
\begin{enumerate}
\item Ha $r = +\infty$, akkor $\mathcal{D}_{0} = \mathbb{K}$, és $\forall x \in \mathbb{K}$-ra a hatványsor abszolút konvergens.
\item Ha $r = 0$, akkor $\mathcal{D}_{0} = \{a\}$ és $\sum\limits_{n=0}^{\infty}{a_{n}(a-a)^{n}} = a_{0}$.
\item Ha $0 < r < +\infty$, akkor $K_{r}(a) \subset \mathcal{D}_{0} \subset G_{r}(a) = \{x \in \mathbb{K} : |x-a| \leq r\}$ és a $K_{r}(a)$ környezet $\forall x$ pontjára a hatványsor az $x$ helyen abszolút konvergens.
\item Ha $r > 0$, akkor tetszőleges $0 \leq \rho < r$ számhoz válasszuk az $x \in K_{r}(a)$ elemet úgy, hogy $|x-a| = \rho$. Ekkor $\sum\limits_{n=0}^{\infty}{|a_{n}(x-a)^{n}|} = \sum\limits_{n=0}^{\infty}{|a_{n}||x-a|^{n})} = \sum\limits_{n=0}^{\infty}{|a_{n}|\rho^{n})} < +\infty$
\end{enumerate}
\section{Analitikus függvények}
Tegyük fel, hogy a $\sum{(a_{n}(t-a)^{n})}$ hatványsor $r$ konvergenciasugara (ld. C--H-tétel) nem nulla. Ekkor értelmezhetjük az alábbi függvényt: $f(x) := \sum\limits_{n=0}^{\infty}{a_{n}(x-a)^{n}}, (x \in K_{r}(a))$, ami nem más, mint a $\sum{(a_{n}(t-a)^{n})}$ függvénysor $F(x) := \sum\limits_{n=0}^{\infty}{a_{n}(x-a)^{n}}, (x \in \mathcal{D}_{0})$ összegfüggvényének a leszűkítése a $K_{r}(a)$ környezetre: $f = F|_{K_{r}(a)}$, ($f$ a hatványsor összegfüggvénye). Az ilyen szerkezetű $f$ függvényt analitikusnak nevezzük. \\
Megjegyzés: $\mathcal{D}_{0}$ a $\sum{(a_{n}(t-a)^{n})}$ hatványsor konvergenciatartományát jelöli.
\subsection{Fontos analitikus függvények}
Olyan $a_{n}$-ek, amire $\lim{(\sqrt[n]{|a_{n}|})} = 0$, tehát $r = +\infty$ a $\sum{(a_{n}t^{n})}$ hatványsorok esetén. \vspace{0.3cm} \\
Ezek az $a_{n}$-ek: $\dfrac{1}{n!}, \dfrac{(-1)^n}{(2n+1)!}, \dfrac{(-1)^n}{(2n)!}, \dfrac{1}{(2n+1)!}, \dfrac{1}{(2n)!}$.
\begin{itemize}
\item $\exp{x} := \exp{(x)} = e^{x} = \sum\limits_{n=0}^{\infty}{\dfrac{x^n}{n!}, (x \in \mathbb{K})}$
\item $\sin{x} := \sin{(x)} = \sum\limits_{n=0}^{\infty}{(-1)^n\dfrac{x^{2n+1}}{(2n+1)!}, (x \in \mathbb{K})}$
\item $\cos{x} := \cos{(x)} = \sum\limits_{n=0}^{\infty}{(-1)^n\dfrac{x^{2n}}{(2n)!}, (x \in \mathbb{K})}$
\item $\sinh{x} := \sinh{(x)} = \sum\limits_{n=0}^{\infty}{\dfrac{x^{2n+1}}{(2n+1)!}, (x \in \mathbb{K})}$
\item $\cosh{x} := \cosh{(x)} = \sum\limits_{n=0}^{\infty}{\dfrac{x^{2n}}{(2n)!}, (x \in \mathbb{K})}$
\end{itemize}
\end{document}

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -0,0 +1,388 @@
\documentclass[margin=0px]{article}
\usepackage{listings}
\usepackage[utf8]{inputenc}
\usepackage{graphicx}
\usepackage{float}
\usepackage[a4paper, margin=0.7in]{geometry}
\usepackage{amsthm}
\usepackage{fancyhdr}
\usepackage{setspace}
\onehalfspacing
\renewcommand{\figurename}{ábra}
\newenvironment{tetel}[1]{\paragraph{#1 \\}}{}
\pagestyle{fancy}
\lhead{\it{PTI BSc Záróvizsga tételek}}
\rhead{11. Objektumelvű programozási nyelvek}
\title{\textbf{{\Large ELTE IK - Programtervező Informatikus BSc} \vspace{0.2cm} \\ {\huge Záróvizsga tételek}} \vspace{0.3cm} \\ 11. Objektumelvű programozási nyelvek}
\author{}
\date{}
\begin{document}
\maketitle
\begin{tetel}{Objektumelvű programozási nyelvek}
Osztály és objektum. Egységbe zárás, tagok, konstruktorok. Információ elrejtése. Túlterhelés. Memóriakezelés, szemétgyűjtés. Öröklődés, többszörös öröklődés. Altípusosság. Statikus és dinamikus típus, típusellenőrzés. Felüldefiniálás, dinamikus kötés. Generikusok. Altípusos és parametrikus polimorfizmus. Objektumok összehasonlítása és másolása.
\end{tetel}
\section{Osztály és objektum}
Az osztály egy felhasználói típus, amelynek alapján példányok (objektumok)
hozhatók létre. Az osztály alapvetően attribútum és metódus (művelet) definíciókat
tartalmaz. Az osztály írja le az objektum típusát: megadja a tulajdonságait és azok
lehetséges értékeit (azaz a típusértékeket), valamint az objektumon végrehajtható műveleteket (típusműveletek).\\
\noindent Példa C++-ban:
\begin{verbatim}
//definition of Point
class Point {
private:
int xCoord;
int yCoord;
public:
//constructor
Point(int xCoord, int yCoord) : xCoord(xCoord),yCoord(yCoord) {}
void Translate(int dx, int dy) {
xCoord+=dx;
yCoord+=dy;
}
void Translate(Point delta) {
xCoord+=delta.xCoord;
yCoord+=delta.yCoord;
}
int getX() { return xCoord; }
int getY() { return yCoord; }
};
int main(int argc, char* argv[])
{
Point point(0,0);
point.Translate(5,-2);
cout<<point.getX()<<","<<point.getY()<<endl; //5,-2
Point delta(-2,1);
point.Translate(delta);
cout<<point.getX()<<","<<point.getY()<<endl; //3,-1
return 0;
}
\end{verbatim}
Megjegyzés: A nem objektum-orientált nyelvekben nincsenek osztályok, pl. régebbi nyelvekben, mint a C, ADA, Pascal, vagy
funkcionális nyelvekben (Haskell, Clean, stb.).
\section{Egységbe zárás}
Az egységbe zárás azt fejezi ki, hogy az összetartozó adatok és függvények, eljárások együtt vannak, egy egységbe tartoznak. További fontos fogalom az adatelrejtés, ami azt jelenti, hogy kívülről csak az férhető hozzá közvetlenül, amit az objektum osztálya megenged. Ez fontos ahhoz, hogy megelőzze a nem kívánt kapcsolatok kialakulását, megkönnyítse a kód értelmezését, és elkerülje az adatok ellenőrizetlen terjedését (lásd objektumtobzódás).
Ha az objektum, illetve osztály elrejti az összes adattagját, és csak bizonyos metódusokon keresztül férhetnek hozzá a kliensek, akkor az egységbe zárás az absztrakciót és információelrejtés erős formáját valósítja meg. Egyes nyelvek, mint a Java vagy a C++, C\# ezt ki is kényszerítik (public: nyilvános, private: csak az adott osztályú objektumok számára, protected: csak az adott osztály, vagy leszármazott osztályok példányai számára), míg mások, mint a Python nem, itt csak konvenciókkal valósítható meg hasonló (kérlek ne piszkáld közvetlenül azt, aminek aláhúzással kezdődik a neve). A Java és a C\# ismeri a csomagnyilvánosságot is, ez Javában alapértelmezett. Ezeket a jellemzőket adattagokhoz és metódusokhoz is hozzá lehet rendelni.
Az adatelrejtés támogatja a refaktorálást, azaz az osztály belső reprezentációja szabadabban átírható, a klienseket ez nem érinti, egészen addig, amíg a meglévő publikus metódusokat ugyanazzal a paraméterezéssel hívhatják. Továbbá bátorítja a programozókat, hogy egy helyre tegyék az összetartozó adatokat és az őket feldolgozó függvényeket, eljárásokat, amely szerveződést a programozó társai is megérthetnek. A kapcsolatok lazítását is megkönnyíti.
\section{Konstruktor, destruktor}
\subsection{Konstruktor}
A konstruktor az objektumok inicializáló eljárása, akkor fut le, ha egy osztályból új objektumot példányosítunk. Alapértelmezett konstruktor alatt a paraméter nélküli konstruktort értjük, a legtöbb programozási nyelv esetén ezt a fordítóprogram automatikusan generálja üres törzzsel, amennyiben nem lett megadva egy konstruktor sem egy osztályban.
Többek között a konstruktorban szokás gondoskodni arról, hogy az objektum dinamikus élettartamú változói számára tárhelyet foglaljunk.
\subsection{Destruktor}
A destruktor a konstruktor ellentétes párja, ez az eljárás az objektumok felszabadításakor fut le. Meghívása automatikusan megtörténik, attól függetlenül, hogy az objektum felszabadítása automatikusan történik a hatókör végeztével (lokális objektumok esetén), manuálisan a programozó által (dinamikus élettartamú objektumok esetén) vagy a szemétgyűjtő által (szintén dinamikus élettartamú objektumok esetén).
A desktruktorban szokás többek között az objektum dinamikus helyfoglalású adattagjait és a lefoglalt erőforrásokat felszabadítani.
\section{Információ elrejtése}
Az objektum elrejti az adatait és bizonyos műveleteit. Ez azt jelenti, hogy nemtudjuk pontosan, hogy egy objektumban hogyan vannak az adatok ábrázolva, sőt aműveletek implementációit sem ismerjük. Az információk elrejtése az objektumbiztonságát szolgálja, amelyeket csak a ellenőrzött műveleteken keresztül érhetünkel.
\section{Túlterhelés és felüldefiniálás}
\subsection{Túlterhelés}
Több azonos nevű, különböző szignatúrájú függvény. A függvényhívás aktuálisparaméterei meghatározzák, hogy melyik függvény fog meghívódni. Ezt már afordításidőben eldől (statikus, fordításidejű kötés).
A túlterhelés (overloading) segítségével azonos nevű alprogramokat hozhatunk létre eltérő szignatúrával. A szignatúra a legtöbb programozási nyelvben az alprogram nevét és a formális paraméterek számát és típusát jelenti, de egyes nyelvekben (például Ada) a visszatérési érték típusa is beletartozik. A túlterhelés elsődleges felhasználási területe, hogy ugyanazt a tevékenységet különböző paraméterezéssel is elvégezhessük.
A fordító az alprogramhívásból el tudja dönteni, hogy a túlterhelt változatok közül melyiket kell meghívni. Ha egyik sem illeszkedik vagy több is illeszkedik, akkor fordítási hiba lép fel.
\subsection{Felüldefiniálás}
Egy osztályhierarchián belül az utódosztály újradefiniálja az ősosztály metódusát.(azonos név, azonos szignatúra). Ha ősosztály típusú mutatón vagy referenciánkeresztül érjük el az osztályhierarchia példányait és ezen keresztül meghívjuk afelülírt metódust, akkor futási időben dől el, hogy pontosan melyik metódus kerülmeghívásra. (dinamikus, futásidejű kötés).
\section{Objektumok másolása, összehasonlítása}
Az objektumok másolása egy speciális konstruktorral, az úgynevezett másoló konstruktorral (copy constructor) történik. Ez paraméterül az adott osztály egy példányát kapja meg, és azt a programozó által megadott működési logika szerint lemásolja az éppen inicializált objektumba.
Több programozási nyelv (például C++) fordítóprogramja automatikusan elkészít egy másoló konstruktort, ha a programozó nem definiál sajátot. Ez az alapértelmezett másoló konstruktor lemásolja a forrásobjektum összes adattagjának értékét, ezt nevezzük sekély másolatnak (shallow copy). Ha az objektum dinamikus foglalású adattagokat is tartalmaz, akkor azoknak nem az értéke, hanem csak a hivatkozása lesz lemásolva, ami általában nem a kívánt működés. Ez esetben saját másoló konstruktor írása szükséges, ami mély másolatot (deep copy) készít.
\section{Automatikus, statikus és dinamikus élettartam, szemétgyűjtés}
Élettartam: A változók élettartama alatt a program végrehajtási idejének azt a szakaszát értjük, amíg a változó számára lefoglalt tárhely a változóé.
\subsection{Automatikus élettartam}
A blokkokban deklarált lokális változók automatikus élettartamúak, ami azt jelenti, hogy a deklarációtól a tartalmazó blokk végéig tart, azaz egybeesik a hatókörrel. A helyfoglalás számukra a végrehajtási verem aktuális aktivációs rekordjában történik meg.
\subsection{Statikus élettartam}
A globális változók, illetve egyes nyelvekben a statikusként deklarált változók (például C/C++ esetén a \texttt{static} kulcsszóval) statikus élettartamúak. Az ilyen változók élettartama a program teljes végrehajtási idejére kiterjed, számukra a helyfoglalás már a fordítási időben megtörténhet.
\subsection{Dinamikus élettartam}
A dinamikus élettartamú változók esetén a programozó foglal helyet számukra a dinamikus tárterületen (heap), és a programozó feladata gondoskodni arról is, hogy ezt a tárterületet később felszabadítsa. Amennyiben utóbbiról megfeledkezik, azt nevezzük memóriaszivárgásnak (memory leak).
Mint látjuk, a dinamikus élettartam esetén a hatókör semmilyen módon nem kapcsolódik össze az élettartammal, az élettartam szűkebb vagy tágabb is lehet a hatókörnél.
\subsection{Szemétgyűjtő}
A szemétgyűjtő másik neve a hulladékgyűjtő, az angol Garbage Collector név után pedig gyakran csak GC-nek rövidítik. Feladata a dinamikus memóriakezeléshez kapcsolódó tárhelyfelszabadítás automatizálása, és a felelősség levétele a programozó válláról, így csökkentve a hibalehetőséget.
A szemétgyűjtő figyeli, hogy mely változók kerültek ki a hatókörükből, és azokat felszabadíthatóvá nyilvánítja. A módszer hátránya a számításigényessége, illetve a nemdeterminisztikussága. A szemétgyűjtő ugyanis nem szabadítja fel egyből a hatókörükből kikerült változókat, és a felszabadítás sorrendje sem ugyanaz, amilyen sorrendben a változók felszabadíthatóvá váltak.
Azt, hogy a hulladékgyűjtő mikor és mely változót szabadítja fel, egy programozási nyelvenként egyedi, összetett algoritmus határozza meg, amelyben rendszerint szerepet játszik a rendelkezésre álló memória telítettsége, illetve a felszabadításhoz szükséges becsült idő. (Például ha egy objektum rendelkezik destruktorral, akkor általában a GC később szabadítja csak fel.)
Összességében a szemétgyűjtő csak annyit garantál, hogy előbb-utóbb (legkésőbb a program futásának végeztével) minden dinamikusan allokált változót felszabadít.
Szemétgyűjtést használó nyelvek pl. Java, C\#, Ada. C/C++-ban nincs szemétgyűjtés, a programozónak kell gondoskodni a dinamikusan allokált memóriaterületek felszabadításáról.
\section{Öröklődés}
Egy osztály legegyszerűbben adattagjainak és metódusainak felsorolásával hozható létre. Azonban az objektum-orientált paradigma lehetőséget ad egy másik, hatékonyabb módszerre is, az öröklődésre. Az öröklődés az újrafelhasználhatóságot szem előtt tartva arra ad lehetőséget, hogy már meglévő (szülő-, ős-) osztályból kiindulva hozzunk létre új (gyermek-, leszármazott-, al-) osztályt. Az öröklés két osztály között fennálló olyan kapcsolat, amely során a leszármazott osztály rendelkezik a szülő osztály majdnem összes tulajdonságával (nem privát adattagjait és metódusait sajátjaként kezeli), s ezeket újabbakkal egészítheti ki. Az így létrehozott osztály is lehet más osztályok őse (kivéve pl. Java-ban a \texttt{final} kulcsszóval ellátott osztályok, ezekből már nem származtathatunk), így ezek az osztályok egy öröklési hierarchiába szerveződnek. Attól függően, hogy egy osztálynak egy- vagy több őse van, beszélünk egyszeres- ill. többszörös öröklődésről. A Java az egyszeres öröklődést támogatja, de pl. C++-ban van többszörös öröklődés.
A Java-ban az osztályhierarchia legfelső eleme az Object osztály, amelyből minden más osztály (közvetve vagy közvetlenül) származik.
Egy alosztály az örökölt metódusokat újraimplementálhatja. Ilyenkor az adott metódus ugyanolyan néven, de más, módosított (alosztályra specifikált) tartalommal kerül megvalósításra. Az ilyen metódusokat polimorfnak nevezzük. Java-ban minden olyan metódust, ami nincs ellátva a \texttt{final} kulcsszóval, újra lehet definiálni. (C++-ban mindent, ami nem privát)\\
\noindent Példák:
\begin{itemize}
\item C++:
\begin{verbatim}
class RegularPolygon
{
protected:
const double radius;
public:
RegularPolygon(double radius) : radius(radius) {}
virtual double area() = 0;
};
class EquilateralTriangle : public RegularPolygon
{
public:
EquilateralTriangle(double radius) : RegularPolygon(radius) {}
virtual double area()
{
return 0.75*sqrt(3.0)*radius*radius;
}
};
\end{verbatim}
\item Java:
\begin{verbatim}
public abstract class RegularPolygon{
protected final double radius;
public RegularPolygon(double radius){
this.radius = radius;
}
public abstract double area();
}
public class EquilateralTriangle extends RegularPolygon{
public EquilateralTriangle(double radius){
super(radius);
}
public double area(){
return 0.75*Math.sqrt(3.0)*radius*radius;
}
}
\end{verbatim}
\end{itemize}
\section{Statikus és dinamikus típus és kötés}
Nem a kliens, hanem az objektum feladata megválasztani, hogyan reagáljon egy metódushívásra. Ezt tipikusan futás időben végzi el, és a metódushívást a hozzá társított táblából választja ki. Ez dinamikus kötés néven ismert, és megkülönbözteti az objektumot az absztrakt adattípustól és a modultól, amelyek rögzített megvalósítással bírnak minden példány számára. Ha a metódus kiválasztásába beleszól a többi paraméter, akkor többszörös kötésről van szó (lásd kettős metódus, multimetódus, többszörös metódus).
A metódushívást tekintik üzenetátadásnak is, ahol a kliens a kötésben részt vevő objektumnak küld üzenetet.
\begin{itemize}
\item statikus típus: A változó deklarációjában megadott típus. Fordítás során egyértelműen eldől, nem változhat
futás során. A statikus típus határozza meg, hogy mit szabad csinálni az objektummal (pl. hogy milyen
műveletek hívhatók meg rá).
\item dinamikus típus: A változó által hivatkozott objektum típusa. Vagy a statikus típus leszármazottja, vagy maga
a statikus típus. Futás során változhat.
\end{itemize}
\noindent Példa(Java):
\begin{verbatim}
Object o = new String("Hello”);
\end{verbatim}
Itt az o változó statikus típusa \texttt{Object}, dinamikus típusa pedig \texttt{String}.\\
\noindent Kötések:
\begin{itemize}
\item statikus kötés: A változó statikus típusa szerinti adattagokra lehet hivatkozni.
\item dinamikus kötés: A változó dinamikus típusa szerinti adattagok használhatók.
\end{itemize}
A kötés akkor fontos, ha a hívott művelet, vagy a hivatkozott változó a statikus és a dinamikus típusban
különbözik, vagy esetleg a statikus típusban nem is létezik (ekkor a dinamikus típusban sem hivatkozhatunk
az adattagra).\\
\noindent Többféleképpen lehet a kötéseket meghatározni a különböző nyelvekben:
\begin{itemize}
\item Java : Minden esetben dinamikus kötés van (az örökölt metódusok törzsében is).
\item C++ : A művelet definiálásakor lehet jelezni, ha dinamikus kötést szeretnénk (\texttt{virtual}).
\item Ada : A híváskor lehet jelezni, ha dinamikus kötést szeretnénk.
\end{itemize}
\section{Generikusok}
Generikus programozás: Algoritmusok, adatszerkezetek általánosított, több típusra is működő
leprogramozása (pl. generikus rendezés, generikus verem, …). Ezt az általános kódot nevezzük sablonnak
(template).
Bizonyos nyelvekben (Ada, C++) egy sablont példányosítani kell ekkor a kívánt típusokat, objektumokat
(a sablon definíciónak megfelelően) a sablonnak paraméterként megadva példányosul a szóban forgó sablon.
(Ugyanúgy, mint pl. amikor egy függvénynek megadjuk az aktuális paraméterét.) Ezt nevezzük generatív
programozásnak: a program a megadott sablon alapján létrehoz egy "igazi” programegységet (program
generál programot).
Példa: Egy verem sablon példányosításakor megadjuk, hogy milyen típusú elemeket tároljon a verem (típus
paraméter) és hogy hány elem fér a verembe (objektum paraméter).
C++ és Ada esetén egy sablon paramétere alprogram is lehet.
Példa: Egy rendezésnek megadjuk, hogy milyen művelet alapján rendezzen.
Természetesen lehet alapértelmezett sablonparaméter is.
Egy sablon definiálása esetén természetesen a sablont nem lehet minden típusra használni. Egy sablon attól
lesz sablon, hogy több típusra is működik. Azonban megszorításokat tehetünk (és tennünk is kell) arra, hogy
milyen típusokra lehessen azt használni, hogyan lehessen a sablont példányosítani.
Jó példa erre az Ada nyelv, ahol a sablon specifikációja egy "szerződés” a sablon törzse és a példányosítás
között:
\begin{itemize}
\item A sablon törzse nem használhat mást, csak amit a sablon specifikációja megenged neki. (A törzset
nem feltétlenül kell, hogy ismerjük példányosításkor.)
\begin{verbatim}
generic
type Element_T is private;
with function "*" (X, Y: Element_T) return Element_T is <>;
function Square (X : Element_T) return Element_T;
\end{verbatim}
Itt a \texttt{with function} kezdetű sor végén az \texttt{is <>} azt jelenti, hogy ha az adott típusra már létezik *
művelet (pl. egész számokra), akkor nem kell külön megadni példányosításkor, a program automatikusan azt használja.
A törzs:
\begin{verbatim}
function Square (X: Element_T) return Element_T is
begin
return X * X; -- The formal operator "*".
end Square;
\end{verbatim}
\item A példányosításnak biztosítania kell mindent, amit a sablon specifikációja megkövetel tőle.
A következő példában a négyzetre emelő függvényt mátrixokra alkalmazzuk, feltéve, hogy definiáltuk a
mátrixszorzást.
\begin{verbatim}
with Square;
with Matrices;
procedure Matrix_Example is
function Square_Matrix is new Square
(Element_T => Matrices.Matrix_T, "*" => Matrices.Product);
A : Matrices.Matrix_T := Matrices.Identity;
begin
A := Square_Matrix (A);
end Matrix_Example;
\end{verbatim}
\end{itemize}
Például a C++-ban a sablonszerződés nem így működik. Ott a sablon specifikációja az egész
definíció (emiatt sablonosztályokat csak teljes egészében header fájlokban definiálhatunk).
Példányosításkor ezt is ismerni kell, hogy tudjuk, hogyan példányosíthatunk. Az információelrejtés
elve tehát sérül.
Más nyelvekben (pl. Java, funkcionális nyelvek) nem kell a sablonokat példányosítani mindig ugyanaz a
megírt kód hajtódik végre, csak épp az aktuális paraméterekkel. Pl. Java-ban a típusparaméter fordításkor "elveszik",
csak futási időben derül ki.
\section{Polimorfizmus}
A programozási nyelvekben és a típuselméletben a polimorfizmus egy egységes interfészre utal, amit különböző típusok valósítanak meg. Többalakúságot is jelent. A polimorf típuson végzett műveletek több különböző típus értékeire alkalmazhatók. Polimorfizmus többféleképpen is megvalósítható:
\begin{itemize}
\item {\textbf {Ad-hoc polimorfizmus:}} Egy függvénynek sok különböző implementációja van, amelyeket egyenként specifikálnak néhány különböző típus és kombinációja számára. Megvalósítható túlterheléssel.
\item {\textbf {Paraméteres polimorfizmus:}} A kódot általánosan írják meg különböző típusok számára, és alkalmazható az összes típusra, amely megfelel bizonyos, a kódban előre megadott feltételeknek. Objektumorientált környezetben sablonnak vagy generikusnak nevezik. Funkcionális programozási környezetben egyszerűen polimorfizmusnak hívják.
\item {\textbf {Altípusosság:}} A név több különböző osztály példányait jelöli, amelyeknek a függvényt deklaráló közös őse van.[3] Objektumorientált környezetben többnyire erre gondolnak, amikor polimorfizmusról beszélnek.
\end{itemize}
\subsection{Paraméteres polimorfizmus}
A parametrikus polimorfizmus jellemzője, hogy a függvényt egyszer kell megírni, és az minden típusra egységesen fog működni. A függvény paramétereinek típusát a függvény használatakor paraméterben kell megadni, innen a paraméteres név. Szokták generikusnak is hívni, az egységes viselkedés miatt. Használata a teljes típusbiztonság megőrzésével növeli a nyelv kifejezőerejét.
A paraméteres polimorfizmus nemcsak függvényekre, hanem adattípusokra is értelmezhető, tehát adattípusokra is lehetnek paraméteresek, más néven generikusok. A generikus típusok polimorfikus adattípusok néven is megtalálhatók.
A parametrikus polimorfizmus nagyon gyakori a funkcionális programozásban, emiatt gyakran csak polimorfizmusnak nevezik. Az alábbi Haskell példa egy paraméteres polimorf lista adattípust mutat be, két paraméteresen polimorf függvénnyel.
\begin{verbatim}
class List<T> {
class Node<T> {
T elem;
Node<T> next;
}
Node<T> head;
int length() { ... }
}
List<B> map(Func<A, B> f, List<A> xs) {
...
}
\end{verbatim}
Objektumorientált nyelvekben kevésbé gyakori, de legtöbbjükben szintén van lehetőség paraméteres polimorfizmusra. Ezt C++-ban és D-ben template-ek, Javában genericek biztosítják.
\subsection{Altípusosság}
Egyes nyelvekben az altípusosság használható a polimorfizmus korlátozására. Ezekben a nyelvekben az altípusosság lehetővé teszi, hogy egy függvény egy bizonyos T típusú objektumot használjon, de ha S altípusa T-nek, akkor a függvény S típusú objektumokra is használható a Liskov-féle helyettesíti elv szerint. Az altípus jelölése néha S <: T. Megfordítva, T szupertípusa S-nek, ennek jele T :> S. Az altípusos polimorfizmus rendszerint dinamikus.
A következő példában a kutya és a macska az állatok altípusa. A letsHear() eljárás állatot fogad, de altípusos objektumokkal is működik.
\begin{verbatim}
abstract class Animal {
abstract String talk();
}
class Cat extends Animal {
String talk() {
return "Meow!";
}
}
class Dog extends Animal {
String talk() {
return "Woof!";
}
}
void letsHear(final Animal a) {
println(a.talk());
}
int main() {
letsHear(new Cat());
letsHear(new Dog());
}
\end{verbatim}
A következő példában Number, Rational, és Integer típusok úgy, hogy Number :> Rational és Number :> Integer. Egy függvény, aminek paramétere Number, úgy működik Integer vagy Rational paraméterrel, mint Number paraméterrel. Az aktuális típus elrejthető a felhasználó elől, és objektumazonossággal férhető hozzá. Valójában, ha a Number típus absztrakt, akkor nem is lehetnek olyan objektumok, amelyek aktuális típusa Number. Lásd: absztrakt osztály, absztrakt adattípus. Ez a típushierarchia számtoronyként is ismert a Scheme programozási nyelvből, és rendszerint még több típusból áll.
Az objektumorientált nyelvek az altípusos polimorfizmust öröklődéssel valósítják meg. Tipikus implementációkban az osztályok tartalmaznak virtuális táblát, ami hivatkozza az osztály interfészének polimorf részét megvalósító függvényeit. Minden objektum tartalmaz egy referenciát erre a táblára, amire mindig szükség van, ha valami egy polimorf függvényt hív. Ez a mechanizmus példa a:
\begin{itemize}
\item Késői kötésre, mert a virtuális függvényhívások csak a híváskor kapcsolódnak;
\item Egyszeri küldésre, mivel a virtuális függvényhívások csak az első argumentumuk virtuális tábláját veszik figyelembe, így a többi argumentum dinamikus típusa nincs figyelembe véve.
\end{itemize}
Néhány objektumrendszer, például a Common Lisp Object System többszörös küldésre is képes, így a hívások az összes argumentumokban polimorfak lesznek.
\end{document}

Binary file not shown.

View File

@@ -0,0 +1,405 @@
\documentclass[margin=0px]{article}
\usepackage{listings}
\usepackage[utf8]{inputenc}
\usepackage{graphicx}
\usepackage{float}
\usepackage[a4paper, margin=0.7in]{geometry}
\usepackage{subcaption}
\usepackage{amsthm}
\usepackage{amssymb}
\usepackage{amsmath}
\usepackage{fancyhdr}
\usepackage{setspace}
\onehalfspacing
\renewcommand{\figurename}{ábra}
\newenvironment{tetel}[1]{\paragraph{#1 \\}}{}
\pagestyle{fancy}
\lhead{\it{PTI BSc Záróvizsga tételek}}
\rhead{12. Formális nyelvek és automaták}
\title{\textbf{{\Large ELTE IK - Programtervező Informatikus BSc} \vspace{0.2cm} \\ {\huge Záróvizsga tételek}} \vspace{0.3cm} \\ 12. Formális nyelvek és automaták}
\author{}
\date{}
\begin{document}
\maketitle
\begin{tetel}{Formális nyelvek és automaták}
Generatív grammatikák és a Chomsky-féle hierarchia. Grammatikák normálformái. Reguláris kifejezések. Véges automata. Veremautomata. Nyelvosztályok zártsági tulajdonságai. A reguláris és a környezetfüggetlen nyelvosztályok algoritmikus problémái.
\end{tetel}
\section{Formális nyelvtanok és a Chomsky-féle hierarchia}
\subsection{Alapfogalmak}
\begin{description}
\item[Ábécé, szó] \hfill \\
Szimbólumok véges nemüres halmazát ábécének nevezzük.
Egy $V$ ábécé elemeiből képzett véges sorozatokat $V$ feletti szavaknak vagy sztringeknek nevezzük. A 0 hosszúságú sorozatot üres szónak nevezzük és
$\varepsilon$-nal jelöljük.
A $V$ ábécé feletti szavak halmazát (beleértve az üres szót is) $V^*$-gal, a nemüres szavak halmazát $V^+$-szal jelöljük.
\item[Konkatenáció] \hfill \\
Az $ x = uv$ szót az $u,v \in V$ szavak konkatenációjának nevezzük.
A konkatenáció asszociatív, de (általában) nem kommutatív.
$V^*$ zárt a konkatenációra. Azaz:
\begin{align*}
u,v \in V^* \Rightarrow uv \in V^*
\end{align*}
Továbbá $\varepsilon$ egységelemnek tekinthető $V^*$-gal és a konkatenációval. Azaz:
\begin{align*}
u \in V^* \Rightarrow u\varepsilon \in V^* \textrm{, és }\varepsilon u \in V^*
\end{align*}
\item[Egyéb definíciók] \hfill
\begin{itemize}
\item $u,v \in V$. Az $u$ szót a $v$ részszavának nevezzük, ha $ v = xuy , \ (x,y \in V)$ teljesül. Ha még $xy\neq\varepsilon$, akkor $u$ valódi részszó.
\item $ v = xuy \ (x,y,u,v \in V)$. Ekkor:
\begin{itemize}
\item Ha $x=\varepsilon$, akkor $u$-t a $v$ szó prefixének nevezzük
\item Ha $y=\varepsilon$, akkor $u$-t a $v$ szó szufixének nevezzük
\end{itemize}
\item Egy $u\in V$ szó tükörképe alatt a szimbólumai fordított sorrendben való felírását értjük. (Jele: $u^{-1}$)
\end{itemize}
\end{description}
\subsection{Formális nyelvtanok}
\begin{description}
\item[Nyelv] \hfill \\
Ha $L \subset V^*$, akkor $L$-et $V$ feletti nyelvnek tekintjük.
Az üres nyelv (egy szót sem tartalmaz) jele: $\emptyset$
$L$ nyelv véges nyelv, ha véges számú szót tartalmaz, különben végtelen nyelv.
Nyelvekre vonatkozó műveletek:
\begin{itemize}
\item $ L_1 \cup L_2 = \{u | \ u \in L_1 $ vagy $ u \in L_2\}$ : az $L_1$ és $L_2$ nyelv uniója
\item $ L_1 \cap L_2 = \{u | \ u \in L_1 $ és $ u \in L_2\}$ : az $L_1$ és $L_2$ nyelv metszete
\item $ L_1 - L_2 = \{u | \ u \in L_1 $ és $ u \notin L_2\}$ : az $L_1$ és $L_2$ nyelv különbsége
\item $\overline{L} = V^* - L$ : az $L \subseteq V^*$ komplementere
\item $L_1L_2 = \{u_1u_2 | \ u_1 \in L_1, u_2 \in L_2\}$ : az $L_1$ és $L_2$ nyelv konkatenációja\\
Minden nyelvre fennáll: $\emptyset L = L \emptyset = \emptyset$ illetve $\{\varepsilon\}L = L\{\varepsilon\} = L$
\item $L^i$ : az $L$ nyelv $i$-edik ($i \geq 1$) iterációja (a konkatenációra nézve), és $L^0 = \{\varepsilon\}$
\item $ L^* = \bigcup\limits_{i\geq1} L^i$ : az $L$ nyelv iteratív lezártja
\end{itemize}
Az unió, konkatenáció és iteráció lezárása műveleteket reguláris művelteknek nevezzük.
\item[Grammatika] \hfill \\
Nyelvek sokféle módon előállíthatók. A produkciós rendszerekkel való előállítás egyik módja a nyelvek generálása grammatikával.
A $G$ generatív grammatikán egy $(N,T,P,S)$ négyest értünk, ahol:
\begin{itemize}
\item $N$ és $T$ diszjunkt ábécék, a nemterminális ($N$) és terminális ($T$) szimbólumok ábécéi.
\item $S\in N$ a kezdőszimbólum.
\item $P$ az $(x,y)$ rendezett párok halmaza, ahol $x,y \in (N \cup T)^*$ és $x$ legalább egy nemterminális szimbólumot tartalmaz. \\
A $P$ halmaz elemeit átírási szabályoknak nevezzük.
\end{itemize}
Az $(x,y)$ jelölés helyett az $x \rightarrow y$ jelölést alkalmazzuk. (Ha $\rightarrow \notin (N\cup T)$ )
\item[Levezetés] \hfill \\
$ G = (N,T,P,S) $, és $u,v \in (N\cup T)^*$. A $v$ szó közvelenül (egy lépésben) levezethető $u$ szóból $G$-ben, ha
\begin{align*}
u = u_1xu_2, \ v = u_1yu_2 \ \textrm{és} \ x \rightarrow y \in P \quad (u_1, u_2 \in (N \cup T)^*)
\end{align*}
Ezt $ u \Longrightarrow_G v$ jelöljük.
Azt mondjuk, hogy a $v$ szó $k \ (\geq 1)$ lépésben levezethető az $u$ szóból $G$-ben, ha
\begin{align*}
\exists u_1, ... , u_{k+1} \in (N\cup T)^*: u = u_1, v = u_{k+1} \ \textrm{és} \ u_i \Longrightarrow_G u_{i+1} \quad (1 \leq i \leq k)
\end{align*}
A $v$ szó levezethető az $u$ szóból G-ben, ha $u=v$ vagy $\exists k \geq 1$ szám, hogy $v$ $k$ lépésben levezethető $u$-ból.\\
Másképp: A $v$ szó levezethető az $u$ szóból G-ben (jele: $ u \Longrightarrow_G^* v $), ha $u=v$ vagy $\exists z \in (N\cup T)^*$ szó, hogy $ u \Longrightarrow_G^* z $ és $ z \Longrightarrow_G v $
\item[Generált nyelv] \hfill \\
$L(G)$ a $G=(N,T,P,S)$ grammatika által generált nyelv, ha:
\begin{align*}
L(G) = \{w | \ S \Longrightarrow_G^* w, w \in T^*\}
\end{align*}
\end{description}
\subsection{Chomsky-féle hierarchia}
$G = (N,T,P,S)$ generatív grammatika $i$-típusú ($i=0,1,2,3$), ha $P$ szabályhalmazára a következők teljesülnek:
\begin{description}
\item[Mondatszerkezetű grammatika (i=0)] \hfill \\
Nincs korlátozás
\item[Környezetfüggő grammatika (i=1)] \hfill \\
$P$ minden szabálya $u_1Au_2 \rightarrow u_1vu_2$ alakú, ahol, $A\in N$ és $ v \neq \varepsilon $, ($u_1,u_2, v \in (N \cup T)^*$).
Kivéve az $S \rightarrow \varepsilon$ szabályt (ha létezik). Ekkor $S$ nem fordul elő egyetlen szabály jobboldalán sem.
\item[Környezetfüggetlen grammatika (i=2)] \hfill \\
$P$ minden szabálya $A \rightarrow v$ alakú, ahol, $A\in N, v \in (N \cup T)^*$.
\item[Reguláris grammatika (i=3)] \hfill \\
$P$ minden szabálya $A \rightarrow vB$ vagy $A \rightarrow v$ alakú, ahol, $A,B\in N, v \in T^*$.
\end{description}
\noindent
$L$ nyelv $i$-típusú, ha $i$-típusú grammatikával generálható. Az $i$-típusú nyelvek osztályát $\mathcal{L}_i$ jelöljük.
\noindent
Az $i$-típusú nyelvosztályok a következő tulajdonságokkal rendelkeznek:
\begin{itemize}
\item $ \mathcal{L}_3 \subset \mathcal{L}_2 \subset \mathcal{L}_1 \subset \mathcal{L}_0 $
\item Az $\mathcal{L}_i \ (i=0,1,2,3)$ nyelvosztályok mindegyike zárt a reguláris műveletekre.
\end{itemize}
\section{Automaták}
Formális nyelvek megadása nemcsak generatív, hanem felismerő eszközökkel is lehetséges, azaz olyan számítási eszközök segítségével, amelyek szavak feldolgozására és azonosítására alkalmasak.
Ilyen eszköz például az automata, amely egy szó, mint input hatására kétféleképpen viselkedhet: vagy elfogadja, vagy elutasítja.
\subsection{Véges Automata}
\begin{description}
\item[Definíció] \hfill \\
A véges automata egy rendezett ötös,
\[A=(Q,T,\delta,q_0, F)\]
ahol:
\begin{itemize}
\item Q - állapotok véges nemüres halmaza
\item T - input szimbólumok ábécéje
\item $\delta : Q \times T \rightarrow Q$ - állapot-átementi függvény
\item $q_0 \in Q$ - kezdőállapot
\item $F \subseteq Q$ - elfogadó állapotok halmaza
\end{itemize}
Működés:\\
A véges automata diszkrét időintervallumokban végrehajtott lépések sorozata által működik. Minden egyes lépés során az automata elolvassa a következő input szimbólumot és átmegy egy olyan állapotba, amelyet az állapotátmeneti függvény meghatároz (az aktuális állapot és input szimbólum alapján).
Kezdetben az $A$ véges automata a $q_0$ kezdőállapotban van és az olvasófej az input szalagon levő $u \in T^*$ szó első betűjét dolgozza fel. Ezután a véges automata lépések sorozatát végrehajtva elolvassa az input $u$ szót; betűről betűre haladva olvas és új állapotba kerül.
Miután az $u$ input szó utolsó betűjét is elolvasta a véges automata, vagy $q \in F,$ azaz elfogadó állapotba kerül, és akkor az $u$ szót az automata elfogadja, vagy az új állapot nem lesz eleme $F$-nek, és ekkor az automata a szót nem fogadja el.
\item[VDA - Véges determinisztikus automata] \hfill \\
A $\delta$ függvény egyértékű, ezért minden egyes $(q, a)$ párra, ahol $(q, a) \in Q \times T$ egyetlen olyan $s$ állapot létezik, amelyre $\delta(q, a) = s$ teljesül. Ezért ezt a véges automatát determinisztikusnak nevezzük.
\item[VNDA - Véges nemdeterminisztikus automata] \hfill \\
Ha többértékű állapot-átmeneti függvényt is megengedünk, azaz $\delta : Q \times T \rightarrow 2^Q$, akkor nemdeterminisztikus véges automatáról beszélünk. (Ebben az esetben aktuális állapotnak egy állapothalmaz valamely elemét, mintsem egyetlen állapotot tekinthetünk.)
Ez azt jelenti, hogy a kezdeti állapot helyettesíthető egy $Q_0 \subseteq Q$ kezdőállapot halmazzal.
(És az is előfordulhat, hogy egy a input szimbólum esetén $\delta(q, a)$ üres az aktuális állapotok mindegyikére.)
\item[Tulajdonságok] \hfill \\
Az állapot-átmeneteket
\[qa \rightarrow p\]
alakú szabályok formájában is írhatjuk $p \in \delta(q, a) $ esetén. Jelöljük $M_\delta$-val az $A = (Q, T, \delta,Q_0, F)$ nemdeterminisztikus véges automata $\delta$ állapot-átmenet függvénye által az előbbi módon származó szabályok halmazát.
Ha minden egyes $(q, a)$ párra egyetlen $qa \rightarrow p$ szabály van $M_\delta$-ban, akkor a véges automata determinisztikus, egyébként nemdeterminisztikus.
\begin{itemize}
\item Közvetlen redukció: \\
Legyen $A = (Q, T, \delta, q_0, F)$ egy véges automata és legyenek $u, v \in QT^*$ szavak. Azt mondjuk, hogy az $A$ automata az $u$ szót a $v$ szóra redukálja egy lépésben/közvetlenül. Ha van olyan $qa \rightarrow p$ szabály $M_\delta$-ban, és van olyan $w \in T^*$ szó, amelyre $u = qaw$ és $v = pw$ teljesül.
\item Redukció:\\
Az $A = (Q, T, \delta, q_0, F)$ véges automata az $u \in QT^*$ szót a $v \in QT^*$ szóra redukálja $(u \Longrightarrow_A^* v)$, ha $u = v$, vagy $ \exists z \in QT^*$, amelyre $u \Longrightarrow_A^* z$ és $z \Longrightarrow_A v$ teljesül.
\item Az automata által elfogadott nyelv:\\
Az $A = (Q, T, \delta, q_0, F)$ véges automata által elfogadott/felismert nyelv alatt az \[ L(A) = \{u \in T^* | \ q_0u \Longrightarrow_A^* p, \quad q_0 \in Q_0 \textrm{ és } p \in F\} \] szavak halmazát értjük. (Az üres szó, akkor és csak akkor van benne az automata által elfogadott $L(A)$ nyelvben, ha $Q_0 \cap F \neq \emptyset$).
\item Tétel:\\
Minden $A$ nemdeterminisztikus véges automatához meg tudunk adni egy 3-típusú $G$ grammatikát úgy, hogy $L(G) = L(A)$ teljesül.
\item Tétel: \\
Minden 3-típusú G grammatikához meg tudunk adni egy $A$ véges automatát úgy, hogy $L(A) = L(G)$ teljesül. \\
Ezek után fenáll a kérdés: Létezik-e olyan reguláris nyelv, amely VNDA-val felismerhető, de nem ismerhető fel VDA-val? \\
Válasz: Nincs.
\item Tétel:\\
Minden $A = (Q, T, \delta,Q_0, F)$ VNDA-hoz meg tudunk konstruálni egy $A' = (Q', T, \delta', q_0', F')$ VDA-t úgy, hogy $L(A) = L(A')$ teljesül.
\end{itemize}
\end{description}
\subsection{Veremautomata}
\begin{description}
\item[Definíció] \hfill \\
A veremautomata egy rendezett hetes
\[A = (Z,Q, T, \delta, z_0, q_0, F)\]
ahol
\begin{itemize}
\item Z - a veremszimbólumok véges halmaza,
\item Q - az állapotok véges halmaza,
\item T - az inputszimbólumok véges halmaza,
\item $\delta : Z \times Q \times (T \cup \{\varepsilon\}) \rightarrow 2^{Z^* \times Q}$ - átmeneti függvény
\item $z_0 \in Z $ - a kezdeti veremszimbólum,
\item $q_0 \in Q $ - a kezdeti állapot,
\item $F \subseteq Q$ - az elfogadó állapotok halmaza
\end{itemize}
A veremautomata konfigurációja alatt egy $uq$ alakú szót értünk, ahol $u \in Z^*$ a verem aktuális tartalma és $q \in Q$ az aktuális állapot. \\
A kezdeti konfiguráció $z_0q_0$.
Működés: \\
Tegyük fel, hogy az $A$ veremautomata olvasófeje az $a$ inputszimbólumon áll, a veremautomata $q$ állapotban van, valamint a verem tetején levő szimbólum $z$. Legyen $ \delta(z, q, a) = {(u_1, r_1), . . . , (u_n, r_n)}$, ahol $u_i \in Z^*$ és $r_i \in Q, 1 \leq i \leq n$. Ekkor $A$ következő állapota valamely $r_i$ lesz és egyidejűleg $z$-t helyettesíti az $u_i$ szóval, továbbá az olvasófej egy cellával jobbra lép az input szalagon.\\
Ha $\delta(z, q, \varepsilon)$ nem üres, akkor ún. $\varepsilon$-átmenet hajtható végre.
Ha az input szalag a $w \in T^*$ szót tartalmazza és a $z_0q_0$ kezdeti konfigurációból kiindulva a lépések sorozatát végrehajtva az $A$ veremautomata egy $up$ konfigurációba ér, ahol $p$ elfogadó állapot, akkor azt mondjuk, hogy $A$ elfogadta a $w$ szó.
\item[Tulajdonságok] \hfill
\begin{itemize}
\item Közvetlen redukció: \\
$\alpha, \beta \in Z^*QT^*$\\
Az $A$ veremautomata az $\alpha $ szót a $\beta$ szóra redukálja egy lépésben ($\alpha \Longrightarrow_A \beta$), ha:
\[\exists z \in Z, \ p,q \in Q, \ a \in T \cup \{\varepsilon\}, \ r,u \in Z^* \textrm{ és } w\in T^*\]
hogy:
\[(u,p) \in \delta(z,q,a) \textrm{ és } \alpha = rzqaw \textrm{ és } \beta = rupw\]
\item Redukció: \\
Az A veremautomata az $\alpha$ szót a $\beta$ szóra redukálja ($\alpha \Longrightarrow_A^* \beta$), ha vagy $\alpha = \beta$, vagy
$ \exists \gamma_1,...,\gamma_n \in Z^*QT^*$ szavakból álló véges sorozat, hogy $\alpha = \gamma_1, \ \beta = \gamma_n, \quad \textrm{ és } \quad \\ {\gamma_i \Longrightarrow_A \gamma_{i+1} \quad (i=1,...,n-1)}$
\item A veremautomata által elfogadott nyelv: \\
Az A veremautomata által (elfogadó állapottal) elfogadott nyelv:
\[L(A) = \{ w \in T^* | \ z_0q_0w \Longrightarrow_A^* up, \textrm{ ahol } u \in Z^*, p \in F \} \]
\item Determinizmus: \\
A $\delta$ leképezést szabályok formájában is megadhatjuk. Az így nyert szabályhalmazt $M_\delta$-val jelöljük. Tehát
\begin{enumerate}
\item $zqa \rightarrow up \in M_\delta$ ha $(u, p) \in \delta(z, q, a)$
\item $zq \rightarrow up \in M_\delta$ ha $(u, p) \in \delta(z, q, \varepsilon)$
\end{enumerate}
Az $A = (Z,Q, T,\delta, z_0, q_0, F)$ veremautomatát determinisztikusnak mondjuk, ha minden $(z, q) \in Z \times Q$ pár esetén:
\begin{enumerate}
\item $\forall a \in T: |\delta(z, q, a)| = 1$ és $\delta(z, q, \varepsilon) = \emptyset$
vagy
\item $|(z, q, \varepsilon)| = 1 $ és $\forall a \in T: \delta(z, q, a) = \emptyset$
\end{enumerate}
\item Üres veremmel elfogadott nyelv: \\
Az $N(A)$ nyelvet az $A$ veremautomata üres veremmel fogadja el, ha
\[ N(A) = \{w \in T^* | \ z_0q_0w \Longrightarrow_A^* p, \textrm{ ahol } p \in Q \} \]
\item Tétel: \\
Bármely $G$ környezetfüggetlen grammatikához meg tudunk adni egy olyan $A$ veremautomatát, amelyre $L(A) = L(G)$ teljesül.
\item Tétel: \\
Minden $A$ veremautomatához meg tudunk adni egy környezetfüggetlen $G$ grammatikát úgy, hogy $L(G) = N(A)$ teljesül.
\end{itemize}
\end{description}
\section{Reguláris nyelvek tulajdonságai és alkalmazásai}
\subsection{3-típusú grammatikák normálformája}
Minden 3-típusú, azaz reguláris nyelv generálható egy olyan grammatikával, amelynek szabályai:
\begin{itemize}
\item $ X \rightarrow aY$, ahol $X,Y \in N$ és $a \in T$
\item $X \rightarrow \varepsilon$, ahol $X \in N$
\end{itemize}
\subsection{Reguláris kifejzések}
\begin{description}
\item[Motiváció] \hfill \\
Ismeretes, hogy minden véges nyelv reguláris. Tudjuk továbbá, hogy az $\mathcal{L}_3$ nyelvosztály (a reguláris nyelvek osztálya) zárt az unió, a konkatenáció és az iteráció lezártja műveletekre nézve.
Következésképpen, kiindulva véges számú véges nyelvből és az előzőekben felsorolt, ún. reguláris műveleteket véges sokszor alkalmazva reguláris nyelvet kapunk.
Kérdés az, hogy vajon ezzel az eljárással minden reguláris nyelvet
elő tudunk-e állítani, azaz, ez a módszer elégséges-e az $\mathcal{L}_3$ nyelvosztály leírására?
\item[Definíció] \hfill \\
Legyenek $V$ és $V' = \{\varepsilon, \cdot, +, *, (, )\}$ diszjunkt ábécék. A $V$ ábécé feletti reguláris kifejezéseket rekurzív módon a következőképpen definiáljuk:
\begin{enumerate}
\item $\varepsilon$ reguláris kifejezés $V$ felett.
\item Minden $a \in V$ reguláris kifejezés $V$ felett.
\item Ha R reguláris kifejezés V felett, akkor $(R)^*$ is reguláris kifejezés $V$ felett. [iteratív lezárás]
\item Ha $Q$ és $R$ reguláris kifejezések $V$ felett, akkor $(Q) \cdot (R)$ [konkatenáció] és $(Q) + (R)$ [unió] is reguláris kifejezés $V$ felett.
\end{enumerate}
\textit{Megjegyzés: Minden reguláris kifejezés jelöl (meghatároz) valamely reguláris nyelvet. (Pl.: $\varepsilon$ a $\{\varepsilon\}$ nyelvet, $a+b$ az $\{a\} \cup \{b\} = \{a,b\}$ és $a\cdot b$ az $\{a\}\{b\} = \{ab\}$ nyelvet.) A reguláris kifejezés a szintaxis, az, hogy hogyan értelmezzük, a szemantika.}
\item[Axiómák]\hfill \\
$P,Q,R$ reguláris kifejezések. Ekkor fennállnak a következő tulajdonságok:
\begin{itemize}
\item Asszociativitás:
\[P+(Q+R) = (P+Q)+R\]
\[P\cdot(Q\cdot R) = (P\cdot Q)\cdot R\]
\item Kommutativitás:
\[P+Q = Q+P\]
\item Disztributivitás:
\[P\cdot (Q+R) = P\cdot Q + P\cdot R\]
\[(P+Q)\cdot R = P\cdot R + Q\cdot R\]
\item Egységelem:
\[\varepsilon\cdot P = P\cdot\varepsilon = P\]
\[P^* = \varepsilon + P \cdot P^*\]
\[P^* = (\varepsilon+P)^*\]
\end{itemize}
A fenti axiómák azonban még önmagukban nem elegendőek az összes reguláris kifejezés előállítására (helyettesítés segítségével). Szükség van még az alábbi inferencia szabályra:
\[P=R+P\cdot Q \quad \land \quad \varepsilon \notin Q \quad \Longrightarrow \quad P = R\cdot Q^*\]
Vegyük még hozzá az $\emptyset$ szimbólumot a reguláris kifejezések halmazához, amely az üres nyelvet jelöli. (Ebben az esetben nincs szükségünk az $\varepsilon$ szimbólumra, mivel $\emptyset^* = \{\varepsilon\}$). Így, a definícióban helyettesíthetjük az $\varepsilon$ szimbólumot az $\emptyset$ szimbólummal. Ekkor helyettesítjük $\varepsilon$-t a megelőző axióma rendszerben $(\emptyset)^*$-gal és még egy további
axiómát tekintünk:
\[\emptyset\cdot P = P\cdot\emptyset = \emptyset\]
A fenti szabályok elégségesek ahhoz, hogy levezessünk minden érvényes egyenlőséget
reguláris kifejezések között.
\item[Reguláris kifejezések és reguláris nyelvek] \hfill \\
Minden reguláris kifejezés egy reguláris (3-típusú) nyelvet jelöl, és megfordítva, minden reguláris nyelvhez megadható egy, ezen nyelvet jelölő reguláris kifejezés.\\ (Ezzel választ adtunk a motivációban feltett kérdésre.)
\end{description}
\subsection{Lineáris grammatikák és nyelvek}
\begin{description}
\item[Definíció] \hfill \\
Egy $G=(N,T,P,S)$ környezetfüggetlen grammatikát lineárisnak nevezünk, ha minden szabálya:
\begin{enumerate}
\item $A\rightarrow u, \quad A \in N, u \in T^*$
\item $A\rightarrow u_1Bu_2, \quad A,B\in N, u_1,u_2 \in T^*$
\end{enumerate}
Továbbá $G$-t bal-lineárisnak, illetve jobb-lineárisnak mondjuk, ha $u_1 = \varepsilon$, illetve $u_2 = \varepsilon$ minden 2. alakú szabályra.
Egy $L$ nyelvet lineárisnak, bal-lineárisnak, illetve jobb-lineárisnak mondunk,
ha van olyan $G$ lineáris, bal-lineáris, illetve jobb-lineáris grammatika,
amelyre $L = L(G)$ teljesül.
\item[Lineáris és reguláris grammatikák, nyelvek] \hfill \\
A jobb-lineáris grammatikák azonosak a reguláris grammatikákkal (3-típusúak).
Tétel: \\
Minden bal-lineáris grammatika reguláris (3-típusú) nyelvet generál.
\end{description}
\section{Környezetfüggetlen nyelvek tulajdonságai és elemzésük}
\subsection{Környezetfüggetlen grammatikák normálformái}
Környezetfüggetlen grammatikák normálformái olyan grammatikai transzformációval előállított grammatikák, melyek:
\begin{itemize}
\item bizonyos szintaktikai feltételeknek/tulajdonságoknak tesznek eleget
\item (általában) valamilyen szempontból egyszerűbbek, mint az eredeti grammatikák
\item ugyanazt a nyelvet generálják (így ugyanazon típusba tartoznak)
\end{itemize}
Tétel:\\
Minden $G = (N, T, P, S)$ környezetfüggetlen grammatikához meg tudunk konstruálni egy vele ekvivalens $G' = (N', T, P', S')$ környezetfüggetlen grammatikát úgy, hogy: $G'$ minden szabályának jobboldala nemüres szó [kivéve azt az esetet, mikor $\varepsilon \in L(G)$, ekkor $S' \rightarrow \varepsilon$ az egyetlen szabály, melynek jobboldala az üres szó és ekkor $S'$ nem fordul elő $G'$ egyetlen szabályának jobboldalán sem.]
\begin{description}
\item[$\varepsilon$-mentes grammatika] \hfill \\
A $G$ grammatika $\varepsilon$-mentes, ha egyetlen szabályának jobboldala sem az üres szó.
Tétel:\\
Minden környezetfüggetlen $G$ grammatikához meg tudunk konstruálni egy $G'$ $\varepsilon$-mentes környezetfüggetlen grammatikát, amelyre $L(G') = L(G) - \{\varepsilon\}$ teljesül.
\item[Chomsky normálforma] \hfill \\
A $G = (N, T, P, S)$ környezetfüggetlen grammatikát Chomsky-normálformájúnak mondjuk, ha minden egyes szabálya:
\begin{itemize}
\item $X \rightarrow a$, ahol $X \in N, a \in T$
\item $X \rightarrow YZ$, ahol $X,Y,Z \in N$
\end{itemize}
Tétel:\\
Minden $\varepsilon$-mentes $G=(N,T,P,S)$ környezetfüggetlen grammatikához meg tudunk konstruálni egy vele ekvivalens $G' = (N', T, P', S)$ Chomsky-normálformájú környezetfüggetlen grammatikát.
Tétel (az előző következménye):\\
Minden $G$ környezetfüggetlen grammatika esetében eldönthető, hogy egy $u$ szó benne van-e $G$ grammatika által generált nyelvben.
\item[Redukált grammatika] \hfill
\begin{itemize}
\item A környezetfüggetlen grammatika egy nemterminálisát inaktívnak/nem aktívnak nevezzük, ha nem vezethető le belőle terminális szó.
\item A környezetfüggetlen grammatika egy nemterminálisát nem elérhetőnek nevezzük, ha nem fordul elő egyetlen olyan szóban sem, amely a kezdőszimbólumból levezethető.
\item Egy nemterminálist nem hasznosnak mondunk, ha vagy inaktív, és/vagy nem elérhető.
\item Az, hogy egy $A$ nemterminális elérhető-e vagy aktív-e, az eldönthető.
\item Egy környezetfüggetlen grammatika redukált, ha minden nemterminálisa aktív és elérhető.
\end{itemize}
Tétel:\\
Minden környezetfüggetlen grammatikához meg tudunk konstruálni egy vele ekvivalens redukált környezetfüggetlen grammatikát.
\end{description}
\subsection{Levezetési fa}
A környezetfüggetlen grammatikák levezetéseit fákkal is jellemezhetjük. A levezetési fa egy szó előállításának lehetőségeiről ad információkat. A levezetési fa egy irányított gráf, amely speciális tulajdonságoknak tesz eleget:
\begin{itemize}
\item A gyökér cimkéje: $S$
\item A többi csúcs cimkéje ($N\cup T$) valamely eleme
\end{itemize}
A levezetési fa nem minden esetben adja meg a levezetés során alkalmazott szabályok sorrendjét. Két levezetés lényegében azonos, ha csak a szabályok alkalmazásának sorrendjében különbözik.
Egy környezetfüggetlen grammatika minden levezetési fája egy egyértelmű (egyetlen) legbaloldalibb levezetést határoz meg. A legbaloldalibb levezetés során minden levezetési lépésben a legbaloldalibb nemterminálist kell helyettesítenünk.
\\\\
Tétel:\\
Minden környezetfüggetlen grammatikáról eldönthető, hogy az általa generált nyelv az üres nyelv-e vagy sem.
\subsection{Bar-Hillel Lemma}
Minden $L$ környezetfüggetlen nyelvhez meg tudunk adni két $p$ és $q$ természetes számot úgy, hogy minden olyan szó $L$-ben, amely hosszabb, mint $p$
\[uxwyz\]
alakú, ahol $|xwy| \leq q$, $xy \neq \varepsilon$ , és minden
\[ux^iwy^iv\]
szó is benne van az $L$ nyelvben minden $i \geq 0$ egész számra ($u,x,w,y,v \in T^*$).
\\\\
Tétel:\\
Eldönthető, hogy egy környezetfüggetlen grammatika végtelen nyelvet generál-e vagy sem.
\end{document}

View File

@@ -0,0 +1,518 @@
\documentclass[margin=0px]{article}
\usepackage{listings}
\usepackage[utf8]{inputenc}
\usepackage{graphicx}
\usepackage{float}
\usepackage[a4paper, margin=0.7in]{geometry}
\usepackage{amsthm}
\usepackage{amssymb}
\usepackage{fancyhdr}
\usepackage{setspace}
\onehalfspacing
\makeatletter
\renewcommand\paragraph{%
\@startsection{paragraph}{4}{0mm}%
{-\baselineskip}%
{.5\baselineskip}%
{\normalfont\normalsize\bfseries}}
\makeatother
\renewcommand{\figurename}{ábra}
\newenvironment{tetel}[1]{\paragraph{#1 \\}}{}
\pagestyle{fancy}
\lhead{\it{PTI BSc Záróvizsga tételek}}
\rhead{13. Számításelmélet}
\title{\textbf{{\Large ELTE IK - Programtervező Informatikus BSc} \vspace{0.2cm} \\ {\huge Záróvizsga tételek}} \vspace{0.3cm} \\ 13. Számításelmélet}
\author{}
\date{}
\begin{document}
\maketitle
\begin{tetel}{Számításelmélet}
A Turing gép és a Church-Turing tézis. Turing gépek variánsok: többszalagos, nemdeterminisztikus, számoló, offline. Rekurzív és rekurzívan felsorolható nyelvek. Eldönthetetlen problémák. Idő- és tárbonyolultsági osztályok: P, NP, PSPACE. NP-teljes problémák.
\end{tetel}
\section{Kiszámíthatóság}
\subsubsection{Algoritmusmodellek}
\begin{itemize}
\item \textbf{Gödel}: rekurzív függvények (primitív rekurzív függvények 1931-ben, majd általánosabb 1934-ben)
\item \textbf{Church}: $\lambda$-kalkulus, $\lambda$-definiálható függvények: ekvivalensek a rekurzív függvényekkel (bizonyított)
\item \textbf{Turing}: Turing-gép (1936), a $\lambda$-definiálható és a Turing-géppel kiszámítható függvények megegyeznek (bizonyított)
\end{itemize}
\noindent \textbf{Church-Turing tézis}: A kiszámíthatóság különböző matematikai modelljei mind az effektíven
kiszámítható függvények osztályát definiálják.
\subsubsection{Fogalmak}
Kiszámítási problémának nevezünk egy olyan, a matematika nyelvén megfogalmazott
kérdést, amire egy algoritmussal szeretnénk megadni a választ. A
gyakorlati élet szinte minden problémájához rendelhető, megfelelő absztrakciót
használva, egy kiszámítási probléma.\\
\noindent Egy problémát a hozzá tartozó konkrét bementettel együtt a probléma egy
példányának nevezzük.\\
Speciális kiszámítási probléma az eldöntési probléma. Ilyenkor a problémával
kapcsolatos kérdés egy eldöntendő kérdés, tehát a probléma egy példányára a
válasz "igen" vagy "nem" lesz.\\
Egy kiszámítási probléma reprezentálható egy $f : A \to B$ függvénnyel. Az $A$
halmaz tartalmazza a probléma egyes bemeneteit, jellemzően egy megfelelő ábécé
feletti szóban elkódolva, míg a $B$ halmaz tartalmazza a bemenetekre adott
válaszokat, szintén valamely alkalmas ábécé feletti szóban elkódolva. Értelemszerűen,
ha eldöntési problémáról van szó, akkor az $f$ értékkészlete, vagyis a $B$
egy két elemű halmaz: $\left\{igen, nem\right\}$, $\left\{1, 0\right\}$, stb.\\
\noindent \textbf{Kiszámítható függvény}: Egy $f : A \to B$ függvényt \textit{kiszámíthatónak}
nevezünk, ha minden $x \in A$ elemre az $f(x) \in B$ függvényérték kiszámítható valamilyen
algoritmikus modellel.\\
\noindent \textbf{Megoldható, eldönthető probléma}: Egy kiszámítási probléma \textit{megoldható}
(eldöntési probléma esetén azt mondjuk, hogy \textit{eldönthető}), ha az általa meghatározott
függvény kiszámítható.\\
\noindent \textbf{Algoritmusok időigénye}: Legyenek $f,g: \mathbb{N} \to \mathbb{N}$ függvények, ahol
$\mathbb{N}$ a természetes számok halmaza. Azt mondjuk, hogy $f$ legfeljebb olyan gyorsan nő, mint $g$
(jelölése: $f(n) = \mathcal{O}(g(n))$), ha $\exists c>0$ és $n_{0} \in \mathbb{N}$, hogy
$f(n) \leq c * g(n) \ \forall n \geq n_{0}$. Az $f(n) = \Omega(g(n))$ jelöli azt, hogy $g(n) = \mathcal{O}(f(n))$
teljesül és $f(n) = \Theta(g(n))$ jelöli azt, hogy $f(n) = \mathcal{O}(g(n))$ és $f(n) = \Omega(g(n))$ is teljesül.\\
\noindent \textbf{Példa}: $3n^{3} + 5n^{2} + 6 = \mathcal{O}(n^{3})$, $n^{k} = \mathcal{O}(2^{n}) \ \forall k \geq 0$, stb.\\
\noindent \textbf{Tétel}: Minden polinomiális függvény lassabban nő, mint bármely exponenciális függvény,
azaz minden $p(n)$ polinomhoz és $c>0$-hoz $\exists n_{0}$ egész szám, hogy $\forall n \geq n_{0}$ esetén $p(n) \leq 2^{cn}$\\
\noindent \textbf{Kiszámítási probléma megfeleltetése eldöntési problémának}: Tekintsünk egy $P$ kiszámítási problémát
és legyen $f: A \to B$ a $P$ által meghatározott függvény. Ekkor megadható $P$-hez egy $P'$ eldöntési probléma úgy, hogy
$P'$ pontosan akkor eldönthető, ha $P$ kiszámítható. Állítsuk párba ugyanis minden $a \in A$ elemre az $a$ és $f(a)$ elemeket,
és kódoljuk el az így kapott párokat egy-egy szóban. Ezek után legyen $P'$ az így kapott szavakból képzett formális nyelv.
Nyilvánvaló, hogy ha minden $a \in A$ és $b \in B$ elemre az $(a,b) \in P'$ tartalmazás eldönthető (azaz $P'$ eldönthető), akkor
$P$ kiszámítható és fordítva.
E megfeleltetés miatt a továbbiakban jellemzően eldöntési problémákkal foglalkozunk.
\section{Turing-gépek}
Hasonlóan a véges automatához vagy a veremautomatához, a Turing-gép is
egy véges sok állapottal rendelkező eszköz. A Turing-gép egy két irányban
végtelen szalagon dolgozik. A szalag cellákra van osztva, tulajdonképpen ez
a gép (korlátlan) memóriája. Kezdetben a szalagon csak a bemenő szó van,
minden cellán egy betű. A szalag többi cellája egy úgynevezett blank vagy
szóköz ($\sqcup$) szimbólumokkal van feltöltve. Kezdetben a gép úgynevezett író-olvasó
feje a bemenő szó első betűjén áll és a gép a kezdőállapotában van.
A gép az író-olvasó fejet tetszőlegesen képes mozgatni a szalagon. Képes továbbá
a fej pozíciójában a szalag tartalmát kiolvasni és átírni. A gépnek van két
kitüntetett állapota, a $q_{i}$ és a $q_{n}$ állapotok. Ha ezekbe az állapotokba kerül,
akkor rendre elfogadja illetve elutasítja a bemenő szót.
Formálisan a Turing-gépet a következő módon definiáljuk.\\
\noindent \textbf{A Turing-gép formális definíciója}: A Turing-gép egy olyan
$M = (Q, \Sigma, \Gamma, \delta, q_{0}, q_{i}, q_{n})$ rendszer, ahol:
\begin{itemize}
\item $Q$ az állapotok véges, nem üres halmaza,
\item $q_{0}, q_{i}, q_{n} \in Q$, $q_{0}$ a kezdőállapot, $q_{i}$ az elfogadó állapot,
$q_{n}$ pedig az elutasító állapot,
\item $\Sigma$ és $\Gamma$ ábécék, a bemenő jelek és a szalagszimbólumok ábécéje úgy, hogy
$\Sigma \subseteq \Gamma$ és $\Gamma - \Sigma$ tartalmaz egy speciális $\sqcup$ szimbólumot,
\item $\delta : (Q - \left\{q_{i},q_{n}\right\}) \times \Gamma \to Q \times \Gamma \times \left\{L, R, S\right\}$
az átmenetfüggvény.
\end{itemize}
Úgy mint a veremautomaták esetében, egy $M$ Turing-gép működésének fázisait is konfigurációkkal írhatjuk le.\\
\noindent \textbf{Turing-gép konfigurációja}: Az $M$ Turing-gép konfigurációja egy olyan $uqv$ szó, ahol
$q \in Q$ és $u, v \in \Gamma^{*}$, $v \not = \varepsilon$. Ez a konfiguráció az $M$ azon állapotát tükrözi
amikor a szalag tartalma $uv$ ($uv$ előtt és után a szalagon már csak $\sqcup$ van), a gép a $q$ állapotban van,
és az író-olvasó fej a $v$ első betűjére mutat. $M$ összes konfigurációjának halmazát $\mathcal{C}_{M}$-el jelöljük.\\
\noindent \textbf{Turing-gép kezdőkonfigurációja}: $M$ kezdőkonfigurációja egy olyan $q_{0}u\sqcup$ szó, ahol
$u$ csak $\Sigma$-beli betűket tartalmaz.\\
\noindent \textbf{Turing-gép konfigurációátmenete}: $M$ konfigurációátmenete egy olyan
$\vdash \subseteq \mathcal{C}_{M} \times \mathcal{C}_{M}$ reláció, amit a következőképpen definiálunk.
Legyen $uqav$ egy konfiguráció, ahol $a \in \Gamma$ és $u, v \in \Gamma^{*}$. A következő három esetet
különböztetjük meg:
\begin{enumerate}
\item Ha $\delta(q,a) = (r, b, S)$, akkor $uqav \vdash urbv$.
\item Ha $\delta(q,a) = (r, b, R)$, akkor $uqav \vdash ubrv'$, ahol $v' = v$, ha $v \not = \varepsilon$, különben
$v' = \sqcup$.
\item Ha $\delta(q,a) = (r, b, L)$, akkor $uqav \vdash u'rcbv$, ahol $u'c = u$ valamely $u' \in \Gamma^{*}$-ra
és $c \in \Gamma$-ra, ha $u \not = \varepsilon$, egyébként pedig $u' = \varepsilon$, $c = \sqcup$.
\end{enumerate}
Azt mondjuk, hogy $M$ véges sok lépésben eljut a $C$ konfigurációból a $C'$ konfigurációba (jele $C \vdash^{*} C'$),
ha létezik olyan $n \geq 0$ és $C_{1}, ... C_{n}$ konfigurációsorozat, hogy $C_{1} = C$, $C_{n} = C'$ és minden
$1 \leq i < n$-re $C_{i} \vdash C_{i+1}$.
Ha $q \in \left\{q_{i}, q_{n}\right\}$, akkor azt mondjuk, hogy az $uqv$ konfiguráció egy megállási
konfiguráció. Továbbá, $q = q_{i}$ esetében elfogadó, míg $q = q_{n}$ esetében elutasító
konfigurációról beszélünk.\\
\noindent \textbf{Turing-gép által felismert nyelv}: Az $M$ Turing-gép által felismert nyelv (jelölése $L(M)$)
azoknak az $u \in \Sigma^{*}$ szavaknak a halmaza, melyekre igaz, hogy $q_{0}u\sqcup \vdash^{*} xq_{i}y$
valamely $x,y \in \Gamma^{*}$, $y \not = \varepsilon$ szavakra.
\begin{figure}[H]
\centering
\includegraphics[width=0.6\linewidth]{img/turinggep_pelda}
\caption{Egy, az $L = \left\{u\#u \ | \ u \in \left\{0,1\right\}^{+}\right\}$ felismerő Turing-gép.}
\label{fig:turinggep_pelda}
\end{figure}
\noindent \textbf{Turing-gépek ekvivalenciája}: Két Turing-gépet ekvivalensnek nevezünk, ha ugyanazt a nyelvet ismerik fel.\\
\noindent \textbf{Turing-felismerhető nyelv, rekurzívan felismerhető nyelvek osztálya}:
Egy $L \subseteq \Sigma^{*}$ nyelv Turing-felismerhető, ha $L = L(M)$ valamely $M$ Turing-gépre.
A Turing-felismerhető nyelveket szokás \textit{rekurzívan felsorolhatónak} is nevezni.
A rekurzívan felsorolható nyelvek osztályát $RE$-vel jelöljük.\\
\noindent \textbf{Turing-eldönthető nyelv, rekurzív nyelvek osztálya}:
Egy $L \subseteq \Sigma^{*}$ nyelv Turing-eldönthető, ha létezik olyan Turing-gép,
amely minden bemeneten megállási konfigurációba jut és felismeri $L$-et.
A Turing-felismerhető nyelveket szokás \textit{rekurzívnak} is nevezni.
A rekurzív nyelvek osztályát $R$-rel jelöljük.\\
\noindent \textbf{Turing-gép futási ideje, időigénye}:
Tekintsünk egy $M = (Q, \Sigma, \Gamma, \delta, q_{0}, q_{i}, q_{n})$ Turing-gépet és annak egy
$u \in \Sigma^{*}$ bemenő szavát. Azt mondjuk, hogy $M$ futási ideje (időigénye) az $u$ szón $n$ ($n \geq 0$),
ha $M$ a $q_{0}u\sqcup$ kezdőkonfigurációból $n$ lépésben el tud jutni egy megállási konfigurációba. Ha nincs ilyen
szám, akkor $M$ futási ideje az $u$ szón végtelen.
Legyen $f : \mathbb{N} \to \mathbb{N}$ egy függvény. Azt mondjuk, hogy $M$ időigénye $f(n)$ (vagy azt, hogy $M$
egy $f(n)$ időkorlátos gép), ha minden $u \in \Sigma^{*}$ input szóra $M$ időigénye az $u$ szón legfeljebb $f(l(u))$.
\subsubsection{Többszalagos Turing-gépek}
A többszalagos Turing-gépek, értelemszerűen, egynél több szalaggal rendelkeznek.
Mindegyik szalaghoz tartozik egy-egy író-olvasó fej, melyek egymástól
függetlenül képesek mozogni a szalagon.\\
\noindent \textbf{Többszalagos Turing-gép definíciója}: Legyen $k > 1$. Egy $k$-szalagos Turing-gép egy olyan
$M = (Q, \Sigma, \Gamma, \delta, q_{0}, q_{i}, q_{n})$ rendszer, ahol a komponensek a $\delta$ kivételével
megegyeznek az egyszalagos Turing-gép komponenseivel, $\delta$ pedig a következőképpen adódik.
$\delta : (Q - \left\{q_{i},q_{n}\right\}) \times \Gamma^{k} \to Q \times \Gamma^{k} \times \left\{L, R, S\right\}^{k}$.
Legyenek $q, p \in Q$, $a_{1}, a_{2}, ... , a_{k}, b_{1}, b_{2}, ..., b_{k} \in \Gamma$ és
$D_{1}, D_{2}, ..., D_{k} \in \left\{L, R, S\right\}$. Ha $\delta(q,a_{1}, a_{2}, ... , a_{k}) = (p,b_{1}, b_{2}, ..., b_{k}, D_{1}, D_{2}, ..., D_{k})$, akkor a gép akkor a gép a $q$ állapotból, ha a szalagjain rendre az
$a_{1}, a_{2}, ... , a_{k}$ betűket olvassa, át tud menni a $p$ állapotba, miközben az
$a_{1}, a_{2}, ... , a_{k}$ betűket átírja a $b_{1}, b_{2}, ... , b_{k}$ betűkre és a szalagokon a fejeket
$D_{1}, D_{2}, ... , D_{k}$ irányokba mozgatja.
A többszalagos Turing-gép konfigurációja, a konfigurációátmenet valamint a
felismert illetve eldöntött nyelv definíciója az egyszalagos eset értelemszerű általánosítása.
A többszalagos Turing-gép időigényét is az egyszalagoshoz hasonlóan definiáljuk.\\
\noindent \textbf{Többszalagos és egyszalagos gépek ekvivalenciája}: Minden $k$-szalagos, $f(n)$ időkorlátos Turing-géphez
van vele ekvivalens $\mathcal{O}(n*f(n))$ időkorlátos egyszalagos Turing-gép.
\subsubsection{Nemdeterminisztikus Turing-gépek}
Egy $M$ nemdeterminisztikus Turing-gép állapotfüggvénye
$\delta : (Q - \left\{q_{i},q_{n}\right\}) \times \mathcal{P}(\Gamma \to Q \times \Gamma \times \left\{L, R\right\})$
alakú. Tehát $M$ minden konfigurációjából néhány (esetleg nulla) különböző konfigurációba mehet át.
Ily módon $M$ számítási sorozatai egy $u$ szón egy fával reprezentálhatók. A fa csúcsa $M$ kezdőkonfigurációja,
a szögpontjai pedig $M$ konfigurációi. A fa minden levele megfelel $M$ egy számítási sorozatának az
$u$-n. $M$ akkor fogadja el $u$-t, ha a fa valamelyik levele elfogadó konfiguráció.
Nevezzük ezt a most leírt fát az $M$ nemdeterminisztikus számítási fájának az
$u$-n. Az $M$ által felismert nyelv a determinisztikus esethez hasonlóan definiálható,
a gép által eldöntött nyelv pedig a következőképpen.\\
\noindent \textbf{Nemdeterminisztikus Turing-gép által eldöntött nyelv}: Azt mondjuk, hogy egy nemdeterminisztikus
$M$ Turing-gép eldönt egy $L \subseteq \Gamma^{*}$ nyelvet, ha felismeri, és minden $u \in \Sigma{*}$ szóra
$M$ számítási sorozatai végesek és elfogadási vagy elutasítási konfigurációba vezetnek.\\
\noindent \textbf{Nemdeterminisztikus Turing-gép időigénye}: Legyen $f : \mathbb{N} \to \mathbb{N}$ függvény, $M$
egy nemdeterminisztikus Turing-gép. Az $M$ időigénye $f(n)$, ha egy $n$ hosszú $u$ bemeneten nincsenek $M$-nek
$f(n)$-nél hosszabb számítási sorozatai, azaz az $M$ számítási fája az $u$-n legfeljebb $f(n)$ magas.\\
\noindent \textbf{Determinisztikus és nemdeterminisztikus Turing-gépek ekvivalenciája}:
Minden $M$ nemdeterminisztikus Turing-géphez megadható egy ekvivalens $M'$ determinisztikus Turing-gép.
Továbbá, ha $M$ $f(n)$ időigényű valamely $f : \mathbb{N} \to \mathbb{N}$ függvényre, akkor
$M'$ $2^{\mathcal{O}(f(n))}$ időigényű.
\section{Eldönthetetlen problémák}
Ebben a fejezetben megmutatjuk, hogy bár a Turing-gép a lehető legáltalánosabb
algoritmus modell, mégis vannak olyan problémák, melyek nem számíthatók ki Turing-géppel.\\
\noindent \textbf{Emlékeztető}: A rekurzívan felsorolható (Turing-felismerhető) nyelvek osztályát $RE$-vel,
a rekurzív (Turing-eldönthető) nyelvek osztályát $R$-rel jelöljük.\\
Világos, hogy $R \subseteq RE $. A célunk az, hogy megmutassuk: az $R$ valódi részhalmaza az $RE$-nek,
azaz van olyan nyelv (probléma) ami Turing-felismerhető, de nem eldönthető.
Csak olyan Turing-gépeket fogunk vizsgálni, melyek bemenő ábécéje a $\left\{0, 1\right\}$ halmaz.
Ez nem jelenti az általánosság megszorítását, hiszen ha találunk egy olyan $\left\{0, 1\right\}$ feletti nyelvet,
melyet nem lehet eldönteni ilyen Turing-géppel, akkor ezt a nyelvet egyáltalán nem lehet eldönteni.\\
\subsubsection{Turing-gépek kódolása}
A $\left\{0, 1\right\}$ feletti szavak felsorolhatóak (vagyis megszámlálhatóak). Valóban, tekintsük azt a felsorolást,
amelyben a szavak a hosszuk szerint követik egymást, és két egyforma hosszú szó közül pedig az van
előbb, amelyik az alfabetikus rendezés szerint megelőzi a másikat. Ily módon
a $\left\{0, 1\right\}^{*}$ halmaz elemeinek egy felsorolása a következőképpen alakul: $w_{1} = \varepsilon$,
$w_{2} = 0$, $w_{3} = 1$, $w_{4} = 00$, $w_{5} = 01$ és így tovább. Ebben a fejezetben tehát a
$w_{i}$ szóval a $\left\{0, 1\right\}^{*}$ $i$. elemét jelöljük.
Legyen továbbá $M$ egy $\left\{0, 1\right\}$ inputábécé feletti Turing-gép. Van olyan $k > 0$ szám, hogy
$Q$-t felírhatjuk $Q = \left\{p_{1}, ... p_{k}\right\}$ alakban, ahol $p_{1} = q_{0}$, $p_{k-1} = q_{i}$, $p_{k} = q_{n}$.
Továbbá, van olyan $m > 0$ szám, hogy $\Gamma$-t felírhatjuk $\Gamma = \left\{X_{1}, ... X_{m}\right\}$ alakban,
ahol $X_{1} = 0$, $X_{2} = 1$, $X_{3} = \sqcup$, és $X_{4}, ... X_{m}$ az $M$ további szalagszimbólumai.
Nevezzük végül az $L, R, S$ szimbólumokat (amelyek irányokat jelölnek) rendre $D_{1}$, $D_{2}$ és $D_{3}$-nak.
Ezek után $M$ egy $\delta(p_{i},X_{j}) = (p_{r}, X_{s}, D_{t})$ ($0 \leq i,r \leq k$, $1 \leq j,s \leq m$ és $1 \leq t \leq 3$)
átmenete elkódolható a $0^{i}10^{j}10^{r}10^{s}10^{t}$ szóval. Mivel minden $0$-s blokk hossza legalább $1$, az átmenetet
kódoló szóban nem szerepel az $11$ részszó. Tehát az M összes átmenetét kódoló szavakat összefűzhetjük egy olyan szóvá,
melyben az átmeneteket az $11$ részszó választja el egymástól. Az így kapott szó pedig magát $M$-et kódolja.\\
A továbbiakban $M_{i}$-vel jelöljük azt a Turing-gépet, amelyet a $w_{i}$ szó kódol ($i \geq 1$). Amennyiben
$w_{i}$ nem a fent leírt kódolása egy Turing-gépnek, akkor tekintsük $M_{i}$-t olyannak, ami minden input esetén
azonnal a $q_{n}$ állapotba megy, azaz $L(M_{i}) = \emptyset$.\\
A későbbiekben szükségünk lesz arra, hogy elkódoljunk egy $(M, w)$ Turing-gép és bemenet
párost egy $\left\{0, 1\right\}$ feletti szóban. Mivel a Turing-gépek kódolása nem tartalmazhat
$111$-et, ezért $(M, w)$ kódja a következő: $M$ kódja után írunk $111$-et, majd utána $w$-t.
\subsubsection{Egy nem rekurzívan felsorolható nyelv}
\noindent \textbf{Az $L_{\acute{a}tl\acute{o}}$ nyelv}: Az $L_{\acute{a}tl\acute{o}}$ nyelv azon $\left\{0, 1\right\}$
feletti Turing-gépek bináris kódjait tartalmazza, melyek nem fogadják el önmaguk kódját, mint bemenő szót, azaz
$L_{\acute{a}tl\acute{o}} = \left\{w_{i} \ | \ i \geq 1, w_{i} \notin L(M_{i}) \right\}$\\
\noindent \textbf{Tétel}: $L_{\acute{a}tl\acute{o}} \notin RE$.
\subsubsection{Egy rekurzívan felsorolható, de nem eldönthető nyelv}
\noindent \textbf{Az $L_{u}$ nyelv}: Tekintsük azon $(M, w)$ párok halmazát (egy megfelelő bináris szóban elkódolva),
ahol $M$ egy $\left\{0, 1\right\}$ bemenő ábécé feletti Turing-gép, $w$ pedig egy $\left\{0, 1\right\}$ feletti
szó úgy, hogy $w \in L(M)$, azaz $M$ elfogadja $w$-t. Ezt a nyelvet jelöljük $L_{u}$-val.
$L_{u} = \left\{\langle w_{i},w_{j} \rangle \ | \ i, j \geq 1, w_{j} \in L(M_{i}) \right\}$\\
\noindent \textbf{Tétel}: $L_{u} \in RE$.\\
\noindent \textbf{Tétel}: $L_{u} \notin R$.
\subsubsection{További tételek}
\begin{enumerate}
\item Legyen $L$ egy nyelv. Ha $L, \bar{L} \in RE$, akkor $L \in R$. Következmény: a rekurzívan felsorolható
nyelvek nem zártak a komplementerképzésre.
\item Ha $L \in R$, akkor $\bar{L} \in R$, azaz a rekurzív nyelvek zártak a komplementerképzésre.
\end{enumerate}
\subsubsection{További eldönthetetlen problémák}
\noindent \textbf{Kiszámítható függvény}: Legyen $\Sigma$ és $\Delta$ két ábécé és $f$ $\Sigma^{*}$ból
$\Delta^{*}$-ba képző függvény. Azt mondjuk, hogy $f$ kiszámítható, ha van olyan $M$ Turing-gép, hogy
$M$-et egy $w \in \Sigma^{*}$ szóval a bemenetén elindítva, $M$ úgy áll meg, hogy a szalagján a
$f(w) \in \Delta^{*}$ szó van.\\
\noindent \textbf{Eldöntési problémák visszavezetése}: Legyen $L_{1} \subseteq \Sigma^{*}$ és $L_{2} \subseteq \Delta^{*}$
két eldöntési probléma. $L_{1}$ visszavezethető $L_{2}$-re ($L_{1} \leq L_{2}$), ha van olyan
$f : \Sigma^{*} \to \Delta^{*}$ kiszámítható függvény, hogy minden $w \in \Sigma^{*}$ szóra
$w \in L_{1}$ pontosan akkor teljesül, ha $f(w) \in L_{2}$ is teljesül.\\
\noindent \textbf{Tétel}: Legyen $L_{1} \subseteq \Sigma^{*}$ és $L_{2} \subseteq \Delta^{*}$
két eldöntési probléma és tegyük fel, hogy $L_{1}$ visszavezethető $L_{2}$-re. Ekkor igazak a következő állítások:
\begin{enumerate}
\item Ha $L_{1}$ eldönthetetlen, akkor $L_{2}$ is.
\item Ha $L_{1} \notin RE$ , akkor $L_{2} \notin RE$.
\end{enumerate}
\noindent \textbf{A megállási probléma}: Legyen $L_{h} = \left\{\langle M, w \rangle \ |\ M \ meg\acute{a}ll \ a \ w \ bemeneten \right\}$,
azaz $L_{h}$ azon $\langle M, w \rangle$ Turing-gép és bemenet párosokat tartalmazza elkódolva, melyekre $M$ megáll a $w$ bemeneten.
$L_{h}$ eldönthetetlen ($L_{u}$ visszavezethető $L_{h}$-ra), viszont $L_{h} \in RE$.\\
\noindent \textbf{Az $L_{\ddot{u}res}$ probléma}: Legyen $L_{\ddot{u}res} = \left\{\langle M \rangle \ |\ L(M) = \emptyset \right\}$.
$L_{\ddot{u}res}$ eldönthetetlen ($L_{u}$ visszavezethető $L_{\ddot{u}res}$-re), valamint $L_{\ddot{u}res} \notin RE$.\\
\noindent \textbf{Rekurzívan felsorolható nyelvek (nem triviális) tulajdonsága}: Ha $\mathcal{P}$ a rekurzívan felsorolható
nyelvek egy halmaza, akkor $\mathcal{P}$ a rekurzívan felsorolható nyelvek egy tulajdonsága. Ha $\mathcal{P} \not = \emptyset$ és
$\mathcal{P} \not = RE$, akkor $\mathcal{P}$ nem triviális tulajdonsága a rekurzívan felsorolható nyelveknek.\\
\noindent \textbf{Rice tétele}:
Adott $\mathcal{P}$ tulajdonságra jelöljük $L_{\mathcal{P}}$-vel azon Turing-gépek kódjainak halmazát, amelyek
$\mathcal{P}$-beli nyelvet ismernek fel. Ha $\mathcal{P}$ a rekurzívan felsorolható nyelvek egy nem triviális tulajdonsága, akkor
$L_{\mathcal{P}}$ eldönthetetlen.\\
\noindent \textbf{Post Megfelelkezési Probléma (röviden PMP)}: A PMP problémát a következőképpen definiáljuk. Legyen
$\Sigma$ egy legalább két betűt tartalmazó ábécé és legyen $D = \left\{[\frac{u_{1}}{v_{1}}], ..., [\frac{u_{n}}{v_{n}}]\right\}$
egy dominóhalmaz, melyben $n \geq 1$ és $u_{1}, ..., u_{n}, v_{1}, ..., v_{n} \in \Sigma^{+}$. A kérdés az, hogy van-e egy olyan
$1 \leq i_{1}, ..., i_{m} \leq m$ ($m \geq 1$) indexsorozat, melyre teljesül, hogy a $[\frac{u_{i_{1}}}{v_{i_{1}}}], ..., [\frac{u_{i_{m}}}{v_{i_{m}}}]$ dominókat egymás mellé írva alul és felül ugyanaz a szó adódik, azaz
$u_{i_{1}} ... u_{i_{m}} = v_{i_{1}} ... v_{i_{m}}$. Ebben az esetben a fenti dominósorozatot a D egy megoldásának nevezzük.
Formális nyelvként a következőképpen definiálhatjuk a PMP-t:
PMP $= \left\{ \langle D \rangle \ |\ D-nek \ van \ megold\acute{a}sa \right\}$. PMP eldönthetetlen.
\section{Bonyolultságelmélet}
A bonyolultságelmélet célja a megoldható (és ezen belül az eldönthető) problémák osztályozása a megoldáshoz szükséges
erőforrások (jellemzően az idő és a tár) mennyisége szerint.
\subsubsection{Időbonyolultsági fogalmak}
\noindent \textbf{TIME}: Legyen $f : \mathbb{N} \to \mathbb{N}$ függvény. \textbf{TIME}($f(n)$) $= \left\{L \ | \ L \ eld\ddot{o}nthet\tilde{o} \ \mathcal{O}(f(n)) \ id\tilde{o}ig\acute{e}ny\tilde{u} \ Turing-g\acute{e}ppel \right\}$\\
\noindent \textbf{P} $=\bigcup_{k \geq 1}$ \textbf{TIME}($n^{k}$). Tehát \textbf{P} azon nyelveket tartalmazza,
melyek eldönthetőek polinom időkorlátos determinisztikus Turing-géppel. Ilyen például a jól ismert \textsc{Elérhetőség}
probléma, melynek bemenete egy $G$ gráf és annak két kitüntetett csúcsa ($s$ és $t$). A kérdés az, hogy van-e a $G$-ben
út $s$-ből $t$-be. Ha az \textsc{Elérhetőség} problémára nyelvként tekintünk, akkor írhatjuk azt, hogy\\
\textsc{Elérhetőség} $= \left\{\langle G, s, t \rangle \ | \ G-ben \ van \ \acute{u}t \ s-b\tilde{o}l \ t-be\right\}$.\\
Könnyen megadható az \textsc{Elérhetőség} problémáját polinom időben eldöntő determinisztikus Turing-gép, tehát
\textsc{Elérhetőség} $\in$ \textbf{P}.\\
\noindent \textbf{NTIME}: Legyen $f : \mathbb{N} \to \mathbb{N}$ függvény.\\ \textbf{NTIME}($f(n)$) $= \left\{L \ | \ L \ eld\ddot{o}nthet\tilde{o} \ \mathcal{O}(f(n)) \ id\tilde{o}ig\acute{e}ny\tilde{u} \ nemdeterminisztikus\ Turing-g\acute{e}ppel \right\}$\\
\noindent \textbf{NP} $=\bigcup_{k \geq 1}$ \textbf{NTIME}($n^{k}$).
Az \textbf{NP}-beli problémák rendelkeznek egy közös tulajdonsággal az alábbi értelemben.
Ha tekintjük egy \textbf{NP}-beli probléma egy példányát és egy lehetséges "bizonyítékot"
arra nézve, hogy ez a példány "igen" példánya az adott problémának,
akkor ezen bizonyíték helyességének leellenőrzése polinom időben elvégezhető.
Ennek megfelelően egy \textbf{NP}-beli problémát eldöntő nemdeterminisztikus Turing-gép
általában úgy működik, hogy "megsejti" a probléma bemenetének egy lehetséges megoldását,
és polinom időben leellenőrzi, hogy a megoldás helyes-e.
Tekintsük a \textsc{Sat} problémát, amit a következőképpen definiálunk. Adott egy $\phi$ ítéletlogikai KNF.
A kérdés az, hogy kielégíthető-e. Annak a bizonyítéka, hogy a $\phi$ kielégíthető, egy olyan változó-hozzárendelés,
ami mellett kiértékelve a $\phi$-t igaz értéket kapunk. Egy tetszőleges változó-hozzárendelés tehát a $\phi$
kielégíthetőségének egy lehetséges bizonyítéka .Annak leellenőrzése pedig, hogy ez a
hozzárendelés tényleg igazzá teszi-e $\phi$-t, polinom időben elvégezhető. A \textsc{Sat}
\textbf{NP}-beli probléma.\\
\noindent Az a definíciókból következik, hogy fennáll a \textbf{P} $\subseteq$ \textbf{NP} tartalmazás.
\subsubsection{NP-teljes problémák}
\noindent \textbf{Polinom időben kiszámítható függvény}: Legyen $\Sigma$ és $\Delta$ két ábécé és $f$ $\Sigma^{*}$ból
$\Delta^{*}$-ba képző függvény. Azt mondjuk, hogy $f$ polinom időben kiszámítható, ha kiszámítható egy polinom
időigényű Turing-géppel.\\
\noindent \textbf{Eldöntési problémák polinom idejű visszavezetése}:
Legyen $L_{1} \subseteq \Sigma^{*}$ és $L_{2} \subseteq \Delta^{*}$ két eldöntési probléma.
$L_{1}$ polinom időben visszavezethető $L_{2}$-re ($L_{1} \leq_{p} L_{2}$), ha $L_{1} \leq L_{2}$ és
a visszavezetésben használt $f$ függvény polinom időben kiszámítható.\\
\noindent \textbf{Tétel}: Legyen $L_{1}$ és $L_{2}$ két probléma úgy, hogy $L_{1} \leq_{p} L_{2}$. Ha $L_{2}$
\begin{enumerate}
\item \textbf{P}-beli, akkor $L_{1}$ is \textbf{P}-beli.
\item \textbf{NP}-beli, akkor $L_{1}$ is \textbf{NP}-beli.
\end{enumerate}
\noindent \textbf{NP-teljes probléma}: Legyen $L$ egy probléma. Azt mondjuk, hogy $L$ \textbf{NP}-teljes, ha
\begin{enumerate}
\item \textbf{NP}-beli, és
\item minden további \textbf{NP}-beli probléma polinom időben visszavezethető $L$-re.
\end{enumerate}
\noindent \textbf{Tétel}: Legyen $L$ egy \textbf{NP}-teljes probléma. Ha $L \in$ \textbf{P}, akkor \textbf{P} $=$ \textbf{NP}.\\
\noindent \textbf{Megjegyzés}: Jelenleg \textbf{NEM} tudunk \textbf{P}-beli \textbf{NP}-teljes problémáról!!!\\
\noindent \textbf{Tétel}: Legyen $L_{1}$ egy \textbf{NP}-teljes, $L_{2}$ pedig \textbf{NP}-beli probléma.
Ha $L_{1} \leq_{p} L_{2}$, akkor $L_{2}$ is \textbf{NP}-teljes.\\
\noindent \textbf{Cooke tétele}: \textsc{Sat} \textbf{NP}-teljes.\\
\noindent Legyen $k \geq 1$.
k\textsc{Sat} $= \left\{\langle \phi \rangle \ | \ \phi \ minden \ tagj\acute{a}ban \ k \ liter\acute{a}l \ van. \right\}$\\
\noindent \textbf{Tétel}: 3\textsc{Sat} \textbf{NP}-teljes, ugyanis \textsc{Sat} $\leq_{p}$ 3\textsc{Sat}.\\
\noindent \textsc{Teljes részgráf} $= \left\{\langle G, k \rangle \ | \ G \ v\acute{e}ges \ gr\acute{a}f, k \geq 1, \ G-nek \ \exists \ k
\ cs\acute{u}cs\acute{u} \ r\acute{e}szgr\acute{a}fja \right\}$.
Tehát a \textsc{Teljes részgráf} azon $G$ és $k$ párokat tartalmazza, megfelelő ábécé feletti
szavakban elkódolva, melyekre igaz, hogy $G$-ben van $k$ csúcsú teljes részgráf,
azaz olyan részgráf, melyben bármely két csúcs között van él.\\
\noindent \textsc{Teljes részgráf}$= \left\{\langle G, k \rangle \ | \ G \ v\acute{e}ges \ gr\acute{a}f, k \geq 1, \ G-nek \ \exists \ k
\ cs\acute{u}cs\acute{u} \ r\acute{e}szgr\acute{a}fja \right\}$.
Tehát a \textsc{Teljes részgráf} azon $G$ és $k$ párokat tartalmazza, megfelelő ábécé feletti
szavakban elkódolva, melyekre igaz, hogy $G$-ben van $k$ csúcsú teljes részgráf,
azaz olyan részgráf, melyben bármely két csúcs között van él.\\
\noindent \textsc{Független csúcshalmaz} $= \left\{\langle G, k \rangle \ | \ G \ v\acute{e}ges \ gr\acute{a}f, k \geq 1, \ G-nek \ \exists \ k \ elem\tilde{u} \ f\ddot{u}ggetlen \ cs\acute{u}cshalmaza \right\}$.
Vagyis a \textsc{Független csúcshalmaz} azon $G$ és $k$ párokat tartalmazza, melyekre
igaz, hogy $G$-ben van $k$ olyan csúcs, melyek közül egyik sincs összekötve a
másikkal.\\
\noindent \textsc{Csúcslefedés} $=$\\
$\left\{\langle G, k \rangle \ | \begin{array}{lr}
\ G \ v\acute{e}ges \ gr\acute{a}f, k \geq 1, \ G-nek \ van \ olyan \ k \ elem\tilde{u} \ cs\acute{u}cshalmaza, \\
mely \ tartalmazza \ G \ minden \ \acute{e}l\acute{e}nek \ legal\acute{a}bb \ 1 \ v\acute{e}gpontj\acute{a}t.
\end{array}
\right\}$.\\
\noindent \textsc{Teljes részgráf}, \textsc{Független csúcshalmaz} és \textsc{Csúcslefedés} \textbf{NP}-teljesek
(\textsc{Teljes részgráf} $\leq_{p}$ \textsc{Független csúcshalmaz} $\leq_{p}$ \textsc{Csúcslefedés}).\\
\noindent \textsc{Utazóügynök} $=$\\
$\left\{\langle G, k \rangle \ |
\begin{array}{lr}
\ G \ v\acute{e}ges \ ir\acute{a}ny\acute{i}tatlan \ gr\acute{a}f, \ az \ \acute{e}leken \ egy-egy \
pozit\acute{i}v \ eg\acute{e}sz \ s\acute{u}llyal \ \acute{e}s \\
van \ G-ben \ legfeljebb \ k \ \ddot{o}sszs\acute{u}ly\acute{u} \ Hamilton \ k\ddot{o}r
\end{array}
\right\}$.\\
\noindent \textbf{Tétel}: Az \textsc{Utazóügynök} probléma \textbf{NP}-teljes.
\subsubsection{Tárbonyolultság}
A tárbonyolultságot egy speciális, úgynevezett offline Turing-gépen vizsgáljuk.\\
\noindent \textbf{Off-line Turing-gép}: Offline Turing-gépnek nevezünk egy olyan többszalagos Turing-gépet,
mely a bemenetet tartalmazó szalagot csak olvashatja, a többi, ún. munkaszalagokra
pedig írhat is. Az offline Turing-gép tárigényébe csak a munkaszalagokon
felhasznált terület számít be.\\
A továbbiakban Turing-gép alatt minidig offline Turing-gépet értünk. Most
definiáljuk a tárbonyolultsággal kapcsolatos nyelvosztályokat.\\
\noindent \textbf{SPACE}(f(n)) = $\left\{L|L \ eld\ddot{o}nthet\tilde{o} \ \mathcal{O}(f(n)) \ t\acute{a}rig\acute{e}ny\tilde{u} \
determinisztikus \ Turing-g\acute{e}ppel \right\}$\\
\noindent \textbf{NSPACE}(f(n)) = $\left\{L|L \ eld\ddot{o}nthet\tilde{o} \ \mathcal{O}(f(n)) \ t\acute{a}rig\acute{e}ny\tilde{u} \
nemdeterminisztikus \ Turing-g\acute{e}ppel \right\}$\\
\noindent \textbf{PSPACE} $=\bigcup_{k > 0}$ \textbf{SPACE}($n^{k}$)\\
\noindent \textbf{NPSPACE} $=\bigcup_{k > 0}$ \textbf{NSPACE}($n^{k}$)\\
\noindent \textbf{L} $=$ \textbf{SPACE}($\log_{2} n$) \\
\noindent \textbf{NL} $=$ \textbf{NSPACE}($\log_{2} n$) \\
\noindent \textbf{Savitch tétele}: Ha $f(n) \geq \log n$, akkor \textbf{NSPACE}($f(n)$) $\subseteq$ \textbf{SPACE}($f^{2}(n)$).
\end{document}

Binary file not shown.

View File

@@ -0,0 +1,773 @@
\documentclass[margin=0px]{article}
\usepackage{listings}
\usepackage[utf8]{inputenc}
\usepackage{graphicx}
\usepackage{float}
\usepackage[a4paper, margin=0.7in]{geometry}
\usepackage{amsthm}
\usepackage{amssymb}
\usepackage{fancyhdr}
\usepackage{setspace}
\onehalfspacing
\makeatletter
\renewcommand\paragraph{%
\@startsection{paragraph}{4}{0mm}%
{-\baselineskip}%
{.5\baselineskip}%
{\normalfont\normalsize\bfseries}}
\makeatother
\renewcommand{\figurename}{ábra}
\newenvironment{tetel}[1]{\paragraph{#1 \\}}{}
\pagestyle{fancy}
\lhead{\it{PTI BSc Záróvizsga tételek}}
\rhead{13.1 Logika}
\title{\textbf{{\Large ELTE IK - Programtervező Informatikus BSc} \vspace{0.2cm} \\ {\huge Záróvizsga tételek}} \vspace{0.3cm} \\ 13.1 Logika}
\author{}
\date{}
\begin{document}
\maketitle
\begin{tetel}{Logika}
Ítéletkalkulus és elsőrendű predikátumkalkulus: szintaxis, szemantika, ekvivalens átalakítások, a szemantikus következmény fogalma, rezolúció.
\end{tetel}
\section{Logika}
\subsection{Alapfogalmak}
A logika tárgya az emberi gondolkodási folyamat vizsgálata és
helyes gondolkodási formák keresése, illetve létrehozása.\\
\noindent Fogalmak:
\begin{enumerate}
\item \textbf{Állítás}: Olyan kijelentés, melynek logikai értéke (igaz
volta) eldönthető, tetszőleges kontextusban igaz vagy hamis. Azt mondjuk,
hogy egy állítás igaz, ha információtartalma megfelel a valóságnak (a tényeknek),
és hamis az ellenkező esetben.
A mindennapi beszédben használt kijelentő mondatok legtöbbször nem állítások, mivel
a mondat tartalmába a kontextus is beleszámít: időpont, környezet állapota, általános műveltség
bizonyos szintje, stb. (pl. nem állítás az, hogy "ma reggel 8-kor sütött a nap", de állítás pl. az, hogy
"minden páros szám osztható 2-vel").
\item \textbf{Igazságérték}: Az igazságértékek halmaza $\mathbb{L}=\left\{igaz,hamis\right\}$.
\item \textbf{Gondolkodási forma}: Gondolkodási forma alatt egy olyan $(F,A)$ párt értünk, ahol
$A$ állítás, $F=\left\{A_{1},A_{2},...,A_{n}\right\}$ pedig állítások egy halmaza.
A gondolkodásforma helyes, ha minden esetben, amikor $F$ minden állítása
igaz, akkor $A$ is igaz.
\end{enumerate}
\subsection{Ítéletkalkulus}
\subsubsection{Az ítéletlogika szintaxisa}
\paragraph{Az ítéletlogika ábécéje}
Az ítéletlogika ábécéje $V_{0}=V_{v} \cup \left\{(,)\right\} \cup \left\{\neg, \wedge, \vee, \supset\right\}$, ahol $V_{v}$ az
ítéletváltozók halmaza. Tehát $V_{0}$ az ítéletváltozókat, a zárójeleket, és a logikai műveletek jeleit tartalmazza.
\paragraph{Az ítéletlogika nyelve}
Az ítéletlogika nyelve ($\mathcal{L}_{0}$) ítéletlogikai formulákból áll, amelyek a következőképpen állnak elő:
\begin{enumerate}
\item Minden ítéletváltozó ítéletlogikai formula. Ezek az úgynevezett prímformulák (vagy atomi formulák).
\item Ha $A$ ítéletlogikai formula, akkor $\neg A$ is az.
\item Ha $A$ és $B$ ítéletlogikai formulák, akkor $(A \wedge B)$, $(A \vee B)$ és $(A \supset B)$ is
ítéletlogikai formulák.
\item Minden ítéletlogikai formula az 1-3. szabályok véges sokszori alkalmazásával áll elő.
\end{enumerate}
\noindent \textbf{Literál}: Ha $X$ ítéletváltozó, akkor az $X$ és $\neg X$ formulák literálok, amelyek alapja $X$.\\
\noindent \textbf{Közvetlen részformula}:
\begin{enumerate}
\item Prímformulának nincs közvetlen részformulája.
\item $\neg A$ közvetlen részformulája $A$.
\item $A \circ B$ ($\circ$ a $\wedge, \vee, \supset$ binér összekötőjelek egyike) közvetlen részformulái $A$ (bal oldali)
és $B$ (jobb oldali).
\end{enumerate}
\noindent \textbf{Részformula}: Legyen $A \in \mathcal{L}_{0}$ egy ítéletlogikai formula. Ekkor $A$ részformuláinak
halmaza a legszűkebb olyan halmaz, melynek
\begin{enumerate}
\item eleme az $A$, és
\item ha a C formula eleme, akkor C közvetlen részformulái is elemei.
\end{enumerate}
\noindent \textbf{Szerkezeti fa}: Egy C formula szerkezeti fája egy olyan véges rendezett fa, melynek csúcsai formulák,
\begin{enumerate}
\item gyökere C,
\item a $\neg A$ csúcsának pontosan egy gyermeke van, az $A$,
\item a $A \circ B$ csúcsának pontosan két gyermeke van, rendre az $A$ és $B$ formulák,
\item levelei prímformulák.
\end{enumerate}
\begin{figure}[H]
\centering
\includegraphics[width=0.3\linewidth]{img/szerkfa}
\caption{Példa szerkezeti fára.}
\label{fig:szerkfa}
\end{figure}
\noindent \textbf{Logikai összetettség}: Egy formula logikai összetettsége a benne található logikai összekötőjelek száma.\\
\noindent \textbf{Művelet hatásköre}: Egy művelet hatásköre a formula részformulái közül az
a legkisebb logikai összetettségű részformula, melyben az adott művelet előfordul.\\
\noindent \textbf{Fő logikai összekötőjel}: Egy formula fő logikai összekötőjele az az összekötőjel, amelynek
hatásköre maga a formula.\\
\noindent \textbf{Precedencia}: A logikai összekötőjelek precedenciája csökkenő sorrendben a következő: $\neg, \wedge, \vee, \supset$.\\
A definíciók alapján egyértelmű, hogy egy \textit{teljesen zárójelezett formulában} mi a logikai összekötőjelek hatásköre és mi a fő
logikai összekötőjel. Most megmutatjuk, hogy egy formulában milyen esetekben és mely részformulákat határoló zárójelek hagyhatóak el úgy, hogy a logikai összekötőjelek hatásköre ne változzon. A részformulák közül a prímformuláknak és a negációs formuláknak nincs külső zárójelpárja, ezért csak az $(A \circ B)$ alakú részformulákról kell eldöntenünk, hogy írható-e helyettük $A \circ B$. A zárójelek elhagyását
mindig a formula külső zárójelpárjának (ha van ilyen) elhagyásával kezdjük. Majd ha egy részformulában már megvizsgáltuk a külső zárójelelhagyás kérdését, utána ezen részformula közvetlen részformuláinak külső zárójeleivel foglalkozunk. Két eset lehetséges:
\begin{enumerate}
\item A részformula egy negációs formula, melyben az $(A \circ B)$ alakú közvetlen részformula külső zárójelei nem hagyhatók el.
\item A részformula egy $(A \bullet B)$ vagy $A \bullet B$ alakú formula, melynek $A$ és $B$ közvetlen részformuláiban kell dönteni a külső zárójelek sorsáról. Ha az $A$ formula $A_{1} \circ A_{2}$ alakú, akkor $A$ külső zárójelpárja akkor hagyható el, ha $\circ$ nagyobb precedenciájú, mint $\bullet$. Ha a $B$ formula $B_{1} \circ B_{2}$ alakú, akkor $B$ külső zárójelpárja akkor hagyható el, ha $\circ$ nagyobb vagy egyenlő precedenciájú, mint $\bullet$.
\item Ha egy $(A \wedge B)$ vagy $A \wedge B$ alakú formula valamely közvetlen részformulája szintén konjunkció, illetve egy
$(A \vee B)$ vagy $A \vee B$ alakú formula valamely közvetlen részformulája szintén diszjunkció, akkor az ilyen részformulákból a külső zárójelpár elhagyható.
\end{enumerate}
\noindent \textbf{Formulaláncok}: A zárójelek elhagyására vonatkozó megállapodásokat figyelembe véve úgynevezett konjunkciós, diszjunkciós, illetve implikációs formulaláncokat is nyerhetünk. Ezek alakja $A_{1} \wedge ... \wedge A_{n}$, $A_{1} \vee ... \vee A_{n}$, illetve
$A_{1} \supset ... \supset A_{n}$ Ezeknek a láncformuláknak a fő logikai összekötőjelét a következő zárójelezési megállapodással fogjuk meghatározni: $(A_{1} \wedge (A_{2} \wedge ... \wedge (A_{n-1} \wedge A_{n})...))$, $(A_{1} \vee (A_{2} \vee ... \vee (A_{n-1} \vee A_{n})...))$, illetve $(A_{1} \supset (A_{2} \supset ... \supset (A_{n-1} \supset A_{n})...))$
\subsubsection{Az ítéletlogika szemantikája}
\noindent \textbf{Interpretáció}: $\mathcal{L}_{0}$ interpretációján egy $\mathcal{I} : V_{v} \to \mathbb{L}$ függvényt értünk, mely minden ítéletváltozóhoz egyértelműen hozzárendel egy igazságértéket.\\
\noindent \textbf{Boole-értékelés}: $\mathcal{L}_{0}$-beli formulák $\mathcal{I}$ \textit{interpretációbeli Boole-értékelése} a következő $\mathcal{B}_{\mathcal{I}} : \mathcal{L}_{0} \to \mathbb{L}$ függvény:
\begin{enumerate}
\item ha $A$ prímformula, akkor $\mathcal{B}_{\mathcal{I}}(A) = \mathcal{I}(A)$,
\item $\mathcal{B}_{\mathcal{I}}(\neg A)$ legyen $\neg \mathcal{B}_{\mathcal{I}}(A) $,
\item $\mathcal{B}_{\mathcal{I}}(A \wedge B)$ legyen $\mathcal{B}_{\mathcal{I}}(A) \wedge \mathcal{B}_{\mathcal{I}}(B)$,
\item $\mathcal{B}_{\mathcal{I}}(A \vee B)$ legyen $\mathcal{B}_{\mathcal{I}}(A) \vee \mathcal{B}_{\mathcal{I}}(B)$,
\item $\mathcal{B}_{\mathcal{I}}(A \supset B)$ legyen $\mathcal{B}_{\mathcal{I}}(A) \supset \mathcal{B}_{\mathcal{I}}(B)$,
\end{enumerate}
\noindent \textbf{Bázis}: A formula ítéletváltozóinak egy rögzített sorrendje.\\
\noindent \textbf{Szemantikus fa}: Egy formula különböző interpretációit szemantikus fa segítségével szemléltethetjük. A szemantikus
fa egy olyan bináris fa, amelynek $i$. szintje ($i>=1$) a bázis $i$. ítéletváltozójához tartozik, és minden csúcsából két él indul, az
egyik a szinthez rendelt ítéletváltozóval, a másik annak negáltjával címkézve. Az $X$ ítéletváltozó esetén az $X$ címke jelentse azt, hogy az $X$ \textit{igaz} az adott interpretációban, a $\neg X$ címke pedig azt, hogy \textit{hamis} az adott interpretációban. A szemantikus fa
minden ága egy-egy lehetséges interpretációt reprezentál. Egy $n$ változós formula esetén minden ág $n$ hosszú, és a fának $2^{n}$ ága van és az összes lehetséges interpretációt tartalmazza.
\begin{figure}[H]
\centering
\includegraphics[width=0.6\linewidth]{img/szemantikusfa}
\caption{Az X,Y,Z ítéletváltozókat tartalmazó formula szemantikus fája.}
\label{fig:szemantikusfa}
\end{figure}
\noindent \textbf{Igazságtábla}: Egy $n$ változós formula igazságtáblája egy $n+1$ oszlopból és $2^{n}$ sorból álló táblázat.
A táblázat fejlécében az $i$. oszlophoz ($1<=i<=n$) a formula bázisának $i$. ítéletváltozója, az $n+1$. oszlophoz maga a formula
van hozzárendelve. Az első $n$ oszlopban az egyes sorokhoz megadjuk rendre a formula különböző interpretációit, majd a formula
oszlopába minden sorba beírjuk a formula - a sorhoz tartozó interpretációbeli Boole-értékeléssel kapott - igazságértékét.\\
\noindent \textbf{A logikai műveletek igazságtáblája}:
\begin{table}[H]
\begin{tabular}{ll|lllll}
X & Y & $\neg X$ & $X \wedge Y$ & $X \vee Y$ & $ X \supset Y$ & \\ \hline
i & i & h & i & i & i & \\
i & h & h & h & i & h & \\
h & i & i & h & i & i & \\
h & h & i & h & h & i &
\end{tabular}
\end{table}
\noindent \textbf{Igazhalmaz, hamishalmaz}: Egy $A$ formula igazhalmaza $(A^{i})$
azon interpretációk halmaza, melyen a formula igazságértékelése igaz. Az $A$ formula
hamishalmaza $(A^{h})$ pedig azon interpretációk halmaza, melyekre a formula igazságértékelése hamis.\\
\noindent \textbf{Igazságértékelés függvény}: Olyan függvény, amely minden formulához hozzárendeli az igazhalmazát ($\varphi A^{i}$) vagy
a hamishalmazát ($\varphi A^{h}$).\\
Legyen $A$ egy tetszőleges ítéletlogikai formula. Határozzuk meg $A$-hoz az interpretációira vonatkozó $\varphi A^{i}$, illetve
$\varphi A^{h}$ feltételeket a következőképpen:
\begin{enumerate}
\item Ha $A$ prímformula, a $\varphi A^{i}$ feltételt pontosan azok az $\mathcal{I}$ interpretációk elégítik ki, melyekre
$\mathcal{I}(A)=igaz$, a $\varphi A^{h}$ feltételt pedig pontosan azok melyekre $\mathcal{I}(A)=hamis$.
\item A $\varphi (\neg A)^{i}$ feltételek pontosan akkor teljesülnek, ha teljesülnek a $\varphi A^{h}$ feltételek.
\item A $\varphi (A \wedge B)^{i}$ feltételek pontosan akkor teljesülnek, ha a $\varphi A^{i}$ és a $\varphi B^{i}$ feltételek egyszerre teljesülnek.
\item A $\varphi (A \vee B)^{i}$ feltételek pontosan akkor teljesülnek, ha a $\varphi A^{i}$ vagy a $\varphi B^{i}$ feltételek teljesülnek.
\item A $\varphi (A \supset B)^{i}$ feltételek pontosan akkor teljesülnek, ha a $\varphi A^{h}$ vagy a $\varphi B^{i}$ feltételek teljesülnek.
\end{enumerate}
\noindent \textbf{Tétel}: Tetszőleges $A$ ítéletlogikai formula esetén a $\varphi A^{i}$ feltételeket pontosan az $A^{i}$-beli
interpretációk teljesítik.\\
\noindent \textbf{Igazságértékelés-fa}: Egy $A$ formula $\varphi A^{i}$, illetve $\varphi A^{h}$ feltételeket kielégítő interpretációit
az igazságértékelés-fa segítségével szemléltethetjük. Az igazságértékelés-fát a formula szerkezeti fájának felhasználásával állítjuk elő.
A gyökérhez hozzárendeljük, hogy $A$ melyik igazságértékre való igazságértékelés-feltételeit keressük, majd a gyökér alá $A$ közvetlen részformulái kerülnek a megfelelő feltétel-előírással, az alábbiak szerint:
\begin{figure}[H]
\centering
\includegraphics[width=0.7\linewidth]{img/igazsagertfa}
\caption{Igazságértékelés-fa feltétel-előírásai.}
\label{fig:igazsagertfa}
\end{figure}
Ezután a gyökérhez a \checkmark (feldolgozott) jelet rendeljük. Az eljárást rekurzívan folytatjuk, amíg egy ágon a fel nem dolgozott
formulák
\begin{itemize}
\item (a) mind ítéletváltozók nem lesznek, vagy
\item (b) ugyanarra a formulára egymásnak ellentmondó előírás nem jelenik meg.
\end{itemize}
Az (a) esetben az ágon előforduló ítéletváltozóknak az ágon rögzített igazságértékeit tartalmazó $n$-esek mind elemei $\varphi A^{i}$
gyökér esetén a formula igazhalmazának, $\varphi A^{h}$ gyökér esetén a formula hamishalmazának.
A (b) esetben nem áll elő ilyen igazságérték $n$-es.
\begin{figure}[H]
\centering
\includegraphics[width=0.5\linewidth]{img/igazsagertfapelda}
\caption{Az $(Y \vee Z) \wedge (Z \supset \neg X)$ formula igazságértékelés-fája.}
\label{fig:igazsagertfapelda}
\end{figure}
\noindent A fenti példában a formula igazhalmaza az igazságértékelés-fa alapján: $\left\{(i,i,h),(h,i,i),(h,i,h),(h,h,i)\right\}$\\
\noindent \textbf{Kiterjesztett igazságtábla}: Egy igazságtáblában a formula igazságértéke kiszámításának megkönnyítésére vezették
be a kiterjesztett igazságtáblát. A kiterjesztett igazságtáblában az ítéletváltozókhoz és a formulához rendelt oszlopokon kívül rendre
a formula részformuláihoz tartozó oszlopok is megjelennek. Tulajdonképpen a szerkezeti fában megjelenő részformulák vannak felsorolva.
\begin{figure}[H]
\centering
\includegraphics[width=0.5\linewidth]{img/kiterjigaztabla}
\caption{Az $(Y \vee Z) \wedge (Z \supset \neg X)$ formula kiterjesztett igazságtáblája.}
\label{fig:kiterjigaztabla}
\end{figure}
\noindent \textbf{Formula kielégíthetősége, modellje}: Egy $A$ ítéletlogikai formula \textit{kielégíthető}, ha létezik olyan $\mathcal{I}$
interpretáció, melyre $\mathcal{I} \models_{0} A$, azaz a $\mathcal{B}_{\mathcal{I}}$ Boole-értékelés $A$-hoz igaz értéket rendel. Egy
ilyen interpretációt $A$ \textit{modelljének} nevezünk. Ha $A$-nak nincs modellje, akkor azt mondjuk, hogy \textit{kielégíthetetlen}.
Ha $A$ igazságtáblájában van olyan sor, amelyben a formula oszlopában igaz érték szerepel, akkor a formula kielégíthető, különben kielégíthetetlen. Ugyanígy, ha $\varphi A^{i}$ nem üres, akkor kielégíthető, különben kielégíthetetlen.\\
\noindent \textbf{Ítéletlogikai törvény, tautológia}: Egy $A$ ítéletlogikai formula \textit{ítéletlogikai törvény} vagy másképpen \textit{tautológia}, ha $\mathcal{L}_{0}$ minden interpretációja modellje $A$-nak. (jelölés: $\models_{0} A$)\\
\noindent \textbf{Eldöntésprobléma}: Eldöntésproblémának nevezzük a következő feladatokat:
\begin{enumerate}
\item Döntsük el tetszőleges formuláról, hogy tautológia-e!
\item Döntsük el tetszőleges formuláról, hogy kielégíthetetlen-e!
\end{enumerate}
\noindent \textbf{Tautologikusan ekvivalens formulák}: Az $A$ és $B$ ítéletlogikai formulák \textit{tautologikusan ekvivalensek} (jelölés: $A \sim _{0} B$), ha $\mathcal{L}_{0}$ minden $\mathcal{I}$ interpretációjában $\mathcal{B}_{\mathcal{I}}(A)=\mathcal{B}_{\mathcal{I}}(B)$.\\
\noindent \textbf{Formulahalmaz kielégíthetősége, modellje}: $\mathcal{L}_{0}$ formuláinak egy tetszőleges $\Gamma$ halmaza
kielégíthető, ha van $\mathcal{L}_{0}$-nak olyan $\mathcal{I}$ interpretációja, melyre: $\forall A \in \Gamma: \mathcal{I} \models_{0} A$.
Egy ilyen $\mathcal{I}$ interpretáció modellje $\Gamma$-nak. Ha $\Gamma$-nak nincs modellje, akkor $\Gamma$ kielégíthetetlen.\\
\noindent \textbf{Lemma}: Egy $\left\{A_{1},A_{2},...,A_{n}\right\}$ formulahalmaznak pontosan azok az $\mathcal{I}$ interpretációk
a modelljei, amelyek a $A_{1} \wedge A_{2} \wedge ... \wedge A_{n}$ formulának. Következésképpen $\left\{A_{1},A_{2},...,A_{n}\right\}$
pontosan akkor kielégíthetetlen, ha az $A_{1} \wedge A_{2} \wedge ... \wedge A_{n}$ formula kielégíthetlen.\\
\noindent \textbf{Szemantikus következmény}: Legyen $\Gamma$ ítéletlogikai formulák tetszőleges halmaza, $B$ egy tetszőleges formula.
Azt mondjuk, hogy a $B$ formula \textit{tautologikus következménye} a $\Gamma$ formulahalmaznak (jelölés: $\Gamma \models_{0} B$), ha minden olyan interpretáció, amely modellje $\Gamma$-nak, modellje $B$-nek is. A $\Gamma$-beli formulákat feltételformuláknak, vagy premisszáknak,
a B formulát következményformulának (konklúziónak) hívjuk.\\
\noindent \textbf{Tétel}: Legyen $\Gamma$ ítéletlogikai formulák tetszőleges halmaza, $A$,$B$,$C$ tetszőleges ítéletlogikai formulák.
Ha $\Gamma \models_{0} A$, $\Gamma \models_{0} B$ és $\left\{A,B\right\} \models_{0} C$, akkor $\Gamma \models_{0} C$.\\
\noindent \textbf{Tétel}: Legyenek $A_{1},A_{2},...,A_{n}, B$ tetszőleges ítéletlogikai formulák.
$\left\{A_{1},A_{2},...,A_{n}\right\} \models_{0} B$ pontosan akkor, ha a $\left\{A_{1},A_{2},...,A_{n}, \neg B\right\}$
formulahalmaz kielégíthetetlen, azaz a $A_{1} \wedge A_{2} \wedge ... \wedge A_{n} \wedge \neg B$ formula kielégíthetetlen.\\
\noindent \textbf{Tétel}: Legyenek $A_{1},A_{2},...,A_{n}, B$ tetszőleges ítéletlogikai formulák.
$\left\{A_{1},A_{2},...,A_{n}\right\} \models_{0} B$ pontosan akkor, ha
$\models_{0} A_{1} \wedge A_{2} \wedge ... \wedge A_{n} \supset B$.\\
\paragraph{Ekvivalens átalakítások}
Fogalmak:
\begin{enumerate}
\item Egy prímformulát (ítéletváltozót), vagy annak a negáltját közös néven \textit{literálnak} nevezünk. A prímformula
a \textit{literál alapja}. Egy literált bizonyos esetekben \textit{egységkonjunkciónak} vagy \textit{egységdiszjunkciónak}
(\textit{egységklóznak}) is hívunk.
\item \textit{Elemi konjunkció} az egységkonjunkció, illetve a különböző alapú literálok konjunkciója ($\wedge$ kapcsolat
a literálok között). \textit{Elemi diszjunkció} vagy \textit{klóz} az egységdiszjunkció és a különböző alapú literálok
diszjunkciója ($\vee$ kapcsolat a literálok között). Egy elemi konjunkció, illetve elemi diszjunkció \textit{teljes}
egy $n$-változós logikai műveletre nézve, ha mind az $n$ ítéletváltozó alapja valamely literáljának.
\item \textit{Diszjunktív normálformának} (DNF) nevezzük az elemi konjunkciók diszjunkcióját.
\textit{Konjunktív normálformának} (KNF) nevezzük az elemi diszjunkciók konjunkcióját. \textit{Kitüntetett}
diszjunktív, illetve konjunktív normálformákról (KDNF, ileltve KKNF) beszélünk, ha a bennük szereplő
elemi konjunkciók, illetve elemi diszjunkciók teljesek.
\end{enumerate}
\noindent \textbf{Tetszőleges logikai műveletet leíró KDNF, KKNF előállítása}: Legyen $b: \mathbb{L}^{n} \to \mathbb{L}$
egy $n$-változós logikai művelet. Adjuk meg $b$ művelettábláját.
Az első $n$ oszlop fejlécébe az $X_{1}$, $X_{2}$, ... $X_{n}$ ítéletváltozókat írjuk.\\
\noindent A $b$-t leíró KDNF előállítása:
\begin{enumerate}
\item Válasszuk ki azokat a sorokat a művelettáblában, ahol az adott igazságérték $n$-eshez $b$ \textit{igaz}
értéket rendel hozzá. Legyenek ezek a sorok rendre $s_{1}, s_{2}, .. s_{r}$. Minden ilyen sorhoz rendeljünk
hozzá egy $X_{1}' \wedge X_{2}' \wedge ... \wedge X_{n}'$ teljes elemi konjunkciót úgy, hogy az $X_{j}'$ literál
$X_{j}$ vagy $\neg X_{j}$ legyen aszerint, hogy ebben a sorban $X_{j}$ \textit{igaz} vagy \textit{hamis} igazságérték
szerepel. Az így nyert teljes elemi konjunkciók legyenek rendre $k_{s_{1}}, k_{s_{2}}, .. k_{s_{r}}$.
\item Az így kapott teljes elemi konjunkciókból készítsünk egy diszjunkciós láncformulát:
$k_{s_{1}} \vee k_{s_{2}} \vee ... \vee k_{s_{r}}$. Ez a formula lesz a $b$ művelet kitüntetett diszjunktív
normálformája (KDNF).
\end{enumerate}
\begin{figure}[H]
\centering
\includegraphics[width=0.5\linewidth]{img/kdnf_pelda}
\caption{Egy háromváltozós $b$ logikai művelet művelettáblája és az előállított teljes elemi konjunkciók.}
\label{fig:kdnf_pelda}
\end{figure}
A fenti példa $b$ műveletének kitüntetett diszjunktív normálformája a következő formula:\\
$(X \wedge Y \wedge \neg Z) \vee (X \wedge \neg Y \wedge \neg Z) \vee (\neg X \wedge Y \wedge Z) \vee (\neg X \wedge \neg Y \wedge Z) \vee (\neg X \wedge \neg Y \wedge \neg Z)$.\\
\noindent A $b$-t leíró KKNF előállítása:
\begin{enumerate}
\item Válasszuk ki azokat a sorokat a művelettáblában, ahol az adott igazságérték $n$-eshez $b$ \textit{hamis}
értéket rendel hozzá. Legyenek ezek a sorok rendre $s_{1}, s_{2}, .. s_{r}$. Minden ilyen sorhoz rendeljünk
hozzá egy $X_{1}' \vee X_{2}' \vee ... \vee X_{n}'$ teljes elemi diszjunkciót úgy, hogy az $X_{j}'$ literál
$X_{j}$ vagy $\neg X_{j}$ legyen aszerint, hogy ebben a sorban $X_{j}$ \textit{hamis} vagy \textit{igaz} igazságérték
szerepel. Az így nyert teljes elemi diszjunkciók legyenek rendre $d_{s_{1}}, d_{s_{2}}, .. d_{s_{r}}$.
\item Az így kapott teljes elemi diszjunkciókból készítsünk egy konjunkciós láncformulát:
$d_{s_{1}} \wedge d_{s_{2}} \wedge ... \wedge d_{s_{r}}$. Ez a formula lesz a $b$ művelet kitüntetett konjunktív
normálformája (KKNF).
\end{enumerate}
\begin{figure}[H]
\centering
\includegraphics[width=0.5\linewidth]{img/kknf_pelda}
\caption{Egy háromváltozós $b$ logikai művelet művelettáblája és az előállított teljes elemi diszjunkciók.}
\label{fig:kknf_pelda}
\end{figure}
A fenti példa $b$ műveletének kitüntetett konjunktív normálformája a következő formula:\\
$(\neg X \vee \neg Y \vee \neg Z) \wedge (\neg X \vee Y \vee \neg Z) \wedge (X \vee Y \vee \neg Z)$. \\
\noindent \textbf{KNF, DNF egyszerűsítése}: Egy ítéletlogikai formula logikai összetettségén a formulában szereplő
logikai összekötőjelek számát értettük. Ugyanazt a logikai műveletet leíró formulák közül azt tekintjük egyszerűbbnek,
amelynek kisebb a logikai összetettsége (azaz kevesebb logikai összekötőjelet tartalmaz).
Legyen $X$ egy ítéletváltozó $k$ egy az $X$-et nem tartalmazó elemi konjunkció, $d$ egy $X$-et nem tartalmazó elemi
diszjunkció. Ekkor az
\begin{itemize}
\item (a) $(X \wedge k) \vee (\neg X \wedge k) \sim_{0} k $ és
\item (b) $(X \vee d) \wedge (\neg X \vee d) \sim_{0} d $
\end{itemize}
egyszerűsítési szabályok alkalmazásával konjunktív és diszjunktív normálformákat írhatunk át egyszerűbb alakba.\\
\noindent Klasszikus Quine--McCluskey-féle algoritmus KDNF egyszerűsítésére:
\begin{enumerate}
\item Soroljuk fel a KDNF-ben szereplő összes teljes elemi konjunkciót az $L_{0}$ listában, $j:=0$.
\item Megvizsgáljuk az $L_{j}$-ben szereplő összes lehetséges elemi konjunkciópárt, hogy alkalmazható-e
rájuk az (a) egyszerűsítési szabály. Ha igen, akkor a két kiválasztott konjunkciót $\checkmark$-val megjelöljük,
és az eredmény konjunkciót beírjuk a $L_{j+1}$ listába. Azok az elemi konjunkciók, amelyek az $L_{j}$ vizsgálata
során nem lesznek megjelölve, nem voltak egyszerűsíthetők, tehát bekerülnek az egyszerűsített diszjunktív
normálformába.
\item Ha az $L_{j+1}$ konjunkciólista nem üres, akkor $j:=j+1$. Hajtsuk végre újból a 2. lépést.
\item Az algoritmus során kapott, de meg nem jelölt elemi konjunkciókból készítsünk egy diszjunkciós
láncformulát. Így az eredeti KDNF-el logikailag ekvivalens, egyszerűsített DNF-et kapunk.
\end{enumerate}
\paragraph{Rezolúció}
Legyenek $A_{1}, A_{2}, ... , A_{n}, B$ tetszőleges ítéletlogikai formulák.
Azt szeretnénk bebizonyítani, hogy $\left\{A_{1}, A_{2}, ... , A_{n}\right\} \models_{0} B$,
ami ekvivalens azzal, hogy $\left\{A_{1}, A_{2}, ... , A_{n}, \neg B\right\}$ kielégíthetetlen.
Írjuk át ez utóbbi formulahalmaz formuláit KNF alakba! Ekkor a
$\left\{KNF_{A_{1}}, KNF_{A_{2}}, ... , KNF_{A_{n}}, KNF_{\neg B}\right\}$ formulahalmazt
kapjuk, ami pontosan akkor kielégíthetetlen, ha a halmaz formuláiban szereplő klózok halmaza
kielégíthetetlen.
A klózokra vonatkozó egyszerűsítési szabály szerint ha $X$ ítéletváltozó, $C$ pedig $X$-et nem
tartalmazó klóz, akkor $(X \vee C) \wedge (\neg X \vee C) \sim_{0} C$. Az $X$ és a $\neg X$
egységklózok (azt mondjuk, hogy $X$ és $\neg X$ komplemens literálpár) konjunkciójával ekvivalens
egyszerűbb, egyetlen literált sem tartalmazó klóz az üres klóz, melyet a $\square$ jellel
jelölünk és definíció szerint minden interpretációban hamis igazságértékű.
Legyenek most $C_{1}$ és $C_{2}$ olyan klózok, melyek pontosan egy komplemens literálpárt tartalmaznak,
azaz $C_{1} = C_{1}' \vee L_{1}$ és $C_{2} = C_{2}' \vee L_{2}$, ahol $L_{1}$ és $L_{2}$ az egyetlen
komplemens literálpár ($C_{1}'$ és $C_{2}'$ üres klózok is lehetnek). Világos, hogy ha a két klózban
a komplemens literálpáron kívül is vannak literálok, és ezek nem mind azonosak, az egyszerűsítési
szabály alkalmazhatósági feltétele nem áll fenn.\\
\noindent \textbf{Tétel}: Ha $C_{1} = C_{1}' \vee L_{1}$ és $C_{2} = C_{2}' \vee L_{2}$,
ahol $L_{1}$ és $L_{2}$ komplemens literálpár, akkor $\left\{C_{1},C_{2}\right\} \models_{0} C_{1}' \vee C_{2}'$\\
\noindent \textbf{Rezolvens}: Legyenek $C_{1}$ és $C_{2}$ olyan klózok, melyek pontosan egy komplemens literálpárt tartalmaznak,
azaz $C_{1} = C_{1}' \vee L_{1}$ és $C_{2} = C_{2}' \vee L_{2}$, ahol $L_{1}$ és $L_{2}$ a komplemens literálpár,
a $C_{1}' \vee C_{2}'$ klózt a $(C_{1},C_{2})$ klózpár (vagy a $C_{1} \vee C_{2}$ formula) \textit{rezolvensének} nevezzük.
Ha $C_{1} = L_{1}$ és $C_{2} = L_{2}$ (azaz $C_{1}'$ és $C_{2}'$ üres klózok), rezolvensük az üres klóz ($\square$).
Az a tevékenység, melynek eredménye a rezolvens, a \textit{rezolválás}.
\begin{figure}[H]
\centering
\includegraphics[width=0.7\linewidth]{img/rezolvens}
\caption{Példák klózpárok rezolválhatóságára, rezolvensére.}
\label{fig:rezolvens}
\end{figure}
\noindent \textbf{Tétel}: Ha a $C$ klóz a $(C_{1},C_{2})$ klózpár rezolvense, akkor azon $\mathcal{I}$ interpretációk
a $\left\{C_{1}, C_{2}\right\}$ klózhalmazt nem elégíthetik ki, amelyekben $C$ igazságértéke hamis, azaz
$\mathcal{B}_{\mathcal{I}}(C) = hamis$.\\
\noindent \textbf{Rezolúciós levezetés}: Egy $S$ klózhalmazból a $C$ klóz rezolúciós levezetése egy olyan véges
$k_{1}, k_{2}, ... ,k_{m} (m \geq 1)$ klózsorozat, ahol minden $j = 1, 2, ..., m$-re
\begin{enumerate}
\item vagy $k_{j} \in S$,
\item vagy van olyan $1 \leq s,t \le j$, hogy $k_{j}$ a $(k_{s}, k_{t})$ klózpár rezolvense,
\end{enumerate}
\noindent és a klózsorozat utolsó tagja, $k_{m}$, éppen a $C$ klóz.
Megállapodásunk szerint a rezolúciós kalkulus eldöntésproblémája az, hogy levezethető-e $S$-ből $\square$. A
rezolúciós levezetés célja tehát $\square$ levezetése $S$-ből. Azt, hogy $\square$ levezethető $S$-ből,
úgy is ki lehet fejezni, hogy létezik $S$-nek rezolúciós cáfolata.\\
\noindent Példa: Próbáljuk meg levezetni $\square$-t az
$S = \left\{\neg X \vee Y, \neg Y \vee Z, X \vee Z, \neg V \vee Y \vee Z, \neg Z \right\}$
klózhalmazból. A levezetés bármelyik $S$-beli klózból indítható.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\linewidth]{img/rezoluciopelda}
\caption{$\square$ rezolúciós levezetése $S$-ből.}
\label{fig:rezoluciopelda}
\end{figure}
\noindent \textbf{Lemma}: Legyen $S$ tetszőleges klózhalmaz. $S$-ből történő rezolúciós levezetés esetén bármely $S$-ből
levezetett klóz tautologikus következménye $S$-nek.\\
\noindent \textbf{A rezolúciós kalkulus helyessége}: A rezolúciós kalkulus \textit{helyes}, azaz tetszőleges
$S$ klózhalmaz esetén amennyiben $S$-ből levezethető $\square$, akkor $S$ \textit{kielégíthetetlen}.\\
\noindent \textbf{A rezolúciós kalkulus teljessége}: A rezolúciós kalkulus \textit{teljes}, azaz bármely véges, kielégíthetetlen
$S$ klózhalmaz esetén $S$-ből levezethető $\square$.\\
\noindent \textbf{Levezetési fa}: Egy rezolúciós levezetés szerkezetét \textit{levezetési fa} segítségével szemléltethetjük.
A levezetési fa csúcsai klózok. Két csúcsból pontosan akkor vezet él egy harmadik, közös csúcsba, ha az a két klóz rezolvense.
\begin{figure}[H]
\centering
\includegraphics[width=0.5\linewidth]{img/rezoluciopelda_levfa}
\caption{Az előző példa levezetési fája.}
\label{fig:rezoluciopelda_levfa}
\end{figure}
\noindent \textbf{Rezolúciós stratégiák}:
\begin{itemize}
\item \textit{Lineáris rezolúció}: Egy $S$ klózhalmazból való lineáris rezolúciós levezetés egy olyan
$k_{1},l_{1},k_{2},l_{2}, ..., k_{m-1},l_{m-1}, k_{m}$ rezolúciós levezetés, amelyben minden
$j = 2, 3, ..., m$-re $k_{j}$ a $(k_{j-1},l_{j-1})$ klózpár rezolvense. A $k_{j}$ klózokat centrális
klózoknak, az $l_{j}$ klózokat mellékklózoknak nevezzük.
Tetszőleges rezolúciós levezetés átírható lineárissá, azaz a lineáris rezolúciós kalkulus teljes.
\item \textit{Lineáris inputrezolúció}: Egy $S$ klózhalmazból való lineáris inputrezolúciós levezetés
egy olyan $k_{1},l_{1},k_{2},l_{2}, ..., k_{m-1},l_{m-1}, k_{m}$ lineáris rezolúciós levezetés, amelyben minden
$j = 1, 2, ..., m-1$-re $l_{j} \in S$, azaz a lineáris inputrezolúciós levezetésben a mellékklózok $S$ elemei.
A lineáris inputrezolúciós stratégia nem teljes, de megadható olyan formulaosztály, melyre az. A legfeljebb egy
negált literált tartalmazó klózokat Horn-klózoknak nevezzük, a Horn-formulák pedig azok a formulák, melyek
konjunktív normálformája Horn-klózok konjunkciója. A lineáris inputrezolúciós stratégia Horn-formulák esetén teljes.
\end{itemize}
\subsection{Predikátumkalkulus}
\subsubsection{Elsőrendű logikai nyelvek szintaxisa}
Egy elsőrendű logikai nyelv ábécéje logikai és logikán kívüli szimbólumokat, továbbá elválasztójeleket tartalmaz.
A logikán kívüli szimbólumhalmaz megadható $<Srt, Pr, Fn, Cnst>$ alakban, ahol:
\begin{enumerate}
\item $Srt$ nemüres halmaz, elemei fajtákat szimbolizálnak,
\item $Pr$ nemüres halmaz, elemei predikátumszimbólumok,
\item az $Fn$ halmaz elemei függvényszimbólumok,
\item $Cnst$ pedig a függvényszimbólumok halmaza.
\end{enumerate}
\noindent Az $<Srt, Pr, Fn, Cnst>$ ábécé szignatúrája egy $<\nu_{1}, \nu_{2}, \nu_{3}>$ hármas, ahol
\begin{enumerate}
\item minden $P \in Pr$ predikátumszimbólumhoz $\nu_{1}$ a predikátumszimbólum alakját,
azaz a $(\pi_{1}, \pi_{2}, ..., \pi_{k})$ fajtasorozatot,
\item minden $f \in Fn$ függvényszimbólumhoz $\nu_{2}$ a függvényszimbólum alakját,
azaz a $(\pi_{1}, \pi_{2}, ..., \pi_{k}, \pi)$ fajtasorozatot és
\item minden $c \in Cnst$ konstansszimbólumhoz $\nu_{3}$ a konstansszimbólumhoz alakját,
azaz $(\pi)$-t
\end{enumerate}
\noindent rendel ($k > 0$ és $\pi_{1}, \pi_{2}, ..., \pi_{k}, \pi \in Srt$).
Logikai jelek az ítéletlogikában is használt logikai összekötőjelek, valamint az univerzális ($\forall$)
és egzisztenciális ($\exists$) kvantorok és a különböző fajtájú individuumváltozók. Egy elsőrendű
nyelv ábécéjében minden $\pi \in Srt$ fajtához szimbólumoknak megszámlálhatóan végtelen
$v_{1}^{\pi}, v_{2}^{\pi}, ...$ rendszere tartozik, ezeket a szimbólumokat nevezzük $\pi$ fajtájú
változóknak. Elválasztójel a nyitó és csukó zárójelek, és a vessző.
Az elsőrendű logikai nyelvekben az elválasztójelek és a logikai jelek mindig ugyanazok, viszont
a logikán kívüli jelek halmaza, illetve ezek szignatúrája nyelvről nyelvre lényegesen különbözhet.
Ezért mindig megadjuk a $<Srt, Pr, Fn, Cnst>$ négyest és ennek $<\nu_{1}, \nu_{2}, \nu_{3}>$
szignatúráját, amikor egy elsőrendű logikai nyelv ábécéjére hivatkozunk. Jelölése $V[V_{\nu}]$,
ahol $V_{\nu}$ adja meg a $<\nu_{1}, \nu_{2}, \nu_{3}>$ szignatúrájú $<Srt, Pr, Fn, Cnst>$ négyest.\\
\noindent \textbf{Termek}: A $V[V_{\nu}]$ ábécé feletti termek halmaza $\mathcal{L}_{t}[V_{\nu}]$, ami
a következő tulajdonságokkal bír:
\begin{enumerate}
\item Minden $\pi \in Srt$ fajtájú változó és konstans $\pi$ fajtájú term.
\item Ha az $f \in Fn$ függvényszimbólum $(\pi_{1}, \pi_{2}, ..., \pi_{k}, \pi)$ alakú
és $t_{1}, t_{2}, ..., t_{k}$ -- rendre $\pi_{1}, \pi_{2}, ..., \pi_{k}$ fajtájú -- termek,
akkor az $f(s_{1}, s_{2}, ..., s_{k})$ egy $\pi$ fajtájú term.
\item Minden term az 1-2. szabályok véges sokszori alkalmazásával áll elő.
\end{enumerate}
\noindent \textbf{Formulák}: A $V[V_{\nu}]$ ábécé feletti elsőrendű formulák halmaza $\mathcal{L}_{f}[V_{\nu}]$, ami
a következő tulajdonságokkal bír:
\begin{enumerate}
\item Ha a $P \in Pr$ predikátumszimbólum $(\pi_{1}, \pi_{2}, ..., \pi_{k})$ alakú
és az $t_{1}, t_{2}, ..., t_{k}$ -- rendre $\pi_{1}, \pi_{2}, ..., \pi_{k}$ fajtájú --
termek, akkor a $P(t_{1}, t_{2}, ..., t_{k})$ szó egy elsőrendű formula.
Az így nyert formulákat atomi formuláknak nevezzük.
\item Ha $S$ elsőrendű formula, akkor $\neg S$ is az.
\item Ha $S$ és $T$ elsőrendű formulák és $\circ$ binér logikai összekötőjel,
akkor $(S \circ T)$ is elsőrendű formula.
\item Ha $S$ eleme elsőrendű formula, $Q$ kvantor ($\forall$ vagy $\exists$) és $x$
tetszőleges változó, akkor $QxS$ is elsőrendű formula. Az így nyert formulákat kvantált formuláknak nevezzük,
a $\forall xS$ alakú formulák univerzálisan kvantált formulák, a $\exists xS$ alakú formulák
pedig egzisztenciálisan kvantált formulák. A kvantált formulákban $Qx$ a formula prefixe, $S$
pedig a magja.
\item Minden elsőrendű formula az 1-4. szabályok véges sokszori alkalmazásával áll elő.
\end{enumerate}
\noindent A $V[V_{\nu}]$ ábécé feletti elsőrendű logikai nyelv
$\mathcal{L}[V_{\nu}] = \mathcal{L}_{t}[V_{\nu}] \cup \mathcal{L}_{f}[V_{\nu}]$, azaz $\mathcal{L}[V_{\nu}]$
minden szava vagy term, vagy formula.\\
A negációs, konjunkciós, diszjunkciós, implikációs (ezek jelentése ua., mint nulladrendben) és kvantált formulák
összetett formulák.
Az elsőrendű logikai nyelv prímformulái az atomi formulák és a kvantált formulák.\\
\noindent \textbf{Változóelőfordulás fajtái}: Egy formula $x$ változójának egy előfordulása:
\begin{itemize}
\item szabad, ha nem esik $x$-re vonatkozó kvantor hatáskörébe,
\item kötött, ha $x$-re vonatkozó kvantor hatáskörébe esik.
\end{itemize}
\noindent \textbf{Változó fajtái}: Egy formula $x$ változója:
\begin{itemize}
\item szabad, ha minden előfordulása szabad,
\item kötött, ha minden előfordulása kötött, és
\item vegyes, ha van szabad és kötött előfordulása is.
\end{itemize}
\noindent \textbf{Formula zártsága, nyíltsága}: Egy formula:
\begin{itemize}
\item zárt, ha minden változója kötött,
\item nyílt, ha legalább egy változójának van szabad előfordulása és
\item kvantormentes, ha nincs benne kvantor
\end{itemize}
Megjegyzés: a zárt formulák elsőrendű állításokat szimbolizálnak (egy elsőrendű állítás nem más, mint elemek egy halmazára
megfogalmazott kijelentő mondat).
\subsubsection{Az elsőrendű logika szemantikája}
\noindent \textbf{Matematikai struktúra}: Matematikai struktúrán egy $<U, R, M, K>$ négyest értünk, ahol:
\begin{enumerate}
\item $U = \bigcup_{\pi} U_{\pi}$ nem üres alaphalmaz (univerzum),
\item $R$ az $U$-n értelmezett logikai függvények (relációk) halmaza,
\item $M$ az $U$-n értelmezett matematikai függvények (alapműveletek) halmaza,
\item $K$ az $U$ kijelölt elemeinek (konstansainak) halmaza (lehet üres).
\end{enumerate}
\noindent \textbf{Interpretáció}: Az interpretáció egy $<U, R, M, K>$ matematikai struktúra és
$\mathcal{I} = <\mathcal{I}_{Srt}, \mathcal{I}_{Pr}, \mathcal{I}_{Fn}, \mathcal{I}_{Cnst}>$
függvénynégyes, ahol:
\begin{itemize}
\item az $\mathcal{I}_{Srt} : \pi \mapsto U_{\pi}$ függvény megad minden egyes $\pi \in Srt$ fajtához
egy $U_{\pi}$ nemüres halmazt, a $\pi$ fajtájú individuumok halmazát,
\item az $\mathcal{I}_{Pr} : P \mapsto P^{\mathcal{I}}$ függvény megad minden
$(\pi_{1}, \pi_{2}, ..., \pi_{k})$ alakú $P \in Pr$ predikátumszimbólumhoz egy
$P^{\mathcal{I}} : U_{\pi_{1}} \times U_{\pi_{2}} \times ... \times U_{\pi_{k}} \to \mathbb{L}$
logikai függvényt (relációt),
\item az $\mathcal{I}_{Fn} : f \mapsto f^{\mathcal{I}}$ függvény hozzárendel minden
$(\pi_{1}, \pi_{2}, ..., \pi_{k}, \pi)$ alakú $f \in Fn$ függvényszimbólumhoz egy
$P^{\mathcal{I}} : U_{\pi_{1}} \times U_{\pi_{2}} \times ... \times U_{\pi_{k}} \to U_{\pi}$
matematikai függvényt (műveletet),
\item az $\mathcal{I}_{Cnst} : c \mapsto ct^{\mathcal{I}}$ pedig minden $\pi$ fajtájú
$c \in Cnst$ konstansszimbólumhoz az $U_{\pi}$ individuumtartománynak egy individuumát
rendeli, azaz $c^{\mathcal{I}} \in U_{\pi}$.
\end{itemize}
\noindent \textbf{Változókiértékelés}: Legyen az $\mathcal{L}[V_{\nu}]$ nyelvnek $\mathcal{I}$ egy interpretációja,
az interpretáció univerzuma legyen U és jelölje V a nyelv változóinak halmazát. Egy olyan $\kappa : V \to U$ leképezést,
ahol ha $x$ $\pi$ fajtájú változó, akkor $\kappa(x) \in U_{\pi}$, $\mathcal{I}$-beli változókiértékelésnek nevezünk.\\
\noindent \textbf{$\mathcal{L}_{t}[V_{\nu}]$ szemantikája}:
Legyen az $\mathcal{L}[V_{\nu}]$ nyelvnek $\mathcal{I}$ egy interpretációja és $\kappa$ egy $\mathcal{I}$-beli
változókiértékelés. Az $\mathcal{L}[V_{\nu}]$ nyelv egy $\pi$ fajtájú $t$ termjének értéke $\mathcal{I}$-ben
a $\kappa$ változókiértékelés mellett az alábbi -- $|t|^{\mathcal{I},\kappa}$-val jelölt -- $U_{\pi}$-beli
individuum:
\begin{enumerate}
\item ha $c \in Cnst$ $\pi$ fajtájú konstansszimbólum, akkor $|c|^{\mathcal{I},\kappa}$ az $U_{\pi}$-beli
$c^{\mathcal{I}}$ individuum,
\item ha $x$ $\pi$ fajtájú változó, akkor $|x|^{\mathcal{I},\kappa}$ az $U_{\pi}$-beli $\kappa(x)$ individuum,
\item ha $t_{1}, t_{2}, ..., t_{k}$ rendre $\pi_{1}, \pi_{2}, ..., \pi_{k}$ fajtájú termek és ezek értékei
a $\kappa$ változókiértékelés mellett rendre az $U_{\pi_{1}}$-beli $|t_{1}|^{\mathcal{I},\kappa}$, az
$U_{\pi_{2}}$-beli $|t_{2}|^{\mathcal{I},\kappa}$ ... és az $U_{\pi_{k}}$-beli $|t_{k}|^{\mathcal{I},\kappa}$
individuumok, akkor egy $(\pi_{1}, \pi_{2}, ..., \pi_{k}, \pi)$ alakú $f \in Fn$ függvényszimbólum esetén
$|f(t_{1}, t_{2}, ..., t_{k})|^{\mathcal{I},\kappa}$ az $U_{\pi}$-beli
$f^{\mathcal{I}}(|t_{1}|^{\mathcal{I},\kappa}, |t_{2}|^{\mathcal{I},\kappa}, ..., |t_{k}|^{\mathcal{I},\kappa})$
individuum.
\end{enumerate}
\noindent \textbf{Változókiértékelés $x$-variánsa}: Legyen $x$ egy változó. A $\kappa^{*}$ változókiértékelés a
$\kappa$ változókiértékelés $x$-variánsa, ha $\kappa^{*}(y) = y$ minden $x$-től különböző $y$ változó esetén.\\
\noindent \textbf{Elsőrendű logikai formula logikai értéke}:
Legyen az $\mathcal{L}[V_{\nu}]$ nyelvnek $\mathcal{I}$ egy interpretációja és $\kappa$ egy $\mathcal{I}$-beli
változókiértékelés. Az $\mathcal{L}[V_{\nu}]$ nyelv egy $C$ formulájához $\mathcal{I}$-ben a $\kappa$ változókiértékelés
mellett az alábbi -- $|C|^{\mathcal{I},\kappa}$-val jelölt -- igazságértéket rendeljük:
\begin{enumerate}
\item $|P(t_{1}, t_{2}, ..., t_{k})|^{\mathcal{I},\kappa} = \left\{
\begin{array}{lr}
igaz & : P^{\mathcal{I}}(|t_{1}|^{\mathcal{I},\kappa}, |t_{2}|^{\mathcal{I},\kappa}, ..., |t_{k}|^{\mathcal{I},\kappa}) = igaz \\
hamis & : kulonben
\end{array}
\right\}$
\item $|\neg A|^{\mathcal{I},\kappa}$ legyen $\neg |A|^{\mathcal{I},\kappa}$
\item $|A \wedge B|^{\mathcal{I},\kappa}$ legyen $|A|^{\mathcal{I},\kappa} \wedge |B|^{\mathcal{I},\kappa}$
\item $|A \vee B|^{\mathcal{I},\kappa}$ legyen $|A|^{\mathcal{I},\kappa} \vee |B|^{\mathcal{I},\kappa}$
\item $|A \supset B|^{\mathcal{I},\kappa}$ legyen $|A|^{\mathcal{I},\kappa} \supset |B|^{\mathcal{I},\kappa}$
\item $|\forall x A|^{\mathcal{I},\kappa} = \left\{
\begin{array}{lr}
igaz & : |A|^{\mathcal{I},\kappa^{*}} = igaz \ \kappa \ minden \ \kappa^{*} \ x-variansara \\
hamis & : kulonben
\end{array}
\right\}$
\item $|\exists x A|^{\mathcal{I},\kappa} = \left\{
\begin{array}{lr}
igaz & : |A|^{\mathcal{I},\kappa^{*}} = igaz \ \kappa \ valamely \ \kappa^{*} \ x-variansara \\
hamis & : kulonben
\end{array}
\right\}$
\end{enumerate}
\noindent \textbf{Elsőrendű formula kielégíthetősége}: Egy $A$ elsőrendű formula kielégíthető, ha van
olyan $\mathcal{I}$ interpretáció és $\kappa$ változókiértékelés, amelyre $|A|^{\mathcal{I},\kappa} = igaz$
(ekkor azt mondjuk, hogy az $\mathcal{I}$ interpretáció és $\kappa$ változókiértékelés kielégíti $A$-t),
különben kielégíthetetlen.
Amennyiben az $A$ formula zárt, igazságértékét egyedül az interpretáció határozza meg. Ha $|A|^{\mathcal{I}} = igaz$,
azt mondjuk, hogy az $\mathcal{I}$ kielégíti $A$-t vagy másképpen: $\mathcal{I}$ modellje $A$-nak ($\mathcal{I} \models A$).\\
\noindent \textbf{Logikailag igaz elsőrendű formula}: Egy $A$ elsőrendű logikai formula logikailag igaz,
ha minden $\mathcal{I}$ interpretációban és $\mathcal{I}$ minden $\kappa$ változókiértékelése mellett
$|A|^{\mathcal{I},\kappa} = igaz$. Jelölése: $\models A$.\\
\noindent \textbf{Szemantikus következmény}: Azt mondjuk, hogy a $G$ formula \textit{szemantikus következménye} az
$\mathcal{F}$ formulahalmaznak, ha minden olyan $\mathcal{I}$ interpretációra, amelyre $\mathcal{I} \models \mathcal{F}$
fennáll, $\mathcal{I} \models G$ is igaz (jelölés: $\mathcal{F} \models G$).\\
\noindent \textbf{Tétel}: Legyenek $A_{1}, A_{2}, ..., A_{n}, B$ ($n \geq 1$) tetszőleges, ugyanabból az elsőrendű logikai nyelvből
való formulák. Ekkor $\left\{A_{1}, A_{2}, ..., A_{n}\right\} \models B$ akkor és csak akkor, ha
$A_{1} \wedge A_{2} \wedge ... \wedge A_{n} \wedge \neg B$ kielégíthetetlen.\\
\noindent \textbf{Rezolúció}: Elsőrendű predikátumkalkulusban is végezhető rezolúció, ráadásul a módszer
helyes és teljes is. Nehézséget a klózok kialakítása okozhat, amelyek zárt,
univerzálisan kvantált literálok konjunkciójából állnak. Ehhez eszközeink a
prenex-, illetve skolem-formák.
\end{document}

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -0,0 +1,399 @@
\documentclass[margin=0px]{article}
\usepackage{listings}
\usepackage[utf8]{inputenc}
\usepackage{graphicx}
\usepackage{float}
\usepackage[a4paper, margin=0.7in]{geometry}
\usepackage{amsthm}
\usepackage{amssymb}
\usepackage{t1enc}
\usepackage{fancyhdr}
\usepackage{setspace}
\onehalfspacing
\newenvironment{tetel}[1]{\paragraph{#1 \\}}{}
\pagestyle{fancy}
\lhead{\it{PTI BSc Záróvizsga tételek}}
\rhead{14. Alapvető algoritmusok}
\title{\textbf{{\Large ELTE IK - Programtervező Informatikus BSc} \vspace{0.2cm} \\ {\huge Záróvizsga tételek}} \vspace{0.3cm} \\ 14. Alapvető algoritmusok}
\author{}
\date{}
\begin{document}
\maketitle
\begin{tetel}{Alapvető algoritmusok és adatszerkezetek}
Függvények aszimptotikus viselkedése, algoritmusok hatékonysága. Összehasonlító rendezések (beszúró, összefésülő, gyors- és kupacrendezés), maximális műveletigény alsó korlátja. Rendezés lineáris időben (bucket, leszámláló és radix rendezés). Adattömörítés (naiv, Huffman, LZW). Mintaillesztés (brute-force, quicksearch, KMP).
\end{tetel}
\section{Függvények aszimptotikus viselkedése, algoritmusok hatékonysága}
TODO
\section{Összehasonlító rendező algoritmusok (buborék és beszúró rendezés, ill. verseny, kupac, gyors és összefésülő rendezés)}
Buborék- és beszúró rendezés klasszikusak, $n^2$-es műveletigényűek, a többi hatékony, $n\log(n)$-es idejűek.
\subsection{Buborékrendezés}
A legnagyobb értéket cserékkel a végéig felbuborékozza, ezt minden ciklus végén elhagyjuk. A gyakorlatban nem használják.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{img/Buborekrendezes.png}
\caption{Buborékrendezés}
\end{figure}
\subsection{Beszúró rendezés}
Kis $n$-re (kb 30) ez a rendezés a legjobb. \\
Itt az elemmozgatás mindig 1 értékadás (buborékrendezésnél a csere 3 értékadás). Listára is implementálni lehet, ez esetben a pointereket állítjuk át, az elemek helyben maradnak. \\
$A[1..j]$ rendezett, $j=1..n$.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{img/Beszurorend.jpg}
\caption{Beszúró rendezés}
\end{figure}
\subsection{Versenyrendezés}
Gyakorlatban nem használják. \\
Teljes bináris fa az alapja, egy versenyfa. Szintfolytonosan ábrázoljuk tömbösen.\\
\begin{enumerate}
\item A versenyfa kitöltése (a verseny lejátszása). Maximum a gyökérben, ennek kiírása az outputra.
\item $(n-1)$-szer
\begin{itemize}
\item[a)] gyökérben szereplő maximális elem helyének megkeresése a levélszinten és $-\infty$ írása a helyére
\item[b)] az egészet újrajátsszuk (azt az ágat, ahol volt) $\to$ 2. legjobb feljut a gyökérbe
\end{itemize}
\end{enumerate}
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{img/Versenyrend.jpg}
\includegraphics[width=0.3\textwidth]{img/VFaKitolt.jpg}
\includegraphics[width=0.3\textwidth]{img/VFaMax.jpg}
\caption{Versenyrendezés}
\end{figure}
\subsection{Kupacrendezés}
\begin{enumerate}
\item Kezdő kupac kialakítása. Rendezetlen input tömbből tartalmi invariánst készítünk, ami már kupac struktúrájú. Elv: cserékkel lesüllyesztjük az elemet a nagyobb gyerek irányába, ha kisebb a nagyobbik gyereknél. A süllyesztés eljuthat ahhoz a csúcshoz, amelynek nincs jobb gyereke.
\item $(n-1)$-szer
\begin{itemize}
\item[a)] gyökérelem és az alsó szint jobb szélső (=utolsó) aktív elemének cseréje, és a csere után lekerült elem inaktívvá tétele
\item[b)] a gyökérbe került elem süllyesztése az aktív kupacon
\end{itemize}
\end{enumerate}
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{img/Kezdokupac.jpg}
\includegraphics[width=0.3\textwidth]{img/Sully.jpg}
\includegraphics[width=0.3\textwidth]{img/KupacRend.jpg}
\caption{Kupacrendezés}
\end{figure}
A kezdőkupac kialakításánál, és a ciklus közben a süllyesztés módja kicsit különbözik, hiszen az első esetben a változó elem süllyed le a teljes kupacon, a másodikban a gyökér süllyed az aktív kupacon. A képen látható algoritmus mindkét műveletet teljesíti.
\subsection{Gyorsrendezés}
Elve: véletlenül választunk egy elemet. A nála kisebb elemeket tőle balra, a nagyobbakat jobbra rakjuk, az elemet berakjuk a két rész közé. Rekurzív algoritmus.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{img/GyorsRend.jpg}
\includegraphics[width=0.3\textwidth]{img/Helyrevisz.jpg}
\caption{Gyorsrendezés}
\end{figure}
\subsection{Összefésülő rendezés}
Alapja: 2 rendezett sorozat összefésülése. Ezt alkalmazhatjuk felülről lefelé (rekurzív) vagy alulról felfelé (iteratív), ez utóbbit szekvenciális fájloknál.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{img/OFRend.jpg}
\caption{Összefésülő rendezés}
\end{figure}
\section{A műveletigény alsó korlátja összehasonlító rendezésekre}
\subsection{Műveletigény}
Kijelöljük a domináns műveleteket, és az $n$ inputméret függvényében hányszor hajtódnak végre, ezt nézzük. Jelölés általánosan $T(n)$, de lehet konkrétan is, pl $Cs(n)$ [csere]. $mT(n)$ a minimális műveletigény, $MT(n)$ a maximális és $AT(n)$ az átlagos.
\begin{itemize}
\item[$\Theta$]: nagyságrendileg azonos, két konstans közé beszorítható
\item[$\mathcal{O}$]: nagyságrendi felső becslés, $o$: nincs megengedve az egyenlőség
\item[$\Omega$]: nagyságrendi alsó becslés, $\omega$: nincs megengedve az egyenlőség
\end{itemize}
\subsection{Alsókorlát}
Például: $n$ elem maximumkiválasztása legalább $(n-1)$ összehasonlítást igényel. Bizonyítása: Ha ennél kevesebb összehasonlítás lenne, akkor legalább 1 elem kimaradt, és ezzel ellentmondásba kerülhetünk. \\
\textit{Döntési fa}: Algoritmus $n$ méretű inputra. Kiegyenesednek a ciklusok véges hosszú lánccá, a végrehajtás nyoma egy fa struktúrát ad. Tökéletes fa: minden belső pontnak 2 gyereke van. Ennél az algoritmusnál nincs jobb, mert $2^{h(t)} \geq n!$, összehasonlító rendezés esetén, $n!$ input.
\subsection{Alsókorlát legrosszabb esetben}
Tétel: $MO_R(n) = \Omega(n\log{n})$ A legkedvezőtlenebb permutációra legalább $n\log{n}$ összehasonlítás. Bizonyítás: $\log_2{n!} \leq n\log_2{n} = \Omega(n\log{n})$, és $MO_R(n)=h(t) \geq \log_2{n!}$ (lemma miatt) $\Rightarrow$ $MO_R(n)=\Omega(n\log{n})$.
\subsection{Alsókorlát átlagos esetben}
Legyen minden input egyformán valószínű ($\frac{1}{n!}$). \\
$AO_R(n) = \frac{1}{n!}\sum_{p \in Perm(n)}{O_R(p)}$, és könnyű belátni, hogy $\sum_{p}{O_R(p)} = lhsum(h(t_R(n)))$ [levél-magasság-összeg]. \\
Lemma: Az $n!$ levelet tartalmazó tökéletes fák közül azokra a legkisebb az $lhsum(h(t_R(n)))$ érték, amelyek majdnem teljesek. \\
Tétel: $AO_R(n) = \Omega(n\log{n})$.
\section{Rendezés lineáris időben (bucket-, leszámláló- és radix rendezés)}
TODO
\section{Adattömörítések}
\subsection{Huffman-algoritmus}
A Huffman-algoritmussal való tömörítés lényege, hogy a gyakrabban előforduló elemeket (karaktereket) rövidebb, míg a ritkábban előfordulókar hosszabb kódszavakkal kódoljuk.
Ehhez tisztában kell lennünk az egyes karakterek gyakoriságával (vagy relatív gyakoriságával). Ezek alapján egy ún. Huffman-fát építünk, melyben az éleket a kód betűivel címkézzük, a fa levelein a kódolandó betűk helyezkednek el, a gyökérből a levelekig vezető út címkéi alapján rajuk össze a kódszavakat.\\
\noindent
Az algoritmus (spec. bináris Huffman fára):
\begin{enumerate}
\item A kódolandó szimbólumokat gyakoriságaik alapján sorba rendezzük.
\item A következő redukciós lépéseket addig hajtjuk végre, míg egy csoportunk marad.
\item Kiválasztjuk az utolsó két elemet (legritkább), összevonjuk őket egy új csoportba, és ennek a csoportnak a gyakorisága a gyakoriságok összege lesz.
\item A csoportot visszahelyezzük a rendezett sorba (gyakoriság alapján rendezve).
\item A csoportból új csúcsot képezünk, mely csúcs az őt alkotó két elem szülője lesz.
\end{enumerate}
\noindent
Példa:\\
Legyen a következő 5 betű, mely a megadott gyakorisággal fordul elő:\\
\begin{tabular}{|c|c|c|c|c|}
\hline A & B & C & D & E \\
\hline 5 & 4 & 3 & 2 & 1 \\
\hline
\end{tabular}\\
Ekkor a redukciós lépések a következők:
\begin{itemize}
\item \begin{tabular}{|c|c|c|c|}
\hline A & B & C & D, E \\
\hline 5 & 4 & 3 & 3 \\
\hline
\end{tabular}
\item \begin{tabular}{|c|c|c|}
\hline C, D, E & A & B \\
\hline 6 & 5 & 4 \\
\hline
\end{tabular}
\item \begin{tabular}{|c|c|}
\hline A , B & C, D, E \\
\hline 9 & 6 \\
\hline
\end{tabular}
\item \begin{tabular}{|c|}
\hline A , B , C, D, E \\
\hline 15 \\
\hline
\end{tabular}
\end{itemize}
A huffman-fa a XY. ábrán látható.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{img/Huffman_fa.png}
\caption{Huffman-fa példa}
\label{fig:Huffman_fa}
\end{figure}
Tehát a kódszavak:
\begin{tabular}{|c|c|c|c|c|}
\hline A & B & C & D & E \\
\hline 00 & 01 & 10 & 110 & 111 \\
\hline
\end{tabular}
\subsection{LZW-algoritmus}
Az LZW (Lempel-Ziv-Welch) tömörítésnek a lényege, hogy egy szótárat bővítünk folyamatosan, és az egyes kódolandó szavakhoz szótárindexeket rendelünk.
\begin{description}
\item[Kódolás] \hfill \\
A kódolás algoritmusa a következő lépésekből áll:
\begin{enumerate}
\item A szótárt inicializáljuk az összes 1 hosszú szóval
\item \label{itm:szotar} Kikeressük a szótárból a leghosszabb, jelenlegi inputtal összeillő $W$ sztringet
\item $W$ szótárindexét kiadjuk, és $W$-t eltávolítjuk az inputról
\item A $W$ szó és az input következő szimbólumának konkatenációját felvesszük a szótárba
\item A \ref{itm:szotar}. lépéstől ismételjük
\end{enumerate}
\item[Dekódolás] \hfill \\
A dekódolás során is építenünk kell a szótárat. Ezt már azonban csak a dekódolt szöveg(rész) segítségével tudjuk megtenni, mivel egy megkapott kód dekódolt szava és az utána lévő szó első karakteréből áll össze a szótár következő eleme.
Tehát a dekódolás lépései:
\begin{enumerate}
\item Kikeressük a kapott kódhoz tartozó szót a szótárból ($u$), az output-ra rakjuk
\item Kikeressük a következő szót ($v$) a szótárból, az első szimbólumát $u$-hoz konkatenálva a szótárba rakjuk a következő indexszel.
\item Amennyiben már nincs következő szó, dekódolunk, de nem írunk a szótárba.
\end{enumerate}
Megtörténhet az az eset, hogy mégis kapunk olyan kódszót, mely még nincs benne a szótárban. Ez akkor fordulhat elő, ha a kódolásnál az aktuálisan szótárba írt szó következik.\\
Példa:
Szöveg: AAA\\
Szótár: A - 1
Ekkor a kódolásnál vesszük az első karaktert, a szótárbeli indexe 1, ezt kiküldjük az outputra. A következő karakter A, így AA-t beírjuk a szótárba 2-es indexszel. Az első karaktert töröljük az inputról. Addig olvasunk, míg szótárbeli egyezést találunk, így AA-t olvassuk (amit pont az előbb raktunk be), ennek indexe 2, tehát ezt küldjük az outputra. AA-t töröljük az inputról, és ezzel végeztünk is. Az output: 1,2
Dekódoljuk az 1,2 inputot! Jelenleg a szótárban csak A van 1-es indexszel. Vegyük az input első karakterét, az 1-et, ennek szótárbeli megfelelője A. Ezt tegyük az outputra. A következő index a 2, de ilyen bejegyzés még nem szerepel a szótárban. \\
Ebben az esetben a dekódolásnál, egy trükköt vetünk be. A szótárba írás pillanatában még nem ismert a beírandó szó utolsó karaktere (A példában A-t találtuk, de nem volt 2-es bejegyzés). Ekkor ?-et írunk a szótárba írandó szó utolsó karakterének helyére. (Tehát A? - 2 kerül a szótárba). De mostmár tudni lehet az új bejegyzés első betűjét ( A? - 2 az új bejegyzés, ennek első betűje A). Cseréljük le a ?-et erre a betűre. (Tehát AA - 2 lesz a szótárban).
\end{description}
\section{Mintaillesztés}
\subsection{Knuth-Morris-Pratt algoritmus}
A Knuth-Morris-Pratt eljárásnak a Brute-Force (hasonlítsuk össze, toljunk egyet, stb..) módszerrel szemben az az előnye, hogy egyes esetekben, ha a mintában vannak ismétlődő elemek, akkor egy tolásnál akár több karakternyit is ugorhatunk.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{img/KMP_sample.png}
\caption{KMP algoritmus több karakter tolás estén}
\label{fig:KMP_sample}
\end{figure}
Az ugrás megállapítását a következőképp tesszük: Az eddig megvizsgált egyező mintarész elején (prefix) és végén (suffix) olyan kartersorozatot keresünk, melyek megegyeznek. Ha találunk ilyet, akkor a mintát annyival tolhatjuk, hogy az elején lévő része ráilleszkedjen a végén levőre.
Azt, hogy ez egyes esetekben mekkorát tolhatunk nem kell minden elromlás alkalmával vizsgálni. Ha a mintára önmagával lefuttatjuk az algoritmus egy módosított változatát (\ref{fig:KMP_initnext}. ábra), kitölthetünk egy tömböt, mely alapján a tolásokat végezni fogjuk.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{img/KMP_initnext.jpg}
\caption{KMP tolásokat szabályzó tömb kitöltése}
\label{fig:KMP_initnext}
\end{figure}
Az algoritmus (ld \ref{fig:KMP}. ábra):
\begin{itemize}
\item Két indexet $i$ és $j$ futtatunk a szövegen illetve a mintán.
\item Ha az $i+1$-edik és $j+1$-edik karakterek megegyeznek, akkor léptetjük mind a kettőt.
\item Ha nem egyeznek meg, akkor:
\begin{itemize}
\item Ha a minta első elemét vizsgáltuk, akkor egyet tolunk a mintán, magyarul a minta indexe marad az első betűn, és a szövegben lévő indexet növeljük eggyel ($i=i+1$)
\item Ha nem a minta első elemét vizsgáltuk, akkor annyit tolunk, amennyit szabad. Ez azt jelenti, hogy csak a mintán lévő indexet helyezzük egy kisebb helyre ($j = next[j]$)
\end{itemize}
\item Addig megyünk, míg vagy a minta, vagy a szöveg végére nem érünk. Ha a minta végére értünk, akkor megtaláltuk a mintát a szövegben, ha a szöveg végére értünk, akkor pedig nem.
\end{itemize}
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{img/KMP.jpg}
\caption{KMP algoritmus}
\label{fig:KMP}
\end{figure}
\subsection{Boyer-Moore | Quick search algoritmus}
Míg a KMP algoritmus az elromlás helye előtti rész alapján döntött a tolásról, addig a QS a minta utáni karakter alapján. Tehát elromlás esetén:
\begin{itemize}
\item Ha a minta utáni karakter benne van a mintában, akkor jobbról az első előfordulására illesztjük. (\ref{fig:BoyerMoore_shift1}. ábra)
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{img/BoyerMoore_shift1.png}
\caption{QS - eltolás ha a minta utáni karakter benne van a mintában}
\label{fig:BoyerMoore_shift1}
\end{figure}
\item Ha a minta utáni karakter nincs benne a mintában, akkor a mintát ezen karakter után illesztjük. (\ref{fig:BoyerMoore_shift2}. ábra)
\begin{figure}[H]
\centering
\includegraphics[width=0.6\textwidth]{img/BoyerMoore_shift2.png}
\caption{QS - eltolás ha a minta utáni karakter nincs benne a mintában}
\label{fig:BoyerMoore_shift2}
\end{figure}
\end{itemize}
Az eltolás kiszámítását megint elő lehet segíteni egy tömbbel, most azonban, mivel nem a minta az érdekes, és nem tudjuk pontosan mely karakterek szerepelnek a szövegben, így a tömbbe az egész abc-t fel kell vennünk (\ref{fig:BoyerMoore_initshift}. ábra)
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{img/BoyerMoore_initshift.jpg}
\caption{QS - Az eltolást elősegítő tömb ($Shift['a'...'z']$) konstruálása}
\label{fig:BoyerMoore_initshift}
\end{figure}
Az algoritmus (ld. \ref{fig:BoyerMoore}. ábra):
\begin{itemize}
\item Két indexet $k$ és $j$ futtatunk a szövegen illetve a mintán.
\item Ha a szöveg $k+j$-edik eleme megegyezik a minta $j$-edik karakterével, akkor léptetjük $j$-t (mivel a szövegben $k+j$-edik elemet nézzük, így elég $j$-t növelni).
\item Ha nem egyeznek meg, akkor:
\begin{itemize}
\item Ha a minta már a szöveg végén van ($k=n-m$), akkor csak növeljük $k$-t eggyel, ami hamissá teszi a ciklus feltételt.
\item Ha még nem vagyunk a szöveg végén $k$-t toljuk annyival, amennyivel lehet (ezt az előre beállított $Shift$ tömb határozza meg). És a $j$-t visszaállítjuk 1-re.
\end{itemize}
\item Addig megyünk, míg vagy a minta végére érünk $j$-vel, vagy a mintát továbbtoltuk a szöveg végénél. Előbbi esetben egyezést találtunk, míg az utóbbiban nem.
\end{itemize}
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{img/BoyerMoore.jpg}
\caption{QS}
\label{fig:BoyerMoore}
\end{figure}
\subsection{Rabin-Karp algoritmus}
A Rabin-Karp algoritmus lényege, hogy minden betűhöz az ábécéből egy számjegyet rendelünk, és a keresést számok összehasonlításával végezzük. Világos, hogy ehhez egy ábécé méretnek megfelelő számrendszerre lesz szükségünk. A szövegből mindig a minta hosszával egyező részeket szelünk ki, és ezeket hasonlítjuk össze.\\
\noindent
Példa:\\
Minta: BBAC $\rightarrow$ 1102 \\
Szöveg: DACABBAC $\rightarrow$ 30201102, amiből a következő számokat állítjuk elő: 3020, 0201, 2011, 0110, 1102\\
\noindent
A fent látható szeletek lesznek az $s_i$-k.\\
\noindent
Az algoritmus működéséhez azonban számos apró ötletet alkalmazunk:
\begin{enumerate}
\item A minta számokká alakítását Horner-módszer segítségével végezzük.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{img/RK_Horner.jpg}
\caption{RK - Horner-módszer}
\label{fig:RK_Horner}
\end{figure}
Az $ord()$ függvény az egyes betűknek megfelelő számot adja vissza. A $d$ a számrendszer alapszáma.
\item A szöveg mintával megegyező hosszú szeleteinek ($s_i$) előállítása: \\
$s_0$-t a Horner-módszerrel ki tudjuk számolni. Ezek után $s_{i+1}$ a következőképp számolandó:
\[s_{i+1} = (s_i - ord(S[i])\cdot d^{m-1})\cdot d + ord(S[i+1])\]
\textit{Magyarázat: $s_i$ elejéről levágjuk az első számjegyet ($s_i - ord(S[i])\cdot d^{m-1}$), majd a maradékot eltoljuk egy helyiértékkel (szorzás $d$-vel), végül az utolsó helyiértékre beírjuk a következő betűnek megfelelő számjegyet ($+ord(S[i+1])$)}
Példa:
Az előző példa szövegével és mintájával ($d=10$ elemű ábécé és $m=4$ hosszú minta): \\
$s_0 = 3020$, ekkor: $s_{0+1} = s_1 = (3020 - ord(D) \cdot 10^3)\cdot 10 + ord(B) = (3020-3000)\cdot 10 +1 = 0201$
\item Felmerülhet a kérdés, hogy az ilyen magas alapszámú számrendszerek nem okoznak-e gondot az ábrázolásnál? A kérdés jogos. Vegyük a következő életszerű példát:
4 bájton ábrázoljuk a számainkat ($2^{32}$). Az abc legyen 32 elemű ($d=32$), a minta 8 hosszú ($m=8$). Ekkor a $d^{m-1}$ kiszámítása: $32^7 = (2^5)^7 = 2^{35}$ , ami már nem ábrázolható 4 bájton.
Ennek kiküszöbölésére vezessünk be egy nagy $p$ prímet, melyre $d\cdot p$ még ábrázolható. És a műveleteket számoljuk {\it mod p}. Ekkor természetesen a kongruencia miatt lesz olyan eset, amikor az algoritmus egyezést mutat, mikor valójában nincs. Ez nem okoz gondot, mivel ilyen esetben karakterenkénti egyezést vizsgálva ezt a problémát kezelni tudjuk. (Fordított eset nem fordul elő tehát nem lesz olyan eset, mikor karakterenkénti egyezés van, de numerikus nincs). [Ha $p$ kellően nagy, a jelenség nagyon ritkán fordul elő.]
\item A {\it mod p} számítás egy másik problémát is felvet. Ugyanis a kivonás alkalmával negatív számokat is kaphatunk.
Például: Legyen $p=7$, ekkor, ha $ord(S[i]) = 9$, akkor előző számítás után $s_i = 2...$, de ebből $ord(S[i])\cdot d^{m-1} = 9\cdot 10^3 = 9000$-et vonunk ki negatív számot kapunk.
Megoldásként $s_{i+1}$-et két lépésben számoljuk:
\[s := (s_i+d\cdot p - ord(S[i])\cdot d^{m-1}) \quad mod \quad p \]
\[s_{i+1} := (s\cdot d + ord(S[i+1])) \quad mod \quad p \]
\end{enumerate}
A fentiek alapján az algoritmus a következő (ld. \ref{fig:RK}. ábra)
\begin{enumerate}
\item Kiszámoljuk $d^{m-1}$-et ($dm1$)
\item Egy iterációban meghatározzuk Horner-módszerrel a minta számait ($x$) és $s_0$-t
\item Ellenőrizzük, hogy egyeznek-e
\item Addig számolgatjuk $s_i$ értékét míg a minta nem egyezik $s_i$-vel, vagy a minta a szöveg végére nem ért.
\end{enumerate}
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{img/RK.jpg}
\caption{RK}
\label{fig:RK}
\end{figure}
\end{document}

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1,164 @@
\documentclass[margin=0px]{article}
\usepackage{listings}
\usepackage[utf8]{inputenc}
\usepackage{graphicx}
\usepackage{float}
\usepackage[a4paper, margin=0.7in]{geometry}
\usepackage{amsthm}
\usepackage{amssymb}
\usepackage{t1enc}
\usepackage{fancyhdr}
\usepackage{setspace}
\onehalfspacing
\newenvironment{tetel}[1]{\paragraph{#1 \\}}{}
\pagestyle{fancy}
\lhead{\it{PTI BSc Záróvizsga tételek}}
\rhead{15. Adatszerkezetek és adattípusok}
\title{\textbf{{\Large ELTE IK - Programtervező Informatikus BSc} \vspace{0.2cm} \\ {\huge Záróvizsga tételek}} \vspace{0.3cm} \\ 15. Adatszerkezetek és adattípusok}
\author{}
\date{}
\begin{document}
\maketitle
\begin{tetel}{Adatszerkezetek és adattípusok}
Tömb, verem, sor, láncolt listák; bináris fa, általános fa, bejárások, ábrázolások; bináris kupac, prioritásos sor; bináris kereső fa és műveletei, AVL fa, B+ fa; hasító táblák, hasító függvények, kulcsütközés és feloldásai: láncolással, nyílt címzéssel, próbasorozat; gráfok ábrázolásai.
\end{tetel}
\section{Egyszerű adattípusok ábrázolásai, műveletei és fontosabb alkalmazásai}
\subsection{Adattípus}
\textit{Adatszerkezet}: $\sim$ struktúra. \\
\textit{Adattípus}: adatszerkezet és a hozzá tartozó műveletek. \\
\textit{Adatszerkezetek}:
\begin{itemize}
\item \textit{Tömb}: azonos típusú elemek sorozata, fix méretű.
\item \textit{Verem}: Mindig a verem tetejére rakjuk a következő elemet, csak a legfelsőt kérdezhetjük le, és vehetjük ki.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{img/Verembe.jpg}
\includegraphics[width=0.3\textwidth]{img/Verembol.jpg}
\caption{Verem műveletei}
\end{figure}
\item \textit{Sor}: Egyszerű, elsőbbségi és kétvégű. A prioritásos sornál az elemekhez tartozik egy érték, ami alapján rendezhetjük őket.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{img/Sorba.jpg}
\includegraphics[width=0.3\textwidth]{img/Sorbol.jpg}
\caption{Sor műveletei}
\end{figure}
\item \textit{Lista}: Láncolt ábrázolással reprezentáljuk. 3 szempont szerint különböztethetjük meg a listákat: fejelem van/nincs, láncolás iránya egy/kettő, ciklusosság van/nincs. Ha fejelemes a listánk, akkor a fejelem akkor is létezik, ha üres a lista. \\
A lista node-okból áll, minden node-nak van egy, a következőre mutató pointere, illetve lehet az előzőre is, ha kétirányú. Ezen kívül van egy első és egy aktuális node-ra mutató pointer is, és az utolsó elem mutatója NIL. A listát megvalósíthatjuk úgy, hogy tetszőleges helyre lehessen elemet beszúrni, illetve törölni.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{img/Listaba.jpg}
\includegraphics[width=0.3\textwidth]{img/Torol.jpg}
\caption{Lista műveletei}
\end{figure}
\item \textit{Fa}: Egyszerű, bináris és speciális (kupac, bináris keresőfa, AVL-fa). A bináris fát rekurzívan definiáljuk: $t \in T(E)$ [bin. fák típusérték halmaza(alaptípus)] $\iff$ $t$ üres fa (jele: $\Omega$), vagy $t$-nek van gyökéreleme, $bal(t)$, $jobb(t)$ részfája. Láncoltan ábrázoljuk, tömbösen csak teljes fák, illetve kupac esetén.
\item \textit{Kupac}: Olyan bináris fa, melynek alakja majdnem teljes és balra rendezett. Tömbösen ábrázoljuk, mert pointeresen a bonyolult lépkedést nem teszi lehetővé, tömbösen indexösszefüggésekkel könnyen megoldható.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{img/KupacbaBeszur.jpg}
\caption{Kupac műveletei}
\end{figure}
\item \textit{Hasítótábla}
\item \textit{Gráf} [Nem egyszerű adattípus.]
\end{itemize}
\subsection{Ábrázolásai}
Absztrakciós szintek:
\begin{enumerate}
\item \textit{absztrakt adattípus (ADT)}: specifikáció szintje, itt nincs szerkezeti összefüggés, csak matematikai fogalmak, műveletek logikai axiómákkal vagy előfeltételekkel.
\begin{itemize}
\item algebrai (axiomatikus) specifikáció, példa: $Verembe : V \times E \to V$. Axióma, példa: $Felso(Verembe(v,e)) = e$
\item funkcionális (elő- és utófeltételes) specifikáció, példa: (elsőbbségi) sor $S(E), s \in S$ egy konkrét sor, $s = \{(e_1, t_1), ..., (e_n, t_n)\}$, $n \geq 0$. Ha $n=0$, akkor a sor üres. \\
$\forall i,j \in [1..n]: i \neq j \to t_i \neq t_j$. \\
$Sorbol: S \to S \times E$, $\mathcal{D}_{Sorbol} = S \backslash \{ures\}$. Előfeltétel: $Q = (s = s' \wedge s' \neq \emptyset)$, utófeltétel: $R = (s = s' \backslash \{(e,t)\} \wedge (e,t) \in s' \wedge \forall i (e_i, t_i) \in s' : t \leq t_i)$.
\end{itemize}
\item \textit{absztrakt adatszerkezet (ADS)}: kognitív pszichológia szintje, ábrák. Az alapvető szerkezeti tulajdonságokat tartalmazza (nem mindet). Ennek a szintnek is része a műveletek halmaza. Példák: az ábra egy irányított gráf, művelet magyarázata, adatszerkezet definiálása.
\begin{figure}[H]
\centering
\includegraphics[width=1\textwidth]{img/ads.png}
\caption{ADS}
\end{figure}
\item \textit{ábrázolás/reprezentáció}: döntések (tömbös vagy pointeres ábrázolás), a nyitva hagyott szerkezeti kérdések. Egy adatszerkezetet többféle reprezentációval is meg lehet valósítani (pl. prioritásos sor lehet rendezetlen tömb, rendezett tömb, kupac).
\begin{itemize}
\item \textit{tömbös ábrázolás}: takarékos ábrázolás, elhelyezése, tetszőleges rákövetkezések, bejárások, de ezeket meg kell adni.
\item \textit{pointeres ábrázolás}: minden pointer egy összetett rekord elejére mutat.
\end{itemize}
\item \textit{implementálás}
\item \textit{fizikai szint}
\end{enumerate}
\subsection{Műveletei}
\begin{itemize}
\item Üres adatszerkezet létrehozása
\item Annak lekérdezése, hogy üres-e az adatszerkezet
\item Elem berakása, itt ellenőrizni kell, hogy nem telt-e még meg
\item Elem kivétele vagy törlése, itt ellenőrizni kell, hogy nem üres-e
\item Adott tulajdonságú elem (például maximum, veremben a felső) lekérdezése, itt is ellenőrizni kell, hogy üres-e az adatszerkezet
\item Bejárások (preorder, inorder, postorder, szintfolytonos), listáknál az első, előző vagy következő elemre lépés
\item Elem módosítása bizonyos adatszerkezeteknél (pl. listák)
\end{itemize}
\subsection{Fontosabb alkalmazásai}
\textit{Prioritásos sor}: nagygépes programfuttatásnál az erőforrásokat a prioritás arányában osszuk el, adott pillanatban a maximális prioritásút válasszuk. Sürgősségi ügyeleten, gráfalgoritmusoknál is alkalmazható.
\textit{B-fa}: ipari méretekben adatbázisokban használják.
\section{A hatékony adattárolás és visszakeresés néhány megvalósítása (bináris keresőfa, AVL-fa, 2-3-fa és B-fa, hasítás (,,hash-elés”))}
\subsection{Bináris keresőfa}
Nincsenek benne azonos kulcsok, a követendő elv: ,,kisebb balra, nagyobb jobbra". Inorder bejárással növekvő kulcssorozatot kapunk. \\
Műveletigénye fa magasságú nagyságrendű. \\
Az a cél, hogy a bináris keresőfa ne nyúljon meg láncszerűen, erre jó az AVL-fa és a 2-3-fa.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{img/Beszur.jpg}
\includegraphics[width=0.3\textwidth]{img/Kovetkezo.jpg}
\caption{Bináris keresőfa műveletei}
\end{figure}
\subsection{AVL-fa}
Cél: a $t$ bináris keresőfa magasságának $\log_2(n)$ közelében tartása, azaz $h(t) \leq c \cdot \log_2(n)$, ahol $c$ elfogadhatóan kicsi. Az ilyen fát kiegyensúlyozottnak nevezzük. \\
\textit{AVL}: Adelszon-Velszkij, Landisz 1962-ben alkották meg. \\
A $t$ bináris keresőfát egyúttal AVL-fának nevezzük $\iff$ $t$ minden $x$ csúcsára $|h(bal(x))-h(jobb(x))| \leq 1$. \\
Minden csúcsnak van egy címkéje $+,-,=$ (gyerekek magasságának különbsége). A beszúrás helyétől felfelé ellenőrizzük ezeket, és ha kell, akkor módosítjuk. Ha valahol $++$ vagy $--$ alakul ki, akkor ott elromlik az AVL-tulajdonság, egy vagy több forgatással vagy átkötéssel konstans műveletigénnyel helyre lehet hozni. \\
Többféle séma is van: $(++,+), (++,-), (++,=)$ és a tükörképeik.
\subsection{2-3-fa és B-fa}
2-3-fa kis méretben az elmélet számára jó, a B-fa a gyakorlati változat adatbázisban. \\
$t$ 2-3-fa $\iff$ minden belső csúcsnak 2 vagy 3 gyereke van, a levelek azonos szinten helyezkednek el, adatrekordok csak a levelekben vannak, belső pontokban kulcsok és mutatók, levelekben a kulcsok balról jobbra nőnek. \\
Ha 4 gyerek lenne a beszúrás után, akkor csúcsot kell vágni. Ha törlésnél 1 gyerek lenne valahol, akkor csúcsösszevonásokat és gyerekátadást alkalmazunk. \\
B-fa nagyobb méretű, itt két határ között mozog a gyerekszám: $\lceil\frac{r}{2}\rceil$ és $r$, ahol $50 \leq r \leq 1000$.
\subsection{Hasítás}
Kulcsos rekordokat tárol.
\begin{itemize}
\item \textit{Hasítás láncolással}: a kulcsütközést láncolással oldja fel. Van egy hasítófüggvény: $h: U \to [0..m-1]$, elvárás vele kapcsolatban, hogy gyorsan számolható és egyenletes legyen. $m$-et úgy választjuk meg $n$ nagyságrendjének ismeretében, hogy $\alpha = \frac{n}{m}$ lesz a várható listahossz, ha egyenletes hasítást feltételezünk.\\
Például kétirányú listát használhatunk a hasításhoz. Műveletek: beszúrás, keresés, törlés. \\
Gyakorlatban érdemes $m$-et úgy megválasztani, hogy olyan prímszám legyen, ami nem esik 2-hatvány közelébe.
\item \textit{Hasítás nyitott/nyílt címzéssel}: A kulcsokat lehessen egészként értelmezni, ekkor vannak jó hasítófüggvények. \\
Próbálkozás általános képlete: $h(k) + h_i(k)$ $(mod$ $M)$, $0 \leq i \leq M-1$. Egész addig alkalmazza, amíg üres helyet nem talál.
\begin{enumerate}
\item \textit{Lineáris próba}: $h_i(k) = -i$ $(mod$ $M)$, egyesével balra lépegetve keressük az üres helyet. Hátránya az elsődleges csomósodás, ez jelentős lassulást okoz beszúrásnál és keresésnél.
\item \textit{Négyzetes próba}: $h_i(k) = (-1)^i(\lceil\frac{i}{2}\rceil)^2$ $(mod$ $M)$, a négyzetszámokkal lépegetünk balra-jobbra, ezek az eltolások kiadják $\{0,1,...,M-1\}$-et. Hátrány: másodlagos csomósodás.
\item \textit{Kettős hash-elés}: $h_i(k) =-ih'(k)$ $(mod$ $M)$, $h'(k)$ a $k$-hoz tartozó egyedi lépésköz, $(h'(k),M)=1$ relatív prímek. Ha az $M$ elég nagy, akkor nincs csomósodás.
\end{enumerate}
\item \textit{Hasítófüggvények}: Leggyakoribb: $k$ egész, kongruencia reláció. Általánosan: $h(k) = (ak +b$ $(mod$ $p))$ $(mod$ $M)$, az univerzális hasítás családja. Tapasztalat: $k$ egyenletesen hasít.
\end{itemize}
\end{document}

View File

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

View File

@@ -0,0 +1,139 @@
\documentclass[margin=0px]{article}
\usepackage{listings}
\usepackage[utf8]{inputenc}
\usepackage{graphicx}
\usepackage{float}
\usepackage[a4paper, margin=0.7in]{geometry}
\usepackage{subcaption}
\usepackage{amsthm}
\usepackage{amssymb}
\usepackage{amsmath}
\usepackage{fancyhdr}
\usepackage{setspace}
\onehalfspacing
\renewcommand{\figurename}{ábra}
\newenvironment{tetel}[1]{\paragraph{#1 \\}}{}
\newcommand{\R}{\mathbb{R}}
\pagestyle{fancy}
\lhead{\it{PTI BSc Záróvizsga tételek}}
\rhead{16. Haladó algoritmusok}
\title{\textbf{{\Large ELTE IK - Programtervező Informatikus BSc} \vspace{0.2cm} \\ {\huge Záróvizsga tételek}} \vspace{0.3cm} \\ 16. Haladó algoritmusok}
\author{}
\date{}
\begin{document}
\maketitle
\begin{tetel}{Haladó algoritmusok}
Elemi gráf algoritmusok: szélességi, mélységi bejárás és alkalmazásai. Minimális feszítőfák, általános algoritmus, Kruskal és Prim algoritmusai. Legrövidebb utak egy forrásból, sor alapú Bellman-Ford, Dijkstra, DAG legrövidebb út. Legrövidebb utak minden csúcspárra: Floyd-Warshall algoritmus. Gráf tranzitív lezártja.
\end{tetel}
\section{Gráfalgoritmusok}
\subsection{Gráf ábrázolás}
\begin{description}
\item[Láncolt listás ábrázolás] \hfill \\
A gráf csúcsait helyezzük el egy tömbben (vagy láncolt listában). Minden elemhez rendeljünk hozzá egy láncolt listát, melyben az adott csúcs szomszédjait (az esetleges élsúlyokkal) soroljuk fel.
\item[Mátrixos ábrázolás] \hfill \\
Legyen a csúcsok elemszáma $n$. Ekkor egy $A^{n\times n}$ mátrixban jelöljük, hogy mely csúcsok vannak összekötve. Ekkor mind a sorokban, mind az oszlopokban a csúcsok szerepelnek, és az $a_{ij}$ cellában a $i$ csúcsból $j$ csúcsba vezető él súlya szerepel, ha nincs él a két csúcs között, akkor $-\infty$ (súlyozatlan esetben $1$ és $0$)
Amennyiben a gráf irányítatlan nyilván $a_{ij} = a_{ji}$
\end{description}
\subsection{Szélességi bejárás}
$G$ gráf (irányított/irányítatlan) $s$ startcsúcsából a távolság sorrendjében érjük el a csúcsokat. A legrövidebb utak feszítőfáját adja meg, így csak a távolság számít, a súly nem.
A nyilvántartott csúcsokat egy sor adatszerkezetben tároljuk, az aktuális csúcs gyerekeit a sor-ba tesszük. A következő csúcs pedig a sor legelső eleme lesz.
A csúcsok távolságát egy $d$, szüleiket egy $\pi$ tömbbe írjuk, és $\infty$ illetve $0$ értékekkel inicializáljuk.
Az algoritmus:
\begin{enumerate}
\item Az $s$ startcsúcsot betesszük a sorba
\item A következő lépéseket addig ismételjük, míg a sor üres nem lesz
\item Kivesszük a sor legelső ($u$) elemét
\item Azokat a gyerekcsúcsokat, melyeknek a távolsága nem $\infty$ figyelmen kívül hagyjuk (ezeken már jártunk)
\item A többi gyerekre ($v$): beállítjuk a szülőjét ($\pi[v] = u$), és a távolságát ($d[v] = d[u]+1$). Majd berakjuk a sorba.
\end{enumerate}
\subsection{Minimális költségű utak keresése}
\begin{description}
\item[Dijkstra algoritmus] \hfill \\
Egy $G$ irányított, pozitív élsúlyokkal rendelkező gráfban keres $s$ startcsúcsból minimális költségű utakat minden csúcshoz.
Az algoritmus a szélességi bejárás módosított változata. Mivel itt egy hosszabb útnak lehet kisebb a költsége, mint egy rövidebbnek, egy már megtalált csúcsot nem szabad figyelmen kívül hagyni. Ezért minden csúcs rendelkezik három állapottal (nem elért, elért, kész). A $d$ és $\pi$ tömböket a szélességi bejáráshoz hasonlóan kezeljük.
A még nem kész csúcsokat egy prioritásos sorba helyezzük, vagy minden esetben minimumkeresést alkalmazunk.
Az algoritmus:
\begin{enumerate}
\item Az $s$ startcsúcs súlyát 0-ra állítjuk eltároljuk
\item A következő lépéseket addig ismételjük, míg a konténerünk üres nem lesz
\item Kivesszük a sor legjobb ($u$) elemét, és "kész"-re állítjuk
\item Ha egy gyerekcsúcs ($v$) nem kész, és a jelenleg hozzávezető út súlya kisebb, mint az eddigi, akkor: a szülőjét $u$-ra állítjuk ($\pi[v] = u$), és a súlyát frissítjük ($d[v] = d[u]+d(u,v)$).
\item A többi csúcsot kihagyjuk.
\end{enumerate}
\item[Bellman-Ford algoritmus] \hfill \\
Egy $G$ élsúlyozott (akár negatív) irányított gráf $s$ startcsúcsából keres minden élhez minimális költségű utakat, illetve felismeri, ha negatív költségű kör van a gráfban. A $d$ és $\pi$ tömböket az előzőekhez hasonlóan kezeljük.
Az algoritmus:
\begin{enumerate}
\item A startcsúcs súlyát állítsuk be 0-ra.
\item $n-1$ iterációban menjünk végig az összes csúcson, és minden csúcsot ($u$) vessünk össze minden csúccsal ($v$). Ha olcsóbb utat találtunk akkor $v$-be felülírjuk a súlyát ($d[v] = d[u]+d(u,v)$), és a szülőjét ($\pi[v] = u$).
\item Ha az $n$-edik iterációban is történt módosítás, negatív kör van a gráfban
\end{enumerate}
\end{description}
\subsection{Minimális költség feszítőfa keresése}
A Prim algoritmus egy irányítatlan élsúlyozott (akár negatív) gráf $s$ startcsúcsából keres minimális költségű feszítőfát. A $d$ és $\pi$ tömböket az előzőekhez hasonlóan kezeljük. Az algoritmus egy prioritásos sorba helyezi a csúcsokat.
Az algoritmus:
\begin{enumerate}
\item A startcsúcs súlyát állítsuk be 0-ra.
\item A csúcsokat behelyezzük a prioritásos sorba.
\item A következő lépéseket addig végezzük, míg a prioritásos sor ki nem ürül.
\item Kiveszünk egy csúcsot ($u$) a sorból.
\item Minden gyerekére ($v$), amely még a sorban és a nyilvántartott $v$-be vezető él súlya nagyobb, mint a most megtalált: A $v$ szülőjét $u$-ra változtatjuk, a nyilvántartott súlyt felülírjuk $d[v] = d(u,v)$. Majd felülírjuk a $v$ állapotát a prioritásos sorban.
\item Azokkal a gyerekekkel, melyek nincsenek a sorban, vagy a súlyukon nem tudunk javítani, nem változtatunk.
\end{enumerate}
\subsection{Mélységi bejárás}
$G$ irányított (nem feltétlenül összefüggő) gráf mélységi bejárásával egy mélységi fát (erdőt) kapunk. Az algoritmus a következő:
\begin{itemize}
\item Az élsúlyok nem játszanak szerepet
\item Nincs startcsúcs, a gráf minden csúcsára elindítjuk az algoritmust. (Természetesen ekkor, ha már olyan csúcsot választunk, amin már voltunk, az algoritmus nem indul el.)
\item A csúcsokat mohón választjuk, azaz minden csúcs gyerekei közül az elsőt választva haladunk előre, amíg csak lehet. (Olyan csúcsot találunk, amelynek nincs gyereke, vagy minden gyerekén jártunk már.)
\item Ha már nem lehet előre haladni visszalépünk.
\item Minden csúcshoz hozzárendelünk két értéket. Az egyik a mélységi sorszám, mely azt jelöli, hogy hanyadiknak értük el. A másik a befejezési szám, mely azt jelzi, hogy hanyadiknak léptünk vissza belőle.
\end{itemize}
A gráf éleit a mélységi bejárás közben osztályozhatjuk. (Inicializáláskor minden értéket 0-ra állítottunk)
\begin{itemize}
\item Faél: A következő csúcs mélységi száma 0
\item Visszaél: A következő csúcs mélységi száma nagyobb, mint 0, és befejezési száma 0 (Tehát az aktuális út egy előző csúcsára kanyarodunk vissza)
\item Keresztél: A következő csúcs mélységi száma nagyobb, mint 0, és befejezési száma is nagyobb, mint 0, továbbá az aktuális csúcs mélységi száma nagyobb, mint a következő csúcs mélységi száma. (Ekkor egy az aktuális csúcsot megelőző csúcsból induló, már megtalált útba mutató éllel van dolgunk)
\item Előreél: A következő csúcs mélységi száma nagyobb, mint 0, és befejezési száma is nagyobb, mint 0, továbbá az aktuális csúcs mélységi száma kisebb, mint a következő csúcs mélységi száma. (Ekkor egy az aktuális csúcsból induló, már megtalált útba mutató éllel van dolgunk)
\end{itemize}
\subsection{DAG Topologikus rendezése}
\begin{description}
\item[Alapfogalmak] \hfill
\begin{itemize}
\item Topologikus rendezés: \\
Egy $G(V,E)$ gráf topologikus rendezése a csúcsok olyan sorrendje, melyben $\forall (u\rightarrow v) \in E$ élre $u$ előbb van a sorrendben , mint $v$
\item DAG - Directed Acyclic Graph: \\
Irányított körmentes gráf. \\
Legtöbbször munkafolyamatok irányítására illetve függőségek analizálására használják.
Tulajdonságok:
\begin{itemize}
\item Ha $G$ gráfra a mélységi bejárás visszaélt talál (Azaz kört talált) $\Longrightarrow$ $G$ nem DAG
\item Ha $G$ nem DAG (van benne kör) $\Longrightarrow$ Bármely mélységi bejárás talál visszaélt
\item Ha $G$-nek van topologikus rendezések $\Longrightarrow$ $G$ DAG
\item Minden DAG topologikusan rendezhető.
\end{itemize}
\end{itemize}
\item[DAG topologikus rendezése] \hfill \\
Egy $G$ gráf mélységi bejárása során tegyük verembe azokat a csúcsokat, melyekből visszaléptünk. Az algoritmus után a verem tartalmát kiírva megkapjuk a gráf egy topologikus rendezését.
\end{description}
\end{document}

View File

@@ -0,0 +1,668 @@
\documentclass[margin=0px]{article}
\usepackage{listings}
\usepackage[utf8]{inputenc}
\usepackage{graphicx}
\usepackage{float}
\usepackage[a4paper, margin=0.7in]{geometry}
\usepackage{amsthm}
\usepackage{amssymb}
\usepackage{t1enc}
\usepackage{fancyhdr}
\usepackage{setspace}
\onehalfspacing
\newenvironment{tetel}[1]{\paragraph{#1 \\}}{}
\pagestyle{fancy}
\lhead{\it{PTI BSc Záróvizsga tételek}}
\rhead{17. Operációs rendszerek}
\title{\textbf{{\Large ELTE IK - Programtervező Informatikus BSc} \vspace{0.2cm} \\ {\huge Záróvizsga tételek}} \vspace{0.3cm} \\ 17. Operációs rendszerek}
\author{}
\date{}
\begin{document}
\maketitle
\begin{tetel}{Operációs rendszerek}
Folyamatok megvalósítása, ütemező algoritmusaik. Párhuzamosság, kritikus szekciók, kölcsönös kizárás megvalósítása. Peterson algoritmus. Szemaforok, osztott memória, üzenetküldés. Be-és kimeneti eszközök ütemezési lehetőségei, holtpontok. Memóriakezelés, virtuális memóriakezelés fogalma. Lapozás és szegmentálás. Lapcserélési algoritmusok (pl: LRU). Háttértárak, redundancia, fájlrendszerek, alapvető típusaik és szolgáltatásaik, jellemzőik.
\end{tetel}
\section{Operációs rendszer}
Olyan programrendszer, amely a számítógépes rendszerben a programok végrehajtását vezérli: így például ütemezi a programok végrehajtását, elosztja az erőforrásokat, biztosítja a felhasználó és a számítógépes rendszer közötti kommunikációt. Olyan program, ami egyszerű felhasználói felületet nyújt, eltakarva a számítógép(rendszer) eszközeit. \\
\section{Folyamatok megvalósítása, ütemező algoritmusaik}
\subsection{Folyamatok megvalósítása}
\textit{Program}: fájlrendszerben egy bájthalmaz. \\
\textit{Folyamat}(processz): futó program a memóriában (kód + I/O adatok + állapot). \\
Egyszerre hány folyamat működik? \\
Valódi multitask esetén egymástól teljesen függetlenül mennek a folyamatok. Operációs rendszerek egy szekvenciális modellt követnek, ami álmultitasking. Itt egyidejűleg a memóriához csak egy folyamat fér hozzá, gyorsan váltogat a dolgok között (multiprogramozás). \\
Az operációs rendszernek ahhoz, hogy ezeket a folyamatokat helyesen tudja kezelni, felügyelnie kell a folyamatokat. Az operációs rendszerünk így minden egyes folyamatot nyilvántart, és az operációs rendszer lelkének is nevezett ütemező (scheduler) segítségével szépen sorban minden egyes folyamatnak ad egy kis processzor- (CPU) időszeletet, amíg az adott folyamat dolgozik, azaz a processzorra kerülhet.
\textit{Rendszer modell}: 1 processzor + 1 rendszer memória + 1 I/O eszköz = 1 feladat-végrehajtás \\
Interaktív (ablakos) rendszerekben több program, processz fut.
\begin{itemize}
\item Környezetváltásos rendszer: csak az előtérben lévő alkalmazás fut
\item Kooperatív rendszer: az aktuális processz bizonyos időközönként, vagy időkritikus műveletnél önként lemond a CPU-ról (Win 3.1)
\item Preemptív rendszer: az aktuális processztől a kernel bizonyos idő után elveszi a vezérlést, és a következő várakozó folyamatnak adja.
\item Real time rendszer: egy operációs rendszer nyújtson lehetőséget az időfaktor figyelembe vételéhez. A mai OR-ek kezdenek ilyen tulajdonságokkal is kiegészülni.
\end{itemize}
\textit{Folyamatok létrehozása}: ma tipikusan preemptív rendszereket használunk. Létrehozás oka lehet: rendszer inicializálás, folyamatot eredményező rendszerhívás (másolat az eredetiről [fork], az eredeti cseréje [execve]), felhasználói kérés (parancs\&), nagy rendszerek kötegelt feladatai. \\
A folyamatok futhatnak az előtérben, illetve a háttérben. Ez utóbbiakat hívjuk démonoknak.\\
\textit{Folyamatok kapcsolata}: Szülő-gyermek kapcsolat, folyamatfa: egy folyamatnak egy szülője van, egy folyamatnak viszont lehet több gyereke is, vannak összetartozó folyamatcsoportok. \\ Reinkarnációs szerver: meghajtó programok, kiszolgálók elindítója, ha elhal az egyik, akkor azt újraszüli, reinkarnálja. \\
\textit{Folyamatok befejezése}: Egy folyamat az elindulása után a megadott időkeretben (el)végzi a feladatát. A befejezés lehet önkéntes vagy önkéntelen.
\begin{itemize}
\item Önkéntes befejezések: Szabályos kilépés (exit, return stb.), Kilépés valamilyen hiba miatt, amit a program felfedez (szintén pl. return utasítással).
\item Önkéntelen befejezések: Illegális utasítás, végzetes hiba (0-val osztás, nem létező memória használat, stb), Külső segítséggel: Másik processz, netán mi ,,lőjük” ki az adott folyamatot.
\end{itemize}
\textit{Folyamatok állapota}: A folyamat önálló programegység, saját utasításszámlálóval, veremmel stb. Általában nem függetlenek a folyamatok, egyik-másik eredményétől függ a tevékenység. Egy folyamat három állapotban lehet:
\begin{itemize}
\item Futó
\item Futásra kész, ideiglenesen leállították, arra vár, hogy az ütemező CPU időt adjon a folyamatnak
\item Blokkolt, ha logikailag nem lehet folytatni a tevékenységet, mert pl. egy másik eredményére vár. (catFradi.txt|grepFradi|sort, grep és sort blokkolt az elején)
\end{itemize}
\begin{figure}[H]
\centering
\includegraphics[width=0.6\textwidth]{img/allapot.png}
\caption{Állapotátmenetek}
\end{figure}
\textit{További állapotok}: alvó, megállított, zombi (ha egy gyermek folyamat befejeződik, de szülője nem hív wait(\&st) hívást, akkor a gyermek bent marad a processztáblában, init folyamat törli ezeket). \\
\textit{\textbf{Folyamatok megvalósítása}}: A processzor csak végrehajtja az aktuális utasításokat. Egyszerre egy folyamat aktív. Folyamatokról nem tud a processzor. Ha lecseréljük az aktív folyamatot a következőre, akkor mindent meg kell őrizni, hogy visszatérhessünk a folytatáshoz. A ,,minden": utasításszámláló, regiszterek, lefoglalt memória állapot, nyitott fájl infók, stb. Ezeket az adatokat az úgynevezett folyamatleíró táblában tároljuk (processz tábla, processz vezérlő blokk). Van egy I/O megszakításvektor is. \\
A folyamatokat úgy is osztályozhatjuk, hogy számításigényes vagy input/output-igényes (avagy beviteli/kiviteli, röviden B/K vagy I/O) folyamatról van-e szó. Könnyen belátható, hogy a számításigényes folyamatoknak az a legjobb, ha az ütemező általában hosszú időperiódusra adja meg nekik a processzort, míg az input/output-igényes folyamatoknak a rövidebb periódusidő a megfelelőbb.
\subsection{Ütemező algoritmusok}
\textit{Folyamatok váltása}: Kezdeményezheti időzítő, megszakítás, esemény, rendszerhívás kezdeményezés. Az ütemező elmenti az aktuális folyamat jellemzőket a folyamatleíró táblába. Betölti a következő folyamat állapotát, a processzor folytatja a munkát. Nem lehet menteni a gyorsítótárakat. Gyakori váltás többleterőforrást igényel. A folyamatváltási idő „jó” megadása nem egyértelmű. \\
\textit{Folyamatleíró táblázat}(Process Control Block - PCB): A rendszer inicializálásakor létrejön; 1 elem, rendszerindító már bent van, mikor a rendszer elindul. Tömbszerű szerkezet (PID alapon), de egy-egy elem egy összetett processzus adatokat tartalmazó struktúra. Egy folyamat fontosabb adatai: Azonosítója (ID), neve (programnév); Tulajdonos, csoport azonosító; Memória, regiszter adatok stb. \\
\textit{Szálak}: Önállóan működő programegységek (thread), egy folyamaton belüli különálló utasítássor. Általában egy folyamat = egy utasítássorozat = egy szál. Néha szükséges lehet, hogy egy folyamaton belül ,,több utasítássorozat" legyen. Gyakran ,,lightweight process"-nek nevezik a több utasítássorozatos folyamatot. Egy folyamaton belül több egymástól ,,független" végrehajtási sor lehet. Lehet egy folyamaton belül egy szál vagy egy folyamaton belül több szál. Ez utóbbi esetben, ha egy szál blokkolódik, a folyamat is blokkolva lesz. Van külön száltáblázat. \\
Folyamatnak önálló címtartománya van, globális változói, megnyitott fájlleírói, gyermekfolyamatai, szignálkezelői, ébresztői stb., szálnak ezek nincsenek; viszont mindkettőnek vannak utasításszámlálói, regiszterei, van verme. \\ \\
Egyszerre csak 1 folyamat tud futni. Az ütemező hozza meg a döntést. Ütemezési algoritmus alapján dönti el, hogy melyik fusson. \\
Folyamatváltás biztosan van: ha befejeződik egy folyamat, vagy ha egy folyamat blokkolt állapotba kerül (I/O vagy szemafor miatt). Általában van váltás: ha új folyamat jön létre, I/O megszakítás bekövetkezés (I/O megszakítás után jellemzően egy blokkolt folyamat, ami erre várt, folytathatja futását), időzítő megszakítás (nem megszakítható ütemezés, megszakítható ütemezés). \\
Ütemezések csoportosítása:
\begin{itemize}
\item Minden rendszerre jellemző a pártatlanság, hogy mindenki hozzáférhet a CPU-hoz, ugyanazok az elvek érvényesek mindenkire, és ,,azonos” terhelést kapnak.
\item Kötegelt rendszerek: Áteresztőképesség, áthaladási idő, CPU kihasználtság
\item Interaktív rendszerek: Válaszidő, megfelelés a felhasználói igényeknek
\item Valós idejű rendszerek: Határidők betartása, adatvesztés, minőségromlás
elkerülése
\end{itemize}
\textbf{Ütemezés kötegelt rendszerekben}:
\begin{itemize}
\item Sorrendi ütemezés, nem megszakítható
\begin{itemize}
\item First Come First Served - (FCFS)
\item Egy folyamat addig fut, amíg nem végez, vagy nem blokkolódik.
\item Ha blokkolódik, a sor végére kerül.
\item Pártatlan, egyszerű, láncolt listában tartjuk a folyamatokat.
\item Hátránya: I/O igényes folyamatok nagyon lassan végeznek.
\end{itemize}
\item Legrövidebb feladat először, nem megszakítható ez se (shortest job first -- SJB)
\begin{itemize}
\item Kell előre ismerni a futási időket
\item Akkor optimális, ha kezdetben mindenki elérhető
\end{itemize}
\item Legrövidebb maradék futási idejű következzen
\begin{itemize}
\item Megszakítható, minden új belépéskor vizsgálat.
\end{itemize}
\item Háromszintű ütemezés
\begin{itemize}
\item Bebocsátó ütemező: A feladatokat válogatva engedi be a memóriába.
\item Lemez ütemező: Ha a bebocsátó sok folyamatot enged be és elfogy a memória, akkor lemezre kell írni valamennyit, meg vissza. Ez ritkán fut.
\item CPU ütemező: A korábban említett algoritmusok közül választhatunk.
\end{itemize}
\end{itemize}
\textbf{Ütemezés interaktív rendszerekben}:
\begin{itemize}
\item Körben járó ütemezés -- Round Robin
\begin{itemize}
\item Mindenkinek időszelet, aminek végén, vagy blokkolás esetén jön a következő folyamat
\item Időszelet végén a körkörös listában következő lesz az aktuális folyamat
\item Pártatlan, egyszerű
\item Egy listában tárolhatjuk a folyamatokat (jellemzőit), és ezen megyünk körbe-körbe.
\item Időszelet mérete lehet probléma, mert a processz átkapcsolás időigényes. Ha kicsi az idő, akkor sok CPU megy el a kapcsolgatásra, ha pedig túl nagy, akkor interaktív felhasználóknak lassúnak tűnhet pl a billentyűkezelés.
\end{itemize}
\item Prioritásos ütemezés
\begin{itemize}
\item Fontosság, prioritás bevezetése. Unix: 0-49 nem megszakítható (kernel) prioritás, 50-127 user prioritás
\item Legmagasabb prioritású futhat. Dinamikus prioritás módosítás, különben éhenhalás
\item Prioritási osztályok használata. Egy osztályon belül Round Robin. Ki kell igazítani a folyamatok prioritását, különben az alacsonyak nagyon ritkán jutnak CPU-hoz. Tipikusan minden 100 időszeletnél a prioritásokat újraértékeli és ilyenkor jellemzően a magas prioritások alacsonyabbra kerülnek, majd ezen a soron megy RR. A végén újra felállnak az eredeti osztályok.
\end{itemize}
\item Többszörös sorok
\begin{itemize}
\item Szintén prioritásos és RR
\item Legmagasabb szinten minden folyamat 1 időszeletet kap
\item Következő 2-t, majd 4-et, 8, 16,32,64-et.
\item Ha elhasználta a legmagasabb szintű folyamat az idejét egy szinttel lejjebb kerül.
\end{itemize}
\item Legrövidebb folyamat előbb
\begin{itemize}
\item Bár nem tudjuk a hátralévő időt, de becsüljük meg az előzőekből.
\item Öregedés, súlyozott átlag az időszeletre: T0, T0/2+T1/2, T0/4+T1/4+T2/2, T0/8+T1/8+T2/4+T3/2
\end{itemize}
\item Garantált ütemezés
\begin{itemize}
\item Minden aktív folyamat arányos CPU időt kap.
\item Nyilván kell tartani, hogy egy folyamat már mennyi időt kapott, ha valaki arányosan kevesebb időt kapott, az kerül előbbre.
\end{itemize}
\item Sorsjáték ütemezés
\begin{itemize}
\item Mint az előző, csak a folyamatok között ,,sorsjegyeket" osztunk szét, az kapja a vezérlést, akinél a kihúzott jegy van
\item Arányos CPU időt könnyű biztosítani, hasznos pl. video szervereknél
\end{itemize}
\item Arányos ütemezés
\begin{itemize}
\item Vegyük figyelembe a felhasználókat is. Olyan, mint a garantált, csak a felhasználókra vonatkoztatva.
\end{itemize}
\end{itemize}
\textbf{Ütemezés valós idejű rendszerekben} \\
A valós idejű rendszerben az idő kulcsszereplő. Garantálni kell adott határidőre a tevékenység, válasz megadását.
\begin{itemize}
\item Hard Real Time (szigorú), abszolút, nem módosíthatóhatáridők.
\item Soft Real Time (toleráns), léteznek a határidők, de ezek kis mértékű elmulasztása tolerálható.
\end{itemize}
A programokat több kisebb folyamatra bontják. Külső esemény észlelésekor, adott határidőre válasz
kell. Ütemezhető: ha egységnyi időre eső n esemény CPU válaszidő összege <=1. \\
Gyakori a gyermek folyamatok jelenléte a rendszerben. A szülőnek nem biztos, hogy minden
gyermekével azonos prioritásra van szüksége. Tipikusan a kernel \textit{prioritásos ütemezést}
használ (+RR):
\begin{itemize}
\item Biztosít egy rendszerhívást, amivel a szülő a gyermek prioritását adhatja meg
\item Kernel ütemez -- felhasználói folyamat szabja meg az elvet, prioritást.
\end{itemize}
\textbf{Szálütemezés}:
\begin{itemize}
\item Felhasználói szintű szálak
\begin{itemize}
\item Kernel nem tud róluk, a folyamat kap időszeletet, ezen belül a szálütemező dönt ki fusson
\item Gyors váltás a szálak között
\item Alkalmazásfüggő szálütemezés lehetséges
\end{itemize}
\item Kernel szintű szálak
\begin{itemize}
\item Kernel ismeri a szálakat, kernel dönt melyik folyamat melyik szála következzen
\item Lassú váltás, két szál váltása között teljes környezetátkapcsolás kell
\item Ezt figyelembe is veszik.
\end{itemize}
\end{itemize}
\section{Párhuzamosság, kritikus szekciók, kölcsönös kizárás megvalósítása}
\subsection{Párhuzamosság és megvalósítása}
Ütemező a folyamatok gyors váltogatásával ,,teremt" párhuzamos végrehajtás érzetet. \\
Többprocesszoros rendszerekben több processzor van egy gépben, nagyobb a teljesítmény, de a megbízhatóságot általában nem növeli. \\
Klaszterek: megbízhatóság növelése elsősorban a cél.
\subsection{Kritikus szekciók}
Azokat az utasításokat, azt a programrészt, amelyben a programunk a közös adatokat használja, kritikus területnek, kritikus szekciónak vagy kritikus blokknak nevezzük. \\
Kulcskérdés: a közös erőforrások használata, amikor két folyamat ugyanazt a memóriát használja. Kritikus programterület, szekció, az a rész, mikor a közös erőforrást (memóriát) használjuk. \\
Versenyhelyzet: két vagy több folyamat közös memóriát ír vagy olvas, a végeredmény a futási időpillanattól függ. Nehezen felderíthető hibát okoz. \\
Megoldás: Módszer, ami biztosítja, hogy a közös adatokat egyszerre csak egy folyamat tudja használni.
\subsection{Kölcsönös kizárás és megvalósítása}
Kölcsönös kizárásnak nevezzük azt a módszert, ami biztosítja, hogy ha egy folyamat használ valamilyen megosztott, közös adatot, akkor más folyamatok ebben az időben ne tudják azt elérni. \\
A jó kölcsönös kizárás az alábbi feltételeknek felel meg:
\begin{itemize}
\item Nincs két folyamat egyszerre a kritikus szekciójában.
\item Nincs sebesség, CPU paraméter függőség.
\item Egyetlen kritikus szekción kívül levő folyamat sem blokkolhat másik folyamatot.
\item Egy folyamat sem vár örökké, hogy a kritikus szekcióba tudjon belépni.
\end{itemize}
\begin{figure}[H]
\centering
\includegraphics[width=0.9\textwidth]{img/mutex.png}
\caption{A megkívánt kölcsönös kizárás viselkedése}
\end{figure}
\subsubsection{Megvalósítások}
\begin{itemize}
\item Megszakítások tiltása (összes): Belépéskor az összes megszakítás tiltása, Kilépéskor azok engedélyezése. Ez nem igazán jó, mivel a felhasználói folyamatok kezében lenne a megszakítások tiltása, persze a kernel használja.
\item Osztott, ún. zárolás változó használata: 0 (senki) és 1 (valaki) kritikus szekcióban van. Két folyamat is kritikus szekcióba tud kerülni! Egyik folyamat belép a kritikus szekcióba, de éppen az 1-re állítás előtt a másik folyamat kerül ütemezésre.
\item Szigorú váltogatás: Több folyamatra is általánosítható. A kölcsönös kizárás feltételeit teljesíti a 3. kivételével, ugyanis ha pl 1 folyamat a lassú, nem kritikus szekcióban van, és a 0 folyamat gyorsan belép a kritikus szekcióba, majd befejezi a nem kritikus szekciót is, akkor ez a folyamat blokkolódik mert a kovetkezo=1 lesz!(Saját magát blokkolja!)
\begin{figure}[H]
\centering
\includegraphics[width=0.9\textwidth]{img/szigoru.png}
\caption{Szigorú váltogatás}
\end{figure}
\item G. L. Peterson javította a szigorú váltogatást. A kritikus szekció előtt minden folyamat meghívja a belépés, majd utána kilépés függvényt.
\begin{figure}[H]
\centering
\includegraphics[width=0.6\textwidth]{img/peterson.png}
\includegraphics[width=0.3\textwidth]{img/petersonhiba.png}
\caption{Peterson javítása és a benne rejlő hiba}
\end{figure}
Ez a javítás viszont nagy hibát okozhat. Tegyük fel proc=0. A jelölt ütemezés váltásnál a proc=1 belépése jön. Mivel akarja[0] értéke 0, ezért az 1-es process belép a kritikus szakaszba! Ekkor újra váltson az ütemező, akarja[1]=1, a következő értéke szintén 1, így a következo==proc hamis, azaz a 0. proc is belép a kritikus szakaszba!
\item Tevékeny várakozás gépi kódban: TSL utasítás, Test and Set Lock. Ez atomi művelet, vagyis megszakíthatatlan.
\item Tevékeny várakozás: A korábbi Peterson megoldás is, a TSL használata is jó, csak ciklusban várakozunk. A korábbi megoldásokat, tevékeny várakozással (aktív várakozás) megoldottnak hívjuk, mert a CPU-t ,,üres" ciklusban járatjuk a várakozás során.De ez a CPU időt pazarolja. Helyette jobb lenne az, ha a kritikus szekcióba lépéskor blokkolna a folyamat, ha nem szabad belépnie. Az aktív várakozás nem igazán hatékony. Megoldás: blokkoljuk(alvás) várakozás helyett a folyamatot, majd ha megengedett ébresszük fel. Különböző paraméter megadással is implementálhatók. Tipikus probléma: Gyártó-Fogyasztó probléma vagy másképp korlátos tároló probléma. PL: Pék-pékség-Vásárló háromszög:
\begin{itemize}
\item A pék süti a kenyeret, amíg a pékség polcain van hely.
\item Vásárló tud venni, ha a pékség polcain van kenyér.
\item Ha tele van kenyérrel a pékség, akkor ,,a pék elmegy pihenni".
\item Ha üres a pékség, akkor a vásárló várakozik a kenyérre.
\end{itemize}
\begin{figure}[H]
\centering
\includegraphics[width=0.9\textwidth]{img/pekvasarlo.png}
\caption{Gyártó-fogyasztó probléma egy megvalósítása}
\end{figure}
Ennél a megvalósításnál probléma lehet, hogy A ,,hely" változó elérése nem korlátozott, így ez okozhat versenyhelyzetet.
\begin{itemize}
\item Vásárló látja, hogy a hely 0 és ekkor az ütemező átadja a vezérlést a péknek, aki süt egy kenyeret. Majd látja, hogy a hely 1, ébresztőt küld a vásárlónak. Ez elveszik, mert még a vásárló nem alszik.
\item Vásárló visszakapja az ütemezést, a helyet korábban beolvasta, az 0, megy aludni.
\item A pék az első után megsüti a maradék N-1 kenyeret és ő is aludni megy
\end{itemize}
Lehet ébresztő bittel javítani, de több folyamatnál a probléma nem változik.
\end{itemize}
\section{Szemaforok, osztott memória, üzenetküldés}
\subsection{Szemaforok}
E.W. Dijkstra(1965) javasolta ezen új változótípus bevezetését.
\begin{itemize}
\item Ez valójában egy egész változó.
\item A szemafor tilosat mutat, ha értéke 0. Ekkor a folyamat elalszik, megáll a tilos jelzés előtt.
\item Ha a szemafor >0, szabad a pálya, beléphetünk a kritikus szakaszra. Két művelet tartozik hozzá: ha beléptünk, csökkentjük szemafor értékét (down); ha kilépünk, növeljük a szemafor értékét (up). Ezeket Dijkstra P és V műveletnek nevezte.
\end{itemize}
Elemi művelet: a szemafor változó ellenőrzése, módosítása, esetleges elalvás oszthatatlan művelet, nem lehet megszakítani. Ez garantálja, hogy ne alakuljon ki versenyhelyzet. \\
Ha a szemafor tipikus vasutas helyzetet jelöl, azaz 1 vonat mehet át csak a jelzőn, a szemafor értéke ekkor 0 vagy 1 lehet. Ez a \textit{bináris szemafor}, vagy más néven MUTEX (Mutual Exclusion), és kölcsönös kizárásra használjuk. \\
Rendszerhívással, felhasználói szinten nem biztosítható a műveletek atomiságának megvalósítása. Művelet elején például letiltunk minden megszakítást. Ha több CPU van, akkor az ilyen szemafort védeni tudjuk a TSL utasítással. Viszont ezek a szemafor műveletek kernel szintű, rendszerhívás műveletek. A fejlesztői környezetek biztosítják.
\begin{figure}[H]
\centering
\includegraphics[width=0.45\textwidth]{img/gyarto_szemafor.png}
\includegraphics[width=0.45\textwidth]{img/fogyaszto_szemafor.png}
\caption{Gyártó-fogyasztó probléma megoldása szemaforokkal}
\end{figure}
\textit{Szabad}: kenyér polcot (boltot) védi, hogy egy időben csak egy folyamat tudja használni (vagy a pék, vagy a vásárló): Kölcsönös kizárás, Elemi műveletek (up, down). \\
\textit{Tele, üres szemafor}: szinkronizációs szemaforok, a gyártó álljon meg ha a tároló tele van, illetve a fogyasztó is várjon ha a tároló üres. \\ \\
Szemafornál két utasítás felcserélése is gondot okozhat. \\
\textit{Monitor}: magasabb szintű, nyelvű konstrukció. Eljárások, adatszerkezetek
lehetnek benne. Egy időben csak egy folyamat lehet aktív a monitoron belül.
\subsection{Osztott memória}
Elosztott közös memória: Hálózatban futó folyamatok közti memóriamegosztás. \\
Lehetőségünk van egy programon belüli különböző folyamatok, szálak által használt memóriaterületek közössé tételére, vagyis használhatjuk ugyanazt a memóriarészt, ,,időosztásos" üzemmódban. Különböző, egymással valamilyen módon ,,összekapcsolt" programrészekhez, folyamokhoz, szálakhoz ugyanazt a memóriaterület kapcsoljuk.
\subsection{Üzenetküldés}
A folyamatok jellemzően két primitívet használnak: \textit{Send(célfolyamat, üzenet)}, \textit{Receive(forrás, üzenet)}. Ezek rendszerhívások, nem nyelvi konstrukciók. \\
Ha küldő-fogadó nem azonos gépen van, szükséges ún. nyugtázó üzenet. Így ha küldő nem kapja meg a nyugtát, ismét elküldi az üzenetet. Ha a nyugta veszik el, a küldő újra küld. Ismételt üzenetek megkülönböztetése sorszám segítségével történik. \\
\textit{Összegzés}: Ideiglenes tároló helyek (levelesláda) létrehozása mindkét helyen. El lehet hagyni, ekkor ha send előtt van receive, a küldő blokkolódik, illetve fordítva. Ezt hívják randevú stratégiának. Például a Minix 3 is randevút használ, rögzített méretű üzenetekkel. \\
Adatcső kommunikáció hasonló, csak az adatcsőben nincsenek üzenethatárok, ott csak bájtsorozat van. Az üzenetküldés a párhuzamos rendszerek általános technikája. Pl. MPI \\
Klasszikus IPC (inter-process communication) problémák:
\begin{itemize}
\item Étkező filozófusok esete: körben felváltva 5 villa, tányér. 2 villa kell a spagetti
evéshez. A tányér melletti villákra pályáznak. Esznek-gondolkoznak. A legegyszerűbb megoldás (végtelen ciklusban gondolkodik, felveszi a két villáját egymás után, eszik, leteszi a villákat) pár hibát rejt magában, hogy pl. holtpont lehet, ha egyszerre megszerzik a bal villát és mind várnak a jobbra. Illetve ha leteszi a bal villát és újra próbálkozik, még az
se az igazi, hiszen folyamatosan felveszik a bal villát, majd leteszik. (Éhezés)
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{img/filo.png}
\caption{Étkező filozófusok, javított megoldás: 5 villa szemafor van, és egy maximum. Korlátozott erőforrás megszerzésre példa}
\end{figure}
\item Író-olvasó probléma: Adatbázist egyszerre többen olvashatják, de csak 1 folyamat írhatja.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{img/iro.png}
\includegraphics[width=0.3\textwidth]{img/olvaso.png}
\caption{Író-olvasó probléma megvalósítása}
\end{figure}
\end{itemize}
\section{Be- és kimeneti eszközök ütemezési lehetőségei, holtpontok}
\subsection{Be- és kimeneti eszközök ütemezési lehetőségei}
Input-Output eszközök:
\begin{itemize}
\item \textit{Blokkos eszközök}. Adott méretű blokkban tároljuk az információt. Blokkméret 512 byte - 32768 byte között. Egymástól függetlenül írhatók vagy olvashatók. Blokkonként címezhetőek. Ilyen eszköz: HDD, szalagos egység
\item \textbf{Karakteres eszközök}. Nem címezhető, csak jönnek-mennek sorban a
,,karakterek" (bájtok)
\item \textbf{Időzítő}: kivétel, nem blokkos és nem
karakteres
\end{itemize}
\textit{Megszakítások}: Általában az eszközöknek van állapotbitjük, jelezve, hogy az adat készen van. \\
Megszakítás használat (IRQ):
\begin{enumerate}
\item CPU tevékenység megszakítása
\item a kért sorszámú kiszolgáló végrehajtása
\item a kívánt adat beolvasása, a szorosan hozzátartozó tevékenység elvégzése
\item visszatérés a megszakítás előtti állapothoz.
\end{enumerate}
\textit{Közvetlen memória elérés}(DMA): Direct Memory Access, tartalmaz memória cím regisztert, átvitel irány jelzésre, mennyiségre regisztert. Ezeket szabályos in, out portokon lehet elérni. \\
Működés lépései:
\begin{enumerate}
\item CPU beállítja a DMA vezérlőt. (Regisztereket.)
\item A DMA a lemezvezérlőt kéri a megadott műveletre.
\item Miután a lemezvezérlő beolvasta a pufferébe, a rendszersínen keresztül a memóriába(ból) írja, olvassa az adatot.
\item Lemezvezérlő nyugtázza, hogy kész a kérés teljesítése.
\item DMA megszakítással jelzi, befejezte a műveletet.
\end{enumerate}
\subsection{Holtpontok (deadlock)}
Két vagy több folyamat egy erőforrás megszerzése során olyan helyzetbe kerül, hogy egymást blokkolják a további végrehajtásban. Pontos definíció: Folyamatokból álló halmaz holtpontban van, ha minden folyamat olyan eseményre vár, amit csak a halmaz egy másik folyamata okozhat. Nem csak az I/O eszközökhöz kötődik, pl párhuzamos rendszerek, adatbázisok, stb. \\
Coffman E.G. szerint 4 feltétel szükséges a holtpont kialakulásához:
\begin{enumerate}
\item \textit{Kölcsönös kizárás feltétel.} Minden erőforrás hozzá van rendelve 1 folyamathoz vagy szabad.
\item \textit{Birtoklás és várakozás feltétel.} Korábban kapott erőforrást birtokló folyamat kérhet újabbat.
\item \textit{Megszakíthatatlanság feltétel.} Nem lehet egy folyamattól elvenni az erőforrást, csak a folyamat engedheti el.
\item \textit{Ciklikus várakozás feltétel.} Két vagy több folyamatlánc kialakulása, amiben minden folyamat olyan erőforrásra vár, amit egy másik tart fogva.
\end{enumerate}
Irányított gráffal lehet modellezni a folyamatokat és erőforrásokat. Ha van kör, akkor az holtpontot jelent. \\ \\
Stratégiék holtpont esetén:
\begin{enumerate}
\item A probléma figyelmen kívül hagyása.
\begin{itemize}
\item Nem törődünk vele, nagy valószínűséggel Ő sem talál meg bennünket.
\item Ezt a módszert gyakran strucc algoritmus néven is ismerjük.
\item Vizsgálatok szerint a holtpont probléma és az egyéb (fordító, op.rendszer, hw, sw hiba) összeomlások aránya 1:250.
\item A Unix, Windows világ is ezt a „módszert” használja. De túl nagy az ár a várható haszonért cserébe.
\end{itemize}
\item Felismerés és helyreállítás.
\begin{itemize}
\item Engedjük a holtpontot megjelenni (kör), ezt észrevesszük és cselekszünk.
\item Folyamatosan figyeljük az erőforrás igényeket, elengedéseket.
\item Kezeljük az erőforrás gráfot folyamatosan. Ha kör keletkezik, akkor egy körbeli folyamatot megszüntetünk.
\item Másik módszer, nem foglalkozunk az erőforrás gráffal, ha x (fél óra?) ideje blokkolt egy folyamat, egyszerűen megszüntetjük. Ez nagygépes rendszereknél ismert módszer.
\end{itemize}
\item Megelőzés.
\begin{itemize}
\item A 4 szükséges feltétel egyikének meghiúsítása.
\item A Coffman féle 4 feltétel valamelyikére mindig él egy megszorítás.
\begin{itemize}
\item Kölcsönös kizárás. Ha egyetlen erőforrás soha nincs kizárólag 1 folyamathoz rendelve, akkor nincs holtpont se. De ez nehézkes, míg pl. nyomtató használatnál a
nyomtató démon megoldja a problémát, de ugyanitt a nyomtató puffer egy lemezterület, itt már kialakulhat holtpont.
\item Ha nem lehet olyan helyzet, hogy erőforrásokat birtokló folyamat további erőforrásra várjon, akkor szintén nincs holtpont. Ezt kétféle módon érhetjük el: Előre kell tudni egy folyamat összes erőforrásigényét vagy ha erőforrást akar egy folyamat, először engedje el az összes birtokoltat.
\item A Coffman féle harmadik feltétel a megszakíthatatlanság. Ennek elkerülése eléggé
nehéz. Pl nyomtatás közben nem szerencsés a nyomtatót másnak adni.
\item A negyedik feltétel, a ciklikus várakozás már könnyebben megszüntethető. Egyszerű mód: Minden folyamat egyszerre csak 1 erőforrást birtokolhat. Másik módszer: Sorszámozzuk az erőforrásokat, és a folyamatok csak ezen sorrendben kérhetik az erőforrásokat. Ez jó elkerülési mód, csak megfelelő sorrend nincs.
\end{itemize}
\end{itemize}
\item Dinamikus elkerülés.
\begin{itemize}
\item Erőforrások foglalása csak ,,óvatosan".
\item Bankár algoritmus (Dijkstra, 1965) Mint a kisvárosi bankár hitelezési gyakorlata. A bankár algoritmus minden kérés megjelenésekor azt nézi, hogy a kérés teljesítése biztonságos
állapothoz vezet-e. Ha igen, jóváhagyja, ha nem, a kérést elhalasztja. Eredetileg 1 erőforrásra tervezett. \\
A korábbi megelőzés is, meg ez az elkerülés is olyan információt kér (az erőforrás pontos igényeket, a folyamatok számát előre), ami nehezen megadható. (Folyamatok dinamikusan jönnek létre, erőforrások dinamikusan módosulnak.) Ezért a gyakorlatban kevesen alkalmazzák.
\item Biztonságos állapotok, olyan helyzetek, melyekből létezik olyan kezdődő állapotsorozat, melynek eredményeként mindegyik folyamat megkapja a kívánt erőforrásokat és befejeződik.
\end{itemize}
\end{enumerate}
\section{Memóriakezelés, virtuális memória fogalma}
\textit{Monoprogramozás}: A legegyszerűbb memóriakezelési módszer, időben csak egyetlen programot futtatunk. \\
\textit{Multiprogramozás}: multiprogramozás rögzített partíciókkal: Ekkor a rendelkezésre álló memóriát felosztják több, általában nem egyforma hosszúságú részre. Működéséhez minden partíciónak szüksége van egy úgynevezett várakozási sorra. Ha beérkezik egy igény, az operációs rendszer berakja annak a legkisebb méretű, partíciónak nevezett rész várakozási sorába, ahová még befér. Ilyenkor elvész a partíciónak az a része nem használható , amit az éppen futó processz nem használ. Ha az adott szeletben befejeződik a munka, a legrégebben várakozó megkapja a területet, és elkezd működni.
\subsection{Memóriakezelés}
A memóriakezelő az operációs rendszer része, gyakran a kernelben. Feladata: a memória nyilvántartása, melyek szabadok, foglaltak; memóriát foglaljon folyamatok számára; memóriát felszabadítson; csere vezérlése a RAM és a (Merev)Lemez között. \\
Kétféle algoritmus csoport:
\begin{itemize}
\item Szükséges a folyamatok mozgatása, cseréje a memória és a lemez között. (swap)
\item Nincs erre szükség, ha elegendő memória van.
\end{itemize}
\textit{Multiprogramozás rögzített memóriaszeletekkel}: Osszuk fel a memóriát n (nem egyenlő) szeletre. (Fix szeletek) Pl. rendszerindításnál ez megtehető. Egy közös várakozási sor van, minden szeletre külön-külön várakozási sor. Kötegelt rendszerek tipikus megoldása. \\
\textit{Relokáció}: Nem tudjuk hova kerül egy folyamat, így a memória hivatkozások nem fordíthatók fix értékekre. \\
\textit{Védelem}: Nem kívánatos, ha egy program a másik memóriáját ,,éri el". \\
Másik megoldás: Bázis+határregiszter használata, ezeket a programok nem módosíthatják, de minden címhivatkozásnál ellenőrzés: lassú. \\
\textit{Multiprogramozás memóriacsere használattal}: A korábbi kötegelt rendszerek tipikus megoldása a rögzített memória szeletek használata (IBM OS/MFT). Időosztásos, grafikus felületek esetén ez nem az igazi. Itt a teljes folyamatot mozgatjuk a memória-lemez között. Nincs rögzített memória partíció, mindegyik dinamikusan változik, ahogy az op. rendszer oda-vissza rakosgatja a folyamatokat. Dinamikus, jobb memória kihasználtságú lesz a rendszer, de a sok csere lyukakat hoz létre, ezért memória tömörítést kell végezni. (Sok esetben ez az időveszteség nem megengedhető.) \\
\textit{Dinamikus memóriafoglalás}: Általában nem ismert, hogy egy programnak mennyi dinamikus adatra, veremterületre van szüksége. A program ,,kód" része fix szeletet kap, míg az adat és verem része változót. Ezek tudnak nőni (csökkenni). Ha elfogy a memória, akkor a folyamat leáll, vár a
folytatásra, vagy kikerül a lemezre, hogy a többi még futó folyamat memóriához jusson. Ha van a memóriában már várakozó folyamat, az is cserére kerülhet. \\
A ,,dinamikus" memória nyilvántartása:
\begin{itemize}
\item Allokációs egység definiálása. Ennek mérete kérdés. Ha kicsi, akkor kevésbé lyukasodik a memória, viszont nagy a nyilvántartási ,,erőforrás (memória) igény". Ha nagy az egység, akkor túl sok lesz az egységen belüli maradékokból adódó memóriaveszteség.
\item A nyilvántartás megvalósítása: Bittérkép használattal vagy Láncolt lista használattal. Ha egy folyamat befejeződik, akkor szükség lehet az egymás melletti memória lyukak egyesítésére. Külön lista a lyukak és folyamatok listája.
\end{itemize}
\textit{Memóriafoglalási stratégiák}: Új vagy swap partícióról behozott folyamat számára, több memória elhelyezési algoritmus ismert (hasonlóak a lemezhez):
\begin{itemize}
\item First Fit (első helyre, ahova befér, leggyorsabb, legegyszerűbb)
\item Next Fit (nem az elejéről, hanem az előző befejezési pontjából indul a keresés, kevésbé hatékony, mint a first fit)
\item Best Fit (lassú, sok kis lyukat produkál)
\item Worst Fit (nem lesz sok kis lyuk, de nem hatékony)
\item Quick Fit (méretek szerinti lyuklista, a lyukak összevonása költséges)
\end{itemize}
\subsection{Virtuális memória fogalma}
\textit{Multiprogramozás virtuális memóriahasználattal}: Egy program használhat több memóriát,
mint a rendelkezésre álló fizikai méret. Az operációs rendszer csak a ,,szükséges részt" tartja a fizikai memóriában. Egy program a ,,virtuálismemória-térben" tartózkodik. Az elv akár a monoprogramozás környezetben is használható. \\
\textit{Memory Management Unit (MMU)}: A virtuális címtér ,,lapokra" van osztva. (Ezt laptáblának
nevezzük). Van jelenlét/hiány bit. Virtuális-fizikai lapokat összerendeljük. Ha az MMU látja, hogy egy lap nincs a memóriában, laphibát okoz, op.rendszer kitesz egy lapkeretet, majd behozza a szükséges lapot.
\section{Lapozás és szegmentálás}
\subsection{Lapozás}
\textit{Lapozástervezési szempontok}:
\begin{itemize}
\item Munkahalmaz modell
\begin{itemize}
\item A szükséges lapok betöltése. (Induláskor-előlapozás) A folyamat azon lapjainak fizikai memóriában tartása, melyeket használ. Ez az idővel változik.
\item Nyilván kell tartani a lapokat. Ha egy lapra az utolsó N időegységben nem hivatkoznak, laphiba esetén kidobjuk.
\item Óra algoritmus javítása: Vizsgáljuk meg, hogy a lap eleme a munkahalmaznak? (WSClock algoritmus)
\end{itemize}
\item Lokális, globális helyfoglalás
\begin{itemize}
\item Egy laphibánál ha az összes folyamatot (globális), vagy csak a folyamathoz tartozó (lokális) lapokat vizsgáljuk.
\item Globális algoritmus esetén minden folyamatot elláthatunk méretéhez megfelelő lappal, amit aztán dinamikusan változtatunk.
\item Page Fault Frequency (PFF) algoritmus, laphiba/másodperc arány, ha sok a laphiba, növeljük a folyamat memóriában lévő lapjainak a számát. Ha sok a folyamat, akár teljes folyamatot lemezre vihetünk.(teherelosztás)
\end{itemize}
\item Helyes lapméret meghatározása.
\begin{itemize}
\item Kicsi lapméret: A ,,lapveszteség" kicsi, viszont nagy laptábla kell a nyilvántartáshoz.
\item Nagy lapméret: Fordítva, ,,lapveszteség" nagy, kicsi laptábla.
\item Jellemzően: n x 512 bájt a lapméret, XP, Linuxok 4KB a lapméret. 8KB is használt (szerverek).
\end{itemize}
\item Közös memória
\begin{itemize}
\item Foglalhatunk memóriaterületet, amit több folyamat használhat.
\item Elosztott közös memória: Hálózatban futó folyamatok közti memóriamegosztás.
\end{itemize}
\end{itemize}
\subsection{Szegmentálás}
Virtuális memória: egy dimenziós címtér, 0-tól a maximum címig (4,8,16 GB, ...). \\
Több programnak van dinamikus területe, melyek növekedhetnek, bizonytalan mérettel. Hozzunk létre egymástól független címtereket, ezeket szegmensnek nevezzük. \\
Ebben a világban egy cím 2 részből áll: szegmens szám, és ezen belüli cím. (eltolás) \\
Szegmentálás lehetővé teszi osztott könyvtárak ,,egyszerű" megvalósítását. Logikailag szét lehet szedni a programot, adat szegmens, kód szegmens stb. Védelmi szintet is megadhatunk egy szegmensre. Lapok fix méretűek, a szegmensek nem. Szegmens töredezettség megjelenése. Ez töredezettség-összevonással javítható.
\section{Lapcserélési algoritmusok}
Ha nincs egy virtuális című lap a memóriában, akkor egy lapot ki kell dobni, berakni ezt az új lapot. A processzor gyorsító tár (cache) memória használatnál, vagy a böngésző helyi gyorsítótáránál is hasonló a helyzet.
Optimális lapcserélés: Címkézzünk meg minden lapot azzal a számmal, ahány CPU utasítás végrehajtódik, mielőtt hivatkozunk rá. Dobjuk ki azt a lapot, amelyikben legkisebb ez a szám. Egy baj van, nem lehet megvalósítani, viszont kétszeres futásnál tesztelési célokat szolgálhat.
\begin{itemize}
\item NRU (Not Recently Used) algoritmus:
\begin{itemize}
\item Használjuk a laptábla bejegyzés módosítás (Modify) és hivatkozás (Reference) bitjét. A hivatkozás bitet időnként (óramegszakításnál, kb. 0.02 sec) állítsuk 0-ra, ezzel azt jelezzük, hogy az ,,utóbbi időben" volt-e használva, hivatkozva.
\begin{itemize}
\item 0.osztály: nem hivatkozott, nem módosított
\item 1.osztály: nem hivatkozott, módosított. Ide akkor lehet kerülni, ha az óramegszakítás állítja 0-ra a hivatkozás bitet.
\item 2.osztály: hivatkozott, nem módosított
\item 3.osztály: hivatkozott, módosított
\end{itemize}
\item Válasszunk véletlenszerűen egy lapot a legkisebb nem üres osztályból. Egyszerű, nem igazán hatékony implementálni, megfelelő eredményt ad.
\end{itemize}
\item FIFO lapcserélés. Egyszerű FIFO, más területekről is ismert, ha szükség van egy új lapra akkor a legrégebbi lapot dobjuk ki. Listában az érkezés sorrendjében a lapok, egy lap a lista elejére érkezik, és a végéről távozik. Ennek javítása a Második Lehetőség lapcserélő algoritmus.
\item Második Lehetőség lapcserélő algoritmus. Olyan, mint a FIFO, csak ha a lista végén lévő lapnak a hivatkozás bitje 1, akkor kap egy második esélyt, a lista elejére kerül és a hivatkozás bitet 0-ra állítjuk.
\item Óra algoritmus: olyan, mint a második lehetőség, csak ne a lapokat mozgassuk körbe egy
listában, hanem rakjuk körbe őket és egy mutatóval körbe járunk. A mutató a legrégebbi lapra mutat. Laphibánál, ha a mutatott lap hivatkozás bitje 1, nullázzuk azt, és a következő lapot
vizsgáljuk. Ha vizsgált lap hivatkozás bitje 0, akkor kitesszük.
\item LRU (Least Recently Used) algoritmus: Legkevésbé (legrégebben) használt lap kidobása. HW vagy SW megvalósítás.
\begin{itemize}
\item HW1: Vegyünk egy számlálót, ami minden memória hivatkozásnál 1-gyel nő. Minden laptáblában tudjuk ezt a számlálót tárolni. Minden memóriahivatkozásnál ezt a számlálót beírjuk a lapba. Laphibánál megkeressük a legkisebb számlálóértékű lapot.
\item HW2: LRU bitmátrix használattal, n lap, n x n bitmátrix. Egy k. lapkeret hivatkozásnál állítsuk a mátrix k. sorát 1-re, míg a k. oszlopát 0-ra. Laphibánál a legkisebb értékű sor a legrégebbi.
\end{itemize}
\item NFU (Not Frequently Used) algoritmus:
\begin{itemize}
\item Minden laphoz tegyünk egy számlálót. Minden óramegszakításnál ehhez adjuk hozzá a lap
hivatkozás (R) bitjét.
\item Laphibánál a legkisebb számlálóértékű lapot dobjuk ki. (A leginkább nem használt lap)
\item Hiba, hogy az NFU nem felejt, egy program elején gyakran használt lapok megőrzik nagy értéküket.
\item Módosítsuk: Minden óramegszakításnál csináljunk jobbra egy biteltolást a számlálón, balról pedig hivatkozás bitet tegyük be (shr).(Öregítő algoritmus)
\item Ez jól közelíti az LRU algoritmust.
\item Ez a lapszámláló véges bitszámú (n), így n időegység előtti eseményeket biztosan nem tud megkülönböztetni.
\end{itemize}
\end{itemize}
\section{Lemezterület-szervezés, redundáns tömbök, fájlrendszerek szolgáltatásai és jellemző megvalósításaik}
\subsection{Lemezterület-szervezés}
\subsection{Redundáns tömbök}
RAID -- Redundant Array of Inexpensive Disks. Ha operációs rendszer nyújtja, gyakran Soft Raidnek nevezik. Ha intelligens (külső) vezérlőegység nyújtja, gyakran Hardver Raid-nek, vagy csak Raid diszkrendszernek nevezik. Bár nevében olcsó (Inexpensive), valójában inkább nem az. Több lemezt fog össze, és egy logikai egységként látja az operációs rendszer. Többféle ,,összefogási" elv létezik: RAID 0-6.
\begin{itemize}
\item RAID 0(striping)
\begin{itemize}
\item Ez az a Raid, ami nem is redundáns
\item Több lemez logikai összefűzésével egy meghajtót kapunk.
\item A lemezkapacitások összege adja az új meghajtó kapacitását.
\item A logikai meghajtó blokkjait szétrakja a lemezekre (striping), ezáltal egy fájl írása több lemezre kerül.
\item Gyorsabb I/O műveletek.
\item Nincs meghibásodás elleni védelem.
\end{itemize}
\item RAID 1(tükrözés)
\begin{itemize}
\item Két független lemezből készít egy logikai egységet.
\item Minden adatot párhuzamosan kiír mindkét lemezre.(Tükrözés, mirror)
\item Tárolókapacitás felére csökken.
\item Drága megoldás.
\item Jelentős hibatűrő képesség. Mindkét lemez egyszerre történő meghibásodása okoz adatvesztést.
\end{itemize}
\item RAID 1+0, RAID 0+1
\begin{itemize}
\item RAID 1+0: Tükrös diszkekből vonjunk össze többet.
\item RAID 0+1: RAID 0 összevont lemezcsoportból vegyünk kettőt.
\item A vezérlők gyakran nyújtják egyiket, másikat, mivel így is, úgy is tükrözés van, azaz drága, így ritkán használt.
\end{itemize}
\item RAID 2: Adatbitek mellett hibajavító biteket is tartalmaz. (ECC: Error Correction Code) Pl. 4 diszkhez 3 javító diszk
\item RAID 3: Elég egy plusz ,,paritásdiszk", n+1 diszk, $\sum{n}$ a kapacitás
\item RAID 4: RAID 0 kiegészítése paritásdiszkkel.
\item Ma ezen megoldások (RAID 2,3,4) nem gyakran használatosak.
\item RAID 5
\begin{itemize}
\item Nincs paritásdiszk, ez el van osztva a tömb összes elemére. (stripe set)
\item Adatok is elosztva kerülnek tárolásra.
\item Intenzív CPU igény (vezérlő CPU!!!)
\item Redundáns tárolás, 1 lemez meghibásodása nem okoz adatvesztést. A paritásbitből meg a többiből az egy eltűnt kiszámítható. 2 lemez egyidejű meghibásodása már okoz adatvesztést.
\item N lemez RAID 5 tömbben (N>=3), n-1 lemez méretű logikai meghajtót ad.
\end{itemize}
\item RAID 6
\begin{itemize}
\item A RAID 5 paritásblokkhoz, hibajavító kód kerül tárolásra.(+1 diszk)
\item Még intenzívebb CPU igény.
\item Két diszk egyidejű kiesése sem okoz adatvesztést.
\item Relatív drága
\item N diszk RAID 6-os tömbjének kapacitása, N-2 diszk kapacitással azonos.
\item Elvileg általánosítható a módszer (3 diszk kiesése)
\end{itemize}
\end{itemize}
Ma leggyakrabban a RAID 1,5 verziókat használják. A RAID 6 vezérlők az utóbbi 1-2 évben jelentek meg. Bár olcsó diszkekről szól a RAID, de valójában ezek nem mindig olcsók. RAID 6-nl már 2 lemez kiesik, így ez még inkább drága. \\
Hot-Swap(forró csere) RAID vezérlő: működés közben a meghibásodott lemezt egyszerűen kicseréljük.
\subsection{Fájlrendszerek szolgáltatásai}
\textit{Fájl}: adatok egy logikai csoportja, névvel egyéb paraméterekkel ellátva. A fájl az információtárolás egysége, névvel hivatkozunk rá. Jellemzően egy lemezen helyezkedik el, de általánosan az adathalmaz, adatfolyam akár képernyőhöz, billentyűzethez is köthető. \\
A lemezen általában 3 féle fájl, állomány található:
\begin{itemize}
\item Rendes felhasználói állomány.
\item Ideiglenes állomány
\item Adminisztratív állomány. Ez a működéshez szükséges, általában rejtett.
\end{itemize}
\textit{Könyvtár}: fájlok (könyvtárak) logikai csoportosítása. \\
\textit{Fájlrendszer}: módszer, a fizikai lemezünkön, kötetünkön a fájlok és könyvtárak elhelyezés rendszerének kialakítására. \\
Fájlok elhelyezése: A partíció elején, az ún. Szuperblokk (pl. FAT esetén a 0. blokk ) leírja a rendszer jellemzőit. Általában következik a helynyilvántartás (FAT, láncolt listás nyilvántartás). Ezután a könyvtárszerkezet (inode), a könyvtár bejegyzésekkel, fájl adatokkal. (FAT16-nál a könyvtár előbb van, majd utána a fájl adatok.) \\
Elhelyezési stratégiák:
\begin{itemize}
\item Folytonos tárkiosztás: First Fit, Best Fit, Worst Fit (olyan memória szakaszba tesszük, hogy a lehető legnagyobb rész maradjon szabadon). Veszteséges lemezkihasználás.
\item Láncolt elhelyezkedés: Nincs veszteség (csak a blokkméretből adódóan). Fájl adatok (blokkokra bontva) láncolt lista tábla. Az n. blokk olvasása lassú lesz. Szabad-foglalt szektorok: File Allocation Table,FAT. Ez nagy lehet, a FAT-nak a memóriában kell lenni fájl műveletnél.
\item Indextáblás elhelyezés: Katalógus tartalmazza a fájlhoz tartozó kis tábla (inode) címét. Egy inode címből elérhető a fájl.
\end{itemize}
Fájlrendszer típusok:
\begin{itemize}
\item Merevlemezen alkalmazott fájlrendszer: FAT, NTFS, EXT2FS, XFS, stb
\item Szalagos rendszereken (elsősorban backup) alkalmazott fájlrendszer: Tartalomjegyzék, majd a tartalom szekvenciálisan
\item CD, DVD, Magneto-opto Disc fájlrendszer: CDFS, UDF (Universal Disc Format), kompatibilitás
\item RAM lemezek (ma már kevésbé használtak)
\item FLASH memória meghajtó (FAT32)
\item Hálózati meghajtó: NFS
\item Egyéb pszeudó fájlrendszerek: Zip, tar.gz, ISO
\end{itemize}
\textit{Naplózott fájlrendszerek}: A fájlrendszer sérülés, áramszünet stb. esetén inkonzisztens állapotba kerülhet. Gyakran nevezik: LFS-nek (Log-structured File System) vagy JFS-nek(Journaled). Adatbázis-kezelők mintájára: művelet + log naplózódik. Tranzakciós alapra épül. Leállás, hiba esetén a log alapján helyre lehet állítani. Célszerűen a log másik lemez (másik partíció). Nagyobb erőforrás igényű, de nagyobb a megbízhatóság. \\
A mai operációs rendszerek ,,rengeteg" típust támogatnak, pl: Linux 2.6 kernel több mint 50-et.
A fájlrendszert csatolni többféleképpen is lehet:
\begin{itemize}
\item Mount, eredményeképpen a fájlrendszer állományok elérhetők lesznek.
\item Automatikus csatolás (pl. USB drive)
\item Kézi csatolás (Linux, mount parancs)
\end{itemize}
Külön névtérbeli elérhetőség a Windowsnál az A, B, C stb lemezek. Egységes névtér a UNIX-nál van.
\subsection{Fájlrendszerek szolgáltatásainak jellemző megvalósításai}
\begin{itemize}
\item FAT
\begin{itemize}
\item File Allocation Table. Talán a legrégebbi, ma is élő fájlrendszer.
\item A FAT tábla a lemez foglaltsági térképe, annyi eleme van, ahány blokk a lemezen. Pl: Fat12, FDD, Cluster méret 12 bites. Ha értéke 0, szabad, ha nem, foglalt. Biztonság kedvéért 2 tábla van.
\item Láncolt elhelyezés. A katalógusban a file adatok (név stb) mellett csak az első fájl blokk sorszáma van megadva. A FAT blokk azonosító mutatja a következő blokk címét. Ha nincs tovább, FFF az érték.
\item Rögzített bejegyzés méret, 32 bájt (max. 8.3 név)
\item System, Hidden, Archive, Read only, könyvtár attribútumok
\item A fájl utolsó módosítás ideje is tárolva van.
\item \textit{FAT16}, 16 bites cluster leíró, 4 bájt (2x2) írja le a fájl kezdőblokkját. Max. 4 GB partíciós méret (64kb blokk méretnél), jellemzően 2 GB. Fájlméret maximum is a 4 (2) GB. Külön könyvtári terület (FDD-nez a 0. sáv). FDD-n 512 könyvtári bejegyzés. HDD-n 32736 könyvtári bejegyzés (16 bit előjelesen)
\item \textit{FAT32} (1996-tól elérhető): 28 bites clusterleíró, 2 TB partíciós méret (alap szektor mérettel), 32 MB-ig 1 blokk = 1 szektor(512bájt). 64 MB: 1 blokk=1KB (2 szektor), 128MB: 1 blokk=2KB. 1 blokk max. 64 KB lehet.
\item Támogatták már a hosszú fájl neveket is. Többszörös 8.3 részre fenntartott bejegyzésekkel.
\item Töredezettségmentesítés szükséges.
\end{itemize}
\item NTFS
\begin{itemize}
\item New Technology File System
\item FAT-NTFS hatékonysági határ: kb. 400 MB.
\item 255 karakteres fájl név, 8+3 másodlagos név
\item Kifinomult biztonsági beállítások
\item Ahogy a FAT esetén, itt is szükséges a töredezettségmentesítés.
\item Titkosított fájlrendszer támogatása, naplózás
\item POSIX támogatás. Hardlink (fsutil parancs), időbélyegek, kis-nagybetűk különböznek
\item Tömörített fájl, mappa, felhasználói kvóta kezelés
\item Az NTFS csak klasztereket tart nyilván, szektort (512bájt) nem
\begin{figure}[H]
\centering
\includegraphics[width=0.9\textwidth]{img/ntfs.png}
\caption{NTFS partíció. A Master File Table és a File System Data egy-egy táblázat}
\end{figure}
\item MFT: NTFS partíció az MFT (Master File Table) táblázattal kezdődik. 16 attribútum ad egy fájl bejegyzést. Minden attribútum max. 1kb. Ha ez nem elég, akkor egy attribútum mutat a folytatásra. Az adat is egyfajta attribútum, így egy bejegyzés több adatsort tartalmazhat. (PL: Betekintő kép) Elvi fájlméret $2^64$ bájt lehet. Ha a fájl < 1kb, belefér az attribútumba, közvetlen fájl. Nincs fájlméret maximum.
\end{itemize}
\begin{figure}[H]
\centering
\includegraphics[width=0.6\textwidth]{img/ntfs2.png}
\caption{Az NTFS partíció felépítése}
\end{figure}
\item ext, az ext2 és az ext3
\begin{itemize}
\item Az „ext” kifejezés a fájlrendszerek neveiben az extended (magyarul kiterjesztett) kifejezést takarja. Az extended fájlrendszer volt az első kifejezetten a UNIX-szerű GNU/LINUX operációs rendszerekhez készített fájlrendszer, amely örökölte az UFS (UNIX File System) fájlrendszer metaadat-szerkezetét, és arra készült, hogy a Minix operációs rendszer fájlrendszerének a hibáit kiküszöbölje. A hibák kiküszöbölése többek között a Minix operációs rendszer fájlrendszer-határainak kiterjesztése.
\item Az ext2 fájlrendszer, amely a GNU/LINUX operációs rendszereken kívül más rendszereken is megjelent, több Linux disztribúció alapértelmezett fájlrendszere volt, amíg az utódja, az „ext3” fájlrendszer (third extended filesystem harmadik kiterjesztett fájlrendszer) el nem készült.
\item Az ext3 fájlrendszer (third extended filesystem harmadik kiterjesztett fájlrendszer) az ext2 fájlrendszer utódja, amely már az ext2 fájlrendszerhez képest naplózást is tartalmaz. Ez a naplózás elsősorban a biztonságot növeli, és lehetővé teszi azt, hogy szabálytalan leállás bekövetkezése után ne kelljen az egész fájlrendszert újra ellenőrizni.
\end{itemize}
\item ReiserFS: A ReiserFS fájlrendszer lehetővé teszi egy blokkos eszközön (block device) változó méretű fájlok tárolását és könyvtárstruktúrába rendezését. A kezdeti UNIX és UNIX-szerű operációs rendszerek (így pl. a GNU/LINUX operációs rendszer is) csak egyfajta fájlrendszert támogattak, a saját formátumukat. A modern operációs rendszerek viszont többféle fájlrendszert is támogatnak, és vannak olyan fájlrendszerek is, amelyeket több operációs rendszer is támogat. A ReiserFS fájlrendszer egyáltalán nem ilyen. A ReiserFS fájlrendszer egy olyan fájlrendszer, amely csak és kizárólag a GNU/LINUX operációs rendszer alatt használható jelenleg korlátozás nélkül.
\end{itemize}
\end{document}

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

View File

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

View File

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

View File

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Some files were not shown because too many files have changed in this diff Show More