diff --git a/Readme.md b/Readme.md index 52607a2..b2820bc 100644 --- a/Readme.md +++ b/Readme.md @@ -2,7 +2,7 @@ ## Tooling -- Python 3.6 +- Python 3.5 - [MyPy](http://www.mypy-lang.org/ ) für statische Typchecks - [Pandoc](https://pandoc.org/ ) für die Dokumentation - Python Module: siehe [requirements.txt](https://pip.pypa.io/en/latest/user_guide/#requirements-files ) diff --git a/Readme.txt b/Readme.txt deleted file mode 100644 index 2990537..0000000 --- a/Readme.txt +++ /dev/null @@ -1,23 +0,0 @@ -README ------ - -Für die Ausführung des Algorithmus wird Python 3 (empfohlene Version: 3.6.1) benötigt. -Die Packages, die zusätzlich gebraucht werden, können der requirements.txt entnommen werden. -(Installation kann hier einzeln oder über den Befehl: python -m pip install -r requirements.txt) - -Zur Ausführung bitte im Terminal in den Ordner src gehen und dort das Skript main.py starten. -Parameter, die hierbei möglich sind: - -h zeigt alle Optionen an - -p aktiviert die Ausgabe über den Plotter als Diagramm - -l wird benötigt falls die Eingabe eine Liste von Problemen ist (d.h. für jobshop1.txt) - -i Index des Problems in der Liste (nur relevant bei -l) - -t setzt die Starttemperatur des Simulated Annealings - -s setzt die maximalen Umformungsschritte pro Generierung einer neuen Lösung - -a setzt die Wahrscheinlichkeit, pro Umformungsschritt auch eine Lösung zu akzeptieren, obwohl - noch nicht die maximalen Umformungsschritte erreicht sind - --t -s und -a müssen nicht alle gesetzt sein, dann wird der jeweilige Defaultwert verwendet -Defaultwerte: max_temp = 300, max_steps = 250, accept_prob = 0.01 - -Beispielaufruf: - python .\main.py -p -l -i 2 -t 50 ..\inputdata\jobshop1.txt \ No newline at end of file diff --git a/doc.md b/doc.md deleted file mode 100644 index fd1f7b9..0000000 --- a/doc.md +++ /dev/null @@ -1,36 +0,0 @@ -## scheduling problem defined by: - 1. $m$ specialized machines - 2. tasks $\tau$ of the form $(e, i)$ with $t \in \mathbb{N}$ the execution time and $i \in \{1,2,\dots,m\}$ the machine the task has to run on - 3. $n$ jobs $T_k$ with $\forall T_k:$ linear order of tasks, with $k \in \{1,2,\dots,n\}$ - 4. Additionally, a multiset $\Omega$ of arbitrary but fixed size that contains wait states $\omega := (1, i)$ with $i \in \{1,2,\dots,m\}$ the blocked machine. - -The goal is to find the fastest feasible schedule $\sigma_{min}$. - -## evaluative function - - minimize the execution time of $\sigma$ - - upper bound: largest processing time first - - lower bound: max sum of execution times on one machine - -## solutions - - list of tuples $(t, \tau)$ with $t \in \mathbb{N}$ the scheduled begin of $\tau$ - -## operations - - $\operatorname{ins}(\omega, t)$: block a machine at time $t$ for $w$ time steps. - - $\operatorname{xchg}(\tau_1,\tau_2)$: exchange the position of two tasks. - -Both operations require that the start times are recomputed. - -## neighbourhood of solution - - - $\operatorname{neighbours}(\sigma) = \{x \in \Sigma | \delta(\sigma, x) \leq n\}$ with $\Sigma$ the set of all feasible schedules. - - $\delta$: $\delta ( \sigma )=0$, $\delta ( \operatorname{op}(x)) = \delta (x) + 1$ (ass. ins has the same penalty xchg has), $x$ either op($y$) or $\sigma$ - -## constraints - - only schedule new $\tau$ if another $\tau$ is finished - - only schedule $\tau \in T_k$ that has no unscheduled predecessor in $T_k$ - - only one task on a machine any given time - -## implementation in Python - - translate problem into list of jobs, jobs into lists of tasks, ie problem = [$T_0, T_1,\dots,T_{k-1}$], $T_i$ = [$\tau_1,\tau_2,\dots$] - - address tasks based on their indices, ie [0][1] is the second task of the first job. - - compute only one possible next solution, rate, drop/accept. $\delta$ is computed iteratively during generation diff --git a/notes.md b/notes.md index efe7c46..a21ba6f 100644 --- a/notes.md +++ b/notes.md @@ -26,7 +26,7 @@ - $S = \left\{(o_j,t) | o_j \in O \cup \left\{w_n | n \in \mathbb{N} \wedge w_n \text{ v.d.F. } (1, m) \right\} \wedge o_j \text{ v.d.F. } (d, m, j) \wedge t \in T \forall o \in O : \exists (o,t) \in S\right\}$ - indirekt lässt sich durch laufende Operation und Zeitpunkt auch Belegung einer Maschine zu einem Zeitpunkt ermitteln - Optimierung: sparse speichern -1. Liste von (T, $o_j$) mit $T \in \mathbb{N}$ (Time), $o_j \in O$ (Tasks), j bezeichnet den Job +1. Liste von (T, $o_j$) mit $T \in \mathbb{N}$ (Time), $o_j \in O$ (Tasks) - Operationen: - Vertauschen von 2 Jobs auf einer Maschine, selbstinvers - Verzögern von Operationen (keine expliziten Wartezustände nötig) diff --git a/requirements.txt b/requirements.txt index 55650c7..5556179 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,3 @@ mypy -arpeggio +Arpeggio matplotlib -numpy -tkinter \ No newline at end of file diff --git a/shell.nix b/shell.nix deleted file mode 100644 index e8d926d..0000000 --- a/shell.nix +++ /dev/null @@ -1,3 +0,0 @@ -with import {}; - - (python3.withPackages (ps: [ps.numpy (ps.matplotlib.override {enableQt=true;}) ps.mypy ps.arpeggio])).env diff --git a/src/Generator/__init__.py b/src/Generator/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/Generator/generator.py b/src/Generator/generator.py index 4cc4ab3..d6dca45 100644 --- a/src/Generator/generator.py +++ b/src/Generator/generator.py @@ -38,8 +38,8 @@ def accept(solution): Maybe skip this during the first step to generate a more random solution. """ - return tighten(solution) - #return solution + #return tighten(solution) + return solution def tighten(solution): diff --git a/src/Output/__init__.py b/src/Output/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/Output/output.py b/src/Output/output.py index a2d2168..2eb31ec 100644 --- a/src/Output/output.py +++ b/src/Output/output.py @@ -11,9 +11,7 @@ def create_plot(problem, solution): with plt.xkcd(): fig,ax = plt.subplots() - col = colors.XKCD_COLORS - del col['xkcd:white'] - colorlist = list(col.values()) + colorlist = list(colors.XKCD_COLORS.values()) random.shuffle(colorlist) for m in range(0, problem.machines): mach_ops = [ x for x in solution if problem.problem_data[x[1][0]][x[1][1]][1] == m ] diff --git a/src/Parser/__init__.py b/src/Parser/__init__.py index 59d2edf..d42e09c 100644 --- a/src/Parser/__init__.py +++ b/src/Parser/__init__.py @@ -6,33 +6,33 @@ from collections.abc import Mapping __all__ = ["js1_style", "js2_style"] grammar = """ - // starting point for jobshop1 input file + # starting point for jobshop1 input file job_shop1 = skip_preface - // eat away lines of preface, until first problem_instance is - // encountered; then the list of instances start + # eat away lines of preface, until first problem_instance is + # encountered; then the list of instances start skip_preface = (!problem_instance r"[^\n]+" skip_preface) / (eol skip_preface) / instance_list instance_list = problem_instance (sep_line trim_ws eol problem_instance eol?)* eof_sep problem_instance = trim_ws "instance" ' ' instance_name trim_ws eol trim_ws eol sep_line description eol problem_data description = r"[^\n]*" instance_name = r"\w+" sep_line = trim_ws plus_line trim_ws eol - // lines out of multiple + signs + # lines out of multiple + signs plus_line = r"\+\+\++" - // EOF is a builtin rule matching end of file + # EOF is a builtin rule matching end of file eof_sep = trim_ws plus_line " EOF " plus_line trim_ws eol* EOF - // entry point for jobshop2 input files + # entry point for jobshop2 input files job_shop2 = problem_data EOF problem_data = trim_ws num_jobs ' ' num_machines eol job_data+ - // used for skipping arbitrary number of non-breaking whitespace + # used for skipping arbitrary number of non-breaking whitespace trim_ws = r'[ \t]*' - // git may change line-endings on windows, so we have to match on both + # git may change line-endings on windows, so we have to match on both eol = "\n" / "\r\n" nonneg_num = r'\d+' num_jobs = nonneg_num num_machines = nonneg_num machine = nonneg_num duration = nonneg_num - // task data for 1 job + # task data for 1 job job_data = ' '* machine ' '+ duration (' '+ machine ' '+ duration)* trim_ws eol """ diff --git a/src/SchedulingAlgorithms/__init__.py b/src/SchedulingAlgorithms/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/example.py b/src/example.py index 50d2f22..14ed58a 100644 --- a/src/example.py +++ b/src/example.py @@ -1,10 +1,10 @@ -import Parser.js1_style as p -#import Parser.js2_style as p +#import Parser.js1_style as p +import Parser.js2_style as p from SchedulingAlgorithms import simanneal as sim from Output import output as o -problem = p.parse_file("../inputdata/jobshop1.txt")[0] -#problem = p.parse_file("../inputdata/sample") +#problem = p.parse_file("../inputdata/jobshop1.txt")[0] +problem = p.parse_file("../inputdata/sample") sim.init(problem) solution = sim.anneal() o.create_plot(problem, solution) \ No newline at end of file diff --git a/src/main.py b/src/main.py index 44f5448..ff46783 100644 --- a/src/main.py +++ b/src/main.py @@ -3,7 +3,6 @@ import sys import getopt from SchedulingAlgorithms import simanneal as sim -from Output import output as o def usage(): @@ -13,9 +12,6 @@ Command line options: -p activate pretty output (requires tkinter) -l assume that a file contains multiple problems, default is only 1 -i index of the problem you want solved. has no effect without l - -t set parameter max_temp of simulated annealing - -s set parameter max_steps of simulated annealing - -a set parameter accept_prob of simulated annealing Invocation: python [-hlp] file @@ -27,8 +23,8 @@ def main(): js1 = False plot = False try: - opts, args = getopt.getopt(sys.argv[1:], 'hpli:t:s:a:') - except getopt.GetoptError as err: + opts, args = getopt.getopt(sys.argv[1:], 'hpli:') + except getoptGetoptError as err: print(err) sys.exit() if ('-h', '') in opts: @@ -41,12 +37,6 @@ def main(): js1 = True idx = [int(x[1]) for x in opts if x[0]=='-i'] idx = idx[0] if idx else -1 - max_temp = [int(x[1]) for x in opts if x[0]=='-t'] - max_temp = max_temp[0] if max_temp else -1 - max_steps = [int(x[1]) for x in opts if x[0]=='-s'] - max_steps = max_steps[0] if max_steps else -1 - accept_prob = [int(x[1]) for x in opts if x[0]=='-a'] - accept_prob = accept_prob[0] if accept_prob else -1 if not args: print("No file given.") sys.exit() @@ -65,28 +55,7 @@ def main(): problem = problem[idx] print(problem) sim.init(problem) - if not max_temp == -1: - if not max_steps == -1: - if not accept_prob == -1: - solution = sim.anneal(max_temp, max_steps, accept_prob) - else: - solution = sim.anneal(max_temp = max_temp, max_steps = max_steps) - else: - if not accept_prob == -1: - solution = sim.anneal(max_temp = max_temp, accept_prob = accept_prob) - else: - solution = sim.anneal(max_temp = max_temp) - else: - if not max_steps == -1: - if not accept_prob == -1: - solution = sim.anneal(max_steps = max_steps, accept_prob = accept_prob) - else: - solution = sim.anneal(max_steps = max_steps) - else: - if not accept_prob == -1: - solution = sim.anneal(accept_prob = accept_prob) - else: - solution = sim.anneal() + solution = sim.anneal() print(solution) print(sim.rate(solution)) if plot: