├── Solid ├── __init__.py ├── StochasticHillClimb.py ├── TabuSearch.py ├── HarmonySearch.py ├── SimulatedAnnealing.py ├── EvolutionaryAlgorithm.py ├── GeneticAlgorithm.py └── ParticleSwarm.py ├── docs ├── .nojekyll ├── _static │ ├── custom.css │ ├── up.png │ ├── down.png │ ├── file.png │ ├── minus.png │ ├── plus.png │ ├── comment.png │ ├── ajax-loader.gif │ ├── up-pressed.png │ ├── comment-close.png │ ├── down-pressed.png │ ├── comment-bright.png │ ├── pygments.css │ ├── doctools.js │ ├── underscore.js │ ├── basic.css │ └── alabaster.css ├── objects.inv ├── _sources │ ├── modules.rst.txt │ ├── index.rst.txt │ └── Solid.rst.txt ├── .buildinfo ├── _modules │ ├── index.html │ └── Solid │ │ ├── StochasticHillClimb.html │ │ ├── TabuSearch.html │ │ └── SimulatedAnnealing.html ├── search.html ├── index.html ├── modules.html ├── searchindex.js ├── py-modindex.html └── genindex.html ├── tests ├── __init__.py ├── test_particle_swarm.py ├── test_harmony_search.py ├── test_genetic_algorithm.py ├── test_simulated_annealing.py ├── test_stochastic_hill_climb.py ├── test_tabu_search.py └── test_evolutionary_algorithm.py ├── setup.cfg ├── logo.png ├── MANIFEST ├── .travis.yml ├── setup.py ├── LICENSE ├── .gitignore └── README.md /Solid/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaarv/Solid/HEAD/logo.png -------------------------------------------------------------------------------- /docs/_static/custom.css: -------------------------------------------------------------------------------- 1 | /* This file intentionally left blank. */ 2 | -------------------------------------------------------------------------------- /docs/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaarv/Solid/HEAD/docs/objects.inv -------------------------------------------------------------------------------- /docs/_static/up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaarv/Solid/HEAD/docs/_static/up.png -------------------------------------------------------------------------------- /docs/_static/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaarv/Solid/HEAD/docs/_static/down.png -------------------------------------------------------------------------------- /docs/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaarv/Solid/HEAD/docs/_static/file.png -------------------------------------------------------------------------------- /docs/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaarv/Solid/HEAD/docs/_static/minus.png -------------------------------------------------------------------------------- /docs/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaarv/Solid/HEAD/docs/_static/plus.png -------------------------------------------------------------------------------- /docs/_static/comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaarv/Solid/HEAD/docs/_static/comment.png -------------------------------------------------------------------------------- /docs/_static/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaarv/Solid/HEAD/docs/_static/ajax-loader.gif -------------------------------------------------------------------------------- /docs/_static/up-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaarv/Solid/HEAD/docs/_static/up-pressed.png -------------------------------------------------------------------------------- /docs/_static/comment-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaarv/Solid/HEAD/docs/_static/comment-close.png -------------------------------------------------------------------------------- /docs/_static/down-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaarv/Solid/HEAD/docs/_static/down-pressed.png -------------------------------------------------------------------------------- /docs/_sources/modules.rst.txt: -------------------------------------------------------------------------------- 1 | Solid 2 | ===== 3 | 4 | .. toctree:: 5 | :maxdepth: 4 6 | 7 | Solid 8 | -------------------------------------------------------------------------------- /docs/_static/comment-bright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaarv/Solid/HEAD/docs/_static/comment-bright.png -------------------------------------------------------------------------------- /docs/.buildinfo: -------------------------------------------------------------------------------- 1 | # Sphinx build info version 1 2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. 3 | config: b691e48017afb30514be38e8c3446b04 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /MANIFEST: -------------------------------------------------------------------------------- 1 | # file GENERATED by distutils, do NOT edit 2 | setup.cfg 3 | setup.py 4 | Solid/EvolutionaryAlgorithm.py 5 | Solid/GeneticAlgorithm.py 6 | Solid/HarmonySearch.py 7 | Solid/ParticleSwarm.py 8 | Solid/SimulatedAnnealing.py 9 | Solid/StochasticHillClimb.py 10 | Solid/TabuSearch.py 11 | Solid/__init__.py 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | dist: trusty 3 | language: python 4 | python: 5 | - "2.7.13" 6 | - "3.6.1" 7 | - "nightly" # currently points to 3.7-dev 8 | before_install: 9 | - pip install flake8 10 | # exit-zero treates all errors as warnings. The GitHub editor is 127 chars wide 11 | - flake8 . --count --exit-zero --max-line-length=127 --statistics 12 | install: 13 | - pip install numpy 14 | script: py.test -s 15 | -------------------------------------------------------------------------------- /docs/_sources/index.rst.txt: -------------------------------------------------------------------------------- 1 | .. Solid documentation master file, created by 2 | sphinx-quickstart on Mon Jun 19 19:02:57 2017. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to Solid's documentation! 7 | ================================= 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | :caption: Contents: 12 | 13 | 14 | 15 | Indices and tables 16 | ================== 17 | 18 | * :ref:`genindex` 19 | * :ref:`modindex` 20 | * :ref:`search` 21 | -------------------------------------------------------------------------------- /tests/test_particle_swarm.py: -------------------------------------------------------------------------------- 1 | from Solid.ParticleSwarm import ParticleSwarm 2 | 3 | 4 | class Algorithm(ParticleSwarm): 5 | """ 6 | Tries to get a randomly-generated list to match [.1, .2, .3, .2, .1] 7 | """ 8 | def _objective(self, member): 9 | return sum(abs(member[i] - [.1, .2, .3, .2, .1][i]) if (member[i] > 0 or member[i] < 0) else 1 for i in range(5)) 10 | 11 | 12 | def test_algorithm(): 13 | algorithm = Algorithm(50, 5, [0.,0.,0.,0.,0.], [1.,1.,1.,1.,1.], 1., 2., 2., 500, min_objective=None) 14 | algorithm.run() 15 | -------------------------------------------------------------------------------- /tests/test_harmony_search.py: -------------------------------------------------------------------------------- 1 | from random import uniform 2 | from Solid.HarmonySearch import HarmonySearch 3 | 4 | 5 | class Algorithm(HarmonySearch): 6 | """ 7 | Tries to get a randomly-generated list to match [.1, .2, .3, .2, .1] 8 | """ 9 | def _random_harmony(self): 10 | return list([uniform(0, 1) for _ in range(5)]) 11 | 12 | def _score(self, member): 13 | return 1./ sum(abs(member[i] - [.1, .2, .3, .2, .1][i]) for i in range(5)) 14 | 15 | 16 | def test_algorithm(): 17 | algorithm = Algorithm(50, .5, .3, .01, 2000, max_score=None) 18 | algorithm.run() 19 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | setup( 3 | name = 'solidpy', 4 | packages = ['Solid'], 5 | version = '0.11', 6 | description = 'A comprehensive gradient-free optimization library', 7 | author = 'Devin Soni', 8 | author_email = 'devinsoni1010@gmail.com', 9 | url = 'https://github.com/100/Solid', 10 | download_url = 'https://github.com/100/Solid/archive/0.1.tar.gz', 11 | keywords = ['metaheuristic', 'optimization', 'algorithm', 'artificial intelligence', 'machine learning'], 12 | classifiers = ['Programming Language :: Python :: 2.7'], 13 | install_requires=[ 14 | 'numpy' 15 | ], 16 | ) -------------------------------------------------------------------------------- /tests/test_genetic_algorithm.py: -------------------------------------------------------------------------------- 1 | from random import choice 2 | from Solid.GeneticAlgorithm import GeneticAlgorithm 3 | 4 | 5 | class Algorithm(GeneticAlgorithm): 6 | """ 7 | Tries to get a randomly-generated string to match 000111 8 | """ 9 | def _initial_population(self): 10 | return list(list([choice([0, 1]) for _ in range(6)]) for _ in range(50)) 11 | 12 | def _fitness(self, member): 13 | return float(sum(member[i] == [0,0,0,1,1,1][i] for i in range(6))) 14 | 15 | 16 | def test_algorithm(): 17 | algorithm = Algorithm(.5, .7, 500, max_fitness=None) 18 | algorithm.run() 19 | -------------------------------------------------------------------------------- /tests/test_simulated_annealing.py: -------------------------------------------------------------------------------- 1 | from random import uniform 2 | from Solid.SimulatedAnnealing import SimulatedAnnealing 3 | from numpy import array 4 | 5 | 6 | class Algorithm(SimulatedAnnealing): 7 | """ 8 | Tries to get a randomly-generated list to match [.1, .2, .3, .2, .1] 9 | """ 10 | def _neighbor(self): 11 | return list(array(self.current_state) + array([uniform(-.02, .02) for _ in range(5)])) 12 | 13 | def _energy(self, member): 14 | return sum(abs(member[i] - [.1, .2, .3, .2, .1][i]) if (member[i] > 0 or member[i] < 0) else 1 for i in range(5)) 15 | 16 | 17 | def test_algorithm(): 18 | algorithm = Algorithm(list([uniform(0, 1) for _ in range(5)]), 5, .99, 5000) 19 | algorithm.run() 20 | -------------------------------------------------------------------------------- /tests/test_stochastic_hill_climb.py: -------------------------------------------------------------------------------- 1 | from random import uniform 2 | from Solid.StochasticHillClimb import StochasticHillClimb 3 | from numpy import array 4 | 5 | 6 | class Algorithm(StochasticHillClimb): 7 | """ 8 | Tries to get a randomly-generated list to match [.1, .2, .3, .2, .1] 9 | """ 10 | def _neighbor(self): 11 | return list(array(self.current_state) + array([uniform(-.02, .02) for _ in range(5)])) 12 | 13 | def _objective(self, state): 14 | return 1. / sum(abs(state[i] - [.1, .2, .3, .2, .1][i]) if (state[i] > 0 or state[i] < 0) else 1 for i in range(5)) 15 | 16 | 17 | def test_algorithm(): 18 | algorithm = Algorithm(list([uniform(0, 1) for _ in range(5)]), .01, 1000) 19 | algorithm.run() 20 | -------------------------------------------------------------------------------- /tests/test_tabu_search.py: -------------------------------------------------------------------------------- 1 | from random import choice, randint, random 2 | from string import ascii_lowercase 3 | from Solid.TabuSearch import TabuSearch 4 | from copy import deepcopy 5 | 6 | 7 | class Algorithm(TabuSearch): 8 | """ 9 | Tries to get a randomly-generated string to match string "clout" 10 | """ 11 | def _neighborhood(self): 12 | member = list(self.current) 13 | neighborhood = [] 14 | for _ in range(10): 15 | neighbor = deepcopy(member) 16 | neighbor[randint(0, 4)] = choice(ascii_lowercase) 17 | neighbor = ''.join(neighbor) 18 | neighborhood.append(neighbor) 19 | return neighborhood 20 | 21 | def _score(self, state): 22 | return float(sum(state[i] == "clout"[i] for i in range(5))) 23 | 24 | 25 | def test_algorithm(): 26 | algorithm = Algorithm('abcde', 50, 500, max_score=None) 27 | algorithm.run() 28 | -------------------------------------------------------------------------------- /tests/test_evolutionary_algorithm.py: -------------------------------------------------------------------------------- 1 | from random import choice, randint, random 2 | from string import ascii_lowercase 3 | from Solid.EvolutionaryAlgorithm import EvolutionaryAlgorithm 4 | 5 | 6 | class Algorithm(EvolutionaryAlgorithm): 7 | """ 8 | Tries to get a randomly-generated string to match string "clout" 9 | """ 10 | def _initial_population(self): 11 | return list(''.join([choice(ascii_lowercase) for _ in range(5)]) for _ in range(50)) 12 | 13 | def _fitness(self, member): 14 | return float(sum(member[i] == "clout"[i] for i in range(5))) 15 | 16 | def _crossover(self, parent1, parent2): 17 | partition = randint(0, len(self.population[0]) - 1) 18 | return parent1[0:partition] + parent2[partition:] 19 | 20 | def _mutate(self, member): 21 | if self.mutation_rate >= random(): 22 | member = list(member) 23 | member[randint(0, 4)] = choice(ascii_lowercase) 24 | member = ''.join(member) 25 | return member 26 | 27 | 28 | def test_algorithm(): 29 | algorithm = Algorithm(.5, .7, 500, max_fitness=None) 30 | algorithm.run() 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Devin Soni 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/_sources/Solid.rst.txt: -------------------------------------------------------------------------------- 1 | Solid package 2 | ============= 3 | 4 | Submodules 5 | ---------- 6 | 7 | Solid\.EvolutionaryAlgorithm module 8 | ----------------------------------- 9 | 10 | .. automodule:: Solid.EvolutionaryAlgorithm 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | Solid\.GeneticAlgorithm module 16 | ------------------------------ 17 | 18 | .. automodule:: Solid.GeneticAlgorithm 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | Solid\.HarmonySearch module 24 | --------------------------- 25 | 26 | .. automodule:: Solid.HarmonySearch 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | Solid\.ParticleSwarm module 32 | --------------------------- 33 | 34 | .. automodule:: Solid.ParticleSwarm 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | Solid\.SimulatedAnnealing module 40 | -------------------------------- 41 | 42 | .. automodule:: Solid.SimulatedAnnealing 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | Solid\.StochasticHillClimb module 48 | --------------------------------- 49 | 50 | .. automodule:: Solid.StochasticHillClimb 51 | :members: 52 | :undoc-members: 53 | :show-inheritance: 54 | 55 | Solid\.TabuSearch module 56 | ------------------------ 57 | 58 | .. automodule:: Solid.TabuSearch 59 | :members: 60 | :undoc-members: 61 | :show-inheritance: 62 | 63 | 64 | Module contents 65 | --------------- 66 | 67 | .. automodule:: Solid 68 | :members: 69 | :undoc-members: 70 | :show-inheritance: 71 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | .venv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | 103 | .idea/ 104 | 105 | sphinx/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
6 | 7 | [![Build Status](https://travis-ci.org/100/Solid.svg?branch=master)](https://travis-ci.org/100/Solid) 8 | [![MIT License](https://img.shields.io/dub/l/vibe-d.svg)](https://github.com/100/Cranium/blob/master/LICENSE) 9 | 10 | ## *Solid* is a Python framework for gradient-free optimization. 11 | 12 | #### It contains basic versions of many of the most common [optimization algorithms that do not require the calculation of gradients](https://en.wikipedia.org/wiki/Derivative-free_optimization), and allows for very rapid development using them. 13 | 14 | #### It's a very versatile library that's great for learning, modifying, and of course, using out-of-the-box. 15 | 16 | ## See the detailed documentation [here](https://100.github.io/Solid/). 17 | 18 |
19 | 20 | ## Current Features: 21 | * [Genetic Algorithm](https://github.com/100/Solid/blob/master/Solid/GeneticAlgorithm.py) 22 | * [Evolutionary Algorithm](https://github.com/100/Solid/blob/master/Solid/EvolutionaryAlgorithm.py) 23 | * [Simulated Annealing](https://github.com/100/Solid/blob/master/Solid/SimulatedAnnealing.py) 24 | * [Particle Swarm Optimization](https://github.com/100/Solid/blob/master/Solid/ParticleSwarm.py) 25 | * [Tabu Search](https://github.com/100/Solid/blob/master/Solid/TabuSearch.py) 26 | * [Harmony Search](https://github.com/100/Solid/blob/master/Solid/HarmonySearch.py) 27 | * [Stochastic Hill Climb](https://github.com/100/Solid/blob/master/Solid/StochasticHillClimb.py) 28 | 29 |
30 | 31 | ## Usage: 32 | * ```pip install solidpy``` 33 | * Import the relevant algorithm 34 | * Create a class that inherits from that algorithm, and that implements the necessary abstract methods 35 | * Call its ```.run()``` method, which always returns the best solution and its objective function value 36 | 37 |
38 | 39 | ## Example: 40 | 41 | ```python 42 | from random import choice, randint, random 43 | from string import lowercase 44 | from Solid.EvolutionaryAlgorithm import EvolutionaryAlgorithm 45 | 46 | 47 | class Algorithm(EvolutionaryAlgorithm): 48 | """ 49 | Tries to get a randomly-generated string to match string "clout" 50 | """ 51 | def _initial_population(self): 52 | return list(''.join([choice(lowercase) for _ in range(5)]) for _ in range(50)) 53 | 54 | def _fitness(self, member): 55 | return float(sum(member[i] == "clout"[i] for i in range(5))) 56 | 57 | def _crossover(self, parent1, parent2): 58 | partition = randint(0, len(self.population[0]) - 1) 59 | return parent1[0:partition] + parent2[partition:] 60 | 61 | def _mutate(self, member): 62 | if self.mutation_rate >= random(): 63 | member = list(member) 64 | member[randint(0,4)] = choice(lowercase) 65 | member = ''.join(member) 66 | return member 67 | 68 | 69 | def test_algorithm(): 70 | algorithm = Algorithm(.5, .7, 500, max_fitness=None) 71 | best_solution, best_objective_value = algorithm.run() 72 | 73 | ``` 74 | 75 |
76 | 77 | ## Testing 78 | 79 | To run tests, look in the ```tests``` folder. 80 | 81 | Use [pytest](https://docs.pytest.org/en/latest/); it should automatically find the test files. 82 | 83 |
84 | 85 | ## Contributing 86 | 87 | Feel free to send a pull request if you want to add any features or if you find a bug. 88 | 89 | Check the issues tab for some potential things to do. 90 | 91 | -------------------------------------------------------------------------------- /docs/_modules/index.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | Overview: module code — Solid 0.11 documentation 10 | 11 | 12 | 13 | 14 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
40 |
41 |
42 |
43 | 44 |

All modules for which code is available

45 | 53 | 54 |
55 |
56 |
57 | 77 |
78 |
79 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /docs/search.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | Search — Solid 0.11 documentation 10 | 11 | 12 | 13 | 14 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 |
48 |
49 |
50 |
51 | 52 |

Search

53 |
54 | 55 |

56 | Please activate JavaScript to enable the search 57 | functionality. 58 |

59 |
60 |

61 | From here you can search these documents. Enter your search 62 | words into the box below and click "search". Note that the search 63 | function will automatically search for all of the words. Pages 64 | containing fewer words won't appear in the result list. 65 |

66 |
67 | 68 | 69 | 70 |
71 | 72 |
73 | 74 |
75 | 76 |
77 |
78 |
79 | 89 |
90 |
91 | 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | Welcome to Solid’s documentation! — Solid 0.11 documentation 10 | 11 | 12 | 13 | 14 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
40 |
41 |
42 |
43 | 44 |
45 |

Welcome to Solid’s documentation!

46 |
47 |
48 |
49 |
50 |

Indices and tables

51 | 56 |
57 | 58 | 59 |
60 |
61 |
62 | 95 |
96 |
97 | 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /docs/_static/pygments.css: -------------------------------------------------------------------------------- 1 | .highlight .hll { background-color: #ffffcc } 2 | .highlight { background: #eeffcc; } 3 | .highlight .c { color: #408090; font-style: italic } /* Comment */ 4 | .highlight .err { border: 1px solid #FF0000 } /* Error */ 5 | .highlight .k { color: #007020; font-weight: bold } /* Keyword */ 6 | .highlight .o { color: #666666 } /* Operator */ 7 | .highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */ 8 | .highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ 9 | .highlight .cp { color: #007020 } /* Comment.Preproc */ 10 | .highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */ 11 | .highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ 12 | .highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ 13 | .highlight .gd { color: #A00000 } /* Generic.Deleted */ 14 | .highlight .ge { font-style: italic } /* Generic.Emph */ 15 | .highlight .gr { color: #FF0000 } /* Generic.Error */ 16 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 17 | .highlight .gi { color: #00A000 } /* Generic.Inserted */ 18 | .highlight .go { color: #333333 } /* Generic.Output */ 19 | .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ 20 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 21 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 22 | .highlight .gt { color: #0044DD } /* Generic.Traceback */ 23 | .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ 24 | .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ 25 | .highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ 26 | .highlight .kp { color: #007020 } /* Keyword.Pseudo */ 27 | .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ 28 | .highlight .kt { color: #902000 } /* Keyword.Type */ 29 | .highlight .m { color: #208050 } /* Literal.Number */ 30 | .highlight .s { color: #4070a0 } /* Literal.String */ 31 | .highlight .na { color: #4070a0 } /* Name.Attribute */ 32 | .highlight .nb { color: #007020 } /* Name.Builtin */ 33 | .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ 34 | .highlight .no { color: #60add5 } /* Name.Constant */ 35 | .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ 36 | .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ 37 | .highlight .ne { color: #007020 } /* Name.Exception */ 38 | .highlight .nf { color: #06287e } /* Name.Function */ 39 | .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ 40 | .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ 41 | .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ 42 | .highlight .nv { color: #bb60d5 } /* Name.Variable */ 43 | .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ 44 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 45 | .highlight .mb { color: #208050 } /* Literal.Number.Bin */ 46 | .highlight .mf { color: #208050 } /* Literal.Number.Float */ 47 | .highlight .mh { color: #208050 } /* Literal.Number.Hex */ 48 | .highlight .mi { color: #208050 } /* Literal.Number.Integer */ 49 | .highlight .mo { color: #208050 } /* Literal.Number.Oct */ 50 | .highlight .sa { color: #4070a0 } /* Literal.String.Affix */ 51 | .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ 52 | .highlight .sc { color: #4070a0 } /* Literal.String.Char */ 53 | .highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */ 54 | .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ 55 | .highlight .s2 { color: #4070a0 } /* Literal.String.Double */ 56 | .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ 57 | .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ 58 | .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ 59 | .highlight .sx { color: #c65d09 } /* Literal.String.Other */ 60 | .highlight .sr { color: #235388 } /* Literal.String.Regex */ 61 | .highlight .s1 { color: #4070a0 } /* Literal.String.Single */ 62 | .highlight .ss { color: #517918 } /* Literal.String.Symbol */ 63 | .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ 64 | .highlight .fm { color: #06287e } /* Name.Function.Magic */ 65 | .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ 66 | .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ 67 | .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ 68 | .highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */ 69 | .highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ -------------------------------------------------------------------------------- /Solid/StochasticHillClimb.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | from copy import deepcopy 3 | from math import exp 4 | from random import random 5 | 6 | 7 | class StochasticHillClimb: 8 | """ 9 | Conducts stochastic hill climb 10 | """ 11 | __metaclass__ = ABCMeta 12 | 13 | initial_state = None 14 | current_state = None 15 | best_state = None 16 | 17 | cur_steps = 0 18 | max_steps = None 19 | 20 | best_objective = None 21 | max_objective = None 22 | 23 | temp = None 24 | 25 | def __init__(self, initial_state, temp, max_steps, max_objective=None): 26 | """ 27 | 28 | :param initial_state: initial state of hill climbing 29 | :param max_steps: maximum steps to run hill climbing for 30 | :param temp: temperature in probabilistic acceptance of transition 31 | :param max_objective: objective function to stop algorithm once reached 32 | """ 33 | self.initial_state = initial_state 34 | 35 | if isinstance(max_steps, int) and max_steps > 0: 36 | self.max_steps = max_steps 37 | else: 38 | raise ValueError('Max steps must be a positive integer') 39 | 40 | if max_objective is not None: 41 | if isinstance(max_objective, (float, int)): 42 | self.max_objective = float(max_objective) 43 | else: 44 | raise ValueError('Maximum objective must be a numeric type') 45 | 46 | if isinstance(temp, (float, int)): 47 | self.temp = float(temp) 48 | else: 49 | raise ValueError('Temperature must be a numeric type') 50 | 51 | def __str__(self): 52 | return ('STOCHASTIC HILL CLIMB: \n' + 53 | 'CURRENT STEPS: %d \n' + 54 | 'BEST OBJECTIVE: %f \n' + 55 | 'BEST STATE: %s \n\n') % \ 56 | (self.cur_steps, self.best_objective, str(self.best_state)) 57 | 58 | def __repr__(self): 59 | return self.__str__() 60 | 61 | def _clear(self): 62 | """ 63 | Resets the variables that are altered on a per-run basis of the algorithm 64 | 65 | :return: None 66 | """ 67 | self.cur_steps = 0 68 | self.current_state = None 69 | self.best_state = None 70 | self.best_objective = None 71 | 72 | @abstractmethod 73 | def _neighbor(self): 74 | """ 75 | Returns a random member of the neighbor of the current state 76 | 77 | :return: a random neighbor, given access to self.current_state 78 | """ 79 | pass 80 | 81 | @abstractmethod 82 | def _objective(self, state): 83 | """ 84 | Evaluates a given state 85 | 86 | :param state: a state 87 | :return: objective function value of state 88 | """ 89 | pass 90 | 91 | def _accept_neighbor(self, neighbor): 92 | """ 93 | Probabilistically determines whether or not to accept a transition to a neighbor 94 | 95 | :param neighbor: a state 96 | :return: boolean indicating whether or not transition was accepted 97 | """ 98 | try: 99 | p = 1. / (1 + (exp((self._objective(self.current_state) - self._objective(neighbor)) / self.temp))) 100 | except OverflowError: 101 | return True 102 | return True if p >= 1 else p >= random() 103 | 104 | def run(self, verbose=True): 105 | """ 106 | Conducts hill climb 107 | 108 | :param verbose: indicates whether or not to print progress regularly 109 | :return: best state and best objective function value 110 | """ 111 | self._clear() 112 | self.current_state = self.initial_state 113 | for i in range(self.max_steps): 114 | self.cur_steps += 1 115 | 116 | if ((i + 1) % 100 == 0) and verbose: 117 | print(self) 118 | 119 | neighbor = self._neighbor() 120 | 121 | if self._accept_neighbor(neighbor): 122 | self.current_state = neighbor 123 | 124 | if self._objective(self.current_state) > (self.best_objective or 0): 125 | self.best_objective = self._objective(self.current_state) 126 | self.best_state = deepcopy(self.current_state) 127 | 128 | if self.max_objective is not None and (self.best_objective or 0) > self.max_objective: 129 | print("TERMINATING - REACHED MAXIMUM OBJECTIVE") 130 | return self.best_state, self.best_objective 131 | print("TERMINATING - REACHED MAXIMUM STEPS") 132 | return self.best_state, self.best_objective 133 | -------------------------------------------------------------------------------- /docs/modules.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | Solid — Solid 0.11 documentation 10 | 11 | 12 | 13 | 14 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
40 |
41 | 67 |
68 | 95 |
96 |
97 | 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /docs/searchindex.js: -------------------------------------------------------------------------------- 1 | Search.setIndex({docnames:["Solid","index","modules"],envversion:52,filenames:["Solid.rst","index.rst","modules.rst"],objects:{"":{Solid:[0,0,0,"-"]},"Solid.EvolutionaryAlgorithm":{EvolutionaryAlgorithm:[0,1,1,""],random:[0,4,1,""]},"Solid.EvolutionaryAlgorithm.EvolutionaryAlgorithm":{best_fitness:[0,2,1,""],best_member:[0,2,1,""],crossover_rate:[0,2,1,""],cur_steps:[0,2,1,""],fitnesses:[0,2,1,""],max_fitness:[0,2,1,""],max_steps:[0,2,1,""],mutation_rate:[0,2,1,""],population:[0,2,1,""],run:[0,3,1,""]},"Solid.GeneticAlgorithm":{GeneticAlgorithm:[0,1,1,""],random:[0,4,1,""]},"Solid.GeneticAlgorithm.GeneticAlgorithm":{best_fitness:[0,2,1,""],best_member:[0,2,1,""],crossover_rate:[0,2,1,""],cur_steps:[0,2,1,""],fitnesses:[0,2,1,""],max_fitness:[0,2,1,""],max_steps:[0,2,1,""],mutation_rate:[0,2,1,""],population:[0,2,1,""],run:[0,3,1,""]},"Solid.HarmonySearch":{HarmonySearch:[0,1,1,""],random:[0,4,1,""]},"Solid.HarmonySearch.HarmonySearch":{best:[0,2,1,""],cur_steps:[0,2,1,""],fw:[0,2,1,""],hmcr:[0,2,1,""],hms:[0,2,1,""],max_score:[0,2,1,""],max_steps:[0,2,1,""],memory:[0,2,1,""],par:[0,2,1,""],run:[0,3,1,""],scores:[0,2,1,""]},"Solid.ParticleSwarm":{ParticleSwarm:[0,1,1,""],random:[0,4,1,""],uniform:[0,4,1,""]},"Solid.ParticleSwarm.ParticleSwarm":{best:[0,2,1,""],c1:[0,2,1,""],c2:[0,2,1,""],c3:[0,2,1,""],cur_steps:[0,2,1,""],global_best:[0,2,1,""],lower_bound:[0,2,1,""],max_steps:[0,2,1,""],member_size:[0,2,1,""],min_objective:[0,2,1,""],pos:[0,2,1,""],run:[0,3,1,""],scores:[0,2,1,""],swarm_size:[0,2,1,""],upper_bound:[0,2,1,""],vel:[0,2,1,""]},"Solid.SimulatedAnnealing":{SimulatedAnnealing:[0,1,1,""],random:[0,4,1,""]},"Solid.SimulatedAnnealing.SimulatedAnnealing":{adjust_temp:[0,2,1,""],best_energy:[0,2,1,""],best_state:[0,2,1,""],cur_steps:[0,2,1,""],current_energy:[0,2,1,""],current_state:[0,2,1,""],current_temp:[0,2,1,""],initial_state:[0,2,1,""],max_steps:[0,2,1,""],min_energy:[0,2,1,""],run:[0,3,1,""],start_temp:[0,2,1,""]},"Solid.StochasticHillClimb":{StochasticHillClimb:[0,1,1,""],random:[0,4,1,""]},"Solid.StochasticHillClimb.StochasticHillClimb":{best_objective:[0,2,1,""],best_state:[0,2,1,""],cur_steps:[0,2,1,""],current_state:[0,2,1,""],initial_state:[0,2,1,""],max_objective:[0,2,1,""],max_steps:[0,2,1,""],run:[0,3,1,""],temp:[0,2,1,""]},"Solid.TabuSearch":{TabuSearch:[0,1,1,""],random:[0,4,1,""]},"Solid.TabuSearch.TabuSearch":{best:[0,2,1,""],cur_steps:[0,2,1,""],current:[0,2,1,""],initial_state:[0,2,1,""],max_score:[0,2,1,""],max_steps:[0,2,1,""],run:[0,3,1,""],tabu_list:[0,2,1,""],tabu_size:[0,2,1,""]},Solid:{EvolutionaryAlgorithm:[0,0,0,"-"],GeneticAlgorithm:[0,0,0,"-"],HarmonySearch:[0,0,0,"-"],ParticleSwarm:[0,0,0,"-"],SimulatedAnnealing:[0,0,0,"-"],StochasticHillClimb:[0,0,0,"-"],TabuSearch:[0,0,0,"-"]}},objnames:{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","attribute","Python attribute"],"3":["py","method","Python method"],"4":["py","function","Python function"]},objtypes:{"0":"py:module","1":"py:class","2":"py:attribute","3":"py:method","4":"py:function"},terms:{"class":0,"default":0,"float":0,"function":0,"import":0,"int":0,"return":0,"true":0,The:0,accept:0,adjust_temp:0,algorithm:0,alia:0,all:0,along:0,ani:0,anneal:0,anywher:0,argument:0,arrai:0,array_lik:0,base:0,behav:0,best:0,best_energi:0,best_fit:0,best_memb:0,best_object:0,best_stat:0,bin:0,both:0,boundari:0,broadcast:0,climb:0,close:0,color:0,condit:0,conduct:0,content:2,conveni:0,count:0,crossover_r:0,cur_step:0,current:0,current_energi:0,current_st:0,current_temp:0,densiti:0,dimens:0,discret:0,displai:0,distribut:0,draw:0,drawn:0,elsewher:0,energi:0,equal:0,error:0,eventu:0,evolutionari:0,evolutionaryalgorithm:2,exclud:0,exponenti:0,fit:0,frac:0,from:0,gener:0,genet:0,geneticalgorithm:2,given:0,global_best:0,greater:0,half:0,harmoni:0,harmonysearch:2,high:0,hill:0,hist:0,histogram:0,hmcr:0,hms:0,ignor:0,includ:0,index:1,indic:0,inequ:0,initial_st:0,input:0,integ:0,interv:0,less:0,like:0,linewidth:0,low:0,lower:0,lower_bound:0,mai:0,matplotlib:0,max_fit:0,max_object:0,max_scor:0,max_step:0,member:0,member_s:0,memori:0,min_energi:0,min_object:0,modul:[1,2],mutation_r:0,ndarrai:0,none:0,norm:0,object:0,offici:0,ones_lik:0,open:0,optim:0,option:0,other:0,otherwis:0,out:0,output:0,over:0,packag:2,page:1,par:0,paramet:0,parameter:0,particl:0,particleswarm:2,pass:0,plot:0,plt:0,popul:0,pos:0,print:0,probabl:0,progress:0,pyplot:0,rais:0,rand:0,randint:0,random:0,random_integ:0,random_sampl:0,regularli:0,reli:0,result:0,run:0,sampl:0,satisfi:0,scalar:0,schedul:0,schedule_const:0,score:0,search:[0,1],shape:0,show:0,simul:0,simulatedann:2,singl:0,size:0,sourc:0,start_temp:0,state:0,stochast:0,stochastichillclimb:2,submodul:2,swarm:0,swarm_siz:0,tabu:0,tabu_list:0,tabu_s:0,tabusearch:2,temp:0,temp_begin:0,than:0,thi:0,tupl:0,undefin:0,uniform:0,uniformli:0,upper:0,upper_bound:0,valu:0,vel:0,verbos:0,when:0,whether:0,within:0,word:0,would:0,yield:0,zero:0},titles:["Solid package","Welcome to Solid\u2019s documentation!","Solid"],titleterms:{content:0,document:1,evolutionaryalgorithm:0,geneticalgorithm:0,harmonysearch:0,indic:1,modul:0,packag:0,particleswarm:0,simulatedann:0,solid:[0,1,2],stochastichillclimb:0,submodul:0,tabl:1,tabusearch:0,welcom:1}}) -------------------------------------------------------------------------------- /Solid/TabuSearch.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | from copy import deepcopy 3 | from collections import deque 4 | from numpy import argmax 5 | 6 | 7 | class TabuSearch: 8 | """ 9 | Conducts tabu search 10 | """ 11 | __metaclass__ = ABCMeta 12 | 13 | cur_steps = None 14 | 15 | tabu_size = None 16 | tabu_list = None 17 | 18 | initial_state = None 19 | current = None 20 | best = None 21 | 22 | max_steps = None 23 | max_score = None 24 | 25 | def __init__(self, initial_state, tabu_size, max_steps, max_score=None): 26 | """ 27 | 28 | :param initial_state: initial state, should implement __eq__ or __cmp__ 29 | :param tabu_size: number of states to keep in tabu list 30 | :param max_steps: maximum number of steps to run algorithm for 31 | :param max_score: score to stop algorithm once reached 32 | """ 33 | self.initial_state = initial_state 34 | 35 | if isinstance(tabu_size, int) and tabu_size > 0: 36 | self.tabu_size = tabu_size 37 | else: 38 | raise TypeError('Tabu size must be a positive integer') 39 | 40 | if isinstance(max_steps, int) and max_steps > 0: 41 | self.max_steps = max_steps 42 | else: 43 | raise TypeError('Maximum steps must be a positive integer') 44 | 45 | if max_score is not None: 46 | if isinstance(max_score, (int, float)): 47 | self.max_score = float(max_score) 48 | else: 49 | raise TypeError('Maximum score must be a numeric type') 50 | 51 | def __str__(self): 52 | return ('TABU SEARCH: \n' + 53 | 'CURRENT STEPS: %d \n' + 54 | 'BEST SCORE: %f \n' + 55 | 'BEST MEMBER: %s \n\n') % \ 56 | (self.cur_steps, self._score(self.best), str(self.best)) 57 | 58 | def __repr__(self): 59 | return self.__str__() 60 | 61 | def _clear(self): 62 | """ 63 | Resets the variables that are altered on a per-run basis of the algorithm 64 | 65 | :return: None 66 | """ 67 | self.cur_steps = 0 68 | self.tabu_list = deque(maxlen=self.tabu_size) 69 | self.current = self.initial_state 70 | self.best = self.initial_state 71 | 72 | @abstractmethod 73 | def _score(self, state): 74 | """ 75 | Returns objective function value of a state 76 | 77 | :param state: a state 78 | :return: objective function value of state 79 | """ 80 | pass 81 | 82 | @abstractmethod 83 | def _neighborhood(self): 84 | """ 85 | Returns list of all members of neighborhood of current state, given self.current 86 | 87 | :return: list of members of neighborhood 88 | """ 89 | pass 90 | 91 | def _best(self, neighborhood): 92 | """ 93 | Finds the best member of a neighborhood 94 | 95 | :param neighborhood: a neighborhood 96 | :return: best member of neighborhood 97 | """ 98 | return neighborhood[argmax([self._score(x) for x in neighborhood])] 99 | 100 | def run(self, verbose=True): 101 | """ 102 | Conducts tabu search 103 | 104 | :param verbose: indicates whether or not to print progress regularly 105 | :return: best state and objective function value of best state 106 | """ 107 | self._clear() 108 | for i in range(self.max_steps): 109 | self.cur_steps += 1 110 | 111 | if ((i + 1) % 100 == 0) and verbose: 112 | print(self) 113 | 114 | neighborhood = self._neighborhood() 115 | neighborhood_best = self._best(neighborhood) 116 | 117 | while True: 118 | if all([x in self.tabu_list for x in neighborhood]): 119 | print("TERMINATING - NO SUITABLE NEIGHBORS") 120 | return self.best, self._score(self.best) 121 | if neighborhood_best in self.tabu_list: 122 | if self._score(neighborhood_best) > self._score(self.best): 123 | self.tabu_list.append(neighborhood_best) 124 | self.best = deepcopy(neighborhood_best) 125 | break 126 | else: 127 | neighborhood.remove(neighborhood_best) 128 | neighborhood_best = self._best(neighborhood) 129 | else: 130 | self.tabu_list.append(neighborhood_best) 131 | self.current = neighborhood_best 132 | if self._score(self.current) > self._score(self.best): 133 | self.best = deepcopy(self.current) 134 | break 135 | 136 | if self.max_score is not None and self._score(self.best) > self.max_score: 137 | print("TERMINATING - REACHED MAXIMUM SCORE") 138 | return self.best, self._score(self.best) 139 | print("TERMINATING - REACHED MAXIMUM STEPS") 140 | return self.best, self._score(self.best) 141 | -------------------------------------------------------------------------------- /docs/py-modindex.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | Python Module Index — Solid 0.11 documentation 10 | 11 | 12 | 13 | 14 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
43 |
44 |
45 |
46 | 47 | 48 |

Python Module Index

49 | 50 |
51 | s 52 |
53 | 54 | 55 | 56 | 58 | 59 | 61 | 64 | 65 | 66 | 69 | 70 | 71 | 74 | 75 | 76 | 79 | 80 | 81 | 84 | 85 | 86 | 89 | 90 | 91 | 94 | 95 | 96 | 99 |
 
57 | s
62 | Solid 63 |
    67 | Solid.EvolutionaryAlgorithm 68 |
    72 | Solid.GeneticAlgorithm 73 |
    77 | Solid.HarmonySearch 78 |
    82 | Solid.ParticleSwarm 83 |
    87 | Solid.SimulatedAnnealing 88 |
    92 | Solid.StochasticHillClimb 93 |
    97 | Solid.TabuSearch 98 |
100 | 101 | 102 |
103 |
104 |
105 | 125 |
126 |
127 | 135 | 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /Solid/HarmonySearch.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | from random import choice, random, uniform 3 | from numpy import argmax, argmin 4 | 5 | 6 | class HarmonySearch: 7 | """ 8 | Conducts harmony search 9 | """ 10 | __metaclass__ = ABCMeta 11 | 12 | cur_steps = None 13 | 14 | hms = None 15 | hmcr = None 16 | par = None 17 | fw = None 18 | 19 | memory = None 20 | scores = None 21 | best = None 22 | 23 | max_steps = None 24 | max_score = None 25 | 26 | def __init__(self, hms, hmcr, par, fw, max_steps, max_score=None): 27 | """ 28 | 29 | :param hms: harmony memory size 30 | :param hmcr: harmony memory considering rate 31 | :param par: pitch adjustment rate 32 | :param fw: fret width 33 | :param max_steps: maximum number of steps to run algorithm for 34 | :param max_score: objective function value to stop algorithm once reached 35 | """ 36 | if isinstance(hms, int) and hms > 0: 37 | self.hms = hms 38 | else: 39 | raise TypeError('Harmony memory size must be a positive integer') 40 | 41 | if isinstance(hmcr, float) and 0 <= hmcr <= 1: 42 | self.hmcr = hmcr 43 | else: 44 | raise TypeError('Harmony memory considering rate must be a float between 0 and 1') 45 | 46 | if isinstance(par, float) and 0 <= par <= 1: 47 | self.par = par 48 | else: 49 | raise TypeError('Pitch adjustment rate must be a float between 0 and 1') 50 | 51 | if isinstance(fw, (int, float)): 52 | self.fw = float(fw) 53 | else: 54 | raise TypeError('Fret width must be a numeric type') 55 | 56 | if isinstance(max_steps, int) and max_steps > 0: 57 | self.max_steps = max_steps 58 | else: 59 | raise TypeError('Max steps must be a positive integer') 60 | 61 | if max_score is not None: 62 | if isinstance(max_score, (int, float)): 63 | self.max_score = max_score 64 | else: 65 | raise TypeError('Max score must be a numeric type') 66 | 67 | def __str__(self): 68 | return ('HARMONY SEARCH: \n' + 69 | 'CURRENT STEPS: %d \n' + 70 | 'BEST SCORE: %f \n' + 71 | 'BEST MEMBER: %s \n\n') % \ 72 | (self.cur_steps, self._score(self.best), str(self.best)) 73 | 74 | def __repr__(self): 75 | return self.__str__() 76 | 77 | def _clear(self): 78 | """ 79 | Resets the variables that are altered on a per-run basis of the algorithm 80 | 81 | :return: None 82 | """ 83 | self.cur_steps = 0 84 | self.memory = list([self._random_harmony() for _ in range(self.hms)]) 85 | self.scores = None 86 | 87 | @abstractmethod 88 | def _random_harmony(self): 89 | """ 90 | Generates a random harmony, represented as a list of floats 91 | 92 | :return: list of harmonies 93 | """ 94 | pass 95 | 96 | @abstractmethod 97 | def _score(self, harmony): 98 | """ 99 | Returns score of a harmony 100 | 101 | :param harmony: a harmony 102 | :return: score of harmony 103 | """ 104 | pass 105 | 106 | def _score_all(self): 107 | """ 108 | Finds score of all current harmonies in memory 109 | 110 | :return: None 111 | """ 112 | self.scores = [self._score(x) for x in self.memory] 113 | 114 | def _worst_score(self): 115 | """ 116 | Returns index of worst harmony in memory 117 | 118 | :return: index of worst harmony in memory 119 | """ 120 | return argmin(self.scores) 121 | 122 | def _best_score(self): 123 | """ 124 | Returns index of best harmony in memory 125 | 126 | :return: index of best harmony in memory 127 | """ 128 | return argmax(self.scores) 129 | 130 | def run(self, verbose=True): 131 | """ 132 | Conducts harmony search 133 | 134 | :param verbose: indicates whether or not to print progress regularly 135 | :return: best state and objective function value of best state 136 | """ 137 | self._clear() 138 | self._score_all() 139 | for i in range(self.max_steps): 140 | self.cur_steps += 1 141 | 142 | if verbose and ((i + 1) % 100 == 0): 143 | print(self) 144 | 145 | self._score_all() 146 | 147 | selected = [0.] * len(self.memory[0]) 148 | for i in range(len(selected)): 149 | if self.hmcr >= random(): 150 | selected_component = choice(self.memory)[i] 151 | if self.par >= random(): 152 | selected_component += uniform(-1, 1) * self.fw 153 | else: 154 | selected_component = self._random_harmony()[i] 155 | selected[i] = selected_component 156 | 157 | if self._score(selected) > self._score(self.memory[self._worst_score()]): 158 | self.memory[self._worst_score()] = selected 159 | self.scores[self._worst_score()] = self._score(selected) 160 | 161 | self.best = self.memory[self._best_score()] 162 | 163 | if self.max_score is not None and self._score(self.best) > self.max_score: 164 | print("TERMINATING - REACHED MAXIMUM SCORE") 165 | return self.best, self._score(self.best) 166 | print("TERMINATING - REACHED MAXIMUM STEPS") 167 | return self.best, self._score(self.best) 168 | -------------------------------------------------------------------------------- /Solid/SimulatedAnnealing.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | from copy import deepcopy 3 | from math import exp 4 | from random import random 5 | 6 | 7 | class SimulatedAnnealing: 8 | """ 9 | Conducts simulated annealing algorithm 10 | """ 11 | __metaclass__ = ABCMeta 12 | 13 | initial_state = None 14 | current_state = None 15 | best_state = None 16 | 17 | cur_steps = 0 18 | max_steps = None 19 | 20 | current_energy = None 21 | best_energy = None 22 | min_energy = None 23 | 24 | start_temp = None 25 | current_temp = None 26 | adjust_temp = None 27 | 28 | def _exponential(self, schedule_constant): 29 | def f(): 30 | self.current_temp *= schedule_constant 31 | return f 32 | 33 | def _linear(self, schedule_constant): 34 | def f(): 35 | self.current_temp -= schedule_constant 36 | return f 37 | 38 | def _get_schedule(self, schedule_str, schedule_constant): 39 | if schedule_str == 'exponential': 40 | return self._exponential(schedule_constant) 41 | elif schedule_str == 'linear': 42 | return self._linear(schedule_constant) 43 | else: 44 | raise ValueError('Annealing schedule must be either "exponential" or "linear"') 45 | 46 | def __init__(self, initial_state, temp_begin, schedule_constant, max_steps, 47 | min_energy=None, schedule='exponential'): 48 | """ 49 | 50 | :param initial_state: initial state of annealing algorithm 51 | :param max_steps: maximum number of iterations to conduct annealing for 52 | :param temp_begin: beginning temperature 53 | :param schedule_constant: constant value in annealing schedule function 54 | :param min_energy: energy value to stop algorithm once reached 55 | :param schedule: 'exponential' or 'linear' annealing schedule 56 | """ 57 | self.initial_state = initial_state 58 | 59 | if isinstance(max_steps, int) and max_steps > 0: 60 | self.max_steps = max_steps 61 | else: 62 | raise ValueError('Max steps must be a positive integer') 63 | 64 | if min_energy is not None: 65 | if isinstance(min_energy, (float, int)): 66 | self.min_energy = float(min_energy) 67 | else: 68 | raise ValueError('Minimum energy must be a numeric type') 69 | 70 | if isinstance(temp_begin, (float, int)): 71 | self.start_temp = float(temp_begin) 72 | else: 73 | raise ValueError('Starting temperature must be a numeric type') 74 | 75 | self.adjust_temp = self._get_schedule(schedule, schedule_constant) 76 | 77 | def __str__(self): 78 | return ('SIMULATED ANNEALING: \n' + 79 | 'CURRENT STEPS: %d \n' + 80 | 'CURRENT TEMPERATURE: %f \n' + 81 | 'BEST ENERGY: %f \n' + 82 | 'BEST STATE: %s \n\n') % \ 83 | (self.cur_steps, self.current_temp, self.best_energy, str(self.best_state)) 84 | 85 | def __repr__(self): 86 | return self.__str__() 87 | 88 | def _clear(self): 89 | """ 90 | Resets the variables that are altered on a per-run basis of the algorithm 91 | 92 | :return: None 93 | """ 94 | self.cur_steps = 0 95 | self.current_state = None 96 | self.best_state = None 97 | self.current_energy = None 98 | self.best_energy = None 99 | 100 | @abstractmethod 101 | def _neighbor(self): 102 | """ 103 | Returns a random member of the neighbor of the current state 104 | 105 | :return: a random neighbor, given access to self.current_state 106 | """ 107 | pass 108 | 109 | @abstractmethod 110 | def _energy(self, state): 111 | """ 112 | Finds the energy of a given state 113 | 114 | :param state: a state 115 | :return: energy of state 116 | """ 117 | pass 118 | 119 | def _accept_neighbor(self, neighbor): 120 | """ 121 | Probabilistically determines whether or not to accept a transition to a neighbor 122 | 123 | :param neighbor: a state 124 | :return: boolean indicating whether or not transition is accepted 125 | """ 126 | try: 127 | p = exp(-(self._energy(neighbor) - self._energy(self.current_state)) / self.current_temp) 128 | except OverflowError: 129 | return True 130 | return True if p >= 1 else p >= random() 131 | 132 | def run(self, verbose=True): 133 | """ 134 | Conducts simulated annealing 135 | 136 | :param verbose: indicates whether or not to print progress regularly 137 | :return: best state and best energy 138 | """ 139 | self._clear() 140 | self.current_state = self.initial_state 141 | self.current_temp = self.start_temp 142 | self.best_energy = self._energy(self.current_state) 143 | for i in range(self.max_steps): 144 | self.cur_steps += 1 145 | 146 | if verbose and ((i + 1) % 100 == 0): 147 | print(self) 148 | 149 | neighbor = self._neighbor() 150 | 151 | if self._accept_neighbor(neighbor): 152 | self.current_state = neighbor 153 | self.current_energy = self._energy(self.current_state) 154 | 155 | if self.current_energy < self.best_energy: 156 | self.best_energy = self.current_energy 157 | self.best_state = deepcopy(self.current_state) 158 | 159 | if self.min_energy is not None and self.current_energy < self.min_energy: 160 | print("TERMINATING - REACHED MINIMUM ENERGY") 161 | return self.best_state, self.best_energy 162 | 163 | self.adjust_temp() 164 | if self.current_temp < 0.000001: 165 | print("TERMINATING - REACHED TEMPERATURE OF 0") 166 | return self.best_state, self.best_energy 167 | print("TERMINATING - REACHED MAXIMUM STEPS") 168 | return self.best_state, self.best_energy 169 | -------------------------------------------------------------------------------- /Solid/EvolutionaryAlgorithm.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | from copy import deepcopy 3 | from random import random, shuffle 4 | 5 | 6 | class EvolutionaryAlgorithm: 7 | """ 8 | Conducts evolutionary algorithm 9 | """ 10 | __metaclass__ = ABCMeta 11 | 12 | population = None 13 | fitnesses = None 14 | 15 | crossover_rate = None 16 | 17 | mutation_rate = None 18 | 19 | cur_steps = None 20 | best_fitness = None 21 | best_member = None 22 | 23 | max_steps = None 24 | max_fitness = None 25 | 26 | def __init__(self, crossover_rate, mutation_rate, max_steps, max_fitness=None): 27 | """ 28 | 29 | :param crossover_rate: probability of crossover 30 | :param mutation_rate: probability of mutation 31 | :param max_steps: maximum steps to run genetic algorithm for 32 | :param max_fitness: fitness value to stop algorithm once reached 33 | """ 34 | if isinstance(crossover_rate, float): 35 | if 0 <= crossover_rate <= 1: 36 | self.crossover_rate = crossover_rate 37 | else: 38 | raise ValueError('Crossover rate must be a float between 0 and 1') 39 | else: 40 | raise ValueError('Crossover rate must be a float between 0 and 1') 41 | 42 | if isinstance(mutation_rate, float): 43 | if 0 <= mutation_rate <= 1: 44 | self.mutation_rate = mutation_rate 45 | else: 46 | raise ValueError('Mutation rate must be a float between 0 and 1') 47 | else: 48 | raise ValueError('Mutation rate must be a float between 0 and 1') 49 | 50 | if isinstance(max_steps, int) and max_steps > 0: 51 | self.max_steps = max_steps 52 | else: 53 | raise ValueError('Maximum steps must be a positive integer') 54 | 55 | if max_fitness is not None: 56 | if isinstance(max_fitness, (int, float)): 57 | self.max_fitness = float(max_fitness) 58 | else: 59 | raise ValueError('Maximum fitness must be a numeric type') 60 | 61 | def __str__(self): 62 | return ('EVOLUTIONARY ALGORITHM: \n' + 63 | 'CURRENT STEPS: %d \n' + 64 | 'BEST FITNESS: %f \n' + 65 | 'BEST MEMBER: %s \n\n') % \ 66 | (self.cur_steps, self.best_fitness, str(self.best_member)) 67 | 68 | def __repr__(self): 69 | return self.__str__() 70 | 71 | def _clear(self): 72 | """ 73 | Resets the variables that are altered on a per-run basis of the algorithm 74 | 75 | :return: None 76 | """ 77 | self.cur_steps = 0 78 | self.population = None 79 | self.fitnesses = None 80 | self.best_member = None 81 | self.best_fitness = None 82 | 83 | @abstractmethod 84 | def _initial_population(self): 85 | """ 86 | Generates initial population 87 | 88 | :return: list of members of population 89 | """ 90 | pass 91 | 92 | @abstractmethod 93 | def _fitness(self, member): 94 | """ 95 | Evaluates fitness of a given member 96 | 97 | :param member: a member 98 | :return: fitness of member 99 | """ 100 | pass 101 | 102 | def _populate_fitness(self): 103 | """ 104 | Calculates fitness of all members of current population 105 | 106 | :return: None 107 | """ 108 | self.fitnesses = [self._fitness(x) for x in self.population] 109 | 110 | def _most_fit(self): 111 | """ 112 | Finds most fit member of current population 113 | 114 | :return: most fit member and most fit member's fitness 115 | """ 116 | best_idx = 0 117 | cur_idx = 0 118 | for x in self.fitnesses: 119 | if x > self.fitnesses[best_idx]: 120 | best_idx = cur_idx 121 | cur_idx += 1 122 | return self.population[best_idx], self.fitnesses[best_idx] 123 | 124 | def _select_n(self, n): 125 | """ 126 | Probabilistically selects n members from current population using 127 | roulette-wheel selection 128 | 129 | :param n: number of members to select 130 | :return: n members 131 | """ 132 | shuffle(self.population) 133 | total_fitness = sum(self.fitnesses) 134 | if total_fitness != 0: 135 | probs = list([self._fitness(x) / total_fitness for x in self.population]) 136 | else: 137 | return self.population[0:n] 138 | res = [] 139 | for _ in range(n): 140 | r = random() 141 | sum_ = 0 142 | for i, x in enumerate(probs): 143 | sum_ += probs[i] 144 | if r <= sum_: 145 | res.append(deepcopy(self.population[i])) 146 | break 147 | return res 148 | 149 | @abstractmethod 150 | def _crossover(self, parent1, parent2): 151 | """ 152 | Creates new member of population by combining two parent members 153 | 154 | :param parent1: a member 155 | :param parent2: a member 156 | :return: member made by combining elements of both parents 157 | """ 158 | pass 159 | 160 | @abstractmethod 161 | def _mutate(self, member): 162 | """ 163 | Randomly mutates a member 164 | 165 | :param member: a member 166 | :return: mutated member 167 | """ 168 | pass 169 | 170 | def run(self, verbose=True): 171 | """ 172 | Conducts evolutionary algorithm 173 | 174 | :param verbose: indicates whether or not to print progress regularly 175 | :return: best state and best objective function value 176 | """ 177 | self._clear() 178 | self.population = self._initial_population() 179 | self._populate_fitness() 180 | self.best_member, self.best_fitness = self._most_fit() 181 | num_copy = max(int((1 - self.crossover_rate) * len(self.population)), 2) 182 | num_crossover = len(self.population) - num_copy 183 | for i in range(self.max_steps): 184 | self.cur_steps += 1 185 | 186 | if verbose and ((i + 1) % 100 == 0): 187 | print(self) 188 | 189 | self.population = self._select_n(num_copy) 190 | self._populate_fitness() 191 | 192 | parents = self._select_n(2) 193 | for _ in range(num_crossover): 194 | self.population.append(self._crossover(*parents)) 195 | 196 | self.population = list([self._mutate(x) for x in self.population]) 197 | self._populate_fitness() 198 | 199 | best_member, best_fitness = self._most_fit() 200 | if best_fitness > self.best_fitness: 201 | self.best_fitness = best_fitness 202 | self.best_member = deepcopy(best_member) 203 | 204 | if self.max_fitness is not None and self.best_fitness >= self.max_fitness: 205 | print("TERMINATING - REACHED MAXIMUM FITNESS") 206 | return self.best_member, self.best_fitness 207 | print("TERMINATING - REACHED MAXIMUM STEPS") 208 | return self.best_member, self.best_fitness 209 | -------------------------------------------------------------------------------- /Solid/GeneticAlgorithm.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | from copy import deepcopy 3 | from random import randint, random, shuffle 4 | 5 | 6 | class GeneticAlgorithm: 7 | """ 8 | Conducts genetic algorithm 9 | """ 10 | __metaclass__ = ABCMeta 11 | 12 | population = None 13 | fitnesses = None 14 | 15 | crossover_rate = None 16 | 17 | mutation_rate = None 18 | 19 | cur_steps = None 20 | best_fitness = None 21 | best_member = None 22 | 23 | max_steps = None 24 | max_fitness = None 25 | 26 | def __init__(self, crossover_rate, mutation_rate, max_steps, max_fitness=None): 27 | """ 28 | 29 | :param crossover_rate: probability of crossover 30 | :param mutation_rate: probability of mutation 31 | :param max_steps: maximum steps to run genetic algorithm for 32 | :param max_fitness: fitness value to stop algorithm once reached 33 | """ 34 | if isinstance(crossover_rate, float): 35 | if 0 <= crossover_rate <= 1: 36 | self.crossover_rate = crossover_rate 37 | else: 38 | raise ValueError('Crossover rate must be a float between 0 and 1') 39 | else: 40 | raise ValueError('Crossover rate must be a float between 0 and 1') 41 | 42 | if isinstance(mutation_rate, float): 43 | if 0 <= mutation_rate <= 1: 44 | self.mutation_rate = mutation_rate 45 | else: 46 | raise ValueError('Mutation rate must be a float between 0 and 1') 47 | else: 48 | raise ValueError('Mutation rate must be a float between 0 and 1') 49 | 50 | if isinstance(max_steps, int) and max_steps > 0: 51 | self.max_steps = max_steps 52 | else: 53 | raise ValueError('Maximum steps must be a positive integer') 54 | 55 | if max_fitness is not None: 56 | if isinstance(max_fitness, (int, float)): 57 | self.max_fitness = float(max_fitness) 58 | else: 59 | raise ValueError('Maximum fitness must be a numeric type') 60 | 61 | def __str__(self): 62 | return ('GENETIC ALGORITHM: \n' + 63 | 'CURRENT STEPS: %d \n' + 64 | 'BEST FITNESS: %f \n' + 65 | 'BEST MEMBER: %s \n\n') % \ 66 | (self.cur_steps, self.best_fitness, str(self.best_member)) 67 | 68 | def __repr__(self): 69 | return self.__str__() 70 | 71 | def _clear(self): 72 | """ 73 | Resets the variables that are altered on a per-run basis of the algorithm 74 | 75 | :return: None 76 | """ 77 | self.cur_steps = 0 78 | self.population = None 79 | self.fitnesses = None 80 | self.best_member = None 81 | self.best_fitness = None 82 | 83 | @abstractmethod 84 | def _initial_population(self): 85 | """ 86 | Generates initial population - 87 | members must be represented by a list of binary-values integers 88 | 89 | :return: list of members of population 90 | """ 91 | pass 92 | 93 | @abstractmethod 94 | def _fitness(self, member): 95 | """ 96 | Evaluates fitness of a given member 97 | 98 | :param member: a member 99 | :return: fitness of member 100 | """ 101 | pass 102 | 103 | def _populate_fitness(self): 104 | """ 105 | Calculates fitness of all members of current population 106 | 107 | :return: None 108 | """ 109 | self.fitnesses = list([self._fitness(x) for x in self.population]) 110 | 111 | def _most_fit(self): 112 | """ 113 | Finds most fit member of current population 114 | 115 | :return: most fit member and most fit member's fitness 116 | """ 117 | best_idx = 0 118 | cur_idx = 0 119 | for x in self.fitnesses: 120 | if x > self.fitnesses[best_idx]: 121 | best_idx = cur_idx 122 | cur_idx += 1 123 | return self.population[best_idx], self.fitnesses[best_idx] 124 | 125 | def _select_n(self, n): 126 | """ 127 | Probabilistically selects n members from current population using 128 | roulette-wheel selection 129 | 130 | :param n: number of members to select 131 | :return: n members 132 | """ 133 | shuffle(self.population) 134 | total_fitness = sum(self.fitnesses) 135 | if total_fitness != 0: 136 | probs = list([self._fitness(x) / total_fitness for x in self.population]) 137 | else: 138 | return self.population[0:n] 139 | res = [] 140 | for _ in range(n): 141 | r = random() 142 | sum_ = 0 143 | for i, x in enumerate(probs): 144 | sum_ += probs[i] 145 | if r <= sum_: 146 | res.append(deepcopy(self.population[i])) 147 | break 148 | return res 149 | 150 | def _crossover(self, parent1, parent2): 151 | """ 152 | Creates new member of population by combining two parent members 153 | 154 | :param parent1: a member 155 | :param parent2: a member 156 | :return: member made by combining elements of both parents 157 | """ 158 | partition = randint(0, len(self.population[0]) - 1) 159 | return parent1[0:partition] + parent2[partition:] 160 | 161 | def _mutate(self, member): 162 | """ 163 | Randomly mutates a member 164 | 165 | :param member: a member 166 | :return: mutated member 167 | """ 168 | if self.mutation_rate >= random(): 169 | idx = randint(0, len(member) - 1) 170 | member[idx] = 1 if member[idx] == 0 else 1 171 | return member 172 | 173 | def run(self, verbose=True): 174 | """ 175 | Conducts genetic algorithm 176 | 177 | :param verbose: indicates whether or not to print progress regularly 178 | :return: best state and best objective function value 179 | """ 180 | self._clear() 181 | self.population = self._initial_population() 182 | self._populate_fitness() 183 | self.best_member, self.best_fitness = self._most_fit() 184 | num_copy = max(int((1 - self.crossover_rate) * len(self.population)), 2) 185 | num_crossover = len(self.population) - num_copy 186 | for i in range(self.max_steps): 187 | self.cur_steps += 1 188 | 189 | if verbose and ((i + 1) % 100 == 0): 190 | print(self) 191 | 192 | self.population = self._select_n(num_copy) 193 | self._populate_fitness() 194 | 195 | parents = self._select_n(2) 196 | for _ in range(num_crossover): 197 | self.population.append(self._crossover(*parents)) 198 | 199 | self.population = list([self._mutate(x) for x in self.population]) 200 | self._populate_fitness() 201 | 202 | best_member, best_fitness = self._most_fit() 203 | if best_fitness > self.best_fitness: 204 | self.best_fitness = best_fitness 205 | self.best_member = deepcopy(best_member) 206 | 207 | if self.max_fitness is not None and self.best_fitness >= self.max_fitness: 208 | print("TERMINATING - REACHED MAXIMUM FITNESS") 209 | return self.best_member, self.best_fitness 210 | print("TERMINATING - REACHED MAXIMUM STEPS") 211 | return self.best_member, self.best_fitness 212 | -------------------------------------------------------------------------------- /Solid/ParticleSwarm.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | from random import random 3 | from numpy import apply_along_axis, argmin, array, copy, diag_indices_from, dot, zeros 4 | from numpy.random import uniform 5 | 6 | 7 | class ParticleSwarm: 8 | """ 9 | Conducts particle swarm optimization 10 | """ 11 | __metaclass__ = ABCMeta 12 | 13 | swarm_size = None 14 | member_size = None 15 | lower_bound = None 16 | upper_bound = None 17 | 18 | pos = None 19 | vel = None 20 | scores = None 21 | best = None 22 | global_best = None 23 | 24 | c1 = None 25 | c2 = None 26 | c3 = None 27 | 28 | cur_steps = None 29 | max_steps = None 30 | min_objective = None 31 | 32 | def __init__(self, swarm_size, member_size, lower_bound, upper_bound, c1, c2, c3, 33 | max_steps, min_objective=None): 34 | """ 35 | 36 | :param swarm_size: number of members in swarm 37 | :param member_size: number of components per member vector 38 | :param lower_bound: list of lower bounds, where ith element is ith lower bound 39 | :param upper_bound: list of upper bounds, where ith element is ith upper bound 40 | :param c1: constant for 1st term in velocity calculation 41 | :param c2: contsant for 2nd term in velocity calculation 42 | :param c3: constant for 3rd term in velocity calculation 43 | :param max_steps: maximum steps to run algorithm for 44 | :param min_objective: objective function value to stop algorithm once reached 45 | """ 46 | if isinstance(swarm_size, int) and swarm_size > 0: 47 | self.swarm_size = swarm_size 48 | else: 49 | raise ValueError('Swarm size must be a positive integer') 50 | 51 | if isinstance(member_size, int) and member_size > 0: 52 | self.member_size = member_size 53 | else: 54 | raise ValueError('Member size must be a positive integer') 55 | 56 | if all([isinstance(x, (int, float)) for x in lower_bound]): 57 | self.lower_bound = array([float(x) for x in lower_bound]) 58 | else: 59 | raise ValueError('Lower bounds must be numeric types') 60 | 61 | if all([isinstance(x, (int, float)) for x in upper_bound]): 62 | self.upper_bound = array([float(x) for x in upper_bound]) 63 | else: 64 | raise ValueError('Upper bounds must be numeric types') 65 | 66 | self.pos = uniform(self.lower_bound, self.upper_bound, size=(swarm_size, member_size)) 67 | 68 | self.vel = uniform(self.lower_bound - self.upper_bound, self.upper_bound - self.lower_bound, 69 | size=(swarm_size, member_size)) 70 | 71 | self.best = copy(self.pos) 72 | 73 | if isinstance(c1, (int, float)) and isinstance(c2, (int, float)) and isinstance(c3, (int, float)): 74 | self.c1 = float(c1) 75 | self.c2 = float(c2) 76 | self.c3 = float(c3) 77 | else: 78 | raise ValueError() 79 | 80 | if isinstance(max_steps, int): 81 | self.max_steps = max_steps 82 | else: 83 | raise ValueError() 84 | 85 | if min_objective is not None: 86 | if isinstance(min_objective, (int, float)): 87 | self.min_objective = float(min_objective) 88 | else: 89 | raise ValueError() 90 | 91 | def __str__(self): 92 | return ('PARTICLE SWARM: \n' + 93 | 'CURRENT STEPS: %d \n' + 94 | 'BEST FITNESS: %f \n' + 95 | 'BEST MEMBER: %s \n\n') % \ 96 | (self.cur_steps, self._objective(self.global_best[0]), str(self.global_best[0])) 97 | 98 | def __repr__(self): 99 | return self.__str__() 100 | 101 | def _clear(self): 102 | """ 103 | Resets the variables that are altered on a per-run basis of the algorithm 104 | 105 | :return: None 106 | """ 107 | self.pos = uniform(self.lower_bound, self.upper_bound, size=(self.swarm_size, self.member_size)) 108 | self.vel = uniform(self.lower_bound - self.upper_bound, self.upper_bound - self.lower_bound, 109 | size=(self.swarm_size, self.member_size)) 110 | self.scores = self._score(self.pos) 111 | self.best = copy(self.pos) 112 | self.cur_steps = 0 113 | self._global_best() 114 | 115 | @abstractmethod 116 | def _objective(self, member): 117 | """ 118 | Returns objective function value for a member of swarm - 119 | operates on 1D numpy array 120 | 121 | :param member: a member 122 | :return: objective function value of member 123 | """ 124 | pass 125 | 126 | def _score(self, pos): 127 | """ 128 | Applies objective function to all members of swarm 129 | 130 | :param pos: position matrix 131 | :return: score vector 132 | """ 133 | return apply_along_axis(self._objective, 1, pos) 134 | 135 | def _best(self, old, new): 136 | """ 137 | Finds the best objective function values for each member of swarm 138 | 139 | :param old: old values 140 | :param new: new values 141 | :return: None 142 | """ 143 | old_scores = self._score(old) 144 | new_scores = self._score(new) 145 | best = [] 146 | for i in range(len(old_scores)): 147 | if old_scores[i] < new_scores[i]: 148 | best.append(old[i]) 149 | else: 150 | best.append(new[i]) 151 | self.best = array(best) 152 | 153 | def _global_best(self): 154 | """ 155 | Finds the global best across swarm 156 | 157 | :return: None 158 | """ 159 | if self.global_best is None or min(self.scores) < self._objective(self.global_best[0]): 160 | self.global_best = array([self.pos[argmin(self.scores)]] * self.swarm_size) 161 | 162 | def run(self, verbose=True): 163 | """ 164 | Conducts particle swarm optimization 165 | 166 | :param verbose: indicates whether or not to print progress regularly 167 | :return: best member of swarm and objective function value of best member of swarm 168 | """ 169 | self._clear() 170 | for i in range(self.max_steps): 171 | self.cur_steps += 1 172 | 173 | if verbose and ((i + 1) % 100 == 0): 174 | print(self) 175 | 176 | u1 = zeros((self.swarm_size, self.swarm_size)) 177 | u1[diag_indices_from(u1)] = [random() for x in range(self.swarm_size)] 178 | u2 = zeros((self.swarm_size, self.swarm_size)) 179 | u2[diag_indices_from(u2)] = [random() for x in range(self.swarm_size)] 180 | 181 | vel_new = (self.c1 * self.vel) + \ 182 | (self.c2 * dot(u1, (self.best - self.pos))) + \ 183 | (self.c3 * dot(u2, (self.global_best - self.pos))) 184 | 185 | pos_new = self.pos + vel_new 186 | 187 | self._best(self.pos, pos_new) 188 | self.pos = pos_new 189 | self.scores = self._score(self.pos) 190 | self._global_best() 191 | 192 | if self._objective(self.global_best[0]) < (self.min_objective or 0): 193 | print("TERMINATING - REACHED MINIMUM OBJECTIVE") 194 | return self.global_best[0], self._objective(self.global_best[0]) 195 | print("TERMINATING - REACHED MAXIMUM STEPS") 196 | return self.global_best[0], self._objective(self.global_best[0]) 197 | -------------------------------------------------------------------------------- /docs/_static/doctools.js: -------------------------------------------------------------------------------- 1 | /* 2 | * doctools.js 3 | * ~~~~~~~~~~~ 4 | * 5 | * Sphinx JavaScript utilities for all documentation. 6 | * 7 | * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | /** 13 | * select a different prefix for underscore 14 | */ 15 | $u = _.noConflict(); 16 | 17 | /** 18 | * make the code below compatible with browsers without 19 | * an installed firebug like debugger 20 | if (!window.console || !console.firebug) { 21 | var names = ["log", "debug", "info", "warn", "error", "assert", "dir", 22 | "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", 23 | "profile", "profileEnd"]; 24 | window.console = {}; 25 | for (var i = 0; i < names.length; ++i) 26 | window.console[names[i]] = function() {}; 27 | } 28 | */ 29 | 30 | /** 31 | * small helper function to urldecode strings 32 | */ 33 | jQuery.urldecode = function(x) { 34 | return decodeURIComponent(x).replace(/\+/g, ' '); 35 | }; 36 | 37 | /** 38 | * small helper function to urlencode strings 39 | */ 40 | jQuery.urlencode = encodeURIComponent; 41 | 42 | /** 43 | * This function returns the parsed url parameters of the 44 | * current request. Multiple values per key are supported, 45 | * it will always return arrays of strings for the value parts. 46 | */ 47 | jQuery.getQueryParameters = function(s) { 48 | if (typeof s == 'undefined') 49 | s = document.location.search; 50 | var parts = s.substr(s.indexOf('?') + 1).split('&'); 51 | var result = {}; 52 | for (var i = 0; i < parts.length; i++) { 53 | var tmp = parts[i].split('=', 2); 54 | var key = jQuery.urldecode(tmp[0]); 55 | var value = jQuery.urldecode(tmp[1]); 56 | if (key in result) 57 | result[key].push(value); 58 | else 59 | result[key] = [value]; 60 | } 61 | return result; 62 | }; 63 | 64 | /** 65 | * highlight a given string on a jquery object by wrapping it in 66 | * span elements with the given class name. 67 | */ 68 | jQuery.fn.highlightText = function(text, className) { 69 | function highlight(node) { 70 | if (node.nodeType == 3) { 71 | var val = node.nodeValue; 72 | var pos = val.toLowerCase().indexOf(text); 73 | if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) { 74 | var span = document.createElement("span"); 75 | span.className = className; 76 | span.appendChild(document.createTextNode(val.substr(pos, text.length))); 77 | node.parentNode.insertBefore(span, node.parentNode.insertBefore( 78 | document.createTextNode(val.substr(pos + text.length)), 79 | node.nextSibling)); 80 | node.nodeValue = val.substr(0, pos); 81 | } 82 | } 83 | else if (!jQuery(node).is("button, select, textarea")) { 84 | jQuery.each(node.childNodes, function() { 85 | highlight(this); 86 | }); 87 | } 88 | } 89 | return this.each(function() { 90 | highlight(this); 91 | }); 92 | }; 93 | 94 | /* 95 | * backward compatibility for jQuery.browser 96 | * This will be supported until firefox bug is fixed. 97 | */ 98 | if (!jQuery.browser) { 99 | jQuery.uaMatch = function(ua) { 100 | ua = ua.toLowerCase(); 101 | 102 | var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || 103 | /(webkit)[ \/]([\w.]+)/.exec(ua) || 104 | /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || 105 | /(msie) ([\w.]+)/.exec(ua) || 106 | ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || 107 | []; 108 | 109 | return { 110 | browser: match[ 1 ] || "", 111 | version: match[ 2 ] || "0" 112 | }; 113 | }; 114 | jQuery.browser = {}; 115 | jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; 116 | } 117 | 118 | /** 119 | * Small JavaScript module for the documentation. 120 | */ 121 | var Documentation = { 122 | 123 | init : function() { 124 | this.fixFirefoxAnchorBug(); 125 | this.highlightSearchWords(); 126 | this.initIndexTable(); 127 | 128 | }, 129 | 130 | /** 131 | * i18n support 132 | */ 133 | TRANSLATIONS : {}, 134 | PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; }, 135 | LOCALE : 'unknown', 136 | 137 | // gettext and ngettext don't access this so that the functions 138 | // can safely bound to a different name (_ = Documentation.gettext) 139 | gettext : function(string) { 140 | var translated = Documentation.TRANSLATIONS[string]; 141 | if (typeof translated == 'undefined') 142 | return string; 143 | return (typeof translated == 'string') ? translated : translated[0]; 144 | }, 145 | 146 | ngettext : function(singular, plural, n) { 147 | var translated = Documentation.TRANSLATIONS[singular]; 148 | if (typeof translated == 'undefined') 149 | return (n == 1) ? singular : plural; 150 | return translated[Documentation.PLURALEXPR(n)]; 151 | }, 152 | 153 | addTranslations : function(catalog) { 154 | for (var key in catalog.messages) 155 | this.TRANSLATIONS[key] = catalog.messages[key]; 156 | this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); 157 | this.LOCALE = catalog.locale; 158 | }, 159 | 160 | /** 161 | * add context elements like header anchor links 162 | */ 163 | addContextElements : function() { 164 | $('div[id] > :header:first').each(function() { 165 | $('\u00B6'). 166 | attr('href', '#' + this.id). 167 | attr('title', _('Permalink to this headline')). 168 | appendTo(this); 169 | }); 170 | $('dt[id]').each(function() { 171 | $('\u00B6'). 172 | attr('href', '#' + this.id). 173 | attr('title', _('Permalink to this definition')). 174 | appendTo(this); 175 | }); 176 | }, 177 | 178 | /** 179 | * workaround a firefox stupidity 180 | * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 181 | */ 182 | fixFirefoxAnchorBug : function() { 183 | if (document.location.hash) 184 | window.setTimeout(function() { 185 | document.location.href += ''; 186 | }, 10); 187 | }, 188 | 189 | /** 190 | * highlight the search words provided in the url in the text 191 | */ 192 | highlightSearchWords : function() { 193 | var params = $.getQueryParameters(); 194 | var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; 195 | if (terms.length) { 196 | var body = $('div.body'); 197 | if (!body.length) { 198 | body = $('body'); 199 | } 200 | window.setTimeout(function() { 201 | $.each(terms, function() { 202 | body.highlightText(this.toLowerCase(), 'highlighted'); 203 | }); 204 | }, 10); 205 | $('') 207 | .appendTo($('#searchbox')); 208 | } 209 | }, 210 | 211 | /** 212 | * init the domain index toggle buttons 213 | */ 214 | initIndexTable : function() { 215 | var togglers = $('img.toggler').click(function() { 216 | var src = $(this).attr('src'); 217 | var idnum = $(this).attr('id').substr(7); 218 | $('tr.cg-' + idnum).toggle(); 219 | if (src.substr(-9) == 'minus.png') 220 | $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); 221 | else 222 | $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); 223 | }).css('display', ''); 224 | if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { 225 | togglers.click(); 226 | } 227 | }, 228 | 229 | /** 230 | * helper function to hide the search marks again 231 | */ 232 | hideSearchWords : function() { 233 | $('#searchbox .highlight-link').fadeOut(300); 234 | $('span.highlighted').removeClass('highlighted'); 235 | }, 236 | 237 | /** 238 | * make the url absolute 239 | */ 240 | makeURL : function(relativeURL) { 241 | return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; 242 | }, 243 | 244 | /** 245 | * get the current relative url 246 | */ 247 | getCurrentURL : function() { 248 | var path = document.location.pathname; 249 | var parts = path.split(/\//); 250 | $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { 251 | if (this == '..') 252 | parts.pop(); 253 | }); 254 | var url = parts.join('/'); 255 | return path.substring(url.lastIndexOf('/') + 1, path.length - 1); 256 | }, 257 | 258 | initOnKeyListeners: function() { 259 | $(document).keyup(function(event) { 260 | var activeElementType = document.activeElement.tagName; 261 | // don't navigate when in search box or textarea 262 | if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') { 263 | switch (event.keyCode) { 264 | case 37: // left 265 | var prevHref = $('link[rel="prev"]').prop('href'); 266 | if (prevHref) { 267 | window.location.href = prevHref; 268 | return false; 269 | } 270 | case 39: // right 271 | var nextHref = $('link[rel="next"]').prop('href'); 272 | if (nextHref) { 273 | window.location.href = nextHref; 274 | return false; 275 | } 276 | } 277 | } 278 | }); 279 | } 280 | }; 281 | 282 | // quick alias for translations 283 | _ = Documentation.gettext; 284 | 285 | $(document).ready(function() { 286 | Documentation.init(); 287 | }); -------------------------------------------------------------------------------- /docs/_static/underscore.js: -------------------------------------------------------------------------------- 1 | // Underscore.js 1.3.1 2 | // (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. 3 | // Underscore is freely distributable under the MIT license. 4 | // Portions of Underscore are inspired or borrowed from Prototype, 5 | // Oliver Steele's Functional, and John Resig's Micro-Templating. 6 | // For all details and documentation: 7 | // http://documentcloud.github.com/underscore 8 | (function(){function q(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source== 9 | c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&q(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&q(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c, 10 | h)&&!f--)break;g=!f}}d.pop();return g}var r=this,G=r._,n={},k=Array.prototype,o=Object.prototype,i=k.slice,H=k.unshift,l=o.toString,I=o.hasOwnProperty,w=k.forEach,x=k.map,y=k.reduce,z=k.reduceRight,A=k.filter,B=k.every,C=k.some,p=k.indexOf,D=k.lastIndexOf,o=Array.isArray,J=Object.keys,s=Function.prototype.bind,b=function(a){return new m(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else r._=b;b.VERSION="1.3.1";var j=b.each= 11 | b.forEach=function(a,c,d){if(a!=null)if(w&&a.forEach===w)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e2;a== 12 | null&&(a=[]);if(y&&a.reduce===y)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(z&&a.reduceRight===z)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect= 13 | function(a,c,b){var e;E(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(A&&a.filter===A)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(B&&a.every===B)return a.every(c,b);j(a,function(a,g,h){if(!(e= 14 | e&&c.call(b,a,g,h)))return n});return e};var E=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(C&&a.some===C)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return n});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return p&&a.indexOf===p?a.indexOf(c)!=-1:b=E(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck= 15 | function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a, 17 | c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}}; 24 | b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=J||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.defaults=function(a){j(i.call(arguments, 25 | 1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return q(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=o||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)}; 26 | b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!b.has(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"}; 27 | b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return I.call(a,b)};b.noConflict=function(){r._=G;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.mixin=function(a){j(b.functions(a), 28 | function(c){K(c,b[c]=a[c])})};var L=0;b.uniqueId=function(a){var b=L++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var t=/.^/,u=function(a){return a.replace(/\\\\/g,"\\").replace(/\\'/g,"'")};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape||t,function(a,b){return"',_.escape("+ 29 | u(b)+"),'"}).replace(d.interpolate||t,function(a,b){return"',"+u(b)+",'"}).replace(d.evaluate||t,function(a,b){return"');"+u(b).replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var v=function(a,c){return c?b(a).chain():a},K=function(a,c){m.prototype[a]= 30 | function(){var a=i.call(arguments);H.call(a,this._wrapped);return v(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return v(d,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return v(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain= 31 | true;return this};m.prototype.value=function(){return this._wrapped}}).call(this); 32 | -------------------------------------------------------------------------------- /docs/_static/basic.css: -------------------------------------------------------------------------------- 1 | /* 2 | * basic.css 3 | * ~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- basic theme. 6 | * 7 | * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | /* -- main layout ----------------------------------------------------------- */ 13 | 14 | div.clearer { 15 | clear: both; 16 | } 17 | 18 | /* -- relbar ---------------------------------------------------------------- */ 19 | 20 | div.related { 21 | width: 100%; 22 | font-size: 90%; 23 | } 24 | 25 | div.related h3 { 26 | display: none; 27 | } 28 | 29 | div.related ul { 30 | margin: 0; 31 | padding: 0 0 0 10px; 32 | list-style: none; 33 | } 34 | 35 | div.related li { 36 | display: inline; 37 | } 38 | 39 | div.related li.right { 40 | float: right; 41 | margin-right: 5px; 42 | } 43 | 44 | /* -- sidebar --------------------------------------------------------------- */ 45 | 46 | div.sphinxsidebarwrapper { 47 | padding: 10px 5px 0 10px; 48 | } 49 | 50 | div.sphinxsidebar { 51 | float: left; 52 | width: 230px; 53 | margin-left: -100%; 54 | font-size: 90%; 55 | word-wrap: break-word; 56 | overflow-wrap : break-word; 57 | } 58 | 59 | div.sphinxsidebar ul { 60 | list-style: none; 61 | } 62 | 63 | div.sphinxsidebar ul ul, 64 | div.sphinxsidebar ul.want-points { 65 | margin-left: 20px; 66 | list-style: square; 67 | } 68 | 69 | div.sphinxsidebar ul ul { 70 | margin-top: 0; 71 | margin-bottom: 0; 72 | } 73 | 74 | div.sphinxsidebar form { 75 | margin-top: 10px; 76 | } 77 | 78 | div.sphinxsidebar input { 79 | border: 1px solid #98dbcc; 80 | font-family: sans-serif; 81 | font-size: 1em; 82 | } 83 | 84 | div.sphinxsidebar #searchbox input[type="text"] { 85 | width: 170px; 86 | } 87 | 88 | img { 89 | border: 0; 90 | max-width: 100%; 91 | } 92 | 93 | /* -- search page ----------------------------------------------------------- */ 94 | 95 | ul.search { 96 | margin: 10px 0 0 20px; 97 | padding: 0; 98 | } 99 | 100 | ul.search li { 101 | padding: 5px 0 5px 20px; 102 | background-image: url(file.png); 103 | background-repeat: no-repeat; 104 | background-position: 0 7px; 105 | } 106 | 107 | ul.search li a { 108 | font-weight: bold; 109 | } 110 | 111 | ul.search li div.context { 112 | color: #888; 113 | margin: 2px 0 0 30px; 114 | text-align: left; 115 | } 116 | 117 | ul.keywordmatches li.goodmatch a { 118 | font-weight: bold; 119 | } 120 | 121 | /* -- index page ------------------------------------------------------------ */ 122 | 123 | table.contentstable { 124 | width: 90%; 125 | margin-left: auto; 126 | margin-right: auto; 127 | } 128 | 129 | table.contentstable p.biglink { 130 | line-height: 150%; 131 | } 132 | 133 | a.biglink { 134 | font-size: 1.3em; 135 | } 136 | 137 | span.linkdescr { 138 | font-style: italic; 139 | padding-top: 5px; 140 | font-size: 90%; 141 | } 142 | 143 | /* -- general index --------------------------------------------------------- */ 144 | 145 | table.indextable { 146 | width: 100%; 147 | } 148 | 149 | table.indextable td { 150 | text-align: left; 151 | vertical-align: top; 152 | } 153 | 154 | table.indextable ul { 155 | margin-top: 0; 156 | margin-bottom: 0; 157 | list-style-type: none; 158 | } 159 | 160 | table.indextable > tbody > tr > td > ul { 161 | padding-left: 0em; 162 | } 163 | 164 | table.indextable tr.pcap { 165 | height: 10px; 166 | } 167 | 168 | table.indextable tr.cap { 169 | margin-top: 10px; 170 | background-color: #f2f2f2; 171 | } 172 | 173 | img.toggler { 174 | margin-right: 3px; 175 | margin-top: 3px; 176 | cursor: pointer; 177 | } 178 | 179 | div.modindex-jumpbox { 180 | border-top: 1px solid #ddd; 181 | border-bottom: 1px solid #ddd; 182 | margin: 1em 0 1em 0; 183 | padding: 0.4em; 184 | } 185 | 186 | div.genindex-jumpbox { 187 | border-top: 1px solid #ddd; 188 | border-bottom: 1px solid #ddd; 189 | margin: 1em 0 1em 0; 190 | padding: 0.4em; 191 | } 192 | 193 | /* -- domain module index --------------------------------------------------- */ 194 | 195 | table.modindextable td { 196 | padding: 2px; 197 | border-collapse: collapse; 198 | } 199 | 200 | /* -- general body styles --------------------------------------------------- */ 201 | 202 | div.body p, div.body dd, div.body li, div.body blockquote { 203 | -moz-hyphens: auto; 204 | -ms-hyphens: auto; 205 | -webkit-hyphens: auto; 206 | hyphens: auto; 207 | } 208 | 209 | a.headerlink { 210 | visibility: hidden; 211 | } 212 | 213 | h1:hover > a.headerlink, 214 | h2:hover > a.headerlink, 215 | h3:hover > a.headerlink, 216 | h4:hover > a.headerlink, 217 | h5:hover > a.headerlink, 218 | h6:hover > a.headerlink, 219 | dt:hover > a.headerlink, 220 | caption:hover > a.headerlink, 221 | p.caption:hover > a.headerlink, 222 | div.code-block-caption:hover > a.headerlink { 223 | visibility: visible; 224 | } 225 | 226 | div.body p.caption { 227 | text-align: inherit; 228 | } 229 | 230 | div.body td { 231 | text-align: left; 232 | } 233 | 234 | .first { 235 | margin-top: 0 !important; 236 | } 237 | 238 | p.rubric { 239 | margin-top: 30px; 240 | font-weight: bold; 241 | } 242 | 243 | img.align-left, .figure.align-left, object.align-left { 244 | clear: left; 245 | float: left; 246 | margin-right: 1em; 247 | } 248 | 249 | img.align-right, .figure.align-right, object.align-right { 250 | clear: right; 251 | float: right; 252 | margin-left: 1em; 253 | } 254 | 255 | img.align-center, .figure.align-center, object.align-center { 256 | display: block; 257 | margin-left: auto; 258 | margin-right: auto; 259 | } 260 | 261 | .align-left { 262 | text-align: left; 263 | } 264 | 265 | .align-center { 266 | text-align: center; 267 | } 268 | 269 | .align-right { 270 | text-align: right; 271 | } 272 | 273 | /* -- sidebars -------------------------------------------------------------- */ 274 | 275 | div.sidebar { 276 | margin: 0 0 0.5em 1em; 277 | border: 1px solid #ddb; 278 | padding: 7px 7px 0 7px; 279 | background-color: #ffe; 280 | width: 40%; 281 | float: right; 282 | } 283 | 284 | p.sidebar-title { 285 | font-weight: bold; 286 | } 287 | 288 | /* -- topics ---------------------------------------------------------------- */ 289 | 290 | div.topic { 291 | border: 1px solid #ccc; 292 | padding: 7px 7px 0 7px; 293 | margin: 10px 0 10px 0; 294 | } 295 | 296 | p.topic-title { 297 | font-size: 1.1em; 298 | font-weight: bold; 299 | margin-top: 10px; 300 | } 301 | 302 | /* -- admonitions ----------------------------------------------------------- */ 303 | 304 | div.admonition { 305 | margin-top: 10px; 306 | margin-bottom: 10px; 307 | padding: 7px; 308 | } 309 | 310 | div.admonition dt { 311 | font-weight: bold; 312 | } 313 | 314 | div.admonition dl { 315 | margin-bottom: 0; 316 | } 317 | 318 | p.admonition-title { 319 | margin: 0px 10px 5px 0px; 320 | font-weight: bold; 321 | } 322 | 323 | div.body p.centered { 324 | text-align: center; 325 | margin-top: 25px; 326 | } 327 | 328 | /* -- tables ---------------------------------------------------------------- */ 329 | 330 | table.docutils { 331 | border: 0; 332 | border-collapse: collapse; 333 | } 334 | 335 | table caption span.caption-number { 336 | font-style: italic; 337 | } 338 | 339 | table caption span.caption-text { 340 | } 341 | 342 | table.docutils td, table.docutils th { 343 | padding: 1px 8px 1px 5px; 344 | border-top: 0; 345 | border-left: 0; 346 | border-right: 0; 347 | border-bottom: 1px solid #aaa; 348 | } 349 | 350 | table.footnote td, table.footnote th { 351 | border: 0 !important; 352 | } 353 | 354 | th { 355 | text-align: left; 356 | padding-right: 5px; 357 | } 358 | 359 | table.citation { 360 | border-left: solid 1px gray; 361 | margin-left: 1px; 362 | } 363 | 364 | table.citation td { 365 | border-bottom: none; 366 | } 367 | 368 | /* -- figures --------------------------------------------------------------- */ 369 | 370 | div.figure { 371 | margin: 0.5em; 372 | padding: 0.5em; 373 | } 374 | 375 | div.figure p.caption { 376 | padding: 0.3em; 377 | } 378 | 379 | div.figure p.caption span.caption-number { 380 | font-style: italic; 381 | } 382 | 383 | div.figure p.caption span.caption-text { 384 | } 385 | 386 | /* -- field list styles ----------------------------------------------------- */ 387 | 388 | table.field-list td, table.field-list th { 389 | border: 0 !important; 390 | } 391 | 392 | .field-list ul { 393 | margin: 0; 394 | padding-left: 1em; 395 | } 396 | 397 | .field-list p { 398 | margin: 0; 399 | } 400 | 401 | .field-name { 402 | -moz-hyphens: manual; 403 | -ms-hyphens: manual; 404 | -webkit-hyphens: manual; 405 | hyphens: manual; 406 | } 407 | 408 | /* -- other body styles ----------------------------------------------------- */ 409 | 410 | ol.arabic { 411 | list-style: decimal; 412 | } 413 | 414 | ol.loweralpha { 415 | list-style: lower-alpha; 416 | } 417 | 418 | ol.upperalpha { 419 | list-style: upper-alpha; 420 | } 421 | 422 | ol.lowerroman { 423 | list-style: lower-roman; 424 | } 425 | 426 | ol.upperroman { 427 | list-style: upper-roman; 428 | } 429 | 430 | dl { 431 | margin-bottom: 15px; 432 | } 433 | 434 | dd p { 435 | margin-top: 0px; 436 | } 437 | 438 | dd ul, dd table { 439 | margin-bottom: 10px; 440 | } 441 | 442 | dd { 443 | margin-top: 3px; 444 | margin-bottom: 10px; 445 | margin-left: 30px; 446 | } 447 | 448 | dt:target, .highlighted { 449 | background-color: #fbe54e; 450 | } 451 | 452 | dl.glossary dt { 453 | font-weight: bold; 454 | font-size: 1.1em; 455 | } 456 | 457 | .optional { 458 | font-size: 1.3em; 459 | } 460 | 461 | .sig-paren { 462 | font-size: larger; 463 | } 464 | 465 | .versionmodified { 466 | font-style: italic; 467 | } 468 | 469 | .system-message { 470 | background-color: #fda; 471 | padding: 5px; 472 | border: 3px solid red; 473 | } 474 | 475 | .footnote:target { 476 | background-color: #ffa; 477 | } 478 | 479 | .line-block { 480 | display: block; 481 | margin-top: 1em; 482 | margin-bottom: 1em; 483 | } 484 | 485 | .line-block .line-block { 486 | margin-top: 0; 487 | margin-bottom: 0; 488 | margin-left: 1.5em; 489 | } 490 | 491 | .guilabel, .menuselection { 492 | font-family: sans-serif; 493 | } 494 | 495 | .accelerator { 496 | text-decoration: underline; 497 | } 498 | 499 | .classifier { 500 | font-style: oblique; 501 | } 502 | 503 | abbr, acronym { 504 | border-bottom: dotted 1px; 505 | cursor: help; 506 | } 507 | 508 | /* -- code displays --------------------------------------------------------- */ 509 | 510 | pre { 511 | overflow: auto; 512 | overflow-y: hidden; /* fixes display issues on Chrome browsers */ 513 | } 514 | 515 | span.pre { 516 | -moz-hyphens: none; 517 | -ms-hyphens: none; 518 | -webkit-hyphens: none; 519 | hyphens: none; 520 | } 521 | 522 | td.linenos pre { 523 | padding: 5px 0px; 524 | border: 0; 525 | background-color: transparent; 526 | color: #aaa; 527 | } 528 | 529 | table.highlighttable { 530 | margin-left: 0.5em; 531 | } 532 | 533 | table.highlighttable td { 534 | padding: 0 0.5em 0 0.5em; 535 | } 536 | 537 | div.code-block-caption { 538 | padding: 2px 5px; 539 | font-size: small; 540 | } 541 | 542 | div.code-block-caption code { 543 | background-color: transparent; 544 | } 545 | 546 | div.code-block-caption + div > div.highlight > pre { 547 | margin-top: 0; 548 | } 549 | 550 | div.code-block-caption span.caption-number { 551 | padding: 0.1em 0.3em; 552 | font-style: italic; 553 | } 554 | 555 | div.code-block-caption span.caption-text { 556 | } 557 | 558 | div.literal-block-wrapper { 559 | padding: 1em 1em 0; 560 | } 561 | 562 | div.literal-block-wrapper div.highlight { 563 | margin: 0; 564 | } 565 | 566 | code.descname { 567 | background-color: transparent; 568 | font-weight: bold; 569 | font-size: 1.2em; 570 | } 571 | 572 | code.descclassname { 573 | background-color: transparent; 574 | } 575 | 576 | code.xref, a code { 577 | background-color: transparent; 578 | font-weight: bold; 579 | } 580 | 581 | h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { 582 | background-color: transparent; 583 | } 584 | 585 | .viewcode-link { 586 | float: right; 587 | } 588 | 589 | .viewcode-back { 590 | float: right; 591 | font-family: sans-serif; 592 | } 593 | 594 | div.viewcode-block:target { 595 | margin: -1px -10px; 596 | padding: 0 10px; 597 | } 598 | 599 | /* -- math display ---------------------------------------------------------- */ 600 | 601 | img.math { 602 | vertical-align: middle; 603 | } 604 | 605 | div.body div.math p { 606 | text-align: center; 607 | } 608 | 609 | span.eqno { 610 | float: right; 611 | } 612 | 613 | span.eqno a.headerlink { 614 | position: relative; 615 | left: 0px; 616 | z-index: 1; 617 | } 618 | 619 | div.math:hover a.headerlink { 620 | visibility: visible; 621 | } 622 | 623 | /* -- printout stylesheet --------------------------------------------------- */ 624 | 625 | @media print { 626 | div.document, 627 | div.documentwrapper, 628 | div.bodywrapper { 629 | margin: 0 !important; 630 | width: 100%; 631 | } 632 | 633 | div.sphinxsidebar, 634 | div.related, 635 | div.footer, 636 | #top-link { 637 | display: none; 638 | } 639 | } -------------------------------------------------------------------------------- /docs/_static/alabaster.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | @import url("basic.css"); 54 | 55 | /* -- page layout ----------------------------------------------------------- */ 56 | 57 | body { 58 | font-family: 'goudy old style', 'minion pro', 'bell mt', Georgia, 'Hiragino Mincho Pro', serif; 59 | font-size: 17px; 60 | background-color: #fff; 61 | color: #000; 62 | margin: 0; 63 | padding: 0; 64 | } 65 | 66 | 67 | div.document { 68 | width: 940px; 69 | margin: 30px auto 0 auto; 70 | } 71 | 72 | div.documentwrapper { 73 | float: left; 74 | width: 100%; 75 | } 76 | 77 | div.bodywrapper { 78 | margin: 0 0 0 220px; 79 | } 80 | 81 | div.sphinxsidebar { 82 | width: 220px; 83 | font-size: 14px; 84 | line-height: 1.5; 85 | } 86 | 87 | hr { 88 | border: 1px solid #B1B4B6; 89 | } 90 | 91 | div.body { 92 | background-color: #fff; 93 | color: #3E4349; 94 | padding: 0 30px 0 30px; 95 | } 96 | 97 | div.body > .section { 98 | text-align: left; 99 | } 100 | 101 | div.footer { 102 | width: 940px; 103 | margin: 20px auto 30px auto; 104 | font-size: 14px; 105 | color: #888; 106 | text-align: right; 107 | } 108 | 109 | div.footer a { 110 | color: #888; 111 | } 112 | 113 | p.caption { 114 | font-family: inherit; 115 | font-size: inherit; 116 | } 117 | 118 | 119 | div.relations { 120 | display: none; 121 | } 122 | 123 | 124 | div.sphinxsidebar a { 125 | color: #444; 126 | text-decoration: none; 127 | border-bottom: 1px dotted #999; 128 | } 129 | 130 | div.sphinxsidebar a:hover { 131 | border-bottom: 1px solid #999; 132 | } 133 | 134 | div.sphinxsidebarwrapper { 135 | padding: 18px 10px; 136 | } 137 | 138 | div.sphinxsidebarwrapper p.logo { 139 | padding: 0; 140 | margin: -10px 0 0 0px; 141 | text-align: center; 142 | } 143 | 144 | div.sphinxsidebarwrapper h1.logo { 145 | margin-top: -10px; 146 | text-align: center; 147 | margin-bottom: 5px; 148 | text-align: left; 149 | } 150 | 151 | div.sphinxsidebarwrapper h1.logo-name { 152 | margin-top: 0px; 153 | } 154 | 155 | div.sphinxsidebarwrapper p.blurb { 156 | margin-top: 0; 157 | font-style: normal; 158 | } 159 | 160 | div.sphinxsidebar h3, 161 | div.sphinxsidebar h4 { 162 | font-family: 'Garamond', 'Georgia', serif; 163 | color: #444; 164 | font-size: 24px; 165 | font-weight: normal; 166 | margin: 0 0 5px 0; 167 | padding: 0; 168 | } 169 | 170 | div.sphinxsidebar h4 { 171 | font-size: 20px; 172 | } 173 | 174 | div.sphinxsidebar h3 a { 175 | color: #444; 176 | } 177 | 178 | div.sphinxsidebar p.logo a, 179 | div.sphinxsidebar h3 a, 180 | div.sphinxsidebar p.logo a:hover, 181 | div.sphinxsidebar h3 a:hover { 182 | border: none; 183 | } 184 | 185 | div.sphinxsidebar p { 186 | color: #555; 187 | margin: 10px 0; 188 | } 189 | 190 | div.sphinxsidebar ul { 191 | margin: 10px 0; 192 | padding: 0; 193 | color: #000; 194 | } 195 | 196 | div.sphinxsidebar ul li.toctree-l1 > a { 197 | font-size: 120%; 198 | } 199 | 200 | div.sphinxsidebar ul li.toctree-l2 > a { 201 | font-size: 110%; 202 | } 203 | 204 | div.sphinxsidebar input { 205 | border: 1px solid #CCC; 206 | font-family: 'goudy old style', 'minion pro', 'bell mt', Georgia, 'Hiragino Mincho Pro', serif; 207 | font-size: 1em; 208 | } 209 | 210 | div.sphinxsidebar hr { 211 | border: none; 212 | height: 1px; 213 | color: #AAA; 214 | background: #AAA; 215 | 216 | text-align: left; 217 | margin-left: 0; 218 | width: 50%; 219 | } 220 | 221 | /* -- body styles ----------------------------------------------------------- */ 222 | 223 | a { 224 | color: #004B6B; 225 | text-decoration: underline; 226 | } 227 | 228 | a:hover { 229 | color: #6D4100; 230 | text-decoration: underline; 231 | } 232 | 233 | div.body h1, 234 | div.body h2, 235 | div.body h3, 236 | div.body h4, 237 | div.body h5, 238 | div.body h6 { 239 | font-family: 'Garamond', 'Georgia', serif; 240 | font-weight: normal; 241 | margin: 30px 0px 10px 0px; 242 | padding: 0; 243 | } 244 | 245 | div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } 246 | div.body h2 { font-size: 180%; } 247 | div.body h3 { font-size: 150%; } 248 | div.body h4 { font-size: 130%; } 249 | div.body h5 { font-size: 100%; } 250 | div.body h6 { font-size: 100%; } 251 | 252 | a.headerlink { 253 | color: #DDD; 254 | padding: 0 4px; 255 | text-decoration: none; 256 | } 257 | 258 | a.headerlink:hover { 259 | color: #444; 260 | background: #EAEAEA; 261 | } 262 | 263 | div.body p, div.body dd, div.body li { 264 | line-height: 1.4em; 265 | } 266 | 267 | div.admonition { 268 | margin: 20px 0px; 269 | padding: 10px 30px; 270 | background-color: #EEE; 271 | border: 1px solid #CCC; 272 | } 273 | 274 | div.admonition tt.xref, div.admonition code.xref, div.admonition a tt { 275 | background-color: #FBFBFB; 276 | border-bottom: 1px solid #fafafa; 277 | } 278 | 279 | div.admonition p.admonition-title { 280 | font-family: 'Garamond', 'Georgia', serif; 281 | font-weight: normal; 282 | font-size: 24px; 283 | margin: 0 0 10px 0; 284 | padding: 0; 285 | line-height: 1; 286 | } 287 | 288 | div.admonition p.last { 289 | margin-bottom: 0; 290 | } 291 | 292 | div.highlight { 293 | background-color: #fff; 294 | } 295 | 296 | dt:target, .highlight { 297 | background: #FAF3E8; 298 | } 299 | 300 | div.warning { 301 | background-color: #FCC; 302 | border: 1px solid #FAA; 303 | } 304 | 305 | div.danger { 306 | background-color: #FCC; 307 | border: 1px solid #FAA; 308 | -moz-box-shadow: 2px 2px 4px #D52C2C; 309 | -webkit-box-shadow: 2px 2px 4px #D52C2C; 310 | box-shadow: 2px 2px 4px #D52C2C; 311 | } 312 | 313 | div.error { 314 | background-color: #FCC; 315 | border: 1px solid #FAA; 316 | -moz-box-shadow: 2px 2px 4px #D52C2C; 317 | -webkit-box-shadow: 2px 2px 4px #D52C2C; 318 | box-shadow: 2px 2px 4px #D52C2C; 319 | } 320 | 321 | div.caution { 322 | background-color: #FCC; 323 | border: 1px solid #FAA; 324 | } 325 | 326 | div.attention { 327 | background-color: #FCC; 328 | border: 1px solid #FAA; 329 | } 330 | 331 | div.important { 332 | background-color: #EEE; 333 | border: 1px solid #CCC; 334 | } 335 | 336 | div.note { 337 | background-color: #EEE; 338 | border: 1px solid #CCC; 339 | } 340 | 341 | div.tip { 342 | background-color: #EEE; 343 | border: 1px solid #CCC; 344 | } 345 | 346 | div.hint { 347 | background-color: #EEE; 348 | border: 1px solid #CCC; 349 | } 350 | 351 | div.seealso { 352 | background-color: #EEE; 353 | border: 1px solid #CCC; 354 | } 355 | 356 | div.topic { 357 | background-color: #EEE; 358 | } 359 | 360 | p.admonition-title { 361 | display: inline; 362 | } 363 | 364 | p.admonition-title:after { 365 | content: ":"; 366 | } 367 | 368 | pre, tt, code { 369 | font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; 370 | font-size: 0.9em; 371 | } 372 | 373 | .hll { 374 | background-color: #FFC; 375 | margin: 0 -12px; 376 | padding: 0 12px; 377 | display: block; 378 | } 379 | 380 | img.screenshot { 381 | } 382 | 383 | tt.descname, tt.descclassname, code.descname, code.descclassname { 384 | font-size: 0.95em; 385 | } 386 | 387 | tt.descname, code.descname { 388 | padding-right: 0.08em; 389 | } 390 | 391 | img.screenshot { 392 | -moz-box-shadow: 2px 2px 4px #EEE; 393 | -webkit-box-shadow: 2px 2px 4px #EEE; 394 | box-shadow: 2px 2px 4px #EEE; 395 | } 396 | 397 | table.docutils { 398 | border: 1px solid #888; 399 | -moz-box-shadow: 2px 2px 4px #EEE; 400 | -webkit-box-shadow: 2px 2px 4px #EEE; 401 | box-shadow: 2px 2px 4px #EEE; 402 | } 403 | 404 | table.docutils td, table.docutils th { 405 | border: 1px solid #888; 406 | padding: 0.25em 0.7em; 407 | } 408 | 409 | table.field-list, table.footnote { 410 | border: none; 411 | -moz-box-shadow: none; 412 | -webkit-box-shadow: none; 413 | box-shadow: none; 414 | } 415 | 416 | table.footnote { 417 | margin: 15px 0; 418 | width: 100%; 419 | border: 1px solid #EEE; 420 | background: #FDFDFD; 421 | font-size: 0.9em; 422 | } 423 | 424 | table.footnote + table.footnote { 425 | margin-top: -15px; 426 | border-top: none; 427 | } 428 | 429 | table.field-list th { 430 | padding: 0 0.8em 0 0; 431 | } 432 | 433 | table.field-list td { 434 | padding: 0; 435 | } 436 | 437 | table.field-list p { 438 | margin-bottom: 0.8em; 439 | } 440 | 441 | /* Cloned from 442 | * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68 443 | */ 444 | .field-name { 445 | -moz-hyphens: manual; 446 | -ms-hyphens: manual; 447 | -webkit-hyphens: manual; 448 | hyphens: manual; 449 | } 450 | 451 | table.footnote td.label { 452 | width: .1px; 453 | padding: 0.3em 0 0.3em 0.5em; 454 | } 455 | 456 | table.footnote td { 457 | padding: 0.3em 0.5em; 458 | } 459 | 460 | dl { 461 | margin: 0; 462 | padding: 0; 463 | } 464 | 465 | dl dd { 466 | margin-left: 30px; 467 | } 468 | 469 | blockquote { 470 | margin: 0 0 0 30px; 471 | padding: 0; 472 | } 473 | 474 | ul, ol { 475 | /* Matches the 30px from the narrow-screen "li > ul" selector below */ 476 | margin: 10px 0 10px 30px; 477 | padding: 0; 478 | } 479 | 480 | pre { 481 | background: #EEE; 482 | padding: 7px 30px; 483 | margin: 15px 0px; 484 | line-height: 1.3em; 485 | } 486 | 487 | div.viewcode-block:target { 488 | background: #ffd; 489 | } 490 | 491 | dl pre, blockquote pre, li pre { 492 | margin-left: 0; 493 | padding-left: 30px; 494 | } 495 | 496 | tt, code { 497 | background-color: #ecf0f3; 498 | color: #222; 499 | /* padding: 1px 2px; */ 500 | } 501 | 502 | tt.xref, code.xref, a tt { 503 | background-color: #FBFBFB; 504 | border-bottom: 1px solid #fff; 505 | } 506 | 507 | a.reference { 508 | text-decoration: none; 509 | border-bottom: 1px dotted #004B6B; 510 | } 511 | 512 | /* Don't put an underline on images */ 513 | a.image-reference, a.image-reference:hover { 514 | border-bottom: none; 515 | } 516 | 517 | a.reference:hover { 518 | border-bottom: 1px solid #6D4100; 519 | } 520 | 521 | a.footnote-reference { 522 | text-decoration: none; 523 | font-size: 0.7em; 524 | vertical-align: top; 525 | border-bottom: 1px dotted #004B6B; 526 | } 527 | 528 | a.footnote-reference:hover { 529 | border-bottom: 1px solid #6D4100; 530 | } 531 | 532 | a:hover tt, a:hover code { 533 | background: #EEE; 534 | } 535 | 536 | 537 | @media screen and (max-width: 870px) { 538 | 539 | div.sphinxsidebar { 540 | display: none; 541 | } 542 | 543 | div.document { 544 | width: 100%; 545 | 546 | } 547 | 548 | div.documentwrapper { 549 | margin-left: 0; 550 | margin-top: 0; 551 | margin-right: 0; 552 | margin-bottom: 0; 553 | } 554 | 555 | div.bodywrapper { 556 | margin-top: 0; 557 | margin-right: 0; 558 | margin-bottom: 0; 559 | margin-left: 0; 560 | } 561 | 562 | ul { 563 | margin-left: 0; 564 | } 565 | 566 | li > ul { 567 | /* Matches the 30px from the "ul, ol" selector above */ 568 | margin-left: 30px; 569 | } 570 | 571 | .document { 572 | width: auto; 573 | } 574 | 575 | .footer { 576 | width: auto; 577 | } 578 | 579 | .bodywrapper { 580 | margin: 0; 581 | } 582 | 583 | .footer { 584 | width: auto; 585 | } 586 | 587 | .github { 588 | display: none; 589 | } 590 | 591 | 592 | 593 | } 594 | 595 | 596 | 597 | @media screen and (max-width: 875px) { 598 | 599 | body { 600 | margin: 0; 601 | padding: 20px 30px; 602 | } 603 | 604 | div.documentwrapper { 605 | float: none; 606 | background: #fff; 607 | } 608 | 609 | div.sphinxsidebar { 610 | display: block; 611 | float: none; 612 | width: 102.5%; 613 | margin: 50px -30px -20px -30px; 614 | padding: 10px 20px; 615 | background: #333; 616 | color: #FFF; 617 | } 618 | 619 | div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, 620 | div.sphinxsidebar h3 a { 621 | color: #fff; 622 | } 623 | 624 | div.sphinxsidebar a { 625 | color: #AAA; 626 | } 627 | 628 | div.sphinxsidebar p.logo { 629 | display: none; 630 | } 631 | 632 | div.document { 633 | width: 100%; 634 | margin: 0; 635 | } 636 | 637 | div.footer { 638 | display: none; 639 | } 640 | 641 | div.bodywrapper { 642 | margin: 0; 643 | } 644 | 645 | div.body { 646 | min-height: 0; 647 | padding: 0; 648 | } 649 | 650 | .rtd_doc_footer { 651 | display: none; 652 | } 653 | 654 | .document { 655 | width: auto; 656 | } 657 | 658 | .footer { 659 | width: auto; 660 | } 661 | 662 | .footer { 663 | width: auto; 664 | } 665 | 666 | .github { 667 | display: none; 668 | } 669 | } 670 | 671 | 672 | /* misc. */ 673 | 674 | .revsys-inline { 675 | display: none!important; 676 | } 677 | 678 | /* Make nested-list/multi-paragraph items look better in Releases changelog 679 | * pages. Without this, docutils' magical list fuckery causes inconsistent 680 | * formatting between different release sub-lists. 681 | */ 682 | div#changelog > div.section > ul > li > p:only-child { 683 | margin-bottom: 0; 684 | } 685 | 686 | /* Hide fugly table cell borders in ..bibliography:: directive output */ 687 | table.docutils.citation, table.docutils.citation td, table.docutils.citation th { 688 | border: none; 689 | /* Below needed in some edge cases; if not applied, bottom shadows appear */ 690 | -moz-box-shadow: none; 691 | -webkit-box-shadow: none; 692 | box-shadow: none; 693 | } -------------------------------------------------------------------------------- /docs/_modules/Solid/StochasticHillClimb.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | Solid.StochasticHillClimb — Solid 0.11 documentation 10 | 11 | 12 | 13 | 14 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
40 |
41 |
42 |
43 | 44 |

Source code for Solid.StochasticHillClimb

 45 | from abc import ABCMeta, abstractmethod
 46 | from copy import deepcopy
 47 | from math import exp
 48 | from random import random
 49 | 
 50 | 
 51 | 
[docs]class StochasticHillClimb: 52 | """ 53 | Conducts stochastic hill climb 54 | """ 55 | __metaclass__ = ABCMeta 56 | 57 | initial_state = None 58 | current_state = None 59 | best_state = None 60 | 61 | cur_steps = 0 62 | max_steps = None 63 | 64 | best_objective = None 65 | max_objective = None 66 | 67 | temp = None 68 | 69 | def __init__(self, initial_state, temp, max_steps, max_objective=None): 70 | """ 71 | 72 | :param initial_state: initial state of hill climbing 73 | :param max_steps: maximum steps to run hill climbing for 74 | :param temp: temperature in probabilistic acceptance of transition 75 | :param max_objective: objective function to stop algorithm once reached 76 | """ 77 | self.initial_state = initial_state 78 | 79 | if isinstance(max_steps, int) and max_steps > 0: 80 | self.max_steps = max_steps 81 | else: 82 | raise ValueError('Max steps must be a positive integer') 83 | 84 | if max_objective is not None: 85 | if isinstance(max_objective, (float, int)): 86 | self.max_objective = float(max_objective) 87 | else: 88 | raise ValueError('Maximum objective must be a numeric type') 89 | 90 | if isinstance(temp, (float, int)): 91 | self.temp = float(temp) 92 | else: 93 | raise ValueError('Temperature must be a numeric type') 94 | 95 | def __str__(self): 96 | return ('STOCHASTIC HILL CLIMB: \n' + 97 | 'CURRENT STEPS: %d \n' + 98 | 'BEST OBJECTIVE: %f \n' + 99 | 'BEST STATE: %s \n\n') % \ 100 | (self.cur_steps, self.best_objective, str(self.best_state)) 101 | 102 | def __repr__(self): 103 | return self.__str__() 104 | 105 | def _clear(self): 106 | """ 107 | Resets the variables that are altered on a per-run basis of the algorithm 108 | 109 | :return: None 110 | """ 111 | self.cur_steps = 0 112 | self.current_state = None 113 | self.best_state = None 114 | self.best_objective = None 115 | 116 | @abstractmethod 117 | def _neighbor(self): 118 | """ 119 | Returns a random member of the neighbor of the current state 120 | 121 | :return: a random neighbor, given access to self.current_state 122 | """ 123 | pass 124 | 125 | @abstractmethod 126 | def _objective(self, state): 127 | """ 128 | Evaluates a given state 129 | 130 | :param state: a state 131 | :return: objective function value of state 132 | """ 133 | pass 134 | 135 | def _accept_neighbor(self, neighbor): 136 | """ 137 | Probabilistically determines whether or not to accept a transition to a neighbor 138 | 139 | :param neighbor: a state 140 | :return: boolean indicating whether or not transition was accepted 141 | """ 142 | try: 143 | p = 1. / (1 + (exp((self._objective(self.current_state) - self._objective(neighbor)) / self.temp))) 144 | except OverflowError: 145 | return True 146 | return True if p >= 1 else p >= random() 147 | 148 |
[docs] def run(self, verbose=True): 149 | """ 150 | Conducts hill climb 151 | 152 | :param verbose: indicates whether or not to print progress regularly 153 | :return: best state and best objective function value 154 | """ 155 | self._clear() 156 | self.current_state = self.initial_state 157 | for i in range(self.max_steps): 158 | self.cur_steps += 1 159 | 160 | if ((i + 1) % 100 == 0) and verbose: 161 | print self 162 | 163 | neighbor = self._neighbor() 164 | 165 | if self._accept_neighbor(neighbor): 166 | self.current_state = neighbor 167 | 168 | if self._objective(self.current_state) > self.best_objective: 169 | self.best_objective = self._objective(self.current_state) 170 | self.best_state = deepcopy(self.current_state) 171 | 172 | if self.max_objective is not None and self.best_objective > self.max_objective: 173 | print "TERMINATING - REACHED MAXIMUM OBJECTIVE" 174 | return self.best_state, self.best_objective 175 | print "TERMINATING - REACHED MAXIMUM STEPS" 176 | return self.best_state, self.best_objective
177 |
178 | 179 |
180 |
181 |
182 | 204 |
205 |
206 | 214 | 215 | 216 | 217 | 218 | 219 | -------------------------------------------------------------------------------- /docs/_modules/Solid/TabuSearch.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | Solid.TabuSearch — Solid 0.11 documentation 10 | 11 | 12 | 13 | 14 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
40 |
41 |
42 |
43 | 44 |

Source code for Solid.TabuSearch

 45 | from abc import ABCMeta, abstractmethod
 46 | from copy import deepcopy
 47 | from random import randint, random, shuffle
 48 | from collections import deque
 49 | from numpy import argmax
 50 | 
 51 | 
[docs]class TabuSearch: 52 | """ 53 | Conducts tabu search 54 | """ 55 | __metaclass__ = ABCMeta 56 | 57 | cur_steps = None 58 | 59 | tabu_size = None 60 | tabu_list = None 61 | 62 | initial_state = None 63 | current = None 64 | best = None 65 | 66 | max_steps = None 67 | max_score = None 68 | 69 | def __init__(self, initial_state, tabu_size, max_steps, max_score=None): 70 | """ 71 | 72 | :param initial_state: initial state, should implement __eq__ or __cmp__ 73 | :param tabu_size: number of states to keep in tabu list 74 | :param max_steps: maximum number of steps to run algorithm for 75 | :param max_score: score to stop algorithm once reached 76 | """ 77 | self.initial_state = initial_state 78 | 79 | if isinstance(tabu_size, int) and tabu_size > 0: 80 | self.tabu_size = tabu_size 81 | else: 82 | raise TypeError('Tabu size must be a positive integer') 83 | 84 | if isinstance(max_steps, int) and max_steps > 0: 85 | self.max_steps = max_steps 86 | else: 87 | raise TypeError('Maximum steps must be a positive integer') 88 | 89 | if max_score is not None: 90 | if isinstance(max_score, (int, float)): 91 | self.max_score = float(max_score) 92 | else: 93 | raise TypeError('Maximum score must be a numeric type') 94 | 95 | def __str__(self): 96 | return ('TABU SEARCH: \n' + 97 | 'CURRENT STEPS: %d \n' + 98 | 'BEST SCORE: %f \n' + 99 | 'BEST MEMBER: %s \n\n') % \ 100 | (self.cur_steps, self._score(self.best), str(self.best)) 101 | 102 | def __repr__(self): 103 | return self.__str__() 104 | 105 | def _clear(self): 106 | """ 107 | Resets the variables that are altered on a per-run basis of the algorithm 108 | 109 | :return: None 110 | """ 111 | self.cur_steps = 0 112 | self.tabu_list = deque(maxlen=self.tabu_size) 113 | self.current = self.initial_state 114 | self.best = self.initial_state 115 | 116 | @abstractmethod 117 | def _score(self, state): 118 | """ 119 | Returns objective function value of a state 120 | 121 | :param state: a state 122 | :return: objective function value of state 123 | """ 124 | pass 125 | 126 | @abstractmethod 127 | def _neighborhood(self): 128 | """ 129 | Returns list of all members of neighborhood of current state, given self.current 130 | 131 | :return: list of members of neighborhood 132 | """ 133 | pass 134 | 135 | def _best(self, neighborhood): 136 | """ 137 | Finds the best member of a neighborhood 138 | 139 | :param neighborhood: a neighborhood 140 | :return: best member of neighborhood 141 | """ 142 | return neighborhood[argmax([self._score(x) for x in neighborhood])] 143 | 144 |
[docs] def run(self, verbose=True): 145 | """ 146 | Conducts tabu search 147 | 148 | :param verbose: indicates whether or not to print progress regularly 149 | :return: best state and objective function value of best state 150 | """ 151 | self._clear() 152 | for i in range(self.max_steps): 153 | self.cur_steps += 1 154 | 155 | if ((i + 1) % 100 == 0) and verbose: 156 | print self 157 | 158 | neighborhood = self._neighborhood() 159 | neighborhood_best = self._best(neighborhood) 160 | 161 | while True: 162 | if all([x in self.tabu_list for x in neighborhood]): 163 | print "TERMINATING - NO SUITABLE NEIGHBORS" 164 | return self.best, self._score(self.best) 165 | if neighborhood_best in self.tabu_list: 166 | if self._score(neighborhood_best) > self._score(self.best): 167 | self.tabu_list.append(neighborhood_best) 168 | self.best = deepcopy(neighborhood_best) 169 | break 170 | else: 171 | neighborhood.remove(neighborhood_best) 172 | neighborhood_best = self._best(neighborhood) 173 | else: 174 | self.tabu_list.append(neighborhood_best) 175 | self.current = neighborhood_best 176 | if self._score(self.current) > self._score(self.best): 177 | self.best = deepcopy(self.current) 178 | break 179 | 180 | if self.max_score is not None and self._score(self.best) > self.max_score: 181 | print "TERMINATING - REACHED MAXIMUM SCORE" 182 | return self.best, self._score(self.best) 183 | print "TERMINATING - REACHED MAXIMUM STEPS" 184 | return self.best, self._score(self.best)
185 |
186 | 187 |
188 |
189 |
190 | 212 |
213 |
214 | 222 | 223 | 224 | 225 | 226 | 227 | -------------------------------------------------------------------------------- /docs/genindex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | Index — Solid 0.11 documentation 11 | 12 | 13 | 14 | 15 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
41 |
42 |
43 |
44 | 45 | 46 |

Index

47 | 48 |
49 | A 50 | | B 51 | | C 52 | | E 53 | | F 54 | | G 55 | | H 56 | | I 57 | | L 58 | | M 59 | | P 60 | | R 61 | | S 62 | | T 63 | | U 64 | | V 65 | 66 |
67 |

A

68 | 69 | 73 |
74 | 75 |

B

76 | 77 | 95 | 111 |
112 | 113 |

C

114 | 115 | 145 | 159 |
160 | 161 |

E

162 | 163 | 167 |
168 | 169 |

F

170 | 171 | 179 | 183 |
184 | 185 |

G

186 | 187 | 191 | 195 |
196 | 197 |

H

198 | 199 | 203 | 209 |
210 | 211 |

I

212 | 213 | 223 |
224 | 225 |

L

226 | 227 | 231 |
232 | 233 |

M

234 | 235 | 267 | 283 |
284 | 285 |

P

286 | 287 | 293 | 303 |
304 | 305 |

R

306 | 307 | 325 | 343 |
344 | 345 |

S

346 | 347 | 365 | 381 |
382 | 383 |

T

384 | 385 | 391 | 397 |
398 | 399 |

U

400 | 401 | 405 | 409 |
410 | 411 |

V

412 | 413 | 417 |
418 | 419 | 420 | 421 |
422 |
423 |
424 | 447 |
448 |
449 | 457 | 458 | 459 | 460 | 461 | 462 | -------------------------------------------------------------------------------- /docs/_modules/Solid/SimulatedAnnealing.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | Solid.SimulatedAnnealing — Solid 0.11 documentation 10 | 11 | 12 | 13 | 14 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
40 |
41 |
42 |
43 | 44 |

Source code for Solid.SimulatedAnnealing

 45 | from abc import ABCMeta, abstractmethod
 46 | from copy import deepcopy
 47 | from math import exp
 48 | from random import random
 49 | 
 50 | 
 51 | 
[docs]class SimulatedAnnealing: 52 | """ 53 | Conducts simulated annealing algorithm 54 | """ 55 | __metaclass__ = ABCMeta 56 | 57 | initial_state = None 58 | current_state = None 59 | best_state = None 60 | 61 | cur_steps = 0 62 | max_steps = None 63 | 64 | current_energy = None 65 | best_energy = None 66 | min_energy = None 67 | 68 | start_temp = None 69 | current_temp = None 70 | adjust_temp = None 71 | 72 | def _exponential(self, schedule_constant): 73 | def f(): 74 | self.current_temp *= schedule_constant 75 | return f 76 | 77 | def _linear(self, schedule_constant): 78 | def f(): 79 | self.current_temp -= schedule_constant 80 | return f 81 | 82 | def _get_schedule(self, schedule_str, schedule_constant): 83 | if schedule_str == 'exponential': 84 | return self._exponential(schedule_constant) 85 | elif schedule_str == 'linear': 86 | return self._linear(schedule_constant) 87 | else: 88 | raise ValueError('Annealing schedule must be either "exponential" or "linear"') 89 | 90 | def __init__(self, initial_state, temp_begin, schedule_constant, max_steps, 91 | min_energy=None, schedule='exponential'): 92 | """ 93 | 94 | :param initial_state: initial state of annealing algorithm 95 | :param max_steps: maximum number of iterations to conduct annealing for 96 | :param temp_begin: beginning temperature 97 | :param schedule_constant: constant value in annealing schedule function 98 | :param min_energy: energy value to stop algorithm once reached 99 | :param schedule: 'exponential' or 'linear' annealing schedule 100 | """ 101 | self.initial_state = initial_state 102 | 103 | if isinstance(max_steps, int) and max_steps > 0: 104 | self.max_steps = max_steps 105 | else: 106 | raise ValueError('Max steps must be a positive integer') 107 | 108 | if min_energy is not None: 109 | if isinstance(min_energy, (float, int)): 110 | self.min_energy = float(min_energy) 111 | else: 112 | raise ValueError('Minimum energy must be a numeric type') 113 | 114 | if isinstance(temp_begin, (float, int)): 115 | self.start_temp = float(temp_begin) 116 | else: 117 | raise ValueError('Starting temperature must be a numeric type') 118 | 119 | self.adjust_temp = self._get_schedule(schedule, schedule_constant) 120 | 121 | def __str__(self): 122 | return ('SIMULATED ANNEALING: \n' + 123 | 'CURRENT STEPS: %d \n' + 124 | 'CURRENT TEMPERATURE: %f \n' + 125 | 'BEST ENERGY: %f \n' + 126 | 'BEST STATE: %s \n\n') % \ 127 | (self.cur_steps, self.current_temp, self.best_energy, str(self.best_state)) 128 | 129 | def __repr__(self): 130 | return self.__str__() 131 | 132 | def _clear(self): 133 | """ 134 | Resets the variables that are altered on a per-run basis of the algorithm 135 | 136 | :return: None 137 | """ 138 | self.cur_steps = 0 139 | self.current_state = None 140 | self.best_state = None 141 | self.current_energy = None 142 | self.best_energy = None 143 | 144 | @abstractmethod 145 | def _neighbor(self): 146 | """ 147 | Returns a random member of the neighbor of the current state 148 | 149 | :return: a random neighbor, given access to self.current_state 150 | """ 151 | pass 152 | 153 | @abstractmethod 154 | def _energy(self, state): 155 | """ 156 | Finds the energy of a given state 157 | 158 | :param state: a state 159 | :return: energy of state 160 | """ 161 | pass 162 | 163 | def _accept_neighbor(self, neighbor): 164 | """ 165 | Probabilistically determines whether or not to accept a transition to a neighbor 166 | 167 | :param neighbor: a state 168 | :return: boolean indicating whether or not transition is accepted 169 | """ 170 | try: 171 | p = exp(-(self._energy(neighbor) - self._energy(self.current_state)) / self.current_temp) 172 | except OverflowError: 173 | return True 174 | return True if p >= 1 else p >= random() 175 | 176 |
[docs] def run(self, verbose=True): 177 | """ 178 | Conducts simulated annealing 179 | 180 | :param verbose: indicates whether or not to print progress regularly 181 | :return: best state and best energy 182 | """ 183 | self._clear() 184 | self.current_state = self.initial_state 185 | self.current_temp = self.start_temp 186 | self.best_energy = self._energy(self.current_state) 187 | for i in range(self.max_steps): 188 | self.cur_steps += 1 189 | 190 | if ((i + 1) % 100 == 0) and verbose: 191 | print self 192 | 193 | neighbor = self._neighbor() 194 | 195 | if self._accept_neighbor(neighbor): 196 | self.current_state = neighbor 197 | self.current_energy = self._energy(self.current_state) 198 | 199 | if self.current_energy < self.best_energy: 200 | self.best_energy = self.current_energy 201 | self.best_state = deepcopy(self.current_state) 202 | 203 | if self.min_energy is not None and self.current_energy < self.min_energy: 204 | print "TERMINATING - REACHED MINIMUM ENERGY" 205 | return self.best_state, self.best_energy 206 | 207 | self.adjust_temp() 208 | if self.current_temp < 0.000001: 209 | print "TERMINATING - REACHED TEMPERATURE OF 0" 210 | return self.best_state, self.best_energy 211 | print "TERMINATING - REACHED MAXIMUM STEPS" 212 | return self.best_state, self.best_energy
213 |
214 | 215 |
216 |
217 |
218 | 240 |
241 |
242 | 250 | 251 | 252 | 253 | 254 | 255 | --------------------------------------------------------------------------------