# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['trends', 'trends.tests']

package_data = \
{'': ['*']}

setup_kwargs = {
    'name': 'trends',
    'version': '0.1.0',
    'description': 'Generate and study quasi-monotonic sequences.',
    'long_description': '# Trends\n\n## Trends Are a Generalization of Monotonic Sequences.\n\nIn a monotonically increasing sequence, every element is greater than the preceding element.\nMonotonically decreasing sequences are obvious analogues, so for brevity, I\'ll just use "monotonic" to mean steadily increasing or decreasing.\n\nHere\'s a different, but equivalent definition:\n\nIf, for a sequence, **x_0, x_1, ..., x_n**,\nevery element in the subsequence **x_0, ..., x_k** is less than the following elements, **x_k+1, ... x_n**,\nfor all **0 < k < n**, then the sequence is monotonically increasing.\n\nOr, simpler, if you put your finger between any two sequence elements, everything to the left of your finger is less than everything to the right.\n\nA quasi-monotonic sequence, or trend, relaxes this restriction.\n\nIf, when put your finger between any two sequence elements, the average of everything to the left of your finger is less than the average of everything to the right, we\'ll call that a trend.\n\nIn other words, a monotonic sequence is also a trend\nbut a trend doesn\'t have to be monotonic.\n\nFor example, **0, 1, 4** is both monotonic and a trend.\nIn contrast, **1, 0, 4** is not monotonic,\nyet it is a trend,\nbecause **mean(1) = 1 < mean(0, 4) = 2**,\nand **mean(1, 0) = 1/2 < mean(4) = 4**.\n\nBy convention, just as single float is both a monotonically increasing and decreasing sequence, it\'s also both a rising and a falling trend.\n\n## Averages\n\nThe easiest average to work with is the arithmetic mean,\nbut for defining trends, any average will work that satisfies one condition:\nif S1 and S2 are sequences, and Average(S1) < Average(S2), then\nAverage(S1) < Average(S1 + S2) < Average(S2)\n\nGeometric and harmonic means both satisfy this condition just as well as the arithmetic mean.  Modes do not. For example,\n\n\tmode(1, 1, 2, 2, 2) =  2; mode(1, 1, 3, 3, 3) = 3\n\nbut\n\n\tmode(1, 1, 2, 2, 2 + 1, 1, 3, 3, 3) =\n\tmode(1, 1, 1, 1, 2, 2, 2, 3, 3, 3) = 1\n\nRight now, the code hard-wires "average" to "arithmetic mean."\nEnhancing it, so the average to use could be specified in a config file, would be a useful upgrade.\n\n## Random numbers\n\nIf you\'re a mathematician, you\'d say something like, *"Two reals, independently chosen on a finite interval, are equal with Lebesgue measure zero."*\nThis means that if you had a ***real*** random number generator, and generated a snotload of random floats, no two would ever be identical.\n\nIn Python, `random()` returns floats in `[0, 1)` that are random enough, and have enough digits,\nthat this module treats them like reals and pretends they\'ll never throw out duplicates,\nunless you use `random.seed(FIXED_SEED)` to force it to happen.\n\nThe code nods to reality by throwing an exception if it notices a violation of this assumption.\nIt hasn\'t yet.\n\nI\'m assuming averages of two different random sequences of reals\nare probably also never the same (again *"...Lebesgue measure zero"*),\nbut I would welcome a proof.\n\n## Representation\n\nIf you tack two trends together, their combined average is a weighted average of the pair.\nFor example, a rising trend with length **2** and mean **8.0**,\nfollowed by another rising trend with length **6** and mean **4.0**\nwill combine to form a single, rising trend of length **6**\nand mean **(2*8.0 + 6*4.0)/8 = 40.0/8 = 5**.\n\nIn fact, almost no operations with trends require storing\nthe actual, **x_i** values that make up the trend;\nit\'s enough to keep track of the trend mean, trend length,\nand whether the trend is rising or falling.\n\nThe current version of the package stores only mean and length as trend attributes.\nTrend direction is passed as an argument to trend methods that care.\nIt would be useful\nto explore whether storing direction in the code object itself\ncleans up the code.\n\n## Properties\n\nTrends have some interesting properties, worth mentioning:\n\n- Every sequence of reals that\'s not a trend can be decomposed, uniquely, into maximum-length trends by merging adjacent trends whenever possible.\n- After decomposing a sequence, the means of the trends are monotonic:\nIf you decompose the sequence, left-to-right, into increasing trends, their averages are monotonically decreasing. Decomposition into falling trends produces monotonically increasing averages.\n- Every sequence has exactly one circular permutation that\'s a single, increasing trend.\n\nThese perhaps-not-intuitively-obvious properties\nare shown in Ehrenfeucht, *et al. (vide infra)*.\n\n## Development Environment\n\nI use `poetry` for environment and dependency management.\nThe file `pyproject.toml` contains specifications.\n\nI use `pre-commit` to help minimize the number of bad commits I make.\n<https://pre-commit.com/> explains how to activate it.\nThe `.pre-commit.yaml` file could probably use some work.\n\n`bin/pychecks` performs a suite of linting operations,\nincluding `isort` `black`, `flake8`, `mypy`, `pylint`, `bandit`, and `safety`.\nEvery one of these is documented at <https://readthedocs.io> under *toolname*.readthedocs.io .\nexcept `safety`, which is documented at <https://pyup.io/safety>\n\nI welcome suggestions on what other checks I should add.\n\n`bin/pytests` does unit tests, code-coverage, and mutation testing.\nI use pytest for unit testing and code coverage,\nand mutmut for mutation testing.\nBoth `pytest` and `mutmut` are also documented at <https://readthedocs.io>.\n\nI do argument parsing with `argparse`,\nbut haven\'t yet figured out how to test its help messages.\n\n\n## Reference\n[Andrzej Ehrenfeucht, Jeffrey Haemer, and David Haussler Quasi-Monotonic Sequences: Theory, Algorithms and Applications. SIAM. J. on Algebraic and Discrete Methods 1987;8(3):410-429](https://scholar.colorado.edu/downloads/8049g581k)\n',
    'author': 'Jeffrey S. Haemer',
    'author_email': 'jeffrey.haemer@gmail.com',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://gitlab.com/jsh/trends',
    'packages': packages,
    'package_data': package_data,
    'python_requires': '>=3.9,<4.0',
}


setup(**setup_kwargs)
