X-Git-Url: https://git.njae.me.uk/?a=blobdiff_plain;f=hillclimbing-results%2Fhillclimbing-experiments.ipynb;fp=hillclimbing-results%2Fhillclimbing-experiments.ipynb;h=4cfdc30e9a8354f88603079df799360a7c9a7c3d;hb=01adde8f28fb9fc89639c8e44be1782a76d12449;hp=0000000000000000000000000000000000000000;hpb=db8b9abe893fa68191cdda1bffa3d77619d527f3;p=cipher-tools.git
diff --git a/hillclimbing-results/hillclimbing-experiments.ipynb b/hillclimbing-results/hillclimbing-experiments.ipynb
new file mode 100644
index 0000000..4cfdc30
--- /dev/null
+++ b/hillclimbing-results/hillclimbing-experiments.ipynb
@@ -0,0 +1,2171 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import os,sys,inspect\n",
+ "currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))\n",
+ "parentdir = os.path.dirname(currentdir)\n",
+ "sys.path.insert(0,parentdir) "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from cipher.caesar import *\n",
+ "from cipher.affine import *\n",
+ "from cipher.keyword_cipher import *\n",
+ "from cipher.vigenere import *\n",
+ "from cipher.playfair import *\n",
+ "from cipher.column_transposition import *\n",
+ "from support.text_prettify import *\n",
+ "from support.plot_frequency_histogram import *"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# import logger as myl\n",
+ "# import logging\n",
+ "# myl.logger.setLevel(logging.DEBUG)\n",
+ "# mylg = logging.getLogger('cipherbreak')\n",
+ "import logging\n",
+ "from logger import logger\n",
+ "\n",
+ "import re\n",
+ "from datetime import datetime\n",
+ "import pandas as pd\n",
+ "import csv\n",
+ "import matplotlib as mpl\n",
+ "import matplotlib.pyplot as plt\n",
+ "%matplotlib inline\n",
+ "\n",
+ "from scipy.stats import kendalltau"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "logger.setLevel(logging.DEBUG)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def commonest_alphabet(text):\n",
+ " counts = collections.Counter(sanitise(text))\n",
+ " letters = cat(p[0] for p in counts.most_common())\n",
+ " return cat(deduplicate(letters + string.ascii_lowercase))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def random_ciphertext(message_length):\n",
+ " sample_start = random.randint(0, corpus_length - message_length)\n",
+ " sample = corpus[sample_start:(sample_start + message_length)]\n",
+ " key = list(string.ascii_lowercase)\n",
+ " random.shuffle(key)\n",
+ " key = cat(key)\n",
+ " ciphertext = keyword_encipher(sample, key)\n",
+ " return key, ciphertext"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def log_parse(text, verbose=False):\n",
+ " parts = text.split(' - ')\n",
+ " dt = datetime.strptime(parts[0], \"%Y-%m-%d %H:%M:%S,%f\")\n",
+ " blurb = parts[-1]\n",
+ " worker = int(re.search('worker (\\d+)', blurb).group(1))\n",
+ " iteration = int(re.search('iteration (\\d+)', blurb).group(1))\n",
+ " fitness = float(re.search('fitness (-?\\d+\\.\\d+)', blurb).group(1))\n",
+ " if verbose:\n",
+ " ca = re.search('current alphabet (\\w+)', blurb).group(1)\n",
+ " pa = re.search('plain alphabet (\\w+)', blurb).group(1)\n",
+ " mapped_ca = cat(p[1] for p in sorted(zip(pa, ca)))\n",
+ " return {'time': dt, 'worker': worker, 'iteration': iteration, 'fitness': fitness, \n",
+ " 'cipher_alphabet': ca, 'plain_alphabet': pa, 'mapped_cipher_alphabet': mapped_ca}\n",
+ " else:\n",
+ " return {'time': dt, 'worker': worker, 'iteration': iteration, 'fitness': fitness}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# ps = [log_parse(line, verbose=True) for line in open('cipher.log').readlines()[:10]]\n",
+ "# df = pd.DataFrame(ps)\n",
+ "# df = df.set_index(['worker', 'iteration']).sort_index()\n",
+ "# df[['fitness', 'plain_alphabet', 'cipher_alphabet']].to_csv('test.csv', header=True)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def dump_result(starttime, filename, verbose=False, target_cipher_alphabet=''):\n",
+ " parsed = [log_parse(line, verbose=verbose) for line in open('cipher.log')]\n",
+ " trace = pd.DataFrame([p for p in parsed if p['time'] > starttime])\n",
+ " trace = trace.set_index(['worker', 'iteration']).sort_index()\n",
+ " trace['target_cipher_alphabet'] = target_cipher_alphabet\n",
+ " workers = list(sorted(set(trace.index.get_level_values(0))))\n",
+ " if verbose:\n",
+ " trace[['fitness', 'plain_alphabet', 'cipher_alphabet', 'mapped_cipher_alphabet', 'target_cipher_alphabet']].to_csv(filename, header=True)\n",
+ " else:\n",
+ " trace.fitness.to_csv(filename, header=True)\n",
+ " return workers, trace"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'etoainhsrdlumwycfgpbvkxjqz'"
+ ]
+ },
+ "execution_count": 10,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "plain_alpha = cat(p[0] for p in english_counts.most_common())\n",
+ "plain_alpha"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def unscramble_alphabet(cipher_alphabet, plain_alphabet):\n",
+ " mapping = {p: c for p, c in zip(plain_alphabet, cipher_alphabet)}\n",
+ " unscrambled = cat(mapping[p] for p in sorted(mapping))\n",
+ " return unscrambled"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'theadventuresofsherl'"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# pt = sanitise(open('../2017/8b.plaintext').read())\n",
+ "corpus = sanitise(open('../support/sherlock-holmes.txt').read())\n",
+ "corpus_length = len(corpus)\n",
+ "pt = corpus\n",
+ "pt[:20]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Development"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "-542391.5369482826"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "Pletters(pt)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "-1471429.4753165497"
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "Ptrigrams(pt)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'etaoihnsrdlumwcyfgpbvkxjqz'"
+ ]
+ },
+ "execution_count": 14,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "commonest_alphabet(pt)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "('sbyopakxntlewgimvfcduqrzhj',\n",
+ " 'seirqinyprxncmpfporselmscdwpsg',\n",
+ " 'alowvoicewhisperedwalkpastmean')"
+ ]
+ },
+ "execution_count": 15,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "k, c = random_ciphertext(30)\n",
+ "k, c, keyword_decipher(c, k)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'yearningforrespiteth'"
+ ]
+ },
+ "execution_count": 16,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "pt = sanitise(open('../2017/8b.plaintext').read())\n",
+ "pt[:20]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 40,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'qviaysynjpaaverswvwxvapciyeetjjvavzieziqewtayvzsywpfvvmeiyzfvvmesywpcpywxefswxgihnigteiyzwxvgihvzpys'"
+ ]
+ },
+ "execution_count": 40,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "ct_key = list(string.ascii_lowercase)\n",
+ "random.shuffle(ct_key)\n",
+ "ct_key = cat(ct_key)\n",
+ "# ct = keyword_encipher(pt, 'arcanaimperii')\n",
+ "ct = keyword_encipher(pt, ct_key)\n",
+ "ct_alpha = commonest_alphabet(ct)\n",
+ "ct[:100]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 50,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "('vwpisyxeazhtcfqgjnrokmldbu', -14681.308607565503)"
+ ]
+ },
+ "execution_count": 50,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "start_time = datetime.now()\n",
+ "sa_cipher_alphabet, score = simulated_annealing_break(ct, plain_alphabet=plain_alpha, cipher_alphabet=ct_alpha)\n",
+ "sa_cipher_alphabet, score"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 51,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'iogzvjnxsdmhcyprbaewtkflqu'"
+ ]
+ },
+ "execution_count": 51,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "ct_key"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 52,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'iogzvjnxsdmhcyprbaewtkflqu'"
+ ]
+ },
+ "execution_count": 52,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "cat(p[1] for p in sorted(zip(plain_alpha, sa_cipher_alphabet)))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 53,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'arcnimpebdfghjkloqstuvwxyz'"
+ ]
+ },
+ "execution_count": 53,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "keyword_cipher_alphabet_of('arcanaimperii')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 54,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "cipher.log old.cipher.log\n"
+ ]
+ }
+ ],
+ "source": [
+ "!ls *log"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 55,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['2019-10-28 09:59:14,978 - cipherbreak - DEBUG - Simulated annealing worker 2: iteration 0, temperature 200, current alphabet rjgzieptunyxodfsmbacqhkwvl, plain alphabet etoainhsrdlumwycfgpbvkxjqz, current_fitness -17464.568516864027, best_plaintext getsninycassehpioeoresamtnhhuccesedthdtghousnedino',\n",
+ " '2019-10-28 09:59:14,978 - cipherbreak - DEBUG - Simulated annealing worker 8: iteration 0, temperature 200, current alphabet rjgzieptunyxocfsmbadqhkwvl, plain alphabet etoainhsrdlumwycfgpbvkxjqz, current_fitness -17394.10216261065, best_plaintext geosninycassehpitetresamonhhuccesedohdoghtusnedint',\n",
+ " '2019-10-28 09:59:14,980 - cipherbreak - DEBUG - Simulated annealing worker 0: iteration 0, temperature 200, current alphabet rjgzieptunyxodcsmbafqhkwvl, plain alphabet etoainhsrdlumwycfgpbvkxjqz, current_fitness -17476.383874573305, best_plaintext geosninbcassehpitetresamonhhuccesedohdoghtusnedint',\n",
+ " '2019-10-28 09:59:14,980 - cipherbreak - DEBUG - Simulated annealing worker 1: iteration 0, temperature 200, current alphabet rjgzieptunyxodfsmbacqhkwvl, plain alphabet etoainhsrdlumwycfgpbvkxjqz, current_fitness -17464.568516864027, best_plaintext geosninychsseapitetreshmonaauccesedoadogatusnedint',\n",
+ " '2019-10-28 09:59:14,980 - cipherbreak - DEBUG - Simulated annealing worker 4: iteration 0, temperature 200, current alphabet rjgzieptunyxodfsmbacqhkwvl, plain alphabet etoainhsrdlumwycfgpbvkxjqz, current_fitness -17464.568516864027, best_plaintext geosninycassezpitetresamonzzuccesedozdogztusnedint']"
+ ]
+ },
+ "execution_count": 55,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "recs = open('cipher.log').read().splitlines()\n",
+ "recs[:5]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 66,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'time': datetime.datetime(2019, 10, 28, 9, 59, 14, 978000),\n",
+ " 'worker': 2,\n",
+ " 'iteration': 0,\n",
+ " 'fitness': -17464.568516864027}"
+ ]
+ },
+ "execution_count": 66,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "log_parse(recs[0])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 57,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[{'time': datetime.datetime(2019, 10, 28, 9, 59, 14, 978000),\n",
+ " 'worker': 2,\n",
+ " 'iteration': 0,\n",
+ " 'fitness': -17464.568516864027},\n",
+ " {'time': datetime.datetime(2019, 10, 28, 9, 59, 14, 978000),\n",
+ " 'worker': 8,\n",
+ " 'iteration': 0,\n",
+ " 'fitness': -17394.10216261065},\n",
+ " {'time': datetime.datetime(2019, 10, 28, 9, 59, 14, 980000),\n",
+ " 'worker': 0,\n",
+ " 'iteration': 0,\n",
+ " 'fitness': -17476.383874573305},\n",
+ " {'time': datetime.datetime(2019, 10, 28, 9, 59, 14, 980000),\n",
+ " 'worker': 1,\n",
+ " 'iteration': 0,\n",
+ " 'fitness': -17464.568516864027},\n",
+ " {'time': datetime.datetime(2019, 10, 28, 9, 59, 14, 980000),\n",
+ " 'worker': 4,\n",
+ " 'iteration': 0,\n",
+ " 'fitness': -17464.568516864027}]"
+ ]
+ },
+ "execution_count": 57,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "parsed = [log_parse(line) for line in open('cipher.log')]\n",
+ "parsed[:5]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 58,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " | \n",
+ " fitness | \n",
+ " time | \n",
+ "
\n",
+ " \n",
+ " worker | \n",
+ " iteration | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 0 | \n",
+ " -17464.568517 | \n",
+ " 2019-10-28 10:14:21.136 | \n",
+ "
\n",
+ " \n",
+ " 500 | \n",
+ " -18531.679762 | \n",
+ " 2019-10-28 10:14:22.493 | \n",
+ "
\n",
+ " \n",
+ " 1000 | \n",
+ " -20903.487109 | \n",
+ " 2019-10-28 10:14:23.787 | \n",
+ "
\n",
+ " \n",
+ " 1500 | \n",
+ " -19941.571807 | \n",
+ " 2019-10-28 10:14:25.084 | \n",
+ "
\n",
+ " \n",
+ " 2000 | \n",
+ " -18871.699801 | \n",
+ " 2019-10-28 10:14:26.133 | \n",
+ "
\n",
+ " \n",
+ " 2500 | \n",
+ " -18847.246876 | \n",
+ " 2019-10-28 10:14:27.408 | \n",
+ "
\n",
+ " \n",
+ " 3000 | \n",
+ " -19111.386196 | \n",
+ " 2019-10-28 10:14:28.707 | \n",
+ "
\n",
+ " \n",
+ " 3500 | \n",
+ " -19693.452817 | \n",
+ " 2019-10-28 10:14:29.835 | \n",
+ "
\n",
+ " \n",
+ " 4000 | \n",
+ " -18959.289175 | \n",
+ " 2019-10-28 10:14:31.228 | \n",
+ "
\n",
+ " \n",
+ " 4500 | \n",
+ " -19040.556583 | \n",
+ " 2019-10-28 10:14:32.569 | \n",
+ "
\n",
+ " \n",
+ " 5000 | \n",
+ " -18169.812374 | \n",
+ " 2019-10-28 10:14:33.891 | \n",
+ "
\n",
+ " \n",
+ " 5500 | \n",
+ " -16657.860123 | \n",
+ " 2019-10-28 10:14:35.200 | \n",
+ "
\n",
+ " \n",
+ " 6000 | \n",
+ " -16220.268468 | \n",
+ " 2019-10-28 10:14:36.485 | \n",
+ "
\n",
+ " \n",
+ " 6500 | \n",
+ " -16472.952274 | \n",
+ " 2019-10-28 10:14:37.784 | \n",
+ "
\n",
+ " \n",
+ " 7000 | \n",
+ " -17046.418912 | \n",
+ " 2019-10-28 10:14:39.054 | \n",
+ "
\n",
+ " \n",
+ " 7500 | \n",
+ " -17320.865489 | \n",
+ " 2019-10-28 10:14:40.343 | \n",
+ "
\n",
+ " \n",
+ " 8000 | \n",
+ " -16438.413488 | \n",
+ " 2019-10-28 10:14:41.622 | \n",
+ "
\n",
+ " \n",
+ " 8500 | \n",
+ " -16116.768242 | \n",
+ " 2019-10-28 10:14:42.893 | \n",
+ "
\n",
+ " \n",
+ " 9000 | \n",
+ " -16085.659977 | \n",
+ " 2019-10-28 10:14:44.167 | \n",
+ "
\n",
+ " \n",
+ " 9500 | \n",
+ " -15679.574171 | \n",
+ " 2019-10-28 10:14:45.405 | \n",
+ "
\n",
+ " \n",
+ " 10000 | \n",
+ " -16473.325447 | \n",
+ " 2019-10-28 10:14:46.650 | \n",
+ "
\n",
+ " \n",
+ " 10500 | \n",
+ " -16421.027387 | \n",
+ " 2019-10-28 10:14:48.070 | \n",
+ "
\n",
+ " \n",
+ " 11000 | \n",
+ " -16167.752107 | \n",
+ " 2019-10-28 10:14:49.371 | \n",
+ "
\n",
+ " \n",
+ " 11500 | \n",
+ " -15213.074262 | \n",
+ " 2019-10-28 10:14:50.686 | \n",
+ "
\n",
+ " \n",
+ " 12000 | \n",
+ " -15634.979337 | \n",
+ " 2019-10-28 10:14:51.967 | \n",
+ "
\n",
+ " \n",
+ " 12500 | \n",
+ " -15296.397297 | \n",
+ " 2019-10-28 10:14:52.824 | \n",
+ "
\n",
+ " \n",
+ " 13000 | \n",
+ " -15025.983510 | \n",
+ " 2019-10-28 10:14:53.881 | \n",
+ "
\n",
+ " \n",
+ " 13500 | \n",
+ " -15175.912750 | \n",
+ " 2019-10-28 10:14:54.871 | \n",
+ "
\n",
+ " \n",
+ " 14000 | \n",
+ " -15235.513700 | \n",
+ " 2019-10-28 10:14:56.119 | \n",
+ "
\n",
+ " \n",
+ " 14500 | \n",
+ " -14923.520462 | \n",
+ " 2019-10-28 10:14:57.339 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 9 | \n",
+ " 5000 | \n",
+ " -19218.644968 | \n",
+ " 2019-10-28 10:14:34.337 | \n",
+ "
\n",
+ " \n",
+ " 5500 | \n",
+ " -18770.828622 | \n",
+ " 2019-10-28 10:14:35.625 | \n",
+ "
\n",
+ " \n",
+ " 6000 | \n",
+ " -18390.233128 | \n",
+ " 2019-10-28 10:14:36.920 | \n",
+ "
\n",
+ " \n",
+ " 6500 | \n",
+ " -17361.547211 | \n",
+ " 2019-10-28 10:14:38.208 | \n",
+ "
\n",
+ " \n",
+ " 7000 | \n",
+ " -16846.113490 | \n",
+ " 2019-10-28 10:14:39.501 | \n",
+ "
\n",
+ " \n",
+ " 7500 | \n",
+ " -15002.318165 | \n",
+ " 2019-10-28 10:14:40.762 | \n",
+ "
\n",
+ " \n",
+ " 8000 | \n",
+ " -16992.780932 | \n",
+ " 2019-10-28 10:14:41.757 | \n",
+ "
\n",
+ " \n",
+ " 8500 | \n",
+ " -17115.242295 | \n",
+ " 2019-10-28 10:14:43.037 | \n",
+ "
\n",
+ " \n",
+ " 9000 | \n",
+ " -17297.012437 | \n",
+ " 2019-10-28 10:14:44.327 | \n",
+ "
\n",
+ " \n",
+ " 9500 | \n",
+ " -16511.948405 | \n",
+ " 2019-10-28 10:14:45.552 | \n",
+ "
\n",
+ " \n",
+ " 10000 | \n",
+ " -16175.059178 | \n",
+ " 2019-10-28 10:14:46.828 | \n",
+ "
\n",
+ " \n",
+ " 10500 | \n",
+ " -15482.711195 | \n",
+ " 2019-10-28 10:14:48.096 | \n",
+ "
\n",
+ " \n",
+ " 11000 | \n",
+ " -15190.359782 | \n",
+ " 2019-10-28 10:14:49.376 | \n",
+ "
\n",
+ " \n",
+ " 11500 | \n",
+ " -15776.667896 | \n",
+ " 2019-10-28 10:14:50.523 | \n",
+ "
\n",
+ " \n",
+ " 12000 | \n",
+ " -15112.798387 | \n",
+ " 2019-10-28 10:14:51.327 | \n",
+ "
\n",
+ " \n",
+ " 12500 | \n",
+ " -15539.267169 | \n",
+ " 2019-10-28 10:14:52.194 | \n",
+ "
\n",
+ " \n",
+ " 13000 | \n",
+ " -15209.937930 | \n",
+ " 2019-10-28 10:14:52.907 | \n",
+ "
\n",
+ " \n",
+ " 13500 | \n",
+ " -14917.833732 | \n",
+ " 2019-10-28 10:14:53.804 | \n",
+ "
\n",
+ " \n",
+ " 14000 | \n",
+ " -14822.068093 | \n",
+ " 2019-10-28 10:14:54.706 | \n",
+ "
\n",
+ " \n",
+ " 14500 | \n",
+ " -14996.772583 | \n",
+ " 2019-10-28 10:14:55.742 | \n",
+ "
\n",
+ " \n",
+ " 15000 | \n",
+ " -14818.384023 | \n",
+ " 2019-10-28 10:14:57.001 | \n",
+ "
\n",
+ " \n",
+ " 15500 | \n",
+ " -14698.864982 | \n",
+ " 2019-10-28 10:14:58.250 | \n",
+ "
\n",
+ " \n",
+ " 16000 | \n",
+ " -14689.841559 | \n",
+ " 2019-10-28 10:14:59.546 | \n",
+ "
\n",
+ " \n",
+ " 16500 | \n",
+ " -14698.864982 | \n",
+ " 2019-10-28 10:15:00.651 | \n",
+ "
\n",
+ " \n",
+ " 17000 | \n",
+ " -14681.308608 | \n",
+ " 2019-10-28 10:15:01.702 | \n",
+ "
\n",
+ " \n",
+ " 17500 | \n",
+ " -14681.308608 | \n",
+ " 2019-10-28 10:15:02.920 | \n",
+ "
\n",
+ " \n",
+ " 18000 | \n",
+ " -14681.308608 | \n",
+ " 2019-10-28 10:15:04.255 | \n",
+ "
\n",
+ " \n",
+ " 18500 | \n",
+ " -14681.308608 | \n",
+ " 2019-10-28 10:15:05.523 | \n",
+ "
\n",
+ " \n",
+ " 19000 | \n",
+ " -14681.308608 | \n",
+ " 2019-10-28 10:15:06.791 | \n",
+ "
\n",
+ " \n",
+ " 19500 | \n",
+ " -14681.308608 | \n",
+ " 2019-10-28 10:15:08.055 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
400 rows à 2 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " fitness time\n",
+ "worker iteration \n",
+ "0 0 -17464.568517 2019-10-28 10:14:21.136\n",
+ " 500 -18531.679762 2019-10-28 10:14:22.493\n",
+ " 1000 -20903.487109 2019-10-28 10:14:23.787\n",
+ " 1500 -19941.571807 2019-10-28 10:14:25.084\n",
+ " 2000 -18871.699801 2019-10-28 10:14:26.133\n",
+ " 2500 -18847.246876 2019-10-28 10:14:27.408\n",
+ " 3000 -19111.386196 2019-10-28 10:14:28.707\n",
+ " 3500 -19693.452817 2019-10-28 10:14:29.835\n",
+ " 4000 -18959.289175 2019-10-28 10:14:31.228\n",
+ " 4500 -19040.556583 2019-10-28 10:14:32.569\n",
+ " 5000 -18169.812374 2019-10-28 10:14:33.891\n",
+ " 5500 -16657.860123 2019-10-28 10:14:35.200\n",
+ " 6000 -16220.268468 2019-10-28 10:14:36.485\n",
+ " 6500 -16472.952274 2019-10-28 10:14:37.784\n",
+ " 7000 -17046.418912 2019-10-28 10:14:39.054\n",
+ " 7500 -17320.865489 2019-10-28 10:14:40.343\n",
+ " 8000 -16438.413488 2019-10-28 10:14:41.622\n",
+ " 8500 -16116.768242 2019-10-28 10:14:42.893\n",
+ " 9000 -16085.659977 2019-10-28 10:14:44.167\n",
+ " 9500 -15679.574171 2019-10-28 10:14:45.405\n",
+ " 10000 -16473.325447 2019-10-28 10:14:46.650\n",
+ " 10500 -16421.027387 2019-10-28 10:14:48.070\n",
+ " 11000 -16167.752107 2019-10-28 10:14:49.371\n",
+ " 11500 -15213.074262 2019-10-28 10:14:50.686\n",
+ " 12000 -15634.979337 2019-10-28 10:14:51.967\n",
+ " 12500 -15296.397297 2019-10-28 10:14:52.824\n",
+ " 13000 -15025.983510 2019-10-28 10:14:53.881\n",
+ " 13500 -15175.912750 2019-10-28 10:14:54.871\n",
+ " 14000 -15235.513700 2019-10-28 10:14:56.119\n",
+ " 14500 -14923.520462 2019-10-28 10:14:57.339\n",
+ "... ... ...\n",
+ "9 5000 -19218.644968 2019-10-28 10:14:34.337\n",
+ " 5500 -18770.828622 2019-10-28 10:14:35.625\n",
+ " 6000 -18390.233128 2019-10-28 10:14:36.920\n",
+ " 6500 -17361.547211 2019-10-28 10:14:38.208\n",
+ " 7000 -16846.113490 2019-10-28 10:14:39.501\n",
+ " 7500 -15002.318165 2019-10-28 10:14:40.762\n",
+ " 8000 -16992.780932 2019-10-28 10:14:41.757\n",
+ " 8500 -17115.242295 2019-10-28 10:14:43.037\n",
+ " 9000 -17297.012437 2019-10-28 10:14:44.327\n",
+ " 9500 -16511.948405 2019-10-28 10:14:45.552\n",
+ " 10000 -16175.059178 2019-10-28 10:14:46.828\n",
+ " 10500 -15482.711195 2019-10-28 10:14:48.096\n",
+ " 11000 -15190.359782 2019-10-28 10:14:49.376\n",
+ " 11500 -15776.667896 2019-10-28 10:14:50.523\n",
+ " 12000 -15112.798387 2019-10-28 10:14:51.327\n",
+ " 12500 -15539.267169 2019-10-28 10:14:52.194\n",
+ " 13000 -15209.937930 2019-10-28 10:14:52.907\n",
+ " 13500 -14917.833732 2019-10-28 10:14:53.804\n",
+ " 14000 -14822.068093 2019-10-28 10:14:54.706\n",
+ " 14500 -14996.772583 2019-10-28 10:14:55.742\n",
+ " 15000 -14818.384023 2019-10-28 10:14:57.001\n",
+ " 15500 -14698.864982 2019-10-28 10:14:58.250\n",
+ " 16000 -14689.841559 2019-10-28 10:14:59.546\n",
+ " 16500 -14698.864982 2019-10-28 10:15:00.651\n",
+ " 17000 -14681.308608 2019-10-28 10:15:01.702\n",
+ " 17500 -14681.308608 2019-10-28 10:15:02.920\n",
+ " 18000 -14681.308608 2019-10-28 10:15:04.255\n",
+ " 18500 -14681.308608 2019-10-28 10:15:05.523\n",
+ " 19000 -14681.308608 2019-10-28 10:15:06.791\n",
+ " 19500 -14681.308608 2019-10-28 10:15:08.055\n",
+ "\n",
+ "[400 rows x 2 columns]"
+ ]
+ },
+ "execution_count": 58,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# threshold = datetime(2018, 12, 6, 1)\n",
+ "trace = pd.DataFrame([p for p in parsed if p['time'] > start_time])\n",
+ "trace = trace.set_index(['worker', 'iteration']).sort_index()\n",
+ "trace"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 59,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 59,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ "