Skip to content
Snippets Groups Projects
Commit f21a817b authored by Piotr Maślanka's avatar Piotr Maślanka
Browse files

docs

parent b5b3a73b
No related branches found
No related tags found
No related merge requests found
...@@ -61,7 +61,6 @@ instance/ ...@@ -61,7 +61,6 @@ instance/
# Scrapy stuff: # Scrapy stuff:
.scrapy .scrapy
docs/
# Sphinx documentation # Sphinx documentation
docs/_build/ docs/_build/
......
...@@ -30,6 +30,9 @@ slice them and so on. ...@@ -30,6 +30,9 @@ slice them and so on.
## Series ## Series
Can be imported from _sai.series_. A generic abstract superclass for series -
`Series` can be imported for checking if given object is a series.
### DiscreteSeries ### DiscreteSeries
To use a _DiscreteSeries_ you must give it a set of data to work with. These To use a _DiscreteSeries_ you must give it a set of data to work with. These
...@@ -57,6 +60,17 @@ fs[6] == 6 ...@@ -57,6 +60,17 @@ fs[6] == 6
Although you can't specify a domain where it would be impossible to compute the value. Although you can't specify a domain where it would be impossible to compute the value.
(ie. starting at smaller than zero). Doing so will throw a _ValueError_. (ie. starting at smaller than zero). Doing so will throw a _ValueError_.
Note that when using `join_discrete()` sometimes other series might get calls
from beyond their domain. This can be seen for example here:
```python
logs = FunctionSeries(math.log, '(0;5>')
dirs = DiscreteSeries([(0,1)], '<0;5>')
# Raises ValueError due to math.log being called with 0
dirs.join_discrete(logs, lambda x, y: x+y)
```
### FunctionSeries ### FunctionSeries
Using _FunctionSeries_ is straightforward. Just give them a callable and Using _FunctionSeries_ is straightforward. Just give them a callable and
...@@ -66,12 +80,23 @@ a domain: ...@@ -66,12 +80,23 @@ a domain:
fs = FunctionSeries(lambda x: x**2, '<-2;2>') fs = FunctionSeries(lambda x: x**2, '<-2;2>')
``` ```
## Ranges ### ModuloSeries
_ModuloSeries_ allow you to wrap a finite series in repetition.
```python ```python
from firanka.series import Range fs = ModuloSeries(someOtherSeries)
``` ```
By definition, _ModuloSeries_ has the domain of all real numbers.
Note that someOtherSeries's domain length must be non-zero and finite. Otherwise
_ValueError_ will be thrown.
## Ranges
Can be imported from _sai.series_.
Range would have been better called an **interval**. It is a continuous subset Range would have been better called an **interval**. It is a continuous subset
of the real number line. of the real number line.
......
...@@ -2,8 +2,7 @@ ...@@ -2,8 +2,7 @@
# coding=UTF-8 # coding=UTF-8
from __future__ import print_function, absolute_import, division from __future__ import print_function, absolute_import, division
import six import six
import functools import math
import itertools
from .range import Range, REAL_SET, EMPTY_RANGE from .range import Range, REAL_SET, EMPTY_RANGE
from .exceptions import NotInDomainError from .exceptions import NotInDomainError
...@@ -153,7 +152,6 @@ class DiscreteSeries(Series): ...@@ -153,7 +152,6 @@ class DiscreteSeries(Series):
if self.domain.start < data[0][0]: if self.domain.start < data[0][0]:
raise ValueError('some domain space is not covered by definition!') raise ValueError('some domain space is not covered by definition!')
def apply(self, fun): def apply(self, fun):
return DiscreteSeries([(k, fun(v)) for k, v in self.data], self.domain) return DiscreteSeries([(k, fun(v)) for k, v in self.data], self.domain)
...@@ -265,6 +263,11 @@ class JoinedSeries(Series): ...@@ -265,6 +263,11 @@ class JoinedSeries(Series):
class ModuloSeries(Series): class ModuloSeries(Series):
def __init__(self, series): def __init__(self, series):
"""
Construct a modulo series
:param series: base series to use
:raise ValueError: invalid domain length
"""
super(ModuloSeries, self).__init__(REAL_SET) super(ModuloSeries, self).__init__(REAL_SET)
self.series = series self.series = series
...@@ -272,6 +275,8 @@ class ModuloSeries(Series): ...@@ -272,6 +275,8 @@ class ModuloSeries(Series):
if self.period == 0: if self.period == 0:
raise ValueError('Modulo series cannot have a period of 0') raise ValueError('Modulo series cannot have a period of 0')
elif math.isinf(self.period):
raise ValueError('Modulo series cannot have an infinite period')
def _get_for(self, item): def _get_for(self, item):
if item < 0: if item < 0:
......
# coding=UTF-8 # coding=UTF-8
from __future__ import print_function, absolute_import, division from __future__ import print_function, absolute_import, division
import six import six
import math
import unittest import unittest
from firanka.series import DiscreteSeries, FunctionSeries, Range, ModuloSeries, NotInDomainError from firanka.series import DiscreteSeries, FunctionSeries, Range, ModuloSeries, NotInDomainError
NOOP = lambda x: x
class TestDiscreteSeries(unittest.TestCase): class TestDiscreteSeries(unittest.TestCase):
...@@ -63,7 +65,7 @@ class TestDiscreteSeries(unittest.TestCase): ...@@ -63,7 +65,7 @@ class TestDiscreteSeries(unittest.TestCase):
def test_eval2(self): def test_eval2(self):
sa = DiscreteSeries([[0, 0], [1, 1], [2, 2]]) sa = DiscreteSeries([[0, 0], [1, 1], [2, 2]])
sb = FunctionSeries(lambda x: x, '<0;2>') sb = FunctionSeries(NOOP, '<0;2>')
sc = sa.join_discrete(sb, lambda a, b: a+b) sc = sa.join_discrete(sb, lambda a, b: a+b)
self.assertEqual(sc.eval_points([0,1,2]), [0,2,4]) self.assertEqual(sc.eval_points([0,1,2]), [0,2,4])
...@@ -77,7 +79,7 @@ class TestDiscreteSeries(unittest.TestCase): ...@@ -77,7 +79,7 @@ class TestDiscreteSeries(unittest.TestCase):
def test_eval3(self): def test_eval3(self):
sa = FunctionSeries(lambda x: x**2, '<-10;10)') sa = FunctionSeries(lambda x: x**2, '<-10;10)')
sb = FunctionSeries(lambda x: x, '<0;2)') sb = FunctionSeries(NOOP, '<0;2)')
sc = sa.join(sb, lambda a, b: a*b) sc = sa.join(sb, lambda a, b: a*b)
...@@ -104,9 +106,10 @@ class TestDiscreteSeries(unittest.TestCase): ...@@ -104,9 +106,10 @@ class TestDiscreteSeries(unittest.TestCase):
empty = FunctionSeries(lambda x: x**2, '<-10;10)').discretize([]) empty = FunctionSeries(lambda x: x**2, '<-10;10)').discretize([])
self.assertTrue(empty.domain.is_empty()) self.assertTrue(empty.domain.is_empty())
class TestFunctionSeries(unittest.TestCase): class TestFunctionSeries(unittest.TestCase):
def test_slice(self): def test_slice(self):
series = FunctionSeries(lambda x: x, '<0;2>') series = FunctionSeries(NOOP, '<0;2>')
sp = series[0.5:1.5] sp = series[0.5:1.5]
self.assertEqual(sp[0.5], 0.5) self.assertEqual(sp[0.5], 0.5)
...@@ -118,11 +121,23 @@ class TestFunctionSeries(unittest.TestCase): ...@@ -118,11 +121,23 @@ class TestFunctionSeries(unittest.TestCase):
def test_apply(self): def test_apply(self):
PTS = [-1,-2,-3,1,2,3] PTS = [-1,-2,-3,1,2,3]
series = FunctionSeries(lambda x: x, '<-5;5>').apply(lambda x: x*2) series = FunctionSeries(NOOP, '<-5;5>').apply(lambda x: x*2)
self.assertEqual(series.eval_points(PTS), [x*2 for x in PTS]) self.assertEqual(series.eval_points(PTS), [x*2 for x in PTS])
def test_domain_sensitivity(self):
logs = FunctionSeries(math.log, '(0;5>')
dirs = DiscreteSeries([(0,1),(1,2),(3,4)], '<0;5>')
self.assertRaises(ValueError, lambda: dirs.join_discrete(logs, lambda x, y: x+y))
class TestModuloSeries(unittest.TestCase): class TestModuloSeries(unittest.TestCase):
def test_exceptions(self):
self.assertRaises(ValueError, lambda: ModuloSeries(FunctionSeries(NOOP, '(-inf; 0>')))
self.assertRaises(ValueError, lambda: ModuloSeries(FunctionSeries(NOOP, '(-inf; inf)')))
self.assertRaises(ValueError, lambda: ModuloSeries(FunctionSeries(NOOP, '<0; 0>')))
def test_base(self): def test_base(self):
series = ModuloSeries(DiscreteSeries([(0,1),(1,2),(2,3)], '<0;3)')) series = ModuloSeries(DiscreteSeries([(0,1),(1,2),(2,3)], '<0;3)'))
...@@ -133,7 +148,7 @@ class TestModuloSeries(unittest.TestCase): ...@@ -133,7 +148,7 @@ class TestModuloSeries(unittest.TestCase):
def test_comp_discrete(self): def test_comp_discrete(self):
ser1 = ModuloSeries(FunctionSeries(lambda x: x**2, '<0;3)')) ser1 = ModuloSeries(FunctionSeries(lambda x: x**2, '<0;3)'))
ser2 = FunctionSeries(lambda x: x, '<0;3)') ser2 = FunctionSeries(NOOP, '<0;3)')
ser3 = ser1.join(ser2, lambda x, y: x*y) ser3 = ser1.join(ser2, lambda x, y: x*y)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment