A Python library for representing and manipulating infinite sequences through lazy evaluation.
The Calculus package aims to provide a collection of reusable abstractions for discrete and continuous mathematics.
The current implementation provides a generic Sequence[T]
abstraction together with the specialized NumericSequence and
Recurrence subclasses, serving as the foundation for future
components such as series and function abstractions.
- Generic
Sequence[T]implementation. NumericSequencewith element-wise arithmetic.Recurrencefor sequences defined by recursive relations.NumericRecurrencecombining numeric arithmetic with recursively defined elements.Seriesfor sequences defined by partial sums of an underlying term sequence.- Infinite (and finite) sequences.
- Lazy evaluation via user-defined rules.
- Arbitrary starting indices.
- Element access and slicing.
- Forward iteration over subsequences.
Sequencetransformations (map,combine,shift_by,shift_to).- Factory methods for constant sequences and sequences built from iterables.
- Fully type-annotated (
mypy --strict).
Calculus has no runtime dependencies beyond the Python standard library.
Development requires:
mypyfor static type checkingpyflakesfor static analysispydocstylefor docstring style checkingpytestfor unit testing
Install development dependencies with:
pip install -r requirements-dev.txt├── .github
│ └── workflows
│ └── ci.yml # GitHub Actions CI workflow
├── calculus
│ ├── __init__.py # Package public API
│ ├── numeric_recurrence.py # NumericRecurrence implementation
│ ├── numeric_sequence.py # NumericSequence implementation
│ ├── recurrence.py # Recurrence implementation
│ ├── sequence.py # Generic Sequence implementation
│ ├── series.py # Series implementation
│ └── utils.py # Shared validation helpers
├── tests
│ ├── test_numeric_recurrence.py # Pytest test suite
│ ├── test_numeric_sequence.py # Pytest test suite
│ ├── test_recurrence.py # Pytest test suite
│ ├── test_sequence.py # Pytest test suite
│ └── test_series.py # Pytest test suite
├── .gitignore
├── ARCHITECTURE.md # Class hierarchy and relationships
├── LICENSE
├── NOTES.md # Design rationale and architectural decisions
├── pytest.ini # Adds project root to sys.path for tests
├── README.md
├── requirements-dev.txt # Development and CI dependencies
├── STYLE.md # Project coding and documentation conventions
└── TODO.md # Planned enhancements
from calculus import Sequence
# Infinite sequence of uppercase letters, cycling through the alphabet.
alphabet = Sequence(lambda n: chr(65 + (n - 1) % 26))
print(alphabet.head(5))
# ⟨A, B, C, D, E⟩
print(alphabet[30])
# D
# map() works for any element type, not just numbers.
print(alphabet.map(str.lower).head(5))
# ⟨a, b, c, d, e⟩from calculus import NumericSequence
# Infinite sequence of perfect squares.
squares = NumericSequence(lambda n: n ** 2)
print(squares[3])
# 9
print(squares.head(5))
# ⟨1, 4, 9, 16, 25⟩
# Unary arithmetic.
print(-squares.head(5))
# ⟨-1, -4, -9, -16, -25⟩
# Absolute value.
print(abs(-squares.head(5)))
# ⟨1, 4, 9, 16, 25⟩
# Element-wise addition.
evens = NumericSequence(lambda n: 2 * n)
print((squares + evens).head(5))
# ⟨3, 8, 15, 24, 35⟩
# Element-wise multiplication.
print((squares * evens).head(5))
# ⟨2, 16, 54, 128, 250⟩
# Exponentiation.
nonnegints = NumericSequence(lambda n: n, first_index=0)
print(2 ** nonnegints)
# ⟨1, 2, 4, 8, 16, ...⟩from calculus import Recurrence
# Fibonacci sequence: each term is the sum of the two before it.
fib = Recurrence(lambda n, a: a[-1] + a[-2], basis=(0, 1))
print(fib.head(8))
# ⟨0, 1, 1, 2, 3, 5, 8, 13⟩from calculus import NumericRecurrence
# Fibonacci sequence, with arithmetic operations available directly.
fib = NumericRecurrence(lambda n, a: a[-1] + a[-2], basis=(0, 1))
print((fib + 1).head(8))
# ⟨1, 2, 2, 3, 4, 6, 9, 14⟩
print((-fib).head(8))
# ⟨0, -1, -1, -2, -3, -5, -8, -13⟩
# Babylonian method sequence approximating the real-valued square root
# of 2. Formula: x_{n+1} = 0.5 * (x_n + 2 / x_n) starting with an
# initial guess of 2.0.
babylonian_sqrt2 = NumericRecurrence(
lambda n, a: 0.5 * (a[-1] + 2.0 / a[-1]),
basis=(2.0,)
)
print(babylonian_sqrt2.head(5))
# ⟨2.0, 1.5, 1.4166666666666665, 1.4142156862745097, 1.4142135623746899⟩from calculus import Series
# Triangular numbers: partial sums of the natural numbers.
triangular = Series(lambda n: n)
print(triangular.head(5))
# ⟨1, 3, 6, 10, 15⟩
# Leibniz series: partial sums approximating pi / 4.
leibniz = Series.leibniz()
print(leibniz.map(lambda x: round(x, 4)).head(5))
# ⟨1.0, 0.6667, 0.8667, 0.7238, 0.8349⟩
print(4 * leibniz[1000])
# 3.140592653839794The project emphasizes:
- clean API design;
- strict static typing;
- comprehensive documentation;
- thorough unit testing.
Before committing, run:
mypy --strict calculus
pyflakes calculus
pydocstyle calculus
pytest
git diff --cached --check
STYLE.mddescribes the project's coding and documentation standards.NOTES.mdrecords design decisions and implementation rationale.
See LICENSE.