diff --git a/README.md b/README.md index 9c1a00b..4ecb477 100644 --- a/README.md +++ b/README.md @@ -168,7 +168,7 @@ See examples of what the engine for the exam template can do here: [exam_templat - [X] Output a graph to a matrix - [X] Draw an undirected graph - [X] Draw a directed graph - - [ ] Find a minimal spanning tree with Kruskals algorithm + - [X] Find a minimal spanning tree with Kruskals algorithm #### Chapter 8. Finite state automata diff --git a/exam_template/python/Graph.py b/exam_template/python/Graph.py index f965c64..4f9647c 100644 --- a/exam_template/python/Graph.py +++ b/exam_template/python/Graph.py @@ -68,7 +68,7 @@ class Graph: 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() @@ -136,12 +136,14 @@ class Graph: 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[str(e)]) ] + 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) @@ -161,6 +163,15 @@ class Graph: 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) @@ -186,11 +197,37 @@ def generateNodeCoords(n): 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) @@ -207,11 +244,14 @@ def processFileContent(raw): content = graph.toMatrix().toLaTeX() return replaceContent(content, 'Matrix') - - if __name__ == '__main__': - pass - # matrix = Matrix([[False, False, True], [True, False, True], [True, False, False]]) - # print(matrix) - # print(matrix.toGraph()) - # print(matrix.toGraph().isUndirected()) \ No newline at end of file + 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)) \ No newline at end of file diff --git a/exam_template/python/tex_templates/Kruskals.tex b/exam_template/python/tex_templates/Kruskals.tex new file mode 100644 index 0000000..f06b504 --- /dev/null +++ b/exam_template/python/tex_templates/Kruskals.tex @@ -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} \ No newline at end of file diff --git a/exam_template_graphics/graphics/kruskals.tex b/exam_template_graphics/graphics/kruskals.tex new file mode 100644 index 0000000..7f0b726 --- /dev/null +++ b/exam_template_graphics/graphics/kruskals.tex @@ -0,0 +1,67 @@ +\begin{mgraphbox}[width=\linewidth] + \begin{figure}[H] + \begin{center} + \begin{tikzpicture} + + \begin{scope}[every node/.style={shape=circle, fill=white, draw, inner sep=2pt}] + \node (A) at (0,4.0) {$A$}; +\node (B) at (-2.82843,2.82843) {$B$}; +\node (C) at (-4.0,0.0) {$C$}; +\node (D) at (-2.82843,-2.82843) {$D$}; +\node (E) at (-0.0,-4.0) {$E$}; +\node (F) at (2.82843,-2.82843) {$F$}; +\node (G) at (4.0,-0.0) {$G$}; +\node (H) at (2.82843,2.82843) {$H$}; + \end{scope} + + \begin{scope}[every draw/.style={}] + \draw (A) -- (B) node [midway, above, sloped] (TxAB) {1}; +\draw (A) -- (C) node [midway, above, sloped] (TxAC) {2}; +\draw (A) -- (H) node [midway, above, sloped] (TxAH) {11}; +\draw (B) -- (C) node [midway, above, sloped] (TxBC) {7}; +\draw (B) -- (F) node [midway, above, sloped] (TxBF) {12}; +\draw (C) -- (D) node [midway, above, sloped] (TxCD) {3}; +\draw (C) -- (H) node [midway, above, sloped] (TxCH) {14}; +\draw (D) -- (E) node [midway, above, sloped] (TxDE) {9}; +\draw (D) -- (F) node [midway, above, sloped] (TxDF) {6}; +\draw (D) -- (G) node [midway, above, sloped] (TxDG) {10}; +\draw (F) -- (G) node [midway, above, sloped] (TxFG) {8}; + \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}] + \node (A) at (0,4.0) {$A$}; +\node (B) at (-2.82843,2.82843) {$B$}; +\node (C) at (-4.0,0.0) {$C$}; +\node (D) at (-2.82843,-2.82843) {$D$}; +\node (E) at (-0.0,-4.0) {$E$}; +\node (F) at (2.82843,-2.82843) {$F$}; +\node (G) at (4.0,-0.0) {$G$}; +\node (H) at (2.82843,2.82843) {$H$}; + \end{scope} + + \begin{scope}[every draw/.style={}] + \draw (A) -- (B) node [midway, above, sloped] (TxAB) {1}; +\draw (A) -- (C) node [midway, above, sloped] (TxAC) {2}; +\draw (A) -- (H) node [midway, above, sloped] (TxAH) {11}; +\draw (C) -- (D) node [midway, above, sloped] (TxCD) {3}; +\draw (D) -- (E) node [midway, above, sloped] (TxDE) {9}; +\draw (D) -- (F) node [midway, above, sloped] (TxDF) {6}; +\draw (F) -- (G) node [midway, above, sloped] (TxFG) {8}; + \end{scope} + + \end{tikzpicture} + \end{center} + \end{figure} +\end{mgraphbox} \ No newline at end of file diff --git a/exam_template_graphics/graphics/src/kruskals.txt b/exam_template_graphics/graphics/src/kruskals.txt new file mode 100644 index 0000000..7eb1532 --- /dev/null +++ b/exam_template_graphics/graphics/src/kruskals.txt @@ -0,0 +1,19 @@ +# Graph +kruskals + +A B C D E F G H + +AB 1 +AC 2 +CD 3 +DE 4 +HA 5 +FD 6 +CB 7 +FG 8 +DE 9 +DG 10 +AH 11 +FB 12 +HC 13 +CH 14 \ No newline at end of file diff --git a/exam_template_graphics/main.tex b/exam_template_graphics/main.tex index 422b1a4..b231b60 100644 --- a/exam_template_graphics/main.tex +++ b/exam_template_graphics/main.tex @@ -95,6 +95,8 @@ \verbatimInput{undirectedGraphToMatrix} \verbatimDiagram{directedFromMatrix} + + \verbatimInput{kruskals} \section{Finite state automata} diff --git a/exam_template_graphics/main.toc b/exam_template_graphics/main.toc index 1cd7947..e9ba39f 100644 --- a/exam_template_graphics/main.toc +++ b/exam_template_graphics/main.toc @@ -17,7 +17,8 @@ \contentsline {subsection}{\numberline {5.4}adjacency}{12}{subsection.5.4}% \contentsline {subsection}{\numberline {5.5}undirectedGraphToMatrix}{13}{subsection.5.5}% \contentsline {subsection}{\numberline {5.6}directedFromMatrix}{14}{subsection.5.6}% -\contentsline {section}{\numberline {6}Finite state automata}{15}{section.6}% -\contentsline {subsection}{\numberline {6.1}automata}{15}{subsection.6.1}% -\contentsline {section}{\numberline {7}Raw python}{16}{section.7}% -\contentsline {subsection}{\numberline {7.1}python}{16}{subsection.7.1}% +\contentsline {subsection}{\numberline {5.7}kruskals}{15}{subsection.5.7}% +\contentsline {section}{\numberline {6}Finite state automata}{17}{section.6}% +\contentsline {subsection}{\numberline {6.1}automata}{17}{subsection.6.1}% +\contentsline {section}{\numberline {7}Raw python}{18}{section.7}% +\contentsline {subsection}{\numberline {7.1}python}{18}{subsection.7.1}%