{ "info": { "author": "Dan Saattrup Nielsen", "author_email": "saattrupdan@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3" ], "description": "# NaturalSelection \"Logo\n\nAn all-purpose pythonic genetic algorithm, which includes built-in hyperparameter tuning support for neural networks.\n\n\n## Installation\n\n```\n$ pip install naturalselection\n```\n\n\n## Usage\n\nHere is a toy example optimising a pair of numbers with respect to division.\n\n```python\n>>> import naturalselection as ns\n>>>\n>>> Pair = ns.Genus(x = range(1, 10000), y = range(1, 10000))\n>>>\n>>> pairs = ns.Population(\n... genus = Pair, \n... size = 100, \n... fitness_fn = lambda n: n.x/n.y\n... )\n...\n>>> history = pairs.evolve(generations = 100)\nEvolving population: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 100/100 [00:05<00:00, 19.59it/s]\n>>>\n>>> history.fittest\n{'genome': {'x': 9922, 'y': 10}, 'fitness': 992.2}\n>>>\n>>> history.plot()\n```\n\n![Plot showing fitness value over 100 generations.](https://filedn.com/lRBwPhPxgV74tO0rDoe8SpH/naturalselection_data/numbers_example.png)\n\n\nWe can also easily solve the classical [OneMax problem](http://tracer.lcc.uma.es/problems/onemax/onemax.html), which is about finding the bit-string of a given length with all 1's. Here we set `goal = 100` in the `evolve` function to allow for early stopping if we reach our goal before the maximum number of generations, which we here set to 5,000. Note that it only takes nine seconds, however.\n\n```python3\n>>> import naturalselection as ns\n>>>\n>>> BitString = ns.Genus(**{f'x{n}' : (0,1) for n in range(100)})\n>>>\n>>> def sum_bits(bitstring):\n... return sum(bitstring.get_genome().values())\n...\n>>> bitstrings = ns.Population(\n... genus = BitString,\n... size = 5,\n... fitness_fn = sum_bits\n... )\n... \n>>> history = bitstrings.evolve(generations = 500, goal = 100)\nEvolving population: 36%|\u2588\u2588\u2588\u2588\u2588\u2588 | 1805/5000 [00:09<00:16, 194.43it/s]\n>>> \n>>> history.plot(only_show_max = True)\n```\n\n![Plot showing fitness value over 4500 generations, converging steadily to the optimal filled out sequence of ones.](https://filedn.com/lRBwPhPxgV74tO0rDoe8SpH/naturalselection_data/onemax_example.png)\n\n\nLastly, here is an example of finding a fully connected feedforward neural network to model [MNIST](https://en.wikipedia.org/wiki/MNIST_database).\n\nNote that the models are trained in parallel, so it is loading in a copy of the MNIST data set for every CPU core in your computer, each of which takes up ~750MB of memory. If this causes you to run into memory trouble then you can set the `workers` parameter to something small like 2, or set `multiprocessing = False` to turn parallelism off completely. I've marked these in the code below.\n\n```python3\n>>> import naturalselection as ns\n>>>\n>>> def preprocessing(X):\n... ''' Basic normalisation and scaling preprocessing. '''\n... import numpy as np\n... X = X.reshape((-1, np.prod(X.shape[1:])))\n... X = (X - X.min()) / (X.max() - X.min())\n... X -= X.mean(axis = 0)\n... return X\n... \n>>> def mnist_train_val_sets():\n... ''' Get normalised and scaled MNIST train- and val sets. '''\n... from tensorflow.keras.utils import to_categorical\n... import mnist\n... X_train = preprocessing(mnist.train_images())\n... Y_train = to_categorical(mnist.train_labels())\n... X_val = preprocessing(mnist.test_images())\n... Y_val = to_categorical(mnist.test_labels())\n... return (X_train, Y_train, X_val, Y_val)\n...\n>>> nns = ns.NNs(\n... size = 30,\n... train_val_sets = mnist_train_val_sets(),\n... loss_fn = 'categorical_crossentropy',\n... score = 'accuracy',\n... output_activation = 'softmax',\n... max_epochs = 1,\n... max_training_time = 60,\n... # workers = 2, # If you want to reduce parallelism\n... # multiprocessing = False # If you want to disable parallelism\n... )\n...\n>>> history = nns.evolve(generations = 20)\nEvolving population: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 20/20 [57:18<00:00, 73.22s/it]\nComputing fitness: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 7/7 [01:20<00:00, 10.13s/it]\n>>> \n>>> history.fittest\n{'genome': {'optimizer': 'adagrad', 'hidden_activation': 'relu',\n'batch_size': 32, 'initializer': 'glorot_normal', 'input_dropout': 0.2,\n'neurons0': 256, 'dropout0': 0.0, 'neurons1': 128, 'dropout1': 0.1,\n'neurons2': 256, 'dropout2': 0.1, 'neurons3': 256, 'dropout3': 0.2,\n'neurons4': 128, 'dropout4': 0.4}, 'fitness': 0.9659}\n>>> \n>>> history.plot(\n... title = \"Validation accuracy by generation\",\n... ylabel = \"Validation accuracy\"\n... )\n```\n\n![Plot showing fitness value (which is accuracy in this case) over 20 generations, converging to roughly 96.50%.](https://filedn.com/lRBwPhPxgV74tO0rDoe8SpH/naturalselection_data/mnist_example.png)\n\nWe can then train the best performing model and save it locally:\n\n```python3\n>>> # Training the best model and saving it to mnist_model.h5\n>>> best_score = nns.train_best(file_name = 'mnist_model')\nEpoch: 0 - loss: 0.273, acc: 0.924, val_loss: 0.116, val_acc: 0.966: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 60000/60000 [00:12<00:00, 1388.45it/s]\n(...)\nEpoch: 19 - loss: 0.029, acc: 0.991, val_loss: 0.073, val_acc: 0.982: 100%|\u2588\u2588\u2588\u2588\u2588\u2588| 60000/60000 [00:11<00:00, 1846.24it/s]\n>>>\n>>> best_score\n0.982\n```\n\n## Algorithmic details\n\nThe algorithm follows the standard blueprint for a genetic algorithm as e.g. described on this [Wikipedia page](https://en.wikipedia.org/wiki/Genetic_algorithm), which roughly goes like this:\n\n1. An initial population is constructed\n2. Fitness values for all organisms in the population are computed\n3. A subset of the population (the *elite pool*) is selected\n4. A subset of the population (the *breeding pool*) is selected\n5. Pairs from the breeding pool are chosen, who will breed to create a new \"child\" organism with genome a combination of the \"parent\" organisms. Continue breeding until the children and the elites constitute a population of the same size as the original\n6. A subset of the children (the *mutation pool*) is selected\n7. Every child in the mutation pool is mutated, meaning that they will have their genome altered in some way\n8. Go back to step 2\n\nWe now describe the individual steps in this particular implementation in more detail. Note that step 3 is sometimes left out completely, but since that just corresponds to an empty elite pool I decided to keep it in, for generality.\n\n### Step 1: Constructing the initial population\n\nThe population is a uniformly random sample of the possible genome values as dictated by the genus, which is run when a new `Population` object is created. Alternatively, you may set the `initial_genome` to whatever genome you would like, which will create a population consisting of organisms similar to this genome (the result of starting with a population all equal to the organism and then mutating 80% of them).\n\n```python3\n>>> pairs = ns.Population(\n... genus = Pair,\n... size = 100,\n... fitness_fn = lambda n: n.x/n.y,\n... initial_genome = {'x': 9750, 'y': 15}\n... )\n...\n>>> history = pairs.evolve(generations = 100)\nEvolving population: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 100/100 [00:05<00:00, 19.47it/s]\n>>> \n>>> history.fittest\n{'genome' : {'x' : 9989, 'y' : 3}, 'fitness' : 3329.66666666665}\n```\n\n### Step 2: Compute fitness values\n\nThis happens in the `update_fitness` function which is called by the `evolve` function. These computations will by default be computed in parallel when dealing with neural networks and serialised otherwise, as the benefits are only reaped when fitness computations take up a significant part of the algorithm (in the examples above not concerning neural networks we would actually slow down the algorithm non-trivially by introducing parallelism).\n\n### Steps 3 & 4: Selecting elite pool and breeding pool\n\nThese two pools are selected in exactly the same way, using the `sample` function. They only differ in the amount of organisms sampled, where the default `elitism_rate` is 5% and `breeding_rate` is 80%. In the pool selection it chooses the population based on the distribution with density function the fitness value divided by the sum of all fitness values of the population. This means that the higher fitness score an organism has, the more likely it is for it to be chosen to be a part of the pool. The precise implementation of this is based on the algorithm specified on this [Wikipedia page](https://en.wikipedia.org/wiki/Selection_(genetic_algorithm)).\n\n### Step 5: Breeding\n\nIn this implementation the parent organisms are chosen uniformly at random from the breeding pool. When determining the value of the child's genome we apply the \"single-point crossover\" method, where we choose an index uniformly at random among the attributes, and the child will then inherit all attributes to the left of this index from one parent and the attributes to the right of this index from the other parent.See more on [this Wikipedia page](https://en.wikipedia.org/wiki/Crossover_(genetic_algorithm)).\n\n### Step 6: Selection of mutation pool\n\nThe mutation pool is chosen uniformly at random in contrast to the other two pools, as otherwise we would suddenly be more likely to \"mutate away\" many of the good genes of our fittest organisms. The default `mutation_rate` is 20%.\n\n### Step 7: Mutation\n\nThis implementation is roughly the [bit string mutation](https://en.wikipedia.org/wiki/Mutation_(genetic_algorithm)), where every gene of the organism has a 1/n chance of being uniformly randomly replaced by another gene, with n being the number of genes in the organism's genome. This means that, on average, mutation causes one gene to be altered. The amount of genes altered in a mutation can be modified by changing th\u00e8 `mutation_factor` parameter, which by default is the above 1/n.\n\n\n## Possible future extensions\n\nThese are the ideas that I have thought of implementing in the future. Check the ongoing process on the `dev` branch.\n\n* Enable support for CNNs\n* Enable support for RNNs and in particular LSTMs\n* Include an option to have dependency relations between genes. In a neural network setting this could include the topology as a gene on which all the layer-specific genes depend upon, which would be similar to the approach taken in [this paper](https://arxiv.org/pdf/1703.00548/).\n\n\n## License\n\nThis project is licensed under the [MIT License](https://github.com/saattrupdan/naturalselection/blob/master/LICENSE).\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/saattrupdan/naturalselection", "keywords": "genetic algorithm neural network", "license": "", "maintainer": "", "maintainer_email": "", "name": "naturalselection", "package_url": "https://pypi.org/project/naturalselection/", "platform": "", "project_url": "https://pypi.org/project/naturalselection/", "project_urls": { "Homepage": "https://github.com/saattrupdan/naturalselection" }, "release_url": "https://pypi.org/project/naturalselection/0.6.0/", "requires_dist": [ "numpy", "matplotlib", "tqdm", "tensorflow", "sklearn" ], "requires_python": "", "summary": "An all-purpose pythonic genetic algorithm", "version": "0.6.0" }, "last_serial": 5793666, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "15e457367cca2d5d7082647392d284bc", "sha256": "6afae2c887ec7a6f100ef278cf6b21d1bc6c9ae8a991ca21587db0bd5fa53d12" }, "downloads": -1, "filename": "naturalselection-0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "15e457367cca2d5d7082647392d284bc", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 9737, "upload_time": "2019-08-19T15:12:03", "url": "https://files.pythonhosted.org/packages/1c/98/a06c5f242bb915651ce2813da70a89256f8963ca82168998da304dca211e/naturalselection-0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "799758c4ac6b33b7bc66e7797410e77c", "sha256": "96466b546329b7e4530e3bac0e11a40e077f93e57aa31bffd864946fd2061bff" }, "downloads": -1, "filename": "naturalselection-0.1.tar.gz", "has_sig": false, "md5_digest": "799758c4ac6b33b7bc66e7797410e77c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7893, "upload_time": "2019-08-19T15:12:06", "url": "https://files.pythonhosted.org/packages/6b/7f/cad92d1e5c1455eb1392ee2ebf70e793ad9f569c80b53f92df17cda4e52d/naturalselection-0.1.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "d79936185a15d5d75e96fd0920fb6e76", "sha256": "9aa8dba89633b98200eabca5d7dccc7c8248f467b3cb93755efc226c75363c3a" }, "downloads": -1, "filename": "naturalselection-0.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "d79936185a15d5d75e96fd0920fb6e76", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 9762, "upload_time": "2019-08-19T15:17:21", "url": "https://files.pythonhosted.org/packages/93/3e/d7b62c9130c9003c364fb6fc72cc9349bd396ca011d1b30f0b06a2ed84f8/naturalselection-0.1.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ee6bf85d749374abbd51e8d7b46ed173", "sha256": "080c6564222dc66166c0158011d599cbfb0aede90d292486fcd61c9be97918db" }, "downloads": -1, "filename": "naturalselection-0.1.1.tar.gz", "has_sig": false, "md5_digest": "ee6bf85d749374abbd51e8d7b46ed173", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 1295, "upload_time": "2019-08-19T15:23:39", "url": "https://files.pythonhosted.org/packages/16/b0/deba105d8879349bbe2eb917a12b1098756680d64248474a6ff2f0378add/naturalselection-0.1.1.tar.gz" } ], "0.1.10": [ { "comment_text": "", "digests": { "md5": "aa604ddd63db8cc5338d337e5d1a129b", "sha256": "659842b738a6264fe87244f224485e155d9570badeacfc3b5e586b509e34e763" }, "downloads": -1, "filename": "naturalselection-0.1.10.tar.gz", "has_sig": false, "md5_digest": "aa604ddd63db8cc5338d337e5d1a129b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7353, "upload_time": "2019-08-19T16:20:35", "url": "https://files.pythonhosted.org/packages/51/7d/9a9e13ecca77e4d2260cca70b0e4ccba90e1a0c9e14ddb8d7b8f43847acc/naturalselection-0.1.10.tar.gz" } ], "0.1.11": [ { "comment_text": "", "digests": { "md5": "0d675833d1def013723efd001984d015", "sha256": "bd57031a38359ab48e3015cdc44b4f12bf976a3f3ac6014eebb6132022a2d80c" }, "downloads": -1, "filename": "naturalselection-0.1.11.tar.gz", "has_sig": false, "md5_digest": "0d675833d1def013723efd001984d015", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7353, "upload_time": "2019-08-19T16:23:46", "url": "https://files.pythonhosted.org/packages/13/da/54c3ace3b83d56218521e9d24a0e25be96d695fb6dbdf56d7c83522c5fa4/naturalselection-0.1.11.tar.gz" } ], "0.1.12": [ { "comment_text": "", "digests": { "md5": "66862dee31e0d422e54de55290c54062", "sha256": "8b34ddae2b748981b0aced77308b7c0629ad26f07baceae4463369fbc3ffd2eb" }, "downloads": -1, "filename": "naturalselection-0.1.12.tar.gz", "has_sig": false, "md5_digest": "66862dee31e0d422e54de55290c54062", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7785, "upload_time": "2019-08-19T16:31:06", "url": "https://files.pythonhosted.org/packages/9c/5f/2a9e66c13284b154475fa01e619585c9bf7ff344d20e20ca9dfe72740a06/naturalselection-0.1.12.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "4b7eec5e2cd1f16296eb1982601e6bb2", "sha256": "e0a0cf6950e8998f519e8e803776e2bcf90923f39b0df4170bb13d90a48ccb5c" }, "downloads": -1, "filename": "naturalselection-0.1.2.tar.gz", "has_sig": false, "md5_digest": "4b7eec5e2cd1f16296eb1982601e6bb2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 1287, "upload_time": "2019-08-19T15:25:02", "url": "https://files.pythonhosted.org/packages/05/45/ffc1863bcfbcaa77c96f5075bf1bb54553b47cde553a8376084987763788/naturalselection-0.1.2.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "77314383931cca2e94765c85325b657e", "sha256": "bd8c3040132f10f9467fa6d1c7e207c99a16a89d8c86072ee6c9162158674509" }, "downloads": -1, "filename": "naturalselection-0.1.3.tar.gz", "has_sig": false, "md5_digest": "77314383931cca2e94765c85325b657e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 1278, "upload_time": "2019-08-19T15:27:17", "url": "https://files.pythonhosted.org/packages/9d/05/b8c42d9933c9fee2bba771cd3e0bade546affb61f6cf1aa1f1fe7764208e/naturalselection-0.1.3.tar.gz" } ], "0.1.4": [ { "comment_text": "", "digests": { "md5": "45751f5b0a2a6bf12e17633ad31e6d36", "sha256": "ca222118e164dc051b1d5cbc1c6ac16f823625920f6a5939d08fcc961f20c3aa" }, "downloads": -1, "filename": "naturalselection-0.1.4.tar.gz", "has_sig": false, "md5_digest": "45751f5b0a2a6bf12e17633ad31e6d36", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 1259, "upload_time": "2019-08-19T15:29:59", "url": "https://files.pythonhosted.org/packages/56/0c/d4d1d976bdeb584b5ef4be41b53b8b6e47d2e0a64d1eb65e32e61f2d2e67/naturalselection-0.1.4.tar.gz" } ], "0.1.5": [ { "comment_text": "", "digests": { "md5": "df4b293693e160ce012b8e53bd368541", "sha256": "c5658ac37d1f0289b64089a1e21b208768a0d55b90f4a7ac2dae3765d1e80b39" }, "downloads": -1, "filename": "naturalselection-0.1.5.tar.gz", "has_sig": false, "md5_digest": "df4b293693e160ce012b8e53bd368541", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 1229, "upload_time": "2019-08-19T15:37:59", "url": "https://files.pythonhosted.org/packages/71/03/5f299a156fbb0cb1aa2074b6d897f3570bd5d7722e77b3434b386bd9a848/naturalselection-0.1.5.tar.gz" } ], "0.1.6": [ { "comment_text": "", "digests": { "md5": "8f86ff73cc1ff337f2bfa594840df454", "sha256": "bd2ce2242d69692e2917f0d055af6b16e0cefca91cc51e75327439e8aa95de5e" }, "downloads": -1, "filename": "naturalselection-0.1.6.tar.gz", "has_sig": false, "md5_digest": "8f86ff73cc1ff337f2bfa594840df454", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7845, "upload_time": "2019-08-19T15:42:21", "url": "https://files.pythonhosted.org/packages/63/2e/a763f6313f77ce07c0f1cb97abe783de764cc1538e84fa0fce44054f009b/naturalselection-0.1.6.tar.gz" } ], "0.1.7": [ { "comment_text": "", "digests": { "md5": "2f341f95c3254a17f0d31495c82d1da6", "sha256": "98ecfc9d30a74f481d347c0c217e2a7bbc232f33371a5d464941195426cb6459" }, "downloads": -1, "filename": "naturalselection-0.1.7.tar.gz", "has_sig": false, "md5_digest": "2f341f95c3254a17f0d31495c82d1da6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7862, "upload_time": "2019-08-19T15:48:58", "url": "https://files.pythonhosted.org/packages/82/d8/6cb229d56e0216852cd056c2c57a8c98a56c3a44b121d3b0d01675c4071a/naturalselection-0.1.7.tar.gz" } ], "0.1.8": [ { "comment_text": "", "digests": { "md5": "dac67424100b35ae264216b516b1e12f", "sha256": "a474f9766ca7be7423903c861148fd692bf5caccf5a64383f597134e2f95f01a" }, "downloads": -1, "filename": "naturalselection-0.1.8.tar.gz", "has_sig": false, "md5_digest": "dac67424100b35ae264216b516b1e12f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 1221, "upload_time": "2019-08-19T16:00:15", "url": "https://files.pythonhosted.org/packages/4d/18/053931b97acf7b73a34ccd5a69bff0996780a896580d1f3ccda0ca4277f6/naturalselection-0.1.8.tar.gz" } ], "0.1.9": [ { "comment_text": "", "digests": { "md5": "0e2173507456ca8752d5a25b4fa24c6b", "sha256": "d8859e14e1e88d80b4eabb7dc6a368cf41d5f3217437e166de04d4c42de40327" }, "downloads": -1, "filename": "naturalselection-0.1.9.tar.gz", "has_sig": false, "md5_digest": "0e2173507456ca8752d5a25b4fa24c6b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7366, "upload_time": "2019-08-19T16:02:37", "url": "https://files.pythonhosted.org/packages/3a/03/57e1f31dab012d1c25dfa12712a2bfd67b558c40af1695f03284724cb5f3/naturalselection-0.1.9.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "f9bc4f76fd9ba3936b89b25fac653ed4", "sha256": "8bf82cea3725a0e4480ed974709d722098711e7df4b21e72d21dbd1fe24c464a" }, "downloads": -1, "filename": "naturalselection-0.2.0-py3-none-any.whl", "has_sig": false, "md5_digest": "f9bc4f76fd9ba3936b89b25fac653ed4", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 11053, "upload_time": "2019-08-20T15:31:23", "url": "https://files.pythonhosted.org/packages/3b/5b/2f112cdf3c0296bca0fb196e6e7b4768d9d68fffaee32ba75f83fe1dc93a/naturalselection-0.2.0-py3-none-any.whl" } ], "0.2.1": [ { "comment_text": "", "digests": { "md5": "d9beb3f3fa7469fbd2c08968232cdcef", "sha256": "aa92683a1dd1809af7a009bafe831c63d302caed773cc4ea525d1e3422095799" }, "downloads": -1, "filename": "naturalselection-0.2.1-py3-none-any.whl", "has_sig": false, "md5_digest": "d9beb3f3fa7469fbd2c08968232cdcef", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 11031, "upload_time": "2019-08-20T15:38:03", "url": "https://files.pythonhosted.org/packages/aa/48/fa7ab8fec464e59898395769ef15692ed491f2eb700447ea713a2977a286/naturalselection-0.2.1-py3-none-any.whl" } ], "0.2.2": [ { "comment_text": "", "digests": { "md5": "cd61bdf1ecb1416f25466fdb5ff7b5bd", "sha256": "d31931d7e1fe4aa9ee4d1da1f18d37f0e975b3b4153ae13d84d3d048d5301833" }, "downloads": -1, "filename": "naturalselection-0.2.2-py3-none-any.whl", "has_sig": false, "md5_digest": "cd61bdf1ecb1416f25466fdb5ff7b5bd", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 11039, "upload_time": "2019-08-20T15:41:49", "url": "https://files.pythonhosted.org/packages/92/7c/70d4d57c2bda8e72cb1ac9cdda626a6313827981bafd2b290d62cf19982a/naturalselection-0.2.2-py3-none-any.whl" } ], "0.2.3": [ { "comment_text": "", "digests": { "md5": "853582f5a031a4d1a5729d76357cc767", "sha256": "1d123fb199c1f4286dfccd3e269d6e88b94d4a3ded538958df09947a35aba608" }, "downloads": -1, "filename": "naturalselection-0.2.3-py3-none-any.whl", "has_sig": false, "md5_digest": "853582f5a031a4d1a5729d76357cc767", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 11051, "upload_time": "2019-08-20T15:44:20", "url": "https://files.pythonhosted.org/packages/bd/23/46b4192a972452a431dfc863dbd8fe49878b197d4ac5d49a7afcc36d68d9/naturalselection-0.2.3-py3-none-any.whl" } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "0ab79a78b4f26d3d398da3678239d06a", "sha256": "7b79e031c8e029bc26322cecaa12a27c9965ac14dcdab80b244be304af5e8c7e" }, "downloads": -1, "filename": "naturalselection-0.3.0-py3-none-any.whl", "has_sig": false, "md5_digest": "0ab79a78b4f26d3d398da3678239d06a", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 14527, "upload_time": "2019-08-25T09:51:41", "url": "https://files.pythonhosted.org/packages/7b/e9/80ca2f11d7d544e8ad405890b243685ab0cfcad492edacfe2cb4a588e45c/naturalselection-0.3.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "87a1a20ab5cc5373b4d11f22224243c7", "sha256": "8e9ea633ca90983ba4b0b598dc3db43423263f6185fa6f730419c37662972ba7" }, "downloads": -1, "filename": "naturalselection-0.3.0.tar.gz", "has_sig": false, "md5_digest": "87a1a20ab5cc5373b4d11f22224243c7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16571, "upload_time": "2019-08-25T09:51:43", "url": "https://files.pythonhosted.org/packages/f7/b5/05196e30b2fc616cd90deca46c68b379e4599b59e1b2bda4d8cef296328c/naturalselection-0.3.0.tar.gz" } ], "0.3.1": [ { "comment_text": "", "digests": { "md5": "5a0ef68c75f47917a7bc1d774c868074", "sha256": "1fdf0e64fa12548493829c0d66d105159d337fb450622870be912baf90c27d1b" }, "downloads": -1, "filename": "naturalselection-0.3.1-py3-none-any.whl", "has_sig": false, "md5_digest": "5a0ef68c75f47917a7bc1d774c868074", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 14507, "upload_time": "2019-08-25T10:01:38", "url": "https://files.pythonhosted.org/packages/61/58/0183046d5fbaa8c86a6aa55c405b36a24baa477e074ae29a320062906633/naturalselection-0.3.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "0f15d3a2379ff92523adeb6b7a033f76", "sha256": "57bf1b4f679a305a8cf0241e8e5d6f7eb35ebc192853117463aa2fe37bbbd299" }, "downloads": -1, "filename": "naturalselection-0.3.1.tar.gz", "has_sig": false, "md5_digest": "0f15d3a2379ff92523adeb6b7a033f76", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16487, "upload_time": "2019-08-25T10:01:40", "url": "https://files.pythonhosted.org/packages/6e/11/5593b7bdef3a15693f1e5d977ed012e7ff0c714026e2283b5505a6b9fc5e/naturalselection-0.3.1.tar.gz" } ], "0.3.2": [ { "comment_text": "", "digests": { "md5": "56f62701ada4a0fbdec9b91284ad006d", "sha256": "583ce04d10a14d090691330ced23d9058d2470e027f3dd3a43ca377c0e7e8cbf" }, "downloads": -1, "filename": "naturalselection-0.3.2-py3-none-any.whl", "has_sig": false, "md5_digest": "56f62701ada4a0fbdec9b91284ad006d", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 14586, "upload_time": "2019-08-25T11:53:47", "url": "https://files.pythonhosted.org/packages/f8/f9/2b6a9884021c5841aa8c8161d5a661e9f0d9d1a91890e0858c3c29ff8748/naturalselection-0.3.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "75f7774ef4214d3117c8f0d4826cfc2a", "sha256": "91807df58ff2abd8073e102aab0967218acc2384fbab765cf07bdb302c2471d8" }, "downloads": -1, "filename": "naturalselection-0.3.2.tar.gz", "has_sig": false, "md5_digest": "75f7774ef4214d3117c8f0d4826cfc2a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16601, "upload_time": "2019-08-25T11:53:51", "url": "https://files.pythonhosted.org/packages/3a/fe/13fff7cf8f820b49b64d7f4b0c48a128c8ef58659dadf5f14a35e48089fa/naturalselection-0.3.2.tar.gz" } ], "0.3.3": [ { "comment_text": "", "digests": { "md5": "4fa0ad4a4d0aa9c6f8883a11670656e8", "sha256": "f4bfd3b7302cb55327021fc30876ef6cd640ad1d126cb64af799aff4c17dc842" }, "downloads": -1, "filename": "naturalselection-0.3.3-py3-none-any.whl", "has_sig": false, "md5_digest": "4fa0ad4a4d0aa9c6f8883a11670656e8", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 14586, "upload_time": "2019-08-25T11:56:29", "url": "https://files.pythonhosted.org/packages/a8/14/d1b9b2c5508456cd198b735065be0830190612ce74c497b63d423e9bfa6a/naturalselection-0.3.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "7a50e81906303d4c1aeacd29e8428dad", "sha256": "850b100bd1868c5d6f24e94663281cf2308f8c55ea5be907abd85de6c5a96042" }, "downloads": -1, "filename": "naturalselection-0.3.3.tar.gz", "has_sig": false, "md5_digest": "7a50e81906303d4c1aeacd29e8428dad", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16597, "upload_time": "2019-08-25T11:56:32", "url": "https://files.pythonhosted.org/packages/17/b0/8e2c2a0524b1cb55b2bcf28951453653bd8201ce03be020530a9ba684a66/naturalselection-0.3.3.tar.gz" } ], "0.3.4": [ { "comment_text": "", "digests": { "md5": "74452cb0a2a80ab918a3553bd697f732", "sha256": "e70518ae0fa5113f280d0ff1622f8fcdbda5203537e5c6609911f3aa1f1dc2ba" }, "downloads": -1, "filename": "naturalselection-0.3.4-py3-none-any.whl", "has_sig": false, "md5_digest": "74452cb0a2a80ab918a3553bd697f732", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 14590, "upload_time": "2019-08-25T12:04:14", "url": "https://files.pythonhosted.org/packages/8f/26/ba05912e180eef9e9b5ef6172c281daeef90432eb833e0de15395a1f634a/naturalselection-0.3.4-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d58795e483d4f368c6bc82c4d114edef", "sha256": "2d675ed503b505d5f00be206cc823c83c7ebca9aa91d883f8aebf7aa78833d34" }, "downloads": -1, "filename": "naturalselection-0.3.4.tar.gz", "has_sig": false, "md5_digest": "d58795e483d4f368c6bc82c4d114edef", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16599, "upload_time": "2019-08-25T12:04:16", "url": "https://files.pythonhosted.org/packages/d2/7d/0f5726f2062086540a581177521bfc41b84ed02ba684a3bbe4af0a56560b/naturalselection-0.3.4.tar.gz" } ], "0.4.0": [ { "comment_text": "", "digests": { "md5": "2b443363a5c55d5d0899978fb2614c40", "sha256": "6cb4e1d6af4a76eeee15d82f5c7f6e40a618134af55140e3983b73027377bc15" }, "downloads": -1, "filename": "naturalselection-0.4.0-py3-none-any.whl", "has_sig": false, "md5_digest": "2b443363a5c55d5d0899978fb2614c40", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 16139, "upload_time": "2019-08-30T10:54:30", "url": "https://files.pythonhosted.org/packages/52/b3/1c8af3bcb03f076db0ec7a08bfe1bebea66538622010cb3e1f219874a265/naturalselection-0.4.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "5dd129c13a6a3ade60e80d20fb42cd69", "sha256": "c3ed6f399bff3f98d0c6657c7b7a5dfb93fca3bc9aac6c9de8be878f028599a2" }, "downloads": -1, "filename": "naturalselection-0.4.0.tar.gz", "has_sig": false, "md5_digest": "5dd129c13a6a3ade60e80d20fb42cd69", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18134, "upload_time": "2019-08-30T10:54:32", "url": "https://files.pythonhosted.org/packages/15/7d/64868af3e5769e5ef773968f0212a0a219620d8afc4774573f8918722488/naturalselection-0.4.0.tar.gz" } ], "0.5.0": [ { "comment_text": "", "digests": { "md5": "a12d6637d7d626c82380dfbc82d955e8", "sha256": "e383cd598a06e57ad86f570f3211c0c14e6e9f99675df89bf32cc581397b8636" }, "downloads": -1, "filename": "naturalselection-0.5.0-py3-none-any.whl", "has_sig": false, "md5_digest": "a12d6637d7d626c82380dfbc82d955e8", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 17953, "upload_time": "2019-09-03T15:15:11", "url": "https://files.pythonhosted.org/packages/d4/64/edcc911a9a60a2c91a7c7948ddb5404bcaa9dc7370ea4df1226897d1f010/naturalselection-0.5.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "fa5ea5fc4f185d6e5bbc69c51fb5a425", "sha256": "eaf9d8fa3574150c5b43c92c7032179f9a18e0f15ca9bf2789bb4d95ed4f0130" }, "downloads": -1, "filename": "naturalselection-0.5.0.tar.gz", "has_sig": false, "md5_digest": "fa5ea5fc4f185d6e5bbc69c51fb5a425", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19577, "upload_time": "2019-09-03T15:15:13", "url": "https://files.pythonhosted.org/packages/c0/29/fb59a3c16c9021e06e2cf364d973ec70a51f7c754ec6956fb2ac3e63cf19/naturalselection-0.5.0.tar.gz" } ], "0.6.0": [ { "comment_text": "", "digests": { "md5": "fe9dbc5fc44efc3987819624fa0c1d38", "sha256": "9e0dee6d6c89a1275f49a4fd8dea70302ac720c89383cbc1680ac418beb83224" }, "downloads": -1, "filename": "naturalselection-0.6.0-py3-none-any.whl", "has_sig": false, "md5_digest": "fe9dbc5fc44efc3987819624fa0c1d38", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 18236, "upload_time": "2019-09-06T19:50:01", "url": "https://files.pythonhosted.org/packages/b3/ef/1af4f1b8c6986170ed75e1326eaa325957871d93731c4ee4a7d81aa554ea/naturalselection-0.6.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "609a7d491367714008ca32ea0f36faa3", "sha256": "2d2c5dc8251e442c993d255adfb940a0c467f8a45c6434d72514c93aabb42dad" }, "downloads": -1, "filename": "naturalselection-0.6.0.tar.gz", "has_sig": false, "md5_digest": "609a7d491367714008ca32ea0f36faa3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19916, "upload_time": "2019-09-06T19:50:03", "url": "https://files.pythonhosted.org/packages/05/ba/261ac7e768f0e81a5389a2a0997ceee7c7d73f1f3c0bd6e1b081f6d7a338/naturalselection-0.6.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "fe9dbc5fc44efc3987819624fa0c1d38", "sha256": "9e0dee6d6c89a1275f49a4fd8dea70302ac720c89383cbc1680ac418beb83224" }, "downloads": -1, "filename": "naturalselection-0.6.0-py3-none-any.whl", "has_sig": false, "md5_digest": "fe9dbc5fc44efc3987819624fa0c1d38", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 18236, "upload_time": "2019-09-06T19:50:01", "url": "https://files.pythonhosted.org/packages/b3/ef/1af4f1b8c6986170ed75e1326eaa325957871d93731c4ee4a7d81aa554ea/naturalselection-0.6.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "609a7d491367714008ca32ea0f36faa3", "sha256": "2d2c5dc8251e442c993d255adfb940a0c467f8a45c6434d72514c93aabb42dad" }, "downloads": -1, "filename": "naturalselection-0.6.0.tar.gz", "has_sig": false, "md5_digest": "609a7d491367714008ca32ea0f36faa3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19916, "upload_time": "2019-09-06T19:50:03", "url": "https://files.pythonhosted.org/packages/05/ba/261ac7e768f0e81a5389a2a0997ceee7c7d73f1f3c0bd6e1b081f6d7a338/naturalselection-0.6.0.tar.gz" } ] }