2
0
Fork 0
mirror of https://github.com/MartinThoma/LaTeX-examples.git synced 2025-04-19 11:38:05 +02:00

added another document example

This commit is contained in:
Martin Thoma 2012-08-13 22:16:50 +02:00
parent cec677bc0e
commit 8deee55362
6 changed files with 522 additions and 0 deletions

View file

@ -0,0 +1,107 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
""" Dieses Script berechnet die Länge aller möglichen Routen und speichert sie
in "Entfernungen.txt".
Am Ende wird noch die optimale Route ausgegeben.
Benötigte Rechenzeit: ca. 50s """
from copy import deepcopy
# http://blog.bjrn.se/2008/04/lexicographic-permutations-using.html
def next_permutation(seq, pred=cmp):
"""Like C++ std::next_permutation() but implemented as
generator. Yields copies of seq."""
def reverse(seq, start, end):
# seq = seq[:start] + reversed(seq[start:end]) + \
# seq[end:]
end -= 1
if end <= start:
return
while True:
seq[start], seq[end] = seq[end], seq[start]
if start == end or start+1 == end:
return
start += 1
end -= 1
if not seq:
raise StopIteration
try:
seq[0]
except TypeError:
raise TypeError("seq must allow random access.")
first = 0
last = len(seq)
seq = seq[:]
# Yield input sequence as the STL version is often
# used inside do {} while.
yield seq
if last == 1:
raise StopIteration
while True:
next = last - 1
while True:
# Step 1.
next1 = next
next -= 1
if pred(seq[next], seq[next1]) < 0:
# Step 2.
mid = last - 1
while not (pred(seq[next], seq[mid]) < 0):
mid -= 1
seq[next], seq[mid] = seq[mid], seq[next]
# Step 3.
reverse(seq, next1, last)
# Change to yield references to get rid of
# (at worst) |seq|! copy operations.
yield seq[:]
break
if next == first:
raise StopIteration
raise StopIteration
def Strecke_der_Route(Entfernungen, route):
""" Bestimmt die länge der Route und gibt diese als int zurück """
Entfernung = 0
for step, index in enumerate(route):
index2 = route[(step+1)%len(Entfernungen)]
Entfernung += Entfernungen[index][index2] # von index nach index2
return Entfernung
def optimal_solution_with_brute_force(Entfernungen):
""" Findet die optimale Lösung, indem alle Routen durchgegangen werden.
Zurückgegeben wird eine Liste mit den Indizes """
liste = [i for i in xrange(0, len(Entfernungen))]
min_Entfernung_Route = [i for i in xrange(0, len(Entfernungen))]
min_Entfernung = Strecke_der_Route(Entfernungen, min_Entfernung_Route)
f = open('/home/moose/Entfernungen.txt', 'w')
for route in next_permutation(liste):
entfernung_tmp = Strecke_der_Route(Entfernungen, route)
f.write(str(entfernung_tmp) + "\n")
if entfernung_tmp < min_Entfernung:
min_Entfernung = entfernung_tmp
min_Entfernung_Route = deepcopy(route)
f.close()
return min_Entfernung_Route
Stadtliste = ['Berlin', 'Hamburg', 'München', 'Köln', 'Frankfurt a. M.',
'Stuttgart', 'Düsseldorf', 'Dortmund', 'Essen', 'Bremen']
Entfernungen = []
Entfernungen.append([ 0, 288, 585, 575, 547, 633, 559, 494, 531, 392])
Entfernungen.append([289, 0, 775, 426, 493, 655, 400, 344, 365, 122])
Entfernungen.append([589, 775, 0, 577, 398, 220, 612, 604, 634, 748])
Entfernungen.append([579, 426, 576, 0, 193, 369, 42, 95, 73, 320])
Entfernungen.append([552, 492, 393, 193, 0, 210, 229, 219, 251, 445])
Entfernungen.append([637, 667, 231, 369, 203, 0, 404, 417, 426, 642])
Entfernungen.append([563, 408, 611, 38, 228, 404, 0, 71, 37, 302])
Entfernungen.append([498, 346, 605, 95, 221, 418, 69, 0, 36, 240])
Entfernungen.append([536, 374, 634, 74, 252, 427, 35, 37, 0, 267])
Entfernungen.append([397, 123, 748, 315, 441, 638, 289, 233, 254, 0])
print("Berechnung aller Routen wurde begonnen.")
route = optimal_solution_with_brute_force(Entfernungen)
print("Berechnung aller Routen wurde abgeschlossen.")
print("Länge der optimalen Route: ", Strecke_der_Route(Entfernungen, route))
for index in route:
print(Stadtliste[index])

View file

@ -0,0 +1,59 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
from copy import deepcopy
def compute_length(Entfernungen, route):
""" Berechnet die Länge der Route und gibt diesen Integer zurück. """
entfernung = 0
for i in xrange(0, len(route)-1):
entfernung += Entfernungen[route[i]][route[i+1]]
return entfernung
def nearest_insertion(Entfernungen):
""" Entfernungen: Entfernungen[x][y] gibt die Länge der Strecke von x nach
y als integer an.
return: route als Liste, z.B. [0,3,4,1,2]
Es wird immer mit der Stadt 0 begonnen. """
route = [0]
cities = len(Entfernungen)
maxEntfernung = max([item for sublist in Entfernungen for item in sublist])
aktuelleCity = 0
Entfernungen_read = deepcopy(Entfernungen)
for i in xrange(0, cities):
for sublist in Entfernungen:
sublist[aktuelleCity] = maxEntfernung + 1
aktuelleCity = Entfernungen[aktuelleCity].index( min(Entfernungen[aktuelleCity]) )
minInsert = None
routenLaenge = len(route)*(maxEntfernung+1)
for insertIndex in xrange(0, len(route) ):
route_tmp = deepcopy(route)
route_tmp.insert(insertIndex, aktuelleCity)
if compute_length(Entfernungen_read, route_tmp) < routenLaenge:
routenLaenge = compute_length(Entfernungen_read, route_tmp)
minInsert = insertIndex
route.insert(minInsert, aktuelleCity)
routenLaenge+= Entfernungen[route[-1]][aktuelleCity]
#Drehen der Route, sodass Berlin am Anfang und am Ende steht
route = route[route.index(0)+1:] + route[0:route.index(0)+1]
print("Routenlänge: %i" % compute_length(Entfernungen_read, route))
return route
Entfernungen = []
Entfernungen.append([ 0, 288, 585, 575, 547, 633, 559, 494, 531, 392])
Entfernungen.append([289, 0, 775, 426, 493, 655, 400, 344, 365, 122])
Entfernungen.append([589, 775, 0, 577, 398, 220, 612, 604, 634, 748])
Entfernungen.append([579, 426, 576, 0, 193, 369, 42, 95, 73, 320])
Entfernungen.append([552, 492, 393, 193, 0, 210, 229, 219, 251, 445])
Entfernungen.append([637, 667, 231, 369, 203, 0, 404, 417, 426, 642])
Entfernungen.append([563, 408, 611, 38, 228, 404, 0, 71, 37, 302])
Entfernungen.append([498, 346, 605, 95, 221, 418, 69, 0, 36, 240])
Entfernungen.append([536, 374, 634, 74, 252, 427, 35, 37, 0, 267])
Entfernungen.append([397, 123, 748, 315, 441, 638, 289, 233, 254, 0])
Stadtliste = ['Berlin', 'Hamburg', 'München', 'Köln', 'Frankfurt a. M.',
'Stuttgart', 'Düsseldorf', 'Dortmund', 'Essen', 'Bremen']
for city in nearest_insertion(Entfernungen):
print("%s" % Stadtliste[city])

View file

@ -0,0 +1,72 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
""" Dieses Script analysiert die Verteilung der Längen der Routen. Diese müssen
durch "Entfernungen.txt" gegeben sein.
"""
print("Beginne alle Routen zu lesen.")
f = open('/home/moose/mathe/Entfernungen.txt', 'r')
lines = f.readlines()
f.close()
print("Alle Routen wurden eingelesen.")
number = length = 0
minimum= int(lines[0])
maximum= int(lines[0])
liste = []
dict_entfernungen = {}
for line in lines:
line = int(line)
if line in dict_entfernungen:
dict_entfernungen[line] += 1
else:
dict_entfernungen[line] = 1
liste.append(line)
number += 1
length += line
if line < minimum:
minimum = line
if line > maximum:
maximum = line
print("Minimum: %i" % minimum)
print("Maximum: %i" % maximum)
print("Durchschnitt: %i" % (length/number))
print("Anzahl der Routen: %i" % number)
less_than2069 = 0.0
for length, count in dict_entfernungen.items():
if length <= 2068:
less_than2069 += count
print("maximale Abweichung von 5%%: %f %% aller Strecken" % (less_than2069/number*100))
EntfernungsSet = set(liste)
print("Anzahl der verschiedenen Streckenlängen: %i" % len(dict_entfernungen))
import math, pylab
x_list = []
y_list = []
for x, y in dict_entfernungen.items():
y_list.append(y)
x_list.append(x)
pylab.xlabel("Streckenlange in km")
pylab.ylabel("Anzahl der Routen")
pylab.plot(x_list, y_list, 'b')
# Einzeichnen des Durchschnitts:
y_max = max(y_list)
x_list = []
y_list = []
y_list.append(0)
x_list.append((length/number))
y_list.append(y_max)
x_list.append((length/number))
pylab.plot(x_list, y_list, 'r')
pylab.savefig('Fig1.png')
pylab.show()

View file

@ -0,0 +1,201 @@
\documentclass[a4paper,9pt]{scrartcl}
\usepackage[ngerman]{babel}
\usepackage[utf8]{inputenc}
\usepackage{amssymb,amsmath}
\usepackage{geometry}
\usepackage{graphicx}
\usepackage{hyperref}
\usepackage{listings}
\usepackage{color}
\usepackage{slashbox}
\definecolor{gray}{gray}{0.5}
\lstset{
language=Python, % the language of the code
basicstyle=\footnotesize, % the size of the fonts that are used for the code
keywordstyle=\color{blue},
stringstyle=\color{red},
commentstyle=\color{gray}\slshape,
emph={class, pass, in, for, while, if, is, elif, else, not, and, or, def, print, exec, break, continue, return},
emphstyle=\color{black}\bfseries,
emph={[2]True, False, None, self},
emph={[3]from, import, as},
emphstyle=[3]\color{blue},
morecomment=[s]{"""}{"""},
rulesepcolor=\color{blue},
otherkeywords={1, 2, 3, 4, 5, 6, 7, 8 ,9 , 0, -, =, +, [, ], (, ), \{, \}, :, *, !},
numbers=left, % where to put the line-numbers
numberstyle=\footnotesize, % the size of the fonts that are used for the line-numbers
stepnumber=1, % the step between two line-numbers. If it's 1, each line
% will be numbered
numbersep=5pt, % how far the line-numbers are from the code
showspaces=false, % show spaces adding particular underscores
showstringspaces=false, % underline spaces within strings
showtabs=false, % show tabs within strings adding particular underscores
tabsize=2, % sets default tabsize to 2 spaces
captionpos=b, % sets the caption-position to bottom
breaklines=true, % sets automatic line breaking
breakatwhitespace=false, % sets if automatic breaks should only happen at whitespace
title=\lstname, % show the filename of files included with \lstinputlisting;
% also try caption instead of title
escapeinside={\%*}{*)}, % if you want to add a comment within your code
morekeywords={*,...}, % if you want to add more keywords to the set
literate=%
{Ö}{{\"O}}1
{Ä}{{\"A}}1
{Ü}{{\"U}}1
{ß}{{\ss}}2
{ü}{{\"u}}1
{ä}{{\"a}}1
{ö}{{\"o}}1
}
\geometry{a4paper,left=18mm,right=18mm, top=1cm, bottom=2cm}
\setcounter{secnumdepth}{2}
\setcounter{tocdepth}{2}
\shorthandon{"}
\hypersetup{
pdftitle={Handlungsreisender in Deutschland},
pdfsubject={Aufgabe},
pdfauthor={Martin Thoma},
pdfkeywords={Aufgabe, Mathematik, Lösung}}
\shorthandoff{"}
\begin{document}
\title{Handlungsreisender in Deutschland}
\author{Martin Thoma}
\setcounter{section}{1}
\section*{Aufgabenstellung}
Ein Handlungsreisender will seine Produkte in den zehn größten Städten
Deutschlands verkaufen. Er startet in Berlin und will seine Reise dort
beenden.
Die zehn einwohnerreichsten Städte Deutschlands sind Berlin, Hamburg,
München, Köln, Frankfurt am Main, Stuttgart, Düsseldorf, Dortmund, Essen
und Bremen. \\
Folgende Tabelle gibt die Entfernung zwischen den Städten für eine Autoreise
wieder\footnote{Mit maps.google.com ermittelte Werte. Es wurde immer auf ganze Kilometer gerundet.}:
\begin{tabular}[hc]{|l|c|c|c|c|c|c|c|c|c|c|}
\hline
\backslashbox{von}{nach} & \rotatebox{90}{Berlin} & \rotatebox{90}{Hamburg} & \rotatebox{90}{München} & \rotatebox{90}{Köln} & \rotatebox{90}{Frankfurt am Main} & \rotatebox{90}{Stuttgart} & \rotatebox{90}{Düsseldorf} & \rotatebox{90}{Dortmund} & \rotatebox{90}{Essen} & \rotatebox{90}{Bremen} \\
\hline\hline
Berlin & 0 & 288 & 585 & 575 & 547 & 633 & 559 & 494 & 531 & 392 \\
Hamburg & 289 & 0 & 775 & 426 & 493 & 655 & 400 & 344 & 365 & 122 \\
München & 589 & 775 & 0 & 577 & 398 & 220 & 612 & 604 & 634 & 748 \\
Köln & 579 & 426 & 576 & 0 & 193 & 369 & 42 & 95 & 73 & 320 \\
Frankfurt a. M. & 552 & 492 & 393 & 193 & 0 & 210 & 229 & 219 & 251 & 445 \\
Stuttgart & 637 & 667 & 231 & 369 & 203 & 0 & 404 & 417 & 426 & 642 \\
Düsseldorf& 563 & 408 & 611 & 38 & 228 & 404 & 0 & 71 & 37 & 302 \\
Dortmund & 498 & 346 & 605 & 95 & 221 & 418 & 69 & 0 & 36 & 240 \\
Essen & 536 & 374 & 634 & 74 & 252 & 427 & 35 & 37 & 0 & 267 \\
Bremen & 397 & 123 & 748 & 315 & 441 & 638 & 289 & 233 & 254 & 0 \\
\hline
\end{tabular}\\
\\
Welche Route sollte er wählen?
\subsection{Größenordnung des Problems}
Es gibt $9! = 9 \cdot 8 \cdot 7 \cdot 6 \cdot 5 \cdot 4 \cdot 3 \cdot 2 \cdot 1 = 362.880$ mögliche Routen,
da der Handlungsreisende in Berlin startet und 9 Möglichkeiten für die erste
Stadt hat, 8 für die zweite, usw.\\
Allgemein kann man sagen, dass bei $n$ Städten insgesamt $(n-1)!$ mögliche
Routen bestehen, da die Wahl des Startpunktes egal ist. \\
Falls das Problem symmetrisch wäre, also die Strecke von Berlin nach
München genauso lang wie die von München nach Berlin wäre, könnte man die
Anzahl der Routen auf $\frac{(n-1)!}{2}$ reduzieren. Allerdings ist das
Problem offensichtlich asymmetrisch (siehe München $\rightarrow$ Berlin und
München $\leftarrow$ Berlin)
Die Tabelle \ref{tab:functionGrowth} macht deutlich, wie schnell so etwas
wächst.
\begin{table}[hc]
\centering
\begin{tabular}[hc]{|l|r|r|r|r|r|r|}
\hline
n & $1$ & $log(n)$ & $n \cdot log(n)$ & $n^2$ & $n^3$ & $n!$ \\
\hline\hline
1 & 1 & 0 & 0 & 1 & 1 & 1 \\
2 & 1 & 0,30 & 0,60 & 4 & 8 & 2 \\
3 & 1 & 0,48 & 1,43 & 9 & 27 & 6 \\
4 & 1 & 0,60 & 2,41 & 16 & 64 & 24 \\
5 & 1 & 0,70 & 3,49 & 25 & 125 & 120 \\
6 & 1 & 0,78 & 4,67 & 36 & 216 & 720 \\
7 & 1 & 0,85 & 5,92 & 49 & 343 & 5.040 \\
8 & 1 & 0,90 & 8,13 & 64 & 512 & 40.320\\
9 & 1 & 0,95 & 8,59 & 81 & 729 & 362.880\\
10 & 1 & 1,00 & 10,00 & 100 & 1.000 & 3.628.800\\
20 & 1 & 1,30 & 26,02 & 400 & 8.000 & $2,42 \cdot 10^{18}$ \\
\hline
\end{tabular}
\caption{Wachstum verschiedener Funktionen}
\label{tab:functionGrowth}
\end{table}
\newpage
\subsection{Intuitive Lösung}
Wenn man die Städte so auf der Karte sieht sollte man einfach mal die Route
suchen, von der man denkt sie wäre gut. \\
\begin{center}
%\includegraphics{Germany_location_map.png}
\end{center}
Ich habe mir folgende ausgesucht:\\
\begin{center}
%\includegraphics{Germany_location_map-intuitiv.png}
\end{center}
Das ist die Route Berlin $\rightarrow$ München $\rightarrow$ Stuttgart
$\rightarrow$ Frankfurt a. M. $\rightarrow$ Köln $\rightarrow$ Düsseldorf
$\rightarrow$ Essen $\rightarrow$ Dortmund $\rightarrow$ Bremen
$\rightarrow$ Hamburg $\rightarrow$ Berlin.
Diese Route ist 1969 km lang.
\newpage
\subsection{Optimale Lösung}
\subsubsection{Alle Routen durchgehen}
Die primitivste und langsamste Methode zum Finden der optimalen Lösung ist
einfach alle möglichen Routen durch zu gehen. Dieser Algorithmus ist, was
die Ausführungszeit angeht, in $\mathcal{O}(n!)$. Wie schnell diese wächst
sollte mit Tabelle \ref{tab:functionGrowth} klar geworden sein.\\
Dieser Ansatz ist also nur für sehr kleine Instanzen des Problems geeignet.\\
\\
Eine Auswertung aller Stecken hat folgende Ergebnisse geliefert: \\
1969 km bzw. die von mir intuitiv gefundene Strecke ist eine von 10 optimalen Lösungen.\\
Die längste Route ist 4.913 km lang.\\
Es gibt 3.628.800 Routen, jedoch nur 2.597 verschiedene Streckenlängen. Die
durchschnittliche Streckenlänge beträgt 3.838 km und wurde rot eingezeichnet,
die maximale 4.913 km.\\
Die Verteilung der Streckenlängen sieht wie folgt aus:\\
%\includegraphics{Kurve.png}
\\
Würde man eine maximale Abweichung von $5\%$ akzeptieren, wären nur $0,002\%$
aller Routen akzeptabel. Durch eine zufällig gewählte Strecke wird man also
kaum ein gutes Ergebnis erziehlen
\subsection{Heuristiken}
Eine Heuristik ist in diesem Zusammenhang ein vereinfachtes Verfahren, das
keine optimale Lösung liefert, aber eine akzeptable Näherung daran. Dafür
ist die Heuristik deutlich schneller.\\
\subsubsection{Nächster Nachbar}
Eine mögliche Heurisik ist das auswählen der Stadt, die am nächsten zur
aktuellen Stadt liegt. Mit diesem Verfahren erhält man bei der gegebenen
Städtekonstellation eine Route der Länge 2.162 km. Das sind 193 km oder
$9,8\%$ mehr als die optimale Lösung benötigt.
\subsubsection{Nächster Nachbar - Dynamisch Einfügen}
Die Methode des nächsten Nachbars kann verbessert werden, indem der Nachbar
nicht einfach am Ende in die Route eingefügt wird, sondern an die Stelle, an
der die resultierende Route am kleinsten wäre. Damit erhält man bei der
gegebenen Städtekonstellation eine optimale Route.
\newpage
\lstinputlisting[language=Python]{Handlungsreisender-in-Deutschland-Alle-Routen.py}
\newpage
\lstinputlisting[language=Python]{Handlungsreisender-in-Deutschland-analyse.py}
\newpage
%\lstinputlisting[language=Python]{Handlungsreisender-in-Deutschland-Nearest-Neighbour.py}
\lstinputlisting[language=Python]{Handlungsreisender-in-Deutschland-Nearest-Insertion.py}
\end{document}

View file

@ -0,0 +1,6 @@
make:
pdflatex Handlungsreisender-in-Deutschland.tex -output-format=pdf
make clean
clean:
rm -rf $(TARGET) *.class *.html *.log *.aux *.out

View file

@ -0,0 +1,77 @@
% slashbox.sty by Koichi Yasuoka, May 27, 1993
% minor modification by Toru Sato, May 31, 1993
\typeout{slashbox style by K.Yasuoka, May 1993.}%
\newbox\@slashboxa
\newbox\@slashboxb
\newbox\@slashboxc
\newcount\@slashboxwd
\newcount\@slashboxht
\newdimen\@slashsepl
\newdimen\@slashsepr
\def\slashbox{%
\def\@slashboxpicture##1{%
\put(0,0){\line(##1,1){\@slashboxwd}}%
\put(0,\@slashboxht){\makebox(0,0)[tl]{\box\@slashboxa}}%
\put(\@slashboxwd,0){\makebox(0,0)[br]{\box\@slashboxb}}%
}%
\@slashbox
}%
\def\backslashbox{%
\def\@slashboxpicture##1{%
\put(0,\@slashboxht){\line(##1,-1){\@slashboxwd}}%
\put(0,0){\makebox(0,0)[bl]{\box\@slashboxa}}%
\put(\@slashboxwd,\@slashboxht){\makebox(0,0)[tr]{\box\@slashboxb}}%
}%
\@slashbox
}%
\def\@slashbox{\@ifnextchar [{\@@slashbox}{\@@slashbox[0pt]}}
\def\@@slashbox[#1]{\@ifnextchar [{\@@@slashbox[#1]}{\@@@slashbox[#1][c]}}
\def\@@@slashbox[#1][#2]#3#4{%
% #1: width, #2: suppression of \tabcolsep on `l', `r', or `lr' side
% #3: left item, #4: right item
\@slashsepl=\tabcolsep
\@slashsepr=\tabcolsep
\@tfor\@tempa :=#2\do{\expandafter\let
\csname @slashsep\@tempa\endcsname=\z@}%
\setbox\@slashboxa=\hbox{\strut\hskip\tabcolsep\shortstack[l]{#3}}%
\setbox\@slashboxb=\hbox{\shortstack[r]{#4}\hskip\tabcolsep\strut}%
\setbox\@slashboxa=\hbox{\raise\dp\@slashboxa\box\@slashboxa}%
\setbox\@slashboxb=\hbox{\raise\dp\@slashboxb\box\@slashboxb}%
\setbox\@slashboxc=\hbox{%
\@tempdima=\wd\@slashboxa
\advance\@tempdima by \wd\@slashboxb
\advance\@tempdima by \@slashsepl
\advance\@tempdima by \@slashsepr
\@tempdimb=#1\relax%
\ifdim\@tempdimb>\@tempdima \@tempdima=\@tempdimb\fi%
\@tempdimb=\ht\@slashboxa
\advance\@tempdimb by \dp\@slashboxa
\advance\@tempdimb by \ht\@slashboxb
\advance\@tempdimb by \dp\@slashboxb
\@tempcnta=\@tempdima
\@tempcntb=\@tempdimb
\advance\@tempcnta by \@tempcntb
\advance\@tempcnta by -1
\divide\@tempcnta by \@tempcntb
\ifnum\@tempcnta>6 \@tempcnta=6
\@tempdimb=0.166666666\@tempdima
\else
\ifnum\@tempcnta<1 \@tempcnta=1\fi
\@tempdima=\@tempdimb
\multiply\@tempdima by \@tempcnta
\fi%
\advance\@tempdima by -\@slashsepl
\advance\@tempdima by -\@slashsepr
\@slashboxwd=\@tempdima
\@slashboxht=\@tempdimb
\@tempcntb=\@slashsepl
\setlength{\unitlength}{1sp}%
\begin{picture}(\@slashboxwd,\@slashboxht)(\@tempcntb,0)
\advance\@tempdima by \@slashsepl
\advance\@tempdima by \@slashsepr
\@slashboxwd=\@tempdima
\@slashboxpicture{\@tempcnta}
\end{picture}%
}%
$\vcenter{\box\@slashboxc}$%
}%