Add exam
This commit is contained in:
parent
dcdd3e78e5
commit
b06a6e58f9
277
exam/.vscode/latex.code-snippets
vendored
Normal file
277
exam/.vscode/latex.code-snippets
vendored
Normal file
@ -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",
|
||||
},
|
||||
|
||||
}
|
16
exam/.vscode/makefile.code-snippets
vendored
Normal file
16
exam/.vscode/makefile.code-snippets
vendored
Normal file
@ -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",
|
||||
}
|
||||
}
|
15
exam/Makefile
Normal file
15
exam/Makefile
Normal file
@ -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
|
24
exam/graphics/14.tex
Normal file
24
exam/graphics/14.tex
Normal file
@ -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}
|
24
exam/graphics/14mod.tex
Normal file
24
exam/graphics/14mod.tex
Normal file
@ -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}
|
22
exam/graphics/16.tex
Normal file
22
exam/graphics/16.tex
Normal file
@ -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}
|
37
exam/graphics/17.tex
Normal file
37
exam/graphics/17.tex
Normal file
@ -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}
|
31
exam/graphics/17_2.tex
Normal file
31
exam/graphics/17_2.tex
Normal file
@ -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}
|
10
exam/graphics/3.tex
Normal file
10
exam/graphics/3.tex
Normal file
@ -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}
|
||||
|
27
exam/graphics/5.tex
Normal file
27
exam/graphics/5.tex
Normal file
@ -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
|
15
exam/graphics/6.tex
Normal file
15
exam/graphics/6.tex
Normal file
@ -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}
|
14
exam/graphics/src/14.txt
Normal file
14
exam/graphics/src/14.txt
Normal file
@ -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
|
8
exam/graphics/src/16.txt
Normal file
8
exam/graphics/src/16.txt
Normal file
@ -0,0 +1,8 @@
|
||||
# Graph
|
||||
matrix
|
||||
|
||||
01101
|
||||
10011
|
||||
10000
|
||||
01001
|
||||
11010
|
2
exam/graphics/src/3.txt
Normal file
2
exam/graphics/src/3.txt
Normal file
@ -0,0 +1,2 @@
|
||||
# Truthtable
|
||||
p, q, E not p, p and q, E not (p and q)
|
4
exam/graphics/src/5.txt
Normal file
4
exam/graphics/src/5.txt
Normal file
@ -0,0 +1,4 @@
|
||||
# Relations
|
||||
proveEquivalence
|
||||
|
||||
AA BB CC CD DD DC
|
7
exam/graphics/src/genDivPoset.py
Normal file
7
exam/graphics/src/genDivPoset.py
Normal file
@ -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))
|
348
exam/main.tex
Normal file
348
exam/main.tex
Normal file
@ -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}
|
80
exam/python/FSA.py
Normal file
80
exam/python/FSA.py
Normal file
@ -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))
|
261
exam/python/Graph.py
Normal file
261
exam/python/Graph.py
Normal file
@ -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))
|
46
exam/python/InclusionExclusion.py
Normal file
46
exam/python/InclusionExclusion.py
Normal file
@ -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
|
||||
|
64
exam/python/Powerset.py
Normal file
64
exam/python/Powerset.py
Normal file
@ -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())
|
26
exam/python/Python.py
Normal file
26
exam/python/Python.py
Normal file
@ -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])
|
||||
)
|
298
exam/python/Relations.py
Normal file
298
exam/python/Relations.py
Normal file
@ -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())
|
111
exam/python/Truthtable.py
Normal file
111
exam/python/Truthtable.py
Normal file
@ -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
|
21
exam/python/common.py
Normal file
21
exam/python/common.py
Normal file
@ -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)
|
48
exam/python/run.py
Normal file
48
exam/python/run.py
Normal file
@ -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)
|
12
exam/python/tex_templates/FSA.tex
Normal file
12
exam/python/tex_templates/FSA.tex
Normal file
@ -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}
|
13
exam/python/tex_templates/Graph.tex
Normal file
13
exam/python/tex_templates/Graph.tex
Normal file
@ -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}
|
37
exam/python/tex_templates/Kruskals.tex
Normal file
37
exam/python/tex_templates/Kruskals.tex
Normal file
@ -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}
|
5
exam/python/tex_templates/Matrix.tex
Normal file
5
exam/python/tex_templates/Matrix.tex
Normal file
@ -0,0 +1,5 @@
|
||||
\begin{figure}[H]
|
||||
\[
|
||||
%CONTENT
|
||||
\]
|
||||
\end{figure}
|
0
exam/python/tex_templates/Powerset.tex
Normal file
0
exam/python/tex_templates/Powerset.tex
Normal file
8
exam/python/tex_templates/Python.tex
Normal file
8
exam/python/tex_templates/Python.tex
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
\codeFile{%CODEFILE}{python}
|
||||
|
||||
Output:
|
||||
|
||||
\begin{lstlisting}[breaklines=true, basicstyle=\small]
|
||||
%OUTPUT
|
||||
\end{lstlisting}
|
22
exam/python/tex_templates/Relations/EquivalenceProof.tex
Normal file
22
exam/python/tex_templates/Relations/EquivalenceProof.tex
Normal file
@ -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
|
6
exam/python/tex_templates/Relations/Hasse.tex
Normal file
6
exam/python/tex_templates/Relations/Hasse.tex
Normal file
@ -0,0 +1,6 @@
|
||||
\begin{tikzpicture}
|
||||
\tikzset{every node/.style={shape=circle,draw,fill=white,inner sep=2pt}}
|
||||
|
||||
%CONTENT
|
||||
|
||||
\end{tikzpicture}
|
22
exam/python/tex_templates/Relations/PosetProof.tex
Normal file
22
exam/python/tex_templates/Relations/PosetProof.tex
Normal file
@ -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
|
1
exam/python/tex_templates/Truthtable.tex
Normal file
1
exam/python/tex_templates/Truthtable.tex
Normal file
@ -0,0 +1 @@
|
||||
%CONTENT
|
Loading…
Reference in New Issue
Block a user