# Piecewise-linear maps¶

class plmaps.plmap.PLMap(domain, range)[source]

Let $$I$$ and $$J$$ be closed intervals. We define $$\operatorname{PL}_{S, G}(I, J)$$ to be the set of functions $$\alpha \colon I \to J$$ with the following properties.

• $$\alpha$$ is an orientation-preserving bijection.
• $$\alpha$$ is piecewise-linear, with finitely many linear segments.
• The coordinates of each breakpoint of $$\alpha$$ belong to $$S$$.
• The gradients of each linear section of $$\alpha$$ belong to $$G$$.

We do not require that the endpoints of $$I$$ or $$J$$ belong to $$S$$.

This class represents functions of this form where $$S = \mathbb{Q}$$ and $$G = \mathbb{Q}_{>0}$$.

Variables: domain – see __init__(). range – see __init__(). gradients – The ith entry of this list is the gradient of the ith linear segment.
__init__(domain, range)[source]

Create a new PLMap given the breakpoints’ coordinates. Breakpoint lists are normalised in memory: redudant breakpoints (where the the gradient does not change) are removed. Coordinates are provided via two lists domain and range of Fraction s.

Raises: ValueError – if len(domain) != len(range). ValueError – if len(domain) < 2. ValueError – if domain or range are not increasing sequences. ValueError – if domain or range contain invalid breakpoints. This requirement does not apply the first or last element of each list. ValueError – if domain or range describe linear segments with invalid gradients.
>>> PLMap([0, 1], [0, Fraction(1, 2), 1])
Traceback (most recent call last):
...
ValueError: Domain and range lengths differ
>>> PLMap([], [])
Traceback (most recent call last):
...
ValueError: Domain must be defined by at least two points
>>> PLMap([0, 0], [1, 0])
Traceback (most recent call last):
...
ValueError: domain is not an increasing sequence
>>> PLMap([0, 1], [1, 0])
Traceback (most recent call last):
...
ValueError: range is not an increasing sequence

domain
range
gradients
classmethod identity(t0, t1)[source]
__iter__()[source]

Iterating over a PLMap yields its breakpoints.

classmethod from_aut(aut)[source]

Creates a new PLMap using a Homomorphism.

classmethod from_stream(stream)[source]
save_to_file(filename)[source]
__mul__(other)[source]

Postcompose on the right.

image(x)[source]

Where does the current PLMap send the point $$x$$?

Raises: ValueError – if $$x$$ is not in the current map’s domain.
inverse_image(y)[source]

Where is mapped by the current PLMap to the point $$y$$?

Raises: ValueError – if $$y$$ is not in the current map’s range.
rgradient_at(x)[source]
is_identity()[source]
dump(short=True)[source]
format_pl_segments(**kwargs)[source]
tikz_path()[source]
commutes(other)[source]
centralise_in_F()[source]
restriction(t0, t1)[source]

Produce a copy of the current PLMap restricted to the interval $$[t_0, t_1]$$.

Parameters: target (iterable) – A sequence of at least two integers. The first and last entries are the start and end of the interval onto which we restrict. ValueError – if t0 >= t1. ValueError – if t0 and t1 do not describe a subinterval of self.domain.
restriction_of_range(t0, t1, raw=False)[source]

Produce a copy of the current PLMap restricted to the interval $$[t_0, t_1]$$.

Parameters: target (iterable) – A sequence of at least two integers. The first and last entries are the start and end of the interval onto which we restrict. ValueError – if t0 >= t1. ValueError – if t0 and t1 do not describe a subinterval of self.domain.
is_permutation()[source]
fixed_points(raw=False)[source]
fixed_point_boundary()[source]
is_one_bump()[source]
one_bump_test_conjugate_with(other, initial_gradient, verbose=False)[source]
one_bump_linearity_boxes(other, initial_gradient)[source]
class plmaps.plmap.PL2(domain, range)[source]

$$\operatorname{PL}_2$$ is shorthand for the set of PLMap s with $$S = \mathbb{Z}[1/2]$$ and $$G = 2^{\mathbb Z}$$. As noted above <plmaps.plmaps.PLMap>, we don’t insist that the endpoints of the domain and range lie in S: we’re working with what my thesis calls $$\operatorname{PL}_2^\text{rest}$$ rather than $$\operatorname{PL}_2^\text{flat}$$.

>>> PL2([0, Fraction(1, 3)], [1, Fraction(5, 3)])
<PL2: [0, 1/3] -> [1, 5/3]>
>>> PL2([0, Fraction(1, 2), 1], [1, Fraction(5, 3), 2])
Traceback (most recent call last):
...
ValueError: range contains an invalid breakpoint
>>> PL2([0, 1], [0, 3])
Traceback (most recent call last):
...

one_bump_test_conjugate(other)[source]
one_bump_cent_gen(verbose=False)[source]
If the current PLMap is a one-bump function $$D o D$$, produce an element which generates its centraliser in $$\operatorname{PL}(D)$$. The generator’s initial gradient will be above 1 if and only if the the current PLMap’s initial gradient is above 1.