├── 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
│ ├── up-pressed.png
│ ├── ajax-loader.gif
│ ├── down-pressed.png
│ ├── comment-bright.png
│ ├── comment-close.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/master/logo.png
--------------------------------------------------------------------------------
/docs/_static/custom.css:
--------------------------------------------------------------------------------
1 | /* This file intentionally left blank. */
2 |
--------------------------------------------------------------------------------
/docs/objects.inv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gaarv/Solid/master/docs/objects.inv
--------------------------------------------------------------------------------
/docs/_static/up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gaarv/Solid/master/docs/_static/up.png
--------------------------------------------------------------------------------
/docs/_static/down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gaarv/Solid/master/docs/_static/down.png
--------------------------------------------------------------------------------
/docs/_static/file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gaarv/Solid/master/docs/_static/file.png
--------------------------------------------------------------------------------
/docs/_static/minus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gaarv/Solid/master/docs/_static/minus.png
--------------------------------------------------------------------------------
/docs/_static/plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gaarv/Solid/master/docs/_static/plus.png
--------------------------------------------------------------------------------
/docs/_static/comment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gaarv/Solid/master/docs/_static/comment.png
--------------------------------------------------------------------------------
/docs/_static/up-pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gaarv/Solid/master/docs/_static/up-pressed.png
--------------------------------------------------------------------------------
/docs/_static/ajax-loader.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gaarv/Solid/master/docs/_static/ajax-loader.gif
--------------------------------------------------------------------------------
/docs/_static/down-pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gaarv/Solid/master/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/master/docs/_static/comment-bright.png
--------------------------------------------------------------------------------
/docs/_static/comment-close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gaarv/Solid/master/docs/_static/comment-close.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 | [](https://travis-ci.org/100/Solid)
8 | [](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 |
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 |
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 |
53 |
54 |
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 | $('').
166 | attr('href', '#' + this.id).
167 | attr('title', _('Permalink to this headline')).
168 | appendTo(this);
169 | });
170 | $('dt[id]').each(function() {
171 | $('').
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 | $('' + _('Hide Search Matches') + '
')
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 |
74 |
75 |
B
76 |
112 |
113 |
C
114 |
160 |
161 |
E
162 |
168 |
169 |
F
170 |
184 |
185 |
G
186 |
196 |
197 |
H
198 |
210 |
211 |
I
212 |
224 |
225 |
L
226 |
232 |
233 |
M
234 |
284 |
285 |
P
286 |
304 |
305 |
R
306 |
344 |
345 |
S
346 |
382 |
383 |
T
384 |
398 |
399 |
U
400 |
410 |
411 |
V
412 |
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 |
--------------------------------------------------------------------------------