{ "cells": [ { "attachments": {}, "cell_type": "markdown", "id": "1de4614f", "metadata": {}, "source": [ "# Język — różne perspektywy\n", "\n", "## Słowo wstępne\n", "\n", "W matematyce istnieją dwa spojrzenia na rzeczywistość: ciągłe i\n", "dyskretne.\n", "\n", "Otaczająca nas rzeczywistość fizyczna jest z natury ciągła (przynajmniej\n", "jeśli nie operujemy w mikroskali), lecz język jest dyskretnym wyłomem w\n", "ciągłej rzeczywistości.\n", "\n", "## Lingwistyka matematyczna\n", "\n", "Przypomnijmy sobie definicję języka przyjętą w lingwistyce\n", "matematycznej, w kontekście na przykład teorii.\n", "\n", "****Alfabetem**** nazywamy skończony zbiór symboli.\n", "\n", "****Łańcuchem**** nad alfabetem $\\Sigma$ nazywamy dowolny, skończony,\n", "ciąg złożony z symboli z $\\Sigma$\n", "\n", "****Językiem**** nazywamy dowolny, skończony bądź nieskończony, zbiór\n", "łańcuchów.\n", "\n", "W tym formalnym ujęciu językami są na przykład następujące zbiory:\n", "\n", "- ${\\mathit{poniedziałek},\\mathit{wtorek},\\mathit{środa},\\mathit{czwartek},\\mathit{piątek},\\mathit{sobota},\\mathit{niedziela}$\n", "- ${\\mathit{ab},\\mathit{abb},\\mathit{abbb},\\mathit{abbbb},\\ldots}$\n", "\n", "To podejście, z jednej strony oczywiście nie do końca się potocznym\n", "rozumieniem słowa *język*, z drugiej kojarzy nam się z takimi\n", "narzędziami informatyki jak wyrażenia regularne, automaty skończenie\n", "stanowe czy gramatyki języków programowania.\n", "\n", "``` ipython\n", "import regex as re\n", "rx = re.compile(r'ab+')\n", "\n", "rx.search('żabbba').group(0)\n", "```\n", "\n", "abbb\n", "\n", "``` ipython\n", "import rstr\n", "\n", "rstr.xeger(r'ab+')\n", "```\n", "\n", "abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n", "\n", "## Ujęcie probabilistyczne\n", "\n", "Na tym wykładzie przyjmiemy inną perspektywą, częściowo ciągłą, opartą\n", "na probabilistyce. Język będziemy definiować poprzez ****rozkład\n", "prawdopodobieństwa****: sensownym wypowiedziom czy tekstom będziemy\n", "przypisywać stosunkowe wysokie prawdopodobieństwo, „ułomnym” tekstom —\n", "niższe (być może zerowe).\n", "\n", "Na ogół nie mamy jednak do czynienia z językiem jako takim tylko z jego\n", "przybliżeniami, ****modelami**** (model może być lepszy lub gorszy, ale\n", "przynajmniej powinien być użyteczny…). Formalnie $M$ nazywamy modelem\n", "języka (nad skończonym alfabetem $Sigma$), jeśli dyskretny określa\n", "rozkład prawdopodobieństwa $P_M$:\n", "\n", "$$P_M \\colon \\Sigma^{*} \\rightarrow [0,1].$$\n", "\n", "Rzecz jasna, skoro mamy do czynienia z rozkładem prawdopodobieństwa, to:\n", "\n", "$$\\Sum_{\\alpha \\in \\Sigma^{*}} P_M(\\alpha) = 1$$\n", "\n", "Jeśli $M$ ma być modelem języka polskiego, oczekiwalibyśmy, że dla\n", "napisów:\n", "\n", "- $z_1$ — *W tym stanie rzeczy pan Ignacy coraz częściej myślał o\n", " Wokulskim.*\n", "- $z_2$ — *Po wypełniony zbiornik pełny i należne kwotę, usłyszała w\n", " attendant*\n", "- $z_3$ — *xxxxyźźźźźit backspace hoooooooooop x y z*\n", "\n", "zachodzić będzie:\n", "\n", "$$ P_M(z_1) > P_M(z_2) > P_M(z_3). $$\n", "\n", "Moglibyśmy sprowadzić tę definicję języka do tej „dyskretnej”, tzn.\n", "moglibyśmy przyjąć, że łańcuch $\\alpha$ należy do języka wyznaczonego\n", "przez model $M$, jeśli $P_M(\\alpha) > 0$.\n", "\n", "****Pytanie**** Czy moglibyśmy w ten sposób język nieskończony? Czy może\n", "istnieć dyskretny rozkład prawdopodobieństwa dla nieskończonego zbioru?\n", "\n", "## Co jest symbolem?\n", "\n", "Model języka daje rozkład prawdopodobieństwa nad zbiorem łańcuchów\n", "opartym na skończonym alfabecie, tj. zbiorze symboli. W praktyce alfabet\n", "nie musi być zgodny z potocznym czy językoznawczym rozumieniem tego\n", "słowa. To znaczy alfabet może być zbiorem znaków (liter), ale modelować\n", "język możemy też przyjmując inny typ symboli: sylaby, morfemy (cząstki\n", "wyrazów) czy po prostu całe wyrazy.\n", "\n", "Powinniśmy przy tym pamiętać, że, koniec końców, w pamięci komputera\n", "wszelkiego rodzaju łańcuchy są zapisywane jako ciągi zer i jedynek —\n", "bitów. Omówmy pokrótce techniczną stronę modelowania języka.\n", "\n", "# Kodowanie znaków\n", "\n", "## Cóż może być prostszego od pliku tekstowego?\n", "\n", "``` example\n", "Ala ma kota.\n", "```\n", "\n", "Komputer nic nie wie o literach.\n", "\n", "… w rzeczywistości operuje tylko na liczbach …\n", "\n", "… czy raczej na zerach i jedynkach …\n", "\n", "… a tak naprawdę na ciągłym sygnale elektrycznym …\n", "\n", "![](attachment:./digitalsignal.jpg)\n", "\n", "… zera i jedynki są w naszej głowie …\n", "\n", "… co jest dziwne, *naprawdę* dziwne …\n", "\n", "… ale nikt normalny się tym nie przejmuje.\n", "\n", "## Jak zakodować literę?\n", "\n", "Zakodowanie pikseli składających się na kształtu (****glyfu****) litery\n", "A *oczywiście* nie jest dobrym pomysłem.\n", "\n", "![](attachment:./raster.png)\n", "\n", "Nie, potrzebujemy *arbitralnego* kodowania dla wszystkich możliwych\n", "kształtów litery A (*w naszych głowach*): A, $\\mathcal{A}$,\n", "$\\mathbb{A}$, $\\mathfrak{A}$ powinny otrzymać ten sam kod, powiedzmy 65\n", "(binarnie: 1000001).\n", "\n", "## ASCII\n", "\n", "ASCII to 7-bitowy (****nie**** 8-bitowy!) system kodowania znaków.\n", "\n", "``` ipython\n", "for code in range(0, 128):\n", " print(f'{code}: {chr(code)}')\n", "```\n", "\n", "0: \u0000 1: \u0001 2: \u0002 3: \u0003 4: \u0004 5: \u0005 6: \u0006 7: \u0007 8: \b 9: 10:\n", "\n", "11: \u000b", " 12: \f", " 13: 14: \u000e 15: \u000f 16: \u0010 17: \u0011 18: \u0012 19: \u0013 20: \u0014 21: \u0015 22: \u0016\n", "23: \u0017 24: \u0018 25: \u0019 26: \u001a 27: \u001b 28: \u001c", " 29: \u001d", " 30: \u001e", " 31: \u001f 32: 33: ! 34: \"\n", "35: \\# 36: \\$ 37: % 38: & 39: ' 40: ( 41: ) 42: \\* 43: + 44: , 45: - 46:\n", ". 47: / 48: 0 49: 1 50: 2 51: 3 52: 4 53: 5 54: 6 55: 7 56: 8 57: 9 58:\n", ": 59: ; 60: \\< 61: = 62: \\> 63: ? 64: @ 65: A 66: B 67: C 68: D 69: E\n", "70: F 71: G 72: H 73: I 74: J 75: K 76: L 77: M 78: N 79: O 80: P 81: Q\n", "82: R 83: S 84: T 85: U 86: V 87: W 88: X 89: Y 90: Z 91: \\[ 92: \\\\ 93:\n", "\\] 94: ^ 95: \\_ 96: \\` 97: a 98: b 99: c 100: d 101: e 102: f 103: g\n", "104: h 105: i 106: j 107: k 108: l 109: m 110: n 111: o 112: p 113: q\n", "114: r 115: s 116: t 117: u 118: v 119: w 120: x 121: y 122: z 123: {\n", "124: \\| 125: } 126: \\~ 127: \n", "\n", "## Jak zejść na poziom bitów?\n", "\n", "### Linux — wiersz poleceń\n", "\n", "Linux command line:\n", "\n", "``` example\n", "$ echo 'Ala ma kota' > file.txt\n", "$ hexdump -C file.txt\n", "00000000 41 6c 61 20 6d 61 20 6b 6f 74 61 0a |Ala ma kota.|\n", "0000000c\n", "```\n", "\n", "### Edytor tekstu (Emacs)\n", "\n", "![](attachment:./hexl-mode.png)\n", "\n", "### Uwaga!\n", "\n", "- kiedy dzieje się coś dziwnego, sprawdź co tak *naprawdę* jest w\n", " pliku\n", "- ASCII jest 7-bitowym kodowaniem (128 znaków)\n", " - choć zazwyczaj uzupełnionym (ang. *padded*) do 8 bitów\n", " - nie mów plik *plik ASCII*, kiedy masz na myśli *prosty/czysty\n", " plik tekstowy* (ang. *plain text file*)\n", "\n", "## Higiena plików tekstowych\n", "\n", "### Piekło końca wiersza\n", "\n", "![](attachment:./dante.jpg)\n", "\n", "Więcej na\n", "\n", "\n", "### Dobre rady\n", "\n", "- żadnych niepotrzebnych spacji na końcu wiersza\n", "\n", "- żadnych niepotrzebnych pustych wierszy na końcu pliku\n", "\n", "- … ale ostatni wiersz powinien zakończyć się znakiem końca wiersza\n", "\n", "- nie używać znaków tabulacji (zamiast tego 4 spacje)\n", "\n", " - wyjątek: pliki TSV\n", " - wyjątek: pliki Makefile\n", "\n", "- uwaga na niestandardowe spacje i dziwne znaki o zerowej długości\n", "\n", "## Unikod\n", "\n", "ASCII obejmuje 128 znaków: litery alfabetu łacińskiego (właściwie\n", "angielskiego), cyfry, znaki interpunkcyjne, znaki specjalne itd.\n", "\n", "Co z pozostałymi znakami? Polskimi ogonkami, czeskimi haczykami,\n", "francuskimi akcentami, cyrylicą, koreańskim alfabetem, chińskimi\n", "znakami, rongorongo?\n", "\n", "워싱턴, 부산, 삼성\n", "\n", "Rozwiązaniem jest Unikod (ang. *Unicode*) system, który przypisuje\n", "znakom używanym przez ludzkość liczby (kody, ang. *code points*).\n", "\n", "| Znak | Kod ASCII | Kod Unikodowy |\n", "|-------|-----------|---------------|\n", "| 9 | 57 | 57 |\n", "| a | 97 | 97 |\n", "| ą | \\- | 261 |\n", "| ł | \\- | 322 |\n", "| \\$ℵ\\$ | \\- | 1488 |\n", "| ặ | \\- | 7861 |\n", "| ☣ | \\- | 9763 |\n", "| 😇 | \\- | 128519 |\n", "\n", "## UTF-8\n", "\n", "Kody znaków są pojęciem abstrakcyjnym. Potrzebujemy konkretnego\n", "****kodowania**** by zamienić kody w sekwencję bajtów.\n", "Najpopularniejszym kodowaniem jest UTF-8.\n", "\n", "W kodowaniu UTF-8 znaki zapisywane za pomocą 1, 2, 3 lub 4 bajtów.\n", "\n", "| Znak | Kod Unikodowy |\n", "|-------|---------------|\n", "| 9 | 57 |\n", "| a | 97 |\n", "| ą | 261 |\n", "| ł | 322 |\n", "| \\$ℵ\\$ | 1488 |\n", "| ặ | 7861 |\n", "| ☣ | 9763 |\n", "| 😇 | 128519 |" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.2" } }, "nbformat": 4, "nbformat_minor": 5 }