Add exam
This commit is contained in:
parent
dcdd3e78e5
commit
b06a6e58f9
|
@ -0,0 +1,277 @@
|
||||||
|
{
|
||||||
|
"Exc": {
|
||||||
|
"scope": "latex",
|
||||||
|
"prefix": ["\\exc"],
|
||||||
|
"body":
|
||||||
|
[
|
||||||
|
"\\exc{}",
|
||||||
|
"\\begin{subexcs}",
|
||||||
|
" \\subexc{}",
|
||||||
|
" $0",
|
||||||
|
"\\end{subexcs}"
|
||||||
|
],
|
||||||
|
"description": "Adds new exc with subexcs",
|
||||||
|
},
|
||||||
|
|
||||||
|
"Subexc": {
|
||||||
|
"scope": "latex",
|
||||||
|
"prefix": ["\\subexc"],
|
||||||
|
"body":
|
||||||
|
[
|
||||||
|
"\\subexc{}",
|
||||||
|
"\\begin{ssubexcs}",
|
||||||
|
" \\ssubexc{}",
|
||||||
|
" $0",
|
||||||
|
"\\end{ssubexcs}"
|
||||||
|
],
|
||||||
|
"description": "Adds new subexc with ssubexcs",
|
||||||
|
},
|
||||||
|
|
||||||
|
"Diagram": {
|
||||||
|
"scope": "latex",
|
||||||
|
"prefix": ["dia"],
|
||||||
|
"body": "\\includeDiagram[caption={}, width=1\\linewidth]{graphics/$0.tex}",
|
||||||
|
"description": "Include a diagram",
|
||||||
|
},
|
||||||
|
|
||||||
|
"Graph Table": {
|
||||||
|
"scope": "latex",
|
||||||
|
"prefix": ["graph-table"],
|
||||||
|
"body":
|
||||||
|
[
|
||||||
|
"\\begin{figure}[H]",
|
||||||
|
" \\center",
|
||||||
|
" \\begin{tabular}{c|cc}",
|
||||||
|
" $A$ & \\multicolumn{2}{c}{$v$} \\\\",
|
||||||
|
" \\hline",
|
||||||
|
" & $a$ & $b$ \\\\",
|
||||||
|
" \\hline",
|
||||||
|
" $s_0$ & $s_$ & $s_$ \\\\",
|
||||||
|
" $s_1$ & $s_$ & $s_$ \\\\",
|
||||||
|
" $s_2$ & $s_$ & $s_$ \\\\",
|
||||||
|
" \\end{tabular}",
|
||||||
|
"\\end{figure}"
|
||||||
|
],
|
||||||
|
"description": "Adds graph-table",
|
||||||
|
},
|
||||||
|
|
||||||
|
"Graph Table Double": {
|
||||||
|
"scope": "latex",
|
||||||
|
"prefix": ["graph-dtable"],
|
||||||
|
"body":
|
||||||
|
[
|
||||||
|
"\\begin{figure}[H]",
|
||||||
|
" \\center",
|
||||||
|
" \\begin{tabular}{c|cc}",
|
||||||
|
" $A$ & \\multicolumn{2}{c}{$v$} \\\\",
|
||||||
|
" \\hline",
|
||||||
|
" & $a$ & $b$ \\\\",
|
||||||
|
" \\hline",
|
||||||
|
" $s_0$ & $s_$ & $s_$ \\\\",
|
||||||
|
" $s_1$ & $s_$ & $s_$ \\\\",
|
||||||
|
" $s_2$ & $s_$ & $s_$ \\\\",
|
||||||
|
" \\end{tabular}",
|
||||||
|
"\\end{figure}"
|
||||||
|
],
|
||||||
|
"description": "Adds graph-table",
|
||||||
|
},
|
||||||
|
|
||||||
|
"Graph Table Line": {
|
||||||
|
"scope": "latex",
|
||||||
|
"prefix": ["gtl"],
|
||||||
|
"body": " $s_$ & $s_$ & $s_$ \\\\",
|
||||||
|
"description": "Adds line inside graph-table",
|
||||||
|
},
|
||||||
|
|
||||||
|
"Graph Table Double Line": {
|
||||||
|
"scope": "latex",
|
||||||
|
"prefix": ["gtdl"],
|
||||||
|
"body": " $s_$ & $s_$ & $s_$ & $s_$ & $s_$ \\\\",
|
||||||
|
"description": "Adds line inside a double graph-table",
|
||||||
|
},
|
||||||
|
|
||||||
|
"Induction Proof": {
|
||||||
|
"scope": "latex",
|
||||||
|
"prefix": ["prove-induction"],
|
||||||
|
"body": [
|
||||||
|
"Base case:",
|
||||||
|
"",
|
||||||
|
"\\begin{align*}",
|
||||||
|
"",
|
||||||
|
"\\end{align*}",
|
||||||
|
"",
|
||||||
|
"Assume that",
|
||||||
|
"",
|
||||||
|
"\\[ $1 \\]",
|
||||||
|
"",
|
||||||
|
"Then",
|
||||||
|
"",
|
||||||
|
"\begin{align*}",
|
||||||
|
" &= $1 + \\\\",
|
||||||
|
" &=",
|
||||||
|
"\\end{align*}",
|
||||||
|
"",
|
||||||
|
"\\qed"
|
||||||
|
],
|
||||||
|
"description": "Template for induction proof",
|
||||||
|
},
|
||||||
|
|
||||||
|
"Injective Proof": {
|
||||||
|
"scope": "latex",
|
||||||
|
"prefix": ["prove-injective"],
|
||||||
|
"body": [
|
||||||
|
"In order for $f(x)$ to be injective, it has to hold that",
|
||||||
|
"",
|
||||||
|
"\\[ f(a) = f(b) \\Rightarrow a = b \\]",
|
||||||
|
"",
|
||||||
|
"\\begin{align*}",
|
||||||
|
" f(a) &= f(b) \\\\",
|
||||||
|
" $0",
|
||||||
|
"\\end{align*}",
|
||||||
|
"",
|
||||||
|
"Hence $f(x)$ is injective."
|
||||||
|
],
|
||||||
|
"description": "Template for injective proof",
|
||||||
|
},
|
||||||
|
|
||||||
|
"Surjective Proof": {
|
||||||
|
"scope": "latex",
|
||||||
|
"prefix": ["prove-surjective"],
|
||||||
|
"body": [
|
||||||
|
"In order for $f(x)$ to be surjective, it has to hold that",
|
||||||
|
"",
|
||||||
|
"\\[ \\forall x \\in SET \\exists y \\in SET [f(x) = y] \\]",
|
||||||
|
"",
|
||||||
|
"\\begin{align*}",
|
||||||
|
" y &= $1 \\\\",
|
||||||
|
"",
|
||||||
|
" x &= \\\\" ,
|
||||||
|
"\\end{align*}",
|
||||||
|
"",
|
||||||
|
"$ $ makes up all the elements in SET",
|
||||||
|
"",
|
||||||
|
"\\begin{align*}",
|
||||||
|
" f(y) &= \\\\",
|
||||||
|
"",
|
||||||
|
"\\end{align*}",
|
||||||
|
"",
|
||||||
|
"Hence $f(x)$ is surjective"
|
||||||
|
],
|
||||||
|
"description": "Template for surjective proof",
|
||||||
|
},
|
||||||
|
|
||||||
|
"Bijective Function Proof": {
|
||||||
|
"scope": "latex",
|
||||||
|
"prefix": ["prove-bijective"],
|
||||||
|
"body": [
|
||||||
|
"\\textbf{Injective:}",
|
||||||
|
"",
|
||||||
|
"In order for $f(x)$ to be injective, it has to hold that",
|
||||||
|
"",
|
||||||
|
"\\[ f(a) = f(b) \\Rightarrow a = b \\]",
|
||||||
|
"",
|
||||||
|
"\\begin{align*}",
|
||||||
|
" f(a) &= f(b) \\\\",
|
||||||
|
" $0",
|
||||||
|
"\\end{align*}",
|
||||||
|
"",
|
||||||
|
"Hence $f(x)$ is injective.",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"\\textbf{Surjective:}",
|
||||||
|
"",
|
||||||
|
"In order for $f(x)$ to be surjective, it has to hold that",
|
||||||
|
"",
|
||||||
|
"\\[ \\forall x \\in SET \\exists y \\in SET [f(x) = y] \\]",
|
||||||
|
"",
|
||||||
|
"\\begin{align*}",
|
||||||
|
" y &= $1 \\\\",
|
||||||
|
"",
|
||||||
|
" x &= \\\\" ,
|
||||||
|
"\\end{align*}",
|
||||||
|
"",
|
||||||
|
"$ $ makes up all the elements in SET",
|
||||||
|
"",
|
||||||
|
"\\begin{align*}",
|
||||||
|
" f(y) &= \\\\",
|
||||||
|
"",
|
||||||
|
"\\end{align*}",
|
||||||
|
"",
|
||||||
|
"Hence $f(x)$ is surjective",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"\\textbf{Inverse:}",
|
||||||
|
"",
|
||||||
|
"The inverse is the same as the expression which makes up $x$ which we used to prove that $f(x)$ is surjective. Hence",
|
||||||
|
"",
|
||||||
|
"\\[ f^{-1}(x) = \\]",
|
||||||
|
],
|
||||||
|
"description": "Template for bijective proof",
|
||||||
|
},
|
||||||
|
|
||||||
|
"Equivalence Relation Proof": {
|
||||||
|
"scope": "latex",
|
||||||
|
"prefix": ["prove-eq-rel"],
|
||||||
|
"body": [
|
||||||
|
"In order for this relation to be an equivalence equation, it has to be reflexive, symmetric and transitive.",
|
||||||
|
"",
|
||||||
|
"\\textbf{Reflexive:}",
|
||||||
|
"",
|
||||||
|
"\\[ \\]",
|
||||||
|
"",
|
||||||
|
"\\textbf{Symmetric:}",
|
||||||
|
"",
|
||||||
|
"\\[ \\]",
|
||||||
|
"",
|
||||||
|
"\\textbf{Transitive:}",
|
||||||
|
"",
|
||||||
|
"\\[ \\]",
|
||||||
|
"",
|
||||||
|
"Hence the relation is an equivalence relation",
|
||||||
|
],
|
||||||
|
"description": "Template for equivalence relation proof",
|
||||||
|
},
|
||||||
|
|
||||||
|
"Partial Order Proof": {
|
||||||
|
"scope": "latex",
|
||||||
|
"prefix": ["prove-poset"],
|
||||||
|
"body": [
|
||||||
|
"In order for this relation to be a partial order, it has to be reflexive, antisymmetric and transitive.",
|
||||||
|
"",
|
||||||
|
"\\textbf{Reflexive:}",
|
||||||
|
"",
|
||||||
|
"\\[ \\]",
|
||||||
|
"",
|
||||||
|
"\\textbf{Antisymmetric:}",
|
||||||
|
"",
|
||||||
|
"\\[ \\]",
|
||||||
|
"",
|
||||||
|
"\\textbf{Transitive:}",
|
||||||
|
"",
|
||||||
|
"\\[ \\]",
|
||||||
|
"",
|
||||||
|
"Hence the relation is a partial order",
|
||||||
|
],
|
||||||
|
"description": "Template for poset proof",
|
||||||
|
},
|
||||||
|
|
||||||
|
"Poset MinMax": {
|
||||||
|
"scope": "latex",
|
||||||
|
"prefix": ["minmax-poset"],
|
||||||
|
"body": [
|
||||||
|
"Minimal elements:",
|
||||||
|
" \\[ \\{ $0 \\} \\]",
|
||||||
|
"Maximal elements:",
|
||||||
|
" \\[ \\{ \\} \\]"
|
||||||
|
],
|
||||||
|
"description": "Minimal maximal elements for poset",
|
||||||
|
},
|
||||||
|
|
||||||
|
"Binomial Coefficient": {
|
||||||
|
"scope": "latex",
|
||||||
|
"prefix": ["binom-co"],
|
||||||
|
"body": "\\[ \nCr{$0}{$1}x^{$2}y^{$1} = $3 x^{$2}y^{$1}\\]",
|
||||||
|
"description": "Formula for a binomial coefficient",
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
|
||||||
|
{
|
||||||
|
"hasse": {
|
||||||
|
"scope": "makefile",
|
||||||
|
"prefix": ["hasse"],
|
||||||
|
"body": "python ../../python/Hasse.py graphics/src/$1.txt graphics/$1.tex",
|
||||||
|
"description": "Add hasse diagram",
|
||||||
|
},
|
||||||
|
|
||||||
|
"FSA": {
|
||||||
|
"scope": "makefile",
|
||||||
|
"prefix": ["fsa"],
|
||||||
|
"body": "python ../../python/FSA.py graphics/src/$1.txt graphics/$1.tex",
|
||||||
|
"description": "Add FSA diagram",
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
.DEFAULT_GOAL := default
|
||||||
|
.PHONY: default python
|
||||||
|
|
||||||
|
default: python
|
||||||
|
pdflatex main.tex
|
||||||
|
|
||||||
|
SRC_DIR := $(shell find graphics/src -type f -printf "%f\n" -name *.txt | cut -d '.' -f1)
|
||||||
|
|
||||||
|
python:
|
||||||
|
@for f in $(SRC_DIR); \
|
||||||
|
do \
|
||||||
|
echo -e "\033[33mCOMPILING $$f.tex\033[0m"; \
|
||||||
|
python ../exam_template/python/run.py graphics/src/$$f.txt graphics/$$f.tex; \
|
||||||
|
echo ""; \
|
||||||
|
done
|
|
@ -0,0 +1,24 @@
|
||||||
|
\begin{tikzpicture}
|
||||||
|
\tikzset{
|
||||||
|
->, % makes the edges directed
|
||||||
|
>=Stealth, % makes the arrow heads bold
|
||||||
|
node distance=5cm, % specifies the minimum distance between two nodes. Change if necessary.
|
||||||
|
every state/.style={thick, fill=white}, % sets the properties for each ’state’ node
|
||||||
|
initial text=$ $, % sets the text that appears on the start arrow
|
||||||
|
}
|
||||||
|
|
||||||
|
\node[state, ] (s0) {$s_0$};
|
||||||
|
\node[state, right of=s0] (s1) {$s_1$};
|
||||||
|
\node[state, right of=s1] (s2) {$s_2$};
|
||||||
|
|
||||||
|
\draw (s0) edge[bend right, below] node{$a,0$} (s1);
|
||||||
|
\draw (s0) edge[above] node{$c,1$} (s1);
|
||||||
|
\draw (s0) edge[loop,above] node{b,1} (s0);
|
||||||
|
\draw (s1) edge[above] node{$a,1$} (s2);
|
||||||
|
\draw (s1) edge[bend right, above] node{$b,0$} (s0);
|
||||||
|
\draw (s1) edge[bend right, above] node{$c,0$} (s0);
|
||||||
|
\draw (s2) edge[bend right, above] node{$a,0$} (s1);
|
||||||
|
\draw (s2) edge[bend left, below] node{$b,1$} (s0);
|
||||||
|
\draw (s2) edge[loop,above] node{c,0} (s2);
|
||||||
|
|
||||||
|
\end{tikzpicture}
|
|
@ -0,0 +1,24 @@
|
||||||
|
\begin{tikzpicture}
|
||||||
|
\tikzset{
|
||||||
|
->, % makes the edges directed
|
||||||
|
>=Stealth, % makes the arrow heads bold
|
||||||
|
node distance=5cm, % specifies the minimum distance between two nodes. Change if necessary.
|
||||||
|
every state/.style={thick, fill=white}, % sets the properties for each ’state’ node
|
||||||
|
initial text=$ $, % sets the text that appears on the start arrow
|
||||||
|
}
|
||||||
|
|
||||||
|
\node[state, ] (s0) {$s_0$};
|
||||||
|
\node[state, right of=s0] (s1) {$s_1$};
|
||||||
|
\node[state, right of=s1] (s2) {$s_2$};
|
||||||
|
|
||||||
|
\draw (s0) edge[bend right, above] node{$a,0$} (s1);
|
||||||
|
\draw (s0) edge[above] node{$c,1$} (s1);
|
||||||
|
\draw (s0) edge[loop,above] node{b,1} (s0);
|
||||||
|
\draw (s1) edge[above] node{$a,1$} (s2);
|
||||||
|
\draw (s1) edge[bend right=60, above] node{$b,0$} (s0);
|
||||||
|
\draw (s1) edge[bend right, above] node{$c,0$} (s0);
|
||||||
|
\draw (s2) edge[bend right, above] node{$a,0$} (s1);
|
||||||
|
\draw (s2) edge[bend left, below] node{$b,1$} (s0);
|
||||||
|
\draw (s2) edge[loop,above] node{c,0} (s2);
|
||||||
|
|
||||||
|
\end{tikzpicture}
|
|
@ -0,0 +1,22 @@
|
||||||
|
\newcommand{\arrow}[2]{\path [-{Latex[scale=1]}] (#1) edge (#2);}
|
||||||
|
|
||||||
|
\begin{tikzpicture}
|
||||||
|
|
||||||
|
\begin{scope}[every node/.style={shape=circle, fill=white, draw, inner sep=2pt}]
|
||||||
|
\node (A) at (0,2.5) {$A$};
|
||||||
|
\node (B) at (-2.37764,0.77254) {$B$};
|
||||||
|
\node (C) at (-1.46946,-2.02254) {$C$};
|
||||||
|
\node (D) at (1.46946,-2.02254) {$D$};
|
||||||
|
\node (E) at (2.37764,0.77254) {$E$};
|
||||||
|
\end{scope}
|
||||||
|
|
||||||
|
\begin{scope}[every draw/.style={}]
|
||||||
|
\draw (A) -- (B);
|
||||||
|
\draw (A) -- (C);
|
||||||
|
\draw (A) -- (E);
|
||||||
|
\draw (B) -- (D);
|
||||||
|
\draw (B) -- (E);
|
||||||
|
\draw (D) -- (E);
|
||||||
|
\end{scope}
|
||||||
|
|
||||||
|
\end{tikzpicture}
|
|
@ -0,0 +1,37 @@
|
||||||
|
\newcommand{\point}[4]{
|
||||||
|
\node [label=#3:#4] (#1) at #2 {};
|
||||||
|
}
|
||||||
|
|
||||||
|
\newcommand{\wpath}[3]{
|
||||||
|
\draw (#1) -- (#2) node [midway, above, sloped] (Tx#1#2) {{\tiny $#3$}};
|
||||||
|
}
|
||||||
|
|
||||||
|
\begin{tikzpicture}[]
|
||||||
|
\begin{scope}[every node/.style={fill=black, shape=circle, inner sep=1pt}]
|
||||||
|
\point{1}{(0,1)}{left}{$v_1$}
|
||||||
|
\point{2}{(1,2)}{above}{$v_2$}
|
||||||
|
\point{3}{(1,0)}{below}{$v_3$}
|
||||||
|
|
||||||
|
\point{4}{(3,2)}{above left}{$v_4$}
|
||||||
|
\point{5}{(3,0)}{below right}{$v_5$}
|
||||||
|
|
||||||
|
\point{6}{(5,2)}{above left}{$v_6$}
|
||||||
|
\point{7}{(5,0)}{above left}{$v_7$}
|
||||||
|
\point{8}{(6,1)}{above right}{$v_8$}
|
||||||
|
\end{scope}
|
||||||
|
|
||||||
|
\wpath{1}{3}{1}
|
||||||
|
\wpath{2}{3}{2}
|
||||||
|
\wpath{7}{8}{2}
|
||||||
|
\wpath{3}{5}{3}
|
||||||
|
\wpath{4}{5}{4}
|
||||||
|
\wpath{6}{8}{5}
|
||||||
|
\wpath{5}{6}{6}
|
||||||
|
\wpath{6}{7}{7}
|
||||||
|
\wpath{5}{7}{8}
|
||||||
|
\wpath{4}{6}{9}
|
||||||
|
\wpath{2}{5}{10}
|
||||||
|
\wpath{2}{4}{11}
|
||||||
|
\wpath{1}{2}{12}
|
||||||
|
|
||||||
|
\end{tikzpicture}
|
|
@ -0,0 +1,31 @@
|
||||||
|
\newcommand{\point}[4]{
|
||||||
|
\node [label=#3:#4] (#1) at #2 {};
|
||||||
|
}
|
||||||
|
|
||||||
|
\newcommand{\wpath}[3]{
|
||||||
|
\draw (#1) -- (#2) node [midway, above, sloped] (Tx#1#2) {{\tiny $#3$}};
|
||||||
|
}
|
||||||
|
|
||||||
|
\begin{tikzpicture}[]
|
||||||
|
\begin{scope}[every node/.style={fill=black, shape=circle, inner sep=1pt}]
|
||||||
|
\point{1}{(0,1)}{left}{$v_1$}
|
||||||
|
\point{2}{(1,2)}{above}{$v_2$}
|
||||||
|
\point{3}{(1,0)}{below}{$v_3$}
|
||||||
|
|
||||||
|
\point{4}{(3,2)}{above left}{$v_4$}
|
||||||
|
\point{5}{(3,0)}{below right}{$v_5$}
|
||||||
|
|
||||||
|
\point{6}{(5,2)}{above left}{$v_6$}
|
||||||
|
\point{7}{(5,0)}{above left}{$v_7$}
|
||||||
|
\point{8}{(6,1)}{above right}{$v_8$}
|
||||||
|
\end{scope}
|
||||||
|
|
||||||
|
\wpath{1}{3}{1}
|
||||||
|
\wpath{2}{3}{2}
|
||||||
|
\wpath{7}{8}{2}
|
||||||
|
\wpath{3}{5}{3}
|
||||||
|
\wpath{4}{5}{4}
|
||||||
|
\wpath{6}{8}{5}
|
||||||
|
\wpath{5}{6}{6}
|
||||||
|
|
||||||
|
\end{tikzpicture}
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
\begin{truthtable}
|
||||||
|
{c|c|e|c|e}
|
||||||
|
{$p$ & $q$ & $ \neg p$ & $p \wedge q$ & $ \neg (p \wedge q)$}
|
||||||
|
\T & \T & \F & \T & \F \\
|
||||||
|
\T & \F & \F & \F & \T \\
|
||||||
|
\F & \T & \T & \F & \T \\
|
||||||
|
\F & \F & \T & \F & \T \\
|
||||||
|
\end{truthtable}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
|
||||||
|
In order for this relation to be an equivalence equation, it has to be reflexive, symmetric and transitive.
|
||||||
|
|
||||||
|
\textbf{Reflexive:}
|
||||||
|
|
||||||
|
All elements are related to themself
|
||||||
|
|
||||||
|
\[ DD, AA, CC, BB \]
|
||||||
|
|
||||||
|
\textbf{Symmetric:}
|
||||||
|
|
||||||
|
All relations has its symmetric counterpart
|
||||||
|
|
||||||
|
\begin{gather*}
|
||||||
|
CD\text{ and }DC
|
||||||
|
\end{gather*}
|
||||||
|
|
||||||
|
\textbf{Transitive:}
|
||||||
|
|
||||||
|
All pair of relations where $xRy$ and $yRz$ has its transitive counterpart
|
||||||
|
|
||||||
|
\begin{gather*}
|
||||||
|
DC\text{ and }CD\text{ with }DD \\
|
||||||
|
CD\text{ and }DC\text{ with }CC
|
||||||
|
\end{gather*}
|
||||||
|
|
||||||
|
Hence the relation is an equivalence relation
|
|
@ -0,0 +1,15 @@
|
||||||
|
\begin{tikzpicture}
|
||||||
|
\tikzset{every node/.style={shape=circle,draw,fill=white,inner sep=2pt}}
|
||||||
|
|
||||||
|
\node (3) at (0, 0) {$3$};
|
||||||
|
\node (4) at (1, 0) {$4$};
|
||||||
|
\node (6) at (0, 1) {$6$};
|
||||||
|
\node (12) at (0, 2) {$12$};
|
||||||
|
\node (20) at (1, 1) {$20$};
|
||||||
|
|
||||||
|
\draw (3) -- (6);
|
||||||
|
\draw (4) -- (12);
|
||||||
|
\draw (4) -- (20);
|
||||||
|
\draw (6) -- (12);
|
||||||
|
|
||||||
|
\end{tikzpicture}
|
|
@ -0,0 +1,14 @@
|
||||||
|
# FSA
|
||||||
|
0
|
||||||
|
1 r0
|
||||||
|
2 r1
|
||||||
|
|
||||||
|
0 a,0 )d 1
|
||||||
|
0 c,1 u 1
|
||||||
|
o b,1 u 0
|
||||||
|
1 a,1 u 2
|
||||||
|
1 b,0 )u 0
|
||||||
|
1 c,0 )u 0
|
||||||
|
2 a,0 )u 1
|
||||||
|
2 b,1 (d 0
|
||||||
|
o c,0 u 2
|
|
@ -0,0 +1,8 @@
|
||||||
|
# Graph
|
||||||
|
matrix
|
||||||
|
|
||||||
|
01101
|
||||||
|
10011
|
||||||
|
10000
|
||||||
|
01001
|
||||||
|
11010
|
|
@ -0,0 +1,2 @@
|
||||||
|
# Truthtable
|
||||||
|
p, q, E not p, p and q, E not (p and q)
|
|
@ -0,0 +1,4 @@
|
||||||
|
# Relations
|
||||||
|
proveEquivalence
|
||||||
|
|
||||||
|
AA BB CC CD DD DC
|
|
@ -0,0 +1,7 @@
|
||||||
|
def genDivPosetFrom(s):
|
||||||
|
return set((s1,s2) for s1 in s for s2 in s if s2 % s1 == 0 and s1 != s2)
|
||||||
|
|
||||||
|
s = set([3,4,6,12,20])
|
||||||
|
poset = genDivPosetFrom(s)
|
||||||
|
|
||||||
|
print('\n'.join(str(x) for x in poset))
|
|
@ -0,0 +1,348 @@
|
||||||
|
\documentclass[12pt]{article}
|
||||||
|
\usepackage{ntnu}
|
||||||
|
\usepackage{ntnu-math}
|
||||||
|
\usepackage{ntnu-code}
|
||||||
|
|
||||||
|
\author{10112}
|
||||||
|
\title{MA0301 Spring 2021}
|
||||||
|
|
||||||
|
\usetikzlibrary{automata, positioning, arrows.meta}
|
||||||
|
|
||||||
|
\newcommand{\I}{\Huge\textbf{I}}
|
||||||
|
\newcommand{\II}{\Huge\textbf{I\!I}}
|
||||||
|
\newcommand{\III}{\Huge\textbf{I\!I\!I}}
|
||||||
|
|
||||||
|
\usepackage{listings}
|
||||||
|
\usepackage{blkarray}
|
||||||
|
|
||||||
|
\renewcommand{\theenumi}{\arabic{enumi}}
|
||||||
|
\renewcommand{\theenumii}{(\arabic{enumii})}
|
||||||
|
\renewcommand{\theenumiii}{\alph{enumiii})}
|
||||||
|
|
||||||
|
|
||||||
|
\newcommand{\checkEdge}[3]{
|
||||||
|
Find next edge with the minimum weight. \\
|
||||||
|
The edge between #1 and #2 has weight #3. \\
|
||||||
|
Does adding it connect two separate subgraphs? \\
|
||||||
|
}
|
||||||
|
\newcommand{\yes}{\textbf{Yes. Add edge} \\[2ex]}
|
||||||
|
\newcommand{\no}{\textbf{No. Discard edge} \\[2ex]}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
|
||||||
|
%%%%%%%% 2
|
||||||
|
|
||||||
|
\begin{align*}
|
||||||
|
\neg (\exists x \forall y (\neg P(x,y) \wedge Q(x,y))) \\
|
||||||
|
\forall x \exists y \neg(\neg P(x,y) \wedge Q(x,y)) \\
|
||||||
|
\forall x \exists y (\neg \neg P(x,y) \vee \neg Q(x,y)) \\
|
||||||
|
\forall x \exists y (P(x,y) \vee \neg Q(x,y)) \\
|
||||||
|
\end{align*}
|
||||||
|
|
||||||
|
%%%%%%%% 3
|
||||||
|
\break
|
||||||
|
|
||||||
|
1.
|
||||||
|
|
||||||
|
\input{graphics/3.tex}
|
||||||
|
|
||||||
|
2.
|
||||||
|
|
||||||
|
By looking at the truthtable, we can see that $\neg p \not\equiv \neg(p \wedge q)$ \\
|
||||||
|
|
||||||
|
3.
|
||||||
|
|
||||||
|
\begin{gather*}
|
||||||
|
(p \downarrow q) \downarrow (p \downarrow q) \\
|
||||||
|
\neg ( \neg (p \wedge q) \wedge \neg (p \wedge q)) \\
|
||||||
|
\neg ( (\neg p \vee \neg q) \wedge (\neg p \vee \neg q)) \\
|
||||||
|
\neg (\neg p \vee \neg q) \vee \neg (\neg p \vee \neg q)) \\
|
||||||
|
\neg \neg p \vee \neg \neg q \vee \neg \neg p \vee \neg \neg q \\
|
||||||
|
p \vee q \vee p \vee q \\
|
||||||
|
p \vee q \\
|
||||||
|
\end{gather*}
|
||||||
|
|
||||||
|
\[ (p \downarrow q) \downarrow (p \downarrow q) \equiv p \vee q \]
|
||||||
|
|
||||||
|
|
||||||
|
%%%%%%%% 5
|
||||||
|
\break
|
||||||
|
|
||||||
|
\[ R := \{ (0,0), (1,1), (2,2), (2,3) \} \]
|
||||||
|
|
||||||
|
$R$ is not an equivalence relation. \\
|
||||||
|
|
||||||
|
For reflexivity, it's missing one relation
|
||||||
|
|
||||||
|
\[ (3,3) \]
|
||||||
|
|
||||||
|
For symmetry, it's missing one relation
|
||||||
|
|
||||||
|
\[ (3,2) \]
|
||||||
|
|
||||||
|
For transitivity, it will by now have all missing elements \\
|
||||||
|
|
||||||
|
\[ (2,3) \text{ and } (3,2) \rightarrow (2,2) \]
|
||||||
|
\[ (3,2) \text{ and } (2,3) \rightarrow (3,3) \]
|
||||||
|
|
||||||
|
\[ R := \{ (0,0),(1,1),(2,2),(2,3), (3,2), (3,3) \} \]
|
||||||
|
|
||||||
|
%%%%%%%% 6
|
||||||
|
\break
|
||||||
|
|
||||||
|
\[ A := \{3, 4, 6, 12, 20 \} \]
|
||||||
|
|
||||||
|
\includeDiagram[scale=2, width=5cm]{graphics/6.tex}
|
||||||
|
|
||||||
|
\center
|
||||||
|
By looking at the hasse diagram, we can see that
|
||||||
|
|
||||||
|
\[ \text{Minimal elements: } \{ 3, 4 \} \]
|
||||||
|
\[ \text{Maximal elements: } \{ 12, 20 \} \]
|
||||||
|
|
||||||
|
%%%%%%%% 7
|
||||||
|
\break
|
||||||
|
|
||||||
|
Base case:
|
||||||
|
|
||||||
|
\begin{align*}
|
||||||
|
\sum^3_{i=3} 3^i = \frac{3(3^3-9)}{2} \\[2ex]
|
||||||
|
3^3 = \frac{3(27-9)}{2} \\[2ex]
|
||||||
|
27 = \frac{3(18)}{2} \\[2ex]
|
||||||
|
27 = 9 \cdot 3 \\[2ex]
|
||||||
|
27 = 27 \\[2ex]
|
||||||
|
\end{align*}
|
||||||
|
|
||||||
|
Assume that
|
||||||
|
|
||||||
|
\[ \sum^n_{i=3} 3^i = \frac{3(3^n-9)}{2} \qquad \text{for } n > 2 \]
|
||||||
|
|
||||||
|
Then
|
||||||
|
|
||||||
|
\begin{align*}
|
||||||
|
\sum^{n+1}_{i=3} 3^i &= 3^3 + 3^4 + \ldots + 3^n + 3^{n+1} \\[2ex]
|
||||||
|
&= \frac{3(3^n-9)}{2} + 3^{n+1} \\[2ex]
|
||||||
|
&= \frac{3^{n+1} - 3 \cdot 9 + 2 \cdot 3^{n+1}}{2} \\[2ex]
|
||||||
|
&= \frac{3 \cdot 3^{n+1} - 3 \cdot 9}{2} \\[2ex]
|
||||||
|
&= \frac{3(3^{n+1} - 9)}{2} \\[2ex]
|
||||||
|
\end{align*}
|
||||||
|
|
||||||
|
\qed
|
||||||
|
|
||||||
|
%%%%%%%% 8
|
||||||
|
\break
|
||||||
|
|
||||||
|
\[
|
||||||
|
\{ a_n \}_{n>0} =
|
||||||
|
\begin{cases}
|
||||||
|
a_1 = 3 \\
|
||||||
|
a_2 = 6 \\
|
||||||
|
a_n = a_n + a_{n-1} \quad \text{for } n > 2 \\
|
||||||
|
\end{cases}
|
||||||
|
\]
|
||||||
|
|
||||||
|
\textbf{Base case:}
|
||||||
|
|
||||||
|
For $a_3$, we have that
|
||||||
|
|
||||||
|
\begin{align*}
|
||||||
|
a_3 &= a_2 + a_1 \\
|
||||||
|
&= 6 + 3 \\
|
||||||
|
&= 3(3) \\
|
||||||
|
&\Rightarrow a_3 \bmod 3 = 0
|
||||||
|
\end{align*}
|
||||||
|
|
||||||
|
For $a_4$, we have that
|
||||||
|
|
||||||
|
\begin{align*}
|
||||||
|
a_4 &= a_3 + a_2 \\
|
||||||
|
&= 9 + 6 \\
|
||||||
|
&= 3(5) \\
|
||||||
|
&\Rightarrow a_4 \bmod 3 = 0
|
||||||
|
\end{align*}
|
||||||
|
|
||||||
|
\textbf{Inductive step:}
|
||||||
|
|
||||||
|
Assume that for $k_1 \in \N$, $k_2 \in \N$:
|
||||||
|
|
||||||
|
\begin{align*}
|
||||||
|
a_n &= 3(k_1) \\
|
||||||
|
a_{n-1} &= 3(k_2) \\
|
||||||
|
\end{align*}
|
||||||
|
|
||||||
|
Then
|
||||||
|
|
||||||
|
\begin{align*}
|
||||||
|
a_{n+1} &= a_n + a_{n-1} \\
|
||||||
|
&= 3(k_1) + 3(k_2) \\
|
||||||
|
&= 3(k_1 + k_2) \\
|
||||||
|
&\Rightarrow a_{n+1} \bmod 3 = 0
|
||||||
|
\end{align*}
|
||||||
|
|
||||||
|
\qed
|
||||||
|
|
||||||
|
|
||||||
|
%%%%%%%% 10
|
||||||
|
\break
|
||||||
|
|
||||||
|
\[ f : \Z \rightarrow \Z \]
|
||||||
|
\[ f(x) = x-7 \]
|
||||||
|
|
||||||
|
\textbf{Injective:}
|
||||||
|
|
||||||
|
In order for $f(x)$ to be injective, it has to hold that
|
||||||
|
|
||||||
|
\[ f(a) = f(b) \Rightarrow a = b \]
|
||||||
|
|
||||||
|
\begin{align*}
|
||||||
|
f(a) &= f(b) \\
|
||||||
|
a - 7 &= b - 7 \\
|
||||||
|
a &= b \\
|
||||||
|
\end{align*}
|
||||||
|
|
||||||
|
Hence $f(x)$ is injective. \\
|
||||||
|
|
||||||
|
|
||||||
|
\textbf{Surjective:}
|
||||||
|
|
||||||
|
In order for $f(x)$ to be surjective, it has to hold that
|
||||||
|
|
||||||
|
\[ \forall x \in \Z \exists y \in \Z [f(x) = y] \]
|
||||||
|
|
||||||
|
\begin{align*}
|
||||||
|
y &= x - 7 \\
|
||||||
|
x &= y + 7 \\
|
||||||
|
\end{align*}
|
||||||
|
|
||||||
|
$ x = y + 7 $ makes up all the elements in $\Z$
|
||||||
|
|
||||||
|
\begin{align*}
|
||||||
|
f(x) &= x - 7 \\
|
||||||
|
&= (y + 7) - 7 \\
|
||||||
|
&= y
|
||||||
|
\end{align*}
|
||||||
|
|
||||||
|
Hence $f(x)$ is surjective \\
|
||||||
|
|
||||||
|
\textbf{Conclusion:}
|
||||||
|
|
||||||
|
Since $f(x)$ is both injective and surjective, it is by definition bijective
|
||||||
|
|
||||||
|
|
||||||
|
%%%%%%%% 11
|
||||||
|
\break
|
||||||
|
|
||||||
|
There are no $x^6y^6$ in the expansion of $(3x^5 + 2y)^6$ \\
|
||||||
|
|
||||||
|
For $x^{10}y^4$, there is
|
||||||
|
|
||||||
|
\[ \binom{6}{4}(3x^5)^{6-4}(2y)^4 = 2160 x^{10}y^4 \]
|
||||||
|
|
||||||
|
%%%%%%%% 12
|
||||||
|
\break
|
||||||
|
|
||||||
|
The number of permutations of the letters "ALLTALK" is
|
||||||
|
|
||||||
|
\[ \frac{7!}{(7-7)!2!3!} = 420 \]
|
||||||
|
|
||||||
|
If all of the Ls has to be together, we can think of this block like one letter. \\
|
||||||
|
|
||||||
|
That leaves us with 5 letters, where one of them is repeated once. \\
|
||||||
|
|
||||||
|
\[ \frac{5!}{(5-5)!2!} = 60 \]
|
||||||
|
|
||||||
|
%%%%%%%% 14
|
||||||
|
\break
|
||||||
|
|
||||||
|
\includeDiagram{graphics/14mod.tex}
|
||||||
|
|
||||||
|
Assuming the automation is starting at $s_0$, the output for $acabacab$ would be
|
||||||
|
|
||||||
|
\begin{gather*}
|
||||||
|
s_0 \xrightarrow{a,0} s_1 \\
|
||||||
|
s_1 \xrightarrow{c,0} s_0 \\
|
||||||
|
s_0 \xrightarrow{a,0} s_1 \\
|
||||||
|
s_1 \xrightarrow{b,0} s_0 \\
|
||||||
|
s_0 \xrightarrow{a,0} s_1 \\
|
||||||
|
s_1 \xrightarrow{c,0} s_0 \\
|
||||||
|
s_0 \xrightarrow{a,0} s_1 \\
|
||||||
|
s_1 \xrightarrow{b,0} s_0 \\
|
||||||
|
\end{gather*}
|
||||||
|
|
||||||
|
\[ 00000000 \]
|
||||||
|
|
||||||
|
%%%%%%%% 15
|
||||||
|
\break
|
||||||
|
|
||||||
|
$L$ is a language that only contains words which fits the regular expresson $r$, where
|
||||||
|
|
||||||
|
\[ r = b^*ab^*ab^* \]
|
||||||
|
|
||||||
|
or described with words, \\
|
||||||
|
|
||||||
|
\center "$L$ is a language that only has words that contain exactly two of the letter $a$"
|
||||||
|
|
||||||
|
%%%%%%%% 16
|
||||||
|
\break
|
||||||
|
|
||||||
|
\[
|
||||||
|
\begin{blockarray}{cccccc}
|
||||||
|
& A & B & C & D & E \\
|
||||||
|
\begin{block}{c[ccccc]}
|
||||||
|
A & 0 & 1 & 1 & 0 & 1 \\
|
||||||
|
B & 1 & 0 & 0 & 1 & 1 \\
|
||||||
|
C & 1 & 0 & 0 & 0 & 0 \\
|
||||||
|
D & 0 & 1 & 0 & 0 & 1 \\
|
||||||
|
E & 1 & 1 & 0 & 1 & 0 \\
|
||||||
|
\end{block}
|
||||||
|
\end{blockarray}
|
||||||
|
\]
|
||||||
|
|
||||||
|
\includeDiagram{graphics/16.tex}
|
||||||
|
|
||||||
|
|
||||||
|
%%%%%%%% 17
|
||||||
|
\break
|
||||||
|
|
||||||
|
\includeDiagram[scale=1.6]{graphics/17.tex}
|
||||||
|
|
||||||
|
Performed Kruskal's algorithm as follows: \\[2ex]
|
||||||
|
|
||||||
|
\textbf{Remove all edges} \\
|
||||||
|
|
||||||
|
\checkEdge{1}{3}{1}
|
||||||
|
\yes
|
||||||
|
\checkEdge{2}{3}{2}
|
||||||
|
\yes
|
||||||
|
\checkEdge{7}{8}{2}
|
||||||
|
\yes
|
||||||
|
\checkEdge{3}{5}{3}
|
||||||
|
\yes
|
||||||
|
\checkEdge{4}{5}{4}
|
||||||
|
\yes
|
||||||
|
\checkEdge{6}{8}{5}
|
||||||
|
\yes
|
||||||
|
\checkEdge{5}{6}{6}
|
||||||
|
\yes
|
||||||
|
By now, the graph is already spanning so there aren't any more disconnected subgraphs to connect, but I'll check the last ones anyway, like for-looping over the set of edges in a computer program would. \\
|
||||||
|
|
||||||
|
\checkEdge{6}{7}{7}
|
||||||
|
\no
|
||||||
|
\checkEdge{5}{7}{8}
|
||||||
|
\no
|
||||||
|
\checkEdge{4}{6}{9}
|
||||||
|
\no
|
||||||
|
\checkEdge{2}{5}{10}
|
||||||
|
\no
|
||||||
|
\checkEdge{2}{4}{11}
|
||||||
|
\no
|
||||||
|
\checkEdge{1}{2}{12}
|
||||||
|
\no
|
||||||
|
|
||||||
|
\break{}
|
||||||
|
|
||||||
|
\textbf{Result: }
|
||||||
|
|
||||||
|
\includeDiagram[scale=1.6]{graphics/17_2.tex}
|
||||||
|
|
||||||
|
\end{document}
|
|
@ -0,0 +1,80 @@
|
||||||
|
from sys import argv
|
||||||
|
from pathlib import Path
|
||||||
|
import re
|
||||||
|
|
||||||
|
from common import replaceContent
|
||||||
|
|
||||||
|
placementChart = {
|
||||||
|
'a': 'above',
|
||||||
|
'b': 'below',
|
||||||
|
'l': 'left',
|
||||||
|
'r': 'right'
|
||||||
|
}
|
||||||
|
|
||||||
|
def generateEdge(inputLine):
|
||||||
|
s_src, msg, opts, s_dest = inputLine.split(' ')
|
||||||
|
|
||||||
|
out_options = []
|
||||||
|
|
||||||
|
if '(' in opts or ')' in opts:
|
||||||
|
out_options.append('bend left' if '(' in opts else 'bend right')
|
||||||
|
|
||||||
|
if any(x in opts for x in 'udlr'):
|
||||||
|
out_options.append(
|
||||||
|
'above' if 'u' in opts else \
|
||||||
|
'below' if 'd' in opts else \
|
||||||
|
'left' if 'l' in opts else \
|
||||||
|
'right' if 'r' in opts else ''
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if s_src == 'o':
|
||||||
|
return f'\draw (s{s_dest}) edge[loop,{",".join(out_options)}] node{{{msg}}} (s{s_dest});'
|
||||||
|
else:
|
||||||
|
return f'\draw (s{s_src}) edge[{", ".join(out_options)}] node{{${msg}$}} (s{s_dest});'
|
||||||
|
|
||||||
|
def generateNode(inputLine):
|
||||||
|
s_src, opts = inputLine.split(' ')
|
||||||
|
|
||||||
|
out_opts = []
|
||||||
|
if 's' in opts:
|
||||||
|
out_opts.append('initial')
|
||||||
|
if 'f' in opts:
|
||||||
|
out_opts.append('accepting')
|
||||||
|
|
||||||
|
if place := re.search('[udlr]\d+', opts):
|
||||||
|
out_opts.append(placementChart[place.group()[0]] + ' of=s' + place.group()[1])
|
||||||
|
|
||||||
|
return f'\\node[state, {", ".join(out_opts)}] (s{s_src}) {{$s_{s_src}$}};'
|
||||||
|
|
||||||
|
|
||||||
|
def generate_latex(inputLines):
|
||||||
|
|
||||||
|
nodes, edges = inputLines.split('\n\n')
|
||||||
|
|
||||||
|
output=[]
|
||||||
|
|
||||||
|
for node in nodes.split('\n'):
|
||||||
|
output.append(generateNode(node))
|
||||||
|
|
||||||
|
output.append('')
|
||||||
|
|
||||||
|
for edge in edges.split('\n'):
|
||||||
|
output.append(generateEdge(edge))
|
||||||
|
|
||||||
|
return '\n'.join(output)
|
||||||
|
|
||||||
|
def processFileContent(raw):
|
||||||
|
content = generate_latex(raw)
|
||||||
|
return replaceContent(content, 'FSA')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
pass
|
||||||
|
# filename = argv[1]
|
||||||
|
|
||||||
|
# with open(filename) as file:
|
||||||
|
# content = generate_latex(file.read())
|
||||||
|
|
||||||
|
# with open(str(Path(__file__).parent.absolute()) + '/tex_templates/FSA.tex') as template:
|
||||||
|
# with open(argv[2], 'w') as destination_file:
|
||||||
|
# destination_file.write(template.read().replace('%CONTENT', content))
|
|
@ -0,0 +1,261 @@
|
||||||
|
from sys import argv
|
||||||
|
from pathlib import Path
|
||||||
|
from math import sin, cos, pi
|
||||||
|
|
||||||
|
from common import printc, printerr, replaceContent
|
||||||
|
|
||||||
|
class Matrix:
|
||||||
|
""" Adjacency matrix which supports 0 and 1 """
|
||||||
|
|
||||||
|
def __init__(self, matrix):
|
||||||
|
self.matrix = matrix
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return iter(self.matrix)
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.matrix)
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.matrix == other
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "\n".join(' '.join('\033[32m1\033[0m' if b else '\033[31m0\033[0m' for b in line) for line in self)
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
return self.matrix[key]
|
||||||
|
|
||||||
|
def __setitem__(self, key, item):
|
||||||
|
self.matrix[key] = item
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def fromGraph(cls, graph):
|
||||||
|
return graph.toMatrix()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def fromString(cls, string):
|
||||||
|
matrix = []
|
||||||
|
for line in string.split('\n'):
|
||||||
|
matrix.append([True if char == '1' else False for char in line])
|
||||||
|
|
||||||
|
if len(matrix) != len(matrix[0]):
|
||||||
|
raise ValueError('Matrix not covering all points')
|
||||||
|
|
||||||
|
return cls(matrix)
|
||||||
|
|
||||||
|
def toGraph(self):
|
||||||
|
nodes = [chr(i + 65) for i in range(len(self))]
|
||||||
|
|
||||||
|
edges = []
|
||||||
|
for i, line in enumerate(self):
|
||||||
|
edges += [(nodes[i],nodes[j]) for j, b in enumerate(line) if b]
|
||||||
|
|
||||||
|
return Graph(nodes, edges)
|
||||||
|
|
||||||
|
def toLaTeX(self):
|
||||||
|
return '\\begin{pmatrix}\n' \
|
||||||
|
+ '\n'.join(' ' + ' & '.join('1' if b else '0' for b in line) + ' \\\\' for line in self.matrix) \
|
||||||
|
+ '\n\\end{pmatrix}'
|
||||||
|
|
||||||
|
|
||||||
|
class Graph:
|
||||||
|
def __init__(self, nodes, edges): # Nodes = str, Edges = (str,str)
|
||||||
|
self.nodes = nodes
|
||||||
|
self.edges = edges
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
printc('Is undirected: ' + str(self.isUndirected()))
|
||||||
|
return \
|
||||||
|
f'Nodes: {" ".join(self.nodes)}\n' \
|
||||||
|
+ f'Edges: {" ".join(x+y for x,y in (self.undirectedEdgeSet() if self.isUndirected() else self.edges))}'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def fromMatrix(cls, matrix):
|
||||||
|
return matrix.toGraph()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def fromString(cls, string):
|
||||||
|
splitData = string.split('\n\n')
|
||||||
|
|
||||||
|
if splitData[0] == 'complete':
|
||||||
|
data1 = 'undirected'
|
||||||
|
nodes = [chr(i + 65) for i in range(int(splitData[1]))]
|
||||||
|
data2 = ' '.join(nodes)
|
||||||
|
data3 = '\n'.join([a+b for a in nodes for b in nodes if a != b])
|
||||||
|
elif splitData[0] == 'matrix':
|
||||||
|
return Graph.fromMatrix(Matrix.fromString(splitData[1]))
|
||||||
|
else:
|
||||||
|
data1, data2, data3 = splitData
|
||||||
|
|
||||||
|
graphType = data1
|
||||||
|
nodes = data2.split(' ')
|
||||||
|
edges = [(x,y) for x,y in data3.split('\n')]
|
||||||
|
|
||||||
|
if graphType == 'undirected':
|
||||||
|
edges = [(a,b) for a in nodes for b in nodes if (a,b) in edges or (b,a) in edges]
|
||||||
|
|
||||||
|
return cls(nodes, edges)
|
||||||
|
|
||||||
|
def toMatrix(self):
|
||||||
|
rows = []
|
||||||
|
for node in self.nodes:
|
||||||
|
rows.append([(node,node2) in self.edges for node2 in self.nodes])
|
||||||
|
return Matrix(rows)
|
||||||
|
|
||||||
|
def isUndirected(self):
|
||||||
|
matrix = self.toMatrix()
|
||||||
|
|
||||||
|
flipv = lambda matrix: list(reversed(matrix))
|
||||||
|
rot90cc = lambda matrix: list(list(x) for x in zip(*reversed(matrix)))
|
||||||
|
|
||||||
|
return matrix == rot90cc(flipv(matrix)) \
|
||||||
|
and all(matrix[i][i] == 0 for i in range(len(matrix)))
|
||||||
|
|
||||||
|
def undirectedEdgeSet(self):
|
||||||
|
edges = self.edges
|
||||||
|
if self.isUndirected():
|
||||||
|
edges = sorted(list(set((x,y) if x < y else (y,x) for x,y in edges)))
|
||||||
|
return edges
|
||||||
|
|
||||||
|
# def latexifyEulerPath(self):
|
||||||
|
# degrees = [sum(line) for line in self.toMatrix()]
|
||||||
|
|
||||||
|
# def latexifyEulerCircuit():
|
||||||
|
# pass
|
||||||
|
|
||||||
|
def getKruskalsSpanningTree(self, weigths): # weights = dict[str, int]
|
||||||
|
edges = []
|
||||||
|
connected_subgraphs = [set(v) for v in self.nodes]
|
||||||
|
|
||||||
|
if not all(n in ''.join(x+y for x,y in self.edges) for n in self.nodes):
|
||||||
|
printerr('Not all nodes are connected. There is no spanning tree to be made')
|
||||||
|
return
|
||||||
|
|
||||||
|
def find_subgraph_containing(v):
|
||||||
|
return [x for x in connected_subgraphs if v in x][0]
|
||||||
|
|
||||||
|
def merge_subgraphs_that_contains(u, v):
|
||||||
|
subgraph_v = find_subgraph_containing(v)
|
||||||
|
new_connected_subgraphs = [x for x in connected_subgraphs if v not in x]
|
||||||
|
new_connected_subgraphs = [subgraph_v.union(x) if u in x else x for x in new_connected_subgraphs]
|
||||||
|
return new_connected_subgraphs
|
||||||
|
|
||||||
|
sorted_edges = [ e for e in sorted(self.edges, key=lambda e: weigths[e[0] + e[1]]) ]
|
||||||
|
|
||||||
|
for u,v in sorted_edges:
|
||||||
|
if find_subgraph_containing(u) != find_subgraph_containing(v):
|
||||||
|
edges += [(u, v)]
|
||||||
|
connected_subgraphs = merge_subgraphs_that_contains(u, v)
|
||||||
|
|
||||||
|
edges += [(y,x) for x,y in edges]
|
||||||
|
|
||||||
|
return Graph(self.nodes, edges)
|
||||||
|
|
||||||
|
def toLaTeX(self):
|
||||||
|
zippedNodes = zip(self.nodes, generateNodeCoords(len(self.nodes)))
|
||||||
|
nodeString = '\n'.join(f'\\node ({name}) at ({x},{y}) {{${name}$}};' for name,(x,y) in zippedNodes)
|
||||||
|
|
||||||
|
if self.isUndirected():
|
||||||
|
edgeString = '\n'.join(f'\\draw ({x}) -- ({y});' for x,y in self.undirectedEdgeSet())
|
||||||
|
else:
|
||||||
|
edgeString = '\n'.join(
|
||||||
|
f'\\draw [-{{Latex[scale=1]}}, bend left=8] ({x}) to ({y});' if y != x and (y,x) in self.edges
|
||||||
|
else f'\\draw [-{{Latex[scale=1]}}] ({x}) to [{generateLoopInOutAngle(x, self.nodes)},looseness=8] ({y});' if x == y
|
||||||
|
else f'\\draw [-{{Latex[scale=1]}}] ({x}) to ({y});'
|
||||||
|
for x,y in self.edges
|
||||||
|
)
|
||||||
|
|
||||||
|
return (nodeString, edgeString)
|
||||||
|
|
||||||
|
def toLaTeXWithWeights(self, weights):
|
||||||
|
zippedNodes = zip(self.nodes, generateNodeCoords(len(self.nodes)))
|
||||||
|
nodeString = '\n'.join(f'\\node ({name}) at ({x},{y}) {{${name}$}};' for name,(x,y) in zippedNodes)
|
||||||
|
|
||||||
|
if self.isUndirected():
|
||||||
|
edgeString = '\n'.join(f'\\draw ({x}) -- ({y}) node [midway, above, sloped] (Tx{x+y}) {{{weights[x+y]}}};' for x,y in self.undirectedEdgeSet())
|
||||||
|
|
||||||
|
return (nodeString, edgeString)
|
||||||
|
|
||||||
|
|
||||||
|
def generateLoopInOutAngle(node, nodes):
|
||||||
|
baseAngle = 360 / len(nodes)
|
||||||
|
nodeNum = [i for i,n in enumerate(nodes) if n == node][0]
|
||||||
|
angle = nodeNum * baseAngle + 90
|
||||||
|
return f'out={angle + 15},in={angle - 15}'
|
||||||
|
|
||||||
|
|
||||||
|
def generateNodeCoords(n):
|
||||||
|
vectorLength = n / 2
|
||||||
|
degreeToTurn = (2 * pi) / n
|
||||||
|
|
||||||
|
|
||||||
|
nodeCoords = [(0, vectorLength)]
|
||||||
|
for node in range(n):
|
||||||
|
prev_x = nodeCoords[-1][0]
|
||||||
|
prev_y = nodeCoords[-1][1]
|
||||||
|
|
||||||
|
nodeCoords.append((
|
||||||
|
round(cos(degreeToTurn) * prev_x - sin(degreeToTurn) * prev_y, 5),
|
||||||
|
round(sin(degreeToTurn) * prev_x + cos(degreeToTurn) * prev_y, 5)
|
||||||
|
))
|
||||||
|
|
||||||
|
return nodeCoords
|
||||||
|
|
||||||
|
def extractWeights(string):
|
||||||
|
weights = dict()
|
||||||
|
lines = string.split('\n')
|
||||||
|
for i in range(4, len(lines)):
|
||||||
|
edge, weight = lines[i].split(' ')
|
||||||
|
weights[edge] = int(weight)
|
||||||
|
weights[edge[1] + edge[0]] = int(weight)
|
||||||
|
lines[i] = edge
|
||||||
|
return ('\n'.join(lines), weights)
|
||||||
|
|
||||||
|
def processFileContent(raw):
|
||||||
|
lines = raw.split('\n')
|
||||||
|
lines.pop(1)
|
||||||
|
outputType = lines.pop(0)
|
||||||
|
|
||||||
|
if lines[0] == 'kruskals':
|
||||||
|
lines[0] = 'undirected'
|
||||||
|
string, weights = extractWeights('\n'.join(lines))
|
||||||
|
graph1 = Graph.fromString(string)
|
||||||
|
graph2 = graph1.getKruskalsSpanningTree(weights)
|
||||||
|
return replaceContent(
|
||||||
|
(graph1.toLaTeXWithWeights(weights), graph2.toLaTeXWithWeights(weights)),
|
||||||
|
'Kruskals',
|
||||||
|
replaceF = lambda temp, cont:
|
||||||
|
temp.replace('%NODES1', cont[0][0])
|
||||||
|
.replace('%EDGES1', cont[0][1])
|
||||||
|
.replace('%NODES2', cont[1][0])
|
||||||
|
.replace('%EDGES2', cont[1][1])
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
graph = Graph.fromString('\n'.join(lines))
|
||||||
|
|
||||||
|
print(graph)
|
||||||
|
print(graph.toMatrix())
|
||||||
|
|
||||||
|
if outputType == 'toGraph':
|
||||||
|
content = graph.toLaTeX()
|
||||||
|
return replaceContent(
|
||||||
|
content,
|
||||||
|
'Graph',
|
||||||
|
replaceF = lambda temp, cont: temp.replace('%NODES', cont[0]).replace('%EDGES', cont[1])
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
content = graph.toMatrix().toLaTeX()
|
||||||
|
return replaceContent(content, 'Matrix')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
g = Graph.fromString('complete\n\n6')
|
||||||
|
print(g)
|
||||||
|
|
||||||
|
import random
|
||||||
|
|
||||||
|
d = dict()
|
||||||
|
for e in g.edges:
|
||||||
|
d[str(e)] = random.randint(0, 10)
|
||||||
|
|
||||||
|
print(g.getKruskalsSpanningTree(d))
|
|
@ -0,0 +1,46 @@
|
||||||
|
from itertools import combinations
|
||||||
|
|
||||||
|
def latexifyCondition(condition):
|
||||||
|
return condition[0] if condition[1] else f'\\overline{{{condition[0]}}}'
|
||||||
|
|
||||||
|
def latexify(listOfConditions): # [(str,bool)]
|
||||||
|
lines = []
|
||||||
|
for n in range(1, len(listOfConditions) + 1):
|
||||||
|
line = []
|
||||||
|
for x in combinations(listOfConditions, n):
|
||||||
|
line.append(''.join(latexifyCondition(c) for c in x))
|
||||||
|
lines.append(line)
|
||||||
|
|
||||||
|
linestrs = []
|
||||||
|
for line in lines:
|
||||||
|
linestr = ' + '.join(f'N({x})' for x in line)
|
||||||
|
if len(line) > 1:
|
||||||
|
linestr = f'\\left[ {linestr} \\right]'
|
||||||
|
linestrs.append(linestr)
|
||||||
|
|
||||||
|
b = False
|
||||||
|
result = '\\begin{align*}\nN'
|
||||||
|
for l in linestrs:
|
||||||
|
result += ' &+ ' if b else ' &- '
|
||||||
|
result += l + ' \\\\\n'
|
||||||
|
b = not b
|
||||||
|
result += '\\end{align*}'
|
||||||
|
return result
|
||||||
|
|
||||||
|
def parseInput(string):
|
||||||
|
result = []
|
||||||
|
for x in string.split(' '):
|
||||||
|
if x.startswith('!'):
|
||||||
|
result.append((x[1:], False))
|
||||||
|
else:
|
||||||
|
result.append((x, True))
|
||||||
|
return result
|
||||||
|
|
||||||
|
def processFileContent(raw):
|
||||||
|
listOfConditions = parseInput(raw)
|
||||||
|
content = latexify(listOfConditions)
|
||||||
|
return content
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
pass
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
from itertools import combinations
|
||||||
|
|
||||||
|
from common import replaceContent
|
||||||
|
|
||||||
|
class Set:
|
||||||
|
def __init__(self, elements):
|
||||||
|
self.elements = set(elements)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if len(self) == 0: return "\\emptyset"
|
||||||
|
return f"\\{{ {', '.join(sorted(self.elements))} \\}}"
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return list(sorted(self.elements))
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.elements)
|
||||||
|
|
||||||
|
def __gt__(self, value):
|
||||||
|
if len(self) != len(value):
|
||||||
|
return len(self) > len(value)
|
||||||
|
return self.elements > value.elements
|
||||||
|
|
||||||
|
def __ge__(self, value):
|
||||||
|
return self > value
|
||||||
|
|
||||||
|
def __lt__(self, value):
|
||||||
|
return not self > value
|
||||||
|
|
||||||
|
def __le__(self, value):
|
||||||
|
return self < value
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def fromString(cls, string):
|
||||||
|
return cls(string.split(' '))
|
||||||
|
|
||||||
|
def cardinality(self):
|
||||||
|
return len(self)
|
||||||
|
|
||||||
|
def powerset(self):
|
||||||
|
powerset = []
|
||||||
|
for i in range(len(self) + 1):
|
||||||
|
for subset in combinations(self.elements, i):
|
||||||
|
powerset.append(Set(list(subset)))
|
||||||
|
return Set(powerset)
|
||||||
|
|
||||||
|
def to_vertical_latex(self):
|
||||||
|
column = []
|
||||||
|
for e in sorted(self.elements):
|
||||||
|
column.append(str(e) + ' \\\\')
|
||||||
|
return '\\{\n' + '\n'.join(column) + '\n\\}'
|
||||||
|
|
||||||
|
|
||||||
|
def processFileContent(raw):
|
||||||
|
s = Set.fromString(raw)
|
||||||
|
content = s.powerset().to_vertical_latex()
|
||||||
|
|
||||||
|
return replaceContent(content, 'Powerset')
|
||||||
|
|
||||||
|
#TODO: make process input func
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print(Set(['a', 'b', 'c']).powerset().to_vertical_latex())
|
||||||
|
# print(a for a in Set(['A', 'B', 'C']).powerset())
|
|
@ -0,0 +1,26 @@
|
||||||
|
import tempfile
|
||||||
|
import subprocess
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from common import replaceContent
|
||||||
|
|
||||||
|
def makeTmpFile(content):
|
||||||
|
fd, path = tempfile.mkstemp()
|
||||||
|
while ('_' in path):
|
||||||
|
fd, path = tempfile.mkstemp()
|
||||||
|
with os.fdopen(fd, 'w') as tmp:
|
||||||
|
tmp.write(content)
|
||||||
|
return path
|
||||||
|
|
||||||
|
def grabOutput(path):
|
||||||
|
return subprocess.check_output(['python', path]).decode(sys.stdout.encoding)
|
||||||
|
|
||||||
|
def processFileContent(content):
|
||||||
|
path = makeTmpFile(content)
|
||||||
|
output = grabOutput(path)
|
||||||
|
return replaceContent(
|
||||||
|
(path, output),
|
||||||
|
'Python',
|
||||||
|
lambda temp, cont: temp.replace('%CODEFILE', cont[0]).replace('%OUTPUT', cont[1])
|
||||||
|
)
|
|
@ -0,0 +1,298 @@
|
||||||
|
from sys import argv
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from common import printc, printerr, replaceContent
|
||||||
|
import Graph
|
||||||
|
|
||||||
|
# Increase if hasse diagram becomes too clobbered
|
||||||
|
|
||||||
|
def pairToString(pair):
|
||||||
|
if str(pair[0]).isdigit() or str(pair[1]).isdigit():
|
||||||
|
return f'({pair[0]},{pair[1]})'
|
||||||
|
else:
|
||||||
|
return pair[0] + pair[1]
|
||||||
|
|
||||||
|
def stringToPair(string):
|
||||||
|
if string[0] == '(':
|
||||||
|
return tuple([string.split(',')[0][1:], string.split(',')[0][:-1]])
|
||||||
|
else:
|
||||||
|
return tuple(list(string))
|
||||||
|
|
||||||
|
def textLatex(string):
|
||||||
|
return '\\text{' + string + '}'
|
||||||
|
|
||||||
|
def mathModeListLatex(elements):
|
||||||
|
if len(elements) > 7 or len(elements) and max(len(str(e)) for e in elements) > 10:
|
||||||
|
return '\\begin{gather*}\n' \
|
||||||
|
+ ' \\\\\n'.join(elements) + '\n' \
|
||||||
|
+ '\\end{gather*}'
|
||||||
|
else:
|
||||||
|
return f'\\[ {", ".join(elements)} \\]'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Relation:
|
||||||
|
def __init__(self, pairs): # pair = (str,str)
|
||||||
|
self.pairs = set(pairs)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'\\{{ {", ".join(x + y for x,y in self.pairs)} \}}'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def fromString(cls, string):
|
||||||
|
relations = (stringToPair(x) for x in string.split(' '))
|
||||||
|
return cls(relations)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def fromDivisibilityPosetTo(cls, n):
|
||||||
|
pairs = set()
|
||||||
|
for dst in range(n):
|
||||||
|
pairs.add((dst, dst))
|
||||||
|
for src in range(1, dst):
|
||||||
|
if dst % src == 0:
|
||||||
|
pairs.add((src, dst))
|
||||||
|
return cls(pairs)
|
||||||
|
|
||||||
|
|
||||||
|
def isReflexive(self, verbose=False):
|
||||||
|
elements = set(list(sum(self.pairs, ())))
|
||||||
|
result = all((x,x) in self.pairs for x in elements)
|
||||||
|
|
||||||
|
if not result:
|
||||||
|
printc('Not reflexive, missing following pairs:', color='green')
|
||||||
|
missingPairs = [(x,x) for x in elements if (x,x) not in self.pairs]
|
||||||
|
print(f'\\[ {", ".join(pairToString(p) for p in missingPairs)} \\]')
|
||||||
|
if verbose:
|
||||||
|
return (False, missingPairs)
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
return (True, [(x,x) for x in elements if (x,x) in self.pairs])
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def isSymmetric(self, verbose=False):
|
||||||
|
result = all((y,x) in self.pairs for x,y in self.pairs)
|
||||||
|
|
||||||
|
if not result:
|
||||||
|
printc('Not symmetric, missing following pairs:', color='green')
|
||||||
|
missingPairs = [(x,y) for x,y in self.pairs if (y,x) not in self.pairs]
|
||||||
|
print(f'\\[ {", ".join(pairToString(p) for p in missingPairs)} \\]')
|
||||||
|
if verbose:
|
||||||
|
return (False, missingPairs)
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
return (True, [((x,y), (y,x)) for x,y in self.pairs if (y,x) in self.pairs and x < y])
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def isAntiSymmetric(self, verbose=False):
|
||||||
|
result = not any((y,x) in self.pairs and y != x for x,y in self.pairs)
|
||||||
|
|
||||||
|
if not result:
|
||||||
|
printc('Not antisymmetric, following pairs are symmetric:', color='green')
|
||||||
|
symmetricPairs = [((x,y), (y,x)) for x,y in self.pairs if (y,x) in self.pairs and y > x]
|
||||||
|
print(f'\\[ {", ".join(f"""{pairToString(p)}{textLatex(" and ")}{pairToString(q)}""" for p,q in symmetricPairs)} \\]')
|
||||||
|
if verbose:
|
||||||
|
return (False, symmetricPairs)
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
return (True, [])
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def isTransitive(self, verbose=False):
|
||||||
|
result = True
|
||||||
|
transitivePairs = []
|
||||||
|
nonTransitivePairs = []
|
||||||
|
|
||||||
|
for x,y in self.pairs:
|
||||||
|
for z,w in self.pairs:
|
||||||
|
if not (y != z or ((x,w) in self.pairs)):
|
||||||
|
nonTransitivePairs.append(((x,y), (z,w)))
|
||||||
|
result = False
|
||||||
|
elif (y == z and x != y != w and ((x,w) in self.pairs)):
|
||||||
|
transitivePairs.append(((x,y), (z,w)))
|
||||||
|
|
||||||
|
if not result:
|
||||||
|
printc('Not transitive, following pairs are missing its transitive counterpart:', color='green')
|
||||||
|
print(f'\\[ {", ".join(f"""{pairToString(p)}{textLatex(" and ")}{pairToString(q)}{textLatex(" without ")}{pairToString((p[0], q[1]))}""" for p,q in nonTransitivePairs)} \\]')
|
||||||
|
if verbose:
|
||||||
|
return (False, nonTransitivePairs)
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
return (True, transitivePairs)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def isEquivalenceRelation(self, verbose=False):
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
isReflexive, reflexivePairs = self.isReflexive(verbose=True)
|
||||||
|
isSymmetric, symmetricPairs = self.isSymmetric(verbose=True)
|
||||||
|
isTransitive, transitivePairs = self.isTransitive(verbose=True)
|
||||||
|
|
||||||
|
if not isReflexive:
|
||||||
|
return 'The relation is not an equivalence relation, because it is not reflexive.'
|
||||||
|
+ ' The following elements should be related:\n\n'
|
||||||
|
+ f'\\[ {", ".join(pairToString(p) for p in reflexivePairs)} \\]'
|
||||||
|
if not isSymmetric:
|
||||||
|
return 'The relation is not an equivalence relation, because it is not symmetric.'
|
||||||
|
+ ' It is missing the following symmetric pairs of relations\n\n'
|
||||||
|
+ f'\\[ {", ".join(f"""{pairToString(p)}{textLatex(" and ")}{pairToString(q)}""" for p,q in symmetricPairs)} \\]'
|
||||||
|
if not isTransitive:
|
||||||
|
return 'The relation is not an equivalence relation, because it is not transitive.'
|
||||||
|
+ ' The following pairs of relations are missing its transitive counterpart\n\n'
|
||||||
|
+ f'\\[ {", ".join(f"""{pairToString(p)}{textLatex(" and ")}{pairToString(q)}{textLatex(" without ")}{pairToString((p[0], q[1]))}""" for p,q in transitivePairs)} \\]'
|
||||||
|
|
||||||
|
|
||||||
|
rxStr = mathModeListLatex([pairToString(p) for p in reflexivePairs])
|
||||||
|
smStr = mathModeListLatex([f"""{pairToString(p)}{textLatex(" and ")}{pairToString(q)}""" for p,q in symmetricPairs])
|
||||||
|
trStr = mathModeListLatex([f"""{pairToString(p)}{textLatex(" and ")}{pairToString(q)}{textLatex(" with ")}{pairToString((p[0], q[1]))}""" for p,q in transitivePairs])
|
||||||
|
|
||||||
|
return replaceContent(
|
||||||
|
(rxStr, smStr, trStr),
|
||||||
|
'Relations/EquivalenceProof',
|
||||||
|
lambda temp, cont: temp.replace('%REFLEXIVE', cont[0]).replace('%SYMMETRIC', cont[1]).replace('%TRANSITIVE', cont[2])
|
||||||
|
)
|
||||||
|
|
||||||
|
return self.isReflexive() and self.isSymmetric() and self.isTransitive()
|
||||||
|
|
||||||
|
def isPartialOrder(self, verbose=False):
|
||||||
|
|
||||||
|
result = self.isReflexive() and self.isAntiSymmetric() and self.isTransitive()
|
||||||
|
|
||||||
|
if result:
|
||||||
|
hasse= self.getHassePairs(checkIfPartialOrder=False)
|
||||||
|
min_el = set(a for a,b in hasse if a not in list(zip(*hasse))[1])
|
||||||
|
printc(f"Minimal elements: $\{{ {', '.join(str(e) for e in min_el)} \}}$ \\\\")
|
||||||
|
|
||||||
|
max_el = set(v for k,v in hasse if v not in (x for x,_ in hasse))
|
||||||
|
printc(f"Maximal elements: $\{{ {', '.join(str(e) for e in max_el)} \}}$" )
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
isReflexive, reflexivePairs = self.isReflexive(verbose=True)
|
||||||
|
isAntiSymmetric, antiSymmetricPairs = self.isAntiSymmetric(verbose=True)
|
||||||
|
isTransitive, transitivePairs = self.isTransitive(verbose=True)
|
||||||
|
|
||||||
|
if not isReflexive:
|
||||||
|
return 'The relation is not a partial order, because it is not reflexive.'
|
||||||
|
+ ' The following elements should be related:\n\n'
|
||||||
|
+ f'\\[ {", ".join(pairToString(p) for p in reflexivePairs)} \\]'
|
||||||
|
if not isAntiSymmetric:
|
||||||
|
return 'The relation is not a partial order, because it is not antisymmetric.'
|
||||||
|
+ ' The following relations are symmetric\n\n'
|
||||||
|
+ f'\\[ {", ".join(f"""{pairToString(p)}{textLatex(" and ")}{pairToString(q)}""" for p,q in antiSymmetricPairs)} \\]'
|
||||||
|
if not isTransitive:
|
||||||
|
return 'The relation is not a partial order, because it is not transitive.'
|
||||||
|
+ ' The following pairs of relations are missing its transitive counterpart\n\n'
|
||||||
|
+ f'\\[ {", ".join(f"""{pairToString(p)}{textLatex(" and ")}{pairToString(q)}{textLatex(" without ")}{pairToString((p[0], q[1]))}""" for p,q in transitivePairs)} \\]'
|
||||||
|
|
||||||
|
rxStr = mathModeListLatex([pairToString(p) for p in reflexivePairs])
|
||||||
|
trStr = mathModeListLatex([f"""{pairToString(p)}{textLatex(" and ")}{pairToString(q)}{textLatex(" with ")}{pairToString((p[0], q[1]))}""" for p,q in transitivePairs])
|
||||||
|
|
||||||
|
return replaceContent(
|
||||||
|
(rxStr, trStr),
|
||||||
|
'Relations/PosetProof',
|
||||||
|
lambda temp, cont: temp.replace('%REFLEXIVE', cont[0]).replace('%TRANSITIVE', cont[1])
|
||||||
|
)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def getHassePairs(self, checkIfPartialOrder=True):
|
||||||
|
if checkIfPartialOrder and not self.isPartialOrder():
|
||||||
|
printerr('This is not a partial order')
|
||||||
|
return
|
||||||
|
|
||||||
|
nonReflexivePairs = set((x,y) for x,y in self.pairs if x != y)
|
||||||
|
|
||||||
|
hassePairs = set()
|
||||||
|
for x1, y1 in nonReflexivePairs:
|
||||||
|
for x2, y2 in nonReflexivePairs:
|
||||||
|
if y1 == x2:
|
||||||
|
hassePairs.add((x1, y2))
|
||||||
|
return nonReflexivePairs - hassePairs
|
||||||
|
|
||||||
|
def latexifyHasseDiagram(self):
|
||||||
|
hasse = self.getHassePairs()
|
||||||
|
keys = set(item for tup in hasse for item in tup)
|
||||||
|
y_pos = dict.fromkeys(keys, 0)
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
while len(next_row := [val for key,val in hasse if key in [x for x,y in y_pos.items() if y == i] ]) != 0:
|
||||||
|
for item in next_row:
|
||||||
|
y_pos[item] = i + 1
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
inv_ypos = dict()
|
||||||
|
for key in set(y_pos.values()):
|
||||||
|
inv_ypos[key] = [x for x,y in y_pos.items() if y == key]
|
||||||
|
|
||||||
|
output = []
|
||||||
|
|
||||||
|
for y in inv_ypos.keys():
|
||||||
|
for i, n in enumerate(inv_ypos[y]):
|
||||||
|
output.append(f'\\node ({n}) at ({i - len(inv_ypos[y])/2}, {y * 0.5 * (len(hasse) ** 0.4)}) {{${n}$}};')
|
||||||
|
|
||||||
|
output.append('')
|
||||||
|
|
||||||
|
for x,y in hasse:
|
||||||
|
output.append(f'\\draw ({x}) -- ({y});')
|
||||||
|
|
||||||
|
return '\n'.join(output)
|
||||||
|
|
||||||
|
def latexifyGraph(self):
|
||||||
|
if self.isEquivalenceRelation():
|
||||||
|
graphType = 'undirected'
|
||||||
|
pairs = [(x,y) for x,y in self.pairs if x != y]
|
||||||
|
else:
|
||||||
|
graphType = 'directed'
|
||||||
|
pairs = self.pairs
|
||||||
|
|
||||||
|
nodes = set()
|
||||||
|
for x,y in pairs:
|
||||||
|
nodes.add(x)
|
||||||
|
nodes.add(y)
|
||||||
|
|
||||||
|
edges = "\n".join(pairToString(p) for p in pairs)
|
||||||
|
|
||||||
|
processingString = f'toGraph\n\n{graphType}\n\n{ " ".join(nodes) }\n\n{edges}'
|
||||||
|
return Graph.processFileContent(processingString)
|
||||||
|
|
||||||
|
|
||||||
|
def processFileContent(raw):
|
||||||
|
outputType, inp = raw.split('\n\n')
|
||||||
|
|
||||||
|
if inp.startswith('divisibilityPosetTo'):
|
||||||
|
n = int(inp.split(' ')[1])
|
||||||
|
relation = Relation.fromDivisibilityPosetTo(n)
|
||||||
|
else:
|
||||||
|
relation = Relation.fromString(inp)
|
||||||
|
|
||||||
|
if outputType == 'proveEquivalence':
|
||||||
|
content = relation.isEquivalenceRelation(verbose=True)
|
||||||
|
return content
|
||||||
|
|
||||||
|
elif outputType == 'provePoset':
|
||||||
|
content = relation.isPartialOrder(verbose=True)
|
||||||
|
return content
|
||||||
|
|
||||||
|
elif outputType == 'hasseDiagram':
|
||||||
|
content = relation.latexifyHasseDiagram()
|
||||||
|
return replaceContent(content, 'Relations/Hasse')
|
||||||
|
|
||||||
|
elif outputType == 'graph':
|
||||||
|
content = relation.latexifyGraph()
|
||||||
|
return content
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
pass
|
||||||
|
relations = [(x,y) for x in range(-5, 5) for y in range(-5, 5)]
|
||||||
|
relations = [(chr(70+x), chr(70+y)) for x,y in relations if x*y >= 0]
|
||||||
|
for x in range(-5 ,5):
|
||||||
|
print(str(x) + ' - '+ chr(70 + x))
|
||||||
|
print(Relation(relations).isTransitive())
|
||||||
|
# inp = 'AA BB CC DD AB ACj
|
||||||
|
# relations = [stringToPair(p) for p in inp.split(' ')]
|
||||||
|
# # print(Relation(relations).isEquivalenceRelation())
|
||||||
|
# print(Relation(relations).isPartialOrder())
|
||||||
|
# print(Relation.fromDivisibilityPosetTo(30).isPartialOrder())
|
|
@ -0,0 +1,111 @@
|
||||||
|
from sys import argv
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from common import printerr, replaceContent
|
||||||
|
|
||||||
|
try:
|
||||||
|
from tabulate import tabulate
|
||||||
|
except:
|
||||||
|
printerr('Couldn\'t find tabulate. Do you have it installed?')
|
||||||
|
|
||||||
|
|
||||||
|
def parseExpressionList(inputData):
|
||||||
|
return [e.strip() for e in inputData.split(',')]
|
||||||
|
|
||||||
|
|
||||||
|
class OverloadedBool:
|
||||||
|
"""Overloads the bool in order to make Implies and Iff functions"""
|
||||||
|
|
||||||
|
def __init__(self, val):
|
||||||
|
self.val = val
|
||||||
|
|
||||||
|
def __bool__(self):
|
||||||
|
val = self.val
|
||||||
|
while(type(val) is OverloadedBool):
|
||||||
|
val = val.val
|
||||||
|
return val
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self.val)
|
||||||
|
|
||||||
|
def __add__(self, bool2):
|
||||||
|
""" Implies """
|
||||||
|
return OverloadedBool(not self.val or bool2)
|
||||||
|
|
||||||
|
def __sub__(self, bool2):
|
||||||
|
""" Iff """
|
||||||
|
return OverloadedBool((not self.val or bool2) and (not bool2 or self.val))
|
||||||
|
|
||||||
|
def flattenImpliesIff(exps):
|
||||||
|
return [exp.replace('implies', '+').replace('iff', '-').replace('E', '') for exp in exps]
|
||||||
|
|
||||||
|
def generateTruthTable(exps):
|
||||||
|
|
||||||
|
exps = flattenImpliesIff(exps)
|
||||||
|
|
||||||
|
boolvars = [e for e in exps if len(e) == 1]
|
||||||
|
|
||||||
|
truthtable = []
|
||||||
|
|
||||||
|
for x in reversed(range(2 ** len(boolvars))):
|
||||||
|
for i,digit in enumerate('{0:b}'.format(x).zfill(len(boolvars))):
|
||||||
|
exec(f'{boolvars[i]} = OverloadedBool({digit == "1"})', globals())
|
||||||
|
|
||||||
|
def calculateGridLine():
|
||||||
|
line = []
|
||||||
|
for exp in exps:
|
||||||
|
exec(f'line.append(({exp}))')
|
||||||
|
return line
|
||||||
|
|
||||||
|
truthtable.append(calculateGridLine())
|
||||||
|
|
||||||
|
return truthtable
|
||||||
|
|
||||||
|
|
||||||
|
def latexify(exps, truthtable):
|
||||||
|
|
||||||
|
latex_expressions = \
|
||||||
|
[ (
|
||||||
|
'E' in exp,
|
||||||
|
exp
|
||||||
|
.replace('not', '\\neg')
|
||||||
|
.replace('and', '\\wedge')
|
||||||
|
.replace('or', '\\vee')
|
||||||
|
.replace('implies', '\\Rightarrow')
|
||||||
|
.replace('iff', '\\Leftrightarrow')
|
||||||
|
.replace('E', ''
|
||||||
|
.strip())
|
||||||
|
)
|
||||||
|
for exp in exps]
|
||||||
|
|
||||||
|
return \
|
||||||
|
"""
|
||||||
|
\\begin{{truthtable}}
|
||||||
|
{{{}}}
|
||||||
|
{{{}}}
|
||||||
|
{}
|
||||||
|
\\end{{truthtable}}
|
||||||
|
""".format(
|
||||||
|
'|'.join('e' if e else 'c' for e,_ in latex_expressions),
|
||||||
|
' & '.join(f'${exp}$' for _,exp in latex_expressions),
|
||||||
|
'\n'.join(' ' + ' & '.join('\\T' if b else '\\F' for b in line) + ' \\\\' for line in truthtable)
|
||||||
|
)
|
||||||
|
|
||||||
|
def printTruthtable(exps, truthtable):
|
||||||
|
stringTable = [ ['\033[32mT\033[0m ' if b else '\033[31mF\033[0m' for b in line] for line in truthtable]
|
||||||
|
try:
|
||||||
|
print(tabulate(stringTable, headers=exps))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def processFileContent(raw):
|
||||||
|
exps = parseExpressionList(raw)
|
||||||
|
truthtable = generateTruthTable(exps)
|
||||||
|
|
||||||
|
printTruthtable(exps, generateTruthTable(exps))
|
||||||
|
|
||||||
|
content = latexify(exps, truthtable)
|
||||||
|
return replaceContent(content, 'Truthtable')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
pass
|
|
@ -0,0 +1,21 @@
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
clear = '\033[0m'
|
||||||
|
colors = {
|
||||||
|
'red': '\033[31m',
|
||||||
|
'green': '\033[32m',
|
||||||
|
'yellow': '\033[33m',
|
||||||
|
'blue': '\033[34m',
|
||||||
|
'purple': '\033[35m',
|
||||||
|
'cyan': '\033[36m',
|
||||||
|
}
|
||||||
|
|
||||||
|
def printc(text, color='blue'):
|
||||||
|
print(f'{colors[color]}{text}{clear}')
|
||||||
|
|
||||||
|
def printerr(text):
|
||||||
|
print(f'\033[31;5m[ERROR] {text}{clear}')
|
||||||
|
|
||||||
|
def replaceContent(content, template, replaceF = lambda temp, cont: temp.replace("%CONTENT", cont)):
|
||||||
|
with open(str(Path(__file__).parent.absolute()) + f'/tex_templates/{template}.tex') as template:
|
||||||
|
return replaceF(template.read(), content)
|
|
@ -0,0 +1,48 @@
|
||||||
|
from sys import argv
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import FSA
|
||||||
|
import Graph
|
||||||
|
import Truthtable
|
||||||
|
import Relations
|
||||||
|
import InclusionExclusion
|
||||||
|
import Python
|
||||||
|
|
||||||
|
from common import printerr
|
||||||
|
|
||||||
|
def fetchContentType(content):
|
||||||
|
new_content = content.split('\n')
|
||||||
|
contentType = new_content.pop(0)[2:]
|
||||||
|
return (contentType, '\n'.join(new_content))
|
||||||
|
|
||||||
|
def processContent(content):
|
||||||
|
contentType, content = fetchContentType(content)
|
||||||
|
|
||||||
|
if contentType == 'FSA':
|
||||||
|
result = FSA.processFileContent(content)
|
||||||
|
elif contentType == 'Graph':
|
||||||
|
result = Graph.processFileContent('toGraph\n\n' + content)
|
||||||
|
elif contentType == 'Matrix':
|
||||||
|
result = Graph.processFileContent('toMatrix\n\n' + content)
|
||||||
|
elif contentType == 'Relations':
|
||||||
|
result = Relations.processFileContent(content)
|
||||||
|
elif contentType == 'Truthtable':
|
||||||
|
result = Truthtable.processFileContent(content)
|
||||||
|
elif contentType == 'InclusionExclusion':
|
||||||
|
result = InclusionExclusion.processFileContent(content)
|
||||||
|
elif contentType == 'Python':
|
||||||
|
result = Python.processFileContent(content)
|
||||||
|
else:
|
||||||
|
printerr('DIDN\'T RECOGNIZE FILE TYPE')
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
filename = argv[1]
|
||||||
|
|
||||||
|
with open(filename) as file:
|
||||||
|
content = processContent(file.read())
|
||||||
|
|
||||||
|
with open(argv[2], 'w') as destination_file:
|
||||||
|
destination_file.write(content)
|
|
@ -0,0 +1,12 @@
|
||||||
|
\begin{tikzpicture}
|
||||||
|
\tikzset{
|
||||||
|
->, % makes the edges directed
|
||||||
|
>=Stealth, % makes the arrow heads bold
|
||||||
|
node distance=5cm, % specifies the minimum distance between two nodes. Change if necessary.
|
||||||
|
every state/.style={thick, fill=white}, % sets the properties for each ’state’ node
|
||||||
|
initial text=$ $, % sets the text that appears on the start arrow
|
||||||
|
}
|
||||||
|
|
||||||
|
%CONTENT
|
||||||
|
|
||||||
|
\end{tikzpicture}
|
|
@ -0,0 +1,13 @@
|
||||||
|
\newcommand{\arrow}[2]{\path [-{Latex[scale=1]}] (#1) edge (#2);}
|
||||||
|
|
||||||
|
\begin{tikzpicture}
|
||||||
|
|
||||||
|
\begin{scope}[every node/.style={shape=circle, fill=white, draw, inner sep=2pt}]
|
||||||
|
%NODES
|
||||||
|
\end{scope}
|
||||||
|
|
||||||
|
\begin{scope}[every draw/.style={}]
|
||||||
|
%EDGES
|
||||||
|
\end{scope}
|
||||||
|
|
||||||
|
\end{tikzpicture}
|
|
@ -0,0 +1,37 @@
|
||||||
|
\begin{mgraphbox}[width=\linewidth]
|
||||||
|
\begin{figure}[H]
|
||||||
|
\begin{center}
|
||||||
|
\begin{tikzpicture}
|
||||||
|
|
||||||
|
\begin{scope}[every node/.style={shape=circle, fill=white, draw, inner sep=2pt}]
|
||||||
|
%NODES1
|
||||||
|
\end{scope}
|
||||||
|
|
||||||
|
\begin{scope}[every draw/.style={}]
|
||||||
|
%EDGES1
|
||||||
|
\end{scope}
|
||||||
|
|
||||||
|
\end{tikzpicture}
|
||||||
|
\end{center}
|
||||||
|
\end{figure}
|
||||||
|
\end{mgraphbox}
|
||||||
|
|
||||||
|
Minimal spanning tree:
|
||||||
|
|
||||||
|
\begin{mgraphbox}[width=\linewidth]
|
||||||
|
\begin{figure}[H]
|
||||||
|
\begin{center}
|
||||||
|
\begin{tikzpicture}
|
||||||
|
|
||||||
|
\begin{scope}[every node/.style={shape=circle, fill=white, draw, inner sep=2pt}]
|
||||||
|
%NODES2
|
||||||
|
\end{scope}
|
||||||
|
|
||||||
|
\begin{scope}[every draw/.style={}]
|
||||||
|
%EDGES2
|
||||||
|
\end{scope}
|
||||||
|
|
||||||
|
\end{tikzpicture}
|
||||||
|
\end{center}
|
||||||
|
\end{figure}
|
||||||
|
\end{mgraphbox}
|
|
@ -0,0 +1,5 @@
|
||||||
|
\begin{figure}[H]
|
||||||
|
\[
|
||||||
|
%CONTENT
|
||||||
|
\]
|
||||||
|
\end{figure}
|
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
\codeFile{%CODEFILE}{python}
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
\begin{lstlisting}[breaklines=true, basicstyle=\small]
|
||||||
|
%OUTPUT
|
||||||
|
\end{lstlisting}
|
|
@ -0,0 +1,22 @@
|
||||||
|
|
||||||
|
In order for this relation to be an equivalence equation, it has to be reflexive, symmetric and transitive.
|
||||||
|
|
||||||
|
\textbf{Reflexive:}
|
||||||
|
|
||||||
|
All elements are related to themself
|
||||||
|
|
||||||
|
%REFLEXIVE
|
||||||
|
|
||||||
|
\textbf{Symmetric:}
|
||||||
|
|
||||||
|
All relations has its symmetric counterpart
|
||||||
|
|
||||||
|
%SYMMETRIC
|
||||||
|
|
||||||
|
\textbf{Transitive:}
|
||||||
|
|
||||||
|
All pair of relations where $xRy$ and $yRz$ has its transitive counterpart
|
||||||
|
|
||||||
|
%TRANSITIVE
|
||||||
|
|
||||||
|
Hence the relation is an equivalence relation
|
|
@ -0,0 +1,6 @@
|
||||||
|
\begin{tikzpicture}
|
||||||
|
\tikzset{every node/.style={shape=circle,draw,fill=white,inner sep=2pt}}
|
||||||
|
|
||||||
|
%CONTENT
|
||||||
|
|
||||||
|
\end{tikzpicture}
|
|
@ -0,0 +1,22 @@
|
||||||
|
|
||||||
|
In order for this relation to be a partial order, it has to be reflexive, antisymmetric and transitive.
|
||||||
|
|
||||||
|
\textbf{Reflexive:}
|
||||||
|
|
||||||
|
All elements are related to themself
|
||||||
|
|
||||||
|
%REFLEXIVE
|
||||||
|
|
||||||
|
\textbf{Antisymmetric:}
|
||||||
|
|
||||||
|
No relation have a symmetric counterpart \\
|
||||||
|
|
||||||
|
(Listing the ones that don't have a symmetric counterpart would just be listing the whole set) \\
|
||||||
|
|
||||||
|
\textbf{Transitive:}
|
||||||
|
|
||||||
|
All pair of relations where $xRy$ and $yRz$ has its transitive counterpart
|
||||||
|
|
||||||
|
%TRANSITIVE
|
||||||
|
|
||||||
|
Hence the relation is a partial order
|
|
@ -0,0 +1 @@
|
||||||
|
%CONTENT
|
Loading…
Reference in New Issue