├── cvxpy-mip-helpers
├── __init__.py
├── sos.py
└── mip.py
├── docs
├── _build
│ ├── html
│ │ ├── _static
│ │ │ ├── custom.css
│ │ │ ├── file.png
│ │ │ ├── plus.png
│ │ │ ├── minus.png
│ │ │ ├── documentation_options.js
│ │ │ ├── pygments.css
│ │ │ ├── doctools.js
│ │ │ ├── underscore.js
│ │ │ ├── language_data.js
│ │ │ ├── alabaster.css
│ │ │ ├── basic.css
│ │ │ ├── searchtools.js
│ │ │ └── underscore-1.3.1.js
│ │ ├── objects.inv
│ │ ├── .buildinfo
│ │ ├── searchindex.js
│ │ ├── _sources
│ │ │ └── index.rst.txt
│ │ ├── genindex.html
│ │ ├── search.html
│ │ └── index.html
│ └── doctrees
│ │ ├── index.doctree
│ │ └── environment.pickle
├── index.rst
├── Makefile
├── make.bat
└── conf.py
├── .gitignore
├── setup.py
├── examples
├── flappy_bird.py
├── lunar_land.py
└── cheb.py
└── README.md
/cvxpy-mip-helpers/__init__.py:
--------------------------------------------------------------------------------
1 | from .mip import *
--------------------------------------------------------------------------------
/docs/_build/html/_static/custom.css:
--------------------------------------------------------------------------------
1 | /* This file intentionally left blank. */
2 |
--------------------------------------------------------------------------------
/docs/_build/html/objects.inv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/philzook58/cvxpy-helpers/master/docs/_build/html/objects.inv
--------------------------------------------------------------------------------
/docs/_build/html/_static/file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/philzook58/cvxpy-helpers/master/docs/_build/html/_static/file.png
--------------------------------------------------------------------------------
/docs/_build/html/_static/plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/philzook58/cvxpy-helpers/master/docs/_build/html/_static/plus.png
--------------------------------------------------------------------------------
/docs/_build/doctrees/index.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/philzook58/cvxpy-helpers/master/docs/_build/doctrees/index.doctree
--------------------------------------------------------------------------------
/docs/_build/html/_static/minus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/philzook58/cvxpy-helpers/master/docs/_build/html/_static/minus.png
--------------------------------------------------------------------------------
/docs/_build/doctrees/environment.pickle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/philzook58/cvxpy-helpers/master/docs/_build/doctrees/environment.pickle
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled python modules.
2 | *.pyc
3 |
4 | # Setuptools distribution folder.
5 | /dist/
6 |
7 | # Python egg metadata, regenerated from source files by setuptools.
8 | /*.egg-info
--------------------------------------------------------------------------------
/docs/_build/html/.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: 7afd6ab376664667c1589a1811f23059
4 | tags: 645f666f9bcd5a90fca523b33c5a78b7
5 |
--------------------------------------------------------------------------------
/docs/_build/html/_static/documentation_options.js:
--------------------------------------------------------------------------------
1 | var DOCUMENTATION_OPTIONS = {
2 | URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
3 | VERSION: '',
4 | LANGUAGE: 'None',
5 | COLLAPSE_INDEX: false,
6 | FILE_SUFFIX: '.html',
7 | HAS_SOURCE: true,
8 | SOURCELINK_SUFFIX: '.txt',
9 | NAVIGATION_WITH_KEYS: false
10 | };
--------------------------------------------------------------------------------
/docs/_build/html/searchindex.js:
--------------------------------------------------------------------------------
1 | Search.setIndex({docnames:["index"],envversion:{"sphinx.domains.c":1,"sphinx.domains.changeset":1,"sphinx.domains.cpp":1,"sphinx.domains.javascript":1,"sphinx.domains.math":2,"sphinx.domains.python":1,"sphinx.domains.rst":1,"sphinx.domains.std":1,sphinx:56},filenames:["index.rst"],objects:{},objnames:{},objtypes:{},terms:{index:0,modul:0,page:0,search:0},titles:["Welcome to cvxpy-helpers\u2019s documentation!"],titleterms:{cvxpy:0,document:0,helper:0,indic:0,tabl:0,welcom:0}})
--------------------------------------------------------------------------------
/docs/index.rst:
--------------------------------------------------------------------------------
1 | .. cvxpy-helpers documentation master file, created by
2 | sphinx-quickstart on Fri May 31 16:24:56 2019.
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 cvxpy-helpers'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 |
--------------------------------------------------------------------------------
/docs/_build/html/_sources/index.rst.txt:
--------------------------------------------------------------------------------
1 | .. cvxpy-helpers documentation master file, created by
2 | sphinx-quickstart on Fri May 31 16:24:56 2019.
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 cvxpy-helpers'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 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup
2 |
3 |
4 | with open("README.md", "r") as fh:
5 | long_description = fh.read()
6 |
7 | setup(name='cvxpy-mip-helpers',
8 | version='0.1',
9 | description='Helper functions for mip formulations in cvxpy',
10 | url='http://github.com/storborg/funniest',
11 | author='Philip Zucker',
12 | author_email='flyingcircus@example.com',
13 | license='MIT',
14 | packages=['cvxpy-mip-helpers'],
15 | install_requires=[
16 | 'cvxpy',
17 | 'numpy',
18 | ],
19 | zip_safe=False)
20 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | SOURCEDIR = .
8 | BUILDDIR = _build
9 |
10 | # Put it first so that "make" without argument is like "make help".
11 | help:
12 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
13 |
14 | .PHONY: help Makefile
15 |
16 | # Catch-all target: route all unknown targets to Sphinx using the new
17 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
18 | %: Makefile
19 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
--------------------------------------------------------------------------------
/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=.
11 | set BUILDDIR=_build
12 |
13 | if "%1" == "" goto help
14 |
15 | %SPHINXBUILD% >NUL 2>NUL
16 | if errorlevel 9009 (
17 | echo.
18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19 | echo.installed, then set the SPHINXBUILD environment variable to point
20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
21 | echo.may add the Sphinx directory to PATH.
22 | echo.
23 | echo.If you don't have Sphinx installed, grab it from
24 | echo.http://sphinx-doc.org/
25 | exit /b 1
26 | )
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/examples/flappy_bird.py:
--------------------------------------------------------------------------------
1 | import cvxpy as cvx
2 | import numpy as np
3 | import matplotlib.pyplot as plt
4 |
5 | N = 50 # time steps
6 | dt = 0.1
7 | path = cvx.Variable((N, 3)) # x/y pos and vel
8 | f = cvx.Variable(N-1, boolean=True) # force
9 | vx = 1
10 | g = 9.8
11 | j = 10 # impulse factor
12 | recovery = 10
13 |
14 | # unpack variables
15 | x = path[:,0]
16 | y = path[:,1]
17 |
18 | vy = path[:,2]
19 |
20 | c = [] #constraints
21 | c += [f >= 0] # only fire rocket downward
22 | c += [x[0] == 0, vx[0] == 0, y[0] == 10, vy[0] == 0]
23 |
24 | for t in range(N-1):
25 | c += [x[t + 1] == x[t] + vx*dt ]
26 | c += [y[t + 1] == y[t] + vy[t]*dt ]
27 | c += [vy[t + 1] == vy[t] - g * dt + j * f[t] ]
28 | for t in range(N-recovery):
29 | c += [cvx.sum(f[t:t+recovery] <= 1] # not more than one impulse in recovery window. Is there a recovery window?
30 |
31 | c += [y[N-1] == 0] # landed
32 | c += [vy[N-1] == 0] # gently vx[N-1] == 0
33 |
34 |
35 | # keep position inside allowable region.
36 |
37 | objective = cvx.Minimize(cvx.sum(f)) # minimize total fuel use
38 |
39 | prob = cvx.Problem(objective, c)
40 | prob.solve(verbose = True)
41 | plt.plot(y.value, label="height")
42 | plt.plot(f.value, label="force")
43 | plt.legend()
44 | plt.title("Height vs Time")
45 | plt.show()
46 |
47 |
--------------------------------------------------------------------------------
/examples/lunar_land.py:
--------------------------------------------------------------------------------
1 | import cvxpy as cvx
2 | import numpy as np
3 | import matplotlib.pyplot as plt
4 |
5 | N = 50 # time steps
6 | dt = 0.1
7 | path = cvx.Variable((N, 4)) # x/y pos and vel
8 | f = cvx.Variable(N-1) # force
9 |
10 | # unpack variables
11 | x = path[:,0]
12 | y = path[:,1]
13 | vx = path[:,2]
14 | vy = path[:,3]
15 |
16 | c = [] #constraints
17 | c += [f >= 0] # only fire rocket downward
18 | c += [x[0] == 0, vx[0] == 0, y[0] == 10, vy[0] == 0]
19 |
20 | for t in range(N-1):
21 | c += [x[t + 1] == x[t] + vx[t]*dt ]
22 | c += [y[t + 1] == y[t] + vy[t]*dt ]
23 | c += [vx[t + 1] == vx[t]]
24 | c += [vy[t + 1] == vy[t] + (- 9.8 + f[t])*dt ]
25 |
26 | c += [y[N-1] == 0] # landed
27 | c += [vy[N-1] == 0] # gently vx[N-1] == 0
28 |
29 |
30 | objective = cvx.Minimize(cvx.sum(f)) # minimize total fuel use
31 |
32 | prob = cvx.Problem(objective, c)
33 | prob.solve(verbose = True)
34 | plt.plot(y.value, label="height")
35 | plt.plot(f.value, label="force")
36 | plt.legend()
37 | plt.title("Height vs Time")
38 | plt.show()
39 |
40 | '''
41 | 1d lunear lander
42 | 2d lunar lander - don't do rotational version.
43 |
44 | obstacle lunear lander.
45 | flappy bird mixed integer programming
46 | 0/1 with recovery window.
47 |
48 | partition into convex regions. The pipes make easy boxes though. And in fact the corners are easy also.
49 | NICE
50 |
51 |
52 |
53 |
54 | '''
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # cvxpy-mip-helpers
2 |
3 | A lightweight collection of helpful modelling functions for mixed integer programming. It is based around the cvxpy framework.
4 |
5 | The functions usually will return new variables and also new constraints to add in your constraint set. Don't forget to do that. We could (should?) automate this part by wrapping in more interface.
6 |
7 |
8 | ## Implemented
9 |
10 |
11 | ## Not implemented
12 | * Embedding logical functions
13 | * Unions of convex shapes
14 | * Sums of Squares Programming
15 | * Smart Encodings
16 | * Piecewise Linear Functions
17 | *
18 |
19 |
20 | ## Blog Posts
21 | * http://www.philipzucker.com/2d-robot-arm-inverse-kinematics-using-mixed-integer-programming-in-cvxpy/
22 | * http://www.philipzucker.com/bouncing-a-ball-with-mixed-integer-programming/
23 | * http://www.philipzucker.com/trajectory-optimization-of-a-pendulum-with-mixed-integer-linear-programming/
24 | * http://www.philipzucker.com/solving-the-ising-model-using-a-mixed-integer-linear-program-solver-gurobi/
25 | * http://www.philipzucker.com/deriving-the-chebyshev-polynomials-using-sum-of-squares-optimization-with-sympy-and-cvxpy/
26 |
27 | ## Projects of Interest
28 |
29 | * https://github.com/joehuchette/PiecewiseLinearOpt.jl
30 | * https://github.com/rdeits/ConditionalJuMP.jl
31 | * https://github.com/stephane-caron/pypoman
32 | * https://github.com/sadraddini/PWA-Control
33 | * https://github.com/sadraddini/pypolycontain
34 | * https://github.com/JuliaOpt/SumOfSquares.jl
35 | * https://github.com/rdeits/Mayday.jl
36 |
--------------------------------------------------------------------------------
/docs/conf.py:
--------------------------------------------------------------------------------
1 | # Configuration file for the Sphinx documentation builder.
2 | #
3 | # This file only contains a selection of the most common options. For a full
4 | # list see the documentation:
5 | # http://www.sphinx-doc.org/en/master/config
6 |
7 | # -- Path setup --------------------------------------------------------------
8 |
9 | # If extensions (or modules to document with autodoc) are in another directory,
10 | # add these directories to sys.path here. If the directory is relative to the
11 | # documentation root, use os.path.abspath to make it absolute, like shown here.
12 | #
13 | # import os
14 | # import sys
15 | # sys.path.insert(0, os.path.abspath('.'))
16 |
17 |
18 | # -- Project information -----------------------------------------------------
19 |
20 | project = 'cvxpy-helpers'
21 | copyright = '2019, Philip Zucker'
22 | author = 'Philip Zucker'
23 |
24 |
25 | # -- General configuration ---------------------------------------------------
26 |
27 | # Add any Sphinx extension module names here, as strings. They can be
28 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
29 | # ones.
30 | extensions = [
31 | ]
32 |
33 | # Add any paths that contain templates here, relative to this directory.
34 | templates_path = ['_templates']
35 |
36 | # List of patterns, relative to source directory, that match files and
37 | # directories to ignore when looking for source files.
38 | # This pattern also affects html_static_path and html_extra_path.
39 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
40 |
41 |
42 | # -- Options for HTML output -------------------------------------------------
43 |
44 | # The theme to use for HTML and HTML Help pages. See the documentation for
45 | # a list of builtin themes.
46 | #
47 | html_theme = 'alabaster'
48 |
49 | # Add any paths that contain custom static files (such as style sheets) here,
50 | # relative to this directory. They are copied after the builtin static files,
51 | # so a file named "default.css" will overwrite the builtin "default.css".
52 | html_static_path = ['_static']
53 |
--------------------------------------------------------------------------------
/docs/_build/html/genindex.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Index — cvxpy-helpers documentation
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 |
Index
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
86 |
87 |
88 |
96 |
97 |
98 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/examples/cheb.py:
--------------------------------------------------------------------------------
1 | from sympy import *
2 | import cvxpy as cvx
3 | import matplotlib.pyplot as plt
4 | import numpy as np
5 |
6 | #build corresponding cvx variable for sympy variable
7 | def cvxvar(expr, PSD=True):
8 | if expr.func == MatrixSymbol:
9 | i = int(expr.shape[0].evalf())
10 | j = int(expr.shape[1].evalf())
11 | return cvx.Variable((i,j), PSD=PSD)
12 | elif expr.func == Symbol:
13 | return cvx.Variable()
14 |
15 | def cvxify(expr, cvxdict): # replaces sympy variables with cvx variables
16 | return lambdify(tuple(cvxdict.keys()), expr)(*cvxdict.values())
17 |
18 |
19 | xs = np.linspace(-1,1,100)
20 |
21 | for N in range(3,6):
22 | #plot actual chebyshev
23 | chebcoeff = np.zeros(N)
24 | chebcoeff[-1] = 1
25 | plt.plot(xs, np.polynomial.chebyshev.chebval(xs, chebcoeff), color='r')
26 |
27 | cvxdict = {}
28 | # Going to need symbolic polynomials in x
29 | x = Symbol('x')
30 | xn = Matrix([x**n for n in range(N)]);
31 |
32 | def sospoly(varname):
33 | Q = MatrixSymbol(varname, N,N)
34 | p = (xn.T * Matrix(Q) * xn)[0]
35 | return p, Q
36 |
37 | t = Symbol('t')
38 | cvxdict[t] = cvxvar(t)
39 |
40 | #lagrange multiplier polynomial 1
41 | pl1, l1 = sospoly('l1')
42 | cvxdict[l1] = cvxvar(l1)
43 |
44 | #lagrange multiplier polynomial 2
45 | pl2, l2 = sospoly('l2')
46 | cvxdict[l2] = cvxvar(l2)
47 |
48 | #Equation SOS Polynomial 1
49 | peq1, eq1 = sospoly('eq1')
50 | cvxdict[eq1] = cvxvar(eq1)
51 |
52 | #Equation SOS Polynomial 2
53 | peq2, eq2 = sospoly('eq2')
54 | cvxdict[eq2] = cvxvar(eq2)
55 |
56 | a = MatrixSymbol("a", N,1)
57 | pa = Matrix(a).T*xn #sum([polcoeff[k] * x**k for k in range(n)]);
58 | pa = pa[0]
59 | cvxdict[a] = cvxvar(a, PSD=False)
60 |
61 |
62 | constraints = []
63 |
64 |
65 | # Rough Derivation for upper constraint
66 | # pol <= t
67 | # 0 <= t - pol + lam * (x+1)(x-1) # relax constraint with lambda
68 | # eq1 = t - pol + lam
69 | # 0 = t - pol + lam - eq1
70 | z1 = t - pa + pl1 * (x+1)*(x-1) - peq1
71 | z1 = Poly(z1, x).all_coeffs()
72 | constraints += [cvxify(expr, cvxdict) == 0 for expr in z1]
73 |
74 | # Derivation for lower constraint
75 | # -t <= pol
76 | # 0 <= pol + t + lam * (x+1)(x-1) # relax constraint with lambda
77 | # eq2 = pol + t + lam # eq2 is SOS
78 | # 0 = t - pol + lam - eq2 #Rearrange to equal zero.
79 | z2 = pa + t + pl2 * (x+1)*(x-1) - peq2
80 | z2 = Poly(z2, x).all_coeffs()
81 | constraints += [cvxify(expr, cvxdict) == 0 for expr in z2]
82 |
83 | constraints += [cvxdict[a][N-1,0] == 2**(N-2) ]
84 | obj = cvx.Minimize(cvxdict[t]) #minimize maximum absolute value
85 | prob = cvx.Problem(obj,constraints)
86 | prob.solve()
87 |
88 | print(cvxdict[a].value.flatten())
89 | plt.plot(xs, np.polynomial.polynomial.polyval(xs, cvxdict[a].value.flatten()), color='g')
90 |
91 |
92 | plt.show()
--------------------------------------------------------------------------------
/docs/_build/html/search.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Search — cvxpy-helpers documentation
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 |
Search
39 |
40 |
41 |
42 | Please activate JavaScript to enable the search
43 | functionality.
44 |
45 |
46 |
47 | From here you can search these documents. Enter your search
48 | words into the box below and click "search". Note that the search
49 | function will automatically search for all of the words. Pages
50 | containing fewer words won't appear in the result list.
51 |
52 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
96 |
97 |
98 |
106 |
107 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/docs/_build/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Welcome to cvxpy-helpers’s documentation! — cvxpy-helpers documentation
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 |
Welcome to cvxpy-helpers’s documentation!
35 |
36 |
37 |
38 |
39 |
Indices and tables
40 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
92 |
93 |
94 |
105 |
106 |
107 |
108 |
109 |
110 |
--------------------------------------------------------------------------------
/docs/_build/html/_static/pygments.css:
--------------------------------------------------------------------------------
1 | .highlight .hll { background-color: #ffffcc }
2 | .highlight { background: #f8f8f8; }
3 | .highlight .c { color: #8f5902; font-style: italic } /* Comment */
4 | .highlight .err { color: #a40000; border: 1px solid #ef2929 } /* Error */
5 | .highlight .g { color: #000000 } /* Generic */
6 | .highlight .k { color: #004461; font-weight: bold } /* Keyword */
7 | .highlight .l { color: #000000 } /* Literal */
8 | .highlight .n { color: #000000 } /* Name */
9 | .highlight .o { color: #582800 } /* Operator */
10 | .highlight .x { color: #000000 } /* Other */
11 | .highlight .p { color: #000000; font-weight: bold } /* Punctuation */
12 | .highlight .ch { color: #8f5902; font-style: italic } /* Comment.Hashbang */
13 | .highlight .cm { color: #8f5902; font-style: italic } /* Comment.Multiline */
14 | .highlight .cp { color: #8f5902 } /* Comment.Preproc */
15 | .highlight .cpf { color: #8f5902; font-style: italic } /* Comment.PreprocFile */
16 | .highlight .c1 { color: #8f5902; font-style: italic } /* Comment.Single */
17 | .highlight .cs { color: #8f5902; font-style: italic } /* Comment.Special */
18 | .highlight .gd { color: #a40000 } /* Generic.Deleted */
19 | .highlight .ge { color: #000000; font-style: italic } /* Generic.Emph */
20 | .highlight .gr { color: #ef2929 } /* Generic.Error */
21 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
22 | .highlight .gi { color: #00A000 } /* Generic.Inserted */
23 | .highlight .go { color: #888888 } /* Generic.Output */
24 | .highlight .gp { color: #745334 } /* Generic.Prompt */
25 | .highlight .gs { color: #000000; font-weight: bold } /* Generic.Strong */
26 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
27 | .highlight .gt { color: #a40000; font-weight: bold } /* Generic.Traceback */
28 | .highlight .kc { color: #004461; font-weight: bold } /* Keyword.Constant */
29 | .highlight .kd { color: #004461; font-weight: bold } /* Keyword.Declaration */
30 | .highlight .kn { color: #004461; font-weight: bold } /* Keyword.Namespace */
31 | .highlight .kp { color: #004461; font-weight: bold } /* Keyword.Pseudo */
32 | .highlight .kr { color: #004461; font-weight: bold } /* Keyword.Reserved */
33 | .highlight .kt { color: #004461; font-weight: bold } /* Keyword.Type */
34 | .highlight .ld { color: #000000 } /* Literal.Date */
35 | .highlight .m { color: #990000 } /* Literal.Number */
36 | .highlight .s { color: #4e9a06 } /* Literal.String */
37 | .highlight .na { color: #c4a000 } /* Name.Attribute */
38 | .highlight .nb { color: #004461 } /* Name.Builtin */
39 | .highlight .nc { color: #000000 } /* Name.Class */
40 | .highlight .no { color: #000000 } /* Name.Constant */
41 | .highlight .nd { color: #888888 } /* Name.Decorator */
42 | .highlight .ni { color: #ce5c00 } /* Name.Entity */
43 | .highlight .ne { color: #cc0000; font-weight: bold } /* Name.Exception */
44 | .highlight .nf { color: #000000 } /* Name.Function */
45 | .highlight .nl { color: #f57900 } /* Name.Label */
46 | .highlight .nn { color: #000000 } /* Name.Namespace */
47 | .highlight .nx { color: #000000 } /* Name.Other */
48 | .highlight .py { color: #000000 } /* Name.Property */
49 | .highlight .nt { color: #004461; font-weight: bold } /* Name.Tag */
50 | .highlight .nv { color: #000000 } /* Name.Variable */
51 | .highlight .ow { color: #004461; font-weight: bold } /* Operator.Word */
52 | .highlight .w { color: #f8f8f8; text-decoration: underline } /* Text.Whitespace */
53 | .highlight .mb { color: #990000 } /* Literal.Number.Bin */
54 | .highlight .mf { color: #990000 } /* Literal.Number.Float */
55 | .highlight .mh { color: #990000 } /* Literal.Number.Hex */
56 | .highlight .mi { color: #990000 } /* Literal.Number.Integer */
57 | .highlight .mo { color: #990000 } /* Literal.Number.Oct */
58 | .highlight .sa { color: #4e9a06 } /* Literal.String.Affix */
59 | .highlight .sb { color: #4e9a06 } /* Literal.String.Backtick */
60 | .highlight .sc { color: #4e9a06 } /* Literal.String.Char */
61 | .highlight .dl { color: #4e9a06 } /* Literal.String.Delimiter */
62 | .highlight .sd { color: #8f5902; font-style: italic } /* Literal.String.Doc */
63 | .highlight .s2 { color: #4e9a06 } /* Literal.String.Double */
64 | .highlight .se { color: #4e9a06 } /* Literal.String.Escape */
65 | .highlight .sh { color: #4e9a06 } /* Literal.String.Heredoc */
66 | .highlight .si { color: #4e9a06 } /* Literal.String.Interpol */
67 | .highlight .sx { color: #4e9a06 } /* Literal.String.Other */
68 | .highlight .sr { color: #4e9a06 } /* Literal.String.Regex */
69 | .highlight .s1 { color: #4e9a06 } /* Literal.String.Single */
70 | .highlight .ss { color: #4e9a06 } /* Literal.String.Symbol */
71 | .highlight .bp { color: #3465a4 } /* Name.Builtin.Pseudo */
72 | .highlight .fm { color: #000000 } /* Name.Function.Magic */
73 | .highlight .vc { color: #000000 } /* Name.Variable.Class */
74 | .highlight .vg { color: #000000 } /* Name.Variable.Global */
75 | .highlight .vi { color: #000000 } /* Name.Variable.Instance */
76 | .highlight .vm { color: #000000 } /* Name.Variable.Magic */
77 | .highlight .il { color: #990000 } /* Literal.Number.Integer.Long */
--------------------------------------------------------------------------------
/cvxpy-mip-helpers/sos.py:
--------------------------------------------------------------------------------
1 | import cvxpy as cvx
2 | from sympy import *
3 | import random
4 | '''
5 | The idea is to use raw cvxpy and sympy as much as possible for maximum flexibility.
6 |
7 | Construct a sum of sqaures polynomial using sospoly. This returns a variable dictionary mapping sympy variables to cvxpy variables.
8 | You are free to the do polynomial operations (differentiation, integration, algerba) in pure sympy
9 | When you want to express an equality constraint, use poly_eq(), which takes the vardict and returns a list of cvxpy constraints.
10 | Once the problem is solved, use poly_value to get back the solution polynomials.
11 |
12 | That some polynomial is sum of squares can be expressed as the equality with a fresh polynomial that is explicility sum of sqaures.
13 |
14 | With the approach, we get the full unbridled power of sympy (including grobner bases!)
15 |
16 | I prefer manually controlling the vardict to having it auto controlled by a class, just as a I prefer manually controlling my constraint sets
17 | Classes suck.
18 | '''
19 |
20 |
21 | def cvxify(expr, cvxdict): # replaces sympy variables with cvx variables in sympy expr
22 | return lambdify(tuple(cvxdict.keys()), expr)(*cvxdict.values())
23 |
24 | def sospoly(terms, name=None):
25 | ''' returns sum of squares polynomial using terms, and vardict mapping to cvxpy variables '''
26 | if name == None:
27 | name = str(random.getrandbits(32))
28 | N = len(terms)
29 | xn = Matrix(terms)
30 | Q = MatrixSymbol(name, N,N)
31 | p = (xn.T * Matrix(Q) * xn)[0]
32 | Qcvx = cvx.Variable((N,N), PSD=True)
33 | vardict = {Q : Qcvx}
34 | return p, vardict
35 |
36 | def polyvar(terms,name=None):
37 | ''' builds sumpy expression and vardict for an unknown linear combination of the terms '''
38 | if name == None:
39 | name = str(random.getrandbits(32))
40 | N = len(terms)
41 | xn = Matrix(terms)
42 | Q = MatrixSymbol(name, N, 1)
43 | p = (xn.T * Matrix(Q))[0]
44 | print(p)
45 | Qcvx = cvx.Variable((N,1))
46 | vardict = {Q : Qcvx}
47 | return p, vardict
48 |
49 | def poly_eq(p1, p2 , vardict):
50 | ''' returns a list of cvxpy constraints '''
51 | dp = p1 - p2
52 | polyvars = list(dp.free_symbols - set(vardict.keys()))
53 | return [ cvxify(expr, vardict) == 0 for expr in poly(dp, gens = polyvars).coeffs()]
54 |
55 | def vardict_value(vardict):
56 | ''' evaluate numerical values of vardict '''
57 | return {k : v.value for (k, v) in vardict.items()}
58 |
59 | def poly_value(p1, vardict):
60 | ''' evaluate polynomial expressions with vardict'''
61 | return cvxify(p1, vardict_value(vardict))
62 |
63 | if __name__ == "__main__":
64 | x = symbols('x')
65 | terms = [1, x, x**2]
66 | #p, cdict = polyvar(terms)
67 | p, cdict = sospoly(terms)
68 | c = poly_eq(p, (1 + x)**2 , cdict)
69 | print(c)
70 | prob = cvx.Problem(cvx.Minimize(1), c)
71 | prob.solve()
72 |
73 | print(factor(poly_value(p, cdict)))
74 |
75 | # global poly minimization
76 | vdict = {}
77 | t, d = polyvar([1], name='t')
78 | vdict.update(d)
79 |
80 | p, d = sospoly([1,x,x**2], name='p')
81 | vdict.update(d)
82 | constraints = poly_eq(7 + x**2 - t, p, vdict)
83 | obj = cvx.Maximize( cvxify(t,vdict) )
84 | prob = cvx.Problem(obj, constraints)
85 | prob.solve()
86 | print(poly_value(t,vdict))
87 |
88 |
89 | '''
90 | p, d = sospoly([1,x,x**2,x**3])
91 | cvxdict += d
92 |
93 | p, d = sospoly( [ x ** i * y ** j for i in range(3) for j in range(3)] )
94 | cvxdict += d
95 | '''
96 |
97 |
98 |
99 | '''
100 |
101 | def sospoly(terms, varname=None):
102 | N = len(terms)
103 | xn = Matrix(terms)
104 | Q = MatrixSymbol(varname, N,N)
105 | p = (xn.T * Matrix(Q) * xn)[0]
106 | Qcvx = cvx.Variable((N,N), PSD=True)
107 | vardict = {Q : Qcvx}
108 | return SOSExpr(p, vardict)
109 |
110 | # Sympy + cvxpy = SOS
111 |
112 | class SOS():
113 | def __init__(self, ):
114 | cvx.
115 |
116 | def __eq__(self, rhs):
117 | def constraints(self):
118 |
119 | def sospoly( deglist ):
120 |
121 | def sospoly(deglist):
122 | product([deg for (_,deg) in ])
123 | for (var, deg)
124 | xn = Matrix([x**n for n in range(N)]);
125 | Q = MatrixSymbol(varname, N,N)
126 | p = (xn.T * Matrix(Q) * xn)[0]
127 | return p, Q
128 |
129 | def sospoly(terms)
130 |
131 | def cvxify(expr, cvxdict): # replaces sympy variables with cvx variables
132 | return lambdify(tuple(cvxdict.keys()), expr)(*cvxdict.values())
133 | class SOSPoly():
134 | def __init__(self,terms):
135 | #N = product([deg for (_,deg) in deglist])
136 | #xn = Matrix([x**n for n in range(N)]);
137 | N = len(terms)
138 | xn = Matrix(terms)
139 | Q = MatrixSymbol(varname, N,N)
140 | self.p = (xn.T * Matrix(Q) * xn)[0]
141 | self.vardict =
142 | def __rmul__(self, rhs):
143 | self.p * rhs
144 | def __add__(self,)
145 |
146 |
147 |
148 |
149 | def liftconstpoly(p):
150 | return SOSExpr(p, {})
151 |
152 | class SOSExpr():
153 | def __init__(self, expr=0, vardict = {}):
154 | self.vardict = vardict
155 | self.sympy_expr = expr
156 | def __rmul__()
157 |
158 | def value():
159 |
160 | def cvxify(self): # replaces sympy variables with cvx variables
161 | return lambdify(tuple(self.vardict.keys()), expr)(*(self.vardict.values()))
162 |
163 |
164 | # maybe only off equality.
165 | # SOS is by setting equzl to unknown SOS poly.
166 |
167 |
168 |
169 |
170 | class SOSConstraint():
171 | def __init__(self, lhs, op, rhs):
172 | if op = "GTE":
173 | vs = getvars(lhs,rhs)
174 | sospoly()
175 |
176 | def to_cvx(self):
177 | z1 = Poly(z1, x).all_coeffs()
178 | constraints += [cvxify(expr, cvxdict) == 0 for expr in z1]
179 |
180 | '''
181 |
--------------------------------------------------------------------------------
/cvxpy-mip-helpers/mip.py:
--------------------------------------------------------------------------------
1 | import cvxpy as cvx
2 | import numpy as np
3 | import pypoman
4 |
5 | def circle(N):
6 | """Builds N sided polygon MIP approximation of circle. returns x, y, constraints"""
7 | x = cvx.Variable()
8 | y = cvx.Variable()
9 | l = cvx.Variable(N) #interpolation variables
10 | segment = cvx.Variable(N,boolean=True) #segment indicator variables, relaxing the boolean constraint gives the convex hull of the polygon
11 |
12 | angles = np.linspace(0, 2*np.pi, N, endpoint=False)
13 | xs = np.cos(angles) #we're using a VRep
14 | ys = np.sin(angles)
15 |
16 | constraints = []
17 | constraints += [x == l*xs, y == l*ys] # x and y are convex sum of the corner points
18 | constraints += [cvx.sum(l) == 1, l <= 1, 0 <= l] #interpolations variables. Between 0 and 1 and sum up to 1
19 | constraints += [cvx.sum(segment) == 1] # only one indicator variable can be nonzero
20 |
21 | constraints += [l[N-1] <= segment[N-1] + segment[0]] #special wrap around case
22 | for i in range(N-1):
23 | constraints += [l[i] <= segment[i] + segment[i+1]] # interpolation variables suppressed
24 | return x, y, constraints
25 |
26 | # one encoding for a relu
27 | # Another possible one is to use rays. lam(1,0) + (1-lam)(1,1) = (x,y)
28 | # https://arxiv.org/pdf/1711.07356.pdf
29 | def relu(x, M=100):
30 | y = cvx.Variable(x.shape)
31 | z = cvx.Variable(x.shape, boolean=True)
32 | notz = 1 - z
33 | constraints = []
34 | constraints += [y >= 0, y >= x]
35 | constraints += [x <= M * z,- M * notz <= x]
36 | constraints += [y <= M * z, y <= x + 2 * M * notz]
37 | return y, constraints
38 |
39 | def curveMIP(pts):
40 | d = pts.shape[1]
41 | N = pts.shape[0]
42 | x = cvx.Variable(d)
43 | l = cvx.Variable(N) #interpolation variables
44 | segment = cvx.Variable(N-1,boolean=True)
45 | constraints = []
46 | constraints += [x == pts.T@l]
47 | constraints += [cvx.sum(l) == 1, l <= 1, 0 <= l] #interpolations variables. Between 0 and 1 and sum up to 1
48 | constraints += [cvx.sum(segment) == 1] # only one indicator variable can be nonzero
49 |
50 | constraints += [l[0] <= segment[0]] #special cases
51 | constraints += [l[N-1] <= segment[N-2]]
52 | for i in range(1,N-1):
53 | constraints += [l[i] <= segment[i] + segment[i+1]] # interpolation variables suppressed
54 | return x, segments, constraints
55 |
56 |
57 | def functionMIP(f, xs):
58 | ''' samples f at xs (ordered array of positions) to build piecewise linear approximation. Returns a function that can be applied to cvx variables'''
59 | #fs = np.array([f(x) for pt in pts])
60 | fs = f(xs) #assume f is vectorized
61 | def g(x):
62 | fx, segs, constraints = curveMIP( np.stack(fs,pts).T)
63 | constraints += [x == fx[1]]
64 | return fx[0], constraints
65 | return g
66 |
67 | def notMIP(z):
68 | return 1 - z
69 |
70 | def tableMIP(table):
71 | """ given a table of booleans (a tabulation of a boolean function), outputs a function that uses the first element of the table as the output"""
72 | A, b = pypoman.duality.compute_polytope_halfspaces(np.array(table))
73 | A1 = A[:,1:]
74 | A2 = A[:,0]
75 | def g(a): # a? or a tuple of as?
76 | z = cvx.Variable(boolean = True) #vectorize?
77 | constraints = []
78 | constraints += [A1@a + A2*z <= b]
79 | return z, constraints
80 | return g
81 |
82 | def allBools(n):
83 | assert(n >= 0)
84 | if n == 0:
85 | return []
86 | elif n == 1:
87 | return [(0,),(1,)]
88 | else:
89 | rec = allBools(n-1)
90 | return [(0,) + bs for bs in rec] + [ (1,) + bs for bs in rec]
91 |
92 | def buildTable(f, arity=2):
93 | inputs = allBools(arity)
94 | table = [(f(*bs),) + bs for bs in inputs]
95 | return table
96 |
97 | def mipify(f, arity=2, allowExtra = False):
98 | table = buildTable(f,arity=arity)
99 | return tableMIP(table)
100 | '''
101 | def g(*args):
102 | assert(len(args) == arity)
103 | assert(args[0].shape == args[1].shape)
104 | z = cvx.Variable(args[0].shape, boolean=True)
105 | return g
106 | '''
107 |
108 |
109 |
110 | andMIP = mipify(lambda a,b: a * b)
111 | orMIP = mipify(lambda a,b: max(a, b))
112 | xorMIP = mipify(lambda a, b: int(a == b))
113 |
114 | print(buildTable(lambda a,b: a * b))
115 | print(andMIP)
116 | '''
117 |
118 |
119 | make mip pendulum using circle. Turns pendulum into a sequence of inlcined planes. Possibly a bad approximation
120 | The SHO oscillator sine apporixmation at the stable point is replaced with peicewise parabolas. you could do worse. Although.. piecewise parabolas in cartesian space?
121 |
122 | rather than circle
123 | arbitrary mipcurve
124 | mipclosedcurve
125 | mip surface - given triangualtion of surface, we can mip it
126 | delauney - simple 2d plane areas
127 | union - open union - reify the individal areas and then extrnal sum z == 1
128 | listunion
129 |
130 | functions ~ curves
131 |
132 | def suppressedPair(N):
133 | l = cvx.variable(N)
134 | z = cvx.Variable(N, boolean=True)
135 | constraints = [0 <= l, l <= z]
136 | return l, z, constraints
137 |
138 |
139 | # curve_mip is union of segments. Vrep of a segment is just 2 points.
140 |
141 |
142 | def union_of_vrep(vreps):
143 | nshapes = len(vreps)
144 | c = []
145 | indicators = cvx.Variable(nshapes, boolean=True)
146 | c += [cvx.sum(indicators) == 1] # in exactly 1
147 | xs = []
148 | for i,vrep in enumerate(vreps):
149 | (verts, d) = vrep.shape
150 | coordinates = cvx.Variables(verts)
151 | c += [coordinates >= 0, coordinates <= indicator[i]]
152 | xs.append(coordinates * vrep)
153 | x = cvx.Variable(d)
154 | c += [sum(xs) == x]
155 | return x, c
156 |
157 |
158 | #what happened to reify?
159 | # ctx is constraints built so far. We need to this to compute big M.
160 | # and really it would be nice (vital?) to turn off boolean
161 | def reify_halfplane(p, ctx):
162 | pass
163 |
164 | class PolyRel():
165 | # list of integers
166 | from : List[Int]
167 | to : List[Int]
168 | vars : List[cvx.Variables] # maybe the from to lists should just be these.
169 | constraints = List[Cvx.Expr] ?
170 |
171 | def compose(self, ):
172 | def converse(self, ):
173 | def complement(self):
174 | def __rdiv__()
175 | def __rmul__(self,r):
176 | sefl.compose(r)
177 | def union(self,r):
178 | def intersect(self,r):
179 | def query_sub(self,r):
180 | return prob
181 | def
182 |
183 |
184 | '''
--------------------------------------------------------------------------------
/docs/_build/html/_static/doctools.js:
--------------------------------------------------------------------------------
1 | /*
2 | * doctools.js
3 | * ~~~~~~~~~~~
4 | *
5 | * Sphinx JavaScript utilities for all documentation.
6 | *
7 | * :copyright: Copyright 2007-2019 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, addItems) {
70 | if (node.nodeType === 3) {
71 | var val = node.nodeValue;
72 | var pos = val.toLowerCase().indexOf(text);
73 | if (pos >= 0 &&
74 | !jQuery(node.parentNode).hasClass(className) &&
75 | !jQuery(node.parentNode).hasClass("nohighlight")) {
76 | var span;
77 | var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
78 | if (isInSVG) {
79 | span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
80 | } else {
81 | span = document.createElement("span");
82 | span.className = className;
83 | }
84 | span.appendChild(document.createTextNode(val.substr(pos, text.length)));
85 | node.parentNode.insertBefore(span, node.parentNode.insertBefore(
86 | document.createTextNode(val.substr(pos + text.length)),
87 | node.nextSibling));
88 | node.nodeValue = val.substr(0, pos);
89 | if (isInSVG) {
90 | var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
91 | var bbox = node.parentElement.getBBox();
92 | rect.x.baseVal.value = bbox.x;
93 | rect.y.baseVal.value = bbox.y;
94 | rect.width.baseVal.value = bbox.width;
95 | rect.height.baseVal.value = bbox.height;
96 | rect.setAttribute('class', className);
97 | addItems.push({
98 | "parent": node.parentNode,
99 | "target": rect});
100 | }
101 | }
102 | }
103 | else if (!jQuery(node).is("button, select, textarea")) {
104 | jQuery.each(node.childNodes, function() {
105 | highlight(this, addItems);
106 | });
107 | }
108 | }
109 | var addItems = [];
110 | var result = this.each(function() {
111 | highlight(this, addItems);
112 | });
113 | for (var i = 0; i < addItems.length; ++i) {
114 | jQuery(addItems[i].parent).before(addItems[i].target);
115 | }
116 | return result;
117 | };
118 |
119 | /*
120 | * backward compatibility for jQuery.browser
121 | * This will be supported until firefox bug is fixed.
122 | */
123 | if (!jQuery.browser) {
124 | jQuery.uaMatch = function(ua) {
125 | ua = ua.toLowerCase();
126 |
127 | var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
128 | /(webkit)[ \/]([\w.]+)/.exec(ua) ||
129 | /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
130 | /(msie) ([\w.]+)/.exec(ua) ||
131 | ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
132 | [];
133 |
134 | return {
135 | browser: match[ 1 ] || "",
136 | version: match[ 2 ] || "0"
137 | };
138 | };
139 | jQuery.browser = {};
140 | jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
141 | }
142 |
143 | /**
144 | * Small JavaScript module for the documentation.
145 | */
146 | var Documentation = {
147 |
148 | init : function() {
149 | this.fixFirefoxAnchorBug();
150 | this.highlightSearchWords();
151 | this.initIndexTable();
152 | if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) {
153 | this.initOnKeyListeners();
154 | }
155 | },
156 |
157 | /**
158 | * i18n support
159 | */
160 | TRANSLATIONS : {},
161 | PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; },
162 | LOCALE : 'unknown',
163 |
164 | // gettext and ngettext don't access this so that the functions
165 | // can safely bound to a different name (_ = Documentation.gettext)
166 | gettext : function(string) {
167 | var translated = Documentation.TRANSLATIONS[string];
168 | if (typeof translated === 'undefined')
169 | return string;
170 | return (typeof translated === 'string') ? translated : translated[0];
171 | },
172 |
173 | ngettext : function(singular, plural, n) {
174 | var translated = Documentation.TRANSLATIONS[singular];
175 | if (typeof translated === 'undefined')
176 | return (n == 1) ? singular : plural;
177 | return translated[Documentation.PLURALEXPR(n)];
178 | },
179 |
180 | addTranslations : function(catalog) {
181 | for (var key in catalog.messages)
182 | this.TRANSLATIONS[key] = catalog.messages[key];
183 | this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
184 | this.LOCALE = catalog.locale;
185 | },
186 |
187 | /**
188 | * add context elements like header anchor links
189 | */
190 | addContextElements : function() {
191 | $('div[id] > :header:first').each(function() {
192 | $('').
193 | attr('href', '#' + this.id).
194 | attr('title', _('Permalink to this headline')).
195 | appendTo(this);
196 | });
197 | $('dt[id]').each(function() {
198 | $('').
199 | attr('href', '#' + this.id).
200 | attr('title', _('Permalink to this definition')).
201 | appendTo(this);
202 | });
203 | },
204 |
205 | /**
206 | * workaround a firefox stupidity
207 | * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075
208 | */
209 | fixFirefoxAnchorBug : function() {
210 | if (document.location.hash && $.browser.mozilla)
211 | window.setTimeout(function() {
212 | document.location.href += '';
213 | }, 10);
214 | },
215 |
216 | /**
217 | * highlight the search words provided in the url in the text
218 | */
219 | highlightSearchWords : function() {
220 | var params = $.getQueryParameters();
221 | var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
222 | if (terms.length) {
223 | var body = $('div.body');
224 | if (!body.length) {
225 | body = $('body');
226 | }
227 | window.setTimeout(function() {
228 | $.each(terms, function() {
229 | body.highlightText(this.toLowerCase(), 'highlighted');
230 | });
231 | }, 10);
232 | $('' + _('Hide Search Matches') + '
')
234 | .appendTo($('#searchbox'));
235 | }
236 | },
237 |
238 | /**
239 | * init the domain index toggle buttons
240 | */
241 | initIndexTable : function() {
242 | var togglers = $('img.toggler').click(function() {
243 | var src = $(this).attr('src');
244 | var idnum = $(this).attr('id').substr(7);
245 | $('tr.cg-' + idnum).toggle();
246 | if (src.substr(-9) === 'minus.png')
247 | $(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
248 | else
249 | $(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
250 | }).css('display', '');
251 | if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
252 | togglers.click();
253 | }
254 | },
255 |
256 | /**
257 | * helper function to hide the search marks again
258 | */
259 | hideSearchWords : function() {
260 | $('#searchbox .highlight-link').fadeOut(300);
261 | $('span.highlighted').removeClass('highlighted');
262 | },
263 |
264 | /**
265 | * make the url absolute
266 | */
267 | makeURL : function(relativeURL) {
268 | return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
269 | },
270 |
271 | /**
272 | * get the current relative url
273 | */
274 | getCurrentURL : function() {
275 | var path = document.location.pathname;
276 | var parts = path.split(/\//);
277 | $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
278 | if (this === '..')
279 | parts.pop();
280 | });
281 | var url = parts.join('/');
282 | return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
283 | },
284 |
285 | initOnKeyListeners: function() {
286 | $(document).keyup(function(event) {
287 | var activeElementType = document.activeElement.tagName;
288 | // don't navigate when in search box or textarea
289 | if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') {
290 | switch (event.keyCode) {
291 | case 37: // left
292 | var prevHref = $('link[rel="prev"]').prop('href');
293 | if (prevHref) {
294 | window.location.href = prevHref;
295 | return false;
296 | }
297 | case 39: // right
298 | var nextHref = $('link[rel="next"]').prop('href');
299 | if (nextHref) {
300 | window.location.href = nextHref;
301 | return false;
302 | }
303 | }
304 | }
305 | });
306 | }
307 | };
308 |
309 | // quick alias for translations
310 | _ = Documentation.gettext;
311 |
312 | $(document).ready(function() {
313 | Documentation.init();
314 | });
315 |
--------------------------------------------------------------------------------
/docs/_build/html/_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/_build/html/_static/language_data.js:
--------------------------------------------------------------------------------
1 | /*
2 | * language_data.js
3 | * ~~~~~~~~~~~~~~~~
4 | *
5 | * This script contains the language-specific data used by searchtools.js,
6 | * namely the list of stopwords, stemmer, scorer and splitter.
7 | *
8 | * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
9 | * :license: BSD, see LICENSE for details.
10 | *
11 | */
12 |
13 | var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"];
14 |
15 |
16 | /* Non-minified version JS is _stemmer.js if file is provided */
17 | /**
18 | * Porter Stemmer
19 | */
20 | var Stemmer = function() {
21 |
22 | var step2list = {
23 | ational: 'ate',
24 | tional: 'tion',
25 | enci: 'ence',
26 | anci: 'ance',
27 | izer: 'ize',
28 | bli: 'ble',
29 | alli: 'al',
30 | entli: 'ent',
31 | eli: 'e',
32 | ousli: 'ous',
33 | ization: 'ize',
34 | ation: 'ate',
35 | ator: 'ate',
36 | alism: 'al',
37 | iveness: 'ive',
38 | fulness: 'ful',
39 | ousness: 'ous',
40 | aliti: 'al',
41 | iviti: 'ive',
42 | biliti: 'ble',
43 | logi: 'log'
44 | };
45 |
46 | var step3list = {
47 | icate: 'ic',
48 | ative: '',
49 | alize: 'al',
50 | iciti: 'ic',
51 | ical: 'ic',
52 | ful: '',
53 | ness: ''
54 | };
55 |
56 | var c = "[^aeiou]"; // consonant
57 | var v = "[aeiouy]"; // vowel
58 | var C = c + "[^aeiouy]*"; // consonant sequence
59 | var V = v + "[aeiou]*"; // vowel sequence
60 |
61 | var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0
62 | var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1
63 | var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1
64 | var s_v = "^(" + C + ")?" + v; // vowel in stem
65 |
66 | this.stemWord = function (w) {
67 | var stem;
68 | var suffix;
69 | var firstch;
70 | var origword = w;
71 |
72 | if (w.length < 3)
73 | return w;
74 |
75 | var re;
76 | var re2;
77 | var re3;
78 | var re4;
79 |
80 | firstch = w.substr(0,1);
81 | if (firstch == "y")
82 | w = firstch.toUpperCase() + w.substr(1);
83 |
84 | // Step 1a
85 | re = /^(.+?)(ss|i)es$/;
86 | re2 = /^(.+?)([^s])s$/;
87 |
88 | if (re.test(w))
89 | w = w.replace(re,"$1$2");
90 | else if (re2.test(w))
91 | w = w.replace(re2,"$1$2");
92 |
93 | // Step 1b
94 | re = /^(.+?)eed$/;
95 | re2 = /^(.+?)(ed|ing)$/;
96 | if (re.test(w)) {
97 | var fp = re.exec(w);
98 | re = new RegExp(mgr0);
99 | if (re.test(fp[1])) {
100 | re = /.$/;
101 | w = w.replace(re,"");
102 | }
103 | }
104 | else if (re2.test(w)) {
105 | var fp = re2.exec(w);
106 | stem = fp[1];
107 | re2 = new RegExp(s_v);
108 | if (re2.test(stem)) {
109 | w = stem;
110 | re2 = /(at|bl|iz)$/;
111 | re3 = new RegExp("([^aeiouylsz])\\1$");
112 | re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
113 | if (re2.test(w))
114 | w = w + "e";
115 | else if (re3.test(w)) {
116 | re = /.$/;
117 | w = w.replace(re,"");
118 | }
119 | else if (re4.test(w))
120 | w = w + "e";
121 | }
122 | }
123 |
124 | // Step 1c
125 | re = /^(.+?)y$/;
126 | if (re.test(w)) {
127 | var fp = re.exec(w);
128 | stem = fp[1];
129 | re = new RegExp(s_v);
130 | if (re.test(stem))
131 | w = stem + "i";
132 | }
133 |
134 | // Step 2
135 | re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
136 | if (re.test(w)) {
137 | var fp = re.exec(w);
138 | stem = fp[1];
139 | suffix = fp[2];
140 | re = new RegExp(mgr0);
141 | if (re.test(stem))
142 | w = stem + step2list[suffix];
143 | }
144 |
145 | // Step 3
146 | re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
147 | if (re.test(w)) {
148 | var fp = re.exec(w);
149 | stem = fp[1];
150 | suffix = fp[2];
151 | re = new RegExp(mgr0);
152 | if (re.test(stem))
153 | w = stem + step3list[suffix];
154 | }
155 |
156 | // Step 4
157 | re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
158 | re2 = /^(.+?)(s|t)(ion)$/;
159 | if (re.test(w)) {
160 | var fp = re.exec(w);
161 | stem = fp[1];
162 | re = new RegExp(mgr1);
163 | if (re.test(stem))
164 | w = stem;
165 | }
166 | else if (re2.test(w)) {
167 | var fp = re2.exec(w);
168 | stem = fp[1] + fp[2];
169 | re2 = new RegExp(mgr1);
170 | if (re2.test(stem))
171 | w = stem;
172 | }
173 |
174 | // Step 5
175 | re = /^(.+?)e$/;
176 | if (re.test(w)) {
177 | var fp = re.exec(w);
178 | stem = fp[1];
179 | re = new RegExp(mgr1);
180 | re2 = new RegExp(meq1);
181 | re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
182 | if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
183 | w = stem;
184 | }
185 | re = /ll$/;
186 | re2 = new RegExp(mgr1);
187 | if (re.test(w) && re2.test(w)) {
188 | re = /.$/;
189 | w = w.replace(re,"");
190 | }
191 |
192 | // and turn initial Y back to y
193 | if (firstch == "y")
194 | w = firstch.toLowerCase() + w.substr(1);
195 | return w;
196 | }
197 | }
198 |
199 |
200 |
201 |
202 |
203 | var splitChars = (function() {
204 | var result = {};
205 | var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648,
206 | 1748, 1809, 2416, 2473, 2481, 2526, 2601, 2609, 2612, 2615, 2653, 2702,
207 | 2706, 2729, 2737, 2740, 2857, 2865, 2868, 2910, 2928, 2948, 2961, 2971,
208 | 2973, 3085, 3089, 3113, 3124, 3213, 3217, 3241, 3252, 3295, 3341, 3345,
209 | 3369, 3506, 3516, 3633, 3715, 3721, 3736, 3744, 3748, 3750, 3756, 3761,
210 | 3781, 3912, 4239, 4347, 4681, 4695, 4697, 4745, 4785, 4799, 4801, 4823,
211 | 4881, 5760, 5901, 5997, 6313, 7405, 8024, 8026, 8028, 8030, 8117, 8125,
212 | 8133, 8181, 8468, 8485, 8487, 8489, 8494, 8527, 11311, 11359, 11687, 11695,
213 | 11703, 11711, 11719, 11727, 11735, 12448, 12539, 43010, 43014, 43019, 43587,
214 | 43696, 43713, 64286, 64297, 64311, 64317, 64319, 64322, 64325, 65141];
215 | var i, j, start, end;
216 | for (i = 0; i < singles.length; i++) {
217 | result[singles[i]] = true;
218 | }
219 | var ranges = [[0, 47], [58, 64], [91, 94], [123, 169], [171, 177], [182, 184], [706, 709],
220 | [722, 735], [741, 747], [751, 879], [888, 889], [894, 901], [1154, 1161],
221 | [1318, 1328], [1367, 1368], [1370, 1376], [1416, 1487], [1515, 1519], [1523, 1568],
222 | [1611, 1631], [1642, 1645], [1750, 1764], [1767, 1773], [1789, 1790], [1792, 1807],
223 | [1840, 1868], [1958, 1968], [1970, 1983], [2027, 2035], [2038, 2041], [2043, 2047],
224 | [2070, 2073], [2075, 2083], [2085, 2087], [2089, 2307], [2362, 2364], [2366, 2383],
225 | [2385, 2391], [2402, 2405], [2419, 2424], [2432, 2436], [2445, 2446], [2449, 2450],
226 | [2483, 2485], [2490, 2492], [2494, 2509], [2511, 2523], [2530, 2533], [2546, 2547],
227 | [2554, 2564], [2571, 2574], [2577, 2578], [2618, 2648], [2655, 2661], [2672, 2673],
228 | [2677, 2692], [2746, 2748], [2750, 2767], [2769, 2783], [2786, 2789], [2800, 2820],
229 | [2829, 2830], [2833, 2834], [2874, 2876], [2878, 2907], [2914, 2917], [2930, 2946],
230 | [2955, 2957], [2966, 2968], [2976, 2978], [2981, 2983], [2987, 2989], [3002, 3023],
231 | [3025, 3045], [3059, 3076], [3130, 3132], [3134, 3159], [3162, 3167], [3170, 3173],
232 | [3184, 3191], [3199, 3204], [3258, 3260], [3262, 3293], [3298, 3301], [3312, 3332],
233 | [3386, 3388], [3390, 3423], [3426, 3429], [3446, 3449], [3456, 3460], [3479, 3481],
234 | [3518, 3519], [3527, 3584], [3636, 3647], [3655, 3663], [3674, 3712], [3717, 3718],
235 | [3723, 3724], [3726, 3731], [3752, 3753], [3764, 3772], [3774, 3775], [3783, 3791],
236 | [3802, 3803], [3806, 3839], [3841, 3871], [3892, 3903], [3949, 3975], [3980, 4095],
237 | [4139, 4158], [4170, 4175], [4182, 4185], [4190, 4192], [4194, 4196], [4199, 4205],
238 | [4209, 4212], [4226, 4237], [4250, 4255], [4294, 4303], [4349, 4351], [4686, 4687],
239 | [4702, 4703], [4750, 4751], [4790, 4791], [4806, 4807], [4886, 4887], [4955, 4968],
240 | [4989, 4991], [5008, 5023], [5109, 5120], [5741, 5742], [5787, 5791], [5867, 5869],
241 | [5873, 5887], [5906, 5919], [5938, 5951], [5970, 5983], [6001, 6015], [6068, 6102],
242 | [6104, 6107], [6109, 6111], [6122, 6127], [6138, 6159], [6170, 6175], [6264, 6271],
243 | [6315, 6319], [6390, 6399], [6429, 6469], [6510, 6511], [6517, 6527], [6572, 6592],
244 | [6600, 6607], [6619, 6655], [6679, 6687], [6741, 6783], [6794, 6799], [6810, 6822],
245 | [6824, 6916], [6964, 6980], [6988, 6991], [7002, 7042], [7073, 7085], [7098, 7167],
246 | [7204, 7231], [7242, 7244], [7294, 7400], [7410, 7423], [7616, 7679], [7958, 7959],
247 | [7966, 7967], [8006, 8007], [8014, 8015], [8062, 8063], [8127, 8129], [8141, 8143],
248 | [8148, 8149], [8156, 8159], [8173, 8177], [8189, 8303], [8306, 8307], [8314, 8318],
249 | [8330, 8335], [8341, 8449], [8451, 8454], [8456, 8457], [8470, 8472], [8478, 8483],
250 | [8506, 8507], [8512, 8516], [8522, 8525], [8586, 9311], [9372, 9449], [9472, 10101],
251 | [10132, 11263], [11493, 11498], [11503, 11516], [11518, 11519], [11558, 11567],
252 | [11622, 11630], [11632, 11647], [11671, 11679], [11743, 11822], [11824, 12292],
253 | [12296, 12320], [12330, 12336], [12342, 12343], [12349, 12352], [12439, 12444],
254 | [12544, 12548], [12590, 12592], [12687, 12689], [12694, 12703], [12728, 12783],
255 | [12800, 12831], [12842, 12880], [12896, 12927], [12938, 12976], [12992, 13311],
256 | [19894, 19967], [40908, 40959], [42125, 42191], [42238, 42239], [42509, 42511],
257 | [42540, 42559], [42592, 42593], [42607, 42622], [42648, 42655], [42736, 42774],
258 | [42784, 42785], [42889, 42890], [42893, 43002], [43043, 43055], [43062, 43071],
259 | [43124, 43137], [43188, 43215], [43226, 43249], [43256, 43258], [43260, 43263],
260 | [43302, 43311], [43335, 43359], [43389, 43395], [43443, 43470], [43482, 43519],
261 | [43561, 43583], [43596, 43599], [43610, 43615], [43639, 43641], [43643, 43647],
262 | [43698, 43700], [43703, 43704], [43710, 43711], [43715, 43738], [43742, 43967],
263 | [44003, 44015], [44026, 44031], [55204, 55215], [55239, 55242], [55292, 55295],
264 | [57344, 63743], [64046, 64047], [64110, 64111], [64218, 64255], [64263, 64274],
265 | [64280, 64284], [64434, 64466], [64830, 64847], [64912, 64913], [64968, 65007],
266 | [65020, 65135], [65277, 65295], [65306, 65312], [65339, 65344], [65371, 65381],
267 | [65471, 65473], [65480, 65481], [65488, 65489], [65496, 65497]];
268 | for (i = 0; i < ranges.length; i++) {
269 | start = ranges[i][0];
270 | end = ranges[i][1];
271 | for (j = start; j <= end; j++) {
272 | result[j] = true;
273 | }
274 | }
275 | return result;
276 | })();
277 |
278 | function splitQuery(query) {
279 | var result = [];
280 | var start = -1;
281 | for (var i = 0; i < query.length; i++) {
282 | if (splitChars[query.charCodeAt(i)]) {
283 | if (start !== -1) {
284 | result.push(query.slice(start, i));
285 | start = -1;
286 | }
287 | } else if (start === -1) {
288 | start = i;
289 | }
290 | }
291 | if (start !== -1) {
292 | result.push(query.slice(start));
293 | }
294 | return result;
295 | }
296 |
297 |
298 |
--------------------------------------------------------------------------------
/docs/_build/html/_static/alabaster.css:
--------------------------------------------------------------------------------
1 | @import url("basic.css");
2 |
3 | /* -- page layout ----------------------------------------------------------- */
4 |
5 | body {
6 | font-family: Georgia, serif;
7 | font-size: 17px;
8 | background-color: #fff;
9 | color: #000;
10 | margin: 0;
11 | padding: 0;
12 | }
13 |
14 |
15 | div.document {
16 | width: 940px;
17 | margin: 30px auto 0 auto;
18 | }
19 |
20 | div.documentwrapper {
21 | float: left;
22 | width: 100%;
23 | }
24 |
25 | div.bodywrapper {
26 | margin: 0 0 0 220px;
27 | }
28 |
29 | div.sphinxsidebar {
30 | width: 220px;
31 | font-size: 14px;
32 | line-height: 1.5;
33 | }
34 |
35 | hr {
36 | border: 1px solid #B1B4B6;
37 | }
38 |
39 | div.body {
40 | background-color: #fff;
41 | color: #3E4349;
42 | padding: 0 30px 0 30px;
43 | }
44 |
45 | div.body > .section {
46 | text-align: left;
47 | }
48 |
49 | div.footer {
50 | width: 940px;
51 | margin: 20px auto 30px auto;
52 | font-size: 14px;
53 | color: #888;
54 | text-align: right;
55 | }
56 |
57 | div.footer a {
58 | color: #888;
59 | }
60 |
61 | p.caption {
62 | font-family: inherit;
63 | font-size: inherit;
64 | }
65 |
66 |
67 | div.relations {
68 | display: none;
69 | }
70 |
71 |
72 | div.sphinxsidebar a {
73 | color: #444;
74 | text-decoration: none;
75 | border-bottom: 1px dotted #999;
76 | }
77 |
78 | div.sphinxsidebar a:hover {
79 | border-bottom: 1px solid #999;
80 | }
81 |
82 | div.sphinxsidebarwrapper {
83 | padding: 18px 10px;
84 | }
85 |
86 | div.sphinxsidebarwrapper p.logo {
87 | padding: 0;
88 | margin: -10px 0 0 0px;
89 | text-align: center;
90 | }
91 |
92 | div.sphinxsidebarwrapper h1.logo {
93 | margin-top: -10px;
94 | text-align: center;
95 | margin-bottom: 5px;
96 | text-align: left;
97 | }
98 |
99 | div.sphinxsidebarwrapper h1.logo-name {
100 | margin-top: 0px;
101 | }
102 |
103 | div.sphinxsidebarwrapper p.blurb {
104 | margin-top: 0;
105 | font-style: normal;
106 | }
107 |
108 | div.sphinxsidebar h3,
109 | div.sphinxsidebar h4 {
110 | font-family: Georgia, serif;
111 | color: #444;
112 | font-size: 24px;
113 | font-weight: normal;
114 | margin: 0 0 5px 0;
115 | padding: 0;
116 | }
117 |
118 | div.sphinxsidebar h4 {
119 | font-size: 20px;
120 | }
121 |
122 | div.sphinxsidebar h3 a {
123 | color: #444;
124 | }
125 |
126 | div.sphinxsidebar p.logo a,
127 | div.sphinxsidebar h3 a,
128 | div.sphinxsidebar p.logo a:hover,
129 | div.sphinxsidebar h3 a:hover {
130 | border: none;
131 | }
132 |
133 | div.sphinxsidebar p {
134 | color: #555;
135 | margin: 10px 0;
136 | }
137 |
138 | div.sphinxsidebar ul {
139 | margin: 10px 0;
140 | padding: 0;
141 | color: #000;
142 | }
143 |
144 | div.sphinxsidebar ul li.toctree-l1 > a {
145 | font-size: 120%;
146 | }
147 |
148 | div.sphinxsidebar ul li.toctree-l2 > a {
149 | font-size: 110%;
150 | }
151 |
152 | div.sphinxsidebar input {
153 | border: 1px solid #CCC;
154 | font-family: Georgia, serif;
155 | font-size: 1em;
156 | }
157 |
158 | div.sphinxsidebar hr {
159 | border: none;
160 | height: 1px;
161 | color: #AAA;
162 | background: #AAA;
163 |
164 | text-align: left;
165 | margin-left: 0;
166 | width: 50%;
167 | }
168 |
169 | div.sphinxsidebar .badge {
170 | border-bottom: none;
171 | }
172 |
173 | div.sphinxsidebar .badge:hover {
174 | border-bottom: none;
175 | }
176 |
177 | /* To address an issue with donation coming after search */
178 | div.sphinxsidebar h3.donation {
179 | margin-top: 10px;
180 | }
181 |
182 | /* -- body styles ----------------------------------------------------------- */
183 |
184 | a {
185 | color: #004B6B;
186 | text-decoration: underline;
187 | }
188 |
189 | a:hover {
190 | color: #6D4100;
191 | text-decoration: underline;
192 | }
193 |
194 | div.body h1,
195 | div.body h2,
196 | div.body h3,
197 | div.body h4,
198 | div.body h5,
199 | div.body h6 {
200 | font-family: Georgia, serif;
201 | font-weight: normal;
202 | margin: 30px 0px 10px 0px;
203 | padding: 0;
204 | }
205 |
206 | div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; }
207 | div.body h2 { font-size: 180%; }
208 | div.body h3 { font-size: 150%; }
209 | div.body h4 { font-size: 130%; }
210 | div.body h5 { font-size: 100%; }
211 | div.body h6 { font-size: 100%; }
212 |
213 | a.headerlink {
214 | color: #DDD;
215 | padding: 0 4px;
216 | text-decoration: none;
217 | }
218 |
219 | a.headerlink:hover {
220 | color: #444;
221 | background: #EAEAEA;
222 | }
223 |
224 | div.body p, div.body dd, div.body li {
225 | line-height: 1.4em;
226 | }
227 |
228 | div.admonition {
229 | margin: 20px 0px;
230 | padding: 10px 30px;
231 | background-color: #EEE;
232 | border: 1px solid #CCC;
233 | }
234 |
235 | div.admonition tt.xref, div.admonition code.xref, div.admonition a tt {
236 | background-color: #FBFBFB;
237 | border-bottom: 1px solid #fafafa;
238 | }
239 |
240 | div.admonition p.admonition-title {
241 | font-family: Georgia, serif;
242 | font-weight: normal;
243 | font-size: 24px;
244 | margin: 0 0 10px 0;
245 | padding: 0;
246 | line-height: 1;
247 | }
248 |
249 | div.admonition p.last {
250 | margin-bottom: 0;
251 | }
252 |
253 | div.highlight {
254 | background-color: #fff;
255 | }
256 |
257 | dt:target, .highlight {
258 | background: #FAF3E8;
259 | }
260 |
261 | div.warning {
262 | background-color: #FCC;
263 | border: 1px solid #FAA;
264 | }
265 |
266 | div.danger {
267 | background-color: #FCC;
268 | border: 1px solid #FAA;
269 | -moz-box-shadow: 2px 2px 4px #D52C2C;
270 | -webkit-box-shadow: 2px 2px 4px #D52C2C;
271 | box-shadow: 2px 2px 4px #D52C2C;
272 | }
273 |
274 | div.error {
275 | background-color: #FCC;
276 | border: 1px solid #FAA;
277 | -moz-box-shadow: 2px 2px 4px #D52C2C;
278 | -webkit-box-shadow: 2px 2px 4px #D52C2C;
279 | box-shadow: 2px 2px 4px #D52C2C;
280 | }
281 |
282 | div.caution {
283 | background-color: #FCC;
284 | border: 1px solid #FAA;
285 | }
286 |
287 | div.attention {
288 | background-color: #FCC;
289 | border: 1px solid #FAA;
290 | }
291 |
292 | div.important {
293 | background-color: #EEE;
294 | border: 1px solid #CCC;
295 | }
296 |
297 | div.note {
298 | background-color: #EEE;
299 | border: 1px solid #CCC;
300 | }
301 |
302 | div.tip {
303 | background-color: #EEE;
304 | border: 1px solid #CCC;
305 | }
306 |
307 | div.hint {
308 | background-color: #EEE;
309 | border: 1px solid #CCC;
310 | }
311 |
312 | div.seealso {
313 | background-color: #EEE;
314 | border: 1px solid #CCC;
315 | }
316 |
317 | div.topic {
318 | background-color: #EEE;
319 | }
320 |
321 | p.admonition-title {
322 | display: inline;
323 | }
324 |
325 | p.admonition-title:after {
326 | content: ":";
327 | }
328 |
329 | pre, tt, code {
330 | font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
331 | font-size: 0.9em;
332 | }
333 |
334 | .hll {
335 | background-color: #FFC;
336 | margin: 0 -12px;
337 | padding: 0 12px;
338 | display: block;
339 | }
340 |
341 | img.screenshot {
342 | }
343 |
344 | tt.descname, tt.descclassname, code.descname, code.descclassname {
345 | font-size: 0.95em;
346 | }
347 |
348 | tt.descname, code.descname {
349 | padding-right: 0.08em;
350 | }
351 |
352 | img.screenshot {
353 | -moz-box-shadow: 2px 2px 4px #EEE;
354 | -webkit-box-shadow: 2px 2px 4px #EEE;
355 | box-shadow: 2px 2px 4px #EEE;
356 | }
357 |
358 | table.docutils {
359 | border: 1px solid #888;
360 | -moz-box-shadow: 2px 2px 4px #EEE;
361 | -webkit-box-shadow: 2px 2px 4px #EEE;
362 | box-shadow: 2px 2px 4px #EEE;
363 | }
364 |
365 | table.docutils td, table.docutils th {
366 | border: 1px solid #888;
367 | padding: 0.25em 0.7em;
368 | }
369 |
370 | table.field-list, table.footnote {
371 | border: none;
372 | -moz-box-shadow: none;
373 | -webkit-box-shadow: none;
374 | box-shadow: none;
375 | }
376 |
377 | table.footnote {
378 | margin: 15px 0;
379 | width: 100%;
380 | border: 1px solid #EEE;
381 | background: #FDFDFD;
382 | font-size: 0.9em;
383 | }
384 |
385 | table.footnote + table.footnote {
386 | margin-top: -15px;
387 | border-top: none;
388 | }
389 |
390 | table.field-list th {
391 | padding: 0 0.8em 0 0;
392 | }
393 |
394 | table.field-list td {
395 | padding: 0;
396 | }
397 |
398 | table.field-list p {
399 | margin-bottom: 0.8em;
400 | }
401 |
402 | /* Cloned from
403 | * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68
404 | */
405 | .field-name {
406 | -moz-hyphens: manual;
407 | -ms-hyphens: manual;
408 | -webkit-hyphens: manual;
409 | hyphens: manual;
410 | }
411 |
412 | table.footnote td.label {
413 | width: .1px;
414 | padding: 0.3em 0 0.3em 0.5em;
415 | }
416 |
417 | table.footnote td {
418 | padding: 0.3em 0.5em;
419 | }
420 |
421 | dl {
422 | margin: 0;
423 | padding: 0;
424 | }
425 |
426 | dl dd {
427 | margin-left: 30px;
428 | }
429 |
430 | blockquote {
431 | margin: 0 0 0 30px;
432 | padding: 0;
433 | }
434 |
435 | ul, ol {
436 | /* Matches the 30px from the narrow-screen "li > ul" selector below */
437 | margin: 10px 0 10px 30px;
438 | padding: 0;
439 | }
440 |
441 | pre {
442 | background: #EEE;
443 | padding: 7px 30px;
444 | margin: 15px 0px;
445 | line-height: 1.3em;
446 | }
447 |
448 | div.viewcode-block:target {
449 | background: #ffd;
450 | }
451 |
452 | dl pre, blockquote pre, li pre {
453 | margin-left: 0;
454 | padding-left: 30px;
455 | }
456 |
457 | tt, code {
458 | background-color: #ecf0f3;
459 | color: #222;
460 | /* padding: 1px 2px; */
461 | }
462 |
463 | tt.xref, code.xref, a tt {
464 | background-color: #FBFBFB;
465 | border-bottom: 1px solid #fff;
466 | }
467 |
468 | a.reference {
469 | text-decoration: none;
470 | border-bottom: 1px dotted #004B6B;
471 | }
472 |
473 | /* Don't put an underline on images */
474 | a.image-reference, a.image-reference:hover {
475 | border-bottom: none;
476 | }
477 |
478 | a.reference:hover {
479 | border-bottom: 1px solid #6D4100;
480 | }
481 |
482 | a.footnote-reference {
483 | text-decoration: none;
484 | font-size: 0.7em;
485 | vertical-align: top;
486 | border-bottom: 1px dotted #004B6B;
487 | }
488 |
489 | a.footnote-reference:hover {
490 | border-bottom: 1px solid #6D4100;
491 | }
492 |
493 | a:hover tt, a:hover code {
494 | background: #EEE;
495 | }
496 |
497 |
498 | @media screen and (max-width: 870px) {
499 |
500 | div.sphinxsidebar {
501 | display: none;
502 | }
503 |
504 | div.document {
505 | width: 100%;
506 |
507 | }
508 |
509 | div.documentwrapper {
510 | margin-left: 0;
511 | margin-top: 0;
512 | margin-right: 0;
513 | margin-bottom: 0;
514 | }
515 |
516 | div.bodywrapper {
517 | margin-top: 0;
518 | margin-right: 0;
519 | margin-bottom: 0;
520 | margin-left: 0;
521 | }
522 |
523 | ul {
524 | margin-left: 0;
525 | }
526 |
527 | li > ul {
528 | /* Matches the 30px from the "ul, ol" selector above */
529 | margin-left: 30px;
530 | }
531 |
532 | .document {
533 | width: auto;
534 | }
535 |
536 | .footer {
537 | width: auto;
538 | }
539 |
540 | .bodywrapper {
541 | margin: 0;
542 | }
543 |
544 | .footer {
545 | width: auto;
546 | }
547 |
548 | .github {
549 | display: none;
550 | }
551 |
552 |
553 |
554 | }
555 |
556 |
557 |
558 | @media screen and (max-width: 875px) {
559 |
560 | body {
561 | margin: 0;
562 | padding: 20px 30px;
563 | }
564 |
565 | div.documentwrapper {
566 | float: none;
567 | background: #fff;
568 | }
569 |
570 | div.sphinxsidebar {
571 | display: block;
572 | float: none;
573 | width: 102.5%;
574 | margin: 50px -30px -20px -30px;
575 | padding: 10px 20px;
576 | background: #333;
577 | color: #FFF;
578 | }
579 |
580 | div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p,
581 | div.sphinxsidebar h3 a {
582 | color: #fff;
583 | }
584 |
585 | div.sphinxsidebar a {
586 | color: #AAA;
587 | }
588 |
589 | div.sphinxsidebar p.logo {
590 | display: none;
591 | }
592 |
593 | div.document {
594 | width: 100%;
595 | margin: 0;
596 | }
597 |
598 | div.footer {
599 | display: none;
600 | }
601 |
602 | div.bodywrapper {
603 | margin: 0;
604 | }
605 |
606 | div.body {
607 | min-height: 0;
608 | padding: 0;
609 | }
610 |
611 | .rtd_doc_footer {
612 | display: none;
613 | }
614 |
615 | .document {
616 | width: auto;
617 | }
618 |
619 | .footer {
620 | width: auto;
621 | }
622 |
623 | .footer {
624 | width: auto;
625 | }
626 |
627 | .github {
628 | display: none;
629 | }
630 | }
631 |
632 |
633 | /* misc. */
634 |
635 | .revsys-inline {
636 | display: none!important;
637 | }
638 |
639 | /* Make nested-list/multi-paragraph items look better in Releases changelog
640 | * pages. Without this, docutils' magical list fuckery causes inconsistent
641 | * formatting between different release sub-lists.
642 | */
643 | div#changelog > div.section > ul > li > p:only-child {
644 | margin-bottom: 0;
645 | }
646 |
647 | /* Hide fugly table cell borders in ..bibliography:: directive output */
648 | table.docutils.citation, table.docutils.citation td, table.docutils.citation th {
649 | border: none;
650 | /* Below needed in some edge cases; if not applied, bottom shadows appear */
651 | -moz-box-shadow: none;
652 | -webkit-box-shadow: none;
653 | box-shadow: none;
654 | }
655 |
656 |
657 | /* relbar */
658 |
659 | .related {
660 | line-height: 30px;
661 | width: 100%;
662 | font-size: 0.9rem;
663 | }
664 |
665 | .related.top {
666 | border-bottom: 1px solid #EEE;
667 | margin-bottom: 20px;
668 | }
669 |
670 | .related.bottom {
671 | border-top: 1px solid #EEE;
672 | }
673 |
674 | .related ul {
675 | padding: 0;
676 | margin: 0;
677 | list-style: none;
678 | }
679 |
680 | .related li {
681 | display: inline;
682 | }
683 |
684 | nav#rellinks {
685 | float: right;
686 | }
687 |
688 | nav#rellinks li+li:before {
689 | content: "|";
690 | }
691 |
692 | nav#breadcrumbs li+li:before {
693 | content: "\00BB";
694 | }
695 |
696 | /* Hide certain items when printing */
697 | @media print {
698 | div.related {
699 | display: none;
700 | }
701 | }
--------------------------------------------------------------------------------
/docs/_build/html/_static/basic.css:
--------------------------------------------------------------------------------
1 | /*
2 | * basic.css
3 | * ~~~~~~~~~
4 | *
5 | * Sphinx stylesheet -- basic theme.
6 | *
7 | * :copyright: Copyright 2007-2019 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 form.search {
85 | overflow: hidden;
86 | }
87 |
88 | div.sphinxsidebar #searchbox input[type="text"] {
89 | float: left;
90 | width: 80%;
91 | padding: 0.25em;
92 | box-sizing: border-box;
93 | }
94 |
95 | div.sphinxsidebar #searchbox input[type="submit"] {
96 | float: left;
97 | width: 20%;
98 | border-left: none;
99 | padding: 0.25em;
100 | box-sizing: border-box;
101 | }
102 |
103 |
104 | img {
105 | border: 0;
106 | max-width: 100%;
107 | }
108 |
109 | /* -- search page ----------------------------------------------------------- */
110 |
111 | ul.search {
112 | margin: 10px 0 0 20px;
113 | padding: 0;
114 | }
115 |
116 | ul.search li {
117 | padding: 5px 0 5px 20px;
118 | background-image: url(file.png);
119 | background-repeat: no-repeat;
120 | background-position: 0 7px;
121 | }
122 |
123 | ul.search li a {
124 | font-weight: bold;
125 | }
126 |
127 | ul.search li div.context {
128 | color: #888;
129 | margin: 2px 0 0 30px;
130 | text-align: left;
131 | }
132 |
133 | ul.keywordmatches li.goodmatch a {
134 | font-weight: bold;
135 | }
136 |
137 | /* -- index page ------------------------------------------------------------ */
138 |
139 | table.contentstable {
140 | width: 90%;
141 | margin-left: auto;
142 | margin-right: auto;
143 | }
144 |
145 | table.contentstable p.biglink {
146 | line-height: 150%;
147 | }
148 |
149 | a.biglink {
150 | font-size: 1.3em;
151 | }
152 |
153 | span.linkdescr {
154 | font-style: italic;
155 | padding-top: 5px;
156 | font-size: 90%;
157 | }
158 |
159 | /* -- general index --------------------------------------------------------- */
160 |
161 | table.indextable {
162 | width: 100%;
163 | }
164 |
165 | table.indextable td {
166 | text-align: left;
167 | vertical-align: top;
168 | }
169 |
170 | table.indextable ul {
171 | margin-top: 0;
172 | margin-bottom: 0;
173 | list-style-type: none;
174 | }
175 |
176 | table.indextable > tbody > tr > td > ul {
177 | padding-left: 0em;
178 | }
179 |
180 | table.indextable tr.pcap {
181 | height: 10px;
182 | }
183 |
184 | table.indextable tr.cap {
185 | margin-top: 10px;
186 | background-color: #f2f2f2;
187 | }
188 |
189 | img.toggler {
190 | margin-right: 3px;
191 | margin-top: 3px;
192 | cursor: pointer;
193 | }
194 |
195 | div.modindex-jumpbox {
196 | border-top: 1px solid #ddd;
197 | border-bottom: 1px solid #ddd;
198 | margin: 1em 0 1em 0;
199 | padding: 0.4em;
200 | }
201 |
202 | div.genindex-jumpbox {
203 | border-top: 1px solid #ddd;
204 | border-bottom: 1px solid #ddd;
205 | margin: 1em 0 1em 0;
206 | padding: 0.4em;
207 | }
208 |
209 | /* -- domain module index --------------------------------------------------- */
210 |
211 | table.modindextable td {
212 | padding: 2px;
213 | border-collapse: collapse;
214 | }
215 |
216 | /* -- general body styles --------------------------------------------------- */
217 |
218 | div.body {
219 | min-width: 450px;
220 | max-width: 800px;
221 | }
222 |
223 | div.body p, div.body dd, div.body li, div.body blockquote {
224 | -moz-hyphens: auto;
225 | -ms-hyphens: auto;
226 | -webkit-hyphens: auto;
227 | hyphens: auto;
228 | }
229 |
230 | a.headerlink {
231 | visibility: hidden;
232 | }
233 |
234 | a.brackets:before,
235 | span.brackets > a:before{
236 | content: "[";
237 | }
238 |
239 | a.brackets:after,
240 | span.brackets > a:after {
241 | content: "]";
242 | }
243 |
244 | h1:hover > a.headerlink,
245 | h2:hover > a.headerlink,
246 | h3:hover > a.headerlink,
247 | h4:hover > a.headerlink,
248 | h5:hover > a.headerlink,
249 | h6:hover > a.headerlink,
250 | dt:hover > a.headerlink,
251 | caption:hover > a.headerlink,
252 | p.caption:hover > a.headerlink,
253 | div.code-block-caption:hover > a.headerlink {
254 | visibility: visible;
255 | }
256 |
257 | div.body p.caption {
258 | text-align: inherit;
259 | }
260 |
261 | div.body td {
262 | text-align: left;
263 | }
264 |
265 | .first {
266 | margin-top: 0 !important;
267 | }
268 |
269 | p.rubric {
270 | margin-top: 30px;
271 | font-weight: bold;
272 | }
273 |
274 | img.align-left, .figure.align-left, object.align-left {
275 | clear: left;
276 | float: left;
277 | margin-right: 1em;
278 | }
279 |
280 | img.align-right, .figure.align-right, object.align-right {
281 | clear: right;
282 | float: right;
283 | margin-left: 1em;
284 | }
285 |
286 | img.align-center, .figure.align-center, object.align-center {
287 | display: block;
288 | margin-left: auto;
289 | margin-right: auto;
290 | }
291 |
292 | .align-left {
293 | text-align: left;
294 | }
295 |
296 | .align-center {
297 | text-align: center;
298 | }
299 |
300 | .align-right {
301 | text-align: right;
302 | }
303 |
304 | /* -- sidebars -------------------------------------------------------------- */
305 |
306 | div.sidebar {
307 | margin: 0 0 0.5em 1em;
308 | border: 1px solid #ddb;
309 | padding: 7px 7px 0 7px;
310 | background-color: #ffe;
311 | width: 40%;
312 | float: right;
313 | }
314 |
315 | p.sidebar-title {
316 | font-weight: bold;
317 | }
318 |
319 | /* -- topics ---------------------------------------------------------------- */
320 |
321 | div.topic {
322 | border: 1px solid #ccc;
323 | padding: 7px 7px 0 7px;
324 | margin: 10px 0 10px 0;
325 | }
326 |
327 | p.topic-title {
328 | font-size: 1.1em;
329 | font-weight: bold;
330 | margin-top: 10px;
331 | }
332 |
333 | /* -- admonitions ----------------------------------------------------------- */
334 |
335 | div.admonition {
336 | margin-top: 10px;
337 | margin-bottom: 10px;
338 | padding: 7px;
339 | }
340 |
341 | div.admonition dt {
342 | font-weight: bold;
343 | }
344 |
345 | div.admonition dl {
346 | margin-bottom: 0;
347 | }
348 |
349 | p.admonition-title {
350 | margin: 0px 10px 5px 0px;
351 | font-weight: bold;
352 | }
353 |
354 | div.body p.centered {
355 | text-align: center;
356 | margin-top: 25px;
357 | }
358 |
359 | /* -- tables ---------------------------------------------------------------- */
360 |
361 | table.docutils {
362 | border: 0;
363 | border-collapse: collapse;
364 | }
365 |
366 | table.align-center {
367 | margin-left: auto;
368 | margin-right: auto;
369 | }
370 |
371 | table caption span.caption-number {
372 | font-style: italic;
373 | }
374 |
375 | table caption span.caption-text {
376 | }
377 |
378 | table.docutils td, table.docutils th {
379 | padding: 1px 8px 1px 5px;
380 | border-top: 0;
381 | border-left: 0;
382 | border-right: 0;
383 | border-bottom: 1px solid #aaa;
384 | }
385 |
386 | table.footnote td, table.footnote th {
387 | border: 0 !important;
388 | }
389 |
390 | th {
391 | text-align: left;
392 | padding-right: 5px;
393 | }
394 |
395 | table.citation {
396 | border-left: solid 1px gray;
397 | margin-left: 1px;
398 | }
399 |
400 | table.citation td {
401 | border-bottom: none;
402 | }
403 |
404 | th > p:first-child,
405 | td > p:first-child {
406 | margin-top: 0px;
407 | }
408 |
409 | th > p:last-child,
410 | td > p:last-child {
411 | margin-bottom: 0px;
412 | }
413 |
414 | /* -- figures --------------------------------------------------------------- */
415 |
416 | div.figure {
417 | margin: 0.5em;
418 | padding: 0.5em;
419 | }
420 |
421 | div.figure p.caption {
422 | padding: 0.3em;
423 | }
424 |
425 | div.figure p.caption span.caption-number {
426 | font-style: italic;
427 | }
428 |
429 | div.figure p.caption span.caption-text {
430 | }
431 |
432 | /* -- field list styles ----------------------------------------------------- */
433 |
434 | table.field-list td, table.field-list th {
435 | border: 0 !important;
436 | }
437 |
438 | .field-list ul {
439 | margin: 0;
440 | padding-left: 1em;
441 | }
442 |
443 | .field-list p {
444 | margin: 0;
445 | }
446 |
447 | .field-name {
448 | -moz-hyphens: manual;
449 | -ms-hyphens: manual;
450 | -webkit-hyphens: manual;
451 | hyphens: manual;
452 | }
453 |
454 | /* -- hlist styles ---------------------------------------------------------- */
455 |
456 | table.hlist td {
457 | vertical-align: top;
458 | }
459 |
460 |
461 | /* -- other body styles ----------------------------------------------------- */
462 |
463 | ol.arabic {
464 | list-style: decimal;
465 | }
466 |
467 | ol.loweralpha {
468 | list-style: lower-alpha;
469 | }
470 |
471 | ol.upperalpha {
472 | list-style: upper-alpha;
473 | }
474 |
475 | ol.lowerroman {
476 | list-style: lower-roman;
477 | }
478 |
479 | ol.upperroman {
480 | list-style: upper-roman;
481 | }
482 |
483 | li > p:first-child {
484 | margin-top: 0px;
485 | }
486 |
487 | li > p:last-child {
488 | margin-bottom: 0px;
489 | }
490 |
491 | dl.footnote > dt,
492 | dl.citation > dt {
493 | float: left;
494 | }
495 |
496 | dl.footnote > dd,
497 | dl.citation > dd {
498 | margin-bottom: 0em;
499 | }
500 |
501 | dl.footnote > dd:after,
502 | dl.citation > dd:after {
503 | content: "";
504 | clear: both;
505 | }
506 |
507 | dl.field-list {
508 | display: flex;
509 | flex-wrap: wrap;
510 | }
511 |
512 | dl.field-list > dt {
513 | flex-basis: 20%;
514 | font-weight: bold;
515 | word-break: break-word;
516 | }
517 |
518 | dl.field-list > dt:after {
519 | content: ":";
520 | }
521 |
522 | dl.field-list > dd {
523 | flex-basis: 70%;
524 | padding-left: 1em;
525 | margin-left: 0em;
526 | margin-bottom: 0em;
527 | }
528 |
529 | dl {
530 | margin-bottom: 15px;
531 | }
532 |
533 | dd > p:first-child {
534 | margin-top: 0px;
535 | }
536 |
537 | dd ul, dd table {
538 | margin-bottom: 10px;
539 | }
540 |
541 | dd {
542 | margin-top: 3px;
543 | margin-bottom: 10px;
544 | margin-left: 30px;
545 | }
546 |
547 | dt:target, span.highlighted {
548 | background-color: #fbe54e;
549 | }
550 |
551 | rect.highlighted {
552 | fill: #fbe54e;
553 | }
554 |
555 | dl.glossary dt {
556 | font-weight: bold;
557 | font-size: 1.1em;
558 | }
559 |
560 | .optional {
561 | font-size: 1.3em;
562 | }
563 |
564 | .sig-paren {
565 | font-size: larger;
566 | }
567 |
568 | .versionmodified {
569 | font-style: italic;
570 | }
571 |
572 | .system-message {
573 | background-color: #fda;
574 | padding: 5px;
575 | border: 3px solid red;
576 | }
577 |
578 | .footnote:target {
579 | background-color: #ffa;
580 | }
581 |
582 | .line-block {
583 | display: block;
584 | margin-top: 1em;
585 | margin-bottom: 1em;
586 | }
587 |
588 | .line-block .line-block {
589 | margin-top: 0;
590 | margin-bottom: 0;
591 | margin-left: 1.5em;
592 | }
593 |
594 | .guilabel, .menuselection {
595 | font-family: sans-serif;
596 | }
597 |
598 | .accelerator {
599 | text-decoration: underline;
600 | }
601 |
602 | .classifier {
603 | font-style: oblique;
604 | }
605 |
606 | .classifier:before {
607 | font-style: normal;
608 | margin: 0.5em;
609 | content: ":";
610 | }
611 |
612 | abbr, acronym {
613 | border-bottom: dotted 1px;
614 | cursor: help;
615 | }
616 |
617 | /* -- code displays --------------------------------------------------------- */
618 |
619 | pre {
620 | overflow: auto;
621 | overflow-y: hidden; /* fixes display issues on Chrome browsers */
622 | }
623 |
624 | span.pre {
625 | -moz-hyphens: none;
626 | -ms-hyphens: none;
627 | -webkit-hyphens: none;
628 | hyphens: none;
629 | }
630 |
631 | td.linenos pre {
632 | padding: 5px 0px;
633 | border: 0;
634 | background-color: transparent;
635 | color: #aaa;
636 | }
637 |
638 | table.highlighttable {
639 | margin-left: 0.5em;
640 | }
641 |
642 | table.highlighttable td {
643 | padding: 0 0.5em 0 0.5em;
644 | }
645 |
646 | div.code-block-caption {
647 | padding: 2px 5px;
648 | font-size: small;
649 | }
650 |
651 | div.code-block-caption code {
652 | background-color: transparent;
653 | }
654 |
655 | div.code-block-caption + div > div.highlight > pre {
656 | margin-top: 0;
657 | }
658 |
659 | div.code-block-caption span.caption-number {
660 | padding: 0.1em 0.3em;
661 | font-style: italic;
662 | }
663 |
664 | div.code-block-caption span.caption-text {
665 | }
666 |
667 | div.literal-block-wrapper {
668 | padding: 1em 1em 0;
669 | }
670 |
671 | div.literal-block-wrapper div.highlight {
672 | margin: 0;
673 | }
674 |
675 | code.descname {
676 | background-color: transparent;
677 | font-weight: bold;
678 | font-size: 1.2em;
679 | }
680 |
681 | code.descclassname {
682 | background-color: transparent;
683 | }
684 |
685 | code.xref, a code {
686 | background-color: transparent;
687 | font-weight: bold;
688 | }
689 |
690 | h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
691 | background-color: transparent;
692 | }
693 |
694 | .viewcode-link {
695 | float: right;
696 | }
697 |
698 | .viewcode-back {
699 | float: right;
700 | font-family: sans-serif;
701 | }
702 |
703 | div.viewcode-block:target {
704 | margin: -1px -10px;
705 | padding: 0 10px;
706 | }
707 |
708 | /* -- math display ---------------------------------------------------------- */
709 |
710 | img.math {
711 | vertical-align: middle;
712 | }
713 |
714 | div.body div.math p {
715 | text-align: center;
716 | }
717 |
718 | span.eqno {
719 | float: right;
720 | }
721 |
722 | span.eqno a.headerlink {
723 | position: relative;
724 | left: 0px;
725 | z-index: 1;
726 | }
727 |
728 | div.math:hover a.headerlink {
729 | visibility: visible;
730 | }
731 |
732 | /* -- printout stylesheet --------------------------------------------------- */
733 |
734 | @media print {
735 | div.document,
736 | div.documentwrapper,
737 | div.bodywrapper {
738 | margin: 0 !important;
739 | width: 100%;
740 | }
741 |
742 | div.sphinxsidebar,
743 | div.related,
744 | div.footer,
745 | #top-link {
746 | display: none;
747 | }
748 | }
--------------------------------------------------------------------------------
/docs/_build/html/_static/searchtools.js:
--------------------------------------------------------------------------------
1 | /*
2 | * searchtools.js
3 | * ~~~~~~~~~~~~~~~~
4 | *
5 | * Sphinx JavaScript utilities for the full-text search.
6 | *
7 | * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
8 | * :license: BSD, see LICENSE for details.
9 | *
10 | */
11 |
12 | if (!Scorer) {
13 | /**
14 | * Simple result scoring code.
15 | */
16 | var Scorer = {
17 | // Implement the following function to further tweak the score for each result
18 | // The function takes a result array [filename, title, anchor, descr, score]
19 | // and returns the new score.
20 | /*
21 | score: function(result) {
22 | return result[4];
23 | },
24 | */
25 |
26 | // query matches the full name of an object
27 | objNameMatch: 11,
28 | // or matches in the last dotted part of the object name
29 | objPartialMatch: 6,
30 | // Additive scores depending on the priority of the object
31 | objPrio: {0: 15, // used to be importantResults
32 | 1: 5, // used to be objectResults
33 | 2: -5}, // used to be unimportantResults
34 | // Used when the priority is not in the mapping.
35 | objPrioDefault: 0,
36 |
37 | // query found in title
38 | title: 15,
39 | partialTitle: 7,
40 | // query found in terms
41 | term: 5,
42 | partialTerm: 2
43 | };
44 | }
45 |
46 | if (!splitQuery) {
47 | function splitQuery(query) {
48 | return query.split(/\s+/);
49 | }
50 | }
51 |
52 | /**
53 | * Search Module
54 | */
55 | var Search = {
56 |
57 | _index : null,
58 | _queued_query : null,
59 | _pulse_status : -1,
60 |
61 | htmlToText : function(htmlString) {
62 | var htmlElement = document.createElement('span');
63 | htmlElement.innerHTML = htmlString;
64 | $(htmlElement).find('.headerlink').remove();
65 | docContent = $(htmlElement).find('[role=main]')[0];
66 | return docContent.textContent || docContent.innerText;
67 | },
68 |
69 | init : function() {
70 | var params = $.getQueryParameters();
71 | if (params.q) {
72 | var query = params.q[0];
73 | $('input[name="q"]')[0].value = query;
74 | this.performSearch(query);
75 | }
76 | },
77 |
78 | loadIndex : function(url) {
79 | $.ajax({type: "GET", url: url, data: null,
80 | dataType: "script", cache: true,
81 | complete: function(jqxhr, textstatus) {
82 | if (textstatus != "success") {
83 | document.getElementById("searchindexloader").src = url;
84 | }
85 | }});
86 | },
87 |
88 | setIndex : function(index) {
89 | var q;
90 | this._index = index;
91 | if ((q = this._queued_query) !== null) {
92 | this._queued_query = null;
93 | Search.query(q);
94 | }
95 | },
96 |
97 | hasIndex : function() {
98 | return this._index !== null;
99 | },
100 |
101 | deferQuery : function(query) {
102 | this._queued_query = query;
103 | },
104 |
105 | stopPulse : function() {
106 | this._pulse_status = 0;
107 | },
108 |
109 | startPulse : function() {
110 | if (this._pulse_status >= 0)
111 | return;
112 | function pulse() {
113 | var i;
114 | Search._pulse_status = (Search._pulse_status + 1) % 4;
115 | var dotString = '';
116 | for (i = 0; i < Search._pulse_status; i++)
117 | dotString += '.';
118 | Search.dots.text(dotString);
119 | if (Search._pulse_status > -1)
120 | window.setTimeout(pulse, 500);
121 | }
122 | pulse();
123 | },
124 |
125 | /**
126 | * perform a search for something (or wait until index is loaded)
127 | */
128 | performSearch : function(query) {
129 | // create the required interface elements
130 | this.out = $('#search-results');
131 | this.title = $('' + _('Searching') + ' ').appendTo(this.out);
132 | this.dots = $(' ').appendTo(this.title);
133 | this.status = $('
').appendTo(this.out);
134 | this.output = $('').appendTo(this.out);
135 |
136 | $('#search-progress').text(_('Preparing search...'));
137 | this.startPulse();
138 |
139 | // index already loaded, the browser was quick!
140 | if (this.hasIndex())
141 | this.query(query);
142 | else
143 | this.deferQuery(query);
144 | },
145 |
146 | /**
147 | * execute search (requires search index to be loaded)
148 | */
149 | query : function(query) {
150 | var i;
151 |
152 | // stem the searchterms and add them to the correct list
153 | var stemmer = new Stemmer();
154 | var searchterms = [];
155 | var excluded = [];
156 | var hlterms = [];
157 | var tmp = splitQuery(query);
158 | var objectterms = [];
159 | for (i = 0; i < tmp.length; i++) {
160 | if (tmp[i] !== "") {
161 | objectterms.push(tmp[i].toLowerCase());
162 | }
163 |
164 | if ($u.indexOf(stopwords, tmp[i].toLowerCase()) != -1 || tmp[i].match(/^\d+$/) ||
165 | tmp[i] === "") {
166 | // skip this "word"
167 | continue;
168 | }
169 | // stem the word
170 | var word = stemmer.stemWord(tmp[i].toLowerCase());
171 | // prevent stemmer from cutting word smaller than two chars
172 | if(word.length < 3 && tmp[i].length >= 3) {
173 | word = tmp[i];
174 | }
175 | var toAppend;
176 | // select the correct list
177 | if (word[0] == '-') {
178 | toAppend = excluded;
179 | word = word.substr(1);
180 | }
181 | else {
182 | toAppend = searchterms;
183 | hlterms.push(tmp[i].toLowerCase());
184 | }
185 | // only add if not already in the list
186 | if (!$u.contains(toAppend, word))
187 | toAppend.push(word);
188 | }
189 | var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
190 |
191 | // console.debug('SEARCH: searching for:');
192 | // console.info('required: ', searchterms);
193 | // console.info('excluded: ', excluded);
194 |
195 | // prepare search
196 | var terms = this._index.terms;
197 | var titleterms = this._index.titleterms;
198 |
199 | // array of [filename, title, anchor, descr, score]
200 | var results = [];
201 | $('#search-progress').empty();
202 |
203 | // lookup as object
204 | for (i = 0; i < objectterms.length; i++) {
205 | var others = [].concat(objectterms.slice(0, i),
206 | objectterms.slice(i+1, objectterms.length));
207 | results = results.concat(this.performObjectSearch(objectterms[i], others));
208 | }
209 |
210 | // lookup as search terms in fulltext
211 | results = results.concat(this.performTermsSearch(searchterms, excluded, terms, titleterms));
212 |
213 | // let the scorer override scores with a custom scoring function
214 | if (Scorer.score) {
215 | for (i = 0; i < results.length; i++)
216 | results[i][4] = Scorer.score(results[i]);
217 | }
218 |
219 | // now sort the results by score (in opposite order of appearance, since the
220 | // display function below uses pop() to retrieve items) and then
221 | // alphabetically
222 | results.sort(function(a, b) {
223 | var left = a[4];
224 | var right = b[4];
225 | if (left > right) {
226 | return 1;
227 | } else if (left < right) {
228 | return -1;
229 | } else {
230 | // same score: sort alphabetically
231 | left = a[1].toLowerCase();
232 | right = b[1].toLowerCase();
233 | return (left > right) ? -1 : ((left < right) ? 1 : 0);
234 | }
235 | });
236 |
237 | // for debugging
238 | //Search.lastresults = results.slice(); // a copy
239 | //console.info('search results:', Search.lastresults);
240 |
241 | // print the results
242 | var resultCount = results.length;
243 | function displayNextItem() {
244 | // results left, load the summary and display it
245 | if (results.length) {
246 | var item = results.pop();
247 | var listItem = $(' ');
248 | if (DOCUMENTATION_OPTIONS.FILE_SUFFIX === '') {
249 | // dirhtml builder
250 | var dirname = item[0] + '/';
251 | if (dirname.match(/\/index\/$/)) {
252 | dirname = dirname.substring(0, dirname.length-6);
253 | } else if (dirname == 'index/') {
254 | dirname = '';
255 | }
256 | listItem.append($(' ').attr('href',
257 | DOCUMENTATION_OPTIONS.URL_ROOT + dirname +
258 | highlightstring + item[2]).html(item[1]));
259 | } else {
260 | // normal html builders
261 | listItem.append($(' ').attr('href',
262 | item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX +
263 | highlightstring + item[2]).html(item[1]));
264 | }
265 | if (item[3]) {
266 | listItem.append($(' (' + item[3] + ') '));
267 | Search.output.append(listItem);
268 | listItem.slideDown(5, function() {
269 | displayNextItem();
270 | });
271 | } else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
272 | $.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT + item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX,
273 | dataType: "text",
274 | complete: function(jqxhr, textstatus) {
275 | var data = jqxhr.responseText;
276 | if (data !== '' && data !== undefined) {
277 | listItem.append(Search.makeSearchSummary(data, searchterms, hlterms));
278 | }
279 | Search.output.append(listItem);
280 | listItem.slideDown(5, function() {
281 | displayNextItem();
282 | });
283 | }});
284 | } else {
285 | // no source available, just display title
286 | Search.output.append(listItem);
287 | listItem.slideDown(5, function() {
288 | displayNextItem();
289 | });
290 | }
291 | }
292 | // search finished, update title and status message
293 | else {
294 | Search.stopPulse();
295 | Search.title.text(_('Search Results'));
296 | if (!resultCount)
297 | Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.'));
298 | else
299 | Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount));
300 | Search.status.fadeIn(500);
301 | }
302 | }
303 | displayNextItem();
304 | },
305 |
306 | /**
307 | * search for object names
308 | */
309 | performObjectSearch : function(object, otherterms) {
310 | var filenames = this._index.filenames;
311 | var docnames = this._index.docnames;
312 | var objects = this._index.objects;
313 | var objnames = this._index.objnames;
314 | var titles = this._index.titles;
315 |
316 | var i;
317 | var results = [];
318 |
319 | for (var prefix in objects) {
320 | for (var name in objects[prefix]) {
321 | var fullname = (prefix ? prefix + '.' : '') + name;
322 | if (fullname.toLowerCase().indexOf(object) > -1) {
323 | var score = 0;
324 | var parts = fullname.split('.');
325 | // check for different match types: exact matches of full name or
326 | // "last name" (i.e. last dotted part)
327 | if (fullname == object || parts[parts.length - 1] == object) {
328 | score += Scorer.objNameMatch;
329 | // matches in last name
330 | } else if (parts[parts.length - 1].indexOf(object) > -1) {
331 | score += Scorer.objPartialMatch;
332 | }
333 | var match = objects[prefix][name];
334 | var objname = objnames[match[1]][2];
335 | var title = titles[match[0]];
336 | // If more than one term searched for, we require other words to be
337 | // found in the name/title/description
338 | if (otherterms.length > 0) {
339 | var haystack = (prefix + ' ' + name + ' ' +
340 | objname + ' ' + title).toLowerCase();
341 | var allfound = true;
342 | for (i = 0; i < otherterms.length; i++) {
343 | if (haystack.indexOf(otherterms[i]) == -1) {
344 | allfound = false;
345 | break;
346 | }
347 | }
348 | if (!allfound) {
349 | continue;
350 | }
351 | }
352 | var descr = objname + _(', in ') + title;
353 |
354 | var anchor = match[3];
355 | if (anchor === '')
356 | anchor = fullname;
357 | else if (anchor == '-')
358 | anchor = objnames[match[1]][1] + '-' + fullname;
359 | // add custom score for some objects according to scorer
360 | if (Scorer.objPrio.hasOwnProperty(match[2])) {
361 | score += Scorer.objPrio[match[2]];
362 | } else {
363 | score += Scorer.objPrioDefault;
364 | }
365 | results.push([docnames[match[0]], fullname, '#'+anchor, descr, score, filenames[match[0]]]);
366 | }
367 | }
368 | }
369 |
370 | return results;
371 | },
372 |
373 | /**
374 | * search for full-text terms in the index
375 | */
376 | performTermsSearch : function(searchterms, excluded, terms, titleterms) {
377 | var docnames = this._index.docnames;
378 | var filenames = this._index.filenames;
379 | var titles = this._index.titles;
380 |
381 | var i, j, file;
382 | var fileMap = {};
383 | var scoreMap = {};
384 | var results = [];
385 |
386 | // perform the search on the required terms
387 | for (i = 0; i < searchterms.length; i++) {
388 | var word = searchterms[i];
389 | var files = [];
390 | var _o = [
391 | {files: terms[word], score: Scorer.term},
392 | {files: titleterms[word], score: Scorer.title}
393 | ];
394 | // add support for partial matches
395 | if (word.length > 2) {
396 | for (var w in terms) {
397 | if (w.match(word) && !terms[word]) {
398 | _o.push({files: terms[w], score: Scorer.partialTerm})
399 | }
400 | }
401 | for (var w in titleterms) {
402 | if (w.match(word) && !titleterms[word]) {
403 | _o.push({files: titleterms[w], score: Scorer.partialTitle})
404 | }
405 | }
406 | }
407 |
408 | // no match but word was a required one
409 | if ($u.every(_o, function(o){return o.files === undefined;})) {
410 | break;
411 | }
412 | // found search word in contents
413 | $u.each(_o, function(o) {
414 | var _files = o.files;
415 | if (_files === undefined)
416 | return
417 |
418 | if (_files.length === undefined)
419 | _files = [_files];
420 | files = files.concat(_files);
421 |
422 | // set score for the word in each file to Scorer.term
423 | for (j = 0; j < _files.length; j++) {
424 | file = _files[j];
425 | if (!(file in scoreMap))
426 | scoreMap[file] = {}
427 | scoreMap[file][word] = o.score;
428 | }
429 | });
430 |
431 | // create the mapping
432 | for (j = 0; j < files.length; j++) {
433 | file = files[j];
434 | if (file in fileMap)
435 | fileMap[file].push(word);
436 | else
437 | fileMap[file] = [word];
438 | }
439 | }
440 |
441 | // now check if the files don't contain excluded terms
442 | for (file in fileMap) {
443 | var valid = true;
444 |
445 | // check if all requirements are matched
446 | var filteredTermCount = // as search terms with length < 3 are discarded: ignore
447 | searchterms.filter(function(term){return term.length > 2}).length
448 | if (
449 | fileMap[file].length != searchterms.length &&
450 | fileMap[file].length != filteredTermCount
451 | ) continue;
452 |
453 | // ensure that none of the excluded terms is in the search result
454 | for (i = 0; i < excluded.length; i++) {
455 | if (terms[excluded[i]] == file ||
456 | titleterms[excluded[i]] == file ||
457 | $u.contains(terms[excluded[i]] || [], file) ||
458 | $u.contains(titleterms[excluded[i]] || [], file)) {
459 | valid = false;
460 | break;
461 | }
462 | }
463 |
464 | // if we have still a valid result we can add it to the result list
465 | if (valid) {
466 | // select one (max) score for the file.
467 | // for better ranking, we should calculate ranking by using words statistics like basic tf-idf...
468 | var score = $u.max($u.map(fileMap[file], function(w){return scoreMap[file][w]}));
469 | results.push([docnames[file], titles[file], '', null, score, filenames[file]]);
470 | }
471 | }
472 | return results;
473 | },
474 |
475 | /**
476 | * helper function to return a node containing the
477 | * search summary for a given text. keywords is a list
478 | * of stemmed words, hlwords is the list of normal, unstemmed
479 | * words. the first one is used to find the occurrence, the
480 | * latter for highlighting it.
481 | */
482 | makeSearchSummary : function(htmlText, keywords, hlwords) {
483 | var text = Search.htmlToText(htmlText);
484 | var textLower = text.toLowerCase();
485 | var start = 0;
486 | $.each(keywords, function() {
487 | var i = textLower.indexOf(this.toLowerCase());
488 | if (i > -1)
489 | start = i;
490 | });
491 | start = Math.max(start - 120, 0);
492 | var excerpt = ((start > 0) ? '...' : '') +
493 | $.trim(text.substr(start, 240)) +
494 | ((start + 240 - text.length) ? '...' : '');
495 | var rv = $('
').text(excerpt);
496 | $.each(hlwords, function() {
497 | rv = rv.highlightText(this, 'highlighted');
498 | });
499 | return rv;
500 | }
501 | };
502 |
503 | $(document).ready(function() {
504 | Search.init();
505 | });
506 |
--------------------------------------------------------------------------------
/docs/_build/html/_static/underscore-1.3.1.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 |
9 | (function() {
10 |
11 | // Baseline setup
12 | // --------------
13 |
14 | // Establish the root object, `window` in the browser, or `global` on the server.
15 | var root = this;
16 |
17 | // Save the previous value of the `_` variable.
18 | var previousUnderscore = root._;
19 |
20 | // Establish the object that gets returned to break out of a loop iteration.
21 | var breaker = {};
22 |
23 | // Save bytes in the minified (but not gzipped) version:
24 | var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
25 |
26 | // Create quick reference variables for speed access to core prototypes.
27 | var slice = ArrayProto.slice,
28 | unshift = ArrayProto.unshift,
29 | toString = ObjProto.toString,
30 | hasOwnProperty = ObjProto.hasOwnProperty;
31 |
32 | // All **ECMAScript 5** native function implementations that we hope to use
33 | // are declared here.
34 | var
35 | nativeForEach = ArrayProto.forEach,
36 | nativeMap = ArrayProto.map,
37 | nativeReduce = ArrayProto.reduce,
38 | nativeReduceRight = ArrayProto.reduceRight,
39 | nativeFilter = ArrayProto.filter,
40 | nativeEvery = ArrayProto.every,
41 | nativeSome = ArrayProto.some,
42 | nativeIndexOf = ArrayProto.indexOf,
43 | nativeLastIndexOf = ArrayProto.lastIndexOf,
44 | nativeIsArray = Array.isArray,
45 | nativeKeys = Object.keys,
46 | nativeBind = FuncProto.bind;
47 |
48 | // Create a safe reference to the Underscore object for use below.
49 | var _ = function(obj) { return new wrapper(obj); };
50 |
51 | // Export the Underscore object for **Node.js**, with
52 | // backwards-compatibility for the old `require()` API. If we're in
53 | // the browser, add `_` as a global object via a string identifier,
54 | // for Closure Compiler "advanced" mode.
55 | if (typeof exports !== 'undefined') {
56 | if (typeof module !== 'undefined' && module.exports) {
57 | exports = module.exports = _;
58 | }
59 | exports._ = _;
60 | } else {
61 | root['_'] = _;
62 | }
63 |
64 | // Current version.
65 | _.VERSION = '1.3.1';
66 |
67 | // Collection Functions
68 | // --------------------
69 |
70 | // The cornerstone, an `each` implementation, aka `forEach`.
71 | // Handles objects with the built-in `forEach`, arrays, and raw objects.
72 | // Delegates to **ECMAScript 5**'s native `forEach` if available.
73 | var each = _.each = _.forEach = function(obj, iterator, context) {
74 | if (obj == null) return;
75 | if (nativeForEach && obj.forEach === nativeForEach) {
76 | obj.forEach(iterator, context);
77 | } else if (obj.length === +obj.length) {
78 | for (var i = 0, l = obj.length; i < l; i++) {
79 | if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
80 | }
81 | } else {
82 | for (var key in obj) {
83 | if (_.has(obj, key)) {
84 | if (iterator.call(context, obj[key], key, obj) === breaker) return;
85 | }
86 | }
87 | }
88 | };
89 |
90 | // Return the results of applying the iterator to each element.
91 | // Delegates to **ECMAScript 5**'s native `map` if available.
92 | _.map = _.collect = function(obj, iterator, context) {
93 | var results = [];
94 | if (obj == null) return results;
95 | if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
96 | each(obj, function(value, index, list) {
97 | results[results.length] = iterator.call(context, value, index, list);
98 | });
99 | if (obj.length === +obj.length) results.length = obj.length;
100 | return results;
101 | };
102 |
103 | // **Reduce** builds up a single result from a list of values, aka `inject`,
104 | // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
105 | _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
106 | var initial = arguments.length > 2;
107 | if (obj == null) obj = [];
108 | if (nativeReduce && obj.reduce === nativeReduce) {
109 | if (context) iterator = _.bind(iterator, context);
110 | return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
111 | }
112 | each(obj, function(value, index, list) {
113 | if (!initial) {
114 | memo = value;
115 | initial = true;
116 | } else {
117 | memo = iterator.call(context, memo, value, index, list);
118 | }
119 | });
120 | if (!initial) throw new TypeError('Reduce of empty array with no initial value');
121 | return memo;
122 | };
123 |
124 | // The right-associative version of reduce, also known as `foldr`.
125 | // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
126 | _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
127 | var initial = arguments.length > 2;
128 | if (obj == null) obj = [];
129 | if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
130 | if (context) iterator = _.bind(iterator, context);
131 | return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
132 | }
133 | var reversed = _.toArray(obj).reverse();
134 | if (context && !initial) iterator = _.bind(iterator, context);
135 | return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator);
136 | };
137 |
138 | // Return the first value which passes a truth test. Aliased as `detect`.
139 | _.find = _.detect = function(obj, iterator, context) {
140 | var result;
141 | any(obj, function(value, index, list) {
142 | if (iterator.call(context, value, index, list)) {
143 | result = value;
144 | return true;
145 | }
146 | });
147 | return result;
148 | };
149 |
150 | // Return all the elements that pass a truth test.
151 | // Delegates to **ECMAScript 5**'s native `filter` if available.
152 | // Aliased as `select`.
153 | _.filter = _.select = function(obj, iterator, context) {
154 | var results = [];
155 | if (obj == null) return results;
156 | if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
157 | each(obj, function(value, index, list) {
158 | if (iterator.call(context, value, index, list)) results[results.length] = value;
159 | });
160 | return results;
161 | };
162 |
163 | // Return all the elements for which a truth test fails.
164 | _.reject = function(obj, iterator, context) {
165 | var results = [];
166 | if (obj == null) return results;
167 | each(obj, function(value, index, list) {
168 | if (!iterator.call(context, value, index, list)) results[results.length] = value;
169 | });
170 | return results;
171 | };
172 |
173 | // Determine whether all of the elements match a truth test.
174 | // Delegates to **ECMAScript 5**'s native `every` if available.
175 | // Aliased as `all`.
176 | _.every = _.all = function(obj, iterator, context) {
177 | var result = true;
178 | if (obj == null) return result;
179 | if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
180 | each(obj, function(value, index, list) {
181 | if (!(result = result && iterator.call(context, value, index, list))) return breaker;
182 | });
183 | return result;
184 | };
185 |
186 | // Determine if at least one element in the object matches a truth test.
187 | // Delegates to **ECMAScript 5**'s native `some` if available.
188 | // Aliased as `any`.
189 | var any = _.some = _.any = function(obj, iterator, context) {
190 | iterator || (iterator = _.identity);
191 | var result = false;
192 | if (obj == null) return result;
193 | if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
194 | each(obj, function(value, index, list) {
195 | if (result || (result = iterator.call(context, value, index, list))) return breaker;
196 | });
197 | return !!result;
198 | };
199 |
200 | // Determine if a given value is included in the array or object using `===`.
201 | // Aliased as `contains`.
202 | _.include = _.contains = function(obj, target) {
203 | var found = false;
204 | if (obj == null) return found;
205 | if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
206 | found = any(obj, function(value) {
207 | return value === target;
208 | });
209 | return found;
210 | };
211 |
212 | // Invoke a method (with arguments) on every item in a collection.
213 | _.invoke = function(obj, method) {
214 | var args = slice.call(arguments, 2);
215 | return _.map(obj, function(value) {
216 | return (_.isFunction(method) ? method || value : value[method]).apply(value, args);
217 | });
218 | };
219 |
220 | // Convenience version of a common use case of `map`: fetching a property.
221 | _.pluck = function(obj, key) {
222 | return _.map(obj, function(value){ return value[key]; });
223 | };
224 |
225 | // Return the maximum element or (element-based computation).
226 | _.max = function(obj, iterator, context) {
227 | if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
228 | if (!iterator && _.isEmpty(obj)) return -Infinity;
229 | var result = {computed : -Infinity};
230 | each(obj, function(value, index, list) {
231 | var computed = iterator ? iterator.call(context, value, index, list) : value;
232 | computed >= result.computed && (result = {value : value, computed : computed});
233 | });
234 | return result.value;
235 | };
236 |
237 | // Return the minimum element (or element-based computation).
238 | _.min = function(obj, iterator, context) {
239 | if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
240 | if (!iterator && _.isEmpty(obj)) return Infinity;
241 | var result = {computed : Infinity};
242 | each(obj, function(value, index, list) {
243 | var computed = iterator ? iterator.call(context, value, index, list) : value;
244 | computed < result.computed && (result = {value : value, computed : computed});
245 | });
246 | return result.value;
247 | };
248 |
249 | // Shuffle an array.
250 | _.shuffle = function(obj) {
251 | var shuffled = [], rand;
252 | each(obj, function(value, index, list) {
253 | if (index == 0) {
254 | shuffled[0] = value;
255 | } else {
256 | rand = Math.floor(Math.random() * (index + 1));
257 | shuffled[index] = shuffled[rand];
258 | shuffled[rand] = value;
259 | }
260 | });
261 | return shuffled;
262 | };
263 |
264 | // Sort the object's values by a criterion produced by an iterator.
265 | _.sortBy = function(obj, iterator, context) {
266 | return _.pluck(_.map(obj, function(value, index, list) {
267 | return {
268 | value : value,
269 | criteria : iterator.call(context, value, index, list)
270 | };
271 | }).sort(function(left, right) {
272 | var a = left.criteria, b = right.criteria;
273 | return a < b ? -1 : a > b ? 1 : 0;
274 | }), 'value');
275 | };
276 |
277 | // Groups the object's values by a criterion. Pass either a string attribute
278 | // to group by, or a function that returns the criterion.
279 | _.groupBy = function(obj, val) {
280 | var result = {};
281 | var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
282 | each(obj, function(value, index) {
283 | var key = iterator(value, index);
284 | (result[key] || (result[key] = [])).push(value);
285 | });
286 | return result;
287 | };
288 |
289 | // Use a comparator function to figure out at what index an object should
290 | // be inserted so as to maintain order. Uses binary search.
291 | _.sortedIndex = function(array, obj, iterator) {
292 | iterator || (iterator = _.identity);
293 | var low = 0, high = array.length;
294 | while (low < high) {
295 | var mid = (low + high) >> 1;
296 | iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
297 | }
298 | return low;
299 | };
300 |
301 | // Safely convert anything iterable into a real, live array.
302 | _.toArray = function(iterable) {
303 | if (!iterable) return [];
304 | if (iterable.toArray) return iterable.toArray();
305 | if (_.isArray(iterable)) return slice.call(iterable);
306 | if (_.isArguments(iterable)) return slice.call(iterable);
307 | return _.values(iterable);
308 | };
309 |
310 | // Return the number of elements in an object.
311 | _.size = function(obj) {
312 | return _.toArray(obj).length;
313 | };
314 |
315 | // Array Functions
316 | // ---------------
317 |
318 | // Get the first element of an array. Passing **n** will return the first N
319 | // values in the array. Aliased as `head`. The **guard** check allows it to work
320 | // with `_.map`.
321 | _.first = _.head = function(array, n, guard) {
322 | return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
323 | };
324 |
325 | // Returns everything but the last entry of the array. Especcialy useful on
326 | // the arguments object. Passing **n** will return all the values in
327 | // the array, excluding the last N. The **guard** check allows it to work with
328 | // `_.map`.
329 | _.initial = function(array, n, guard) {
330 | return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
331 | };
332 |
333 | // Get the last element of an array. Passing **n** will return the last N
334 | // values in the array. The **guard** check allows it to work with `_.map`.
335 | _.last = function(array, n, guard) {
336 | if ((n != null) && !guard) {
337 | return slice.call(array, Math.max(array.length - n, 0));
338 | } else {
339 | return array[array.length - 1];
340 | }
341 | };
342 |
343 | // Returns everything but the first entry of the array. Aliased as `tail`.
344 | // Especially useful on the arguments object. Passing an **index** will return
345 | // the rest of the values in the array from that index onward. The **guard**
346 | // check allows it to work with `_.map`.
347 | _.rest = _.tail = function(array, index, guard) {
348 | return slice.call(array, (index == null) || guard ? 1 : index);
349 | };
350 |
351 | // Trim out all falsy values from an array.
352 | _.compact = function(array) {
353 | return _.filter(array, function(value){ return !!value; });
354 | };
355 |
356 | // Return a completely flattened version of an array.
357 | _.flatten = function(array, shallow) {
358 | return _.reduce(array, function(memo, value) {
359 | if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value));
360 | memo[memo.length] = value;
361 | return memo;
362 | }, []);
363 | };
364 |
365 | // Return a version of the array that does not contain the specified value(s).
366 | _.without = function(array) {
367 | return _.difference(array, slice.call(arguments, 1));
368 | };
369 |
370 | // Produce a duplicate-free version of the array. If the array has already
371 | // been sorted, you have the option of using a faster algorithm.
372 | // Aliased as `unique`.
373 | _.uniq = _.unique = function(array, isSorted, iterator) {
374 | var initial = iterator ? _.map(array, iterator) : array;
375 | var result = [];
376 | _.reduce(initial, function(memo, el, i) {
377 | if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) {
378 | memo[memo.length] = el;
379 | result[result.length] = array[i];
380 | }
381 | return memo;
382 | }, []);
383 | return result;
384 | };
385 |
386 | // Produce an array that contains the union: each distinct element from all of
387 | // the passed-in arrays.
388 | _.union = function() {
389 | return _.uniq(_.flatten(arguments, true));
390 | };
391 |
392 | // Produce an array that contains every item shared between all the
393 | // passed-in arrays. (Aliased as "intersect" for back-compat.)
394 | _.intersection = _.intersect = function(array) {
395 | var rest = slice.call(arguments, 1);
396 | return _.filter(_.uniq(array), function(item) {
397 | return _.every(rest, function(other) {
398 | return _.indexOf(other, item) >= 0;
399 | });
400 | });
401 | };
402 |
403 | // Take the difference between one array and a number of other arrays.
404 | // Only the elements present in just the first array will remain.
405 | _.difference = function(array) {
406 | var rest = _.flatten(slice.call(arguments, 1));
407 | return _.filter(array, function(value){ return !_.include(rest, value); });
408 | };
409 |
410 | // Zip together multiple lists into a single array -- elements that share
411 | // an index go together.
412 | _.zip = function() {
413 | var args = slice.call(arguments);
414 | var length = _.max(_.pluck(args, 'length'));
415 | var results = new Array(length);
416 | for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
417 | return results;
418 | };
419 |
420 | // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
421 | // we need this function. Return the position of the first occurrence of an
422 | // item in an array, or -1 if the item is not included in the array.
423 | // Delegates to **ECMAScript 5**'s native `indexOf` if available.
424 | // If the array is large and already in sort order, pass `true`
425 | // for **isSorted** to use binary search.
426 | _.indexOf = function(array, item, isSorted) {
427 | if (array == null) return -1;
428 | var i, l;
429 | if (isSorted) {
430 | i = _.sortedIndex(array, item);
431 | return array[i] === item ? i : -1;
432 | }
433 | if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
434 | for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i;
435 | return -1;
436 | };
437 |
438 | // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
439 | _.lastIndexOf = function(array, item) {
440 | if (array == null) return -1;
441 | if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
442 | var i = array.length;
443 | while (i--) if (i in array && array[i] === item) return i;
444 | return -1;
445 | };
446 |
447 | // Generate an integer Array containing an arithmetic progression. A port of
448 | // the native Python `range()` function. See
449 | // [the Python documentation](http://docs.python.org/library/functions.html#range).
450 | _.range = function(start, stop, step) {
451 | if (arguments.length <= 1) {
452 | stop = start || 0;
453 | start = 0;
454 | }
455 | step = arguments[2] || 1;
456 |
457 | var len = Math.max(Math.ceil((stop - start) / step), 0);
458 | var idx = 0;
459 | var range = new Array(len);
460 |
461 | while(idx < len) {
462 | range[idx++] = start;
463 | start += step;
464 | }
465 |
466 | return range;
467 | };
468 |
469 | // Function (ahem) Functions
470 | // ------------------
471 |
472 | // Reusable constructor function for prototype setting.
473 | var ctor = function(){};
474 |
475 | // Create a function bound to a given object (assigning `this`, and arguments,
476 | // optionally). Binding with arguments is also known as `curry`.
477 | // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
478 | // We check for `func.bind` first, to fail fast when `func` is undefined.
479 | _.bind = function bind(func, context) {
480 | var bound, args;
481 | if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
482 | if (!_.isFunction(func)) throw new TypeError;
483 | args = slice.call(arguments, 2);
484 | return bound = function() {
485 | if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
486 | ctor.prototype = func.prototype;
487 | var self = new ctor;
488 | var result = func.apply(self, args.concat(slice.call(arguments)));
489 | if (Object(result) === result) return result;
490 | return self;
491 | };
492 | };
493 |
494 | // Bind all of an object's methods to that object. Useful for ensuring that
495 | // all callbacks defined on an object belong to it.
496 | _.bindAll = function(obj) {
497 | var funcs = slice.call(arguments, 1);
498 | if (funcs.length == 0) funcs = _.functions(obj);
499 | each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
500 | return obj;
501 | };
502 |
503 | // Memoize an expensive function by storing its results.
504 | _.memoize = function(func, hasher) {
505 | var memo = {};
506 | hasher || (hasher = _.identity);
507 | return function() {
508 | var key = hasher.apply(this, arguments);
509 | return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
510 | };
511 | };
512 |
513 | // Delays a function for the given number of milliseconds, and then calls
514 | // it with the arguments supplied.
515 | _.delay = function(func, wait) {
516 | var args = slice.call(arguments, 2);
517 | return setTimeout(function(){ return func.apply(func, args); }, wait);
518 | };
519 |
520 | // Defers a function, scheduling it to run after the current call stack has
521 | // cleared.
522 | _.defer = function(func) {
523 | return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
524 | };
525 |
526 | // Returns a function, that, when invoked, will only be triggered at most once
527 | // during a given window of time.
528 | _.throttle = function(func, wait) {
529 | var context, args, timeout, throttling, more;
530 | var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
531 | return function() {
532 | context = this; args = arguments;
533 | var later = function() {
534 | timeout = null;
535 | if (more) func.apply(context, args);
536 | whenDone();
537 | };
538 | if (!timeout) timeout = setTimeout(later, wait);
539 | if (throttling) {
540 | more = true;
541 | } else {
542 | func.apply(context, args);
543 | }
544 | whenDone();
545 | throttling = true;
546 | };
547 | };
548 |
549 | // Returns a function, that, as long as it continues to be invoked, will not
550 | // be triggered. The function will be called after it stops being called for
551 | // N milliseconds.
552 | _.debounce = function(func, wait) {
553 | var timeout;
554 | return function() {
555 | var context = this, args = arguments;
556 | var later = function() {
557 | timeout = null;
558 | func.apply(context, args);
559 | };
560 | clearTimeout(timeout);
561 | timeout = setTimeout(later, wait);
562 | };
563 | };
564 |
565 | // Returns a function that will be executed at most one time, no matter how
566 | // often you call it. Useful for lazy initialization.
567 | _.once = function(func) {
568 | var ran = false, memo;
569 | return function() {
570 | if (ran) return memo;
571 | ran = true;
572 | return memo = func.apply(this, arguments);
573 | };
574 | };
575 |
576 | // Returns the first function passed as an argument to the second,
577 | // allowing you to adjust arguments, run code before and after, and
578 | // conditionally execute the original function.
579 | _.wrap = function(func, wrapper) {
580 | return function() {
581 | var args = [func].concat(slice.call(arguments, 0));
582 | return wrapper.apply(this, args);
583 | };
584 | };
585 |
586 | // Returns a function that is the composition of a list of functions, each
587 | // consuming the return value of the function that follows.
588 | _.compose = function() {
589 | var funcs = arguments;
590 | return function() {
591 | var args = arguments;
592 | for (var i = funcs.length - 1; i >= 0; i--) {
593 | args = [funcs[i].apply(this, args)];
594 | }
595 | return args[0];
596 | };
597 | };
598 |
599 | // Returns a function that will only be executed after being called N times.
600 | _.after = function(times, func) {
601 | if (times <= 0) return func();
602 | return function() {
603 | if (--times < 1) { return func.apply(this, arguments); }
604 | };
605 | };
606 |
607 | // Object Functions
608 | // ----------------
609 |
610 | // Retrieve the names of an object's properties.
611 | // Delegates to **ECMAScript 5**'s native `Object.keys`
612 | _.keys = nativeKeys || function(obj) {
613 | if (obj !== Object(obj)) throw new TypeError('Invalid object');
614 | var keys = [];
615 | for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
616 | return keys;
617 | };
618 |
619 | // Retrieve the values of an object's properties.
620 | _.values = function(obj) {
621 | return _.map(obj, _.identity);
622 | };
623 |
624 | // Return a sorted list of the function names available on the object.
625 | // Aliased as `methods`
626 | _.functions = _.methods = function(obj) {
627 | var names = [];
628 | for (var key in obj) {
629 | if (_.isFunction(obj[key])) names.push(key);
630 | }
631 | return names.sort();
632 | };
633 |
634 | // Extend a given object with all the properties in passed-in object(s).
635 | _.extend = function(obj) {
636 | each(slice.call(arguments, 1), function(source) {
637 | for (var prop in source) {
638 | obj[prop] = source[prop];
639 | }
640 | });
641 | return obj;
642 | };
643 |
644 | // Fill in a given object with default properties.
645 | _.defaults = function(obj) {
646 | each(slice.call(arguments, 1), function(source) {
647 | for (var prop in source) {
648 | if (obj[prop] == null) obj[prop] = source[prop];
649 | }
650 | });
651 | return obj;
652 | };
653 |
654 | // Create a (shallow-cloned) duplicate of an object.
655 | _.clone = function(obj) {
656 | if (!_.isObject(obj)) return obj;
657 | return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
658 | };
659 |
660 | // Invokes interceptor with the obj, and then returns obj.
661 | // The primary purpose of this method is to "tap into" a method chain, in
662 | // order to perform operations on intermediate results within the chain.
663 | _.tap = function(obj, interceptor) {
664 | interceptor(obj);
665 | return obj;
666 | };
667 |
668 | // Internal recursive comparison function.
669 | function eq(a, b, stack) {
670 | // Identical objects are equal. `0 === -0`, but they aren't identical.
671 | // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
672 | if (a === b) return a !== 0 || 1 / a == 1 / b;
673 | // A strict comparison is necessary because `null == undefined`.
674 | if (a == null || b == null) return a === b;
675 | // Unwrap any wrapped objects.
676 | if (a._chain) a = a._wrapped;
677 | if (b._chain) b = b._wrapped;
678 | // Invoke a custom `isEqual` method if one is provided.
679 | if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b);
680 | if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a);
681 | // Compare `[[Class]]` names.
682 | var className = toString.call(a);
683 | if (className != toString.call(b)) return false;
684 | switch (className) {
685 | // Strings, numbers, dates, and booleans are compared by value.
686 | case '[object String]':
687 | // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
688 | // equivalent to `new String("5")`.
689 | return a == String(b);
690 | case '[object Number]':
691 | // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
692 | // other numeric values.
693 | return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
694 | case '[object Date]':
695 | case '[object Boolean]':
696 | // Coerce dates and booleans to numeric primitive values. Dates are compared by their
697 | // millisecond representations. Note that invalid dates with millisecond representations
698 | // of `NaN` are not equivalent.
699 | return +a == +b;
700 | // RegExps are compared by their source patterns and flags.
701 | case '[object RegExp]':
702 | return a.source == b.source &&
703 | a.global == b.global &&
704 | a.multiline == b.multiline &&
705 | a.ignoreCase == b.ignoreCase;
706 | }
707 | if (typeof a != 'object' || typeof b != 'object') return false;
708 | // Assume equality for cyclic structures. The algorithm for detecting cyclic
709 | // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
710 | var length = stack.length;
711 | while (length--) {
712 | // Linear search. Performance is inversely proportional to the number of
713 | // unique nested structures.
714 | if (stack[length] == a) return true;
715 | }
716 | // Add the first object to the stack of traversed objects.
717 | stack.push(a);
718 | var size = 0, result = true;
719 | // Recursively compare objects and arrays.
720 | if (className == '[object Array]') {
721 | // Compare array lengths to determine if a deep comparison is necessary.
722 | size = a.length;
723 | result = size == b.length;
724 | if (result) {
725 | // Deep compare the contents, ignoring non-numeric properties.
726 | while (size--) {
727 | // Ensure commutative equality for sparse arrays.
728 | if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break;
729 | }
730 | }
731 | } else {
732 | // Objects with different constructors are not equivalent.
733 | if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false;
734 | // Deep compare objects.
735 | for (var key in a) {
736 | if (_.has(a, key)) {
737 | // Count the expected number of properties.
738 | size++;
739 | // Deep compare each member.
740 | if (!(result = _.has(b, key) && eq(a[key], b[key], stack))) break;
741 | }
742 | }
743 | // Ensure that both objects contain the same number of properties.
744 | if (result) {
745 | for (key in b) {
746 | if (_.has(b, key) && !(size--)) break;
747 | }
748 | result = !size;
749 | }
750 | }
751 | // Remove the first object from the stack of traversed objects.
752 | stack.pop();
753 | return result;
754 | }
755 |
756 | // Perform a deep comparison to check if two objects are equal.
757 | _.isEqual = function(a, b) {
758 | return eq(a, b, []);
759 | };
760 |
761 | // Is a given array, string, or object empty?
762 | // An "empty" object has no enumerable own-properties.
763 | _.isEmpty = function(obj) {
764 | if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
765 | for (var key in obj) if (_.has(obj, key)) return false;
766 | return true;
767 | };
768 |
769 | // Is a given value a DOM element?
770 | _.isElement = function(obj) {
771 | return !!(obj && obj.nodeType == 1);
772 | };
773 |
774 | // Is a given value an array?
775 | // Delegates to ECMA5's native Array.isArray
776 | _.isArray = nativeIsArray || function(obj) {
777 | return toString.call(obj) == '[object Array]';
778 | };
779 |
780 | // Is a given variable an object?
781 | _.isObject = function(obj) {
782 | return obj === Object(obj);
783 | };
784 |
785 | // Is a given variable an arguments object?
786 | _.isArguments = function(obj) {
787 | return toString.call(obj) == '[object Arguments]';
788 | };
789 | if (!_.isArguments(arguments)) {
790 | _.isArguments = function(obj) {
791 | return !!(obj && _.has(obj, 'callee'));
792 | };
793 | }
794 |
795 | // Is a given value a function?
796 | _.isFunction = function(obj) {
797 | return toString.call(obj) == '[object Function]';
798 | };
799 |
800 | // Is a given value a string?
801 | _.isString = function(obj) {
802 | return toString.call(obj) == '[object String]';
803 | };
804 |
805 | // Is a given value a number?
806 | _.isNumber = function(obj) {
807 | return toString.call(obj) == '[object Number]';
808 | };
809 |
810 | // Is the given value `NaN`?
811 | _.isNaN = function(obj) {
812 | // `NaN` is the only value for which `===` is not reflexive.
813 | return obj !== obj;
814 | };
815 |
816 | // Is a given value a boolean?
817 | _.isBoolean = function(obj) {
818 | return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
819 | };
820 |
821 | // Is a given value a date?
822 | _.isDate = function(obj) {
823 | return toString.call(obj) == '[object Date]';
824 | };
825 |
826 | // Is the given value a regular expression?
827 | _.isRegExp = function(obj) {
828 | return toString.call(obj) == '[object RegExp]';
829 | };
830 |
831 | // Is a given value equal to null?
832 | _.isNull = function(obj) {
833 | return obj === null;
834 | };
835 |
836 | // Is a given variable undefined?
837 | _.isUndefined = function(obj) {
838 | return obj === void 0;
839 | };
840 |
841 | // Has own property?
842 | _.has = function(obj, key) {
843 | return hasOwnProperty.call(obj, key);
844 | };
845 |
846 | // Utility Functions
847 | // -----------------
848 |
849 | // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
850 | // previous owner. Returns a reference to the Underscore object.
851 | _.noConflict = function() {
852 | root._ = previousUnderscore;
853 | return this;
854 | };
855 |
856 | // Keep the identity function around for default iterators.
857 | _.identity = function(value) {
858 | return value;
859 | };
860 |
861 | // Run a function **n** times.
862 | _.times = function (n, iterator, context) {
863 | for (var i = 0; i < n; i++) iterator.call(context, i);
864 | };
865 |
866 | // Escape a string for HTML interpolation.
867 | _.escape = function(string) {
868 | return (''+string).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/');
869 | };
870 |
871 | // Add your own custom functions to the Underscore object, ensuring that
872 | // they're correctly added to the OOP wrapper as well.
873 | _.mixin = function(obj) {
874 | each(_.functions(obj), function(name){
875 | addToWrapper(name, _[name] = obj[name]);
876 | });
877 | };
878 |
879 | // Generate a unique integer id (unique within the entire client session).
880 | // Useful for temporary DOM ids.
881 | var idCounter = 0;
882 | _.uniqueId = function(prefix) {
883 | var id = idCounter++;
884 | return prefix ? prefix + id : id;
885 | };
886 |
887 | // By default, Underscore uses ERB-style template delimiters, change the
888 | // following template settings to use alternative delimiters.
889 | _.templateSettings = {
890 | evaluate : /<%([\s\S]+?)%>/g,
891 | interpolate : /<%=([\s\S]+?)%>/g,
892 | escape : /<%-([\s\S]+?)%>/g
893 | };
894 |
895 | // When customizing `templateSettings`, if you don't want to define an
896 | // interpolation, evaluation or escaping regex, we need one that is
897 | // guaranteed not to match.
898 | var noMatch = /.^/;
899 |
900 | // Within an interpolation, evaluation, or escaping, remove HTML escaping
901 | // that had been previously added.
902 | var unescape = function(code) {
903 | return code.replace(/\\\\/g, '\\').replace(/\\'/g, "'");
904 | };
905 |
906 | // JavaScript micro-templating, similar to John Resig's implementation.
907 | // Underscore templating handles arbitrary delimiters, preserves whitespace,
908 | // and correctly escapes quotes within interpolated code.
909 | _.template = function(str, data) {
910 | var c = _.templateSettings;
911 | var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
912 | 'with(obj||{}){__p.push(\'' +
913 | str.replace(/\\/g, '\\\\')
914 | .replace(/'/g, "\\'")
915 | .replace(c.escape || noMatch, function(match, code) {
916 | return "',_.escape(" + unescape(code) + "),'";
917 | })
918 | .replace(c.interpolate || noMatch, function(match, code) {
919 | return "'," + unescape(code) + ",'";
920 | })
921 | .replace(c.evaluate || noMatch, function(match, code) {
922 | return "');" + unescape(code).replace(/[\r\n\t]/g, ' ') + ";__p.push('";
923 | })
924 | .replace(/\r/g, '\\r')
925 | .replace(/\n/g, '\\n')
926 | .replace(/\t/g, '\\t')
927 | + "');}return __p.join('');";
928 | var func = new Function('obj', '_', tmpl);
929 | if (data) return func(data, _);
930 | return function(data) {
931 | return func.call(this, data, _);
932 | };
933 | };
934 |
935 | // Add a "chain" function, which will delegate to the wrapper.
936 | _.chain = function(obj) {
937 | return _(obj).chain();
938 | };
939 |
940 | // The OOP Wrapper
941 | // ---------------
942 |
943 | // If Underscore is called as a function, it returns a wrapped object that
944 | // can be used OO-style. This wrapper holds altered versions of all the
945 | // underscore functions. Wrapped objects may be chained.
946 | var wrapper = function(obj) { this._wrapped = obj; };
947 |
948 | // Expose `wrapper.prototype` as `_.prototype`
949 | _.prototype = wrapper.prototype;
950 |
951 | // Helper function to continue chaining intermediate results.
952 | var result = function(obj, chain) {
953 | return chain ? _(obj).chain() : obj;
954 | };
955 |
956 | // A method to easily add functions to the OOP wrapper.
957 | var addToWrapper = function(name, func) {
958 | wrapper.prototype[name] = function() {
959 | var args = slice.call(arguments);
960 | unshift.call(args, this._wrapped);
961 | return result(func.apply(_, args), this._chain);
962 | };
963 | };
964 |
965 | // Add all of the Underscore functions to the wrapper object.
966 | _.mixin(_);
967 |
968 | // Add all mutator Array functions to the wrapper.
969 | each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
970 | var method = ArrayProto[name];
971 | wrapper.prototype[name] = function() {
972 | var wrapped = this._wrapped;
973 | method.apply(wrapped, arguments);
974 | var length = wrapped.length;
975 | if ((name == 'shift' || name == 'splice') && length === 0) delete wrapped[0];
976 | return result(wrapped, this._chain);
977 | };
978 | });
979 |
980 | // Add all accessor Array functions to the wrapper.
981 | each(['concat', 'join', 'slice'], function(name) {
982 | var method = ArrayProto[name];
983 | wrapper.prototype[name] = function() {
984 | return result(method.apply(this._wrapped, arguments), this._chain);
985 | };
986 | });
987 |
988 | // Start chaining a wrapped Underscore object.
989 | wrapper.prototype.chain = function() {
990 | this._chain = true;
991 | return this;
992 | };
993 |
994 | // Extracts the result from a wrapped and chained object.
995 | wrapper.prototype.value = function() {
996 | return this._wrapped;
997 | };
998 |
999 | }).call(this);
1000 |
--------------------------------------------------------------------------------