Code for the 1-row Gomory–Johnson infinite group relaxation

class cutgeneratingfunctionology.igp.CrazyPiece(interval, generators=None, cosets=[])
__call__(x)
__div__(other)
__init__(interval, generators=None, cosets=[])
__module__ = 'cutgeneratingfunctionology.igp'
__mul__(other)

Multiply self by a scalar.

__neg__()
__rmul__(other)

Multiply self by a scalar.

range()
class cutgeneratingfunctionology.igp.DirectedMoveCompositionCompletion(fdms=[], covered_components=[], proj_add_vert=set([]), show_plots=False, plot_background=None, function=None, pts_of_discontinuity=None, show_zero_perturbation=True, show_kwds={})
__init__(fdms=[], covered_components=[], proj_add_vert=set([]), show_plots=False, plot_background=None, function=None, pts_of_discontinuity=None, show_zero_perturbation=True, show_kwds={})

Computation of the continuous closure of (the inverse semigroup generated by) a set of moves.

Input for abstract move ensembles:
  • fdms: list of FunctionalDirectedMove elements (each is a move with a list of domains)
  • covered_components: list of lists of intervals
  • pts_of_discontinuity: Either True'' (everywhere discontinuous), or a list of points where discontinuity is allowed.  If not provided (or ``None''), uses the following defaults: If ``function is provided, uses the allowed discontinuities of its effective perturbations. Otherwise, defaults to True (everywhere discontinuous).
Additional input for move ensembles coming from a function:
  • function: a FastPiecewise function
__module__ = 'cutgeneratingfunctionology.igp'
__repr__()
_plot_directed_moves(moves, extra_graphics=None, **kwds)
add_backward_moves()
add_move(fdm)

Add a functional directed move to self. Merge or restrict functional directed move if necessary.

complete(max_num_rounds=None, error_if_max_num_rounds_exceeded=True)
complete_one_round()
extend_component_by_continuity(component)
extend_components_by_continuity()
extend_components_by_moves()

Compose self.covered_components with the functional directed moves.

extend_components_by_strip_lemma()
extend_moves_by_composition_of_moves()
generate_zero_perturbation_points()
max_component_intervals()
max_directed_move_intervals()
maybe_show_plot(current_dense_move_plot=None)
num_component_intervals()
num_directed_move_intervals()
plot(legend_label='moves', *args, **kwds)
reduce_moves_by_components()

Reduce moves with self.covered_components.

results()
update_stats()

Update max_component_intervals and max_directed_move_intervals.

class cutgeneratingfunctionology.igp.DynamicStdErrStreamHandler

Bases: logging.StreamHandler

A handler class which writes logging records, appropriately formatted, to a stream. Note that this class does not close the stream, as sys.stdout or sys.stderr may be used.

__init__()

Initialize the handler.

If stream is not specified, sys.stderr is used.

__module__ = 'cutgeneratingfunctionology.igp'
emit(record)

Emit a record.

If a formatter is specified, it is used to format the record. The record is then written to the stream with a trailing newline. If exception information is present, it is formatted using traceback.print_exception and appended to the stream. If the stream has an ‘encoding’ attribute, it is used to determine how to do the output to the stream.

flush()

Flushes the stream.

class cutgeneratingfunctionology.igp.Face(triple, vertices=None, is_known_to_be_minimal=False)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: F = Face([[1/5, 3/10], [3/4, 17/20], [1, 6/5]])
sage: F.vertices
[(1/5, 17/20), (3/10, 3/4), (3/10, 17/20), (1/5, 4/5), (1/4, 3/4)]
sage: F.minimal_triple
([1/5, 3/10], [3/4, 17/20], [1, 23/20])
__cmp__(right)
__contains__(point)
__hash__()
__init__(triple, vertices=None, is_known_to_be_minimal=False)
__module__ = 'cutgeneratingfunctionology.igp'
__repr__()
covered_component()
dimension()
directed_move_with_domain_and_codomain()

Maps a horizontal or vertical edge to a forward translation move. Maps a diagonal edge to a reflection move.

Note

Backward translation moves will be added to DirectedMoveCompositionCompletion by add_backward_moves in round 0.

The domain and codomain are lists of open intervals. Their endpoints will be considered when treating the additive vertices.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: from cutgeneratingfunctionology.igp import *
sage: face_hor = Face([[2/5, 3/5],[4/5],[6/5,7/5]])
sage: face_hor.directed_move_with_domain_and_codomain()
((1, -1/5), [<Int(2/5, 3/5)>], [<Int(1/5, 2/5)>])
sage: face_ver = Face([[4/5],[2/5, 3/5],[6/5,7/5]])
sage: face_ver.directed_move_with_domain_and_codomain() == face_hor.directed_move_with_domain_and_codomain()
True
sage: face_dia = Face([[2/5, 3/5],[2/5, 1/5],[4/5]])
sage: face_dia.directed_move_with_domain_and_codomain()
((-1, 4/5),
 [<Int(2/5, 3/5)>, <Int(1/5, 2/5)>],
 [<Int(1/5, 2/5)>, <Int(2/5, 3/5)>])
functional_directed_move(is_backward_translation=False)

Returns the (forward by default or backward if is_backward_translation=True) translation move if given a horizontal/vertical edge, or the reflection move if given a diagonal edge.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: from cutgeneratingfunctionology.igp import *
sage: face_hor = Face([[2/5, 3/5],[4/5],[6/5,7/5]])
sage: face_hor.functional_directed_move()
<FunctionalDirectedMove (1, -1/5) with domain [<Int(2/5, 3/5)>], range [<Int(1/5, 2/5)>]>
sage: face_hor.functional_directed_move(is_backward_translation=True)
<FunctionalDirectedMove (1, 1/5) with domain [<Int(1/5, 2/5)>], range [<Int(2/5, 3/5)>]>
sage: face_ver = Face([[4/5],[2/5, 3/5],[6/5,7/5]])
sage: face_ver.functional_directed_move() == face_hor.functional_directed_move()
True
sage: face_ver.functional_directed_move(is_backward_translation=True) == face_hor.functional_directed_move(is_backward_translation=True)
True
sage: face_dia = Face([[2/5, 3/5],[2/5, 1/5],[4/5]])
sage: face_dia.functional_directed_move()
<FunctionalDirectedMove (-1, 4/5) with domain [<Int(1/5, 2/5)>, <Int(2/5, 3/5)>], range [<Int(2/5, 3/5)>, <Int(1/5, 2/5)>]>
sage: face_dia.functional_directed_move(is_backward_translation=True)
<FunctionalDirectedMove (-1, 4/5) with domain [<Int(1/5, 2/5)>, <Int(2/5, 3/5)>], range [<Int(2/5, 3/5)>, <Int(1/5, 2/5)>]>
interior_contains(point)
is_0D()
is_1D()
is_2D()
is_diagonal()
is_directed_move()
is_horizontal()
is_vertical()
plot(rgbcolor=(0.000000000000000, 0.980392156862745, 0.603921568627451), fill_color=None, edge_thickness=2, vertex_size=30, *args, **kwds)
polyhedron()
exception cutgeneratingfunctionology.igp.FactorUndetermined

Bases: exceptions.Exception

__module__ = 'cutgeneratingfunctionology.igp'
__weakref__

list of weak references to the object (if defined)

cutgeneratingfunctionology.igp.GrowthDiagramBinWord
cutgeneratingfunctionology.igp.GrowthDiagramBurge
cutgeneratingfunctionology.igp.GrowthDiagramDomino
cutgeneratingfunctionology.igp.GrowthDiagramRSK
cutgeneratingfunctionology.igp.GrowthDiagramSylvester
cutgeneratingfunctionology.igp.GrowthDiagramYoungFibonacci
cutgeneratingfunctionology.igp.LinearCodeFromVectorSpace
exception cutgeneratingfunctionology.igp.MaximumNumberOfIterationsReached

Bases: exceptions.Exception

__module__ = 'cutgeneratingfunctionology.igp'
__weakref__

list of weak references to the object (if defined)

class cutgeneratingfunctionology.igp.ParametricFamily_bccz_counterexample(constructor, default_values, names)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily

_images/igp-1.svg

return function psi, a counterexample to Gomory–Johnson’s conjecture constructed by Basu–Conforti–Cornuejols–Zambelli [IR1].

psi is a continuous facet (hence extreme), but is not piecewise linear. cf. [IR1]

It can be considered as an absolutely continuous, measurable, non-piecewise linear “2-slope function”. A separate case with different parameters, which gives rise to a continuous “1-slope function”, is discussed in [KZh2015b, section 5].

Parameters:

  • f (real) \(\in (0,1)\);
  • q (real), q > 2: ratio of the geometric series;
  • eta (real), 0 <= eta < 1: to control the series sum;
  • maxiter (integer): maximum number of iterations;
Note:
psi is the uniform limit of the sequence of functions psi_n, generated by psi_n_in_bccz_counterexample_construction(f, [e[0], e[1], …, e[n - 1]]). e is a geometric series with ratio q, such that: 0 < … < e[n] <= e[n - 1] <= … <= e[1] <= e[0] <= 1 - f and sum_{i = 0}^{infty} {2^i * e[i]} <= f. The first n terms of e are generated by generate_example_e_for_psi_n(f, n, q, eta)

See also:

def generate_example_e_for_psi_n(f, n q, eta)
def psi_n_in_bccz_counterexample_construction(f, e)
Examples:

quick exact evaluations:

sage: from cutgeneratingfunctionology.igp import *
sage: bccz_counterexample(f=2/3, q=4, eta=0, maxiter=10000)(r=1/5)
21/40
sage: bccz_counterexample(f=2/3, q=4, eta=0, maxiter=10000)(r=1/4)
3/4

too many iterations:

sage: bccz_counterexample(f=2/3, q=4, eta=0, maxiter=10000)(r=9/40) # doctest: +SKIP

References:

  • [IR1]: A. Basu, M. Conforti, G. Cornuejols, and G. Zambelli, A counterexample to a conjecture of Gomory and Johnson, Mathematical Programming Ser. A 133 (2012), 25-38.
  • [KZh2015b] M. Koeppe and Y. Zhou, An electronic compendium of extreme functions for the Gomory-Johnson infinite group problem, Operations Research Letters, 2015, http://dx.doi.org/10.1016/j.orl.2015.06.004
__module__ = 'cutgeneratingfunctionology.igp'
_construct_function(f=2/3, q=4, eta=1/1000, maxiter=10000)

Construct the function.

class cutgeneratingfunctionology.igp.ParametricFamily_bcdsp_arbitrary_slope(constructor, default_values, names)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily

_images/igp-2.svg

A family of extreme functions with an arbitrary number \(k\) of slopes. (k >= 2)

Function is known to be extreme under the condition:
0 < f <= 1/2.

Tests show that the function is also extreme when f <= 4/5.

Examples:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = bcdsp_arbitrary_slope(f=1/2, k=2)
sage: h == gmic(f=1/2)
True
sage: h = bcdsp_arbitrary_slope(f=1/2, k=3)
sage: h == gj_forward_3_slope(f=1/2, lambda_1=1/2, lambda_2=1/4)
True
sage: h = bcdsp_arbitrary_slope(f=1/2, k=4)
sage: number_of_slopes(h)
4
sage: extremality_test(h)
True
sage: h = bcdsp_arbitrary_slope(f=4/5, k=10)
sage: number_of_slopes(h)
10
sage: extremality_test(h)
True
Reference:
[arbitrary_num_slopes] A. Basu, M. Conforti, M. Di Summa, and J. Paat, Extreme Functions with an Arbitrary Number of Slopes, 2015, http://www.ams.jhu.edu/~abasu9/papers/infinite-slopes.pdf, to appear in Proceedings of IPCO 2016.
__module__ = 'cutgeneratingfunctionology.igp'
_construct_function(f=1/2, k=4, field=None, conditioncheck=True)

Construct the function.

class cutgeneratingfunctionology.igp.ParametricFamily_bhk_gmi_irrational(constructor, default_values, names)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily

_images/igp-3.svg

A version of the irrational function with non-zero second slope, obtained by forming a convex combination of a modified version of the irrational function with the GMI cut. Constructed by Chun Yu Hong, 2013.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = bhk_gmi_irrational()
sage: extremality_test(h, False)
True
__module__ = 'cutgeneratingfunctionology.igp'
_construct_function(f=4/5, d1=3/5, d2=1/10, a0=3/20, delta=(1/200, 1/200*sqrt(2)), alpha=19/20, field=None)

Construct the function.

class cutgeneratingfunctionology.igp.ParametricFamily_bhk_irrational(constructor, default_values, names)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily

_images/igp-4.svg
Summary:
  • Name: Basu-Hildebrand-Koeppe’s irrational function.
  • Infinite; Dim = 1; Slopes = 3; Continuous; Covered intervals and equivariant perturbation.
  • Discovered [BHKoppe14] p.33, section.5.2, fig.9-10.
  • Proven extreme [BHKoppe14] p.34, thm.5.3.
  • (Although only extremality has been established in literature, the same proof shows that), bhk_irrational is a facet.
Parameters:
  • f (real) \(\in (0,1)\);
  • d1 (real): length of the positive slope;
  • d2 (real): length of the zero slopes;
  • a0 (real): length of the first zig-zag;
  • delta (n-tuple of reals): length of the extra zig-zags.
Function is known to be extreme under the conditions:
  • 0 < f < 1;
  • d1, d2, a0, delta > 0;
  • d1 + d2 < f;
  • len(delta) == 2
  • sum(delta) < d2 / 4; Weaker condition: 2*delta[0] + delta[1] < d2 / 2;
  • the two components of delta are linearly independent over Q.
Relation between the code parameters and the paper parameters:
  • t1 = delta[0], t2 = delta[0] + delta[1], …
  • a1 = a0 + t1, a2 = a0 + t2, …
  • A = f/2 - a0/2 - d2/4,
  • A0 = f/2 - a0/2 + d2/4.
Examples:

[BHKoppe14] p.34, thm.5.3:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.NOTSET) # enable INFO messages disabled by other doctests
sage: h = bhk_irrational(f=4/5, d1=3/5, d2=1/10, a0=15/100, delta=(1/200, sqrt(2)/200))
INFO: ...
sage: extremality_test(h, False)
INFO: ...
True

[BHKoppe14] thm 5.4: Not extreme for rational data:

sage: h = bhk_irrational(delta=[1/200, 3/200])
INFO: ...
sage: extremality_test(h, False)
INFO: ...
INFO: ... Total: 1 stability orbit...
False

A generalization with 3 zigzags instead of 2 as in [BHKoppe14]:

sage: h = bhk_irrational(f=4/5, d1=3/5, d2=1/10, a0=15/100, delta=(1/200, 6* sqrt(2)/200, 1/500))
INFO: ...
sage: extremality_test(h, False) # not tested - takes 20min on Macbook Pro 2.7Ghz Core i7
INFO: ...
INFO: ... Total: 3 stability orbits...
False

Verify that p constructed below is an effective perturbation of h:

sage: sqrt2 = h.end_points()[0].parent().gen()
sage: pb = ((0, 0), (343/1000, -3/100), (1331/4000, -9/400), (1249/4000, -3/400), (151/500, 0), (303/1000, 0), (1171/4000, 3/400), (1089/4000, 9/400), (131/500, 3/100), (87/250, -3/100), (1351/4000, -9/400), (1269/4000, -3/400), (307/1000, 0), (77/250, 0), (1191/4000, 3/400), (1109/4000, 9/400), (267/1000, 3/100), (353/1000, -3/100), (1371/4000, -9/400), (1289/4000, -3/400), (39/125, 0), (313/1000, 0), (1211/4000, 3/400), (1129/4000, 9/400), (34/125, 3/100), (179/500, -3/100), (1391/4000, -9/400), (1309/4000, -3/400), (317/1000, 0), (159/500, 0), (1231/4000, 3/400), (1149/4000, 9/400), (277/1000, 3/100), (363/1000, -3/100), (1411/4000, -9/400), (1329/4000, -3/400), (161/500, 0), (323/1000, 0), (1251/4000, 3/400), (1169/4000, 9/400), (141/500, 3/100), (46/125, -3/100), (1431/4000, -9/400), (1349/4000, -3/400), (327/1000, 0), (41/125, 0), (1271/4000, 3/400), (1189/4000, 9/400), (287/1000, 3/100), (373/1000, -3/100), (1451/4000, -9/400), (1369/4000, -3/400), (83/250, 0), (333/1000, 0), (1291/4000, 3/400), (1209/4000, 9/400), (73/250, 3/100), (189/500, -3/100), (1471/4000, -9/400), (1389/4000, -3/400), (337/1000, 0), (169/500, 0), (1311/4000, 3/400), (1229/4000, 9/400), (297/1000, 3/100), (383/1000, -3/100), (1491/4000, -9/400), (1409/4000, -3/400), (171/500, 0), (343/1000, 0), (1331/4000, 3/400), (1249/4000, 9/400), (151/500, 3/100), (97/250, -3/100), (1511/4000, -9/400), (1429/4000, -3/400), (347/1000, 0), (87/250, 0), (1351/4000, 3/400), (1269/4000, 9/400), (307/1000, 3/100), (493/1000, -3/100), (1931/4000, -9/400), (1849/4000, -3/400), (113/250, 0), (453/1000, 0), (1771/4000, 3/400), (1689/4000, 9/400), (103/250, 3/100), (249/500, -3/100), (1951/4000, -9/400), (1869/4000, -3/400), (457/1000, 0), (229/500, 0), (1791/4000, 3/400), (1709/4000, 9/400), (417/1000, 3/100), (503/1000, -3/100), (1971/4000, -9/400), (1889/4000, -3/400), (231/500, 0), (463/1000, 0), (1811/4000, 3/400), (1729/4000, 9/400), (211/500, 3/100), (127/250, -3/100), (1991/4000, -9/400), (1909/4000, -3/400), (467/1000, 0), (117/250, 0), (1831/4000, 3/400), (1749/4000, 9/400), (427/1000, 3/100), (513/1000, -3/100), (2011/4000, -9/400), (1929/4000, -3/400), (59/125, 0), (473/1000, 0), (1851/4000, 3/400), (1769/4000, 9/400), (54/125, 3/100), (259/500, -3/100), (2031/4000, -9/400), (1949/4000, -3/400), (477/1000, 0), (239/500, 0), (1871/4000, 3/400), (1789/4000, 9/400), (437/1000, 3/100), (523/1000, -3/100), (2051/4000, -9/400), (1969/4000, -3/400), (241/500, 0), (483/1000, 0), (1891/4000, 3/400), (1809/4000, 9/400), (221/500, 3/100), (66/125, -3/100), (2071/4000, -9/400), (1989/4000, -3/400), (487/1000, 0), (61/125, 0), (1911/4000, 3/400), (1829/4000, 9/400), (447/1000, 3/100), (533/1000, -3/100), (2091/4000, -9/400), (2009/4000, -3/400), (123/250, 0), (493/1000, 0), (1931/4000, 3/400), (1849/4000, 9/400), (113/250, 3/100), (269/500, -3/100), (2111/4000, -9/400), (2029/4000, -3/400), (497/1000, 0), (249/500, 0), (1951/4000, 3/400), (1869/4000, 9/400), (457/1000, 3/100), (1, 0))
sage: pv = ((0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0), (1, 0), (-1, 0), (0, 0), (0, 0))
sage: bkpts = [b[0]+b[1]*sqrt2 for b in pb]
sage: values = [v[0]+v[1]*sqrt2 for v in pv]
sage: p = piecewise_function_from_breakpoints_and_values(bkpts, values)
sage: h1 = h + 8/10000*p
sage: minimality_test(h1)
INFO: ...
True
sage: h2 = h - 8/10000*p
sage: minimality_test(h2)
INFO: ...
True
__module__ = 'cutgeneratingfunctionology.igp'
_construct_function(f=4/5, d1=3/5, d2=1/10, a0=3/20, delta=(1/200, 1/200*sqrt(2)), field=None)

Construct the function.

class cutgeneratingfunctionology.igp.ParametricFamily_bhk_slant_irrational(constructor, default_values, names)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily

_images/igp-5.svg

A version of the irrational function with non-zero second slope

Parameters:
  • f (real) \(\in (0,1)\);
  • d1 (real): length of the positive slopes;
  • d2 (real): length of the slant (c2) slopes;
  • a0 (real): length of the first zig-zag;
  • delta (n-tuple of reals): length of the extra zig-zags.
  • c2 (real): slant slope, c2 = 0 in bhk_irrational()
Function is known to be extreme under the conditions:
  • 0 < f < 1;
  • d1, d2, a0, delta > 0;
  • d1 + d2 < f;
  • len(delta) == 2
  • sum(delta) < d2 / 4; Weaker condition: 2*delta[0] + delta[1] < d2 / 2;
  • the two components of delta are linearly independent over Q.
  • (?? sufficient ??) -1 / (1 - f) <= c2 <= (1 - d1 - d2) / (d1 + d2) / (1 - f);
Also needs:
  • sum(delta) < (f/2 - d2/4 - 3*a0/2) * c1 / (c1-c2);
  • 5*a0 > 2*(c1-c2)/(c1-c3) * d2 + d2 / 2 + d1.
  • d?? > 0
Relation between the code parameters and the paper parameters:
  • t1 = delta[0], t2 = delta[0] + delta[1], …
  • a1 = a0 + t1, a2 = a0 + t2, …
  • A = f/2 - a0/2 - d2/4,
  • A0 = f/2 - a0/2 + d2/4.

Examples:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = bhk_slant_irrational(f=4/5, d1=3/5, d2=1/10, a0=15/100, delta=(1/200, sqrt(2)/200), c2=1/16)
sage: h2 = bhk_gmi_irrational(f=4/5, d1=3/5, d2=1/10, a0=15/100, delta=(1/200, sqrt(2)/200), alpha=95/100)
sage: h == h2
True

Bug example (function is not minimal):

sage: h3 = bhk_irrational(f=4/5, d1=3/5, d2=1/10, a0=40/180, delta=(1/400, sqrt(2)/400))
sage: minimality_test(h3)
False
__module__ = 'cutgeneratingfunctionology.igp'
_construct_function(f=4/5, d1=3/5, d2=1/10, a0=3/20, delta=(1/200, 1/200*sqrt(2)), c2=0, field=None)

Construct the function.

class cutgeneratingfunctionology.igp.ParametricFamily_chen_4_slope(constructor, default_values, names)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily

_images/igp-6.svg

This 4-slope function is shown [KChen_thesis] to be a facet.

Parameters:
  • f (real) \(\in (0,1)\);
  • s_pos, s_neg (real): positive slope and negative slope
  • lam1, lam2 (real).

Function is claimed to be extreme under the following conditions, according to literature [KChen_thesis]:

  • 1/2 <= f < 1;
  • s_pos >= 1/f;
  • s_neg <= 1/(f - 1);
  • 0 <= lam1 < min(1/2, (s_pos - s_neg) / s_pos / (1 - s_neg * f));
  • f - 1 / s_pos < lam2 < min(1/2, (s_pos - s_neg) / s_neg / (s_pos * (f - 1) - 1)).
Note:

The lower bound 0 < lam1 claimed in [KChen_thesis] is not sufficient for extremality. The following example satisfies the extremality conditions according to [KChen_thesis], however it violates the subadditivity, and thus is not an extreme function:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = chen_4_slope(f=7/10, s_pos=2, s_neg=-4, lam1=1/100, lam2=49/100, condition_according_to_literature=True)
sage: h._claimed_parameter_attribute
'extreme'
sage: extremality_test(h, False)
False

On the other hand, the hypotheses stated by Chen are also not necessary for extremality. For example, the following function does not satisfy the hypotheses, however it is extreme:

sage: h = chen_4_slope(f=7/10, s_pos=2, s_neg=-4, lam1=1/10, lam2=1/10, condition_according_to_literature=True)
sage: h._claimed_parameter_attribute
'constructible'
sage: extremality_test(h, False)
True
We propose to revised the conditions for extremality, as follows.
s_pos >= 1/f; s_neg <= 1/(f - 1); lam1 <= 1/2; lam2 <= 1/2; ((f*s_pos-1) * (1-f*s_neg)) * lam1 <= (s_pos-s_neg) * lam2; ((f-1)*s_neg-1) * (1+(1-f)*s_pos) * lam2 <= (s_pos-s_neg) * lam1.
Examples:

[KChen_thesis] p.38, fig.8:

sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = chen_4_slope(f=7/10, s_pos=2, s_neg=-4, lam1=1/4, lam2=1/4)
sage: extremality_test(h, False)
True

sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = chen_4_slope(f=1/2, s_pos=4, s_neg=-4, lam1=1/3, lam2=1/3)
sage: extremality_test(h, False)
True

The following parameters do not satisfy the requirement, however the function is extreme:

sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = chen_4_slope(f=1/2, s_pos=5, s_neg=-5, lam1=1/5, lam2=1/5)
sage: extremality_test(h, False)
True
Reference:
[KChen_thesis]: K. Chen, Topics in group methods for integer programming,
Ph.D. thesis, Georgia Institute of Technology, June 2011.
__module__ = 'cutgeneratingfunctionology.igp'
_construct_function(f=7/10, s_pos=2, s_neg=-4, lam1=1/4, lam2=1/4, field=None, conditioncheck=True, condition_according_to_literature=False, merge=True)

Construct the function.

class cutgeneratingfunctionology.igp.ParametricFamily_chen_4_slope_reworded(constructor, default_values, names)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily

__module__ = 'cutgeneratingfunctionology.igp'
_construct_function(f=7/10, aa=19/240, a=7/80, c=77/80, cc=29/30, field=None, conditioncheck=True, condition_according_to_literature=False, merge=False)

Construct the function.

class cutgeneratingfunctionology.igp.ParametricFamily_cpl_n_group_function(n, cpleq, merge, theta)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily_base

A parametric family of CPL functions.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: cpl3 = cpl_n_group_function(3); cpl3
ParametricFamily_cpl_n_group_function(3, cpleq=False, merge=True, theta=None)
sage: cpl3 is cpl_n_group_function(3, False)
True
sage: cpl3.names()
['f', 'z1', 'z2']
sage: h = cpl3(f=1/6, z=(1/12, 1/12), o=(1/5, 0))
sage: extremality_test(h)
True

Omit the argument o, then it takes the mapping self._theta. With the default value of self._theta, it creates a gmic function:

sage: g = cpl3(1/6, (1/12, 1/12))
sage: g == gmic(1/6)
True

Change self._theta:

sage: cpl3_150 = cpl_n_group_function(3, theta = lambda f, z: (1/5, 0))
sage: hh = cpl3_150(1/6, (1/12, 1/12))
sage: h == hh
True
static __classcall__(cls, n, cpleq=False, merge=True, theta=None)

Normalize arguments for unique representation purposes.

__init__(n, cpleq, merge, theta)

x.__init__(…) initializes x; see help(type(x)) for signature

__module__ = 'cutgeneratingfunctionology.igp'
_default_theta_cpl(f, z)
_default_theta_cpleq(f, z)
_element_constructor_(f, z, o=None, field=None)

The preferred calling method of this parametric family.

args_from_point(point, **options)

Return a dictionary of arguments suitable for _element_constructor_, corresponding to point in the parameter_space.

class cutgeneratingfunctionology.igp.ParametricFamily_dg_2_step_mir(constructor, default_values, names)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily

_images/igp-7.svg
Summary:
  • Name: Dash-Gunluk’s 2-Step MIR;
  • Infinite (or Finite); Dim = 1; Slopes = 2; Continuous; Simple sets method;
  • Discovered [33] p.39 def.8, Fig.5;
  • Proven extreme (for infinite group) [60] p.377, thm.3.3.
  • dg_2_step_mir is a facet.
Parameters:
  • f (real) in (0,1);
  • alpha (real) in (0,f).
Function is known to be extreme under the conditions:
  • 0 < alpha < f < 1;
  • f / alpha < ceil(f / alpha) <= 1 / alpha.

Examples: [33] p.40, Fig.5

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = dg_2_step_mir(f=4/5, alpha=3/10)
sage: extremality_test(h, False)
True
Reference:
[33]: S. Dash and O. Gunluk, Valid inequalities based on simple mixed-integer sets.,
Proceedings 10th Conference on Integer Programming and Combinatorial Optimization (D. Bienstock and G. Nemhauser, eds.), Springer-Verlag, 2004, pp. 33-45.

[60]: R.E. Gomory and E.L. Johnson, Some continuous functions related to corner polyhedra, part II, Mathematical Programming 3 (1972) 359-389.

__module__ = 'cutgeneratingfunctionology.igp'
_claimed_parameter_attribute(f, alpha, **kwargs)

Describe what the literature claims about the function.

Return ‘not_constructible’, ‘constructible’, ‘minimal’, or ‘extreme’.

_construct_function(f=4/5, alpha=3/10, field=None, conditioncheck=True)

Construct the function.

class cutgeneratingfunctionology.igp.ParametricFamily_dg_2_step_mir_limit(constructor, default_values, names)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily

_images/igp-8.svg
Summary:
  • Name: Dash-Gunluk 2-Step MIR Limit;
  • Infinite; Dim = 1; Slopes = 1; Discontinuous; Simple sets method;
  • Discovered [33] p.41, def.12;
  • Proven extreme [33] p.43, lemma 14.
  • dg_2_step_mir_limit is a facet.
Parameters:
  • f (real) \(\in (0,1)\);
  • d (positive integer): number of slopes on [0,f).
Function is known to be extreme under the conditions:
  • 0 < f < 1;
  • d >= ceil(1 / (1 - f)) - 1.
Note:

This is the limit function as alpha in dg_2_step_mir() tends (from left) to f/d, where d is integer; cf. [33] p.42, lemma 13.

It’s a special case of drlm_2_slope_limit():

dg_2_step_mir_limit(f, d) = multiplicative_homomorphism(drlm_2_slope_limit(f=1-f, nb_pieces_left=1, nb_pieces_right=d), -1).

Examples: [33] p.42, Fig.6

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN) # Suppress warning about experimental discontinuous code.
sage: h = dg_2_step_mir_limit(f=3/5, d=3)
sage: extremality_test(h, False)
True
Reference:
[33]: S. Dash and O. Gunluk, Valid inequalities based on simple mixed-integer sets.,
Proceedings 10th Conference on Integer Programming and Combinatorial Optimization (D. Bienstock and G. Nemhauser, eds.), Springer-Verlag, 2004, pp. 33-45.
__module__ = 'cutgeneratingfunctionology.igp'
_claimed_parameter_attribute(f, d, **kwargs)

Describe what the literature claims about the function.

Return ‘not_constructible’, ‘constructible’, ‘minimal’, or ‘extreme’.

_construct_function(f=3/5, d=3, field=None, **kwds)

Construct the function.

class cutgeneratingfunctionology.igp.ParametricFamily_drlm_2_slope_limit(constructor, default_values, names)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily

_images/igp-9.svg
Summary:
  • Name: Dey–Richard–Li–Miller’s 2-Slope Limit;
  • Infinite; Dim = 1; Slopes = 1; Discontinuous; Group relations method;
  • Discovered [40] p.158 def.10;
  • Proven extreme [40] p.159 thm.8.
  • (Although only extremality has been established in literature, the same proof shows that) drlm_2_slope_limit is a facet.
Parameters:
  • f (real) \(\in (0,1)\);
  • nb_pieces_left (positive integer) : number of linear pieces to the left of f;
  • nb_pieces_right (positive integer) : number of linear pieces to the right of f.
Function is known to be extreme under the conditions:
nb_pieces_left * (1-f) <= nb_pieces_right * f.
Examples:

[40] p.159 Fig.4

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN) # Suppress warning about experimental discontinuous code.
sage: h = drlm_2_slope_limit(f=3/5, nb_pieces_left=3, nb_pieces_right=4)
sage: extremality_test(h, False)
True
Reference:
[40]: S.S. Dey, J.-P.P. Richard, Y. Li, and L.A. Miller, On the extreme inequalities of infinite group problems,
Mathematical Programming 121 (2010) 145-170.
__module__ = 'cutgeneratingfunctionology.igp'
_construct_function(f=3/5, nb_pieces_left=3, nb_pieces_right=4, field=None, conditioncheck=True)

Construct the function.

class cutgeneratingfunctionology.igp.ParametricFamily_drlm_3_slope_limit(constructor, default_values, names)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily

_images/igp-10.svg
Summary:
  • Name: Dey–Richard–Li–Miller’s 3-Slope Limit;
  • Infinite; Dim = 1; Slopes = 2; Discontinuous; Group relations method;
  • Discovered [40] p.161 def.11;
  • Proven extreme [40] p.161 thm.9.
  • (Although only extremality has been established in literature, the same proof shows that) drlm_3_slope_limit is a facet.
Parameters:
f (real) \(\in (0,1)\);
Function is known to be extreme under the conditions:
0 < f < 1/3.
Note:
This is the limit function as bkpt tends to f in drlm_backward_3_slope(f, bkpt).
Examples:

[40] p.162 Fig.5

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN) # Suppress warning about experimental discontinuous code.
sage: h = drlm_3_slope_limit(f=1/5)
sage: extremality_test(h, False)
True
Reference:
[40]: S.S. Dey, J.-P.P. Richard, Y. Li, and L.A. Miller, On the extreme inequalities of infinite group problems,
Mathematical Programming 121 (2010) 145-170.
__module__ = 'cutgeneratingfunctionology.igp'
_construct_function(f=1/5, field=None, conditioncheck=True)

Construct the function.

class cutgeneratingfunctionology.igp.ParametricFamily_drlm_backward_3_slope(constructor, default_values, names)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily

_images/igp-11.svg
Summary:
  • Name: Dey–Richard–Li–Miller’s Backward 3-Slope;
  • Infinite; Dim = 1; Slopes = 3; Continuous; Group relations method;
  • Discovered [40] p.154 eq.5;
  • Proven [40] p.153 thm.6.
  • (Although only extremality has been established in literature, the same proof shows that) drlm_backward_3_slope is a facet.
Parameters:
f, bkpt (real) \(\in (0,1)\).
Function is known to be extreme under the conditions:
f < bkpt < (1+f)/4 < 1.
Note:

In [40], they require that f, bkpt are rational numbers. The proof is based on interpolation of finite cyclic group extreme functions(cf. [8]), so it needs rational numbers. But in fact, by analysing covered intervals and using the condition f < bkpt <= (1+f)/4 < 1, one can prove that the function is extreme without assuming f, bkpt being rational numbers.

In [61] p.374, Appendix C, p.360. Fig.10, they consider real number f, bkpt, and claim (without proof) that:

  1. the function (named pi3(u)) is facet (thus extreme);
  2. can add a perturbation (zigzag) on the third slope as shown in Fig.10;

An extremality proof for the general (not necessarily rational) case appears in [KZh2015b, section 4].

Examples:
  • Finite group –> Example 3.8 in [8] p.386,

  • Infinite group –> Interpolation using Equation 5 from [40] p.154

    sage: from cutgeneratingfunctionology.igp import *
    sage: h = drlm_backward_3_slope(f=1/12, bkpt=2/12)
    sage: extremality_test(h, False)
    True
    sage: h = drlm_backward_3_slope(f=1/12, bkpt=3/12)
    sage: extremality_test(h, False)
    True
    

References:

  • [8] J. Araoz, L. Evans, R.E. Gomory, and E.L. Johnson, Cyclic groups and knapsack facets, Mathematical Programming 96 (2003) 377-408.
  • [40] S.S. Dey, J.-P.P. Richard, Y. Li, and L.A. Miller, On the extreme inequalities of infinite group problems, Mathematical Programming 121 (2010) 145-170.
  • [61] R.E. Gomory and E.L. Johnson, T-space and cutting planes, Mathematical Programming 96 (2003) 341-375.
  • [KZh2015b] M. Koeppe and Y. Zhou, An electronic compendium of extreme functions for the Gomory-Johnson infinite group problem, Operations Research Letters, 2015, http://dx.doi.org/10.1016/j.orl.2015.06.004
__module__ = 'cutgeneratingfunctionology.igp'
_construct_function(f=1/12, bkpt=1/6, field=None, conditioncheck=True)

Construct the function.

class cutgeneratingfunctionology.igp.ParametricFamily_gj_2_slope(constructor, default_values, names)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily

_images/igp-12.svg
Summary:
  • Name: Gomory–Johnson’s 2-Slope;
  • Infinite (or Finite); Dim = 1; Slopes = 2; Continuous; Analysis of subadditive polytope method;
  • Discovered [61] p.352, Fig.5, construction 1;
  • Proven extreme (infinite group) [60] p.377, thm.3.3; [61] p.352, thm.4; p.354, thm.5.
  • gj_2_slope is a facet.
Parameters:
  • f (real) \(\in (0,1)\);
  • lambda_1 (real) in (0,1].
Function is known to be extreme under the conditions:
  • 0 < lambda_1 <=1,
  • lambda_1 < f/(1 - f).

Examples: [61] p.354, Fig.6

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = gj_2_slope(f=3/5, lambda_1=1/6)
sage: extremality_test(h, False)
True
sage: h = gj_2_slope(f=3/5, lambda_1=1/2)
sage: extremality_test(h, False)
True
sage: h = gj_2_slope(f=3/5, lambda_1=1)
sage: extremality_test(h, False, f=3/5)         # Provide f to suppress warning
True
Reference:

[60]: R.E. Gomory and E.L. Johnson, Some continuous functions related to corner polyhedra, part II, Mathematical Programming 3 (1972) 359-389.

[61]: R.E. Gomory and E.L. Johnson, T-space and cutting planes, Mathematical Programming 96 (2003) 341-375.

__module__ = 'cutgeneratingfunctionology.igp'
_construct_function(f=3/5, lambda_1=1/6, field=None, conditioncheck=True)

Construct the function.

class cutgeneratingfunctionology.igp.ParametricFamily_gj_2_slope_repeat(constructor, default_values, names)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily

_images/igp-13.svg
Summary:
  • Name: Gomory–Johnson’s 2-Slope-repeat;
  • Infinite (or Finite); Dim = 1; Slopes = 2; Continuous; Analysis of subadditive polytope method;
  • Discovered [61] p.354, Fig.7, construction 2;
  • Proven extreme (for infinite group) [60] p.377, thm.3.3; [61] p.354, thm.5; p.355, thm.6.
  • gj_2_slope_repeat is a facet.
Parameters:
  • f (real) \(\in (0,1)\);
  • s_positive, s_negative (real);
  • m, n >= 2 (integer).
Function is known to be extreme under the conditions:
  • \(0 < f < 1\);
  • s_positive > 1/f; s_negative < 1/(f - 1);
  • m >= (s_positive - s_positive*s_negative*f) / (s_positive - s_negative);
  • n >= (- s_negative + s_positive*s_negative*(f - 1)) / (s_positive - s_negative).

Examples: [61] p.354, Fig.7

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = gj_2_slope_repeat(f=3/5, s_positive=4, s_negative=-5, m=4, n=3)
sage: extremality_test(h, False)
True
Reference:

[60]: R.E. Gomory and E.L. Johnson, Some continuous functions related to corner polyhedra, part II, Mathematical Programming 3 (1972) 359-389.

[61]: R.E. Gomory and E.L. Johnson, T-space and cutting planes, Mathematical Programming 96 (2003) 341-375.

__module__ = 'cutgeneratingfunctionology.igp'
_construct_function(f=3/5, s_positive=4, s_negative=-5, m=4, n=3, field=None, conditioncheck=True)

Construct the function.

class cutgeneratingfunctionology.igp.ParametricFamily_gj_forward_3_slope(constructor, default_values, names)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily

_images/igp-14.svg
Summary:
  • Name: Gomory–Johnson’ Forward 3-Slope;
  • Infinite (or Finite); Dim = 1; Slopes = 3; Continuous; Analysis of subadditive polytope method;
  • Discovered [61] p.359, Construction.3, Fig.8;
  • Proven extreme [61] p.359, thm.8.
  • gj_forward_3_slope is a facet.
Parameters:
  • f (real) \(\in (0,1)\);
  • lambda_1, lambda_2 (real) \(\in (0,1)\).
Function is known to be extreme under the conditions:
  • 0 <= lambda_1 <= 1/2;
  • 0 <= lambda_2 <= 1 (in literature).
Note:

Since the domain and range are in [0,1], I think the conditions for a three-slope extreme function should be:

(0 <= lambda_1 <= 1/2) & (0 <= lambda_2 <= 1) & (0 < lambda_1 * f + lambda_2 * (f - 1) < lambda_1 * f).

Examples:

[61] p.360, Fig.8

sage: from cutgeneratingfunctionology.igp import *
sage: h = gj_forward_3_slope(f=4/5, lambda_1=4/9, lambda_2=1/3)
sage: extremality_test(h, False)
True
sage: h = gj_forward_3_slope(f=4/5, lambda_1=4/9, lambda_2=2/3)
sage: extremality_test(h, False)
True
sage: h = gj_forward_3_slope(f=4/5, lambda_1=4/9, lambda_2=1)
sage: extremality_test(h, False)
True

Try irrational case

sage: h = gj_forward_3_slope(f=sqrt(17)/5, lambda_1=2*sqrt(5)/9, lambda_2=2/sqrt(10))
sage: extremality_test(h, False)
True
Reference:
[61]: R.E. Gomory and E.L. Johnson, T-space and cutting planes, Mathematical Programming 96 (2003) 341-375.
__module__ = 'cutgeneratingfunctionology.igp'
_construct_function(f=4/5, lambda_1=4/9, lambda_2=2/3, field=None, conditioncheck=True)

Construct the function.

class cutgeneratingfunctionology.igp.ParametricFamily_gmic(constructor, default_values, names)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily

_images/igp-15.svg
Summary:
  • Name: GMIC (Gomory mixed integer cut);
  • Infinite (or Finite); Dim = 1; Slopes = 2; Continuous; Analysis of subadditive polytope method;
  • Discovered [55] p.7-8, Eq.8;
  • Proven extreme (for infinite group) [60] p.377, thm.3.3; (finite group) [57] p.514, Appendix 3.
  • (Although only extremality has been established in literature, the same proof shows that) gmic is a facet.
Parameters:
f (real) \(\in (0,1)\).
Examples:

[61] p.343, Fig. 1, Example 1

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = gmic(4/5)
sage: extremality_test(h, False)
True
Reference:

[55]: R.E. Gomory, An algorithm for the mixed integer problem, Tech. Report RM-2597, RAND Corporation, 1960.

[57]: R.E. Gomory, Some polyhedra related to combinatorial problems, Linear Algebra and its Application 2 (1969) 451-558.

[60]: R.E. Gomory and E.L. Johnson, Some continuous functions related to corner polyhedra, part II, Mathematical Programming 3 (1972) 359-389.

[61]: R.E. Gomory and E.L. Johnson, T-space and cutting planes, Mathematical Programming 96 (2003) 341-375.

__module__ = 'cutgeneratingfunctionology.igp'
_construct_function(f=4/5, field=None, conditioncheck=True)

Construct the function.

class cutgeneratingfunctionology.igp.ParametricFamily_kf_n_step_mir(constructor, default_values, names)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily

_images/igp-16.svg
Summary:
  • Name: Kianfar-Fathi’s n-Step MIR;
  • Infinite (or Finite); Dim = 1; Slopes = 2; Continuous; Simple sets method;
  • Discovered [74] p.328, def.3, thm.2;
  • Proven extreme (for infinite group) [60] p.377, thm.3.3.
  • (Although only extremality has been established in literature, the same proof shows that) kf_n_step_mir is a facet.
Parameters:
  • f (real) \(\in (0,1)\);
  • a (list of reals, with length = n) \(\in (0,f)\).
Function is known to be extreme under the conditions:
  • 0 < a[1] < f < 1 == a[0];
  • a[i] > 0, for i = 0, 1, … , n-1;
  • b[i - 1] / a[i] < ceil(b[i - 1] / a[i]) <= a[i - 1] / a[i], for i = 1, 2, … , n-1;
where,
  • b[0] = f;
  • b[i] = b[i - 1] - a[i] * floor(b[i - 1] / a[i]), for i = 1, 2, … , n-1.
Note:
if a[i] > b[i-1] for some i, then the kf_n_step_mir function degenerates, i.e. kf_n_step_mir(f, [a[0], .. , a[n - 1]]) = kf_n_step_mir(f, [a[0], .. a[i - 1], a[i + 1], … , a[n - 1]])

Examples: [74] p.333 - p.335, Fig.1 - Fig.6

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = kf_n_step_mir(f=4/5, a=[1])
sage: extremality_test(h, False)
True
sage: h = kf_n_step_mir(f=4/5, a=[1, 3/10])
sage: extremality_test(h, False)
True
sage: h = kf_n_step_mir(f=4/5, a=[1, 3/10, 8/100])
sage: extremality_test(h, False)
True
sage: h = kf_n_step_mir(f=4/5, a=[1, 3/10, 8/100, 3/100])
sage: extremality_test(h, False)
True
sage: h = kf_n_step_mir(f=4/5, a=[1, 45/100, 2/10, 558/10000, 11/1000])
sage: extremality_test(h, False)
True
sage: h = kf_n_step_mir(f=4/5, a=[1, 48/100, 19/100, 8/100, 32/1000, 12/1000])
sage: extremality_test(h, False)
True
Reference:

[60]: R.E. Gomory and E.L. Johnson, Some continuous functions related to corner polyhedra, part II, Mathematical Programming 3 (1972) 359-389.

[74]: K. Kianfar and Y. Fathi, Generalized mixed integer rounding valid inequalities:
Facets for infinite group polyhedra, Mathematical Programming 120 (2009) 313-346.
__module__ = 'cutgeneratingfunctionology.igp'
_claimed_parameter_attribute(f, a, **kwargs)

Describe what the literature claims about the function.

Return ‘not_constructible’, ‘constructible’, ‘minimal’, or ‘extreme’.

_construct_function(f=4/5, a=(1, 3/10, 2/25), field=None, conditioncheck=True)

Construct the function.

class cutgeneratingfunctionology.igp.ParametricFamily_kzh_3_slope_param_extreme_1(constructor, default_values, names)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily

_images/igp-17.svg

New extreme function discovered by computer based search followed by parametric search. It has 3 slopes in the general case.

Parameters: real numbers \(f\), \(a\), \(b\), where \(a\) is the length of the first interval right to \(f\) and \(b\) is the length of interval centered at \((1+f)/2\).

Function is known to be extreme under the conditions:
0 <= a and 0 <= b <= f and 3*f+4*a-b-1 <= 0

Examples:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = kzh_3_slope_param_extreme_1(f=6/19, a=1/19, b=5/19)
sage: extremality_test(h)
True
sage: h = kzh_3_slope_param_extreme_1(f=1/3, a=1/18, b=1/4)
sage: extremality_test(h)
True
__module__ = 'cutgeneratingfunctionology.igp'
_construct_function(f=6/19, a=1/19, b=5/19, field=None, conditioncheck=True)

Construct the function.

class cutgeneratingfunctionology.igp.ParametricFamily_kzh_3_slope_param_extreme_2(constructor, default_values, names)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily

_images/igp-18.svg

New extreme function discovered by computer based search followed by parametric search. The function looks like gj_forward_3_slope + drlm_backward_3_slope.

Parameters: real numbers \(f\), \(a\), \(b\), where \(a\) is the length of interval centered at \(f/2\), and \(b\) is the length of interval centered at \((1+f)/2\).

Function is known to be extreme under the (sufficient) conditions:
0 < a < f < 1; 2*b - a <= f <= a + b and f <= (1+a-b)/2

Examples:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = kzh_3_slope_param_extreme_2(f=5/9, a=3/9, b=2/9)
sage: extremality_test(h)
True
sage: h = kzh_3_slope_param_extreme_2(f=4/9, a=2/9, b=3/9)
sage: extremality_test(h) # Claimed conditions for extremality are NOT satisfied.
True
sage: h = kzh_3_slope_param_extreme_2(5/9, 2/5, 7/20)
sage: extremality_test(h)
False
__module__ = 'cutgeneratingfunctionology.igp'
_construct_function(f=5/9, a=1/3, b=2/9, field=None, conditioncheck=True)

Construct the function.

class cutgeneratingfunctionology.igp.ParametricFamily_kzh_4_slope_param_extreme_1(constructor, default_values, names)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily

_images/igp-19.svg

New extreme function discovered by computer based search followed by parametric search. The function looks like gj_forward_3_slope + kzh_3_slope_param_extreme_1.

Parameters: real numbers \(f\), \(a\), \(b\), where \(a\) is the length of interval centered at \(f/2\), and \(b\) is the first bkpt, which is also the length of interval centered at \((1+f)/2\).

Function is known to be extreme under the (sufficient) conditions:
a > max{3*f-2, f/2}; b > 0; a + 3*b > 2*f - 1; 2*a + 3*b < 3*f - 1.

Examples:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = kzh_4_slope_param_extreme_1(f=13/18, a=7/18, b=1/18)
sage: extremality_test(h)
True
sage: h = kzh_4_slope_param_extreme_1(f=13/18, a=14/37, b=1/19)
sage: extremality_test(h)
True
__module__ = 'cutgeneratingfunctionology.igp'
_construct_function(f=13/18, a=7/18, b=1/18, field=None, conditioncheck=True)

Construct the function.

class cutgeneratingfunctionology.igp.ParametricFamily_ll_strong_fractional(constructor, default_values, names)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily

_images/igp-20.svg

Letchford–Lodi’s strong fractional cut.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = ll_strong_fractional(f=2/3)
sage: extremality_test(h, False)
True
sage: h = ll_strong_fractional(f=2/7)
sage: minimality_test(h, False)
False
Reference:
[78] Letchford-Lodi (2002) Thm. 2, Fig. 3 (but note this figure shows the wrong function;
see ll_strong_fractional_bad_figure_3 and ll_strong_fractional_bad_figure_3_corrected)

[33] S. Dash and O. Gunluk (2004) Thm. 16

Remarks:

Discontinuous, 1-slope;

For f >= 1/2, this function is facet (extreme), and is identical to drlm_2_slope_limit(f=f, nb_pieces_left=1, nb_pieces_right=1).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: f=2/3
sage: l = ll_strong_fractional(f)
sage: d = drlm_2_slope_limit(f=f, nb_pieces_left=1, nb_pieces_right=ceil(1/f)-1)
sage: dg = automorphism(dg_2_step_mir_limit(f=1-f, d=ceil(1/f)-1))
sage: show(plot(l, color='red', legend_label='ll_strong_fractional')) # not tested
sage: show(plot(d, color='blue', legend_label='drlm_2_slope_limit')) # not tested
sage: show(plot(dg, color='green', legend_label='automorphism(dg_2_step_mir_limit)')) # not tested
sage: l == d == dg
True
Remarks:
The function is NOT minimal for 0 < f < 1/2. It equals drlm_2_slope_limit(f=f, nb_pieces_left=1, nb_pieces_right=ceil(1/f)-1), except for limits at breakpoints.

EXAMPLES:

sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: f=1/3
sage: l = ll_strong_fractional(f)
sage: d = drlm_2_slope_limit(f=f, nb_pieces_left=1, nb_pieces_right=ceil(1/f)-1)
sage: dg = automorphism(dg_2_step_mir_limit(f=1-f, d=ceil(1/f)-1))
sage: show(plot(l, color='red', legend_label='ll_strong_fractional')) # not tested
sage: show(plot(d, color='blue', legend_label='drlm_2_slope_limit')) # not tested
sage: show(plot(dg, color='green', legend_label='automorphism(dg_2_step_mir_limit)')) # not tested
sage: d == dg
True
sage: l == d
False
__module__ = 'cutgeneratingfunctionology.igp'
_claimed_parameter_attribute(f, **kwargs)

Describe what the literature claims about the function.

Return ‘not_constructible’, ‘constructible’, ‘minimal’, or ‘extreme’.

_construct_function(f=2/3, field=None, conditioncheck=True)

Construct the function.

class cutgeneratingfunctionology.igp.ParametricFamily_psi_n_in_bccz_counterexample_construction(constructor, default_values, names)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily

Summary:
  • Name: psi_n in the construction of BCCZ’s counterexample to GJ’s conjecture;
  • Infinite; Dim = 1; Slopes = 2; Continuous; Analysis of subadditive polytope method.
  • Discovered [IR1] p.30, section.3, fig.1;
  • Proven extreme [IR1] p.35, thm.4.7.
Note:

The (uniform) limit \(\psi = \lim_{n to \infty} \psi_n\) is well defined if \(\sum_{i = 0}^{\infty} {2^i * e[i]} < f\).

The (uniform) limit psi is a continuous facet, but is not piecewise linear. A counterexample of GJ’s conjecture.

Could use the function generate_example_e_for_psi_n(f, n, q) to generate a sequence e that satisfies the conditions for extremality.

psi_n_in_bccz_counterexample_construction() is a special case of kf_n_step_mir(), with f=f, a = [1, (f + e[0])/2, (f - e[0] + 2*e[1])/4, …]

Parameters:
  • f (real) \(\in (0,1)\);
  • e (list of reals, with length = n) \(\in (0,f)\).
Function is known to be extreme under the conditions:
  • 0 < f < 1;
  • 0 < e[n - 1] <= e[n - 2] <= … <= e[1] <= e[0] <= 1 - f;
  • sum_{i = 0}^{n - 1} 2^i * e[i] < f.
Examples:

[IR1] p.30, fig.1:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = psi_n_in_bccz_counterexample_construction(f=2/3, e=[1/12, 1/24])
sage: extremality_test(h, False)
True
sage: h = psi_n_in_bccz_counterexample_construction(f=4/5, e=[1/5, 1/20, 1/80, 1/320, 1/1280])
sage: extremality_test(h, False, f=4/5)         # Suppress warning about non-unique f
True
sage: h = psi_n_in_bccz_counterexample_construction(f=4/5, e=generate_example_e_for_psi_n(f=4/5, n=7, q=3, eta=0))
sage: extremality_test(h, False)
True
sage: sum([plot(psi_n_in_bccz_counterexample_construction(e=generate_example_e_for_psi_n(n=n)), color=color, legend_label="psi_%d"%n) for n, color in zip(range(7),rainbow(7))]) # not tested
Reference:
[IR1]: A. Basu, M. Conforti, G. Cornuejols, and G. Zambelli, A counterexample to a conjecture of Gomory and Johnson,
Mathematical Programming Ser. A 133 (2012), 25-38.
__module__ = 'cutgeneratingfunctionology.igp'
_construct_function(f=2/3, e=(1/12, 1/24), field=None, conditioncheck=True)

Construct the function.

class cutgeneratingfunctionology.igp.ParametricFamily_rlm_dpl1_extreme_3a(constructor, default_values, names)

Bases: cutgeneratingfunctionology.igp.parametric_family.ParametricFamily

_images/igp-21.svg

From Richard–Li–Miller [RLM2009].

For 0 < f < 1/3, by Thm.28, the DPL1 function phi (whose corresponding h is shown on p.273, Fig.3-lowerleft) is “extreme” (not the usual definition).

See def.19 for the definition of DPLn, which is a special family of discontinuous piecewise linear functions. See Prop.18 and Fig 1 for relation between the DPLn representation \(\phi\) and the group representation \(\pi\), where \(\pi(u)\) is called \(f(u)\), and \(f\) is called \(r_0\) throughout this paper.

All we know from the paper is that \(\pi\) on p.273, Fig.3-lowerleft is subadditive. However, the extremality is unknown (see discussion after thm.28 p.272).

Indeed, the function rlm_dpl1_fig3_lowerleft(f) is a facet (and thus extreme) for any 0 < f < 1/3. This can be verified using the covered components and the additivity equations. (Specifically, 2 * pi(f+) = pi(2f+) and 2* pi((1+f) / 2 +) = pi(f+))

This is worked out in [KZh2015b, section 2].

Example: p.273, Fig.3-lowerleft

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN) # Suppress warning about experimental discontinuous code.
sage: h = rlm_dpl1_extreme_3a(f=1/4)
sage: extremality_test(h, False)
True

All other 3 functions (corresponding to phi from the DPL1 family) shown in Fig.3 are proven to be extreme. They are covered by drlm_3_slope_limit and drlm_2_slope_limit classes:

  • upper-left: drlm_3_slope_limit(1/3)
  • upper-right: drlm_2_slope_limit(f=3/5, nb_pieces_left=1, nb_pieces_right=1)
  • lower-right: drlm_2_slope_limit(f=3/5, nb_pieces_left=1, nb_pieces_right=2)

Reference:

[RLM2009]J.-P. P. Richard, Y. Li, and L. A. Miller, Valid inequalities for MIPs and group polyhedra from approximate liftings, Mathematical Programming 118 (2009), no. 2, 253-277, doi:10.1007/s10107-007-0190-9
[KZh2015b]M. Koeppe and Y. Zhou, An electronic compendium of extreme functions for the Gomory-Johnson infinite group problem, Operations Research Letters, 2015, http://dx.doi.org/10.1016/j.orl.2015.06.004
__module__ = 'cutgeneratingfunctionology.igp'
_construct_function(f=1/4, field=None, conditioncheck=True)

Construct the function.

class cutgeneratingfunctionology.igp.ParametricRealField(values=None, names=None, allow_coercion_to_float=True, mutable_values=None, allow_refinement=None, big_cells=None, base_ring=None, sym_ring=None, bsa=None)

Bases: sage.rings.ring.Field

A Metaprogramming trick for parameter space analysis.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: K.<f> = ParametricRealField([4/5])
sage: h = gmic(f, field=K)
sage: I_list = J_list = h.intervals()
sage: K_list = I_list + [ (a+1, b+1) for (a, b) in h.intervals() ]
sage: _ = [ verts(I, J, KK) for I in I_list for J in J_list for KK in K_list ]
sage: K.get_eq()
set()
sage: R = f._sym.parent().ring()
sage: sorted([ p for p in K.get_lt() if p in R ])   # filter out the rational function 1/(f^2 - f), which is normalized differently starting Sage 8.4b2
[-2*f, -2*f + 1, -f - 1, -f, f - 2, f - 1, 2*f - 2]
sage: K.get_eq_factor()
set()
sage: K.get_lt_factor()
{-f, -f + 1/2, f - 1}

sage: K.<f, lam> = ParametricRealField([4/5, 1/6])
sage: h = gj_2_slope(f, lam, field=K)
sage: K.get_lt()
{(-1/2)/(-1/2*f^2*lam - 1/2*f^2 + f*lam + 1/2*f - 1/2*lam),
 (-f*lam - f + lam)/(-f + 1),
 -lam,
 lam - 1,
 -f,
 f - 1,
 -1/2*f*lam - 1/2*f + 1/2*lam,
 f*lam - lam}
sage: K.get_lt_factor()
{-lam, lam - 1, -f, f - 1, -f*lam - f + lam}

sage: K.<f,alpha> = ParametricRealField([4/5, 3/10])
sage: h=dg_2_step_mir(f, alpha, field=K, conditioncheck=False)
sage: extremality_test(h)
True

sage: K.<f,a1,a2,a3> = ParametricRealField([4/5, 1, 3/10, 2/25])
sage: h = kf_n_step_mir(f, (a1, a2, a3), conditioncheck=False)
sage: extremality_test(h)
True

sage: K.<f> = ParametricRealField([1/5])
sage: h = drlm_3_slope_limit(f, conditioncheck=False)
sage: extremality_test(h)
True
sage: K.get_lt_factor()
{-f, f - 1, f - 1/2, f - 1/3}

Elements coerce to RDF, RR, float to enable plotting of functions:

sage: K.<f> = ParametricRealField([4/5])
sage: RDF(f)
0.8
sage: RR(f)
0.800000000000000
sage: float(f)
0.8
sage: 0.2 - f
-0.600000000000000

Plotting will show symbolic labels on the axes:

sage: plot_with_colored_slopes(gmic(f))
Graphics object...

But they do not coerce or convert into any exact fields:

sage: QQ(f)
Traceback (most recent call last):
...
TypeError: unable to convert f~ to a rational
sage: AA(f)
Traceback (most recent call last):
...
TypeError: Illegal initializer for algebraic number

Test that values can also be initialized by vectors (internally we make it tuples):

sage: f = vector(QQ, [1, 2])
sage: K.<f0, f1> = ParametricRealField(f)
sage: f = vector(f0.parent(), [f0, f1]); f
((f0)~, (f1)~)
sage: f.parent()
Vector space of dimension 2 over ParametricRealField(names = ['f0', 'f1'], values = [1, 2])
sage: f[0]*f[1] <= 4
True

Test-point free mode (limited functionality and MUCH slower because of many more polynoial evaluations via libsingular):

sage: K.<a, b> = ParametricRealField(None, mutable_values=True)
sage: a <= 2
Traceback (most recent call last):
...
FactorUndetermined: a cannot be evaluated because the test point is not complete
sage: K.assume_comparison(a.sym(), operator.le, 3)

Partial test point mode:

sage: K.<a, b> = ParametricRealField([None, 1], mutable_values=True)
sage: a <= 2
Traceback (most recent call last):
...
FactorUndetermined: a cannot be evaluated because the test point is not complete
sage: b <= 11
True
Element

alias of cutgeneratingfunctionology.spam.parametric_real_field_element.ParametricRealFieldElement

__copy__()
__dict__ = dict_proxy({'_first_ngens': <function _first_ngens>, '__module__': 'cutgeneratingfunctionology.igp', 'changed_values': <function changed_values>, 'get_lt': <function get_lt>, 'freeze': <function freeze>, 'change_test_point': <function change_test_point>, '_an_element_impl': <function _an_element_impl>, 'off_the_record': <function off_the_record>, '__dict__': <attribute '__dict__' of 'ParametricRealField' objects>, 'get_le': <function get_le>, 'is_point_consistent': <function is_point_consistent>, '__init__': <function __init__>, 'plot': <function plot>, 'get_eq': <function get_eq>, '_eval_factor': <function _eval_factor>, '_factor_sign': <function _factor_sign>, 'get_le_factor': <function get_le_factor>, 'get_eq_factor': <function get_eq_factor>, 'monomial_list': <function monomial_list>, 'v_dict': <function v_dict>, '__doc__': "\n A Metaprogramming trick for parameter space analysis.\n\n EXAMPLES::\n\n sage: from cutgeneratingfunctionology.igp import *\n sage: logging.disable(logging.INFO) # Suppress output in automatic tests.\n sage: K.<f> = ParametricRealField([4/5])\n sage: h = gmic(f, field=K)\n sage: I_list = J_list = h.intervals()\n sage: K_list = I_list + [ (a+1, b+1) for (a, b) in h.intervals() ]\n sage: _ = [ verts(I, J, KK) for I in I_list for J in J_list for KK in K_list ]\n sage: K.get_eq()\n set()\n sage: R = f._sym.parent().ring()\n sage: sorted([ p for p in K.get_lt() if p in R ]) # filter out the rational function 1/(f^2 - f), which is normalized differently starting Sage 8.4b2\n [-2*f, -2*f + 1, -f - 1, -f, f - 2, f - 1, 2*f - 2]\n sage: K.get_eq_factor()\n set()\n sage: K.get_lt_factor()\n {-f, -f + 1/2, f - 1}\n\n sage: K.<f, lam> = ParametricRealField([4/5, 1/6])\n sage: h = gj_2_slope(f, lam, field=K)\n sage: K.get_lt()\n {(-1/2)/(-1/2*f^2*lam - 1/2*f^2 + f*lam + 1/2*f - 1/2*lam),\n (-f*lam - f + lam)/(-f + 1),\n -lam,\n lam - 1,\n -f,\n f - 1,\n -1/2*f*lam - 1/2*f + 1/2*lam,\n f*lam - lam}\n sage: K.get_lt_factor()\n {-lam, lam - 1, -f, f - 1, -f*lam - f + lam}\n\n sage: K.<f,alpha> = ParametricRealField([4/5, 3/10])\n sage: h=dg_2_step_mir(f, alpha, field=K, conditioncheck=False)\n sage: extremality_test(h)\n True\n\n sage: K.<f,a1,a2,a3> = ParametricRealField([4/5, 1, 3/10, 2/25])\n sage: h = kf_n_step_mir(f, (a1, a2, a3), conditioncheck=False)\n sage: extremality_test(h)\n True\n\n sage: K.<f> = ParametricRealField([1/5])\n sage: h = drlm_3_slope_limit(f, conditioncheck=False)\n sage: extremality_test(h)\n True\n sage: K.get_lt_factor()\n {-f, f - 1, f - 1/2, f - 1/3}\n\n Elements coerce to RDF, RR, float to enable plotting of functions::\n\n sage: K.<f> = ParametricRealField([4/5])\n sage: RDF(f)\n 0.8\n sage: RR(f)\n 0.800000000000000\n sage: float(f)\n 0.8\n sage: 0.2 - f\n -0.600000000000000\n\n Plotting will show symbolic labels on the axes::\n\n sage: plot_with_colored_slopes(gmic(f))\n Graphics object...\n\n But they do not coerce or convert into any exact fields::\n\n sage: QQ(f)\n Traceback (most recent call last):\n ...\n TypeError: unable to convert f~ to a rational\n sage: AA(f)\n Traceback (most recent call last):\n ...\n TypeError: Illegal initializer for algebraic number\n\n Test that values can also be initialized by vectors (internally we make it tuples)::\n\n sage: f = vector(QQ, [1, 2])\n sage: K.<f0, f1> = ParametricRealField(f)\n sage: f = vector(f0.parent(), [f0, f1]); f\n ((f0)~, (f1)~)\n sage: f.parent()\n Vector space of dimension 2 over ParametricRealField(names = ['f0', 'f1'], values = [1, 2])\n sage: f[0]*f[1] <= 4\n True\n\n Test-point free mode (limited functionality and MUCH slower because of many more polynoial\n evaluations via libsingular)::\n\n sage: K.<a, b> = ParametricRealField(None, mutable_values=True)\n sage: a <= 2\n Traceback (most recent call last):\n ...\n FactorUndetermined: a cannot be evaluated because the test point is not complete\n sage: K.assume_comparison(a.sym(), operator.le, 3)\n\n Partial test point mode::\n\n sage: K.<a, b> = ParametricRealField([None, 1], mutable_values=True)\n sage: a <= 2\n Traceback (most recent call last):\n ...\n FactorUndetermined: a cannot be evaluated because the test point is not complete\n sage: b <= 11\n True\n\n ", '__repr__': <function __repr__>, 'remove_test_point': <function remove_test_point>, 'make_proof_cell': <function make_proof_cell>, 'is_factor_known': <function is_factor_known>, 'assume_comparison': <function assume_comparison>, 'unfrozen': <function unfrozen>, 'ppl_polyhedron': <function ppl_polyhedron>, 'change_values': <function change_values>, '_coerce_map_from_': <function _coerce_map_from_>, 'Element': <class 'cutgeneratingfunctionology.spam.parametric_real_field_element.ParametricRealFieldElement'>, 'removed_test_point': <function removed_test_point>, 'frozen': <function frozen>, 'characteristic': <function characteristic>, 'ngens': <function ngens>, 'get_lt_factor': <function get_lt_factor>, 'unfreeze': <function unfreeze>, 'temporary_assumptions': <function temporary_assumptions>, 'find_test_point': <function find_test_point>, '__copy__': <function __copy__>, 'record_factor': <function record_factor>})
__init__(values=None, names=None, allow_coercion_to_float=True, mutable_values=None, allow_refinement=None, big_cells=None, base_ring=None, sym_ring=None, bsa=None)

File: sage/rings/ring.pyx (starting at line 1702)

Initialize self.

INPUT:

  • category (default: None) – a category, or None

This method is used by all the abstract subclasses of IntegralDomain, like NoetherianRing, PrincipalIdealDomain, DedekindDomain, EuclideanDomain, Field, … in order to avoid cascade calls Field.__init__ -> PrincipalIdealDomain.__init__ -> IntegralDomain.__init__ -> …

EXAMPLES:

sage: F = IntegralDomain(QQ)
sage: F.category()
Category of integral domains

sage: F = PrincipalIdealDomain(QQ)
sage: F.category()
Category of principal ideal domains

sage: F = EuclideanDomain(QQ)
sage: F.category()
Category of euclidean domains

sage: F = Field(QQ)
sage: F.category()
Category of fields

If a category is specified, then the category is set to the join of that category with the default category:

sage: F = PrincipalIdealDomain(QQ, category=EnumeratedSets())

The default value for the category is specified by the class attribute default_category:

sage: IntegralDomain._default_category
Category of integral domains

sage: PrincipalIdealDomain._default_category
Category of principal ideal domains

sage: EuclideanDomain._default_category
Category of euclidean domains

sage: Field._default_category
Category of fields
__module__ = 'cutgeneratingfunctionology.igp'
__repr__()

File: sage/structure/sage_object.pyx (starting at line 145)

Default method for string representation.

Note

Do not overwrite this method. Instead, implement a _repr_ (single underscore) method.

EXAMPLES:

By default, the string representation coincides with the output of the single underscore _repr_:

sage: P.<x> = QQ[]
sage: repr(P) == P._repr_()  #indirect doctest
True

Using rename(), the string representation can be customized:

sage: P.rename('A polynomial ring')
sage: repr(P) == P._repr_()
False

The original behaviour is restored with reset_name().:

sage: P.reset_name()
sage: repr(P) == P._repr_()
True

If there is no _repr_ method defined, we fall back to the super class (typically object):

sage: from sage.structure.sage_object import SageObject
sage: S = SageObject()
sage: S
<sage.structure.sage_object.SageObject object at ...>
_an_element_impl(self)

File: sage/structure/parent_old.pyx (starting at line 254)

Return an element of self.

Want it in sufficient generality that poorly-written functions will not work when they are not supposed to. This is cached so does not have to be super fast.

_coerce_map_from_(S)

TESTS:

Test that elements of different ``ParametricRealField``s have no coercion.

sage: from cutgeneratingfunctionology.igp import * sage: logging.disable(logging.INFO) # Suppress output in automatic tests. sage: K.<a> = ParametricRealField([0]) sage: L.<b> = ParametricRealField([1]) sage: a + b Traceback (most recent call last): … TypeError: unsupported operand parent(s)…

Test that real number field elements can be upgraded to ParametricRealFieldElement``s. Note that this requires setting up the ParametricRealField with a specific base ring, because there is no common parent of QQ(x) and a RealNumberField:

sage: sqrt2, = nice_field_values([sqrt(2)])
sage: K.<f> = ParametricRealField([0], base_ring=sqrt2.parent())
sage: f + sqrt2
(f + 1.414213562373095?)~

This currently does not work for Sage’s built-in embedded number field elements…

_eval_factor(fac)

Evaluate fac on the test point.

If there is no test point or the test point has some None coordinates that are needed for the evaluation, raise FactorUndetermined.

_factor_sign(fac)

Determine the sign of fac evaluated on the test point.

If there is no test point or the test point has some None coordinates that are needed for the evaluation, raise FactorUndetermined.

_first_ngens(self, n)

File: sage/structure/category_object.pyx (starting at line 340)

Used by the preparser for R.<x> = ....

EXAMPLES:

sage: R.<x> = PolynomialRing(QQ)
sage: x
x
sage: parent(x)
Univariate Polynomial Ring in x over Rational Field

For orders, we correctly use the ring generator, see trac ticket #15348:

sage: A.<i> = ZZ.extension(x^2 + 1)
sage: i
i
sage: parent(i)
Order in Number Field in i with defining polynomial x^2 + 1
sage: B.<z> = EquationOrder(x^2 + 3)
sage: z.minpoly()
x^2 + 3
assume_comparison(lhs, op, rhs=0)

Record the assumption lhs op rhs.

If this assumption is not satisfied by the current test point, a ParametricRealFieldInconsistencyError is raised.

lhs and rhs should be elements of self._sym_field or be parametric elements (elements of self).

TESTS for consistency checks:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: K.<f> = ParametricRealField([4/5])
sage: K.assume_comparison(f.sym(), operator.gt, 1)
Traceback (most recent call last):
...
ParametricRealFieldInconsistencyError: New constraint...
sage: K.assume_comparison(K(0).sym(), operator.gt, 1)
Traceback (most recent call last):
...
ParametricRealFieldInconsistencyError: New constant constraint...

TESTS for consistency checks when testpoint values is None:

sage: K.<a,b> = ParametricRealField([2, 1], big_cells=True, mutable_values=True, allow_refinement=False)
sage: assert b>0
sage: K.remove_test_point()
sage: K.assume_comparison(b.sym(), operator.lt, 0)
Traceback (most recent call last):
...
ParametricRealFieldInconsistencyError...

User code should not rely on whether assumptions regarding the nonvanishing of denominators are recorded:

sage: K.<f> = ParametricRealField([4/5])
sage: assert f < 1
sage: K.freeze()
sage: K.assume_comparison(1/f.sym(), operator.gt, 1)   # not tested

Therefore, also the implicit cancellation in the field of rational functions does not change semantics when we transform lhs op rhs to lhs - rhs op 0:

sage: K.<f> = ParametricRealField([4/5])
sage: K.freeze()
sage: K.assume_comparison(1/f.sym(), operator.eq, 1/f.sym())

User code should call assume_comparison only for operands that do not have vanishing denominators.

sage: K.<f> = ParametricRealField([4/5]) sage: assert 0 < f < 1 sage: K.freeze() sage: K.assume_comparison(1/f.sym(), operator.gt, 1)

TEST that parametric elements are allowed:

sage: K.<f> = ParametricRealField([4/5])
sage: K.assume_comparison(f, operator.le, 1)
sage: K.get_le_factor()
{f - 1}

TESTS for allow_refinement=True:

Strict inequalities - even-multiplicity factors do matter:

sage: K.<f> = ParametricRealField([4/5])
sage: K.freeze()
sage: f^2 > 0
Traceback (most recent call last):
...
ParametricRealFieldFrozenError...

Weak inequalities:

sage: K.<f> = ParametricRealField([4/5], big_cells=True)
sage: f >= 4/5
True
sage: K.freeze()
sage: f == 4/5
Traceback (most recent call last):
...
ParametricRealFieldFrozenError...

sage: K.<f> = ParametricRealField([4/5], big_cells=True)
sage: f <= 4/5
True
sage: K.freeze()
sage: f == 4/5
Traceback (most recent call last):
...
ParametricRealFieldFrozenError...

Inequations:

sage: K.<f> = ParametricRealField([4/5], big_cells=True)
sage: assert f != 0
sage: K.get_lt_factor()
{-f}
sage: K.<f> = ParametricRealField([4/5], big_cells=False)
sage: assert f != 0
sage: K.get_lt_factor()
{-f}

TESTS for allow_refinement=False:

Strict inequalities:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: K.<f> = ParametricRealField([4/5], allow_refinement=False)
sage: f * (1 - f) > 0
Traceback (most recent call last):
...
ParametricRealFieldRefinementError...
sage: K.<f> = ParametricRealField([4/5], allow_refinement=False)
sage: f > 0
True
sage: 1 - f > 0
True

Strict inequalities - even-multiplicity factors do matter:

sage: K.<f> = ParametricRealField([4/5], allow_refinement=False)
sage: f^2 > 0
Traceback (most recent call last):
...
ParametricRealFieldRefinementError...

Equalities:

sage: K.<f> = ParametricRealField([4/5], allow_refinement=False)
sage: f * (f - 4/5) == 0
Traceback (most recent call last):
...
ParametricRealFieldRefinementError...
sage: f == 4/5
True
sage: f * (f - 4/5) == 0
True

sage: K.<f> = ParametricRealField([4], allow_refinement=False)
sage: f >= 3
True
sage: f * (f - 1) * (f - 2) * (f - 4) == 0
True

Weak inequalities:

sage: K.<f> = ParametricRealField([4/5], allow_refinement=False)
sage: f * (f - 4/5) >= 0
Traceback (most recent call last):
...
ParametricRealFieldRefinementError...
sage: f == 4/5
True
sage: f * (f - 4/5) >= 0
True

sage: K.<x,y> = ParametricRealField([2, 3], allow_refinement=False)
sage: x >= 2
True
sage: x^2 * (x - 1) * y >= 0
True

Weak inequalities - Even-multiplicity factors do matter:

sage: K.<o> = ParametricRealField([0], allow_refinement=False)
sage: o^2 <= 0
True
sage: K.freeze()
sage: o == 0
True

sage: K.<x> = ParametricRealField([0], allow_refinement=False)
sage: x^2 >= 0
True
sage: K.freeze()
sage: x == 0
Traceback (most recent call last):
...
ParametricRealFieldFrozenError...

sage: K.<f> = ParametricRealField([2], allow_refinement=False)
sage: f^2 * (1 - f) <= 0    # disjunction 0 union [1, oo).
Traceback (most recent call last):
...
ParametricRealFieldRefinementError...

Not-equal:

sage: K.<x> = ParametricRealField([1], allow_refinement=False)
sage: x != 0
Traceback (most recent call last):
...
ParametricRealFieldRefinementError...
sage: x >= 0
True
sage: x != 0
True

sage: K.<x> = ParametricRealField([-1], allow_refinement=False)
sage: x <= 0
True
sage: x != 0
True
Bug example::
sage: K.<f, bkpt> = ParametricRealField([1236451991/5178221721, 3733953/12155000], big_cells=True, allow_refinement=True) sage: for lhs in [2*f - 1, bkpt - 1, (-bkpt)/(f + 1), f - 1, -bkpt, bkpt/(-f - 1), -f + 2*bkpt - 1, (f - bkpt + 1)/(-f - 1), f + bkpt - 1, -f, (-f + bkpt - 1)/(f + 1), f - bkpt]: ….: assert(lhs <=0) sage: for lhs in [(-1)/(f^4 - 2*f^3*bkpt + f^2*bkpt^2 + 2*f^3 - 4*f^2*bkpt + 2*f*bkpt^2 + f^2 - 2*f*bkpt + bkpt^2), -f^2 - 2*f - 1, -f + 2*bkpt - 1, (-bkpt^2)/(f^6 - 2*f^5*bkpt + f^4*bkpt^2 + 2*f^5 - 4*f^4*bkpt + 2*f^3*bkpt^2 + f^4 - 2*f^3*bkpt + f^2*bkpt^2), -2*f + bkpt, -f^2 + 4*f*bkpt - 4*bkpt^2 - 2*f + 4*bkpt - 1, -4*f^2 + 8*f - 4, -f^2, -f, (-f^2 + 2*f*bkpt - bkpt^2 - 2*f + 2*bkpt - 1)/(f^2 + 2*f + 1), f - bkpt, -f^2 + 2*f*bkpt - bkpt^2, -f^2 + 2*f - 1, (-bkpt^2)/(f^2 + 2*f + 1), -bkpt^2 + 2*bkpt - 1]: ….: assert(lhs < 0) sage: -f^2 - 2*f*bkpt - bkpt^2 + 2*f + 2*bkpt - 1 < 0 True sage: sorted(K._bsa.eq_poly()) # bug was output [-1] [] sage: sorted(K._bsa.lt_poly()) # bug was output [] [-2*f + bkpt, f - bkpt, f + bkpt - 1] sage: sorted(K._bsa.le_poly()) [] sage: sorted(K._factor_bsa.lt_poly()) # bug was output [-f - bkpt + 1, -f + 2*bkpt - 1, -f - 1, -f, -2*f + bkpt, f - bkpt] [-2*f + bkpt, -f, -f - 1, -f + 2*bkpt - 1, f - bkpt, f + bkpt - 1] sage: sorted(K._factor_bsa.le_poly()) [-bkpt, bkpt - 1, -f, -f + 2*bkpt - 1, f - bkpt, f + bkpt - 1, 2*f - 1] sage: sorted(K._factor_bsa.eq_poly()) []
change_test_point(new_values)
change_values(**values)

Convenience interface for change_test_point.

changed_values(**kwds)

Context manager for temporarily switching to another consistent test point.

This requires setting up the field with mutable_values=True.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: K.<f> = ParametricRealField([4/5], mutable_values=True)
sage: 0 <= f <= 1
True
sage: with K.changed_values(f=1/5):
....:     assert f <= 1/2
Traceback (most recent call last):
...
ParametricRealFieldInconsistencyError: Old test point... does not satisfy the recorded constraints
characteristic()
find_test_point()

Sets a new test point that is consistent with the recorded constraints.

This can fail with ``NotImplementedError’’ or ``ParametricRealFieldInconsistencyError’’.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: K.<x,y,z> = ParametricRealField([1, 2, 3], mutable_values=True, big_cells=True, allow_refinement=False)
sage: assert 0 <= x <= y <= z <= 6
sage: K.remove_test_point()
sage: K.find_test_point()
sage: x.val(), y.val(), z.val()
(3/2, 3, 9/2)

sage: K.<x,y,z> = ParametricRealField(mutable_values=True, big_cells=True, allow_refinement=False)
sage: K.assume_comparison(0, operator.le, x.sym())
sage: K.assume_comparison(x.sym(), operator.le, y.sym())
sage: K.assume_comparison(y.sym(), operator.le, z.sym())
sage: K.assume_comparison(z.sym(), operator.le, 4)
sage: K.find_test_point()
sage: x.val(), y.val(), z.val()
(1, 2, 3)
freeze()
frozen(**kwds)
get_eq()
get_eq_factor()
get_le()
get_le_factor()
get_lt()
get_lt_factor()
is_factor_known(fac, op)
is_point_consistent(new_values)

Check whether new_values satisfies all recorded assumptions.

make_proof_cell(**opt)

Make a SemialgebraicComplexComponent from a ParametricRealField.

In **opt, one can provide: region_type, function, find_region_type, default_var_bound, bddbsa, kwds_dict.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)

sage: def foo(x,y):
....:     return (x+y < 2) and (y^2 < x)
sage: K.<x,y> = ParametricRealField([1,1/2])
sage: region_type = foo(*K.gens())
sage: c = K.make_proof_cell(region_type=region_type)
sage: sorted(c.bsa.lt_poly())
[x + y - 2, y^2 - x]
sage: c.plot()    #not tested

sage: K.<f,bkpt> = ParametricRealField([1/5,3/7])
sage: h = drlm_backward_3_slope(f, bkpt)
sage: region_type = find_region_type_igp(K, h)
sage: c1 = K.make_proof_cell(region_type=region_type)
sage: c1.plot()  # not tested
sage: sorted(c1.bsa.lt_poly())
[-2*f + 3*bkpt - 1, f - 3*bkpt + 1, 2*f - bkpt]
sage: c2 = K.make_proof_cell(region_type=region_type, function=h, find_region_type=None)
monomial_list()
ngens(self)

File: sage/structure/parent_gens.pyx (starting at line 104)

off_the_record(**kwds)
plot(*options, **kwds)
ppl_polyhedron()
record_factor(fac, op)
remove_test_point()

Switch self to test-point free mode.

This requires a ParametricRealField set up with mutable_values=True.

Not many things are implemented in this mode:

EXAMPLE:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: K.<a,b> = ParametricRealField([4, 1], big_cells=True, mutable_values=True, allow_refinement=False)
sage: with K.changed_values():
....:     K.remove_test_point()
....:     with K.temporary_assumptions():
....:         K.assume_comparison(a.sym(), operator.le, 3)
....:         a <= 4
Traceback (most recent call last):
...
FactorUndetermined: a cannot be evaluated because the test point is not complete...
removed_test_point(**kwds)

Context manager for temporarily switching to test-point free mode.

This requires a ParametricRealField set up with mutable_values=True.

EXAMPLE:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: K.<a> = ParametricRealField([4], big_cells=True, mutable_values=True, allow_refinement=False)
sage: with K.removed_test_point():
....:     with K.temporary_assumptions():
....:         K.assume_comparison(a.sym(), operator.le, 3)
....:         K.find_test_point()
....:         with K.frozen():
....:             a <= 4
True
temporary_assumptions(**kwds)
unfreeze()
unfrozen(**kwds)
v_dict()
exception cutgeneratingfunctionology.igp.ParametricRealFieldFrozenError

Bases: exceptions.ValueError

__module__ = 'cutgeneratingfunctionology.igp'
__weakref__

list of weak references to the object (if defined)

exception cutgeneratingfunctionology.igp.ParametricRealFieldInconsistencyError

Bases: exceptions.ValueError

__module__ = 'cutgeneratingfunctionology.igp'
__weakref__

list of weak references to the object (if defined)

exception cutgeneratingfunctionology.igp.ParametricRealFieldRefinementError

Bases: exceptions.ValueError

__module__ = 'cutgeneratingfunctionology.igp'
__weakref__

list of weak references to the object (if defined)

class cutgeneratingfunctionology.igp.PiecewiseCrazyFunction(pwl, crazy_pieces, parent=None)

Bases: sage.structure.element.ModuleElement

__call__

File: /home/travis/.sage/temp/travis-job-5f12b3bd-db33-4304-b8a5-9fa65cd36760/10924/crazy_perturbation.sage9pJzZN.py (starting at line 146)

__dict__ = dict_proxy({'__module__': 'cutgeneratingfunctionology.igp', '__dict__': <attribute '__dict__' of 'PiecewiseCrazyFunction' objects>, '_sub_': <function _sub_>, 'limit_range': <function limit_range>, '__truediv__': <function __truediv__>, '_acted_upon_': <function _acted_upon_>, 'end_points': <function end_points>, '_lmul_': <function _lmul_>, '__weakref__': <attribute '__weakref__' of 'PiecewiseCrazyFunction' objects>, '__init__': <function __init__>, '_rmul_': <function _lmul_>, 'plot': <function plot>, '_neg_': <function _neg_>, '_add_': <function _add_>, '_repr_': <function _repr_>, '__div__': <function __truediv__>, 'find_crazy_piece': <function find_crazy_piece>, '_richcmp_': <function _richcmp_>, '__call__': <sage.misc.cachefunc.CachedSpecialMethod object>, 'limit': <function limit>, '__doc__': None})
__div__(other)

File: sage/structure/element.pyx (starting at line 1654)

Top-level true division operator for Element invoking the coercion model.

See Arithmetic for Elements.

EXAMPLES:

sage: operator.truediv(2, 3)
2/3
sage: operator.truediv(pi, 3)
1/3*pi
sage: K.<i> = NumberField(x^2+1)
sage: operator.truediv(2, K.ideal(i+1))
Fractional ideal (-i + 1)
sage: from sage.structure.element import Element
sage: class MyElement(Element):
....:     def _div_(self, other):
....:         return 42
sage: e = MyElement(Parent())
sage: operator.truediv(e, e)
42

TESTS:

sage: e = Element(Parent())
sage: operator.truediv(e, e)
Traceback (most recent call last):
...
TypeError: unsupported operand parent(s) for /: '<sage.structure.parent.Parent object at ...>' and '<sage.structure.parent.Parent object at ...>'
sage: operator.truediv(1, e)
Traceback (most recent call last):
...
TypeError: unsupported operand parent(s) for /: 'Integer Ring' and '<sage.structure.parent.Parent object at ...>'
sage: operator.truediv(e, 1)
Traceback (most recent call last):
...
TypeError: unsupported operand parent(s) for /: '<sage.structure.parent.Parent object at ...>' and 'Integer Ring'
sage: operator.truediv(int(1), e)
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for /: 'int' and 'sage.structure.element.Element'
sage: operator.truediv(e, int(1))
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for /: 'sage.structure.element.Element' and 'int'
sage: operator.truediv(None, e)
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for /: 'NoneType' and 'sage.structure.element.Element'
sage: operator.truediv(e, None)
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for /: 'sage.structure.element.Element' and 'NoneType'
__init__(pwl, crazy_pieces, parent=None)

File: sage/structure/element.pyx (starting at line 385)

INPUT:

  • parent - a SageObject
__module__ = 'cutgeneratingfunctionology.igp'
__truediv__(other)

File: sage/structure/element.pyx (starting at line 1654)

Top-level true division operator for Element invoking the coercion model.

See Arithmetic for Elements.

EXAMPLES:

sage: operator.truediv(2, 3)
2/3
sage: operator.truediv(pi, 3)
1/3*pi
sage: K.<i> = NumberField(x^2+1)
sage: operator.truediv(2, K.ideal(i+1))
Fractional ideal (-i + 1)
sage: from sage.structure.element import Element
sage: class MyElement(Element):
....:     def _div_(self, other):
....:         return 42
sage: e = MyElement(Parent())
sage: operator.truediv(e, e)
42

TESTS:

sage: e = Element(Parent())
sage: operator.truediv(e, e)
Traceback (most recent call last):
...
TypeError: unsupported operand parent(s) for /: '<sage.structure.parent.Parent object at ...>' and '<sage.structure.parent.Parent object at ...>'
sage: operator.truediv(1, e)
Traceback (most recent call last):
...
TypeError: unsupported operand parent(s) for /: 'Integer Ring' and '<sage.structure.parent.Parent object at ...>'
sage: operator.truediv(e, 1)
Traceback (most recent call last):
...
TypeError: unsupported operand parent(s) for /: '<sage.structure.parent.Parent object at ...>' and 'Integer Ring'
sage: operator.truediv(int(1), e)
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for /: 'int' and 'sage.structure.element.Element'
sage: operator.truediv(e, int(1))
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for /: 'sage.structure.element.Element' and 'int'
sage: operator.truediv(None, e)
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for /: 'NoneType' and 'sage.structure.element.Element'
sage: operator.truediv(e, None)
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for /: 'sage.structure.element.Element' and 'NoneType'
__weakref__

list of weak references to the object (if defined)

_acted_upon_(actor, self_on_left)

Multiply self by a matrix from left or right.

_add_(self, other)

File: sage/structure/element.pyx (starting at line 2346)

Abstract addition method

TESTS:

sage: from sage.structure.element import ModuleElement
sage: e = ModuleElement(Parent())
sage: e + e
Traceback (most recent call last):
...
NotImplementedError: addition not implemented for <sage.structure.parent.Parent object at ...>
_lmul_(scalar)

Multiply self by a scalar.

_neg_(self)

File: sage/structure/element.pyx (starting at line 2376)

Default implementation of negation using multiplication with -1.

_repr_(self)

File: sage/structure/element.pyx (starting at line 523)

_richcmp_(left, right, int op)

File: sage/structure/element.pyx (starting at line 1093)

Default implementation of rich comparisons for elements with equal parents.

It tries to see if _cmp_ is implemented. Otherwise it does a comparison by id for == and !=. Calling this default method with <, <=, > or >= will raise a NotImplementedError.

EXAMPLES:

sage: from sage.structure.parent import Parent
sage: from sage.structure.element import Element
sage: P = Parent()
sage: e1 = Element(P); e2 = Element(P)
sage: e1 == e1    # indirect doctest
True
sage: e1 == e2    # indirect doctest
False
sage: e1 < e2     # indirect doctest
Traceback (most recent call last):
...
NotImplementedError: comparison not implemented for <... 'sage.structure.element.Element'>

We now create an Element class where we define _richcmp_ and check that comparison works:

sage: cython('''
....: from sage.structure.richcmp cimport rich_to_bool
....: from sage.structure.element cimport Element
....: cdef class FloatCmp(Element):
....:     cdef float x
....:     def __init__(self, float v):
....:         self.x = v
....:     cpdef _richcmp_(self, other, int op):
....:         cdef float x1 = (<FloatCmp>self).x
....:         cdef float x2 = (<FloatCmp>other).x
....:         return rich_to_bool(op, (x1 > x2) - (x1 < x2))
....: ''')
sage: a = FloatCmp(1)
sage: b = FloatCmp(2)
sage: a <= b, b <= a
(True, False)

This works despite _cmp_ not being implemented:

sage: a._cmp_(b)
Traceback (most recent call last):
...
NotImplementedError: comparison not implemented for <... '...FloatCmp'>
_rmul_(scalar)

Multiply self by a scalar.

_sub_(self, other)

File: sage/structure/element.pyx (starting at line 2369)

Default implementation of subtraction using addition and negation.

end_points()
find_crazy_piece(x, xeps=0)
limit(x0, epsilon)
limit_range(x0, epsilon)
plot(rgbcolor='magenta')
class cutgeneratingfunctionology.igp.PiecewiseCrazyFunctionsSpace(domain, codomain)

Bases: sage.structure.unique_representation.UniqueRepresentation, cutgeneratingfunctionology.igp.fast_piecewise.PiecewiseFunctionsSpace

Space of piecewise crazy functions.

TESTS:

sage: from cutgeneratingfunctionology.igp import *
sage: pushout(PiecewiseCrazyFunctionsSpace(QQ, QQ), PiecewiseLinearFunctionsSpace(AA, AA))  # known bug -- need to implement construction functor!

sage: TestSuite(PiecewiseCrazyFunctionsSpace(AA, AA)).run(skip=['_test_zero'])
sage: TestSuite(PiecewiseCrazyFunctionsSpace(AA, AA)).run(verbose=True, catch=False)  # not tested - for interactive use
Element

alias of PiecewiseCrazyFunction

__module__ = 'cutgeneratingfunctionology.igp'
_an_element_(self)

File: sage/structure/parent.pyx (starting at line 2612)

Returns an element of self. Want it in sufficient generality that poorly-written functions won’t work when they’re not supposed to. This is cached so doesn’t have to be super fast.

EXAMPLES:

sage: QQ._an_element_()
1/2
sage: ZZ['x,y,z']._an_element_()
x

TESTS:

Since Parent comes before the parent classes provided by categories in the hierarchy of classes, we make sure that this default implementation of _an_element_() does not override some provided by the categories. Eventually, this default implementation should be moved into the categories to avoid this workaround:

sage: S = FiniteEnumeratedSet([1,2,3])
sage: S.category()
Category of facade finite enumerated sets
sage: super(Parent, S)._an_element_
Cached version of <function ..._an_element_from_iterator at ...>
sage: S._an_element_()
1
sage: S = FiniteEnumeratedSet([])
sage: S._an_element_()
Traceback (most recent call last):
...
EmptySetError
_coerce_map_from_(S)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: PiecewiseCrazyFunctionsSpace(AA, AA).has_coerce_map_from(PiecewiseLinearFunctionsSpace(QQ, QQ))
True
_element_constructor_(x, *args, **kwds)

Construct a morphism in this homset from x if possible.

EXAMPLES:

sage: H = Hom(SymmetricGroup(4), SymmetricGroup(7))
sage: phi = Hom(SymmetricGroup(5), SymmetricGroup(6)).natural_map()
sage: phi
Coercion morphism:
  From: Symmetric group of order 5! as a permutation group
  To:   Symmetric group of order 6! as a permutation group

When converting \(\phi\) into \(H\), some coerce maps are applied. Note that (in contrast to what is stated in the following string representation) it is safe to use the resulting map, since a composite map prevents the codomains of all constituent maps from garbage collection, if there is a strong reference to its domain (which is the case here):

sage: H(phi)
Composite map:
  From: Symmetric group of order 4! as a permutation group
  To:   Symmetric group of order 7! as a permutation group
  Defn:   (map internal to coercion system -- copy before use)
        Coercion map:
          From: Symmetric group of order 4! as a permutation group
          To:   Symmetric group of order 5! as a permutation group
        then
          Coercion morphism:
          From: Symmetric group of order 5! as a permutation group
          To:   Symmetric group of order 6! as a permutation group
        then
          (map internal to coercion system -- copy before use)
        Coercion map:
          From: Symmetric group of order 6! as a permutation group
          To:   Symmetric group of order 7! as a permutation group

Also note that making a copy of the resulting map will automatically make strengthened copies of the composed maps:

sage: copy(H(phi))
Composite map:
  From: Symmetric group of order 4! as a permutation group
  To:   Symmetric group of order 7! as a permutation group
  Defn:   Coercion map:
          From: Symmetric group of order 4! as a permutation group
          To:   Symmetric group of order 5! as a permutation group
        then
          Coercion morphism:
          From: Symmetric group of order 5! as a permutation group
          To:   Symmetric group of order 6! as a permutation group
        then
          Coercion map:
          From: Symmetric group of order 6! as a permutation group
          To:   Symmetric group of order 7! as a permutation group
sage: H = Hom(ZZ, ZZ, Sets())
sage: f = H( lambda x: x + 1 )
sage: f.parent()
Set of Morphisms from Integer Ring to Integer Ring in Category of sets
sage: f.domain()
Integer Ring
sage: f.codomain()
Integer Ring
sage: f(1), f(2), f(3)
(2, 3, 4)

sage: H = Hom(Set([1,2,3]), Set([1,2,3]))
sage: f = H( lambda x: 4-x )
sage: f.parent()
Set of Morphisms from {1, 2, 3} to {1, 2, 3} in Category of finite sets
sage: f(1), f(2), f(3) # todo: not implemented

sage: H = Hom(ZZ, QQ, Sets())
sage: f = H( ConstantFunction(2/3) )
sage: f.parent()
Set of Morphisms from Integer Ring to Rational Field in Category of sets
sage: f(1), f(2), f(3)
(2/3, 2/3, 2/3)

By trac ticket #14711, conversion and coerce maps should be copied before using them outside of the coercion system:

sage: H = Hom(ZZ,QQ['t'], CommutativeAdditiveGroups())
sage: P.<t> = ZZ[]
sage: f = P.hom([2*t])
sage: phi = H._generic_convert_map(f.parent()); phi
Conversion map:
  From: Set of Homomorphisms from Univariate Polynomial Ring in t over Integer Ring to Univariate Polynomial Ring in t over Integer Ring
  To:   Set of Morphisms from Integer Ring to Univariate Polynomial Ring in t over Rational Field in Category of commutative additive groups
sage: H._generic_convert_map(f.parent())(f)
Composite map:
  From: Integer Ring
  To:   Univariate Polynomial Ring in t over Rational Field
  Defn:   (map internal to coercion system -- copy before use)
        Polynomial base injection morphism:
          From: Integer Ring
          To:   Univariate Polynomial Ring in t over Integer Ring
        then
          Ring endomorphism of Univariate Polynomial Ring in t over Integer Ring
          Defn: t |--> 2*t
        then
          (map internal to coercion system -- copy before use)
        Ring morphism:
          From: Univariate Polynomial Ring in t over Integer Ring
          To:   Univariate Polynomial Ring in t over Rational Field
sage: copy(H._generic_convert_map(f.parent())(f))
Composite map:
  From: Integer Ring
  To:   Univariate Polynomial Ring in t over Rational Field
  Defn:   Polynomial base injection morphism:
          From: Integer Ring
          To:   Univariate Polynomial Ring in t over Integer Ring
        then
          Ring endomorphism of Univariate Polynomial Ring in t over Integer Ring
          Defn: t |--> 2*t
        then
          Ring morphism:
          From: Univariate Polynomial Ring in t over Integer Ring
          To:   Univariate Polynomial Ring in t over Rational Field
          Defn: Induced from base ring by
                Natural morphism:
                  From: Integer Ring
                  To:   Rational Field

TESTS:

sage: G.<x,y,z> = FreeGroup()
sage: H = Hom(G, G)
sage: H(H.identity())
Identity endomorphism of Free Group on generators {x, y, z}
sage: H()
Traceback (most recent call last):
...
TypeError: unable to convert 0 to an element of
 Set of Morphisms from Free Group on generators {x, y, z}
 to Free Group on generators {x, y, z} in Category of infinite groups
sage: H("whatever")
Traceback (most recent call last):
...
TypeError: unable to convert 'whatever' to an element of
 Set of Morphisms from Free Group on generators {x, y, z}
 to Free Group on generators {x, y, z} in Category of infinite groups
sage: HH = Hom(H, H)
sage: HH(HH.identity(), foo="bar")
Traceback (most recent call last):
...
NotImplementedError: no keywords are implemented for
 constructing elements of ...

AUTHORS:

  • Robert Bradshaw, with changes by Nicolas M. Thiery
_repr_()

TESTS:

sage: Hom(ZZ^2, QQ, category=Sets())._repr_() ‘Set of Morphisms from Ambient free module of rank 2 over the principal ideal domain Integer Ring to Rational Field in Category of sets’

class cutgeneratingfunctionology.igp.PiecewiseQuasiPeriodic(list_of_pairs, quasiperiodic_extension=True)

Bases: cutgeneratingfunctionology.igp.fast_piecewise.PiecewiseLinearFunction_1d

Returns a piecewise quasi-periodic function from a list of (interval, function) pairs. Decomposes a piecewise quasi-periodic function into a periodic function and a linear function.

It is assumed ‘interval’ from the first list of (interval, function) pairs is in the form (0,x1) for some x1 > 0.

__call__(x0)

Evaluats self at x0.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # to disable output in automatic tests.
sage: q = PiecewiseQuasiPeriodic([[(0,1/2), FastLinearFunction(3,0)],[(1/2,3/2), FastLinearFunction(-1,2)]])
sage: q(3/2)
1/2
sage: q(-1)
1
__init__(list_of_pairs, quasiperiodic_extension=True)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # to disable output in automatic tests.
sage: q = PiecewiseQuasiPeriodic([[(0,1/2), FastLinearFunction(3,0)],[(1/2,3/2), FastLinearFunction(-1,2)]])
sage: q.period
3/2
sage: q.linear_term
<FastLinearFunction 1/3*x>
sage: q.periodic_term
<FastPiecewise with 2 parts,
 (0, 1/2)   <FastLinearFunction 8/3*x>       values: [0, 4/3]
 (1/2, 3/2) <FastLinearFunction -4/3*x + 2>  values: [4/3, 0]>
__module__ = 'cutgeneratingfunctionology.igp'
plot(*args, **kwds)

Returns the plot of self.

Keyword arguments are passed onto the plot command for each piece of the function. E.g., the plot_points keyword affects each segment of the plot.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: q = PiecewiseQuasiPeriodic([[(0,1/2), FastLinearFunction(3,0)],[(1/2,3/2), FastLinearFunction(-1,2)]])
sage: p = plot(q)

The implementation of the plot method in Sage 5.11 piecewise.py is incompatible with the use of the xmin and xmax arguments. Test that this has been fixed:

sage: p = q.plot(xmin=0, xmax=3)
sage: p = plot(q, xmin=0, xmax=3)
sage: p = plot(q, 0, 3)
sage: p = plot(q, 0, 3, color='red')

Also the following plot syntax should be accepted:

sage: p = plot(q, [0, 3])
class cutgeneratingfunctionology.igp.ProofCell(family, var_value, find_region_type, bddbsa, polynomial_map)

Bases: cutgeneratingfunctionology.igp.SemialgebraicComplexComponent, cutgeneratingfunctionology.igp.class_call.Classcall

A proof cell for parameter space analysis.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import ProofCell, ParametricFamily, _max_x_y, result_symbolic_expression
sage: import logging
sage: logging.disable(logging.WARN)
sage: C = ProofCell(ParametricFamily(_max_x_y), [1, 2], find_region_type=result_symbolic_expression)
sage: sorted(C.bsa.lt_poly())
[x - y]

Proof cells remember their construction:

sage: C._init_args
(<class 'cutgeneratingfunctionology.igp.ProofCell'>,
 (ParametricFamily(_max_x_y, ...),
  (1, 2),
  <...result_symbolic_expression...>,
  ...),
 {})

Proof cells can be pickled if family is a global variable or can be pickled otherwise (lambda functions cannot be pickled):

sage: p_C = dumps(C)
sage: explain_pickle(p_C)      # not tested
sage: C_copy = loads(p_C)
sage: sorted(C_copy.bsa.lt_poly())
[x - y]
sage: C_copy._init_args == C._init_args
True

(We do not test for equality C_copy == C – we have not even decided yet what the semantics of equality of bsa is.)

static __classcall__(cls, family, var_value, find_region_type, bddbsa=None, polynomial_map=None)
__init__(family, var_value, find_region_type, bddbsa, polynomial_map)

Bug example:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: P.<f,z>=QQ[]
sage: theta = [3*f/(2*f+2), 3*f/(2*f+2)]
sage: family = cpl_n_group_function(3, True, theta=lambda x, y: tuple([t(x, *y) for t in theta]))
sage: var_value = (111/1000, 111/1000)
sage: find_region_type = find_region_type_igp_extreme_big_cells
sage: bddbsa = BasicSemialgebraicSet_veronese(poly_ring=P)
sage: bddbsa.add_polynomial_constraint(f - z, operator.eq)
sage: bddbsa.add_polynomial_constraint(8*f - 1, operator.lt)
sage: bddbsa.add_polynomial_constraint(-f, operator.lt)
sage: polynomial_map = [f, f]
sage: cell = ProofCell(family, var_value, find_region_type, bddbsa, polynomial_map)
sage: sorted(cell.bsa.lt_poly()), sorted(cell.bsa.eq_poly())  # was ([-11*f + 1, 9*f - 1, -11*f^2 + f, 5*f^2 - f], [f - z]))
([-11*f + 1, 9*f - 1], [f - z])
__module__ = 'cutgeneratingfunctionology.igp'
static _construct_field_and_test_point(family, var_value, polynomial_map=None)

Construct a ParametricRealField K using var_value and polynomial_map.

var_value is a list parallel to family.names().

Construct a test_point of type dictionary, which maps each parameter of the family to the corresponding ParametricRealFieldElement if this is a parameter of K, otherwise maps to the default argument value.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: family=ParametricFamily(gmic); var_value=[1/2]; P.<f>=QQ[]; polynomial_map = [f]
sage: K, pt, test_point = ProofCell._construct_field_and_test_point(family, var_value, polynomial_map)
sage: K
ParametricRealField(names = ['f'], values = [1/2])
sage: pt
[f~]
sage: test_point
{'conditioncheck': False,
     'f': f~,
     'field': ParametricRealField(names = ['f'], values = [1/2])}

Bug example:

sage: P.<f,z>=QQ[]
sage: theta = [3*f/(2*f+2), 3*f/(2*f+2)]
sage: family = cpl_n_group_function(3, True, theta=lambda x, y: tuple([t(x, *y) for t in theta]))
sage: var_value = (111/1000, 111/1000)
sage: K, pt, test_point = ProofCell._construct_field_and_test_point(family, var_value)
sage: list(K._bsa.eq_poly())
[]
sage: pt
[f~, z~]
sage: polynomial_map = [f, f]
sage: K, pt, test_point = ProofCell._construct_field_and_test_point(family, var_value, polynomial_map)
sage: list(K._bsa.eq_poly())
[f - z]
sage: pt
[f~, f~]
cutgeneratingfunctionology.igp.RealNumberField(polynomial, name=None, latex_name=None, names=None, check=True, embedding=None, assume_disc_small=False, maximize_at_primes=None, exact_embedding=None)

A NumberField embedded into the real numbers, for which comparisons work according tothe embedding.

This may not be necessary any more in Sage 7.1 after trac ticket #17830; but see trac ticket #20184.

Some special tricks for speed and for pretty printing.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: x=polygen(QQ)
sage: K.<cbrt2> = RealNumberField(x^3 - 2, embedding=RIF(AA.polynomial_root(x^3-2, RIF(0,3))), exact_embedding=AA.polynomial_root(x^3-2, RIF(0,3)))
sage: 6064/4813 < cbrt2 < 90325/71691
True

sage: R.<y> = QQ[]; polynomial=y^2 - 2; embedding=RR(1.4142135623730949); exact_embedding=SR(AA(sqrt(2)))
sage: RealNumberField(polynomial=polynomial, name='a', embedding=embedding, exact_embedding=exact_embedding)
Real Number Field in `a` as the root of the defining polynomial y^2 - 2 near 1.414213562373095?
class cutgeneratingfunctionology.igp.RealNumberFieldElement

Bases: sage.rings.number_field.number_field_element.NumberFieldElement_absolute

__abs__()

File: sage/rings/number_field/number_field_element.pyx (starting at line 979)

Return the absolute value of this number field element.

If a real-valued coercion embedding is defined, the returned absolute value is an element of the same field.

Otherwise, it is the numerical absolute value with respect to the first archimedean embedding, to double precision.

This is the abs( ) Python function. If you want a different embedding or precision, use self.abs(...).

EXAMPLES:

sage: k.<a> = NumberField(x^3 - 2)
sage: abs(a)
1.25992104989487
sage: a.abs()
1.25992104989487
sage: abs(a)^3
2.00000000000000
sage: a.abs()^3
2.00000000000000
sage: a.abs(prec=128)
1.2599210498948731647672106072782283506

Number field with a real-valued coercion embedding (trac ticket #21105):

sage: k.<cbrt2> = NumberField(x^3 - 2, embedding=1.26)
sage: abs(cbrt2)
cbrt2
sage: cbrt2.abs()
cbrt2
sage: abs(cbrt2)^3
2
__dict__ = dict_proxy({'__float__': <function __float__>, '__module__': 'cutgeneratingfunctionology.igp', 'embedded': <function embedded>, '_add_': <function _add_>, '_sub_': <function _sub_>, '_div_': <function _div_>, '_latex_': <function _latex_>, '_maxima_': <function _maxima_>, '__abs__': <function __abs__>, '__dict__': <attribute '__dict__' of 'RealNumberFieldElement' objects>, '_mul_': <function _mul_>, '__repr__': <function __repr__>, '_richcmp_': <function _richcmp_>, '__hash__': <function __hash__>, 'sign': <function sign>, '__weakref__': <attribute '__weakref__' of 'RealNumberFieldElement' objects>, '__doc__': None, '__neg__': <function __neg__>})
__float__()

File: sage/rings/number_field/number_field_element.pyx (starting at line 1866)

EXAMPLES:

sage: k.<a> = NumberField(x^2 + 1)
sage: float(a^2)
-1.0
sage: float(a)
Traceback (most recent call last):
...
TypeError: Unable to coerce a to a rational
sage: (a^2).__float__()
-1.0
sage: k.<a> = NumberField(x^2 + 1,embedding=I)
sage: float(a)
Traceback (most recent call last):
...
TypeError: unable to coerce to a real number
__hash__()

File: sage/rings/number_field/number_field_element.pyx (starting at line 3047)

Return hash of this number field element.

It respects the hash values of rational numbers.

EXAMPLES:

sage: K.<b> = NumberField(x^3 - 2)
sage: hash(b^2 + 1)   # random
175247765440
sage: hash(K(13)) == hash(13)
True
sage: hash(K(-2/3)) == hash(-2/3)
True

No collisions (even on low bits):

sage: from itertools import product
sage: elts = []
sage: for (i,j,k) in product((-1,0,1,2,3), repeat=3):
....:     x = i + j*b + k*b^2
....:     elts.append(x)
....:     if gcd([2,i,j,k]) == 1:
....:         elts.append(x / 2)
....:     if gcd([3,i,j,k]) == 1:
....:         elts.append(x / 3)
sage: len(set(map(hash, elts))) == len(elts)
True
sage: len(set(hash(x)%(2^18) for x in elts)) == len(elts)
True
__module__ = 'cutgeneratingfunctionology.igp'
__neg__()

File: sage/structure/element.pyx (starting at line 1396)

Top-level negation operator for Element.

EXAMPLES:

sage: from sage.structure.element import Element
sage: class MyElement(Element):
....:     def _neg_(self):
....:         return 42
sage: e = MyElement(Parent())
sage: -e
42

TESTS:

sage: e = Element(Parent())
sage: -e
Traceback (most recent call last):
...
TypeError: unsupported operand parent for unary -: '<sage.structure.parent.Parent object at ...>'
__repr__()

File: sage/structure/sage_object.pyx (starting at line 145)

Default method for string representation.

Note

Do not overwrite this method. Instead, implement a _repr_ (single underscore) method.

EXAMPLES:

By default, the string representation coincides with the output of the single underscore _repr_:

sage: P.<x> = QQ[]
sage: repr(P) == P._repr_()  #indirect doctest
True

Using rename(), the string representation can be customized:

sage: P.rename('A polynomial ring')
sage: repr(P) == P._repr_()
False

The original behaviour is restored with reset_name().:

sage: P.reset_name()
sage: repr(P) == P._repr_()
True

If there is no _repr_ method defined, we fall back to the super class (typically object):

sage: from sage.structure.sage_object import SageObject
sage: S = SageObject()
sage: S
<sage.structure.sage_object.SageObject object at ...>
__weakref__

list of weak references to the object (if defined)

_add_(self, right)

File: sage/rings/number_field/number_field_element.pyx (starting at line 2369)

EXAMPLES:

sage: K.<s> = QuadraticField(2)
sage: s + s # indirect doctest
2*s
sage: s + ZZ(3) # indirect doctest
s + 3
_div_(self, other)

File: sage/rings/number_field/number_field_element.pyx (starting at line 2466)

Returns the quotient of self and other as elements of a number field.

EXAMPLES:

sage: C.<I>=CyclotomicField(4)
sage: 1/I # indirect doctest
-I
sage: I/0 # indirect doctest
Traceback (most recent call last):
...
ZeroDivisionError: rational division by zero
sage: G.<a> = NumberField(x^3 + 2/3*x + 1)
sage: a/a # indirect doctest
1
sage: 1/a # indirect doctest
-a^2 - 2/3
sage: a/0 # indirect doctest
Traceback (most recent call last):
...
ZeroDivisionError: number field element division by zero

TESTS:

For quadratic elements:

sage: K.<a> = NumberField(x^2-5)
sage: 2/a # indirect doctest
2/5*a
sage: (a+2)/(a+1)
1/4*a + 3/4
sage: (a+1)*(a+2)/(a+1)
a + 2
sage: (a+1/3)*(5*a+2/7)/(a+1/3)
5*a + 2/7

For order elements, see trac ticket #4190:

sage: K = NumberField(x^2 - 17, 'a')
sage: OK = K.ring_of_integers()
sage: a = OK(K.gen())
sage: (17/a).parent() is K # indirect doctest
True
sage: 17/a in OK
True
sage: (17/(2*a)).parent() is OK
False
sage: (17/(2*a)) in OK
False
sage: (17/(2*a)).parent() is K
True

sage: K = NumberField(x^3 - 17, 'a')
sage: OK = K.ring_of_integers()
sage: a = OK(K.gen())
sage: (17/a) in OK # indirect doctest
True
sage: (17/a).parent() is K # indirect doctest
True
sage: (17/(2*a)).parent() is K # indirect doctest
True
sage: (17/(2*a)) in OK # indirect doctest
False

sage: K1.<a> = NumberField(x^3 - 17)
sage: R.<y> = K1[]
sage: K2 = K1.extension(y^2 - a, 'b')
sage: OK2 = K2.order(K2.gen()) # (not maximal)
sage: b = OK2.basis()[1]; b
b
sage: (17/b).parent() is K2 # indirect doctest
True
sage: (17/b) in OK2 # indirect doctest
True
sage: (17/b^7) in OK2 # indirect doctest
False
_latex_(self)

File: sage/rings/number_field/number_field_element.pyx (starting at line 486)

Returns the latex representation for this element.

EXAMPLES:

sage: C.<zeta12> = CyclotomicField(12)
sage: latex(zeta12^4-zeta12) # indirect doctest
\zeta_{12}^{2} - \zeta_{12} - 1
_maxima_(self, G=None)

File: sage/structure/sage_object.pyx (starting at line 770)

_mul_(self, right)

File: sage/rings/number_field/number_field_element.pyx (starting at line 2419)

Returns the product of self and other as elements of a number field.

EXAMPLES:

sage: C.<zeta12>=CyclotomicField(12)
sage: zeta12*zeta12^11
1
sage: G.<a> = NumberField(x^3 + 2/3*x + 1)
sage: a^3 # indirect doctest
-2/3*a - 1
sage: a^3+a # indirect doctest
1/3*a - 1
_richcmp_(left, right, int op)

File: sage/rings/number_field/number_field_element.pyx (starting at line 793)

EXAMPLES:

sage: K.<a> = NumberField(x^3 - 3*x + 8)
sage: a  + 1 > a # indirect doctest
True
sage: a + 1 < a # indirect doctest
False

Comparison of embedded number fields:

sage: x = polygen(ZZ)
sage: K.<cbrt2> = NumberField(x^3 - 2, embedding=AA(2).nth_root(3))
sage: 6064/4813 < cbrt2 < 90325/71691
True

sage: c20 = 3085094589/2448641198
sage: c21 = 4433870912/3519165675
sage: c20 < cbrt2 < c21
True
sage: c20 >= cbrt2 or cbrt2 <= c20 or c21 <= cbrt2 or cbrt2 >= c21
False

sage: c40 = 927318063212049190871/736012834525960091591
sage: c41 = 112707779922292658185265/89456224206823838627034
sage: c40 < cbrt2 < c41
True
sage: c40 >= cbrt2 or cbrt2 <= c40 or c41 <= cbrt2 or cbrt2 >= c41
False
_sub_(self, right)

File: sage/rings/number_field/number_field_element.pyx (starting at line 2395)

EXAMPLES:

sage: K.<a> = NumberField(x^3 + 2)
sage: (a/2) - (a + 3) # indirect doctest
-1/2*a - 3
embedded()
sign(self)

File: sage/rings/number_field/number_field_element.pyx (starting at line 1020)

Return the sign of this algebraic number (if a real embedding is well defined)

EXAMPLES:

sage: K.<a> = NumberField(x^3 - 2, embedding=AA(2)**(1/3))
sage: K.zero().sign()
0
sage: K.one().sign()
1
sage: (-K.one()).sign()
-1
sage: a.sign()
1
sage: (a - 234917380309015/186454048314072).sign()
1
sage: (a - 3741049304830488/2969272800976409).sign()
-1

If the field is not embedded in real numbers, this method will only work for rational elements:

sage: L.<b> = NumberField(x^4 - x - 1)
sage: b.sign()
Traceback (most recent call last):
...
TypeError: sign not well defined since no real embedding is
specified
sage: L(-33/125).sign()
-1
sage: L.zero().sign()
0
class cutgeneratingfunctionology.igp.RealNumberFieldElement_quadratic

Bases: sage.rings.number_field.number_field_element_quadratic.NumberFieldElement_quadratic

__dict__ = dict_proxy({'__module__': 'cutgeneratingfunctionology.igp', 'embedded': <function embedded>, '__dict__': <attribute '__dict__' of 'RealNumberFieldElement_quadratic' objects>, '_sage_input_': <function _sage_input_>, '__repr__': <function __repr__>, '__hash__': <function __hash__>, '__weakref__': <attribute '__weakref__' of 'RealNumberFieldElement_quadratic' objects>, '__doc__': None})
__hash__()

File: sage/rings/number_field/number_field_element_quadratic.pyx (starting at line 1583)

Return hash of this number field element.

For elements in \(\ZZ\) or \(\QQ\) the hash coincides with the one in the native \(\ZZ\) or \(\QQ\).

EXAMPLES:

sage: L.<a> = QuadraticField(-7)
sage: hash(a)
42082631
sage: hash(L(1))
1
sage: hash(L(-3))
-3
sage: hash(L(-32/118)) == hash(-32/118)
True
__module__ = 'cutgeneratingfunctionology.igp'
__repr__()

File: sage/structure/sage_object.pyx (starting at line 145)

Default method for string representation.

Note

Do not overwrite this method. Instead, implement a _repr_ (single underscore) method.

EXAMPLES:

By default, the string representation coincides with the output of the single underscore _repr_:

sage: P.<x> = QQ[]
sage: repr(P) == P._repr_()  #indirect doctest
True

Using rename(), the string representation can be customized:

sage: P.rename('A polynomial ring')
sage: repr(P) == P._repr_()
False

The original behaviour is restored with reset_name().:

sage: P.reset_name()
sage: repr(P) == P._repr_()
True

If there is no _repr_ method defined, we fall back to the super class (typically object):

sage: from sage.structure.sage_object import SageObject
sage: S = SageObject()
sage: S
<sage.structure.sage_object.SageObject object at ...>
__weakref__

list of weak references to the object (if defined)

_sage_input_(sib, coerced)

Produce an expression which will reproduce this value when evaluated.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: x, = nice_field_values([2^(1/2)])
sage: sage_input(x)
R.<y> = QQ[]
RealNumberField(y^2 - 2, embedding=RR(1.4142135623730949), name='a')([0, 1])
sage: sage_input((x, x))
R.<y> = QQ[]
K = RealNumberField(y^2 - 2, embedding=RR(1.4142135623730949), name='a')
(K([0, 1]), K([0, 1]))
embedded()
class cutgeneratingfunctionology.igp.RealNumberField_absolute(polynomial, name=None, latex_name=None, check=True, embedding=None, assume_disc_small=False, maximize_at_primes=None, exact_embedding=None)

Bases: sage.rings.number_field.number_field.NumberField_absolute

A RealNumberField knows its embedding into a RealIntervalField and use that for <, > comparisons. == comparison is exact, using the underlying numberfield.

A RealNumberField also knows an embedding into an exact field (SR) for the purpose of latexing.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: field, field_values, morphism = number_field_elements_from_algebraics((sqrt(2), sqrt(3)))
sage: emb_field = RealNumberField(field.polynomial(), 'a', 
....:                 embedding=morphism(field.gen(0)),
....:                 exact_embedding=SR(morphism(field.gen(0))))
sage: hom = field.hom([emb_field.gen(0)])
sage: Integer(7)/5 < hom(field_values[0])
True
sage: hom(field_values[0]) < Integer(3)/2
True
sage: hom(field_values[0]) < hom(field_values[1])
True
sage: Integer(3)/2 < hom(field_values[1])
True
sage: hom(field_values[1]) < 2
True
sage: logging.disable(logging.INFO)
sage: field = nice_field_values([sqrt(2),sqrt(3)])[0].parent()
sage: field
Real Number Field in `a` as the root of the defining polynomial y^4 - 4*y^2 + 1 near 0.5176380902050415?
sage: field1 = NumberField(field.polynomial(),"a")
sage: field1
Number Field in a with defining polynomial y^4 - 4*y^2 + 1
sage: field1 == field or field == field1
False
sage: field2 = VectorSpace(field, 2).base_field()
sage: field2
Real Number Field in `a` as the root of the defining polynomial y^4 - 4*y^2 + 1 near 0.5176380902050415?
sage: field == field2 and field2 == field
True
__hash__()

File: sage/misc/fast_methods.pyx (starting at line 106)

The hash provided by this class coincides with that of <type 'object'>.

TESTS:

sage: class MyParent(Parent):
....:   def __init__(self, x):
....:       self.x = x
....:   def __hash__(self):
....:       return hash(self.x)
sage: class MyUniqueParent(UniqueRepresentation, MyParent): pass
sage: issubclass(MyUniqueParent, sage.misc.fast_methods.WithEqualityById)
True
sage: a = MyUniqueParent(1)
sage: hash(a) == hash(a.x)
False
sage: hash(a) == object.__hash__(a)
True

sage: from sage.misc.fast_methods import WithEqualityById
sage: o1 = WithEqualityById()
sage: o2 = WithEqualityById()
sage: hash(o1) == hash(o2)
False
__init__(polynomial, name=None, latex_name=None, check=True, embedding=None, assume_disc_small=False, maximize_at_primes=None, exact_embedding=None)

Create a real number field.

__module__ = 'cutgeneratingfunctionology.igp'
_repr_()

Return string representation of this number field.

EXAMPLES:

sage: k.<a> = NumberField(x^13 - (2/3)*x + 3)
sage: k._repr_()
'Number Field in a with defining polynomial x^13 - 2/3*x + 3'
sage: k.<a> = NumberField(x^13 - (2/3)*x + 3, embedding=-1)
sage: k._repr_()
'Number Field in a with defining polynomial x^13 - 2/3*x + 3 with a = -1.106745229567614?'
class cutgeneratingfunctionology.igp.RealNumberField_quadratic(polynomial, name=None, latex_name=None, check=True, embedding=None, assume_disc_small=False, maximize_at_primes=None, exact_embedding=None)

Bases: sage.rings.number_field.number_field.NumberField_quadratic

__init__(polynomial, name=None, latex_name=None, check=True, embedding=None, assume_disc_small=False, maximize_at_primes=None, exact_embedding=None)

Create a real number field.

__module__ = 'cutgeneratingfunctionology.igp'
_repr_()

Return string representation of this number field.

EXAMPLES:

sage: k.<a> = NumberField(x^13 - (2/3)*x + 3)
sage: k._repr_()
'Number Field in a with defining polynomial x^13 - 2/3*x + 3'
sage: k.<a> = NumberField(x^13 - (2/3)*x + 3, embedding=-1)
sage: k._repr_()
'Number Field in a with defining polynomial x^13 - 2/3*x + 3 with a = -1.106745229567614?'
_sage_input_(sib, coerced)

Produce an expression which will reproduce this value when evaluated.

class cutgeneratingfunctionology.igp.SemialgebraicComplex(family, var_name=None, find_region_type=None, default_var_bound=(-0.100000000000000, 1.10000000000000), bddbsa=None, polynomial_map=None, kwds_dict={}, cell_class=None, **opt_non_default)

Bases: sage.structure.sage_object.SageObject

A proof complex for parameter space analysis.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)

sage: def vol(a,b):
....:     P = Polyhedron(ieqs=[(0,0,1),(0,1,0),(1,-1,0),(1,0,-1),(a,-1,0),(b,0,-1)])
....:     return P.volume()
sage: complex = SemialgebraicComplex(vol, ['a','b'], find_region_type=result_symbolic_expression, default_var_bound=(-1,3))

Breadth-first-search to complete the complex, starting at the point (a,b)=(2,1/2), using heuristic wall-crossing, considering full-dimensional cells only:

sage: complex.bfs_completion(var_value=[2, 1/2], flip_ineq_step=1/1000, check_completion=False, wall_crossing_method='heuristic', goto_lower_dim=False)
sage: sorted(c.region_type for c in complex.components)
[(0,), (0,), (0,), (0,), (1,), (b,), (a,), (a*b,), (a*b,)]
sage: complex.plot()                                  # not tested

Instead of heuristic method, we can use Mathematica’s FindInstance to look for uncovered points in wall-crossing:

sage: complex = SemialgebraicComplex(vol, ['a','b'], find_region_type=result_symbolic_expression, default_var_bound=(-1,3))                         # optional - mathematica
sage: complex.bfs_completion(var_value=[2, 1/2], flip_ineq_step=1/1000, check_completion=False, wall_crossing_method='mathematica', goto_lower_dim=True)        # optional - mathematica
sage: len(complex.components)                         # optional - mathematica
25
sage: complex.plot(goto_lower_dim=True)               # not tested

The entire parameter space is covered by cells:

sage: complex.is_complete()                           # optional - mathematica
True

Example with non-linear wall:

sage: complex = SemialgebraicComplex(lambda x,y: max(x,y^2), ['x','y'], find_region_type=result_symbolic_expression, default_var_bound=(-3,3))  # optional - mathematica
sage: complex.bfs_completion(var_value=[1,1/2], check_completion=True, wall_crossing_method='mathematica', goto_lower_dim=True)                             # optional - mathematica
sage: len(complex.components)                         # optional - mathematica
3
sage: complex.components[0].region_type               # optional - mathematica
(x,)
sage: complex.components[1].region_type               # optional - mathematica
(y^2,)
sage: complex.plot()                                  # not tested

Analyse the extreme/minimal/valid regions of a function in the Gomory-Johnson infinite group problem.

Use random shooting method to complete the complex. See more options in the method shoot_random_points:

sage: complex = SemialgebraicComplex(drlm_backward_3_slope, ['f','bkpt'])
sage: complex.shoot_random_points(50)

Use breadth-first-search to complete the complex. See more options in the method bfs_completion:

sage: complex = SemialgebraicComplex(drlm_backward_3_slope, ['f','bkpt'])
sage: complex.bfs_completion(var_value=[4/5,1/2])
sage: len(complex.components)
17
sage: complex.is_polyhedral()
True
sage: complex.is_face_to_face()
False
sage: complex2 = complex.subcomplex_of_cells_with_given_region_types({'is_extreme','not_extreme','not_minimal'})
sage: complex2.is_face_to_face()
True
sage: extc = complex.subcomplex_of_cells_with_given_region_types()
sage: len(extc.components)
2
sage: extc.is_polyhedral()
True
sage: extc.is_face_to_face()
True
sage: boundary = extc.guess_boundary()
sage: sorted(boundary, key=str)
[-f, -f + 4*bkpt - 1, f - bkpt]
sage: extc.bddbsa = BasicSemialgebraicSet_eq_lt_le_sets(lt=boundary)
sage: extc.is_complete(formal_closure=False) # optional - mathematica
False
sage: extc.is_complete(formal_closure=True) # optional - mathematica
True
sage: pc = extc.polyhedral_complex()
sage: sorted( sorted(pol.vertices_list()) for pol in pc.cells_list() )
[[[0, 0]],
 [[0, 0], [0, 1/4]],
 [[0, 0], [0, 1/4], [1/7, 2/7]],
 [[0, 0], [1/7, 2/7]],
 [[0, 0], [1/7, 2/7], [1/3, 1/3]],
 [[0, 0], [1/3, 1/3]],
 [[0, 1/4]],
 [[0, 1/4], [1/7, 2/7]],
 [[1/7, 2/7]],
 [[1/7, 2/7], [1/3, 1/3]],
 [[1/3, 1/3]]]

Consider low-dimensional cells in the polyhedral case:

sage: complex = SemialgebraicComplex(drlm_backward_3_slope, ['f','bkpt'])   #long time
sage: complex.bfs_completion(var_value=[4/5,1/2],goto_lower_dim=True)       #long time
sage: len(complex.components)                                               #long time
43
sage: (sum(c.sage_polyhedron().plot() for c in complex.components if len(list(c.bsa.eq_poly())) == 1) + sum(c.sage_polyhedron().plot(color='red') for c in complex.components if len(list(c.bsa.eq_poly())) == 2)).show()    # not tested

sage: extc = complex.subcomplex_of_cells_with_given_region_types()          #long time
sage: len(extc.components)                                                  #long time
6
sage: boundary = extc.guess_boundary()                                      #long time
sage: sorted(boundary)                                                      #long time
[-f, -f + 4*bkpt - 1, f - bkpt]
sage: extc.bddbsa = BasicSemialgebraicSet_eq_lt_le_sets(lt=boundary)        #long time
sage: extc.is_complete()                                                    #long time, optional - mathematica
True
__dict__ = dict_proxy({'is_point_covered': <function is_point_covered>, '__module__': 'cutgeneratingfunctionology.igp', 'is_polyhedral': <function is_polyhedral>, 'is_face_to_face': <function is_face_to_face>, 'subcomplex_of_cells_with_given_region_types': <function subcomplex_of_cells_with_given_region_types>, '__doc__': "\n A proof complex for parameter space analysis.\n\n EXAMPLES::\n\n sage: from cutgeneratingfunctionology.igp import *\n sage: logging.disable(logging.WARN)\n\n sage: def vol(a,b):\n ....: P = Polyhedron(ieqs=[(0,0,1),(0,1,0),(1,-1,0),(1,0,-1),(a,-1,0),(b,0,-1)])\n ....: return P.volume()\n sage: complex = SemialgebraicComplex(vol, ['a','b'], find_region_type=result_symbolic_expression, default_var_bound=(-1,3))\n\n Breadth-first-search to complete the complex, starting at the point (a,b)=(2,1/2), using heuristic wall-crossing, considering full-dimensional cells only::\n\n sage: complex.bfs_completion(var_value=[2, 1/2], flip_ineq_step=1/1000, check_completion=False, wall_crossing_method='heuristic', goto_lower_dim=False)\n sage: sorted(c.region_type for c in complex.components)\n [(0,), (0,), (0,), (0,), (1,), (b,), (a,), (a*b,), (a*b,)]\n sage: complex.plot() # not tested\n\n Instead of heuristic method, we can use Mathematica's ``FindInstance`` to look for uncovered points in wall-crossing::\n\n sage: complex = SemialgebraicComplex(vol, ['a','b'], find_region_type=result_symbolic_expression, default_var_bound=(-1,3)) # optional - mathematica\n sage: complex.bfs_completion(var_value=[2, 1/2], flip_ineq_step=1/1000, check_completion=False, wall_crossing_method='mathematica', goto_lower_dim=True) # optional - mathematica\n sage: len(complex.components) # optional - mathematica\n 25\n sage: complex.plot(goto_lower_dim=True) # not tested\n\n The entire parameter space is covered by cells::\n\n sage: complex.is_complete() # optional - mathematica\n True\n \n Example with non-linear wall::\n\n sage: complex = SemialgebraicComplex(lambda x,y: max(x,y^2), ['x','y'], find_region_type=result_symbolic_expression, default_var_bound=(-3,3)) # optional - mathematica\n sage: complex.bfs_completion(var_value=[1,1/2], check_completion=True, wall_crossing_method='mathematica', goto_lower_dim=True) # optional - mathematica\n sage: len(complex.components) # optional - mathematica\n 3\n sage: complex.components[0].region_type # optional - mathematica\n (x,)\n sage: complex.components[1].region_type # optional - mathematica\n (y^2,)\n sage: complex.plot() # not tested\n\n\n Analyse the extreme/minimal/valid regions of a function in the Gomory-Johnson infinite group problem.\n\n Use random shooting method to complete the complex. See more options in the method ``shoot_random_points``::\n\n sage: complex = SemialgebraicComplex(drlm_backward_3_slope, ['f','bkpt'])\n sage: complex.shoot_random_points(50)\n\n Use breadth-first-search to complete the complex. See more options in the method ``bfs_completion``::\n\n sage: complex = SemialgebraicComplex(drlm_backward_3_slope, ['f','bkpt'])\n sage: complex.bfs_completion(var_value=[4/5,1/2])\n sage: len(complex.components)\n 17\n sage: complex.is_polyhedral()\n True\n sage: complex.is_face_to_face()\n False\n sage: complex2 = complex.subcomplex_of_cells_with_given_region_types({'is_extreme','not_extreme','not_minimal'})\n sage: complex2.is_face_to_face()\n True\n sage: extc = complex.subcomplex_of_cells_with_given_region_types()\n sage: len(extc.components)\n 2\n sage: extc.is_polyhedral()\n True\n sage: extc.is_face_to_face()\n True\n sage: boundary = extc.guess_boundary()\n sage: sorted(boundary, key=str)\n [-f, -f + 4*bkpt - 1, f - bkpt]\n sage: extc.bddbsa = BasicSemialgebraicSet_eq_lt_le_sets(lt=boundary)\n sage: extc.is_complete(formal_closure=False) # optional - mathematica\n False\n sage: extc.is_complete(formal_closure=True) # optional - mathematica\n True\n sage: pc = extc.polyhedral_complex()\n sage: sorted( sorted(pol.vertices_list()) for pol in pc.cells_list() )\n [[[0, 0]],\n [[0, 0], [0, 1/4]],\n [[0, 0], [0, 1/4], [1/7, 2/7]],\n [[0, 0], [1/7, 2/7]],\n [[0, 0], [1/7, 2/7], [1/3, 1/3]],\n [[0, 0], [1/3, 1/3]],\n [[0, 1/4]],\n [[0, 1/4], [1/7, 2/7]],\n [[1/7, 2/7]],\n [[1/7, 2/7], [1/3, 1/3]],\n [[1/3, 1/3]]]\n\n Consider low-dimensional cells in the polyhedral case::\n\n sage: complex = SemialgebraicComplex(drlm_backward_3_slope, ['f','bkpt']) #long time\n sage: complex.bfs_completion(var_value=[4/5,1/2],goto_lower_dim=True) #long time\n sage: len(complex.components) #long time\n 43\n sage: (sum(c.sage_polyhedron().plot() for c in complex.components if len(list(c.bsa.eq_poly())) == 1) + sum(c.sage_polyhedron().plot(color='red') for c in complex.components if len(list(c.bsa.eq_poly())) == 2)).show() # not tested\n\n sage: extc = complex.subcomplex_of_cells_with_given_region_types() #long time\n sage: len(extc.components) #long time\n 6\n sage: boundary = extc.guess_boundary() #long time\n sage: sorted(boundary) #long time\n [-f, -f + 4*bkpt - 1, f - bkpt]\n sage: extc.bddbsa = BasicSemialgebraicSet_eq_lt_le_sets(lt=boundary) #long time\n sage: extc.is_complete() #long time, optional - mathematica\n True\n ", 'add_new_component': <function add_new_component>, '__dict__': <attribute '__dict__' of 'SemialgebraicComplex' objects>, 'find_uncovered_random_point': <function find_uncovered_random_point>, '__weakref__': <attribute '__weakref__' of 'SemialgebraicComplex' objects>, '__init__': <function __init__>, 'plot': <function plot>, 'guess_boundary': <function guess_boundary>, 'bfs_completion': <function bfs_completion>, 'find_uncovered_point_mathematica': <function find_uncovered_point_mathematica>, 'subcomplexes_of_cells_with_given_region_types': <function subcomplexes_of_cells_with_given_region_types>, 'cells_containing_point': <function cells_containing_point>, 'generate_random_var_value': <function generate_random_var_value>, '__repr__': <function __repr__>, 'plot_bfs_tree': <function plot_bfs_tree>, 'polyhedral_complex': <function polyhedral_complex>, 'is_complete': <function is_complete>, 'shoot_random_points': <function shoot_random_points>})
__init__(family, var_name=None, find_region_type=None, default_var_bound=(-0.100000000000000, 1.10000000000000), bddbsa=None, polynomial_map=None, kwds_dict={}, cell_class=None, **opt_non_default)

Construct a SemialgebraicComplex.

  • family: A class or constructor, defining a parametric family of computations
  • var_name: a subset of the parameters of family
  • find_region_type: maps the object constructed by family to a type of the parameter region;
    • set to None for functions in Gomory-Johnson model;
    • often set to result_symbolic_expression or result_concrete_value for other functions;
  • default_var_bound: need if we use random shooting method to complete the complex; If given, the bound is also used in plotting

The following argument defines the boundary of the SemialgebraicComplex, so that bfs won’t go beyond the region. They might be useful in the CPL3 examples.

  • bddbsa: a BasicSemialgebraicSet that contains the points in the complex;
  • polynomial_map: need when bddbsa is lower dimensional.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: complex = SemialgebraicComplex(lambda x,y: max(x,y), ['x','y'], find_region_type=result_symbolic_expression, default_var_bound=(-10,10))
__module__ = 'cutgeneratingfunctionology.igp'
__repr__()

File: sage/structure/sage_object.pyx (starting at line 145)

Default method for string representation.

Note

Do not overwrite this method. Instead, implement a _repr_ (single underscore) method.

EXAMPLES:

By default, the string representation coincides with the output of the single underscore _repr_:

sage: P.<x> = QQ[]
sage: repr(P) == P._repr_()  #indirect doctest
True

Using rename(), the string representation can be customized:

sage: P.rename('A polynomial ring')
sage: repr(P) == P._repr_()
False

The original behaviour is restored with reset_name().:

sage: P.reset_name()
sage: repr(P) == P._repr_()
True

If there is no _repr_ method defined, we fall back to the super class (typically object):

sage: from sage.structure.sage_object import SageObject
sage: S = SageObject()
sage: S
<sage.structure.sage_object.SageObject object at ...>
__weakref__

list of weak references to the object (if defined)

add_new_component(var_value, bddbsa=None, polynomial_map=None, pos_poly=None, flip_ineq_step=0, wall_crossing_method=None, goto_lower_dim=False, num_eq=None)

Compute one proof cell around var_value. Append this cell to the complex.

  • bddbsa defines the boundary constraints satisfied by the cell. By default, bddbsa=None, and complex.bddbsa is taken.
  • If flip_ineq_step = 0, do not search for neighbour testpoints. Used in shoot_random_points(). wall_crossing_method = None in this case.
  • If flip_ineq_step > 0, search for neighbour testpoints using wall_crossing_method = ‘mathematica’ or ‘heuristic’ or ‘heuristic_then_mathematica’. Used in bfs. If goto_lower_dim is False or (goto_lower_dim is True and wall_crossing method = ‘heuristic’ but wall is non-linear), then find new testpoints across the wall only.
  • pos_poly is a polynomial. var_value was found by crossing pos_poly < 0 from another cell. The new test points return by new_component.find_neighbour_candidates must satisfy pos_poly(new test point) > 0.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: complex = SemialgebraicComplex(lambda x,y: max(x,y), ['x','y'], find_region_type=result_symbolic_expression, default_var_bound=(-10,10))
sage: complex.add_new_component([1,2], bddbsa=None, flip_ineq_step=1/10, wall_crossing_method='heuristic', goto_lower_dim=True) # the cell {(x,y): x<y}
sage: sorted(complex.components[0].bsa.lt_poly())
[x - y]
sage: complex.components[0].neighbour_points
[(31/20, 29/20), (3/2, 3/2)]
sage: list(complex.points_to_test[0].keys())
[(31/20, 29/20)]
sage: list(complex.points_to_test[1].keys())
[(3/2, 3/2)]

sage: complex = SemialgebraicComplex(lambda x,y: max(x,y^2), ['x','y'], find_region_type=result_symbolic_expression, default_var_bound=(-10,10))        # optional - mathematica
sage: complex.add_new_component([1,1/2], bddbsa=None, flip_ineq_step=1/10, wall_crossing_method='mathematica', goto_lower_dim=False) # the cell {(x,y): x > y^2}      # optional - mathematica
sage: list(complex.components[0].bsa.lt_poly()) # optional - mathematica
[y^2 - x]
sage: list(complex.points_to_test[0].keys()) # optional - mathematica
[(19/20, 1)]
bfs_completion(var_value=None, flip_ineq_step=1/100, check_completion=False, wall_crossing_method='heuristic', goto_lower_dim=False, max_failings=0)

Breadth-first-search to complete the complex.

  • var_value: the starting point. If not given, start with a random point.
  • flip_ineq_step: a small positive number that controls the step length in wall-crossing.
  • check_completion: When check_completion is True, after bfs terminates, check whether the entire parameter space is covered by cells, using Mathematica’s FindInstance (if max_failings=0) or random shooting (if max_failings>0). If an uncovered point has been found, restart the bfs from this point.
  • wall_crossing_method: ‘mathematica’ or ‘heuristic’ or ‘heuristic_then_mathematica’
    • wall_crossing_method=’heuristic_then_mathematica’: try heuristic method first. If it does not find a new testpoint, then use Mathematica.
  • goto_lower_dim: whether lower dimensional cells are considered. If goto_lower_dim is False or if goto_lower_dim is True and wall_crossing method is ‘heuristic’ but the wall is non-linear, then find new testpoint across the wall only.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: complex = SemialgebraicComplex(lambda x,y: min(x^2+ 4*y^2, 4), ['x','y'], find_region_type=result_symbolic_expression, default_var_bound=(-3,3))    # optional - mathematica

When using mathematica’s FindInstance, the returned test point may not be rational. In this example, complex.components[1].var_value is (0, sqrt(799/800)), which is then cast to AA using the function from_mathematica():

sage: complex.bfs_completion(check_completion=True, wall_crossing_method='mathematica', goto_lower_dim=True)  # optional - mathematica
sage: len(complex.components)                               # optional - mathematica
3
sage: complex.plot(goto_lower_dim=True)                     # not tested

sage: complex = SemialgebraicComplex(lambda x,y: min(x+ 4*y, 4), ['x','y'], find_region_type=result_symbolic_expression, default_var_bound=(-5,5))
sage: complex.bfs_completion(var_value=[1,1])
sage: len(complex.components)
2
sage: complex.plot()                                        # not tested

See more examples in the docstring of the class SemialgebraicComplex.

cells_containing_point(var_value)

Yield the cells of the complex that contain the given point var_value.

Inequalities are considered strict.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: complex = SemialgebraicComplex(lambda x,y: max(x,y), ['x','y'], find_region_type=result_symbolic_expression, default_var_bound=(-10,10))
sage: complex.add_new_component([1,2], bddbsa=None, flip_ineq_step=0, wall_crossing_method=None, goto_lower_dim=False) # the cell {(x,y): x<y}
sage: cell = next(complex.cells_containing_point([2,3]))
sage: list(cell.var_value)
[1, 2]
sage: cell = next(complex.cells_containing_point([sqrt(2), sqrt(3)]))
sage: list(cell.var_value)
[1, 2]
find_uncovered_point_mathematica(formal_closure=False)

Call Mathematica FindInstance to get a point that satisfies self.bddbsa and is uncovered by any cells in the complex.

The argument formal_closure whether inequalities are treated as <= 0 or as < 0. If such point does not exist, return None.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: complex = SemialgebraicComplex(lambda x,y: max(x,y), ['x','y'], find_region_type=result_symbolic_expression, default_var_bound=(-10,10)) # optional - mathematica
sage: complex.add_new_component([1,2], bddbsa=None, flip_ineq_step=0, wall_crossing_method=None, goto_lower_dim=False) # the cell {(x,y): x<y} # optional - mathematica
sage: var_value = complex.find_uncovered_point_mathematica(formal_closure=True) # optional - mathematica
sage: var_value # optional - mathematica
(0, -1)
sage: complex.is_point_covered(var_value) # optional - mathematica
False
find_uncovered_random_point(var_bounds=None, max_failings=10000)

Return a random point that satisfies the bounds and is uncovered by any cells in the complex. Return None if the number of attemps > max_failings.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: complex = SemialgebraicComplex(lambda x,y: max(x,y), ['x','y'], find_region_type=result_symbolic_expression, default_var_bound=(-10,10))
sage: complex.add_new_component([1,2], bddbsa=None, flip_ineq_step=0, wall_crossing_method=None, goto_lower_dim=False) # the cell {(x,y): x<y}
sage: var_value = complex.find_uncovered_random_point(max_failings=100)
sage: complex.is_point_covered(var_value)
False
generate_random_var_value(var_bounds=None)

Return a random point that satisfies var_bounds and is in self.bsa.

  • If var_bounds is not specified, self.default_var_bound is taken.
  • var_bounds can be a list of 2-tuples whose length equals to the number of parameters, or lambda functions.
  • It is used in random shooting method for functions like dg_2_step_mir, which involve floor/ceil operations. We try to plot one layer for each n = floor(…) and superimpose the layers at the end to get the whole picture.

Notice that if self.bddbsa.eq_poly() is not empty, it never ends.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: complex = SemialgebraicComplex(lambda x,y: max(x,y), ['x','y'], find_region_type=result_symbolic_expression, default_var_bound=(-10,10))
sage: random_point = complex.generate_random_var_value()
sage: all(complex.default_var_bound[0] < random_point[i] < complex.default_var_bound[1] for i in [0,1])
True
sage: var_bounds=[(0,1),((lambda x: x/2), (lambda x: x))]
sage: random_point = complex.generate_random_var_value(var_bounds=var_bounds)
sage: (0 < random_point[0] < 1) and (random_point[0]/2 < random_point[1] < random_point[0])
True
guess_boundary()
is_complete(formal_closure=False)

Return whether the entire parameter space satisfying self.bddbsa is covered by cells.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: complex = SemialgebraicComplex(lambda x,y: min(x+ 4*y, 4), ['x','y'], find_region_type=result_symbolic_expression, default_var_bound=(-5,5))    # optional - mathematica
sage: complex.bfs_completion(var_value=[1,1], goto_lower_dim=False)  # optional - mathematica
sage: complex.is_complete(formal_closure=True)                       # optional - mathematica
True
sage: complex.is_complete()   # optional - mathematica
False
is_face_to_face()
is_point_covered(var_value)

Return whether the given point var_value is contained in any cell of the complex.

Inequalities are considered strict.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: complex = SemialgebraicComplex(lambda x,y: max(x,y), ['x','y'], find_region_type=result_symbolic_expression, default_var_bound=(-10,10))
sage: complex.add_new_component([1,2], bddbsa=None, flip_ineq_step=0, wall_crossing_method=None, goto_lower_dim=False) # the cell {(x,y): x<y}
sage: complex.is_point_covered([2,3])
True
sage: complex.is_point_covered([3,2])
False
sage: complex.is_point_covered([2,2])
False
sage: complex.is_point_covered([sqrt(2), sqrt(3)])
True
is_polyhedral()
plot(alpha=0.500000000000000, plot_points=300, slice_value=None, goto_lower_dim=False, restart=True, **kwds)

Plot the complex and store the graph.

  • If restart is False, plot the newly added cells on top of the last graph; otherwise, start a new graph.
  • If slice_value is given, it is either a polynomial_map that defines a section, or a list of fixed parameter values with two of them being None. Plot the section.
  • plot_points controls the quality of the plotting.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: complex = SemialgebraicComplex(lambda x,y,z: min(x^2,y^2,z), ['x','y','z'], find_region_type=result_symbolic_expression, default_var_bound=(-10,10))    # not tested
sage: complex.bfs_completion(goto_lower_dim=True)             # not tested
sage: Q.<u,v> = QQ[]                                          # not tested

Plot the slice in (x,y)-space with z=4 (the following two ways give the same thing):

sage: complex.plot(slice_value=[None, None, 4])          # not tested
sage: complex.plot(slice_value=[u, v, 4])                # not tested

Plot the slice in (y,z)-space with x=4 (the following two ways give the same thing):

sage: complex.plot(slice_value=[4, None, None])          # not tested
sage: complex.plot(slice_value=[4, u, v])                # not tested

Plot the slice in (x,y)-space with z=y:

sage: complex.plot(slice_value=[u, v, v])                # not tested

Plot the slice in (x,z)-space with y=x/2:

sage: complex.plot(slice_value=[u, u/2, v])              # not tested
plot_bfs_tree(**kwds)

Plot the bfs tree provided that the complex is 2-dimensional.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: complex = SemialgebraicComplex(drlm_backward_3_slope, ['f','bkpt'])
sage: complex.bfs_completion(var_value=[4/5,1/2],flip_ineq_step=1/20)    #long time
sage: g = complex.plot_bfs_tree()
polyhedral_complex()

Assume that the cells in the SemialgebraicComplex are polyhedral and face-to-face. Return the PolyhedralComplex.

shoot_random_points(num, var_bounds=None, max_failings=1000)

Complete the complex by randomly shooting points.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)                   # not tested
sage: complex = SemialgebraicComplex(lambda x,y: max(x,y), ['x','y'], find_region_type=result_symbolic_expression, default_var_bound=(-10,10))      # not tested
sage: complex.shoot_random_points(100)                # not tested
sage: complex.plot()                                  # not tested

sage: complex = SemialgebraicComplex(lambda x,y: max(x,y^2), ['x','y'], find_region_type=result_symbolic_expression, default_var_bound=(-10,10))
sage: complex.shoot_random_points(100)                # not tested
subcomplex_of_cells_with_given_region_types(given_region_types=set(['is_extreme']))
subcomplexes_of_cells_with_given_region_types()

Return a dictionary mapping region types to subcomplexes.

class cutgeneratingfunctionology.igp.SemialgebraicComplexComponent(K, region_type, bddbsa=None, polynomial_map=None)

Bases: sage.structure.sage_object.SageObject

A proof cell for parameter space analysis.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: def foo(x,y):
....:     return (x+y < 2) and (y^2 < x)
sage: K.<x,y> = ParametricRealField([1,1/2])
sage: region_type = foo(*K.gens())
sage: component = SemialgebraicComplexComponent(K, region_type)
sage: list(component.bsa.lt_poly())
[x + y - 2, y^2 - x]
sage: component.plot(xmin=0, xmax=4, ymin=-3, ymax=3)        # not tested
sage: new_points = component.find_neighbour_candidates(1/4, 'heuristic', goto_lower_dim=False, pos_poly=None)
sage: new_pts = sorted(new_points[0].keys())
sage: new_pts
[(30093/42985, 54831/63571), (11/8, 7/8)]
sage: len(new_pts)
2
sage: all((xx + yy - 2)*(yy^2 - xx) < 0 for (xx, yy) in new_pts)
True
sage: more_new_points = component.find_neighbour_candidates(1/4, 'mathematica', goto_lower_dim=True, pos_poly=None)  # optional - mathematica
sage: sorted(more_new_points[0].keys())  # optional - mathematica
[(17/8, 0), (2065/512, -33/16)]
sage: sorted(more_new_points[1].keys())  # optional - mathematica
[(0, 0), (2, 0)]

sage: K.<x,y> = ParametricRealField([1,1/2])
sage: region_type = foo(*K.gens())
sage: x == 2*y
True
sage: sorted(K._bsa.eq_poly()), sorted(K._bsa.lt_poly()), sorted(K._bsa.le_poly())
([x - 2*y], [3*x - 4, y^2 - x], [])

Without using BasicSemialgebraicSet_local, we got:

sage: xx = K._bsa.poly_ring().gens()[0]; polynomial_map = [xx, 1/2*xx]
sage: component = SemialgebraicComplexComponent(K, region_type, polynomial_map=polynomial_map)
sage: sorted(component.bsa.lt_poly())
[3*x - 4, y^2 - x]

With using BasicSemialgebraicSet_local:

sage: component = SemialgebraicComplexComponent(K, region_type)
sage: sorted(component.bsa.lt_poly())
[-x, 3*x - 4]

In ProofCell region_type should alreay consider the polynomial_map:

sage: K.<x,y> = ParametricRealField([1,1/2])
sage: assert(x == 2*y)
sage: region_type = foo(K.gens()[0], 1/2*K.gens()[0])
sage: sorted(K._bsa.eq_poly()), sorted(K._bsa.lt_poly()), sorted(K._bsa.le_poly())
([x - 2*y], [-x, 3*x - 4], [])
sage: xx = K._bsa.poly_ring().gens()[0]; polynomial_map = [xx, 1/2*xx]
sage: component = SemialgebraicComplexComponent(K, region_type, polynomial_map=polynomial_map)
sage: sorted(component.bsa.lt_poly())
[-x, 3*x - 4]
__dict__ = dict_proxy({'plot': <function plot>, '__module__': 'cutgeneratingfunctionology.igp', 'sage_polyhedron': <function sage_polyhedron>, 'is_polyhedral': <function is_polyhedral>, 'find_neighbour_candidates': <function find_neighbour_candidates>, '__repr__': <function __repr__>, '__dict__': <attribute '__dict__' of 'SemialgebraicComplexComponent' objects>, '__weakref__': <attribute '__weakref__' of 'SemialgebraicComplexComponent' objects>, '__doc__': "\n A proof cell for parameter space analysis.\n\n EXAMPLES::\n\n sage: from cutgeneratingfunctionology.igp import *\n sage: logging.disable(logging.WARN)\n sage: def foo(x,y):\n ....: return (x+y < 2) and (y^2 < x)\n sage: K.<x,y> = ParametricRealField([1,1/2])\n sage: region_type = foo(*K.gens())\n sage: component = SemialgebraicComplexComponent(K, region_type)\n sage: list(component.bsa.lt_poly())\n [x + y - 2, y^2 - x]\n sage: component.plot(xmin=0, xmax=4, ymin=-3, ymax=3) # not tested\n sage: new_points = component.find_neighbour_candidates(1/4, 'heuristic', goto_lower_dim=False, pos_poly=None)\n sage: new_pts = sorted(new_points[0].keys())\n sage: new_pts\n [(30093/42985, 54831/63571), (11/8, 7/8)]\n sage: len(new_pts)\n 2\n sage: all((xx + yy - 2)*(yy^2 - xx) < 0 for (xx, yy) in new_pts)\n True\n sage: more_new_points = component.find_neighbour_candidates(1/4, 'mathematica', goto_lower_dim=True, pos_poly=None) # optional - mathematica\n sage: sorted(more_new_points[0].keys()) # optional - mathematica\n [(17/8, 0), (2065/512, -33/16)]\n sage: sorted(more_new_points[1].keys()) # optional - mathematica\n [(0, 0), (2, 0)]\n\n sage: K.<x,y> = ParametricRealField([1,1/2])\n sage: region_type = foo(*K.gens())\n sage: x == 2*y\n True\n sage: sorted(K._bsa.eq_poly()), sorted(K._bsa.lt_poly()), sorted(K._bsa.le_poly())\n ([x - 2*y], [3*x - 4, y^2 - x], [])\n\n Without using BasicSemialgebraicSet_local, we got::\n\n sage: xx = K._bsa.poly_ring().gens()[0]; polynomial_map = [xx, 1/2*xx]\n sage: component = SemialgebraicComplexComponent(K, region_type, polynomial_map=polynomial_map)\n sage: sorted(component.bsa.lt_poly())\n [3*x - 4, y^2 - x]\n\n With using BasicSemialgebraicSet_local::\n\n sage: component = SemialgebraicComplexComponent(K, region_type)\n sage: sorted(component.bsa.lt_poly())\n [-x, 3*x - 4]\n\n In ProofCell region_type should alreay consider the polynomial_map::\n\n sage: K.<x,y> = ParametricRealField([1,1/2])\n sage: assert(x == 2*y)\n sage: region_type = foo(K.gens()[0], 1/2*K.gens()[0])\n sage: sorted(K._bsa.eq_poly()), sorted(K._bsa.lt_poly()), sorted(K._bsa.le_poly())\n ([x - 2*y], [-x, 3*x - 4], [])\n sage: xx = K._bsa.poly_ring().gens()[0]; polynomial_map = [xx, 1/2*xx]\n sage: component = SemialgebraicComplexComponent(K, region_type, polynomial_map=polynomial_map)\n sage: sorted(component.bsa.lt_poly())\n [-x, 3*x - 4]\n ", '__init__': <function __init__>})
__init__(K, region_type, bddbsa=None, polynomial_map=None)

x.__init__(…) initializes x; see help(type(x)) for signature

__module__ = 'cutgeneratingfunctionology.igp'
__repr__()

File: sage/structure/sage_object.pyx (starting at line 145)

Default method for string representation.

Note

Do not overwrite this method. Instead, implement a _repr_ (single underscore) method.

EXAMPLES:

By default, the string representation coincides with the output of the single underscore _repr_:

sage: P.<x> = QQ[]
sage: repr(P) == P._repr_()  #indirect doctest
True

Using rename(), the string representation can be customized:

sage: P.rename('A polynomial ring')
sage: repr(P) == P._repr_()
False

The original behaviour is restored with reset_name().:

sage: P.reset_name()
sage: repr(P) == P._repr_()
True

If there is no _repr_ method defined, we fall back to the super class (typically object):

sage: from sage.structure.sage_object import SageObject
sage: S = SageObject()
sage: S
<sage.structure.sage_object.SageObject object at ...>
__weakref__

list of weak references to the object (if defined)

find_neighbour_candidates(flip_ineq_step, wall_crossing_method='heuristic', goto_lower_dim=False, pos_poly=None)

Try flipping exactly one inequality at one time, to reach a new testpoint as neighbour candidate.

  • flip_ineq_step defines the step length
  • wall_crossing_method is ‘heuristic’ or ‘mathematica’ or ‘heuristic_then_mathematica’
  • if goto_lower_dim=False, the cell is considered as its formal closure, so no recursion into test points in lower dimensional cells.
  • pos_poly is a polynomial. The return test point must satisfy pos_poly(new test point) > 0.

OUTPUT new_points is a dictionary of dictionaries. The new_points[i] is a dictionay whose keys = candidate neighbour testpoints, values = (bddbsa whose eq_poly has i elements, polynomial_map, no_crossing_l) of the candidate neighbour cell that contains the candidate neighbour testpoint. bddbsa is recorded so that (1) complex.bddbsa is always respected; and (2) can recursively go into lower dimensional cells. polynomial_map is recorded and passed to the constructor of the neighbour cell. no_crossing is passed to the neighour cell for its find_neighbour_candidates method. We no longer update self.bsa by removing (obvious) redundant eq, lt, le constraints from its description at the end, even when ‘mathematica’ is used.

is_polyhedral()
plot(alpha=0.500000000000000, plot_points=300, slice_value=None, default_var_bound=None, show_testpoints=True, goto_lower_dim=False, zorder=0, **kwds)

Plot the cell.

  • If slice_value is given, it is either a polynomial_map that defines a section, or a list of fixed parameter values with two of them being None. Plot the section. See examples in SemialgebraicComplex.plot().
  • show_testpoints controls whether to plot the testpoint in this cell.
  • plot_points controls the quality of the plotting.
  • goto_lower_dim controls whether strict and non-strict inequalies are plotted with different colors.
sage_polyhedron()
class cutgeneratingfunctionology.igp.SubadditivityTestTree(fn, intervals=((0, 1), (0, 1), (0, 2)), global_upper_bound=0, objective_limit=0, use_symmetry=False)

Class for spatial branch and bound for subadditivity testing.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = not_minimal_1()
sage: T = SubadditivityTestTree(h, objective_limit=-1000)
sage: T.minimum(max_number_of_bkpts=0, search_method='BB')
-1/5
sage: T = SubadditivityTestTree(h)
sage: T.is_subadditive()
False

sage: h = kzh_7_slope_1()
sage: T1 = SubadditivityTestTree(h, use_symmetry = False)
sage: T1.is_subadditive()
True
sage: T1.height, len(T1.complete_node_set)
(16, 1447)

sage: T2 = SubadditivityTestTree(h, use_symmetry = True)
sage: T2.is_subadditive()
True
sage: T2.height, len(T2.complete_node_set)
(13, 749)
__init__(fn, intervals=((0, 1), (0, 1), (0, 2)), global_upper_bound=0, objective_limit=0, use_symmetry=False)
__module__ = 'cutgeneratingfunctionology.igp'
generate_covered_components_big_cell(search_method='BB', **kwds)

Generate covered components stratigically using big cell.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = kzh_7_slope_1()
sage: T = SubadditivityTestTree(h,use_symmetry = True)
sage: covered_components_1 = T.generate_covered_components_big_cell()
sage: covered_components_2 = generate_covered_components(h)
sage: covered_components_3 = generate_covered_components_strategically(h)
sage: set(tuple(c) for c in covered_components_1) == set(tuple(c) for c in covered_components_2)
False
sage: set(tuple(c) for c in covered_components_1) == set(tuple(c) for c in covered_components_3)
True
generate_maximal_additive_faces(search_method='BB', **kwds)
is_subadditive(stop_if_fail=False, cache_additive_vertices=False, search_method='BB', **kwds)

Check whether the mininum of delta pi is no smaller than objective_limit. If the parameter cache_additive_vertices is True, then we cache vertices where delta pi equals objective_limit.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = not_minimal_1()
sage: T = SubadditivityTestTree(h)
sage: T.minimum()
-1/5
sage: T = SubadditivityTestTree(h, objective_limit=-1/5)
sage: T.is_subadditive()
True
sage: T = SubadditivityTestTree(h, objective_limit=0)
sage: T.is_subadditive()
False

sage: T = SubadditivityTestTree(h, objective_limit=-1/5)
sage: T.is_subadditive(cache_additive_vertices=True)
True
sage: T.additive_vertices
{(1/5, 1/5)}
sage: h(1/5)+h(1/5)-h(2/5) == T.objective_limit
True
minimum(search_method='BB', **kwds)
next_level(node_set, search_method='BB', find_min=True, stop_only_if_strict=True, **kwds)

Generate nodes in the next level.

node_branching(node, search_method='BB', find_min=True, stop_only_if_strict=True, **kwds)

Branch on a given node, dependent on current self.global_upper_bound.

number_of_leaves()
number_of_nodes()
plot_current_regions(colorful=False, **kwds)
class cutgeneratingfunctionology.igp.SubadditivityTestTreeGeneral(fn, intervals=((0, 1), (0, 1), (0, 2)), global_upper_bound=0, objective_limit=0)

Class for spatial branch and bound for subadditivity testing handling discontinuous cases.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = drlm_2_slope_limit()
sage: T = SubadditivityTestTreeGeneral(h)
sage: T.minimum()
0
sage: len(T.complete_node_set)
203
sage: T = SubadditivityTestTreeGeneral(h)
sage: T.minimum(max_number_of_bkpts = 10000,solver = 'ppl')
0
sage: len(T.complete_node_set)
183

sage: T = SubadditivityTestTreeGeneral(h)
sage: T.is_subadditive()
True
__init__(fn, intervals=((0, 1), (0, 1), (0, 2)), global_upper_bound=0, objective_limit=0)
__module__ = 'cutgeneratingfunctionology.igp'
is_subadditive(stop_if_fail=False, cache_additive_vertices=False, search_method='BB', **kwds)
minimum(search_method='BB', **kwds)
node_branching(node, search_method='BB', find_min=True, stop_only_if_strict=True, **kwds)
number_of_leaves()
number_of_nodes()
class cutgeneratingfunctionology.igp.SubadditivityTestTreeNode(fn, level, intervals, use_symmetry=False)

Bases: object

Class for the node in the spatial branch and bound tree for subadditivity testing.

Each node N has the following attributes:

  • N.affine_estimators = [[slope_I, intercept_I], [slope_J, intercept_J], [slope_K, intercept_K]] describes affine linear underestimators for \(\pi\) on the restrictions to intervals \(I\) and \(J\) and an overestimator for \(pi\) on the restriction to the interval \(K\).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = kzh_7_slope_1()
sage: T = SubadditivityTestTree(h)
sage: T.is_subadditive()
True
sage: # check affine_estimators are exact functions if the node is indivisible.
sage: for node in T.leaf_set:
....:     if not node.is_divisible():
....:         break
sage: slope_I, intercept_I = node.affine_estimators[0]
sage: slope_I*node.I_bkpts()[0]+intercept_I == node.I_values()[0]
True
sage: slope_I*node.I_bkpts()[1]+intercept_I == node.I_values()[1]
True
sage: slope_J, intercept_J = node.affine_estimators[1]
sage: slope_J*node.J_bkpts()[0]+intercept_J == node.J_values()[0]
True
sage: slope_J*node.J_bkpts()[1]+intercept_J == node.J_values()[1]
True
sage: slope_K, intercept_K = node.affine_estimators[2]
sage: slope_K*node.K_bkpts()[0]+intercept_K == node.K_values()[0]
True
sage: slope_K*node.K_bkpts()[1]+intercept_K == node.K_values()[1]
True
I_bkpts()
I_slope_set()
I_values()
J_bkpts()
J_slope_set()
J_values()
K_bkpts()
K_slope_set()
K_values()
__dict__ = dict_proxy({'__module__': 'cutgeneratingfunctionology.igp', '__ne__': <function __ne__>, 'K_bkpts': <function K_bkpts>, '__dict__': <attribute '__dict__' of 'SubadditivityTestTreeNode' objects>, 'I_bkpts': <function I_bkpts>, 'delta_pi_upper_bound': <function delta_pi_upper_bound>, 'I_values': <function I_values>, 'verify_vertices': <function verify_vertices>, '__lt__': <function __lt__>, '__weakref__': <attribute '__weakref__' of 'SubadditivityTestTreeNode' objects>, '__init__': <function __init__>, 'plot': <function plot>, 'K_values': <function K_values>, '__eq__': <function __eq__>, 'delta_pi_fast_affine_lower_bound': <function delta_pi_fast_affine_lower_bound>, 'verify_estimators': <function verify_estimators>, 'new_intervals': <function new_intervals>, 'J_values': <function J_values>, '__doc__': '\n Class for the node in the spatial branch and bound tree for subadditivity testing.\n\n Each node ``N`` has the following attributes:\n\n - ......\n\n - ``N.affine_estimators = [[slope_I, intercept_I], [slope_J, intercept_J], [slope_K, intercept_K]]``\n describes affine linear underestimators for `\\pi` on the restrictions to intervals `I` and `J`\n and an overestimator for `pi` on the restriction to the interval `K`.\n\n\n EXAMPLES::\n\n sage: from cutgeneratingfunctionology.igp import *\n sage: logging.disable(logging.INFO)\n sage: h = kzh_7_slope_1()\n sage: T = SubadditivityTestTree(h)\n sage: T.is_subadditive()\n True\n sage: # check affine_estimators are exact functions if the node is indivisible.\n sage: for node in T.leaf_set:\n ....: if not node.is_divisible():\n ....: break\n sage: slope_I, intercept_I = node.affine_estimators[0]\n sage: slope_I*node.I_bkpts()[0]+intercept_I == node.I_values()[0]\n True\n sage: slope_I*node.I_bkpts()[1]+intercept_I == node.I_values()[1]\n True\n sage: slope_J, intercept_J = node.affine_estimators[1]\n sage: slope_J*node.J_bkpts()[0]+intercept_J == node.J_values()[0]\n True\n sage: slope_J*node.J_bkpts()[1]+intercept_J == node.J_values()[1]\n True\n sage: slope_K, intercept_K = node.affine_estimators[2]\n sage: slope_K*node.K_bkpts()[0]+intercept_K == node.K_values()[0]\n True\n sage: slope_K*node.K_bkpts()[1]+intercept_K == node.K_values()[1]\n True\n ', 'K_slope_set': <function K_slope_set>, 'delta_pi_fast_lower_bound': <function delta_pi_fast_lower_bound>, 'J_bkpts': <function J_bkpts>, '__gt__': <function __gt__>, 'is_fathomed': <function is_fathomed>, 'delta_pi_constant_lower_bound': <function delta_pi_constant_lower_bound>, 'delta_pi_lower_bound': <function delta_pi_lower_bound>, 'generate_children': <function generate_children>, 'is_divisible': <function is_divisible>, 'delta_pi_affine_lower_bound': <function delta_pi_affine_lower_bound>, '__le__': <function __le__>, 'J_slope_set': <function J_slope_set>, 'I_slope_set': <function I_slope_set>, '__hash__': <function __hash__>, 'delta_pi_trivial_affine_lower_bound': <function delta_pi_trivial_affine_lower_bound>, 'branching_direction': <function branching_direction>, '__ge__': <function __ge__>})
__eq__(other)

x.__eq__(y) <==> x==y

__ge__(other)

x.__ge__(y) <==> x>=y

__gt__(other)

x.__gt__(y) <==> x>y

__hash__() <==> hash(x)
__init__(fn, level, intervals, use_symmetry=False)

x.__init__(…) initializes x; see help(type(x)) for signature

__le__(other)

x.__le__(y) <==> x<=y

__lt__(other)

x.__lt__(y) <==> x<y

__module__ = 'cutgeneratingfunctionology.igp'
__ne__(other)

x.__ne__(y) <==> x!=y

__weakref__

list of weak references to the object (if defined)

branching_direction()
delta_pi_affine_lower_bound(solver='Coin')

Compute the best lower bound of delta pi if using affine estimators, by solving an LP. The bound is guaranteed to be no worse than any other bounds in this code. The second output is the slope and intercept values of three estimators.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = kzh_7_slope_1()
sage: T = SubadditivityTestTree(h)
sage: T.is_subadditive()
True
sage: N = T.root.left_child.right_child.left_child.right_child.left_child.right_child
sage: lb, estimators = N.delta_pi_affine_lower_bound('PPL')
sage: lb
-1/3
sage: estimators
[[-5/2, 4/3], [-5/2, 4/3], [-5/2, 3]]
sage: N.delta_pi_affine_lower_bound('PPL')[0] > N.delta_pi_fast_lower_bound()[0]
True
delta_pi_constant_lower_bound()

Compute the constant lower bound of delta pi in the current region defined by self.intervals. The bound is (min of fn on proj(I)) + (min of fn on proj(J)) - (max of fn on proj(K)). The second output is the slope and intercept values of three estimators.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = kzh_7_slope_1()
sage: T = SubadditivityTestTree(h)
sage: T.is_subadditive()
True
sage: T.height
16
sage: N = T.root.left_child.right_child.left_child.right_child.left_child.right_child
sage: N.intervals
((13/33, 16/33), (14/33, 1), (0, 1))
sage: N.projections
[[13/33, 16/33], [14/33, 20/33], [9/11, 1]]
sage: lb, estimators = N.delta_pi_constant_lower_bound() # min([13/33, 16/33]) + min([14/33, 20/33]) - max([9/11, 1])
sage: lb
-9/22
sage: estimators
[[0, 13/66], [0, 13/66], [0, 53/66]]
delta_pi_fast_affine_lower_bound(slope_I, slope_J, slope_K)

If the slopes of the affine estimators are fixed, then compute the best intersepts first. Then compute the affine lower bound of delta pi. Note that if slope_I=slope_J=slope_K=0, then the bound is the constant bound. The second output is the slope and intercept values of three estimators.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = kzh_7_slope_1()
sage: T = SubadditivityTestTree(h)
sage: T.is_subadditive()
True
sage: N = T.root.left_child.right_child.left_child.right_child.left_child.right_child
sage: N.delta_pi_fast_affine_lower_bound(0,0,0) == N.delta_pi_constant_lower_bound()
True
delta_pi_fast_lower_bound()

Choose the better bound between constant and trivial affine lower bounds. The second output is the slope and intercept values of three estimators.

delta_pi_lower_bound(max_number_of_bkpts=0, solver='Coin')

Strategic lower bound of delta pi. If the total number of bkpts in I,J,K is small, use affine bound by solving the LP. Use constant bound if max_number_of_bkpts=0. Otherwise use delta_pi_fast_lower_bound.

delta_pi_trivial_affine_lower_bound()

One heuristic affine lower bound of delta pi. Each affine estimator’s slope is fixed and depends on the two endpoints of the corresponding interval. Time complexity is the same as constant lower bound. No guarantee that the bound is better than constant lower bound. The second output is the slope and intercept values of three estimators.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = kzh_7_slope_1()
sage: T = SubadditivityTestTree(h)
sage: T.is_subadditive()
True
sage: N = T.root.left_child.right_child.left_child.right_child.left_child.right_child
sage: lb, estimators = N.delta_pi_trivial_affine_lower_bound()
sage: lb
-13/18
sage: estimators
[[7/6, -1/3], [-19/12, 11/12], [-41/12, 35/9]]
delta_pi_upper_bound()

Compute the upper bound of delta pi based on the values of delta pi on the vertices of the region.

generate_children(upper_bound=0, stop_only_if_strict=True, **kwds)
is_divisible()
is_fathomed(value=0, stop_only_if_strict=True, **kwds)
new_intervals()
plot(colorful=False, **bound_kwds)
verify_estimators()

If affine estimators have been computed, then verirify that it is indeed lower/upper estimator.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = kzh_7_slope_1()
sage: T = SubadditivityTestTree(h)
sage: T.is_subadditive()
True
sage: all(node.verify_estimators() for node in T.complete_node_set)
True
verify_vertices(**kwds)

If the lower bound of delta pi has been computed, verify delta pi value is no smaller than lower bound.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = kzh_7_slope_1()
sage: T = SubadditivityTestTree(h)
sage: T.is_subadditive()
True
sage: all(node.verify_vertices() for node in T.complete_node_set)
True
class cutgeneratingfunctionology.igp.SubadditivityTestTreeNodeGeneral(fn, level, intervals)

Bases: object

I_bkpts()
I_values()
I_values_min()
J_bkpts()
J_values()
J_values_min()
K_bkpts()
K_values()
K_values_max()
__dict__ = dict_proxy({'__ne__': <function __ne__>, '__module__': 'cutgeneratingfunctionology.igp', 'K_values_max': <function K_values_max>, 'K_bkpts': <function K_bkpts>, 'J_bkpts': <function J_bkpts>, 'I_bkpts': <function I_bkpts>, 'delta_pi_upper_bound': <function delta_pi_upper_bound>, '__gt__': <function __gt__>, '__dict__': <attribute '__dict__' of 'SubadditivityTestTreeNodeGeneral' objects>, '__lt__': <function __lt__>, 'is_fathomed': <function is_fathomed>, 'J_values_min': <function J_values_min>, '__weakref__': <attribute '__weakref__' of 'SubadditivityTestTreeNodeGeneral' objects>, 'delta_pi_constant_lower_bound': <function delta_pi_constant_lower_bound>, 'J_values': <function J_values>, 'generate_children': <function generate_children>, 'I_values_min': <function I_values_min>, 'K_values': <function K_values>, '__eq__': <function __eq__>, 'is_divisible': <function is_divisible>, 'I_values': <function I_values>, '__doc__': None, 'delta_pi_affine_lower_bound': <function delta_pi_affine_lower_bound>, '__le__': <function __le__>, 'new_intervals': <function new_intervals>, '__init__': <function __init__>, '__hash__': <function __hash__>, 'delta_pi_lower_bound': <function delta_pi_lower_bound>, 'branching_direction': <function branching_direction>, '__ge__': <function __ge__>, 'delta_pi_min_of_indivisible_node': <function delta_pi_min_of_indivisible_node>})
__eq__(other)

x.__eq__(y) <==> x==y

__ge__(other)

x.__ge__(y) <==> x>=y

__gt__(other)

x.__gt__(y) <==> x>y

__hash__() <==> hash(x)
__init__(fn, level, intervals)

x.__init__(…) initializes x; see help(type(x)) for signature

__le__(other)

x.__le__(y) <==> x<=y

__lt__(other)

x.__lt__(y) <==> x<y

__module__ = 'cutgeneratingfunctionology.igp'
__ne__(other)

x.__ne__(y) <==> x!=y

__weakref__

list of weak references to the object (if defined)

branching_direction()
delta_pi_affine_lower_bound(solver='Coin')
delta_pi_constant_lower_bound()
delta_pi_lower_bound(max_number_of_bkpts=0, solver='Coin')
delta_pi_min_of_indivisible_node()
delta_pi_upper_bound()
generate_children(upper_bound=0, stop_only_if_strict=True, **kwds)
is_divisible()
is_fathomed(value=0, stop_only_if_strict=True, **kwds)
new_intervals()
cutgeneratingfunctionology.igp._max_x_y(x, y)
cutgeneratingfunctionology.igp._plot_component_rectangle(domain, range, **kwds)

Default colors are for strip lemma rectangles (densely covered)

cutgeneratingfunctionology.igp.addition_names

tuple() -> empty tuple tuple(iterable) -> tuple initialized from iterable’s items

If the argument is a tuple, the return value is the same object.

cutgeneratingfunctionology.igp.adjust_pt_to_satisfy_ineqs(current_point, ineq, strict_ineqs, nonstrict_ineqs, flip_ineq_step)

Walk from current_point (type=vector) in the direction perpendicular to the gradient of ineq with small positive step length flip_ineq_step, while maintaining the value of ineq(*current_point) which is >= 0. until get a new point such that l(new point)<0 for all l in strict_ineqs and l(new point)<=0 for all l in nonstrict_ineqs

Return new_point, or None if it fails to find one.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: P.<a,b>=QQ[]
sage: x, y = adjust_pt_to_satisfy_ineqs(vector([13/10,12/10]), a+b-2, [-a+b^2], [], 1/2) # was (123/85, 179/170), now (253/170, 86/85)
sage: (x + y - 2 > 0) and (-x + y^2 < 0)
True
sage: x, y = adjust_pt_to_satisfy_ineqs(vector([71/80, 89/80]), a+b-2, [-a+b^2], [], 1/4) # was (171073319/163479120, 155884921/163479120), (22159/20640, 19121/20640)  # ineq(71/80, 89/80) == 0. now (446132279/359982240, 363827761/359982240).
sage: (x + y - 2 >= 0) and (-x + y^2 < 0)
True

If impossible, return None:

sage: pt = adjust_pt_to_satisfy_ineqs(vector([11/8, 7/8]), a+b-2, [-a+b^2], [a-1], 1/4); pt is None
True

Bug example in cpl Cell 9 with test point (499/1250, 488072439572/4866126017667). Without converting input to QQ, output was (0.333000000000000, 0.111333333333333) with -2*f - 3*z + 1 = -5.55111512312578e-17 , the QQ of the output=(333/1000, 167/1500) has -2*f - 3*z + 1 == 0. Revise the code to take QQ input current point:

sage: P.<f,z>=QQ[]
sage: current_point = vector([0.333000000000000, 0.100300000000000]); ineq = -3*f + 1; strict_ineqs = [2*f + 2*z - 1, f + 5*z - 1, -f - 6*z + 1, -2*f - 3*z + 1]; nonstrict_ineqs = []; flip_ineq_step = 1/1000
sage: pt = adjust_pt_to_satisfy_ineqs(current_point, ineq, strict_ineqs, nonstrict_ineqs, flip_ineq_step) # got (333/1000, 67/600)
sage: all(l(pt) < 0 for l in strict_ineqs) and all(l(pt) <= 0 for l in nonstrict_ineqs) and ineq(pt)>0
True
Bug example in cpl cell 3 and 25th theta=((f+5z-1)/(2f+12z-2), z/(2f+12z-2)). Computing with QQ results in huge denominator, never ends:
sage: P.<f,z>=QQ[] sage: current_point = vector([RR(30136191997/49655508552), RR(3903863311/49655508552)]) sage: strict_ineqs = [f - 1, -2*f + 1, f^2 - 2*f + 1] #used polynomial sub instead of section, had more ineqs: [1/5*f - 1/5, -2*f + 1, 8/25*f^2 - 6/25*f - 2/25, 2/25*f^2 - 4/25*f + 2/25] # empty because (f-1)^2<0. sage: nonstrict_ineqs = [] sage: pt = adjust_pt_to_satisfy_ineqs(current_point, None, strict_ineqs, nonstrict_ineqs, flip_ineq_step=1/1000); pt is None True
Bug example in cpl bigcell 16 with test point (12219/26000, 24/1625). Redo with QQ had infinite loop. Bug comes from find_neighbour_point where it calls bsa_section.upstairs()._polyhedron.is_empty(), which is not strong enough. If we could test bsa_section is empty (perhaps by tighten_upstairs_by_mccormick), then this example should not appear.
sage: P.<f,z>=QQ[]; sage: current_point = vector((71582788/143165577, 4673/377000)) # came from vector((RR(70727/150800), RR(4673/377000))), sage: ineq=None; strict_ineqs=[2*f - 1, -9*f + 2]; nonstrict_ineqs=[4*f^2 - 4*f + 1]; flip_ineq_step=1/1000 sage: pt = adjust_pt_to_satisfy_ineqs(current_point, None, strict_ineqs, nonstrict_ineqs, flip_ineq_step=1/1000); pt is None #long time True
cutgeneratingfunctionology.igp.all_faces(q)
cutgeneratingfunctionology.igp.all_intervals_covered(q, f, values, last_covered_intervals)
Input:
  • values: [pi(0), pi(1/q), .. pi(1)]
  • last_covered_intervals: covered_intervals after painting complex

Return whether all intervals are covered. Incremental computation

cutgeneratingfunctionology.igp.approx_discts_function(perturbation_list, stability_interval, field=<function RealNumberField>, function=None)
cutgeneratingfunctionology.igp.arithmetic_complexity(fn, f=None, q=None)

Compute the arithmetic complexity.

It is defined as the least common denominator of the values fn(i/q) for i=0,1, … ,q, where fn is a piecewise linear function with rational breakpoints in (1/q)Z, or a discrete function with its domain contained in (1/q)Z.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = gmic(7/9)
sage: arithmetic_complexity(h)
14
sage: arithmetic_complexity(restrict_to_finite_group(h))
14
sage: arithmetic_complexity(dg_2_step_mir_limit())
24

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.automorphism(function, factor=-1)

Apply an automorphism.

_images/igp-22.svg

For the infinite group problem, apply the only nontrivial automorphism of the 1-dimensional infinite group problem to the given function, i.e., construct the function x -> function(-x). See Johnson (1974) for a discussion of the automorphisms.

_images/igp-23.svg

In the finite group case, factor must be an integer coprime with the group order.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # Suppress output in automatic tests.
sage: h = automorphism(gmic(f=4/5))
sage: extremality_test(h, False, f=1/5)
True
sage: h = automorphism(restrict_to_finite_group(gmic(f=4/5)), 2)
sage: extremality_test(h, False)
True
cutgeneratingfunctionology.igp.basic_perturbation(fn, index)

Get a basic perturbation of fn. index counts from 1 (to match the labels in the diagrams).

class cutgeneratingfunctionology.igp.bcds_discontinuous_everywhere
_images/igp-24.svg

An extreme function whose graph is dense in R times [0,1].

Reference:
[bcds_discontinous_everywhere] Amitabh Basu, Michele Conforti, Marco Di Summa, An extreme function which is nonnegative and discontinuous everywhere, arXiv:1802.01499 [math.OC]
__call__(x)

Examples:

sage: from cutgeneratingfunctionology.igp import bcds_discontinuous_everywhere, delta_pi
sage: h = bcds_discontinuous_everywhere()
sage: delta_pi(h, 1/5+sqrt(3), 3/7+sqrt(1/3)) >= 0
True
sage: delta_pi(h, -13/9+sqrt(17), 3/7-3*sqrt(17))>=0
True
sage: delta_pi(h, 19/8, 3/7-3*sqrt(101))>=0
True
sage: delta_pi(h, 19/8+sqrt(101/9), 3/7-1/3*sqrt(101))>=0
True
__init__()
__module__ = 'cutgeneratingfunctionology.igp'
plot(xmin=0, xmax=1, ymin=0, ymax=1, color=None, rgbcolor=None, aspect_ratio='automatic', thickness=None, **kwds)
cutgeneratingfunctionology.igp.bhk_irrational_extreme_limit_to_rational_nonextreme(n=+Infinity)

A sequence of bhk_irrational functions, each extreme, indexed by n = 1, 2, … whose limit (n = Infinity) is a bhk_irrational function with rational parameters, and hence not extreme.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = bhk_irrational_extreme_limit_to_rational_nonextreme(1)
sage: extremality_test(h, False)
True
sage: h = bhk_irrational_extreme_limit_to_rational_nonextreme(2)
sage: extremality_test(h, False)
True
sage: h = bhk_irrational_extreme_limit_to_rational_nonextreme(17)
sage: extremality_test(h, False)
True
sage: h = bhk_irrational_extreme_limit_to_rational_nonextreme()
sage: extremality_test(h, False)
False
cutgeneratingfunctionology.igp.bhk_raises_plotting_error()

There were some problems when plotting the 2d-diagram of functions having irrational data coerced into a (non-quadratic) RealNumberField.

This was a plotting regression introduced by plotting function and shadows at the borders of 2d diagrams.

TESTS:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = bhk_raises_plotting_error()
sage: g = plot_2d_diagram(h)
cutgeneratingfunctionology.igp.bigcellify_igp()

Load igp as follows to override primitives with big_cells primitives:

sage: import cutgeneratingfunctionology.igp as igp; reload(igp); igp.bigcellify_igp(); from cutgeneratingfunctionology.igp import *   # not tested
cutgeneratingfunctionology.igp.california_ip()

The California Integer Programming cut, to be plotted with rgbcolor=(192, 54, 44). Not minimal.

cutgeneratingfunctionology.igp.can_coerce_to_QQ(x)
cutgeneratingfunctionology.igp.channels

Index of channels

Channels in Sage implement the information theoretic notion of transmission of messages.

The channels object may be used to access the codes that Sage can build.

Note

To import these names into the global namespace, use:

sage: from sage.coding.channels_catalog import *
cutgeneratingfunctionology.igp.check_for_strip_lemma_fastpath(m1, m2)

Given two moves \(m_1\) and \(m_2\), return the dense interval by trying to apply the strip lemma. Not used, because we want to add covered intervals back to the domains of moves so that L-U is large.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: t1 = 2/15; t2 = sqrt(2)/15; 
sage: l1 = 4/15; u1 = 3/4 - t1; l2 = 1/3; u2 = 14/15-t2
sage: m1 = FunctionalDirectedMove([open_interval(l1, u1)], (1, t1))
sage: m2 = FunctionalDirectedMove([open_interval(l2, u2)], (1, t2))
sage: check_for_strip_lemma_fastpath(m1, m2)
[<Int(4/15, 14/15)>]
cutgeneratingfunctionology.igp.check_for_strip_lemma_linear_independence(m1, m2)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: t1 = 2/15; t2 = sqrt(2)/15; t3 = 3/15;
sage: l1 = 4/15; u1 = 3/4 - t1; l2 = 1/3; u2 = 14/15-t2
sage: m1 = FunctionalDirectedMove([open_interval(l1, u1)], (1, t1))
sage: m2 = FunctionalDirectedMove([open_interval(l2, u2)], (1, t2))
sage: m3 = FunctionalDirectedMove([open_interval(l2, u2)], (1, t3))
sage: check_for_strip_lemma_linear_independence(m1, m2)
True
sage: check_for_strip_lemma_linear_independence(m1, m3)
False
cutgeneratingfunctionology.igp.check_for_strip_lemma_small_translations(domain1, domain2, t1, t2)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: t1 = 2/15; t2 = sqrt(2)/15;
sage: l1 = 4/15; u1 = 3/4 - t1; l2 = 1/3; u2 = 14/15-t2
sage: m1 = FunctionalDirectedMove([open_interval(l1, u1)], (1, t1))
sage: m2 = FunctionalDirectedMove([open_interval(l2, u2)], (1, t2))
sage: check_for_strip_lemma_small_translations(m1.intervals(), m2.intervals(), m1[1], m2[1])
[<Int(4/15, 14/15)>]
cutgeneratingfunctionology.igp.check_move_on_crazy_pieces(xxx_todo_changeme, cp1, cp2)
cutgeneratingfunctionology.igp.check_pattern_polytope_has_full_dim(l)
cutgeneratingfunctionology.igp.check_perturbation(fn, perturb, show_plots=False, show_plot_tag='perturbation', xmin=0, xmax=1, **show_kwds)
cutgeneratingfunctionology.igp.chen_3_slope_not_extreme(f=1/2, lam=8)

A continuous 3-slope function, constructed by K. Chen in his Ph.D. thesis [KChen_thesis]. The function has non-degenerate intervals with a zero derivative.

Chen claims that the function is extreme under certain conditions. But his proof on page 37 made a mistake in setting up the equations: \(-\\pi(C) + \\pi(CC) + \\pi(D) - \\pi(DD) = 0\). This relation should not exist in \(E(\\pi)\). Returned function can be extreme or NOT. Need to use extremality_test() to check.

See the discussion in [KZh2015b, section 3].

Parameters:
  • f (real) \(\in (0,1)\);
  • lam (real): the first slope has length 1/lam.
Requirement:
  • 0 < f <= 1/2;
  • lam > 3*max(1/f, 1 /(1-f))
Examples:

[KChen_thesis] p.33, fig.7 NOT extreme:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = chen_3_slope_not_extreme(f=1/2, lam=8)
sage: extremality_test(h, False)
False

Extreme example (with parameters NOT satisfying the requirement):

sage: h = chen_3_slope_not_extreme(f=2/3, lam=20)
sage: extremality_test(h, False)
True

References:

  • [KChen_thesis]: K. Chen, Topics in group methods for integer programming, Ph.D. thesis, Georgia Institute of Technology, June 2011.
  • [KZh2015b] M. Koeppe and Y. Zhou, An electronic compendium of extreme functions for the Gomory-Johnson infinite group problem, Operations Research Letters, 2015, http://dx.doi.org/10.1016/j.orl.2015.06.004
cutgeneratingfunctionology.igp.chen_tricky_uncovered_intervals()

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO); 
sage: h = chen_tricky_uncovered_intervals()
sage: extremality_test(h, False)
False
cutgeneratingfunctionology.igp.claimed_region_type(igp_function=ParametricFamily_gmic(default_values=(('f', 4/5), ('field', None), ('conditioncheck', True)), names=('f', )), condition_according_to_literature=True, **kwds)

Return if igp_function is ‘not_constructible’ or ‘constructible’ or ‘extreme’ for the values of parameters given by kwds (use default values if kwds is not provided).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: claimed_region_type(igp_function=chen_4_slope)
'extreme'
sage: claimed_region_type(igp_function=chen_4_slope, condition_according_to_literature=True, f=1/2, s_pos=5, s_neg=-5, lam1=1/5, lam2=1/5)
'constructible'
sage: claimed_region_type(igp_function=chen_4_slope, condition_according_to_literature=True, f=7/10, s_pos=2, s_neg=-4, lam1=1/100, lam2=49/100)
'extreme'
sage: claimed_region_type(igp_function=chen_4_slope, condition_according_to_literature=False, f=7/10, s_pos=2, s_neg=-4, lam1=1/100, lam2=49/100)
'constructible'

The following examples show how claimed_region_type can be used in computing the complex of igp_function. The cells of the complex represent the regions where igp_function is ‘extreme’, ‘constructible’ or ‘not_constructible’ according to the claimed extremality conditions for igp_function:

sage: complex = SemialgebraicComplex(claimed_region_type, ['f','bkpt'], find_region_type=return_result, igp_function=drlm_backward_3_slope)
sage: complex.bfs_completion(var_value=[4/5,1/2])
sage: [c.region_type for c in complex.cells_containing_point([1/12,1/6])]
['extreme']

sage: complex = SemialgebraicComplex(claimed_region_type, ['lam1', 'lam2'], find_region_type=return_result, igp_function=chen_4_slope, condition_according_to_literature=True)
sage: complex.bfs_completion(var_value=[3/10, 45/101])
sage: [c.region_type for c in complex.cells_containing_point([1/100,49/100])]
['extreme']

sage: complex = SemialgebraicComplex(claimed_region_type, ['lam1', 'lam2'], find_region_type=return_result, igp_function=chen_4_slope, condition_according_to_literature=False)
sage: complex.bfs_completion(var_value=[3/10, 45/101])
sage: [c.region_type for c in complex.cells_containing_point([1/100,49/100])]
['constructible']

sage: complex = SemialgebraicComplex(claimed_region_type, ['lam1', 'lam2'], find_region_type=return_result, igp_function=chen_4_slope, condition_according_to_literature=False, kwds_dict={'f':1/2, 's_pos':5, 's_neg':-5})
sage: complex.bfs_completion(var_value=[1/5, 1/4])
sage: [c.region_type for c in complex.cells_containing_point([1/5,1/5])]
['extreme']

sage: complex = SemialgebraicComplex(claimed_region_type,['f','alpha'],find_region_type=return_result, igp_function=dg_2_step_mir)
sage: complex.bfs_completion(var_value=[4/5,3/10]) #not tested #infinite many cells.
cutgeneratingfunctionology.igp.closed_piece(p, q)
cutgeneratingfunctionology.igp.coarse_regions_from_arrangement_of_bkpts(K, h)
cutgeneratingfunctionology.igp.codes

Index of code constructions

The codes object may be used to access the codes that Sage can build.

ParityCheckCode() Parity check codes
CyclicCode() Cyclic codes
BCHCode() BCH Codes
GeneralizedReedSolomonCode() Generalized Reed-Solomon codes
ReedSolomonCode() Reed-Solomon codes
BinaryReedMullerCode() Binary Reed-Muller codes
ReedMullerCode() q-ary Reed-Muller codes
HammingCode() Hamming codes
GolayCode() Golay codes
GoppaCode() Goppa codes
DuadicCodeEvenPair() Duadic codes, even pair
DuadicCodeOddPair() Duadic codes, odd pair
QuadraticResidueCode() Quadratic residue codes
ExtendedQuadraticResidueCode() Extended quadratic residue codes
QuadraticResidueCodeEvenPair() Even-like quadratic residue codes
QuadraticResidueCodeOddPair() Odd-like quadratic residue codes
QuasiQuadraticResidueCode() Quasi quadratic residue codes (Requires GAP/Guava)
ToricCode() Toric codes
WalshCode() Walsh codes
from_parity_check_matrix() Construct a code from a parity check matrix
random_linear_code() Construct a random linear code
RandomLinearCodeGuava() Construct a random linear code through Guava (Requires GAP/Guava)
SubfieldSubcode() Subfield subcodes
ExtendedCode() Extended codes
PuncturedCode() Puncturedcodes

Note

To import these names into the global namespace, use:

sage: from sage.coding.codes_catalog import *
cutgeneratingfunctionology.igp.coefficients_of_theta_and_rhs_in_constraint(c, var_name, n)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: n = 3
sage: var_name = ['f','z1','z2']
sage: P.<f,z1,z2,o1,o2>=QQ[]
sage: c = (f*o1 + f*o2 + z1 + z2 - o1 - o2)/(f^2 + 2*f*z1 + 2*f*z2 - f)
sage: coefficients_of_theta_and_rhs_in_constraint(c, var_name, n)
(((f - 1)/(f^2 + 2*f*z1 + 2*f*z2 - f), (f - 1)/(f^2 + 2*f*z1 + 2*f*z2 - f)),
 (-z1 - z2)/(f^2 + 2*f*z1 + 2*f*z2 - f))
sage: c = (f*o1 + 2*z2*o1 - 2*z1*o2 + z1 - o1)/(f^2 + 2*f*z1 + 2*f*z2 - f)
sage: coefficients_of_theta_and_rhs_in_constraint(c, var_name, n)
(((f + 2*z2 - 1)/(f^2 + 2*f*z1 + 2*f*z2 - f),
  (-2*z1)/(f^2 + 2*f*z1 + 2*f*z2 - f)),
 (-z1)/(f^2 + 2*f*z1 + 2*f*z2 - f))

sage: var_name = ['f','z']
sage: P.<f,z,o1,o2>=QQ[]
sage: c = (f*o1 + 2*z*o1 - 2*z*o2 + z - o1)/(f^2 + 4*f*z - f)
sage: coefficients_of_theta_and_rhs_in_constraint(c, var_name, n)
(((f + 2*z - 1)/(f^2 + 4*f*z - f), (-2*z)/(f^2 + 4*f*z - f)),
 (-z)/(f^2 + 4*f*z - f))
cutgeneratingfunctionology.igp.collect_and_save_cpl_extreme_theta_regions(regions, name='cpl_theta', goto_lower_dim=False)
cutgeneratingfunctionology.igp.color_for_delta(deltafn, additive_color=None)
cutgeneratingfunctionology.igp.color_of_ith_region_type(i)

Return a color in the rainbow.

cutgeneratingfunctionology.igp.compose_functional_directed_moves(A, B, show_plots=False)

Compute the directed move that corresponds to the directed move \(A\) after \(B\).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: compose_functional_directed_moves(FunctionalDirectedMove([(5/10,7/10)],(1, 2/10)),FunctionalDirectedMove([(2/10,4/10)],(1,2/10)))
<FunctionalDirectedMove (1, 2/5) with domain [(3/10, 2/5)], range [<Int[7/10, 4/5]>]>
cutgeneratingfunctionology.igp.connected_pair_of_face(face, q)

Return 2 translation and 1 reflection corresponding to 3 edges of the given triangle face.

cutgeneratingfunctionology.igp.construct_perturbation_given_slopes_and_lengths(fn, perturbation_components, lim_slope, min_slope, max_slope, lengths)
cutgeneratingfunctionology.igp.containing_eps_1d(x, interval, with_limits=True)

Input:

  • \(x\): the projection of vertex \(v\) (of a face \(F\)),
  • interval: the projection of the face \(F\).

The projection direction is I/J/K. Note that \(x\) is in \(interval\).

Return:

  • The projection of approaching limits (\(\subseteq \{x^-, x, x^+\}\)) that need to be considered at \(v\) for testing the additivity of \(F\).

If with_limits=False, this computation is done for additivity of \(F\) sans limits.

cutgeneratingfunctionology.igp.continuous_cut_generating_function_from_group_function(fn)

Construct a cut generating function for continuous variables.

The input is a group function fn, which must be continuous; otherwise an error will be signaled.

The result, together with fn, forms the cut generating function pair for a mixed integer problem.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: continuous_cut_generating_function_from_group_function(gmic(4/5))
piecewise(x|-->-5*x on (-oo, 0), x|-->0 on {0}, x|-->5/4*x on (0, +oo); x)
sage: continuous_cut_generating_function_from_group_function(gomory_fractional(4/5))
piecewise(x|-->0 on {0}, x|-->5/4*x on (0, +oo); x)
sage: continuous_cut_generating_function_from_group_function(automorphism(gomory_fractional(4/5)))
piecewise(x|-->-5/4*x on (-oo, 0), x|-->0 on {0}; x)
cutgeneratingfunctionology.igp.convert_linfun_to_linexp(linfun)

convert MILP’s Linear_Function to PPL’s Linear_Expression.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: fn = pattern_setup_lp(1, more_ini_additive=False, objcoef=None)
sage: linfun = fn[5]; linfun
x_0 + 3*x_1 + x_2
sage: type(linfun)
<type 'sage.numerical.linear_functions.LinearFunction'>
sage: linexp = convert_linfun_to_linexp(linfun); linexp
x0+3*x1+x2
sage: type(linexp)
<type '...Linear_Expression'>
cutgeneratingfunctionology.igp.convert_lrs_to_ppl(lrs_string)

Convert lrs format H-representation to ppl cs; or lrs format V-representation (of a polytope) to ppl gs.

COPY from src/geometry/polyhedron/backend_cdd.py and edit the function Polyhedron_cdd._init_from_cdd_output(self, cdd_output_string)

EXAMPLE:

sage: from cutgeneratingfunctionology.igp import *
sage: x = Variable(0)
sage: y = Variable(1)
sage: cs = Constraint_System()
sage: cs.insert(x >= 0)
sage: cs.insert(y >= 0)
sage: cs.insert(x <= 1)
sage: cs.insert(y <= 1)
sage: in_str = convert_pplcs_to_lrs(cs)
sage: out_str = lrs_redund(in_str)     #      optional - lrslib
sage: type(out_str)                    # py3, optional - lrslib
<class 'str'>
sage: convert_lrs_to_ppl(out_str)      #      optional - lrslib
Constraint_System {x0>=0, x1>=0, -x0+1>=0, -x1+1>=0}
cutgeneratingfunctionology.igp.convert_pplcs_to_lrs(cs, fname=None)
cutgeneratingfunctionology.igp.convert_pplcs_to_normaliz(cs)
cutgeneratingfunctionology.igp.convert_pplcs_to_panda(cs)
cutgeneratingfunctionology.igp.convert_pplcs_to_porta(cs, q=None, f=None)
cutgeneratingfunctionology.igp.convex_vert_list(vertices)
cutgeneratingfunctionology.igp.covered_i_variable(q, z, i)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: covered_i_variable(7, 3/7, 2)
'c_3_2'
cutgeneratingfunctionology.igp.cpl3_0(f=3/5, z1=1/25, z2=1/125, field=None, conditioncheck=True)
cutgeneratingfunctionology.igp.cpl3_1(f=291403/720000, z1=114649/720000, z2=8501/144000, field=None, conditioncheck=True)
cutgeneratingfunctionology.igp.cpl3_10(f=14/33, z1=17/264, z2=None, field=None, conditioncheck=True)
cutgeneratingfunctionology.igp.cpl3_11(f=73/160, z1=None, z2=27/160, field=None, conditioncheck=True)
cutgeneratingfunctionology.igp.cpl3_12(f=5/42, z1=61/336, z2=None, field=None, conditioncheck=True)
cutgeneratingfunctionology.igp.cpl3_13(f=1/14, z1=5/28, z2=None, field=None, conditioncheck=True)
cutgeneratingfunctionology.igp.cpl3_14(f=1/24, z1=9/40, z2=None, field=None, conditioncheck=True)
cutgeneratingfunctionology.igp.cpl3_2(f=8011/24000, z1=1969/48000, z2=401/1920, field=None, conditioncheck=True)
cutgeneratingfunctionology.igp.cpl3_3(f=9469/66000, z1=2869/66000, z2=24709/66000, field=None, conditioncheck=True)
cutgeneratingfunctionology.igp.cpl3_4(f=8497/126000, z1=499/42000, z2=27863/126000, field=None, conditioncheck=True)
_images/igp-25.svg

The function is extreme under the condtions: f + 4*z1 + 4*z2 - 1 <= 0 && -z1 < 0 && -f < 0 && 2*f + 2*z1 - z2 <= 0

TESTS:

sage: from cutgeneratingfunctionology.igp import *
sage: f=1/18; z1=1/25; z2=7/36
sage: h = cpl3_4(f,z1,z2)
sage: extremality_test(h)
True
cutgeneratingfunctionology.igp.cpl3_5(f=3/5, z1=1/25, z2=1/125, field=None, conditioncheck=True)
cutgeneratingfunctionology.igp.cpl3_6(f=1/2000, z1=499/4000, z2=1/4, field=None, conditioncheck=True)
cutgeneratingfunctionology.igp.cpl3_7(f=3/5, z1=1/25, z2=1/125, field=None, conditioncheck=True)
cutgeneratingfunctionology.igp.cpl3_8(f=3/5, z1=1/25, z2=1/125, field=None, conditioncheck=True)
cutgeneratingfunctionology.igp.cpl3_9(f=20489/330000, z1=61603/660000, z2=72581/660000, field=None, conditioncheck=True)
cutgeneratingfunctionology.igp.cpl3_function(r0, z1, o1, o2)

Construct a CPL3= function.

Parameters:
  • 0 < r0 (real) < 1,
  • 0 < z1 (real) <= (1-r0)/4,
  • 0 <= o1, o2 (real), o1 + o2 <= 1/2;
  • if z1 = (1-r0)/4, then o1 + o2 = 1/2.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # Suppress output in automatic tests.
sage: p = cpl3_function(r0=1/7, z1=1/7, o1=1/4, o2=1/12)
sage: p
<FastPiecewise with 6 parts, 
 (0, 1/7)       <FastLinearFunction 0>   values: [0, 0]
 (1/7, 2/7)     <FastLinearFunction 7/4*x - 1/4>         values: [0, 1/4]
 (2/7, 3/7)     <FastLinearFunction 7/12*x + 1/12>       values: [1/4, 1/3]
 (3/7, 5/7)     <FastLinearFunction 7/6*x - 1/6>         values: [1/3, 2/3]
 (5/7, 6/7)     <FastLinearFunction 7/12*x + 1/4>        values: [2/3, 3/4]
 (6/7, 1)       <FastLinearFunction 7/4*x - 3/4>         values: [3/4, 1]>
sage: q = plot(p)
Reference:
  • [1] L. A. Miller, Y. Li, and J.-P. P. Richard, New Inequalities for Finite and Infinite Group Problems from Approximate Lifting, Naval Research Logistics 55 (2008), no.2, 172-191, doi:10.1002/nav.20275
cutgeneratingfunctionology.igp.cpl_fill_region_given_theta(r, theta, flip_ineq_step=1/1000, check_completion=False, wall_crossing_method='heuristic', goto_lower_dim=True, big_cells=False)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: regions = cpl_regions_from_arrangement_of_bkpts(3, cpleq=True)
sage: r = regions[0]
sage: thetas = generate_thetas_of_region(r)
sage: theta = thetas[-1]
sage: theta
((-z)/(f - 1), (-z)/(f - 1))
sage: cpl_complex = cpl_fill_region_given_theta(r, theta)
sage: len(cpl_complex.components)
1
sage: cpl_complex.components[0].region_type
'is_extreme'
cutgeneratingfunctionology.igp.cpl_n_group_function

alias of cutgeneratingfunctionology.igp.ParametricFamily_cpl_n_group_function

cutgeneratingfunctionology.igp.cpl_regions_fix_theta(regions, theta)
cutgeneratingfunctionology.igp.cpl_regions_from_arrangement_of_bkpts(n=3, cpleq=True, flip_ineq_step=1/1000, check_completion=False, wall_crossing_method='heuristic', goto_lower_dim=True, max_failings=0)

Got regions[0:30]: 2-dim; regions[30:78]: 1-dim; regions[78:96]: 0-dim.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: regions = cpl_regions_from_arrangement_of_bkpts(3, cpleq=True)  # long time - 30s
sage: len(regions)                                                    # long time - 30s
96
sage: regions = cpl_regions_from_arrangement_of_bkpts(n=3, cpleq=True, wall_crossing_method='mathematica', flip_ineq_step=1/1000)                          # long time, optional - mathematica
sage: len(regions)                # long time, optional - mathematica
96
cutgeneratingfunctionology.igp.cpl_regions_with_thetas_and_components(n=3, cpleq=True, keep_extreme_only=False, flip_ineq_step=1/1000, check_completion=False, wall_crossing_method='heuristic', goto_lower_dim=True, big_cells=False, regions=None)

Divide the space into cells where the arrangement of breakpoints of \(\pi\) is combinatorially the same.

For each region, find theta solutions, then subdivide into smaller components by running bfs with parametric field.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: regions = cpl_regions_with_thetas_and_components(3, True, False, 0, 1/1000, False, 'mathematica', True)   # optional - mathematica, optional - longtime20min # 25-30 mins
sage: regions = cpl_regions_with_thetas_and_components(3, True, False, 0, 1/1000, False, 'heuristic', True)     # optional - longtime20min
cutgeneratingfunctionology.igp.cpl_thetas_and_regions(regions, thetas_and_regions)

Gather colorful components that correspond to the same expression of theta together.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: regions = cpl_regions_with_thetas_and_components()                            # optional - longtime20min, , long time - 300s
sage: thetas_and_regions = cpl_thetas_and_regions_extreme(regions)                  # optional - longtime20min, , long time
sage: thetas_and_components = cpl_thetas_and_regions(regions, thetas_and_regions)   # optional - longtime20min, , long time
cutgeneratingfunctionology.igp.cpl_thetas_and_regions_extreme(regions)

Gather the blue components that correspond to the same expression of theta together. Favour thetas with 2d extreme regions.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: regions = cpl_regions_with_thetas_and_components()              # optional - longtime20min, long time - 300s
sage: thetas_and_regions = cpl_thetas_and_regions_extreme(regions)    # optional - longtime20min, long time
sage: len(thetas_and_regions)                                         # optional - longtime20min, long time
9
cutgeneratingfunctionology.igp.crystals

Catalog Of Crystals

Let \(I\) be an index set and let \((A,\Pi,\Pi^\vee,P,P^\vee)\) be a Cartan datum associated with generalized Cartan matrix \(A = (a_{ij})_{i,j\in I}\). An abstract crystal associated to this Cartan datum is a set \(B\) together with maps

\[e_i,f_i \colon B \to B \cup \{0\}, \qquad \varepsilon_i,\varphi_i\colon B \to \ZZ \cup \{-\infty\}, \qquad \mathrm{wt}\colon B \to P,\]

subject to the following conditions:

  1. \(\varphi_i(b) = \varepsilon_i(b) + \langle h_i, \mathrm{wt}(b) \rangle\) for all \(b \in B\) and \(i \in I\);
  2. \(\mathrm{wt}(e_ib) = \mathrm{wt}(b) + \alpha_i\) if \(e_ib \in B\);
  3. \(\mathrm{wt}(f_ib) = \mathrm{wt}(b) - \alpha_i\) if \(f_ib \in B\);
  4. \(\varepsilon_i(e_ib) = \varepsilon_i(b) - 1\), \(\varphi_i(e_ib) = \varphi_i(b) + 1\) if \(e_ib \in B\);
  5. \(\varepsilon_i(f_ib) = \varepsilon_i(b) + 1\), \(\varphi_i(f_ib) = \varphi_i(b) - 1\) if \(f_ib \in B\);
  6. \(f_ib = b'\) if and only if \(b = e_ib'\) for \(b,b' \in B\) and \(i\in I\);
  7. if \(\varphi_i(b) = -\infty\) for \(b\in B\), then \(e_ib = f_ib = 0\).

This is a catalog of crystals that are currently implemented in Sage:

Subcatalogs:

Functorial constructions:

TESTS:

sage: 'absolute_import' in dir(crystals)
False
cutgeneratingfunctionology.igp.cython_create_local_so
cutgeneratingfunctionology.igp.dark_rainbow_general(n, format='hex')

Adapted from sage function rainbow.

Returns a list of colors sampled at equal intervals over the spectrum, from Hue-Saturation-Value (HSV) coordinates (0, 1, 1) to (1, 1, 1). This range is red at the extremes, but it covers orange, yellow, green, cyan, blue, violet, and many other hues in between. This function is particularly useful for representing vertex partitions on graphs.

INPUT:

  • n - a number; the length of the list
  • format - a string (default: ‘hex’); the output format for each color in the list; the other choice is ‘rgbtuple’

OUTPUT:

  • a list of strings or RGB 3-tuples of floats in the interval [0.0, 1.0]

EXAMPLES:

sage: from sage.plot.colors import rainbow
sage: rainbow(7)
['#ff0000', '#ffda00', '#48ff00', '#00ff91', '#0091ff', '#4800ff', '#ff00da']
sage: rainbow(7, 'rgbtuple')
[(1.0, 0.0, 0.0), (1.0, 0.8571428571428571, 0.0), (0.2857142857142858, 1.0, 0.0), (0.0, 1.0, 0.5714285714285712), (0.0, 0.5714285714285716, 1.0), (0.2857142857142856, 0.0, 1.0), (1.0, 0.0, 0.8571428571428577)]

AUTHORS:

  • Robert L. Miller
  • Karl-Dieter Crisman (directly use hsv_to_rgb() for hues)
cutgeneratingfunctionology.igp.default_field(polynomial, name=None, latex_name=None, names=None, check=True, embedding=None, assume_disc_small=False, maximize_at_primes=None, exact_embedding=None)

A NumberField embedded into the real numbers, for which comparisons work according tothe embedding.

This may not be necessary any more in Sage 7.1 after trac ticket #17830; but see trac ticket #20184.

Some special tricks for speed and for pretty printing.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: x=polygen(QQ)
sage: K.<cbrt2> = RealNumberField(x^3 - 2, embedding=RIF(AA.polynomial_root(x^3-2, RIF(0,3))), exact_embedding=AA.polynomial_root(x^3-2, RIF(0,3)))
sage: 6064/4813 < cbrt2 < 90325/71691
True

sage: R.<y> = QQ[]; polynomial=y^2 - 2; embedding=RR(1.4142135623730949); exact_embedding=SR(AA(sqrt(2)))
sage: RealNumberField(polynomial=polynomial, name='a', embedding=embedding, exact_embedding=exact_embedding)
Real Number Field in `a` as the root of the defining polynomial y^2 - 2 near 1.414213562373095?
cutgeneratingfunctionology.igp.default_igp_ticks_keywords(function, y_ticks_for_breakpoints=False, extra_xticks=[], extra_yticks=[1])

Compute plot keywords for displaying the ticks.

cutgeneratingfunctionology.igp.delete_one_time_plot_kwds(kwds)
cutgeneratingfunctionology.igp.delta_pi(fn, x, y)

Computes the slack in subaddivity. See also delta_pi_general for discontinuous case.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: fn = not_minimal_2()
sage: delta_pi(fn, 1/5, 3/5)
0
cutgeneratingfunctionology.igp.delta_pi_general(fn, x, y, xyz_eps=(0, 0, 0))

return delta_pi = fn(x, xeps) + fn(y, yeps) - fn(z, zeps).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = piecewise_function_from_breakpoints_and_limits(
....:       bkpt=[0, 1/5, 2/5, 3/5, 4/5, 1], 
....:       limits = [{-1:0, 0:0, 1:0},{-1:1, 0:1, 1:1}, 
....:                 {-1:0, 0:2/5, 1:2/5}, {-1:2/5, 0:1/2, 1:3/5},
....:                 {-1:3/5, 0:3/5, 1:1}, {-1:0, 0:0, 1:0}])
sage: delta_pi_general(h, 2/5, 4/5, (-1, 1, -1))
0
sage: delta_pi_general(h, 2/5, 4/5, (-1, 0, -1))
-2/5

r

cutgeneratingfunctionology.igp.delta_pi_min(fn, I, J, K, approximation='constant', norm='one', branching_point_selection='median')

Return the minimum of the function delta fn in the region whose projections are I,J,K.

cutgeneratingfunctionology.igp.delta_pi_of_face(fn, x, y, F)
cutgeneratingfunctionology.igp.delta_pi_of_face_symbolic(fn, x, y, F, simplify=False)
cutgeneratingfunctionology.igp.dim_cs_matrix(q, changed_vertices, cs_matrix)

Append the new additivity equations corresponding to green vertices in changed_vertices to the cs_matrix. Output the new_cs_matrix and its co-dimension.

cutgeneratingfunctionology.igp.directed_move_composition_completion(fdms, covered_components=[], proj_add_vert=set([]), show_plots=False, plot_background=None, function=None, pts_of_discontinuity=None, max_num_rounds=None, error_if_max_num_rounds_exceeded=True)

Only used in stuff_with_random_irrational_function().

cutgeneratingfunctionology.igp.directly_covered_by_adding_face(last_covered_intervals, face, q, f)

Computes incrementally new covered_intervals by adding a new face. Consider only directly covered and symmetry reflection regarding f.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: last_covered_intervals = [set([0,2]), set([3,4])]
sage: face = (1, 1, 1)
sage: directly_covered_by_adding_face(last_covered_intervals, face, 5, 3)
[{0, 2}, {1, 3, 4}]
cutgeneratingfunctionology.igp.discontinuous_facets_paper_example_psi_prime(merge=True)
_images/igp-26.svg

Example from the paper cite:\(koeppe-zhou:discontinuous-facets\). See hildebrand_discont_3_slope_1.

If merge=False, the function is set up on the same breakpoints as hildebrand_discont_3_slope_1 for an easier comparison of the additive faces; if merge=True, it is set up on a coarser set of breakpoints.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: psi_prime = discontinuous_facets_paper_example_psi_prime()
sage: extremality_test(psi_prime, False)
True
cutgeneratingfunctionology.igp.discontinuous_interpolation(pts, mid, right, left, merge=True)
cutgeneratingfunctionology.igp.discrete_function_from_points_and_values(points, values, field=None)

Create a function defined on a finite list of points.

points and values are two parallel lists.

The data are coerced into a common convenient field via nice_field_values.

cutgeneratingfunctionology.igp.dont_plot_rescaled_perturbation(*args, **kwds)
cutgeneratingfunctionology.igp.dr_projected_sequential_merge_3_slope(f=2/3, lambda_1=1/2, lambda_2=1/2, n=1)
Construct the one-dimensional projected sequential merge inequality: \(h = g \lozenge_n^1 \xi\), where
  • \(g =\) multiplicative_homomorphism(gj_forward_3_slope(f=f, lambda_1=lambda_1, lambda_2=lambda_2),-1);
  • \(\xi =\) gmic(f/n).

See projected_sequential_merge().

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = dr_projected_sequential_merge_3_slope()
sage: extremality_test(h, False)
True
Reference: p.311, fig.5,[39] SS Dey, JPP Richard, Relations between facets of low-and high-dimensional group problems,
Mathematical programming 123 (2), 285-313.
cutgeneratingfunctionology.igp.drlm_2_slope_limit_1_1(f=1/2, nb_pieces_left=1, nb_pieces_right=1)

An iconic choice of parameters in drlm_2_slope_limit.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN) # Suppress warning about experimental discontinuous code.
sage: h = drlm_2_slope_limit_1_1()
sage: extremality_test(h, False)
True
cutgeneratingfunctionology.igp.drlm_gj_2_slope_extreme_limit_to_nonextreme(s=+Infinity)

A sequence of phi_s_in_drlm_not_extreme_2 functions, each extreme, indexed by s, (where s is a real number, s = abs(negative_slope) and s > 2) whose limit (s = Infinity) is a drlm_not_extreme_2 function which is not extreme.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = drlm_gj_2_slope_extreme_limit_to_nonextreme(3)
sage: extremality_test(h, False)
True
sage: h = drlm_gj_2_slope_extreme_limit_to_nonextreme(17)
sage: extremality_test(h, False)
True
sage: h = drlm_gj_2_slope_extreme_limit_to_nonextreme()
sage: extremality_test(h, False)
False
cutgeneratingfunctionology.igp.drlm_not_extreme_1()

Example from S. S. Dey, J.-P. P. Richard, Y. Li, and L. A. Miller, On the extreme inequalities of infinite group problems, Mathematical Programming 121 (2009), no. 1, 145-170, https://doi:10.1007/s10107-008-0229-6. Figure 1.

It is the interpolation of the extreme function C13 for the finite group problem of order 7 from Araoz, Evans, Gomory and Johnson.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = drlm_not_extreme_1()
sage: minimality_test(h, False)
True
sage: extremality_test(h, False)
False
cutgeneratingfunctionology.igp.drlm_not_extreme_2()

Example from S. S. Dey, J.-P. P. Richard, Y. Li, and L. A. Miller, On the extreme inequalities of infinite group problems, Mathematical Programming 121 (2009), no. 1, 145-170, https://doi:10.1007/s10107-008-0229-6. Figure 3.

Note: this is not any of drlm_2_slope_limit functions, since here s_positive = 3, whereas in drlm_2_slope_limit(f=1/2, nb_pieces_left=2, nb_pieces_right=2), the s_positive has to be 4.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN) # Suppress warning about experimental discontinuous code.
sage: h = drlm_not_extreme_2()
sage: minimality_test(h, False)
True
sage: extremality_test(h, False)
False
cutgeneratingfunctionology.igp.embed_function_into_family(given_function, parametric_family, check_completion=False, **opt)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: embed_function_into_family(gmic(3/13), mlr_cpl3_a_2_slope)
{'r0': 3/13, 'z1': 3/26}
sage: given_function = drlm_backward_3_slope(1/12-1/100, 1/6+1/100)
sage: embed_function_into_family(given_function, drlm_backward_3_slope)
{'bkpt': 53/300, 'f': 11/150}
sage: embed_function_into_family(gmic(4/13), mlr_cpl3_a_2_slope)
{'r0': 4/13, 'z1': 3/26}
sage: embed_function_into_family(gmic(4/13), drlm_backward_3_slope)
{}
sage: embed_function_into_family(gmic(4/13), drlm_backward_3_slope, check_completion=True)  # optional - mathematica
{}

sage: given_function = mlr_cpl3_b_3_slope(r0=3/26, z1=1/13)
sage: parametric_family = drlm_backward_3_slope
sage: param_values = embed_function_into_family(given_function, parametric_family)
sage: param_values
{'bkpt': 7/26, 'f': 3/26}
sage: given_function == parametric_family(**param_values)
True

sage: given_function = automorphism(cpl3_8(f=3/5, z1=1/25, z2=1/125))
sage: parametric_family = gj_forward_3_slope
sage: embed_function_into_family(given_function, parametric_family, check_completion=True) # optional - mathematica, long time - 240s
{'f': 2/5, 'lambda_1': 6/25, 'lambda_2': 2/75}
# sage: embed_function_into_family(given_function, parametric_family, wall_crossing_method='mathematica') # not tested # optional - mathematica #long time  #TODO: does not terminate.
# {'f': 2/5, 'lambda_1': 6/25, 'lambda_2': 2/75}
cutgeneratingfunctionology.igp.epstriple_to_cone(epstriple)

Convert (xeps, yeps, zeps) to the corresponding cone.

13 cases, see dic_eps_to_cone.

cutgeneratingfunctionology.igp.equiv5_random_discont_1()

A randomly generated discontinuous function that appears in Equiv V.

cutgeneratingfunctionology.igp.equiv7_example_1()

One-sided discontinuous minimal valid function that appears in Equiv VII example 7.8.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h1 = equiv7_example_1()
sage: generate_uncovered_components(h1)
[[<Int(0, 1/4)>, <Int(1/4, 1/2)>]]
sage: finite_dimensional_extremality_test(h1)
False
sage: len(h1._perturbations)
1
cutgeneratingfunctionology.igp.equiv7_example_2_crazy_perturbation()

An effective perturbation function for the two-sided discontinuous function \(\pi_2 =\) minimal_no_covered_interval() that appears in Equiv VII example 7.9.

This perturbation is bounded, but is not Lipschitz continuous on the interval \((0, 1/2)\). In fact, it is a highly discontinuous “locally microperiodic” perturbation, which does not have a limit at any point in \((0, 1/2)\).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = minimal_no_covered_interval()
sage: cp = equiv7_example_2_crazy_perturbation()
sage: find_epsilon_for_crazy_perturbation(h, cp)
1/6
cutgeneratingfunctionology.igp.equiv7_example_3()
cutgeneratingfunctionology.igp.equiv7_example_post_1()
cutgeneratingfunctionology.igp.equiv7_example_post_2()
cutgeneratingfunctionology.igp.equiv7_example_post_3()
cutgeneratingfunctionology.igp.equiv7_example_post_4()
cutgeneratingfunctionology.igp.equiv7_example_xyz_1()
cutgeneratingfunctionology.igp.equiv7_example_xyz_2()
cutgeneratingfunctionology.igp.equiv7_example_xyz_3()
cutgeneratingfunctionology.igp.equiv7_minimal_2_covered_2_uncovered()

A continuous minimal valid function that appears in Equiv VII.

Five 0-slopes, all uncovered, translation and reflection on all five. (need one more equation)

cutgeneratingfunctionology.igp.exact_optsol(b)

Reconstruct exact rational basic solution. (solver = glp_simplex)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: lp = MixedIntegerLinearProgram(solver = 'GLPK', maximization = False)
sage: x, y = lp[0], lp[1]
sage: lp.add_constraint(-2*x + y <= 1)
sage: lp.add_constraint(x - y <= 1)
sage: lp.add_constraint(x + y >= 2)
sage: lp.set_objective(x + y)
sage: lp.solver_parameter("simplex_or_intopt", "simplex_only")
sage: lp.solve()
2.0
sage: lp.get_values(x)
1.5
sage: lp.get_values(y)
0.5
sage: b = lp.get_backend()
sage: exact_optsol(b)
(3/2, 1/2)
cutgeneratingfunctionology.igp.example7slopecoarse2()

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO); 
sage: h = example7slopecoarse2()
sage: extremality_test(h, False)
False
cutgeneratingfunctionology.igp.example7slopecoarse2_lifted()

obtained via: h = example7slopecoarse2(); hl = lift_until_extreme(h, use_all_perturbations=False, use_largest_absolute_epsilon=True); example7slopecoarse2_lifted() == h._lifted._lifted.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = example7slopecoarse2_lifted()
sage: extremality_test(h, False)
False
cutgeneratingfunctionology.igp.extremality_test(fn, show_plots=False, f=None, max_num_it=1000, phase_1=False, finite_dimensional_test_first=False, show_all_perturbations=False, crazy_perturbations=True, full_certificates=True)

Check if fn is extreme for the group relaxation with the given \(f\).

If fn is discrete, it has to be defined on a cyclic subgroup of the reals containing \(1\), restricted to \([0, 1]\). The group relaxation is the corresponding cyclic group relaxation.

Otherwise fn needs to be defined on the interval \([0, 1]\), and the group relaxation is the infinite group relaxation.

If \(f\) is not provided, uses the one found by find_f().

If show_plots is True (default: False), show many illustrating diagrams.

The function first runs minimality_test.

In the infinite group case, if finite_dimensional_test_first is True (default: False), after testing minimality of fn, we first check if the finite_dimensional_extremality_test finds a perturbation; otherwise (default) we first check for an equivariant perturbation.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # to disable output in automatic tests.
sage: h = piecewise_function_from_breakpoints_and_values([0, 1/2, 1], [0, 1, 0])
sage: # This example has a unique candidate for "f", so we don't need to provide one.
sage: extremality_test(h, False)
True
sage: # Same, with plotting:
sage: extremality_test(h, True) # not tested
... lots of plots shown ...
True
sage: h = multiplicative_homomorphism(gmic(f=4/5), 3) 
sage: # This example has several candidates for "f", so provide the one we mean:
sage: extremality_test(h, True, f=4/15) # not tested
... lots of plots shown ...
True
sage: g = gj_2_slope()
sage: gf = restrict_to_finite_group(g)
sage: # This is now a finite (cyclic) group problem.
sage: extremality_test(gf, True) # not tested
... lots of plots shown ...
True
cutgeneratingfunctionology.igp.face_variable(q, face)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: q=7;
sage: face_variable(q,  Face(([1/7, 2/7], [1/7], [2/7, 3/7])))
'h_1_1'
sage: face_variable(q,  Face(([1/7], [1/7, 2/7], [2/7, 3/7])))
'v_1_1'
sage: face_variable(q,  Face(([1/7, 2/7], [1/7, 2/7], [3/7])))
'd_1_1'
sage: face_variable(q,  Face(([1/7, 2/7], [1/7, 2/7], [2/7, 3/7])))
'l_1_1'
sage: face_variable(q,  Face(([1/7, 2/7], [1/7, 2/7], [3/7, 4/7])))
'u_1_1'
sage: face_variable(q,  Face(([2/7], [2/7], [4/7])))
'p_2_2'
cutgeneratingfunctionology.igp.facet_test(fn, show_plots=False, known_minimal=False, known_extreme=False)

Test whether \(fn\) is a facet.

EXAMPLES:

Minimal, and all intervals are covered (sans limits), unique solution (sans limits), so a facet:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = extreme_functions.drlm_backward_3_slope(conditioncheck=False)
sage: facet_test(h)
True

Extreme function and continuous piecewise linear, so a facet:

sage: h = extreme_functions.bhk_irrational()
sage: facet_test(h)
True

The algorithm cannot handle all cases:

sage: h = kzh_minimal_has_only_crazy_perturbation_1()
sage: facet_test(h, known_extreme=True)                              # long time - 30s
Traceback (most recent call last):
...
NotImplementedError: facet_test does not know how to continue

As a side effect, facet_test stores some data in the function:

sage: h._facet_symbolic.basis                                        # long time
[('function value at', 0.01010000000000000?),
 ('function value at', 0.02020000000000000?), ...,
 ('function value at', 0.8202000000000000?),
 ('slope of component', 0),
 ('slope of component', 1)]
sage: [h._facet_symbolic.basis.index(('function value at', x)) for x in [h.a0, h.a1, h.a2]]   # long time
[11, 19, 25]
sage: h._facet_equation_matrix.column(11)       # random # long time
(0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0)
sage: [ (variable, value) for variable, value in zip(h._facet_symbolic.basis, h._facet_equation_matrix[4]) if value ]  # long time
[(('function value at', 0.01010000000000000?), 1),
 (('function value at', 0.1900000000000000?), 1),
 (('function value at', 0.2071236354684422?), -1),
 (('slope of component', 1), 0.00702363546844223?)]
cutgeneratingfunctionology.igp.fake_f()

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO); 
sage: h = fake_f()
sage: minimality_test(h, f=4/5)
False
sage: minimality_test(h, f=1/5)
False
cutgeneratingfunctionology.igp.find_affine_bounds(fn, I, lower_bound=True, extended=False, norm='one')

Find the affine lower/upper estimator of the function fn over the closed interval I.

cutgeneratingfunctionology.igp.find_affine_bounds_new(fn, X, Y, lower_bound=True, norm='one')
cutgeneratingfunctionology.igp.find_all_bkpts_in_the_interval(bkpts, interval)

Return a list of breakpoints contained in interval and bkpts+Z. bkpts=fn.end_points(), and interval can be any closed interval contained in [0,2].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: fn=gj_2_slope()
sage: bkpts=fn.end_points()
sage: bkpts
[0, 4/15, 1/3, 3/5, 1]
sage: find_all_bkpts_in_the_interval(bkpts,[4/15,3/5])
[4/15, 1/3, 3/5]
sage: find_all_bkpts_in_the_interval(bkpts,[1/15,4/5])
[1/15, 4/15, 1/3, 3/5, 4/5]
sage: find_all_bkpts_in_the_interval(bkpts,[1/3,2])
[1/3, 3/5, 1, 19/15, 4/3, 8/5, 2]
sage: find_all_bkpts_in_the_interval(bkpts,[9/8,19/10])
[9/8, 19/15, 4/3, 8/5, 19/10]
cutgeneratingfunctionology.igp.find_best_intercept(X, Y, slope, lower_bound=True)

Find the intercept of the affine lower/upper estimator with fixed slope.

cutgeneratingfunctionology.igp.find_best_slope_intercept(X, Y, lower_bound=True, solver='Coin', norm='one')

Find the slope and intercept of the affine lower/upper estimator.

cutgeneratingfunctionology.igp.find_bkpts_index(bkpts, interval)
cutgeneratingfunctionology.igp.find_branching_bkpt(fn, I_index, extended=False, branching_point_selection='median')

Select the branching point.

cutgeneratingfunctionology.igp.find_branching_direction(fn, I, J, K, I_index, J_index, K_index)
cutgeneratingfunctionology.igp.find_decomposition_into_intervals_with_same_moves(functional_directed_moves, zero_perturbation_points=set([]))
cutgeneratingfunctionology.igp.find_decomposition_into_stability_intervals_with_completion(fn, show_plots=False, max_num_it=None)
cutgeneratingfunctionology.igp.find_delta(fn, f, q)

Subfunction of the procedure symmetric_2_slope_fill_in(). find a small delta that works for lemma 4 [dense-2-slope]

cutgeneratingfunctionology.igp.find_epsilon_for_crazy_perturbation(fn, cp, show_plots=False)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = kzh_minimal_has_only_crazy_perturbation_1()
sage: bkpts = h.end_points()
sage: t1 = bkpts[10]-bkpts[6]
sage: t2 = bkpts[13]-bkpts[6]
sage: f = bkpts[37]
sage: ucl = bkpts[17]
sage: ucr = bkpts[18]
sage: generators = [t1, t2]
sage: pwl = piecewise_function_from_breakpoints_and_slopes([0,1],[0])
sage: crazy_piece_1 = CrazyPiece((ucl, ucr), generators, [(ucl, 1), (ucr, -1)])
sage: crazy_piece_2 = CrazyPiece((f-ucr, f-ucl), generators, [(f-ucr, 1), (f-ucl, -1)])
sage: cp = PiecewiseCrazyFunction(pwl, [crazy_piece_1, crazy_piece_2])
sage: find_epsilon_for_crazy_perturbation(h, cp)
0.0003958663221935161?

sage: h = minimal_no_covered_interval()
sage: cp = equiv7_example_2_crazy_perturbation()
sage: find_epsilon_for_crazy_perturbation(h, cp)
1/6
cutgeneratingfunctionology.igp.find_epsilon_interval(fn, perturb)

Compute the largest (closed) interval of values \(\epsilon\) such that ` fn + epsilon * perturb ` is a minimal valid function.

cutgeneratingfunctionology.igp.find_epsilon_interval_continuous(fn, perturb)

Compute the interval [minus_epsilon, plus_epsilon] such that (fn + epsilon * perturb) is subadditive for epsilon in this interval. Assumes that fn is subadditive.

If one of the epsilons is 0, the function bails out early and returns 0, 0.

cutgeneratingfunctionology.igp.find_epsilon_interval_general(fn, perturb)

Compute the interval [minus_epsilon, plus_epsilon] such that (fn + epsilon * perturb) is subadditive for epsilon in this interval. Assumes that fn is subadditive.

If one of the epsilons is 0, the function bails out early and returns 0, 0.

cutgeneratingfunctionology.igp.find_f(fn, no_error_if_not_minimal_anyway=False)

Find the value of \(f\) for the given function .

cutgeneratingfunctionology.igp.find_gamma(fn)

Subfunction of the procedure symmetric_2_slope_fill_in(). find gamma>0 such that \(\Delta\pi(x, y) > \gamma\) for all \((x,y)\) in \([0,1]^2 \setminus (E_{\delta} \cup E_f \cup E_{1+f})\).

\(fn\) may be \(\pi_\delta\) in Lemma 5 or \(\pi_{comb}\) in Lemma 4 [dense-2-slope], with sufficiently small delta as described in the proof of the lemma.

EXAMPLE:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: pi_delta = generate_pi_delta(2/5, 1/10)
sage: find_gamma(pi_delta)
1/2
sage: pi_pwl = piecewise_function_from_breakpoints_and_values([0,1/5,2/5,3/5,4/5,1],[0,1/2,1,1/2,1/2, 0])
sage: pi_comb = generate_pi_comb(pi_pwl, 1/3, 1/10)
sage: find_gamma(pi_comb)
1/6
cutgeneratingfunctionology.igp.find_hermite_form_generators(generators)
cutgeneratingfunctionology.igp.find_infinity_norm_distance(pi_1, pi_2)
cutgeneratingfunctionology.igp.find_intersection_with_diagonal(v1, v2)

Find a point (x,x) lying on the line segment between v1,v2.

cutgeneratingfunctionology.igp.find_largest_epsilon(fn, perturb)

Compute the proper rescaling of a given perturbation function.

If the largest epsilon is zero, we should try a different perturbation instead.

cutgeneratingfunctionology.igp.find_midpoint(v1, v2)
cutgeneratingfunctionology.igp.find_point_flip_ineq_heuristic(current_var_value, ineq, ineqs, flip_ineq_step)

The current_var_value satisfies that l(current_var_value) <= 0 for l=ineq and for every l in ineqs, where ineq is a polynomial and ineqs is a list of polynomials.

Use heuristic method (gradient descent method with given small positive step length flip_ineq_step) to find a new_point (type is tuple) such that ineq(new_point) > 0, l(new_point) < 0 for all l in ineqs Return new_point, or None if it fails to find one.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: P.<a,b>=QQ[]
sage: find_point_flip_ineq_heuristic([1,1/2], a+b-2, [-a+b^2], 1/4)
(11/8, 7/8)

After walking towards ineq==0, ineqs < 0 is violated. Need to adjust:

sage: x, y = find_point_flip_ineq_heuristic([1,9/10], a+b-2, [-a+b^2], 1/2)  # got (123/85, 179/170)? (253/170, 86/85)?
sage: (x + y - 2 > 0) and (-x + y^2 < 0)
True
sage: x, y = find_point_flip_ineq_heuristic([11/40,1/2], a+b-2, [-a+b^2], 1/4) # got (39295901/31739294, 125037049/123564610), now get (45793/36987, 34307/33903)? (27439/22240, 22601/22240)?
sage: (x + y - 2 > 0) and (-x + y^2 < 0)
True

Ineq is a redundant inequality, it’s impossible to cross it without crossing any other ineqs. Thus, return None:

sage: pt = find_point_flip_ineq_heuristic([1,1/2], a+b-2, [-a+b^2, a-1], 1/4); pt is None
True

Bug example in cpl Cell 9 with test point (499/1250, 488072439572/4866126017667). Output was (333/1000, 167/1500) which violates ineqs[-1](pt) < 0. BUG! Notice that using sorted(ineqs) with the same current_var_value input gave a correct output. See def adjust_pt_to_satisfy_ineqs below:

sage: P.<f,z>=QQ[]; ineq = -3*f + 1; flip_ineq_step = 1/1000; current_var_value = (499/1250, 488072439572/4866126017667)
sage: ineqs = [2*f + 2*z - 1, f + 5*z - 1, -f - 6*z + 1, -2*f - 3*z + 1]
sage: pt = find_point_flip_ineq_heuristic(current_var_value, ineq, ineqs, flip_ineq_step) #got pt (333/1000, 67/600)
sage: all(l(pt) < 0 for l in ineqs) and ineq(pt)>0
True

Bug example from cpl cell 14 with test point (553/443147, 664/882853), theta 15 = ((-2*z)/(f - 1), 0), fixed. new bug: Bigcell r14, theta29, different order in ineqs:

sage: P.<f,z>=QQ[]; current_var_value = (553/443147, 664/882853); ineq = f^2 + f*z - f + z; ineqs = [2*f + 6*z - 1, f - 2*z, -f + z]; flip_ineq_step = 1/1000
sage: pt = find_point_flip_ineq_heuristic(current_var_value, ineq, ineqs, flip_ineq_step)  #(7927/71253, 39430/357637)? (17182/149045, 34610/302851)?
sage: all(l(pt) < 0 for l in ineqs) and ineq(pt)>0
True
sage: current_var_value = (553/443147, 664/882853); ineq = f^2 + f*z - f + z; ineqs = [f - 2*z, -f + z, 2*f + 6*z - 1]
sage: pt = find_point_flip_ineq_heuristic(current_var_value, ineq, ineqs, flip_ineq_step) # got (17182/149045, 34610/302851)
sage: all(l(pt) < 0 for l in ineqs) and ineq(pt)>0
True

Bug example from cpl cell 17 with test point (1007/8000, 999/8000), theta 16 ((-2*z)/(f - 1), 0):

sage: P.<f,z>=QQ[]; current_var_value = (1007/8000, 999/8000); ineq = -f^2 - f*z + f - z; ineqs = [2*f + 5*z - 1, f - 2*z, -2*f - 6*z + 1, -f + z]; flip_ineq_step = 1/1000
sage: pt = find_point_flip_ineq_heuristic(current_var_value, ineq, ineqs, flip_ineq_step) # got pt (13117/83401, 22445/196184)? (6824/43185, 11717/102636)
sage: all(l(pt) < 0 for l in ineqs) and ineq(pt)>0
True

Bug example in cpl cell 15 with test point (664/882853, 553/443147) theta 6 (f/(f - 4*z + 1), 0). Return None:

sage: P.<f,z>=QQ[]; current_var_value = (8608/76197, 11223/98473); ineq = -f^2 + 3*f*z + 4*z^2 - z; ineqs = [2*f + 6*z - 1, f - z, -2*f*z + 8*z^2 + f - 2*z, f*z - 4*z^2 - f + z]; flip_ineq_step = 1/1000
sage: pt = find_point_flip_ineq_heuristic(current_var_value, ineq, ineqs, flip_ineq_step)
sage: pt is None
True

Bug example in cpl bigcell r27 with test point (8242/139557, 18896/107013) theta9 ((-z)/(f + 2*z - 1), 0):

sage: P.<f,z>=QQ[]; current_var_value = (8242/139557, 18896/107013); ineq = -f^2 - 3*f*z - 2*z^2 + f; ineqs = [-f, f + 5*z - 1, f - z, -2*f - 5*z + 1]; flip_ineq_step = 1/1000
sage: pt = find_point_flip_ineq_heuristic(current_var_value, ineq, ineqs, flip_ineq_step) # got pt (8269/72753, 16950/109541)
sage: all(l(pt) < 0 for l in ineqs) and ineq(pt)>0
True

Bug example:

sage: P.<f,z>=QQ[]; current_var_value = (111/1000, 111/1000); ineq = -11*f^2 + f; ineqs = [9*f- 1, 5*f^2 - f, -11*f + 1]; flip_ineq_step=1/1000 # Can't find a pt whose f < 1/11 because -11*f^2 + f and -11*f + 1 are contradiction.
sage: pt = find_point_flip_ineq_heuristic(current_var_value, ineq, ineqs, flip_ineq_step); pt is None
True

Bug example, need (ineq_value <= 1e-10) rather than <=0. Without that the return was new_point = (7001/26000, 3001/26000) which was wrong as ineq(new_point) == 0:

sage: P.<bkpt,f>=QQ[]; current_var_value = [7001/26000, 3001/26000]; ineq = -13*bkpt + 13*f + 2; ineqs = [26*bkpt - 11, -169*bkpt*f + 169*f^2 + 3, -26*bkpt + 7]; flip_ineq_step = 1/2017;
sage: pt = find_point_flip_ineq_heuristic(current_var_value, ineq, ineqs, flip_ineq_step) # got pt (3738/13883, 7795/67523)
sage: all(l(pt) < 0 for l in ineqs) and ineq(pt)>0
True
cutgeneratingfunctionology.igp.find_polynomial_map(eqs=[], poly_ring=None)

BAD FUCNTION! It is used in ‘mathematica’ approach for non-linear case. Can we avoid it? Return a polynomial map that eliminates linear variables in eqs, and a dictionary recording which equations were used to eliminate those linear variables. Assume that gaussian elimination has been performed by PPL.minimized_constraints() on the input list of equations eqs. It is only called in SemialgebraicComplex.add_new_component in the case polynomial_map is not provided but bddbsa has equations.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: P.<a,b,c>=QQ[]
sage: find_polynomial_map([a+2*b+1])
[a, -1/2*a - 1/2, c]
sage: find_polynomial_map([2*a+b, b+c-1/2])
[a, -2*a, 2*a + 1/2]
sage: find_polynomial_map([a*a-b, b*b-c*c])
[a, a^2, c]
sage: find_polynomial_map([a^2+4*a+1])
[a, b, c]
sage: P.<d>=QQ[]
sage: find_polynomial_map([1-d^3])
[d]
sage: P.<f,a,b> = QQ[]
sage: find_polynomial_map([-f*a + 3*a^2 + 3*f*b - 9*a*b, -11*b + 2, -11*f + 3, -11*a + 1])
[3/11, 1/11, 2/11]
cutgeneratingfunctionology.igp.find_possible_branching_bkpts_index(bkpts, I)

Return [i,j] such that I[0]<bkpts[k]<I[1] for any i<=k<=j. Return None if empty.

cutgeneratingfunctionology.igp.find_region_color(region_type)

Return the color of the region according to the global dictionary region_type_color_map.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: find_region_color('is_extreme')
'blue'
sage: find_region_color(False)
'red'
cutgeneratingfunctionology.igp.find_region_type_igp(K, h, region_level='extreme', is_minimal=None)

Find the type of a igp function h in the ParametricRealField K; (is it constructible? is it minimal? is it extreme?) Record the comparisons in K.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: K.<f> = ParametricRealField([4/5])
sage: h = gmic(f, field=K)
sage: find_region_type_igp(K, h)
'is_extreme'
sage: K.get_lt_factor()
{-f, -f + 1/2, f - 1}

sage: K.<f,bkpt>=ParametricRealField([1/7,3/7])
sage: h = drlm_backward_3_slope(f, bkpt, field=K)
sage: find_region_type_igp(K, h)
'not_extreme'
sage: K.get_lt_factor()
{2*bkpt - 1,
 -f,
 -f + 2*bkpt - 1,
 f - 4*bkpt + 1,
 f - 3*bkpt + 1,
 f - bkpt,
 2*f - 1,
 2*f - bkpt}
cutgeneratingfunctionology.igp.find_region_type_igp_extreme(K, h)
cutgeneratingfunctionology.igp.find_region_type_igp_extreme_big_cells(K, h)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: complex = SemialgebraicComplex(drlm_backward_3_slope, ['f','bkpt'], find_region_type=find_region_type_igp_extreme_big_cells)
sage: complex.bfs_completion(var_value=[4/5,1/2])
sage: len(complex.components)
11
sage: complex.plot() # not tested
cutgeneratingfunctionology.igp.find_slope_intercept_trivial(X, Y)
cutgeneratingfunctionology.igp.finite_dimensional_extremality_test(function, show_plots=False, f=None, warn_about_uncovered_intervals=True, show_all_perturbations=False, full_certificates=True)

Solve a homogeneous linear system of additivity equations with one slope variable for every component (including every non-covered interval) and one jump variable for each (left/right) discontinuity.

Return a boolean that indicates whether the system has a nontrivial solution.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: h1 = drlm_not_extreme_2()
sage: finite_dimensional_extremality_test(h1, show_plots=True)
False
sage: h2 = drlm_3_slope_limit()
sage: finite_dimensional_extremality_test(h2, show_plots=True)
True
sage: h = equiv7_example_1()
sage: finite_dimensional_extremality_test(h)
False
sage: h._perturbations[0].list()
[[<Int{0}>, <FastLinearFunction 0>],
 [<Int(0, 1/2)>, <FastLinearFunction x - 1/4>],
 [(1/2, 1), <FastLinearFunction 0>]]
cutgeneratingfunctionology.igp.finite_dynamical_systems

Catalog of discrete dynamical systems

This module contains constructors for several specific discrete dynamical systems. These are accessible through sage.dynamics.finite_dynamical_system_catalog. or just through \(finite_dynamical_systems.\) (type either of these in Sage and hit tab for a list).

AUTHORS:

  • Darij Grinberg, Tom Roby (2018): initial version
cutgeneratingfunctionology.igp.finite_group_order_from_function_f_oversampling_order(fn, f=None, oversampling=None, order=None)

Determine a finite group order to use, based on the given parameters.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: finite_group_order_from_function_f_oversampling_order(gmic(f=4/5), order=17)
17
sage: finite_group_order_from_function_f_oversampling_order(gmic(f=4/5))
5
sage: finite_group_order_from_function_f_oversampling_order(gj_forward_3_slope())
45
sage: finite_group_order_from_function_f_oversampling_order(gmic(f=4/5), oversampling=3)
15
cutgeneratingfunctionology.igp.fn_constant_bounds(fn, I, lower_bound=True, extended=False)

Find the constant lower/upper bound of the function fn over the closed interval I.

cutgeneratingfunctionology.igp.fn_variable(q, x)
cutgeneratingfunctionology.igp.fractional(num)

Reduces a number modulo \(1\).

cutgeneratingfunctionology.igp.game_theory

Catalog Of Games

TESTS:

sage: 'absolute_import' in dir(game_theory)
False
cutgeneratingfunctionology.igp.gen_initial_polytope_sym(q, f, vertices_color, covered_intervals)
cutgeneratingfunctionology.igp.generate_additive_faces(fn)

Return the list of all additive faces of the subadditive function fn.

In the discontinuous case, this includes the faces determined by limit-additivities as well: Additive faces are defined in the discontinuous case according to [HKoppeZ18a], Definition 9.7 ({def:set-of-additivities-and-limit-additivities-of-a-face-F}), following Lemma 9.6 (lemma:additive-face-discontinuous): The face \(E \in \Delta\mathcal P\) is additive if there exists an enclosing face \(F \in \Delta\mathcal P\) such that for some (equivalently, all) \((x, y) \in \mathop{\mathrm{rel int}}(E)\), the limit \(\Delta\).

The additive faces (together with the empty face) form a subcomplex of \(Delta\mathcal P\). Thus, they are determined by the maximal elements; these are provided by generate_maximal_additive_faces.

Note that \(\Delta\) fn is invariant under swapping \(x\) and \(y\). This function does not break this symmetry.

See also: generate_additive_faces_sans_limits.

cutgeneratingfunctionology.igp.generate_additive_faces_discrete(fn)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: points = [i/13 for i in range(14)]
sage: values = [0, 6/7, 1/6, 5/7, 1/3, 4/7, 1/2, 3/7, 2/3, 2/7, 5/6, 1/7, 1, 0]
sage: fn = discrete_function_from_points_and_values(points, values)
sage: len(generate_additive_faces_discrete(fn))
61
cutgeneratingfunctionology.igp.generate_additive_faces_general(function)

Implementation of generate_additive_faces for discontinuous piecewise linear functions.

cutgeneratingfunctionology.igp.generate_additive_faces_sans_limits(fn)

Return a list of all additive faces of the subadditive function fn without taking limits into consideration.

A face E is additive-sans-limits if for some (equivalently, all) \((x, y) \in \mathop{\mathrm{rel int}}(E)\), we have \(\Delta\).

Such a face E is the convex hull of vertices \((x, y)\) that have the limits \(\Delta\).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = kzh_minimal_has_only_crazy_perturbation_1()
sage: x = h.end_points()
sage: F = Face(([x[6]],[1+x[4]-x[6]],[1+x[4]]))
sage: F in generate_additive_faces(h)
True
sage: F in generate_maximal_additive_faces(h)
False
sage: F in generate_additive_faces_sans_limits(h)
True
cutgeneratingfunctionology.igp.generate_additive_vertices(fn, reduced=True, bkpt=None)

Return the list of additive vertices in the form of 6-tuples (x, y, z, xeps, yeps, zeps).

When reduced is:

  • True: only outputs fewer triples, for the purpose of setting up the system of equations.
  • False: outputs all triples, for the purpose of plotting additive_limit_vertices.
cutgeneratingfunctionology.igp.generate_additive_vertices_from_faces(q, faces)

Return the set of points (x<=y) on q*q 2d-grid that are covered by faces.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: fn = gmic(1/3); q=3;
sage: faces = generate_maximal_additive_faces(fn)
sage: generate_additive_vertices_from_faces(q, faces)
{(0, 0), (0, 1/3), (0, 2/3), (0, 1), (1/3, 1), (2/3, 2/3), (2/3, 1), (1, 1)}
cutgeneratingfunctionology.igp.generate_additivity_equations(fn, symbolic, field=None, f=None, bkpt=None, reduce_system=None, return_vertices=False, vertices=None, undefined_ok=False, **args)

Using additivity, set up a finite-dimensional system of linear equations that must be satisfied by any perturbation.

Use vertices if provided, otherwise call uses the vertices obtained by generate_additive_vertices.

If reduce_system is True (the default when logging.DEBUG is enabled), remove redundant equations to make the system minimal.

If return_vertices is True, return a list of vertices in the form (x, y, z, xeps, yeps, zeps) corresponding to the rows of the matrix. There are two special labels: ‘f’ and ‘1’ that can appear instead of a vertex.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = hildebrand_discont_3_slope_1()
sage: components = generate_covered_intervals(h)
sage: symbolic = generate_symbolic(h, components, field=QQ)
sage: generate_additivity_equations(h, symbolic, field=QQ, reduce_system=False)
181 x 5 dense matrix ...
sage: generate_additivity_equations(h, symbolic, field=QQ, reduce_system=True)
[ 1/4  1/4    0    2    0]
[ 1/4  1/2  1/4    2    2]
[ 1/4  1/2  1/4    3    1]
[ 1/8 -1/8    0    1    0]
[   0  1/8 -1/8    2   -1]
sage: M, vs = generate_additivity_equations(h, symbolic, field=QQ, reduce_system=True, return_vertices=True)
sage: vs
['f', '1', (0, 1/8, 1/8, -1, 0, -1), (1/8, 1/8, 1/4, 0, 0, 0), (3/8, 3/8, 3/4, 1, 1, 1)]

For two-sided discontinuous functions we can use a different basis, in which we see the structure of the subadditivity constraints:

sage: h = hildebrand_2_sided_discont_2_slope_1()
sage: symbolic = generate_symbolic(h, basis_functions=('midpoints', 'slopes'))
sage: M, vs = generate_additivity_equations(h, symbolic, reduce_system=True, return_vertices=True)
sage: for row, v in zip(M, vs): print("Additive vertex {:30}  {}".format(str(v), row))
Additive vertex (0, 1/8, 1/8, -1, 1, 0)         (0, -1, 1, -1, 0, 0, 0, 0)
Additive vertex (0, 1/8, 1/8, 1, -1, 0)         (2, -1, 0, 0, 0, 0, 0, 0)
Additive vertex (0, 5/8, 5/8, -1, 0, -1)        (0, 0, 0, -2, 1, 0, 0, 0)
Additive vertex (0, 5/8, 5/8, 1, 0, 1)          (1, 0, 0, 0, 1, -1, 0, 0)
Additive vertex (1/8, 1/8, 1/4, -1, 1, 0)       (1, 0, 1, 0, 0, 0, -1/16, 1/16)
Additive vertex (1/8, 1/8, 1/4, -1, 1, 1)       (1, 0, 2, 0, 0, 0, 0, 1/16)
Additive vertex (1/8, 1/8, 1/4, -1, -1, -1)     (2, 0, -1, 0, 0, 0, -1/16, 1/8)
Additive vertex (1/8, 5/8, 3/4, 1, 0, 1)        (0, 0, 1, 0, 1, 1, -1/16, 1/16)
cutgeneratingfunctionology.igp.generate_additivity_equations_continuous(function, symbolic, field, f=None, bkpt=None, reduce_system=None, return_vertices=False, vertices=None)
cutgeneratingfunctionology.igp.generate_additivity_equations_general(function, symbolic, field, f=None, bkpt=None, reduce_system=None, return_vertices=False, undefined_ok=False, vertices=None)

Using additivity, set up a finite-dimensional system of linear equations that must be satisfied by any perturbation.

cutgeneratingfunctionology.igp.generate_all_components(fn, show_plots=False)
cutgeneratingfunctionology.igp.generate_all_faces(fn)
cutgeneratingfunctionology.igp.generate_candidate_faces(q, f, covered_intervals, last_face=None, faces_color=None, sym=False)

Returns a list of candidate_faces (lexicographically > last_face) to paint in next step, whose I, J are currently uncovered. Note that candidate_faces only takes faces with I <= J.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: q = 5; f = 3;
sage: vertices_color = initial_vertices_color(q, f);
sage: faces_color, covered_intervals = initial_faces_color_and_covered_intervals(q, f, vertices_color)
sage: generate_candidate_faces(q, f, covered_intervals)
[(1, 1, 0), (1, 1, 1)]
cutgeneratingfunctionology.igp.generate_containing_eps_triple(vertex, triple, with_limits=True)

Given vertex \(v\) of face \(F\), and the 3-projection-interval triple (minimal triple) of \(F\). Return the approaching limits {(xeps, yeps, zeps)} pointing inwards at \(v\) from containing faces of \(F\), that should be considered for testing the additivity of \(F\).

If with_limits=False, this computation is done for additivity of \(F\) sans limits.

cutgeneratingfunctionology.igp.generate_covered_components(function)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = hildebrand_discont_3_slope_1()
sage: generate_covered_components(h)
[[<Int(0, 1/8)>, <Int(3/8, 1/2)>],
 [<Int(1/8, 3/8)>, <Int(1/2, 5/8)>, <Int(7/8, 1)>],
 [<Int(5/8, 7/8)>]]

Also covered components that come from the strip lemma in the irrational case are included:

sage: h = bhk_irrational()
sage: len(generate_covered_components(h))
3
cutgeneratingfunctionology.igp.generate_covered_components_strategically(fn, show_plots=False, additive_faces=None)

Return both directly and indirectly covered components of fn.

Directly covered components are obtained by using the interval lemma (convex additivity domain lemma) on two-dimensional maximal additive faces of fn.

Indirectly covered components are obtained using the one-dimensional maximal additive faces of fn; this includes using limit-additivities. This is justified by Theorem 3.3 in [KoppeZ18] (which covers the two-sided discontinuous case).

If additive_faces is provided, use exactly these faces, assuming that they are additive.

Set logging.getLogger().setLevel(logging.DEBUG) to see a human-readable proof of covered components.

Set show_plots=True to visualize the proof.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: fn = bcdsp_arbitrary_slope(k=4)
sage: two_slope_fn = two_slope_fill_in_extreme(fn, 1)
sage: minimal_fn = 9/10 * two_slope_fn + 1/10 * gmic(f=find_f(two_slope_fn))
sage: minimality_test(minimal_fn)
True
sage: len(generate_covered_components(minimal_fn)) # long time
4
sage: len(generate_covered_components_strategically(minimal_fn)) # long time
4
cutgeneratingfunctionology.igp.generate_covered_intervals(function)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = hildebrand_discont_3_slope_1()
sage: generate_covered_components(h)
[[<Int(0, 1/8)>, <Int(3/8, 1/2)>],
 [<Int(1/8, 3/8)>, <Int(1/2, 5/8)>, <Int(7/8, 1)>],
 [<Int(5/8, 7/8)>]]

Also covered components that come from the strip lemma in the irrational case are included:

sage: h = bhk_irrational()
sage: len(generate_covered_components(h))
3
cutgeneratingfunctionology.igp.generate_directed_move_composition_completion(fn, show_plots=False, max_num_rounds=None, error_if_max_num_rounds_exceeded=True, plot_background=None)
cutgeneratingfunctionology.igp.generate_directly_covered_components(fn)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = gj_2_slope(3/5,1/3)
sage: generate_directly_covered_components(h)
[[<Int(0, 7/30)>, <Int(11/30, 3/5)>], [<Int(7/30, 11/30)>, <Int(3/5, 1)>]]
cutgeneratingfunctionology.igp.generate_directly_covered_intervals(fn)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = gj_2_slope(3/5,1/3)
sage: generate_directly_covered_components(h)
[[<Int(0, 7/30)>, <Int(11/30, 3/5)>], [<Int(7/30, 11/30)>, <Int(3/5, 1)>]]
cutgeneratingfunctionology.igp.generate_example_e_for_psi_n(f=2/3, n=7, q=4, eta=1/1000)

Return the first n terms of a geometric series e that satisfies 0 < … < e[n] <= e[n - 1] <= … <= e[1] <= e[0] <= 1 - f and sum_{i = 0}^{infty} {2^i * e[i]} <= f.

This can be used in psi_n_in_bccz_counterexample_construction(f, [e[0],…,e[n-1]]), so that the function constructed is extreme.

Parameters:
  • f (real) \(\in (0,1)\);
  • n (integer);
  • q (real), q > 2: ratio of the geometric series;
  • eta (real), 0 <= eta < 1: to control the series sum, sum_{i = 0}^{infty} {2^i * e[i]} <= (1 - eta)*f.
Note:
If (eta == 0) and (f >= 1/2), then sum_{i = 0}^{infty} {2^i * e[i]} = f.
This case is not mentioned in [IR1], but using a similar proof, one can show that:
  1. psi_n still converges uniformly to psi;
  2. The limit funciton psi is a continuous facet (hence extreme);
  3. psi is not piecewise linear.

Also notice that: psi is not in W^{1,1}. See [KZh2015b, section 5].

References:

  • [IR1] A. Basu, M. Conforti, G. Cornuejols, and G. Zambelli, A counterexample to a conjecture of Gomory and Johnson, Mathematical Programming Ser. A 133 (2012), 25-38.
  • [KZh2015b] M. Koeppe and Y. Zhou, An electronic compendium of extreme functions for the Gomory-Johnson infinite group problem, Operations Research Letters, 2015, http://dx.doi.org/10.1016/j.orl.2015.06.004
cutgeneratingfunctionology.igp.generate_extreme_functions_for_finite_group(q, f)

A generator that enumerates the interpolations of the extreme functions for the cyclic group problem \(R_{f/q}(1/q \ZZ, \ZZ)\).

cutgeneratingfunctionology.igp.generate_extreme_lifted_function_equiv(fn, show_plots=False, L=[], use_polyhedron=True)
cutgeneratingfunctionology.igp.generate_faces_with_projections_intersecting(function, real_set, break_symmetry=False, halfopen_cover_only=False)
cutgeneratingfunctionology.igp.generate_facet_covered_components(fn, show_plots=False)
cutgeneratingfunctionology.igp.generate_functional_directed_moves(fn)

Compute the (translations and reflections) moves.

cutgeneratingfunctionology.igp.generate_generic_seeds_with_completion(fn, show_plots=False, max_num_it=None)
cutgeneratingfunctionology.igp.generate_ieqs_and_eqns(q, ff, fn_sym, additive_vertices)

Return the equalities (by additivity) and inequalities (by subadditivity) that the slope variables must satisfy.

Inputs:
  • q, ff are integers.
  • fn_sym is the symbolic function generated by considering covered_intervals, as follows. intervals in the same component of a function must have the same slope value. Take slope of the i-th component as i-th unit vector. Then fn_sym maps x (in [0,1]) to a vector of dim = number of components.
  • additive_vertices are the green points on the 2d-grid, where additivity is attained by fn_sym.
Output:
  • ieqdic, eqndic are dictionaries that maps ieq/eqn to the 2d-complex-vertices from which it comes, where key = ieq or eqn, value = set of 2d-complex-vertices.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: q=3; ff=1;
sage: components=[[[0, 1/3]], [[1/3, 1]]]
sage: fn_sym = generate_symbolic_continuous(None, components, field=QQ)
sage: additive_vertices = {(0, 0), (0, 1/3), (0, 2/3), (0, 1), (1/3, 1), (2/3, 2/3), (2/3, 1), (1, 1)}
sage: ieqdic, eqndic = generate_ieqs_and_eqns(q, ff, fn_sym, additive_vertices)
sage: ieqdic
{(0, 0, 0): set(),
(0, 1/3, -1/3): {(1/3, 1/3), (1/3, 2/3)},
(0, 1/3, 0): set(),
(0, 1/3, 1/3): set(),
(1, -1/3, -1/3): set(),
(1, -1/3, 0): set(),
(1, 0, 0): set()}
sage: eqndic
{(-1, 1/3, 0): set(),
(0, 0, 0): {(0, 0), (0, 1/3), (0, 2/3), (0, 1)},
(0, 1/3, 2/3): {(1/3, 1), (2/3, 2/3), (2/3, 1), (1, 1)}}
cutgeneratingfunctionology.igp.generate_intervals_and_two_sided_discontinuous_breakpoints(function, halfopen_cover_only=False)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)                   # disable output for automatic tests

sage: h = kzh_minimal_has_only_crazy_perturbation_1(parametric=True)
sage: list(generate_intervals_and_two_sided_discontinuous_breakpoints(h, halfopen_cover_only=False))
[[0], [0, (x1)~], [(x1)~], [(x1)~, (x2)~], [(x2)~], [(x2)~, (x3)~], [(x3)~],
..., [(x39)~], [(x39)~, 1], [1]]
sage: list(generate_intervals_and_two_sided_discontinuous_breakpoints(h, halfopen_cover_only=True))
[[0], [0, (x1)~], [(x1)~], [(x1)~, (x2)~], [(x2)~, (x3)~], [(x3)~],
..., [(x39)~], [(x39)~, 1], [1]]
cutgeneratingfunctionology.igp.generate_lifted_functions(fn, perturbs=None, use_polyhedron=False, **kwds)

A generator of lifted functions.

If use_polyhedron=False (the default), set up an LP (as a MixedIntegerLinearProgram) with one dimension for each basic perturbation, with the subadditivities. Shoot random directions as objective functions. Solve the MIP. Lift the function by adding the perturbation that corresponds to the MIP solution. MIP solver keywords can be passed in kwds.

If use_polyhedron=True, set up a Polyhedron instead. Polyhedron constructor keywords can be passed in kwds.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN) # to disable output in automatic tests.
sage: h = not_extreme_1()
sage: h_lift = next(generate_lifted_functions(h, solver='ppl'))
sage: extremality_test(h_lift)
True

The above mip problem use ppl backend. We can use other backends, such as solver=InteractiveLP:

sage: h = not_extreme_1()
sage: gen = generate_lifted_functions(h, solver='InteractiveLP')
sage: h_lift = next(gen)
sage: extremality_test(h_lift)
True

If the solver argument is not specified, the code can figure it out, using field (base_ring).

The option solver=InteractiveLP is able to deal with irrational numbers:

sage: h = chen_tricky_uncovered_intervals()
sage: gen = generate_lifted_functions(h, perturbs=None, solver='InteractiveLP', field=None)
sage: h_lift = next(gen)
sage: extremality_test(h_lift)
True

By setting use_polyhedron=True, we use perturbation_polyhedron() rather than perturbation_mip() to generate lifted functions:

sage: h = not_extreme_1()
sage: gen = generate_lifted_functions(h, use_polyhedron=True)
sage: len([h_lift for h_lift in gen])
4
cutgeneratingfunctionology.igp.generate_lim_and_interior_slopes_on_perturbation_components(fn, perturbation_components=None, solver=None, use_polyhedron=True)
cutgeneratingfunctionology.igp.generate_lim_slopes_on_perturbation_components(fn, perturbation_components=None, solver=None, use_polyhedron=True)
cutgeneratingfunctionology.igp.generate_maximal_additive_faces(fn)

Compute the list of maximal additive faces of the subadditive function fn.

In the discontinuous case, this includes the faces determined by limit-additivities as well: Additive faces are defined in the discontinuous case according to [HKoppeZ18a], Definition 9.7 ({def:set-of-additivities-and-limit-additivities-of-a-face-F}), following Lemma 9.6 (lemma:additive-face-discontinuous): The face \(E \in \Delta\mathcal P\) is additive if there exists an enclosing face \(F \in \Delta\mathcal P\) such that for some (equivalently, all) \((x, y) \in \mathop{\mathrm{rel int}}(E)\), the limit \(\Delta\).

The additive faces (together with the empty face) form a subcomplex of \(Delta\mathcal P\). Thus, they are determined by the maximal elements.

(However, in the current implementation, in the discontinuous case, this function actually computes all additive faces, not just the maximal ones.)

Note that \(\Delta\) fn is invariant under swapping \(x\) and \(y\). This function does not break this symmetry.

cutgeneratingfunctionology.igp.generate_maximal_additive_faces_continuous(function)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = gj_2_slope(f=4/5, lambda_1=1/6, conditioncheck=False)
sage: generate_maximal_additive_faces_continuous(h)
[<Face ([0, 23/60], [0, 23/60], [0, 23/60])>,
 <Face ([0], [23/60, 5/12], [23/60, 5/12])>,
 <Face ([23/60, 5/12], [0], [23/60, 5/12])>,
 <Face ([0, 23/60], [5/12, 4/5], [5/12, 4/5])>,
 <Face ([5/12, 4/5], [0, 23/60], [5/12, 4/5])>,
 <Face ([0], [4/5, 1], [4/5, 1])>,
 <Face ([4/5, 1], [0], [4/5, 1])>,
 <Face ([23/60, 5/12], [23/60, 5/12], [4/5, 5/6])>,
 <Face ([23/60, 5/12], [29/30, 1], [83/60, 17/12])>,
 <Face ([29/30, 1], [23/60, 5/12], [83/60, 17/12])>,
 <Face ([4/5, 1], [4/5, 1], [9/5, 2])>]
cutgeneratingfunctionology.igp.generate_nonsymmetric_vertices(fn, f)
cutgeneratingfunctionology.igp.generate_nonsymmetric_vertices_continuous(fn, f)
cutgeneratingfunctionology.igp.generate_nonsymmetric_vertices_general(fn, f)

Generate vertices (x, y, xeps, yeps) that violate symmetric_test.

cutgeneratingfunctionology.igp.generate_overlapping_interval_indices(interval, breakpoints)

Given breakpoints (a list of breakpoints which generate subintervals), return a list of indices of subintervals that have a nonempty intersection with interval.

Examples:

sage: from cutgeneratingfunctionology.igp import *
sage: generate_overlapping_interval_indices([1/3,2/3], [0,1/4,1/2,3/4,1])
[1, 2]
sage: generate_overlapping_interval_indices([1/3,2/3], [0,1/4,1/3,1/2,2/3])
[1, 2, 3]
cutgeneratingfunctionology.igp.generate_perturbation_on_perturbation_components(fn, perturbation_components=None, use_polyhedron=True, repeat=None)
cutgeneratingfunctionology.igp.generate_perturbations(fn, show_plots=False, f=None, max_num_it=1000, finite_dimensional_test_first=False, full_certificates=True)

Generate (with yield) perturbations for extremality_test.

cutgeneratingfunctionology.igp.generate_perturbations_equivariant(fn, show_plots=False, f=None, max_num_it=1000)
cutgeneratingfunctionology.igp.generate_perturbations_finite_dimensional(function, show_plots=False, f=None, full_certificates=True)

Generate (with yield) perturbations for finite_dimensional_extremality_test.

cutgeneratingfunctionology.igp.generate_perturbations_simple(fn, show_plots=False, f=None, oversampling=3, order=None, full_certificates=True)

Generate (with “yield”) perturbations for simple_finite_dimensional_extremality_test.

cutgeneratingfunctionology.igp.generate_pi_comb(pi_pwl, epsilon, delta, f=None)

Subfunction of the procedure symmetric_2_slope_fill_in().

See Lemma 4 in [dense-2-slope]

EXAMPLE:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: pi_pwl = piecewise_function_from_breakpoints_and_values([0,1/5,2/5,3/5,4/5,1],[0,1/2,1,1/2,1/2, 0])
sage: minimality_test(pi_pwl)
True
sage: plot_2d_diagram(pi_pwl)  # not tested
sage: pi_comb = generate_pi_comb(pi_pwl, 1/3, 1/10)
sage: plot_2d_diagram(pi_comb) # not tested
sage: minimality_test(pi_comb)
True
cutgeneratingfunctionology.igp.generate_pi_delta(f, delta)

Subfunction of the procedure symmetric_2_slope_fill_in().

See Equation 2 in [dense-2-slope]

EXAMPLE:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: pi_delta = generate_pi_delta(2/5, 1/10)
sage: plot_2d_diagram(pi_delta) # not tested
sage: minimality_test(pi_delta)
True
cutgeneratingfunctionology.igp.generate_pi_fill_in(fn, q, f=None)

Subfunction of the procedure symmetric_2_slope_fill_in(). Return the fill-in function pi_fill_in of fn with respect to (1/q)Z and the sublinear function \(g(r) = \max(s_p r, s_m r)\). See the first phase in the proof of Lemma 6 [dense-2-slope].

EXAMPLE:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: pi_pwl = piecewise_function_from_breakpoints_and_values([0,1/5,2/5,3/5,4/5,1],[0,1/2,1,1/2,1/2, 0])
sage: pi_comb = generate_pi_comb(pi_pwl, 1/3, 1/10)
sage: pi_fill_in = generate_pi_fill_in(pi_comb, 10)
sage: subadditivity_test(pi_fill_in)
True
sage: minimality_test(pi_fill_in)
False
cutgeneratingfunctionology.igp.generate_pi_pwl(function, epsilon, f=None, order=None)

Subfunction of the procedure symmetric_2_slope_fill_in().

Approximate function by a piesewise linear function pi_pwl whose breakpoints are all rationals, such that abs(function(x) - pi_pwl(x)) <= epsilon for x in (0, 1).

Assume that function is piecewise linear, and \(f\) is a rational number.

Output pi_pwl and the order \(q\).

EXAMPLE:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: h = piecewise_function_from_breakpoints_and_values([0,1/5,2/5,3/5,4/5,1],[0,1/2,1,1/2,1/2,0])
sage: q, pi_pwl = generate_pi_pwl(h, 1/3)
sage: q
5
sage: h_irr = piecewise_function_from_breakpoints_and_values([0,1/5,2/5,3/5+1/10/sqrt(5),4/5-1/10/sqrt(5),1],[0,1/2,1,1/2-1/4/sqrt(5),1/2+1/4/sqrt(5),0])
sage: q, pi_pwl_irr = generate_pi_pwl(h_irr, 1/3)
sage: q
5
sage: pi_pwl_irr == h
True
cutgeneratingfunctionology.igp.generate_pi_sym(fn, f=None)

Subfunction of the procedure symmetric_2_slope_fill_in(). Return pi_sym that coincides with fn on \([0,f/2]\) and \([(1+f)/2, 1]\), and satisfies the symmetry condition. See the second phase in the proof of Lemma 6 [dense-2-slope].

Assume the piecewise linear function fn satisfies that fn(f/2) = fn((1+f)/2) = 1/2.

EXAMPLE:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: pi_pwl = piecewise_function_from_breakpoints_and_values([0,1/5,2/5,3/5,4/5,1],[0,1/2,1,1/2,1/2, 0])
sage: pi_comb = generate_pi_comb(pi_pwl, 1/3, 1/10)
sage: pi_fill_in = generate_pi_fill_in(pi_comb, 10)
sage: pi_sym = generate_pi_sym(pi_fill_in)
sage: symmetric_test(pi_sym, find_f(pi_sym))
True
sage: extremality_test(pi_sym)
True
sage: find_infinity_norm_distance (pi_sym, pi_pwl)
1/6
cutgeneratingfunctionology.igp.generate_random_mip_sol(mip)
cutgeneratingfunctionology.igp.generate_symbolic(fn, components=None, field=None, f=None, show_plots=False, basis_functions=None, **kwds)

Construct a vector-space-valued piecewise linear function compatible with the given function fn.

Two systems of basis_functions are available:
  • ('slopes', 'jumps')
  • ``(‘midpoints’, ‘slopes’)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = hildebrand_discont_3_slope_1()
sage: components =  generate_covered_intervals(h)
sage: g = generate_symbolic(h, components, field=QQ)
sage: g.list()
[[<Int[0, 1/8)>, <FastLinearFunction ((1,0,0,0,0))*x>],
 [(1/8, 3/8), <FastLinearFunction ((0,1,0,0,0))*x + ((1/8,-1/8,0,1,0))>],
 [<Int(3/8, 1/2]>, <FastLinearFunction ((1,0,0,0,0))*x - ((1/4,-1/4,0,-2,0))>],
 [<Int(1/2, 5/8]>, <FastLinearFunction ((0,1,0,0,0))*x + ((1/4,-1/4,0,2,1))>],
 [<Int(5/8, 7/8]>,
  <FastLinearFunction ((0,0,1,0,0))*x + ((1/4,3/8,-5/8,2,1))>],
 [<Int(7/8, 1)>, <FastLinearFunction ((0,1,0,0,0))*x + ((1/4,-1/2,1/4,2,1))>],
 [<Int{1}>, <FastLinearFunction ((1/4,1/2,1/4,2,2))>]]   

sage: h = extreme_functions.drlm_backward_3_slope()
sage: sym = generate_symbolic(h, basis_functions=('midpoints', 'slopes'))
sage: sym.basis
[('function value at', 1/8),
 ('function value at', 1/6),
 ('slope of component', 0),
 ('slope of component', 1),
 ('slope of component', 2)]
cutgeneratingfunctionology.igp.generate_symbolic_continuous(function, components, field=None, f=None)

Construct a vector-space-valued piecewise linear function compatible with the given function. Each of the components of the function has a slope that is a basis vector of the vector space.

cutgeneratingfunctionology.igp.generate_symbolic_general(function, components, field=None, f=None, basis_functions=None)

Construct a vector-space-valued piecewise linear function compatible with the given function.

Each of the components of the function has a slope that is a basis vector of the vector space. Each discontinuous point has a left or/and right jump that is a basis vector of the vector space.

cutgeneratingfunctionology.igp.generate_thetas_of_region(r)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)                                  # not tested
sage: regions = cpl_regions_from_arrangement_of_bkpts(3, cpleq=True) # not tested
sage: r = regions[0]                                                 # not tested
sage: thetas = generate_thetas_of_region(r)                          # not tested
sage: len(thetas)                                                    # not tested
24
sage: thetas[-1]                                                     # not tested
((-z)/(f - 1), (-z)/(f - 1))
cutgeneratingfunctionology.igp.generate_to_cover(q, covered_intervals)

Returns a sorted list {k | 0 <=k < q, [k, (k+1)] is uncovered} from coverd_intervals which is a list of componenents.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: covered_intervals = [set([0,2]), set([3,4])]
sage: generate_to_cover(5, covered_intervals)
[1]
cutgeneratingfunctionology.igp.generate_triples_with_projections_intersecting(function, real_set, break_symmetry=False, halfopen_cover_only=False)

It breaks symmetry but produces duplicates.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)                   # disable output for automatic tests
sage: h = kzh_minimal_has_only_crazy_perturbation_1(parametric=True)
sage: faces = set(generate_faces_with_projections_intersecting(h, h.special_intervals, break_symmetry=False))    # long time - 90s
sage: sum(F.plot(fill_color='lightblue', rgbcolor='blue') for F in faces).show(figsize=15, xmax=1) # not tested
cutgeneratingfunctionology.igp.generate_type_1_vertices(fn, comparison, reduced=True, bkpt=None)
cutgeneratingfunctionology.igp.generate_type_1_vertices_continuous(fn, comparison, bkpt=None)

Output 6-tuples (x, y, z,xeps, yeps, zeps).

cutgeneratingfunctionology.igp.generate_type_1_vertices_general(fn, comparison, reduced=True, bkpt=None)

A generator of vertices.

..._general refers to the fact that it outputs 6-tuples (x,y,z,xeps,yeps,zeps).

When reduced is:

  • True: only outputs fewer triples satisfying comparison relation, for the purpose of minimality_test or setting up system of equations.
  • False: outputs all triples satisfying comparison relation, for the purpose of plotting nonsubadditive or additive_limit_vertices.
cutgeneratingfunctionology.igp.generate_type_2_vertices(fn, comparison, reduced=True, bkpt=None)
cutgeneratingfunctionology.igp.generate_type_2_vertices_continuous(fn, comparison, bkpt=None)
cutgeneratingfunctionology.igp.generate_type_2_vertices_general(fn, comparison, reduced=True, bkpt=None)

A generator of vertices.

When reduced is:

  • True: only outputs fewer triples satisfying comparison relation, for the purpose of minimality_test or setting up system of equations. Note: if \(fn\) is continuous at \(y\), then use \(fn(y^-) = fn(y) = fn(y^+)\).
  • False: outputs all triples satisfying comparison relation, for the purpose of plotting nonsubadditive or additive_limit_vertices.
cutgeneratingfunctionology.igp.generate_uncovered_components(fn, show_plots=False)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = equiv7_example_1()
sage: generate_uncovered_components(h)
[[<Int(0, 1/4)>, <Int(1/4, 1/2)>]]
sage: h = minimal_no_covered_interval()
sage: generate_uncovered_components(h)
[[<Int(0, 1/4)>, <Int(1/4, 1/2)>], [<Int(1/2, 3/4)>, <Int(3/4, 1)>]]
cutgeneratingfunctionology.igp.generate_uncovered_intervals(function)
cutgeneratingfunctionology.igp.generate_uncovered_set(q, uncovered_intervals)

Returns set {k | 0 <=k < q, [k, (k+1)] is uncovered} from uncoverd_intervals which is a list of componenents.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: uncovered_intervals = [set([0,2]), set([3,4])]
sage: generate_uncovered_set(5, uncovered_intervals)
{0, 2, 3, 4}
cutgeneratingfunctionology.igp.generate_vertex_function(q, ff, fn_sym, additive_vertices, kslopes=3)

Generate real valued functions which correspond to vertices of the polytope defined by [ieqs, eqns] = generate_ieqs_and_eqns(..)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: q=3; ff=1;
sage: components=[[[0, 1/3]], [[1/3, 1]]]
sage: fn_sym = generate_symbolic_continuous(None, components, field=QQ)
sage: additive_vertices = {(0, 0), (0, 1/3), (0, 2/3), (0, 1), (1/3, 1), (2/3, 2/3), (2/3, 1), (1, 1)}
sage: h = next(generate_vertex_function(q, ff, fn_sym, additive_vertices, kslopes=2))
sage: h == gmic(1/3)
True
cutgeneratingfunctionology.igp.generate_vertex_values(k_slopes, q, polytope, v_set=set([]), exp_dim=-1, vetime=False)

Enumerate the vertices of the polytope.

Return the vertices (numerators) that were not in v_set and have at least k_slopes.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: q = 5; f = 3; k_slopes = 2;
sage: vertices_color = initial_vertices_color(q, f);
sage: cs = initial_cs(q, f, vertices_color)
sage: polytope = C_Polyhedron(cs)
sage: list(generate_vertex_values(k_slopes , q, polytope))
[(0, 3, 1, 4, 2, 0), (0, 2, 4, 6, 3, 0)]
cutgeneratingfunctionology.igp.generate_vertices_of_additive_faces_sans_limits(fn)

Compute the list of vertices of faces that are additive-sans-limits in the form of 6-tuples (x, y, z, xeps, yeps, zeps). Here z is not reduced modulo 1.

TESTS:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = kzh_minimal_has_only_crazy_perturbation_1()
sage: x = h.end_points()
sage: (x[6], 1+x[4]-x[6], 1+x[4], 0, 0, 0) in generate_vertices_of_additive_faces_sans_limits(h)
True
cutgeneratingfunctionology.igp.get_pretty_fraction_polynomial(fp)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: PR2.<f,z1,z2>=QQ[]
sage: fp = (-2*z1)/(-2*f + 4*z1 - 6)
sage: get_pretty_fraction_polynomial(fp)
z1/(f - 2*z1 + 3)
sage: fp = (f/4+z1/3+z2/3)/(1/12)
sage: get_pretty_fraction_polynomial(fp)
3*f + 4*z1 + 4*z2
cutgeneratingfunctionology.igp.glpk_simplex_exact_solve(lp)

Solve lp by glp_simplex + glp_exact

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: lp = MixedIntegerLinearProgram(solver = 'GLPK', maximization = False)
sage: x, y = lp[0], lp[1]
sage: lp.add_constraint(-2*x + y <= 1)
sage: lp.add_constraint(x - y <= 1)
sage: lp.add_constraint(x + y >= 2)
sage: lp.set_objective(x + y)
sage: print("glp_exact noise follows in old sage versions"); glpk_simplex_exact_solve(lp)
glp_exact...
2.0
cutgeneratingfunctionology.igp.gmic_disjoint(f=4/5)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = gmic_disjoint(4/5)
sage: extremality_test(h, False)
True
cutgeneratingfunctionology.igp.gmic_disjoint_with_singletons(f=4/5)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = gmic_disjoint_with_singletons(4/5)
sage: extremality_test(h, False)
True
cutgeneratingfunctionology.igp.gomory_fractional(f=4/5)

The Gomory fractional cut. Not minimal.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = gomory_fractional(f=4/5)
sage: minimality_test(h, f=4/5)
False
cutgeneratingfunctionology.igp.gradient(ineq)

Return the gradient of the polynomial ineq.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: P.<x,y>=QQ[]
sage: gradient(2*x^2*y+x^3+4*y+5)
[3*x^2 + 4*x*y, 2*x^2 + 4]
sage: P.<z>=QQ[]
sage: gradient(z^3+3*z^2+1)
[3*z^2 + 6*z]
cutgeneratingfunctionology.igp.graph_coloring

File: sage/graphs/graph_coloring.pyx (starting at line 1)

Graph coloring

This module gathers all methods related to graph coloring. Here is what it can do :

Proper vertex coloring

all_graph_colorings() Compute all \(n\)-colorings a graph
first_coloring() Return the first vertex coloring found
number_of_n_colorings() Compute the number of \(n\)-colorings of a graph
numbers_of_colorings() Compute the number of colorings of a graph
chromatic_number() Return the chromatic number of the graph
vertex_coloring() Compute vertex colorings and chromatic numbers

Other colorings

grundy_coloring() Compute Grundy numbers and Grundy colorings
b_coloring() Compute b-chromatic numbers and b-colorings
edge_coloring() Compute chromatic index and edge colorings
round_robin() Compute a round-robin coloring of the complete graph on \(n\) vertices
linear_arboricity() Compute the linear arboricity of the given graph
acyclic_edge_coloring() Compute an acyclic edge coloring of the current graph

AUTHORS:

  • Tom Boothby (2008-02-21): Initial version
  • Carlo Hamalainen (2009-03-28): minor change: switch to C++ DLX solver
  • Nathann Cohen (2009-10-24): Coloring methods using linear programming
cutgeneratingfunctionology.igp.group_function_from_superadditive_lifting_function(phi, f=None)

Convert a group representation ‘fn’ (a subadditive periodic function) from a standard representation ‘phi’ (a superadditive quasiperiodic function).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # Suppress output in automatic tests.
sage: phi = cpl3_function(r0=1/7, z1=1/7, o1=1/4, o2=1/12)
sage: fn = group_function_from_superadditive_lifting_function(phi)
sage: fn_expected = FastPiecewise([[(0, 1/7), FastLinearFunction(7, 0)], [(1/7, 2/7), FastLinearFunction(-21/4, 7/4)], [(2/7, 3/7), FastLinearFunction(35/12, -7/12)], [(3/7, 5/7), FastLinearFunction(-7/6, 7/6)], [(5/7, 6/7), FastLinearFunction(35/12, -7/4)], [(6/7, 1), FastLinearFunction(-21/4, 21/4)]])
sage: fn == fn_expected
True
sage: q = plot(fn)
cutgeneratingfunctionology.igp.groups

Examples of Groups

The groups object may be used to access examples of various groups. Using tab-completion on this object is an easy way to discover and quickly create the groups that are available (as listed here).

Let <tab> indicate pressing the tab key. So begin by typing groups.<tab> to the see primary divisions, followed by (for example) groups.matrix.<tab> to access various groups implemented as sets of matrices.

cutgeneratingfunctionology.igp.h_from_vertex_values(v_n)

Construct the piecewise linear function from vertex.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: v_n = (0, 2, 4, 6, 3, 0)
sage: h = h_from_vertex_values(v_n)
sage: h == piecewise_function_from_breakpoints_and_values([0, 3/5, 1], [0, 1, 0])
True
cutgeneratingfunctionology.igp.hildebrand_2_sided_discont_1_slope_1()
_images/igp-27.svg

The first known example of function that is discontinuous on both sides of the origin but is also extreme.

Constructed by Robert Hildebrand (2013, unpublished).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = hildebrand_2_sided_discont_1_slope_1()
sage: extremality_test(h, False)
True
cutgeneratingfunctionology.igp.hildebrand_2_sided_discont_2_slope_1()
_images/igp-28.svg

The second known example of function that is discontinuous on both sides of the origin but is also extreme. This one has 2 slopes.

Constructed by Robert Hildebrand (2013, unpublished).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = hildebrand_2_sided_discont_2_slope_1()
sage: extremality_test(h, False)
True
cutgeneratingfunctionology.igp.hildebrand_5_slope_22_1()
_images/igp-29.svg

One of Hildebrand’s 5-slope functions.

They held the world record regarding the number of slopes until functions with more slopes were discovered in 2014.

From Hildebrand (2013, unpublished).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = hildebrand_5_slope_22_1()
sage: extremality_test(h, False)
True
cutgeneratingfunctionology.igp.hildebrand_5_slope_24_1()
_images/igp-30.svg

One of Hildebrand’s 5-slope functions.

They held the world record regarding the number of slopes until functions with more slopes were discovered in 2014.

From Hildebrand (2013, unpublished).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = hildebrand_5_slope_24_1()
sage: extremality_test(h, False)
True
cutgeneratingfunctionology.igp.hildebrand_5_slope_28_1()
_images/igp-31.svg

One of Hildebrand’s 5-slope functions.

They held the world record regarding the number of slopes until functions with more slopes were discovered in 2014.

From Hildebrand (2013, unpublished).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = hildebrand_5_slope_28_1()
sage: extremality_test(h, False)
True
cutgeneratingfunctionology.igp.hildebrand_discont_3_slope_1()
_images/igp-32.svg

This is a very new discontinuous 3-slope function that is extreme.

Constructed by Robert Hildebrand (2013, unpublished).

A detailed extremality proof appears as an example in [HKoppeZ18b].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: psi = hildebrand_discont_3_slope_1()
sage: extremality_test(psi, False)
True

In [KoppeZ17b], it is shown that this function (called \(\psi\)) is neither a weak facets nor a facet, by showing that the function ` psi’ = discontinuous_facets_paper_example_psi_prime() ` has a larger additivity domain \(E\) (sans limits):

sage: psi = hildebrand_discont_3_slope_1()
sage: E_psi = set(generate_additive_faces_sans_limits(psi))
sage: psi_prime = discontinuous_facets_paper_example_psi_prime(merge=False)
sage: E_psi_prime = set(generate_additive_faces_sans_limits(psi_prime))
sage: E_psi.issubset(E_psi_prime)
True
sage: sorted(E_psi_prime.difference(E_psi), key=lambda F: F.minimal_triple)
[<Face ([0, 1/8], [0, 1/8], [1/8])>, <Face ([0, 1/8], [0, 1/8], [1/8, 1/4])>, ...]

In fact, if one uses only the faces of \(\psi\) that are additive sans limits, then there is one covered component only; two intervals remain uncovered:

sage: show_plots=False
sage: show_plots=True      # not tested
sage: sorted(generate_covered_components_strategically(psi, show_plots=show_plots,
....:                                                  additive_faces=E_psi))
[[<Int(0, 1/8)>, <Int(3/8, 1/2)>],
 [<Int(1/8, 1/4)>, <Int(1/4, 3/8)>],
 [<Int(5/8, 3/4)>, <Int(3/4, 7/8)>]]
cutgeneratingfunctionology.igp.igp_load(fpath)
cutgeneratingfunctionology.igp.initial_covered_uncovered(q, f, vertices_color)

Returns initial covered_intervals and uncovered_intervals, corresponding to \(\pi(0) = 0\), \(\pi(1) = 0\) and reflection around \(f/2\) and \((1+f)/2\).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: q=5; f=3;
sage: vertices_color = initial_vertices_color(q, f);
sage: initial_covered_uncovered(q, f, vertices_color)
([{0, 2}, {3, 4}], [{1}])
cutgeneratingfunctionology.igp.initial_cs(q, f, vertices_color)

Return the initial constraint system that defines the feasible region of \((\pi(0), \pi(1/q),\dots, \pi(1))\).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: q=5; f=3;
sage: vertices_color = initial_vertices_color(q, f);
sage: cs = initial_cs(q, f, vertices_color)
sage: cs
Constraint_System {x0==0, x5==0, x3-1==0, x1>=0, -x1+1>=0, x2>=0, -x2+1>=0, x3>=0, -x3+1>=0, x4>=0, -x4+1>=0, 2*x1-x2>=0, x1+x2-x3==0, x1+x3-x4>=0, -x0+x1+x4>=0, 2*x2-x4>=0, -x0+x2+x3>=0, -x1+x2+x4>=0, -x1+2*x3>=0, -x2+x3+x4>=0, x3-2*x4==0}
sage: C_Polyhedron(cs).minimized_generators()
Generator_System {point(0/4, 3/4, 1/4, 4/4, 2/4, 0/4), point(0/6, 2/6, 4/6, 6/6, 3/6, 0/6)}
cutgeneratingfunctionology.igp.initial_cs_matrix(q, f)

Returns the matrix of the initial equality constraints’ coefficients, for the purpose of estimating the dimension of the polytope in backtracking search.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: initial_cs_matrix(5, 3)
[ 1  0  0  0  0]
[ 0  0  0  1  0]
[ 0  1  1 -1  0]
[ 0  0  0 -1  2]
cutgeneratingfunctionology.igp.initial_cs_sym(q, f, vertices_color)
cutgeneratingfunctionology.igp.initial_faces_color_and_covered_intervals(q, f, vertices_color)

Return initial faces_color and covered_intervals, corresponding to \(\pi(0) = 0\), \(\pi(1) = 0\) and reflection around \(f/2\) and \((1+f)/2\).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: q=5; f=3;
sage: vertices_color = initial_vertices_color(q, f);
sage: faces_color, covered_intervals = initial_faces_color_and_covered_intervals(q, f, vertices_color)
sage: faces_color[:,:,0]
array([[0, 1, 0, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 0]])
sage: faces_color[:,:,1]
array([[1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 0],
       [1, 1, 1, 1, 0]])
sage: covered_intervals
[{0, 2}, {3, 4}]
cutgeneratingfunctionology.igp.initial_mip(q, f, vertices_color)

Set up a MixedIntegerLinearProgram() with respect to the trivial constraints and the subadditivity/additivity constraints specified by \(q\), \(f\) and vertices_color. Varibles of the MILP are fn[0], …, fn[q], and auxiliary variables delta[x, y].

Global variables:
  • m: MixedIntegerLinearProgram()
  • delta: auxiliary variables delta; controle additive/subadd by m.set_max(delta[x, y], 0) or m.set_max(delta[x, y], None)
  • var_id: maps (x,y) to the index of the variable delta[x, y] in MixedIntegerLinearProgram m

EXAMPLES:

sage: import cutgeneratingfunctionology.igp as igp
sage: q=5; f=3;
sage: vertices_color = igp.initial_vertices_color(q, f);
sage: igp.initial_mip(q, f, vertices_color)
sage: igp.m.number_of_variables()
16
sage: igp.delta[1,1]
x_6
sage: igp.var_id[1,1]
6
cutgeneratingfunctionology.igp.initial_vertices_color(q, f)

paint green (\(=0\)) for vertices (\(x \leq y\)) corresonding to \(\pi(0) = 0\), \(\pi(1) = 0\) and reflection around \(f/2\) and \((1+f)/2\).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: initial_vertices_color(5, 3)
array([[0, 0, 0, 0, 0, 0],
       [1, 1, 0, 1, 1, 0],
       [1, 1, 1, 1, 1, 0],
       [1, 1, 1, 1, 1, 0],
       [1, 1, 1, 1, 0, 0],
       [1, 1, 1, 1, 1, 0]])
cutgeneratingfunctionology.igp.initialization_sym(q, f)
cutgeneratingfunctionology.igp.injective_2_slope_fill_in(fn, epsilon=1, show_plots=False)

Input: a (continuous) minimal function fn for the infinite group problem, or a discrete minimal function for the finite group problem, with rational breakpoints in 1/qZ and rational function values at the breakpoints. (weaker condition: rational breakpoints and the set {x: fn_interpolation(x)=1/2} is the union of some rational x and intervals.) Output: a two-slope extreme function fn2 such that fn2 = fn on 1/mqZ (and the infinity norm distance between fn and fn2 is less than epsilon).

The function is obtained by putting upward and downward tents with slopes equal to the limiting slopes of the input function on top of some intervals between the points of the finite group of order mq = injective_2_slope_fill_in_order.

This construction was introduced in [KoppeZ19].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: fn = discrete_function_from_points_and_values([0,1/5,2/5,3/5,4/5,1],[0,1/2,1,1/2,1/2,0])
sage: minimality_test(fn)
True
sage: extremality_test(fn)
False
sage: fn2 = injective_2_slope_fill_in(fn)
sage: extremality_test(fn2)
True

sage: fn = not_extreme_1()
sage: fn2 = injective_2_slope_fill_in(fn)
sage: extremality_test(fn2)
True
sage: find_infinity_norm_distance (fn, fn2)
1/12
sage: fn_app = injective_2_slope_fill_in(fn, epsilon=1/20)
sage: finite_group_order_from_function_f_oversampling_order(fn_app)
160
sage: minimality_test(fn_app)
True
sage: find_infinity_norm_distance (fn, fn_app)
1/48

sage: fn = gmic()
sage: fn2 = injective_2_slope_fill_in(fn)
sage: fn == fn2
True

sage: fn =restrict_to_finite_group(minimal_has_uncovered_interval(), order=8)
sage: fn2 = injective_2_slope_fill_in(fn)
sage: extremality_test(fn2)
True

sage: fn =restrict_to_finite_group(minimal_has_uncovered_interval(), order=16)
sage: fn2 = injective_2_slope_fill_in(fn)
sage: minimality_test(fn2)
True

sage: fn = minimal_has_uncovered_breakpoints()
sage: fn2 = injective_2_slope_fill_in(fn)
sage: minimality_test(fn2)
True

sage: fn = example7slopecoarse2()
sage: fn2 = injective_2_slope_fill_in(fn)
sage: number_of_slopes(fn2)
2
sage: minimality_test(fn2)
True

sage: fn = lift_until_extreme_only_works_with_strict_subset_L()
sage: fn2 = injective_2_slope_fill_in(fn)
sage: number_of_slopes(fn2)
2
sage: minimality_test(fn2)
True
sage: extremality_test(fn2, full_certificates=False)
True

sage: fn = lift_until_extreme_default_style_bug_example()
sage: fn2 = injective_2_slope_fill_in(fn)  # q=52; q2=order=4004
sage: finite_group_order_from_function_f_oversampling_order(fn2)
12012

Systematic testing:

sage: q = 10; f = 1; show_plots=False
sage: for h in generate_extreme_functions_for_finite_group(q, f): #long time
....:     if number_of_slopes(h) > 2:
....:         if show_plots: plot_2d_diagram(h, colorful=True)
....:         order = injective_2_slope_fill_in_order(h)
....:         if order < 1000:
....:             i = injective_2_slope_fill_in(h, show_plots=show_plots)
....:             assert minimality_test(i)
cutgeneratingfunctionology.igp.injective_2_slope_fill_in_order(fn, epsilon=1)

Compute the sampling order mq for use in injective_2_slope_fill_in.

cutgeneratingfunctionology.igp.interacts

Interacts included with sage

AUTHORS:

  • Harald Schilly (2011-01-16): initial version (#9623) partially based on work by Lauri Ruotsalainen
cutgeneratingfunctionology.igp.interpolate_to_infinite_group(function, merge=True)

Interpolate the given function to make it a function in the infinite group problem.

_images/igp-33.svg

function may be a function of a finite (cyclic) group problem, represented as a FastPiecewise with singleton intervals within [0,1] as its parts.

(function is actually allowed, however, to be more general; it can be any FastPiecewise.)

See restrict_to_finite_group for a discussion of the relation of the finite and infinite group problem.

If merge is True (the default), adjacent pieces of equal slopes are merged into one.

EXAMPLES:

The same as restrict_to_finite_group(drlm_not_extreme_1()):

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: h7 = discrete_function_from_points_and_values([0/7, 1/7, 2/7, 3/7, 4/7, 5/7, 6/7, 7/7], [0/10, 4/10, 8/10, 5/10, 2/10, 6/10, 10/10, 0/10])
sage: finite_dimensional_extremality_test(h7)
True
sage: h = interpolate_to_infinite_group(h7)
sage: extremality_test(h)
False
sage: h21 = restrict_to_finite_group(h, oversampling=3)
sage: finite_dimensional_extremality_test(h21)
False
sage: h28 = restrict_to_finite_group(h, oversampling=4)
sage: finite_dimensional_extremality_test(h28)
False
sage: h14 = restrict_to_finite_group(h, oversampling=2) # for this example, even factor 2 works!
sage: finite_dimensional_extremality_test(h14)
False
cutgeneratingfunctionology.igp.interval_including_endpoints_if_continuous(interval, pts_of_discontinuity=True, fdm=None)
cutgeneratingfunctionology.igp.interval_length_n_step_mir(n, m, a, b)
cutgeneratingfunctionology.igp.interval_mod_1(interval)

Represent the given proper interval modulo \(1\) as a subinterval of \([0,1]\).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: from cutgeneratingfunctionology.igp import *
sage: interval_mod_1([1,6/5])
[0, 1/5]
sage: interval_mod_1([1,2])
[0, 1]
sage: interval_mod_1([-3/10,-1/10])
[7/10, 9/10]
sage: interval_mod_1([-1/5,0])
[4/5, 1]        
cutgeneratingfunctionology.igp.interval_slope_variable(j, k)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: interval_slope_variable(7, 3)
'i_7_s_3'
cutgeneratingfunctionology.igp.is_QQ_linearly_independent(*numbers)

Test if numbers are linearly independent over QQ.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)  # Suppress output in automatic tests.
sage: is_QQ_linearly_independent()
True
sage: is_QQ_linearly_independent(1)
True
sage: is_QQ_linearly_independent(0)
False
sage: is_QQ_linearly_independent(1,2)
False
sage: is_QQ_linearly_independent(1,sqrt(2))
True
sage: is_QQ_linearly_independent(1+sqrt(2),sqrt(2),1)
False
sage: is_QQ_linearly_independent(pi)
True
sage: is_QQ_linearly_independent(1,pi)
Traceback (most recent call last):
...
ValueError: Q-linear independence test only implemented for algebraic numbers
cutgeneratingfunctionology.igp.is_additive_face(fn, face)

Test whether the given face is additive by taking the appropriate limits (pointing inwards) at the vertices.

cutgeneratingfunctionology.igp.is_additive_face_sans_limits(fn, face)

Test whether face is additive-sans-limits for fn.

See generate_additive_faces_sans_limits.

cutgeneratingfunctionology.igp.is_all_QQ(values)

Check if all numbers in the list values are (or can be converted to) rationals.

Returns a tuple of two values:

  • True if all rationals
  • a list of values (converted to elements of QQ if True, or the original elements otherwise).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: is_QQ, QQ_values = is_all_QQ([1, 2/3])
sage: is_QQ
True
sage: QQ_values
[1, 2/3]
sage: [ parent(x) for x in QQ_values ]
[Rational Field, Rational Field]
sage: is_all_QQ([1, pi])
(False, [1, pi])
cutgeneratingfunctionology.igp.is_all_QQ_fastpath(values)

This version does not do the full check whether it can be coerced to QQ, which is slow for RealNumberField.

cutgeneratingfunctionology.igp.is_all_the_same_number_field_fastpath(values)

This version does not try coercions and compares fields using is, rather than their comparison operator.

cutgeneratingfunctionology.igp.is_all_the_same_real_number_field(values)
cutgeneratingfunctionology.igp.is_in_ZZ_span(x, generators)
cutgeneratingfunctionology.igp.is_real_number_field_element(x)
cutgeneratingfunctionology.igp.kzh_10_slope_1()
_images/igp-34.svg

A 10-slope extreme function.

Its two-dimensional polyhedral complex includes special patterns.

This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_10_slope_1()
sage: extremality_test(h)
True

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_28_slope_1()
_images/igp-35.svg

A 28-slope extreme function.

This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

This was briefly the world record, until Basu, Conforti, Di Summa, and Paat gave a construction of a family of functions with an arbitrary number of slopes (see bcdsp_arbitrary_slope).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_28_slope_1()
sage: number_of_slopes(h)
28
sage: extremality_test(h) # long time
True

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_28_slope_2()
_images/igp-36.svg

A 28-slope extreme function.

This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

This was briefly the world record, until Basu, Conforti, Di Summa, and Paat gave a construction of a family of functions with an arbitrary number of slopes (see bcdsp_arbitrary_slope).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_28_slope_2()
sage: number_of_slopes(h)
28
sage: extremality_test(h) # long time
True

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_2q_example_1()

A continuous 4-slope non-extreme function, whose restriction to 1/2q is extreme, thereby showing that an oversampling factor of 3 is optimal.

This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

Example:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_2q_example_1()
sage: extremality_test(h)
False
sage: h_1q = restrict_to_finite_group(h, oversampling=1)
sage: extremality_test(h_1q)
True
sage: h_2q = restrict_to_finite_group(h, oversampling=2)
sage: extremality_test(h_2q)
True
sage: h_3q = restrict_to_finite_group(h, oversampling=3)
sage: extremality_test(h_3q)
False

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_5_slope_fulldim_1()
_images/igp-37.svg

A continuous 5-slope extreme function without any 0-d or 1-d maximal additive faces except for the symmetry reflection or x=0 or y=0.

This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_5_slope_fulldim_1()
sage: extremality_test(h)
True
sage: uncovered_intervals_from_covered_intervals(generate_directly_covered_intervals(h))
[]

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_5_slope_fulldim_2()
_images/igp-38.svg

A continuous 5-slope extreme function without any 0-d or 1-d maximal additive faces except for the symmetry reflection or x=0 or y=0.

This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_5_slope_fulldim_2()
sage: extremality_test(h)
True
sage: uncovered_intervals_from_covered_intervals(generate_directly_covered_intervals(h))
[]

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_5_slope_fulldim_3()
_images/igp-39.svg

A continuous 5-slope extreme function without any 0-d or 1-d maximal additive faces except for the symmetry reflection or x=0 or y=0.

This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_5_slope_fulldim_3()
sage: extremality_test(h)
True
sage: uncovered_intervals_from_covered_intervals(generate_directly_covered_intervals(h))
[]

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_5_slope_fulldim_4()
_images/igp-40.svg

5-slope extreme function without any 0-d or 1-d maximal additive faces except for the symmetry reflection or x=0 or y=0.

This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_5_slope_fulldim_4()
sage: extremality_test(h)
True
sage: uncovered_intervals_from_covered_intervals(generate_directly_covered_intervals(h))
[]

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_5_slope_fulldim_5()
_images/igp-41.svg

5-slope extreme function without any 0-d or 1-d maximal additive faces except for the symmetry reflection or x=0 or y=0.

This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_5_slope_fulldim_5()
sage: extremality_test(h)
True
sage: uncovered_intervals_from_covered_intervals(generate_directly_covered_intervals(h))
[]

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_5_slope_fulldim_covers_1()
_images/igp-42.svg

5-slope extreme function whose extremality proof does not depend on lower-dimensional additive faces. All intervals are directly covered.

This is in contrast to hildebrand_5_slope_22_1 etc., whose extremality proof requires to translate and reflect covered intervals.

This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_5_slope_fulldim_covers_1()
sage: extremality_test(h)
True
sage: uncovered_intervals_from_covered_intervals(generate_directly_covered_intervals(h))
[]

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_5_slope_fulldim_covers_2()
_images/igp-43.svg

5-slope extreme function whose extremality proof does not depend on lower-dimensional additive faces. All intervals are directly covered. This is in contrast to hildebrand_5_slope_22_1 etc., whose extremality proof requires to translate and reflect covered intervals.

This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_5_slope_fulldim_covers_2()
sage: extremality_test(h)
True
sage: uncovered_intervals_from_covered_intervals(generate_directly_covered_intervals(h))
[]

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_5_slope_fulldim_covers_3()
_images/igp-44.svg

5-slope extreme function whose extremality proof does not depend on lower-dimensional additive faces. All intervals are directly covered. This is in contrast to hildebrand_5_slope_22_1 etc., whose extremality proof requires to translate and reflect covered intervals. This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_5_slope_fulldim_covers_3()
sage: extremality_test(h)
True
sage: uncovered_intervals_from_covered_intervals(generate_directly_covered_intervals(h))
[]

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_5_slope_fulldim_covers_4()
_images/igp-45.svg

5-slope extreme function whose extremality proof does not depend on lower-dimensional additive faces. All intervals are directly covered. This is in contrast to hildebrand_5_slope_22_1 etc., whose extremality proof requires to translate and reflect covered intervals. This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_5_slope_fulldim_covers_4()
sage: extremality_test(h)
True
sage: uncovered_intervals_from_covered_intervals(generate_directly_covered_intervals(h))
[]

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_5_slope_fulldim_covers_5()
_images/igp-46.svg

5-slope extreme function whose extremality proof does not depend on lower-dimensional additive faces. All intervals are directly covered. This is in contrast to hildebrand_5_slope_22_1 etc., whose extremality proof requires to translate and reflect covered intervals. This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_5_slope_fulldim_covers_5()
sage: extremality_test(h)
True
sage: uncovered_intervals_from_covered_intervals(generate_directly_covered_intervals(h))
[]

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_5_slope_fulldim_covers_6()
_images/igp-47.svg

5-slope extreme function whose extremality proof does not depend on lower-dimensional additive faces. All intervals are directly covered. This is in contrast to hildebrand_5_slope_22_1 etc., whose extremality proof requires to translate and reflect covered intervals. This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_5_slope_fulldim_covers_6()
sage: extremality_test(h)
True
sage: uncovered_intervals_from_covered_intervals(generate_directly_covered_intervals(h))
[]
cutgeneratingfunctionology.igp.kzh_5_slope_q22_f10_1()
_images/igp-48.svg
cutgeneratingfunctionology.igp.kzh_5_slope_q22_f10_2()
_images/igp-49.svg
cutgeneratingfunctionology.igp.kzh_5_slope_q22_f10_3()
_images/igp-50.svg
cutgeneratingfunctionology.igp.kzh_5_slope_q22_f10_4()
_images/igp-51.svg
cutgeneratingfunctionology.igp.kzh_5_slope_q22_f2_1()
_images/igp-52.svg
cutgeneratingfunctionology.igp.kzh_6_slope_1()
_images/igp-53.svg

A 6-slope extreme function.

Its two-dimensional polyhedral complex includes special patterns.

This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_6_slope_1()
sage: extremality_test(h)
True

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_6_slope_fulldim_covers_1()
_images/igp-54.svg

6-slope extreme function whose extremality proof does not depend on lower-dimensional additive faces. All intervals are directly covered. This is in contrast to hildebrand_5_slope_22_1 etc., whose extremality proof requires to translate and reflect covered intervals. This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_6_slope_fulldim_covers_1()
sage: extremality_test(h)
True
sage: uncovered_intervals_from_covered_intervals(generate_directly_covered_intervals(h))
[]

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_6_slope_fulldim_covers_2()
_images/igp-55.svg

6-slope extreme function whose extremality proof does not depend on lower-dimensional additive faces. All intervals are directly covered. This is in contrast to hildebrand_5_slope_22_1 etc., whose extremality proof requires to translate and reflect covered intervals. This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_6_slope_fulldim_covers_2()
sage: extremality_test(h)
True
sage: uncovered_intervals_from_covered_intervals(generate_directly_covered_intervals(h))
[]

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_6_slope_fulldim_covers_3()
_images/igp-56.svg

6-slope extreme function whose extremality proof does not depend on lower-dimensional additive faces. All intervals are directly covered. This is in contrast to hildebrand_5_slope_22_1 etc., whose extremality proof requires to translate and reflect covered intervals. This example has a similar 2d-diagram as that of kzh_6_slope_fulldim_covers_2() This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_6_slope_fulldim_covers_3()
sage: extremality_test(h)
True
sage: uncovered_intervals_from_covered_intervals(generate_directly_covered_intervals(h))
[]

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_6_slope_fulldim_covers_4()
_images/igp-57.svg
_images/igp-58.svg

6-slope extreme function whose extremality proof does not depend on lower-dimensional additive faces. All intervals are directly covered. This is in contrast to hildebrand_5_slope_22_1 etc., whose extremality proof requires to translate and reflect covered intervals. This example has a similar 2d-diagram as that of kzh_6_slope_fulldim_covers_2() This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_6_slope_fulldim_covers_4()
sage: extremality_test(h)
True
sage: uncovered_intervals_from_covered_intervals(generate_directly_covered_intervals(h))
[]

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_6_slope_fulldim_covers_5()
_images/igp-59.svg
_images/igp-60.svg

6-slope extreme function whose extremality proof does not depend on lower-dimensional additive faces. All intervals are directly covered. This is in contrast to hildebrand_5_slope_22_1 etc., whose extremality proof requires to translate and reflect covered intervals. This example has a similar 2d-diagram as that of kzh_6_slope_fulldim_covers_2() This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_6_slope_fulldim_covers_5()
sage: extremality_test(h)
True
sage: uncovered_intervals_from_covered_intervals(generate_directly_covered_intervals(h))
[]

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_7_slope_1()
_images/igp-61.svg

A 7-slope extreme function.

This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_7_slope_1()
sage: extremality_test(h)
True

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_7_slope_2()
_images/igp-62.svg

A 7-slope extreme function.

This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_7_slope_2()
sage: extremality_test(h)
True

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_7_slope_3()
_images/igp-63.svg

A 7-slope extreme function.

This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_7_slope_3()
sage: extremality_test(h)
True

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_7_slope_4()
_images/igp-64.svg

A 7-slope extreme function.

This example was found by computer-based search described in Koeppe–Zhou [KZh2015a].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = kzh_7_slope_4()
sage: extremality_test(h)
True

Reference:

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.kzh_discontinuous_bhk_irrational(f=4/5, d1=3/5, d2=1/8, a0=19/100, delta_ratio=1/3*sqrt(2), bb=1/1000, c2=0, y1=1/10, y2=1/50, field=None)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: hmin = kzh_discontinuous_bhk_irrational(f=4/5, d1=3/5, d2=5/40, a0=19/100, delta_ratio=sqrt(2)/3, bb=19/23998, c2=5/11999, y1=185/1846, y2=240/11999, field=None)
sage: minimality_test(hmin)
True
class cutgeneratingfunctionology.igp.kzh_extreme_and_weak_facet_but_not_facet(pi=None)
_images/igp-65.svg

An extreme function and weak facet that is not a facet.

This factory class generates a fresh function from an infinite family. The function depends on the sequence of its evaluations.

TESTS:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = kzh_extreme_and_weak_facet_but_not_facet()
sage: hm = kzh_minimal_has_only_crazy_perturbation_1()+1/1000000*kzh_minimal_has_only_crazy_perturbation_1_perturbation()
sage: minimality_test_randomized(h, kzh_minimal_has_only_crazy_perturbation_1(), hm,
....:                            limits=False, extra_cosets=[sqrt(3), -sqrt(3)],
....:                            max_iterations=10)
True
Reference:
Matthias Koeppe, Yuan Zhou. On the notions of facets, weak facets, and extreme functions of the Gomory-Johnson infinite group problem.
__call__(x)

Examples:

sage: from cutgeneratingfunctionology.igp import kzh_extreme_and_weak_facet_but_not_facet, delta_pi
sage: h = kzh_extreme_and_weak_facet_but_not_facet()
sage: bool(delta_pi(h, 1/5+sqrt(3), 3/7+sqrt(1/3)) >= 0)
True
sage: bool(delta_pi(h, -13/9, 3/7)>=0)
True
sage: bool(delta_pi(h, 19/8, 3/7-3*sqrt(101))>=0)
True
sage: bool(delta_pi(h, 19/8+sqrt(101/9), 3/7-1/3*sqrt(101))>=0)
True
__init__(pi=None)
__module__ = 'cutgeneratingfunctionology.igp'
is_in_C(x)
is_in_Cplus(x)
is_in_T(x)
plot(*args, **kwds)
cutgeneratingfunctionology.igp.kzh_minimal_has_only_crazy_perturbation_1(parametric=False, field=None, **parametric_kwds)

This function is a two-sided discontinuous piecewise linear minimal valid function introduced in [KoppeZ18] which is not extreme, but which is not a convex combination of other piecewise linear minimal valid functions. It has two special intervals \((l, u)\) and \((f-u, f-l)\), on which every nonzero perturbation is microperiodic (invariant under the action of a dense additive group).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = kzh_minimal_has_only_crazy_perturbation_1()
sage: minimality_test(h)
True

On the one hand, there do not exist any nonzero piecewise continuous perturbations:

sage: extremality_test(h, crazy_perturbations=False)
True

To attempt to reproduce the automatic proof of this fact that is given in [KoppeZ18], Appendix C, we can do the following:

sage: logging.getLogger().setLevel(logging.DEBUG)  # not tested - for interactive use
sage: import cutgeneratingfunctionology.igp as igp 
sage: igp.strategical_covered_components = True
sage: igp.show_values_of_fastpiecewise = False
sage: igp.show_RNFElement_by_embedding = False
sage: h = kzh_minimal_has_only_crazy_perturbation_1()         # long time
sage: extremality_test(h, crazy_perturbations=False)          # long time
True
sage: igp.strategical_covered_components = False
sage: igp.show_values_of_fastpiecewise = True
sage: igp.show_RNFElement_by_embedding = True

Unfortunately, the details of the code have changed and it now makes different choices for the full-rank subsystem, so the subsystem shown in the publication cannot be reproduced with the current version of the code.

Let’s look a bit closer. We take out the component that is only densely covered, consisting of the two special intervals:

sage: proper_covered_components = generate_covered_components(h)[:2]

symbolic is the template for the perturbation function \(\bar\pi\); it is a general element of the vector space generated by the discontinuous piecewise functions with same slopes on the intervals of each covered component, defined outside of the special intervals:

sage: symbolic = generate_symbolic(h, proper_covered_components, basis_functions=('midpoints', 'slopes'))
sage: plot_symbolic(symbolic, ymin=-1.1, ymax=1.1).show(figsize=(4,40))      # not tested

Here we used the midpoints-and-slopes basis, which is “local.” It makes sure that symbolic is undefined on the special intervals:

sage: symbolic((h.ucl + h.ucr) / 2)
Traceback (most recent call last):
...
ValueError: ...

We generate equations from additive and limit-additive vertices, avoiding (by undefined_ok=True) to write down any equation that touches the special intervals. (The solution set is a superset of the projection to the quotient by the subspace of arbitrary real functions supported on the special intervals.)

sage: M, vs = generate_additivity_equations(h, symbolic, reduce_system=True, return_vertices=True, undefined_ok=True) sage: perturbations = M.right_kernel().basis() sage: len(perturbations) 0

The solution set is trivial. Thus, any perturbation is zero outside of the special intervals.

On the other hand, there exist crazy perturbations, such as the one we construct below:

sage: bkpts = h.end_points()
sage: t1 = bkpts[10]-bkpts[6]
sage: t2 = bkpts[13]-bkpts[6]
sage: f = bkpts[37]
sage: ucl = bkpts[17]
sage: ucr = bkpts[18]
sage: generators = [t1, t2]
sage: pwl = piecewise_function_from_breakpoints_and_slopes([0,1],[0])
sage: crazy_piece_1 = CrazyPiece((ucl, ucr), generators, [(ucl, 1), (ucr, -1)])
sage: crazy_piece_2 = CrazyPiece((f-ucr, f-ucl), generators, [(f-ucr, 1), (f-ucl, -1)])
sage: cp = PiecewiseCrazyFunction(pwl, [crazy_piece_1, crazy_piece_2])
sage: cp == kzh_minimal_has_only_crazy_perturbation_1_perturbation()  # not tested - equality is not implemented
True

This crazy perturbation is valid, since it has positive epsilon:

sage: find_epsilon_for_crazy_perturbation(h, cp)
0.0003958663221935161?

Therefore, the function kzh_minimal_has_only_crazy_perturbation_1() is not extreme.

In [KoppeZ17b], it shown that \(\pi = \) ` is a weak facet. In the proof, we take an arbitrary minimal valid function \(\pi'\) with \(E(\pi) \subseteq E(\pi')\). Because we have no control over the limit-additivities of the function \(\pi'\), all of our arguments have to use addivities-sans-limit of \(\pi\). First we show that \(\pi'\) has to be affine linear on every non-special intervals of \(\pi\).

sage: h = kzh_minimal_has_only_crazy_perturbation_1() sage: additive_faces_sans_limits = list(generate_additive_faces_sans_limits(h)) sage: covered_components = generate_covered_components_strategically(h, additive_faces=additive_faces_sans_limits) sage: uncovered_intervals = uncovered_intervals_from_covered_components(covered_components) sage: uncovered_intervals == [open_interval(h.ucl, h.ucr), open_interval(h._f - h.ucr, h._f - h.ucl)] True

The above is also done by facet_test:

sage: h = kzh_minimal_has_only_crazy_perturbation_1()
sage: facet_test(h)                                     # long time - 45s
Traceback (most recent call last):
...
NotImplementedError: facet_test does not know how to continue

facet_test also sets up a finite system for a general partial function outside the special intervals, again only using additivities-sans-limit.

sage: len(list(b for t, b in h._facet_symbolic.basis if t == ‘function value at’ and b in h.end_points())) # long time 19 sage: len(list(b for t, b in h._facet_symbolic.basis if t == ‘function value at’ and b not in h.end_points())) # long time 18

Again this system has a full rank, and no nontrivial solution exists.

sage: len(h._facet_solution_basis) # long time 0

NOTE:

If parametric=True, the breakpoints and slopes are given symbolic names. This is useful for printing.

sage: h = kzh_minimal_has_only_crazy_perturbation_1(parametric=True) sage: h.which_pair(1/100) (<Int(0, (x1)~)>, <FastLinearFunction ((c3)~)*x + (0.1553846153846154?)>) sage: h.which_pair(250/800) (<Int(l~, u~)>, <FastLinearFunction ((c2)~)*x + (0.3482269355779649?)>) sage: h.which_pair(1/2) (<Int((f - u)~, (f - l)~)>, <FastLinearFunction ((c2)~)*x + (0.6514397033086091?)>)

Note:

This example is obtained by the following code:

sage: import cutgeneratingfunctionology.igp as igp; from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: igp.generate_symbolic_two_sided_discontinuous_basis_functions = ('slopes', 'jumps')   # Restore classic behavior
sage: hmin = kzh_discontinuous_bhk_irrational(f=4/5, d1=3/5, d2=5/40, a0=19/100, delta_ratio=sqrt(2)/3, bb=19/23998, c2=5/11999, y1=185/1846, y2=240/11999, field=None) # long time
sage: hlift = lift_until_extreme(hmin, use_all_perturbations=False, use_largest_absolute_epsilon=False) # long time
sage: h == hlift  # long time
True

Without knowing the input values of kzh_discontinuous_bhk_irrational() that gives a minimal valid ‘hmin’, one could use the default values to construct a non-minimal discontinuous function, and then lift the function to minimal, as follows:

sage: h_org = kzh_discontinuous_bhk_irrational() # long time
sage: hmin_from_org = lift(h_org, phase_1=True, use_all_perturbations=False, use_largest_absolute_epsilon=False) # long time
sage: hmin ==  hmin_from_org # long time
True

‘hmin’ is minimal but not extreme. The solution space of the finite dimensional test has dimension 5:

sage: finite_dimensional_extremality_test(hmin,show_all_perturbations=True) # long time
False
sage: perturbs = hmin._perturbations # long time
sage: len(perturbs) # long time
5

A more general way of lifting ‘hmin’ is to call the following generator. (Use Sage Polyhedron if ‘use_polyhedron’ is set to False. Use LP if with random objective function if ‘use_polyhedron’ is set to True.) Unfortunately, this method is too slow. With use_polyhedron=False, it takes 15-20 mins to find a lifted function:

sage: gen = generate_lifted_functions(hmin, perturbs=perturbs, use_polyhedron=False) # not tested
sage: h = next(gen) # not tested
cutgeneratingfunctionology.igp.kzh_minimal_has_only_crazy_perturbation_1_check_subadditivity_slacks(parametric=False)

Check a claim in the proof of the theorem that kzh_minimal_has_only_crazy_perturbation_1 is a weak facet (but not extreme, nor a facet).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)                   # disable output for automatic tests
sage: logging.getLogger().setLevel(logging.DEBUG)     # not tested - for interactive use
sage: kzh_minimal_has_only_crazy_perturbation_1_check_subadditivity_slacks()
cutgeneratingfunctionology.igp.kzh_minimal_has_only_crazy_perturbation_1_perturbation()

A crazy perturbation for kzh_minimal_has_only_crazy_perturbation_1.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = kzh_minimal_has_only_crazy_perturbation_1()
sage: cp = kzh_minimal_has_only_crazy_perturbation_1_perturbation()
sage: find_epsilon_for_crazy_perturbation(h, cp)                       # long time - 70s
0.0003958663221935161?
cutgeneratingfunctionology.igp.last_lifted(fn)
cutgeneratingfunctionology.igp.latex_formatter_or_empty(x, labels_list=[0, 1])
cutgeneratingfunctionology.igp.latex_formatter_or_f_or_empty(x, f, labels_list=[0, 1])
cutgeneratingfunctionology.igp.latex_tick_formatter_x(x)
cutgeneratingfunctionology.igp.latex_tick_formatter_y(y)
cutgeneratingfunctionology.igp.lcdd_rational(in_str, verbose=False)

Use the command lcdd_gmp from cddlib.

Input: cdd format in_str; Output: cdd format out_str;

cutgeneratingfunctionology.igp.left_open_piece(p, q)
cutgeneratingfunctionology.igp.lie_algebras

Examples of Lie Algebras

There are the following examples of Lie algebras:

  • A rather comprehensive family of 3-dimensional Lie algebras
  • The Lie algebra of affine transformations of the line
  • All abelian Lie algebras on free modules
  • The Lie algebra of upper triangular matrices
  • The Lie algebra of strictly upper triangular matrices

See also sage.algebras.lie_algebras.virasoro.LieAlgebraRegularVectorFields and sage.algebras.lie_algebras.virasoro.VirasoroAlgebra for other examples.

AUTHORS:

  • Travis Scrimshaw (07-15-2013): Initial implementation
cutgeneratingfunctionology.igp.lift(fn, show_plots=False, use_all_perturbations=True, use_largest_absolute_epsilon=True, **kwds)
cutgeneratingfunctionology.igp.lift_extreme_function_for_finite_group_to_infinite_group(fn, show_plots=False, show_all_lifting=True)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = drlm_not_extreme_1()
sage: hh = lift_extreme_function_for_finite_group_to_infinite_group(h)
sage: len(hh)
2
sage: h = example7slopecoarse2()
sage: hh = lift_extreme_function_for_finite_group_to_infinite_group(h)
sage: len(hh)
12
sage: bkpts = [0, 1/13, 3/13, 7/26, 4/13,5/13,21/52,23/52,6/13,8/13,33/52,35/52,9/13,10/13,21/26,11/13,1]
sage: values = [0,1,3/14,5/7,3/4,5/14,55/112,33/112,3/7,4/7,79/112,57/112,9/14,1/4,2/7,11/14,0]
sage: h = piecewise_function_from_breakpoints_and_values(bkpts, values)
sage: hh = lift_extreme_function_for_finite_group_to_infinite_group(h)
sage: len(hh)
2
sage: extremality_test(hh[0])
True

BUG EXAMPLES:

sage: h = FastPiecewise([[(QQ(0), 1/18), FastLinearFunction(QQ(18), QQ(0))], [(1/18, 1/9), FastLinearFunction(-126/11, 18/11)], [(1/9, 1/6), FastLinearFunction(18/55, 18/55)], [(1/6, 2/9), FastLinearFunction(342/55, -36/55)], [(2/9, 5/18), FastLinearFunction(-126/11, 36/11)], [(5/18, 1/3), FastLinearFunction(666/55, -36/11)], [(1/3, 7/18), FastLinearFunction(-306/55, 144/55)], [(7/18, 4/9), FastLinearFunction(18/55, 18/55)], [(4/9, 1/2), FastLinearFunction(342/55, -126/55)], [(1/2, 5/9), FastLinearFunction(-126/11, 72/11)], [(5/9, 11/18), FastLinearFunction(342/55, -36/11)], [(11/18, 2/3), FastLinearFunction(18/55, 18/55)], [(2/3, 13/18), FastLinearFunction(-306/55, 234/55)], [(13/18, 7/9), FastLinearFunction(666/55, -468/55)], [(7/9, 5/6), FastLinearFunction(-126/11, 108/11)], [(5/6, 8/9), FastLinearFunction(342/55, -54/11)], [(8/9, 17/18), FastLinearFunction(18/55, 18/55)], [(17/18, QQ(1)), FastLinearFunction(-126/11, 126/11)]])
sage: lift_extreme_function_for_finite_group_to_infinite_group(h)
[]
cutgeneratingfunctionology.igp.lift_of_minimal_has_uncovered_interval()

This function was obtained by: sage_input(lift(minimal_has_uncovered_interval()))

The function has 3 slopes and discontinuities.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: h = lift_of_minimal_has_uncovered_interval()
sage: len(generate_covered_intervals(h) + generate_uncovered_intervals(h)) >= 2
True
cutgeneratingfunctionology.igp.lift_of_minimal_no_covered_interval()

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: h = lift_of_minimal_no_covered_interval()
sage: extremality_test(h)
False
cutgeneratingfunctionology.igp.lift_on_uncovered_components(fn, show_plots=False, L=[])

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = drlm_not_extreme_1()
sage: hh = lift_on_uncovered_components(h)
sage: len(hh)                     # not tested - wrong doctest
4
sage: h = example7slopecoarse2()
sage: hh = lift_on_uncovered_components(h)   # long time - 240s
sage: len(hh)                     # not tested - wrong doctest
12
sage: bkpts = [0, 1/13, 3/13, 7/26, 4/13,5/13,21/52,23/52,6/13,8/13,33/52,35/52,9/13,10/13,21/26,11/13,1]
sage: values = [0,1,3/14,5/7,3/4,5/14,55/112,33/112,3/7,4/7,79/112,57/112,9/14,1/4,2/7,11/14,0]
sage: h = piecewise_function_from_breakpoints_and_values(bkpts, values)
sage: hh = lift_on_uncovered_components(h)   # long time. 30 mins?
sage: len(hh)                                # not tested - wrong doctest
128
sage: extremality_test(hh[0])     # not tested - wrong doctest
True
cutgeneratingfunctionology.igp.lift_until_extreme(fn, show_plots=False, pause=False, covered_length=True, use_all_perturbations=True, **kwds)
cutgeneratingfunctionology.igp.lift_until_extreme_bug_example()
cutgeneratingfunctionology.igp.lift_until_extreme_default_style_bug_example()
cutgeneratingfunctionology.igp.lift_until_extreme_only_works_with_strict_subset_L()
cutgeneratingfunctionology.igp.limiting_slopes(fn)

Computes the limiting slopes on the right and the left side of the origin.

The function fn is assumed minimal.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN) # Suppress output in automatic tests.
sage: limiting_slopes(gmic(f=4/5))
(5/4, -5)
sage: limiting_slopes(gmic_disjoint_with_singletons(f=4/5))
(5/4, -5)
sage: limiting_slopes(minimal_no_covered_interval())
(+Infinity, -Infinity)
sage: limiting_slopes(drlm_2_slope_limit_1_1())
(2, -Infinity)
sage: limiting_slopes(restrict_to_finite_group(gmic(f=4/5)))
(5/4, -5)
cutgeneratingfunctionology.igp.limits_out_of_range()

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO); 
sage: h = limits_out_of_range()
sage: minimality_test(h, False)
False
cutgeneratingfunctionology.igp.ll_strong_fractional_bad_figure_3()

Corresponds to Figure 3 in Letchford-Lodi (2002); divided by its value at f=2/3 to normalize.

This function is not subadditive, contrary to what is claimed.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = ll_strong_fractional_bad_figure_3()
sage: minimality_test(h, False)
False
cutgeneratingfunctionology.igp.ll_strong_fractional_bad_figure_3_corrected()

Corresponds to what Figure 3 in Letchford-Lodi (2002) should have looked like; divided by its value at f=2/3 to normalize.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = ll_strong_fractional_bad_figure_3_corrected()
sage: extremality_test(h, False)
True
sage: h == ll_strong_fractional()
True
cutgeneratingfunctionology.igp.logger(func)
cutgeneratingfunctionology.igp.lower_triangle_vertices(vertices)

Given the polytope P defined by vertices, return the vertices of the new polytope Q, where Q = P cap {x>=y}, by computing vertices on x=y.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: I=[0,1]
sage: J=[0,1]
sage: K=[0,2]
sage: lower_triangle_vertices(verts(I,J,K))
[(1, 0), (0, 0), (1, 1)]
cutgeneratingfunctionology.igp.lrs_lrs(in_str, verbose=False)

Use the command ‘lrs’ from lrslib. Input: lrs format in_str; Output: lrs format out_str;

cutgeneratingfunctionology.igp.lrs_lrsinput_pploutput(in_str)

Use the command lrs from lrslib.

Input:
lrs format in_str;
Output:
ppl format extreme_points;

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: cube_in_str = "cube\n*cube of side 2 centred at origin\nH-representation\nbegin\n6  4 rational" + "\n1 1 0 0\n1 0 1 0\n1 0 0 1\n1 -1 0 0\n1 0 -1 0\n1 0 0 -1\nend"
sage: lrs_lrsinput_pploutput(cube_in_str)  # optional - lrslib
Generator_System {point(1/1, 1/1, 1/1), point(-1/1, 1/1, 1/1), point(1/1, -1/1, 1/1), point(-1/1, -1/1, 1/1), point(1/1, 1/1, -1/1), point(-1/1, 1/1, -1/1), point(1/1, -1/1, -1/1), point(-1/1, -1/1, -1/1)}
sage: lrs_q5f3_str = "lrs_q5f3\nH-representation\nlinearity 5 1 2 3 13 21\nbegin\n21 7 rational" + "\n0 1 0 0 0 0 0\n0 0 0 0 0 0 1\n-1 0 0 0 1 0 0\n0 0 1 0 0 0 0\n1 0 -1 0 0 0 0\n0 0 0 1 0 0 0\n1 0 0 -1 0 0 0\n0 0 0 0 1 0 0" + "\n1 0 0 0 -1 0 0\n0 0 0 0 0 1 0\n1 0 0 0 0 -1 0\n0 0 2 -1 0 0 0\n0 0 1 1 -1 0 0\n0 0 1 0 1 -1 0\n0 -1 1 0 0 1 0" + "\n0 0 0 2 0 -1 0\n0 -1 0 1 1 0 0\n0 0 -1 1 0 1 0\n0 0 -1 0 2 0 0\n0 0 0 -1 1 1 0\n0 0 0 0 1 -2 0\nend"
sage: lrs_lrsinput_pploutput(lrs_q5f3_str)  # optional - lrslib
Generator_System {point(0/6, 2/6, 4/6, 6/6, 3/6, 0/6), point(0/4, 3/4, 1/4, 4/4, 2/4, 0/4)}    

r

cutgeneratingfunctionology.igp.lrs_redund(in_str, verbose=False)

To remove redundant inequalities from an H-representation or input points that are not vertices from a V-representation use the command ‘redund’ from lrslib.

Input: lrs format in_str; Output: lrs format out_str;

Copy and edit from def _volume_lrs(self, verbose=False), http://www.sagenb.org/src/geometry/polyhedron/base.py

EXAMPLE:

sage: from cutgeneratingfunctionology.igp import *
sage: x = Variable(0)
sage: y = Variable(1)
sage: cs = Constraint_System()
sage: cs.insert(x >= 0)
sage: cs.insert(y >= 0)
sage: cs.insert(x <= 1)
sage: cs.insert(y <= 1)
sage: in_str = convert_pplcs_to_lrs(cs)
sage: out_str = lrs_redund(in_str)      #      optional - lrslib
sage: type(out_str)                     # py3, optional - lrslib
<class 'str'>
cutgeneratingfunctionology.igp.matroids

Catalog of matroids

A module containing constructors for several common matroids.

A list of all matroids in this module is available via tab completion. Let <tab> indicate pressing the tab key. So begin by typing matroids.<tab> to see the various constructions available. Many special matroids can be accessed from the submenu matroids.named_matroids.<tab>.

To create a custom matroid using a variety of inputs, see the function Matroid().

cutgeneratingfunctionology.igp.measure_stats_detail(q, f)

Provides data for scatter plot.

cutgeneratingfunctionology.igp.merge_bkpt(bkpt1, bkpt2)
cutgeneratingfunctionology.igp.merge_components_with_given_component(given_component, other_components)
cutgeneratingfunctionology.igp.merge_components_with_given_component_strategically(given_component, other_components)
cutgeneratingfunctionology.igp.merge_functional_directed_moves(A, B, show_plots=False)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: merge_functional_directed_moves(
....:    FunctionalDirectedMove([(3/10, 7/20), (9/20, 1/2)], (1,0)),
....:    FunctionalDirectedMove([(3/10, 13/40)], (1,0)))
<FunctionalDirectedMove (1, 0) with domain [(3/10, 7/20), (9/20, 1/2)], range [<Int[3/10, 7/20]>, <Int[9/20, 1/2]>]>
cutgeneratingfunctionology.igp.merge_with_key_xeps_delta(*iterables)
cutgeneratingfunctionology.igp.merit_index(fn)

Compute Gomory–Johnson’s merit index.

It is defined as twice the area of additive points in the unit square (see [RD, Definition 19.28], which refers to [61]).

If \(fn\) is a discrete function with finite group order \(q\), then the merit index is defined as twice the number of additive points over \(q^2\).

EXAMPLES:

The merit index for GMIC is \(2f^2 - 2f + 1\) [RD]:

sage: from cutgeneratingfunctionology.igp import *
sage: def merit_index_gmic(f):
....:     return 2*f^2 - 2*f + 1
sage: merit_index(gmic(1/4)) == merit_index_gmic(1/4)
True
sage: merit_index(gmic(1/2)) == merit_index_gmic(1/2)
True

The merit index for drlm_2_slope_limit_1_1 is \(4 f^2 - 6 f + 3\) [40, p. 164]:

sage: def merit_index_drlm_2_slope_limit_1_1(f):
....:     return 4 * f^2 - 6 * f + 3
sage: merit_index(drlm_2_slope_limit_1_1(3/5)) == merit_index_drlm_2_slope_limit_1_1(3/5)
True
sage: merit_index(drlm_2_slope_limit_1_1(1/2)) == merit_index_drlm_2_slope_limit_1_1(1/2)
True

Reference:

  • [40] S. S. Dey, J.-P. P. Richard, Y. Li, and L. A. Miller, Extreme inequalities for infinite group problems, Mathematical Programming 121 (2010), 145-170.
  • [61] R. E. Gomory and E. L. Johnson, T-space and cutting planes, Mathematical Programming 96 (2003), 341-375.
  • [RD] J.-P. P. Richard and S. S. Dey, The group-theoretic approach in mixed integer programming, 50 Years of Integer Programming 1958-2008 (M. Juenger, T. M. Liebling, D. Naddef, G. L. Nemhauser, W. R. Pulleyblank, G. Reinelt, G. Rinaldi, and L. A. Wolsey, eds.), Springer Berlin Heidelberg, 2010, pp. 727-801, doi:10.1007/978-3-540-68279-0_19, ISBN 978-3-540-68274-5.
cutgeneratingfunctionology.igp.minimal_has_uncovered_breakpoints()

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = minimal_has_uncovered_breakpoints()
sage: finite_dimensional_extremality_test(h,show_all_perturbations = True)
False
sage: len(h._perturbations)
3
cutgeneratingfunctionology.igp.minimal_has_uncovered_interval()

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: h = minimal_has_uncovered_interval()
sage: extremality_test(h, False)
False
sage: simple_finite_dimensional_extremality_test(h, oversampling=4)
False
cutgeneratingfunctionology.igp.minimal_no_covered_interval()

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN) 
sage: h = minimal_no_covered_interval()
sage: extremality_test(h, False)
False
cutgeneratingfunctionology.igp.minimality_test(fn, show_plots=False, f=None, full_certificates=True)

Checks if fn is minimal with respect to the group relaxation with the given \(f\).

Assume that \(0 \leq fn \leq 1\). This function calls subadditivity_test and symmetric_test.

If \(f\) is not provided, use the one found by find_f.

If show_plots is True (default: False), show an illustrating diagram.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: minimality_test(piecewise_function_from_breakpoints_and_values([0,1/5,4/5,1],[0,1/2,1,0]))
False
sage: minimality_test(piecewise_function_from_breakpoints_and_values([0,1/2,1], [0,2,0]))
False
cutgeneratingfunctionology.igp.minimality_test_randomized(fn, orig_function=None, testpoint_function=None, extra_cosets=[], max_iterations=None, limits=True, lost_additivity_is_error=False)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = kzh_minimal_has_only_crazy_perturbation_1()
sage: bkpts = h.end_points()
sage: t1 = bkpts[10]-bkpts[6]
sage: t2 = bkpts[13]-bkpts[6]
sage: f = bkpts[37]
sage: ucl = bkpts[17]
sage: ucr = bkpts[18]
sage: generators = [t1, t2]
sage: pwl = piecewise_function_from_breakpoints_and_slopes([0,1],[0])
sage: crazy_piece_1 = CrazyPiece((ucl, ucr), generators, [(ucl, 1), (ucr, -1)])
sage: crazy_piece_2 = CrazyPiece((f-ucr, f-ucl), generators, [(f-ucr, 1), (f-ucl, -1)])
sage: cp = PiecewiseCrazyFunction(pwl, [crazy_piece_1, crazy_piece_2])
sage: eps = find_epsilon_for_crazy_perturbation(h, cp)
sage: hcp = PiecewiseCrazyFunction(h+eps*pwl, [eps*crazy_piece_1, eps*crazy_piece_2]) # In fact, hcp = h + eps * cp, but it fails in doctest.
sage: minimality_test_randomized(hcp, h, max_iterations=10)
True
cutgeneratingfunctionology.igp.mkdir_p(path)
cutgeneratingfunctionology.igp.mlr_cpl3_a_2_slope(r0=3/13, z1=3/26, field=None, conditioncheck=True)
_images/igp-66.svg
Summary:
  • The group representation of the continuous piecewise linear lifting (CPL) function.
  • Infinity; Dim = 1; Slopes = 2 ; Continuous.
  • Discovered [1] p.179, Table 3, Ext. pnt a.
  • Proven extreme p.188, thm.19.
Parameters:
  • 0 < r0 (real) < 1,
  • 0 < z1 (real) <= (1-r0)/4
Function is known to be extreme under the conditions:
  • 0 < r0 < 1,
  • 0 <= z1 < 1
Note:
Parameter z1 is not actually used. Same as gmic(f=r0).
Examples:

page 183, Fig 2, point a:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # Suppress output in automatic tests.
sage: h = mlr_cpl3_a_2_slope(r0=3/13, z1=3/26)
sage: extremality_test(h)
True
sage: phi = cpl3_function(r0=3/13, z1=3/26, o1=3/20, o2=3/20)
sage: fn = group_function_from_superadditive_lifting_function(phi)
sage: h == fn
True
sage: h == gmic(f=3/13)
True
Reference:
  • [1] L. A. Miller, Y. Li, and J.-P. P. Richard, New Inequalities for Finite and Infinite Group Problems from Approximate Lifting, Naval Research Logistics 55 (2008), no.2, 172-191, doi:10.1002/nav.20275
cutgeneratingfunctionology.igp.mlr_cpl3_b_3_slope(r0=3/26, z1=1/13, field=None, conditioncheck=True)
_images/igp-67.svg
Summary:
  • The group representation of the continuous piecewise linear lifting (CPL) function.
  • Infinity; Dim = 1; Slopes = 3 ; Continuous.
  • Discovered [1] p.179, Table 3, Ext. pnt b.
  • Proven extreme p.188, thm.19.
Parameters:
  • 0 < r0 (real) < 1,
  • 0 < z1 (real) <= (1-r0)/4.
Function is known to be extreme under the conditions:
  • 3*r0 + 8*z1 <= 1
Note:
  • When z1 = (1-r0)/4, the function is the same as gmic(f=r0).
  • mlr_cpl3_b_3_slope(r0,z1) is the same as drlm_backward_3_slope(f=r0,bkpt=r0+2*z1).
Examples:

page 183, Fig 2, point b:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # Suppress output in automatic tests.
sage: h1 = mlr_cpl3_b_3_slope(r0=3/26, z1=1/13)
sage: extremality_test(h1)
True
sage: phi = cpl3_function(r0=3/26, z1=1/13, o1=7/58, o2=7/58)
sage: fn = group_function_from_superadditive_lifting_function(phi)
sage: h1 == fn
True
sage: h2 = drlm_backward_3_slope(f=3/26,bkpt=7/26)
sage: extremality_test(h2)
True
sage: h1 == h2
True
sage: h3 = mlr_cpl3_b_3_slope(r0=3/26, z1=23/104, conditioncheck=False)
sage: h3 == gmic(f=3/26)
True
Reference:
  • [1] L. A. Miller, Y. Li, and J.-P. P. Richard, New Inequalities for Finite and Infinite Group Problems from Approximate Lifting, Naval Research Logistics 55 (2008), no.2, 172-191, doi:10.1002/nav.20275
cutgeneratingfunctionology.igp.mlr_cpl3_c_3_slope(r0=5/24, z1=1/12, field=None, conditioncheck=True)
_images/igp-68.svg
Summary:
  • The group representation of the continuous piecewise linear lifting (CPL) function.
  • Infinity; Dim = 1; Slopes = 3 ; Continuous.
  • Discovered [1] p.179, Table 3, Ext. pnt c.
  • Proven extreme p.188, thm.19.
Parameters:
  • 0 < r0 (real) < 1,
  • 0 < z1 (real) <= (1-r0)/4
Function is known to be extreme under the conditions:
  • 3*r0 + 4*z1 <= 1
Note:
  • mlr_cpl3_c_3_slope(r0,z1) is the same as drlm_backward_3_slope(f=r0,bkpt=r0+z1).
Examples:

page 183, Fig 2, point c:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # Suppress output in automatic tests.
sage: h1 = mlr_cpl3_c_3_slope(r0=5/24, z1=1/12)
sage: extremality_test(h1)
True
sage: phi = cpl3_function(r0=5/24, z1=1/12, o1=7/29, o2=2/29)
sage: fn = group_function_from_superadditive_lifting_function(phi)
sage: h1 == fn
True
sage: h2 = drlm_backward_3_slope(f=5/24,bkpt=7/24)
sage: extremality_test(h2)
True
sage: h1 == h2
True
Reference:
  • [1] L. A. Miller, Y. Li, and J.-P. P. Richard, New Inequalities for Finite and Infinite Group Problems from Approximate Lifting, Naval Research Logistics 55 (2008), no.2, 172-191, doi:10.1002/nav.20275
cutgeneratingfunctionology.igp.mlr_cpl3_d_3_slope(r0=1/6, z1=None, field=None, conditioncheck=True)
_images/igp-69.svg
Summary:
  • The group representation of the continuous piecewise linear lifting (CPL) function.
  • Infinity; Dim = 1; Slopes = 3 ; Continuous.
  • Discovered [1] p.179, Table 3, Ext. pnt d.
  • Proven extreme p.188, thm.19.
Parameters:
  • 0 < r0 (real) < 1,
  • 0 < z1 (real) <= (1-r0)/4
Function is known to be extreme under the conditions:
  • r0 = 2*z1,
  • r0 + 8*z1 <= 1
Note:
  • multiplicative_homomorphism(mlr_cpl3_d_3_slope(r0, z1=2*r0), -1) is the same as gj_forward_3_slope(f=1-r0, lambda_1=2*z1/(1-r0), lambda_2=z1/r0);
  • gj_forward_3_slope being extreme only requires: r0 >= z1, r0 + 4*z1 <= 1.
Examples:

p.183, Fig 2, point d1:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # Suppress output in automatic tests.
sage: h1 = mlr_cpl3_d_3_slope(r0=1/6, z1=1/12)
sage: extremality_test(h1)
True
sage: phi = cpl3_function(r0=1/6, z1=1/12, o1=1/5, o2=0) 
sage: fn1 = group_function_from_superadditive_lifting_function(phi)
sage: h1 == fn1
True
sage: h2 = mlr_cpl3_d_3_slope(r0=1/6, z1=5/24, conditioncheck=False)
sage: extremality_test(h2)
False
sage: phi = cpl3_function(r0=1/6, z1=5/24, o1=7/20, o2=3/20)
sage: fn2 = group_function_from_superadditive_lifting_function(phi)
sage: h2 == fn2
True
Reference:
  • [1] L. A. Miller, Y. Li, and J.-P. P. Richard, New Inequalities for Finite and Infinite Group Problems from Approximate Lifting, Naval Research Logistics 55 (2008), no.2, 172-191, doi:10.1002/nav.20275
cutgeneratingfunctionology.igp.mlr_cpl3_f_2_or_3_slope(r0=1/6, z1=None, field=None, conditioncheck=True)
_images/igp-70.svg
Summary:
  • The group representation of the continuous piecewise linear lifting (CPL) function.
  • Infinity; Dim = 1; Slopes = 2 or 3; Continuous.
  • Discovered [1] p.179, Table 3, Ext. pnt f.
  • Proven extreme p.188, thm.19.
Parameters:
  • 0 < r0 (real) < 1,
  • 0 < z1 (real) <= (1-r0)/4
Function is known to be extreme under the conditions:
  • r0 <= z1,
  • r0 + 5*z1 = 1
Note:
When z1 = (1-r0)/4, the function is the same as gmic(f=r0).
Examples:

page 184, Fig 3, point f1 and f2:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # Suppress output in automatic tests.
sage: h1 = mlr_cpl3_f_2_or_3_slope(r0=1/6, z1=1/6)
sage: extremality_test(h1, f=1/6)
True
sage: phi = cpl3_function(r0=1/6, z1=1/6, o1=1/3, o2=0) 
sage: fn = group_function_from_superadditive_lifting_function(phi, f=1/6)
sage: h1 == fn
True
sage: h2 = mlr_cpl3_f_2_or_3_slope(r0=3/23, z1=4/23)
sage: extremality_test(h2)
True
sage: h3 = mlr_cpl3_f_2_or_3_slope(r0=3/23, z1=5/23, conditioncheck=False)
sage: h3 == gmic(f=3/23)
True
Reference:
  • [1] L. A. Miller, Y. Li, and J.-P. P. Richard, New Inequalities for Finite and Infinite Group Problems from Approximate Lifting, Naval Research Logistics 55 (2008), no.2, 172-191, doi:10.1002/nav.20275
cutgeneratingfunctionology.igp.mlr_cpl3_g_3_slope(r0=1/12, z1=None, field=None, conditioncheck=True)
_images/igp-71.svg
Summary:
  • The group representation of the continuous piecewise linear lifting (CPL) function.
  • Infinity; Dim = 1; Slopes = 3 ; Continuous.
  • Discovered [1] p.179, Table 3, Ext. pnt g.
  • Proven extreme p.188, thm.19.
Parameters:
  • 0 < r0 (real) < 1,
  • 0 < z1 (real) <= (1-r0)/4
Function is known to be extreme under the conditions:
  • r0 < z1,
  • 2*r0 + 4*z1 = 1
Examples:

page 184, Fig 3, point g:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # Suppress output in automatic tests.
sage: h1 = mlr_cpl3_g_3_slope(r0=1/12, z1=5/24)
sage: extremality_test(h1)
True
sage: phi = cpl3_function(r0=1/12, z1=5/24, o1=5/18, o2=1/6)
sage: fn1 = group_function_from_superadditive_lifting_function(phi)
sage: h1 == fn1
True
sage: h2 = mlr_cpl3_g_3_slope(r0=1/12, z1=11/48, conditioncheck=False)
sage: extremality_test(h2)
False
sage: phi = cpl3_function(r0=1/12, z1=11/48, o1=11/36, o2=7/36)
sage: fn2 = group_function_from_superadditive_lifting_function(phi)
sage: h2 == fn2
True
Reference:
  • [1] L. A. Miller, Y. Li, and J.-P. P. Richard, New Inequalities for Finite and Infinite Group Problems from Approximate Lifting, Naval Research Logistics 55 (2008), no.2, 172-191, doi:10.1002/nav.20275
cutgeneratingfunctionology.igp.mlr_cpl3_h_2_slope(r0=1/4, z1=1/6, field=None, conditioncheck=True)
_images/igp-72.svg
Summary:
  • The group representation of the continuous piecewise linear lifting (CPL) function.
  • Infinity; Dim = 1; Slopes = 2 ; Continuous.
  • Discovered [1] p.179, Table 3, Ext. pnt h.
  • Proven extreme p.188, thm.19.
Parameters:
  • 0 < r0 (real) < 1,
  • 0 < z1 (real) <= (1-r0)/4
Function is known to be extreme under the conditions:
  • r0 + 4*z1 <= 1 < 2*r0 + 4*z1
Note:
When z1 = (1-r0)/4, the function is the same as gmic(f=r0).
Examples:

page 183, Fig 2, point h:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # Suppress output in automatic tests.
sage: h1 = mlr_cpl3_h_2_slope(r0=1/4, z1=1/6)
sage: extremality_test(h1)
True
sage: phi = cpl3_function(r0=1/4, z1=1/6, o1=1/4, o2=1/4) 
sage: fn = group_function_from_superadditive_lifting_function(phi)
sage: h1 == fn
True
sage: h2 = mlr_cpl3_h_2_slope(r0=1/4, z1=3/16)
sage: h2 == gmic(f=1/4)
True
Reference:
  • [1] L. A. Miller, Y. Li, and J.-P. P. Richard, New Inequalities for Finite and Infinite Group Problems from Approximate Lifting, Naval Research Logistics 55 (2008), no.2, 172-191, doi:10.1002/nav.20275
cutgeneratingfunctionology.igp.mlr_cpl3_k_2_slope(r0=7/27, z1=4/27, field=None, conditioncheck=True)
_images/igp-73.svg
Summary:
  • The group representation of the continuous piecewise linear lifting (CPL) function.
  • Infinity; Dim = 1; Slopes = 2 ; Continuous.
  • Discovered [1] p.179, Table 3, Ext. pnt k.
  • Proven extreme p.188, thm.19.
Parameters:
  • 0 < r0 (real) < 1,
  • 0 < z1 (real) <= (1-r0)/4
Function is known to be extreme under the conditions:
  • r0 <= 2*z1,
  • r0 + 5*z1 = 1
Examples:

page 185, Fig 4, point k1:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # Suppress output in automatic tests.
sage: h = mlr_cpl3_k_2_slope(r0=7/27, z1=4/27)
sage: extremality_test(h)
True
sage: phi = cpl3_function(r0=7/27, z1=4/27, o1=1/3, o2=0) 
sage: fn = group_function_from_superadditive_lifting_function(phi)
sage: h == fn
True
Reference:
  • [1] L. A. Miller, Y. Li, and J.-P. P. Richard, New Inequalities for Finite and Infinite Group Problems from Approximate Lifting, Naval Research Logistics 55 (2008), no.2, 172-191, doi:10.1002/nav.20275
cutgeneratingfunctionology.igp.mlr_cpl3_l_2_slope(r0=8/25, z1=None, field=None, conditioncheck=True)
_images/igp-74.svg
Summary:
  • The group representation of the continuous piecewise linear lifting (CPL) function.
  • Infinity; Dim = 1; Slopes = 2 ; Continuous.
  • Discovered [1] p.179, Table 3, Ext. pnt l.
  • Proven extreme p.188, thm.19.
Parameters:
  • 0 < r0 (real) < 1,
  • 0 < z1 (real) <= (1-r0)/4
Function is known to be extreme under the conditions:
  • r0 = 2*z1,
  • 6*z1 <= 1 < 7*z1
Note:
There is a typo in one of the given slopes [1] p.179, Table 3, Ext. pnt l, s3. The given slope is -4*z1/(2*z1-4*z1*r0) while the correct slope is (1-4*z1)/(2*z1-4*z1*r0).
Examples:

page 185, Fig 4, point l:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # Suppress output in automatic tests.
sage: h1 = mlr_cpl3_l_2_slope(r0=8/25, z1=4/25)
sage: extremality_test(h1)
True 
sage: phi = cpl3_function(8/25,4/25,4/9,0)
sage: fn1 = group_function_from_superadditive_lifting_function(phi)
sage: h1 == fn1
True
sage: h2 = mlr_cpl3_l_2_slope(r0=8/25, z1=17/100, conditioncheck=False)
sage: extremality_test(h2)
False
sage: phi = cpl3_function(r0=8/25, z1=17/100, o1=17/36, o2=1/36)
sage: fn2 = group_function_from_superadditive_lifting_function(phi)
sage: h2 == fn2
True
Reference:
  • [1] L. A. Miller, Y. Li, and J.-P. P. Richard, New Inequalities for Finite and Infinite Group Problems from Approximate Lifting, Naval Research Logistics 55 (2008), no.2, 172-191, doi:10.1002/nav.20275
cutgeneratingfunctionology.igp.mlr_cpl3_n_3_slope(r0=9/25, z1=2/25, field=None, conditioncheck=True)
_images/igp-75.svg
Summary:
  • The group representation of the continuous piecewise linear lifting (CPL) function.
  • Infinity; Dim = 1; Slopes = 3 ; Continuous.
  • Discovered [1] p.179, Table 3, Ext. pnt n.
  • Proven extreme p.188, thm.19.
Parameters:
  • 0 < r0 (real) < 1,
  • 0 < z1 (real) <= (1-r0)/4
Function is known to be extreme under the conditions:
  • r0 > 2*z1,
  • r0 + 8*z1 <= 1
Note:
  • multiplicative_homomorphism( mlr_cpl3_n_3_slope(r0, z1), -1) == gj_forward_3_slope(f=1-r0, lambda_1=4*z1/(1-r0), lambda_2=2*z1/r0);
  • gj_forward_3_slope being extreme only requires: r0 >= z1, r0 + 4*z1 <= 1.
Examples:

page 185, Fig 4, point n2:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # Suppress output in automatic tests.
sage: h1 = mlr_cpl3_n_3_slope(r0=9/25, z1=2/25)
sage: extremality_test(h1)
True
sage: phi = cpl3_function(r0=9/25, z1=2/25, o1=1/4, o2=0) 
sage: fn1 = group_function_from_superadditive_lifting_function(phi)
sage: h1 == fn1
True
sage: h2 = mlr_cpl3_n_3_slope(r0=9/25, z1=4/25, conditioncheck=False)
sage: extremality_test(h2)
True
sage: phi = cpl3_function(r0=9/25, z1=4/25, o1=1/2, o2=0)
sage: fn2 = group_function_from_superadditive_lifting_function(phi)
sage: h2 == fn2
True
Reference:
  • [1] L. A. Miller, Y. Li, and J.-P. P. Richard, New Inequalities for Finite and Infinite Group Problems from Approximate Lifting, Naval Research Logistics 55 (2008), no.2, 172-191, doi:10.1002/nav.20275
cutgeneratingfunctionology.igp.mlr_cpl3_o_2_slope(r0=3/8, z1=None, field=None, conditioncheck=True)
_images/igp-76.svg
Summary:
  • The group representation of the continuous piecewise linear lifting (CPL) function.
  • Infinity; Dim = 1; Slopes = 2 ; Continuous.
  • Discovered [1] p.179, Table 3, Ext. pnt o.
  • Proven extreme p.188, thm.19.
Parameters:
  • 0 < r0 (real) < 1,
  • 0 < z1 (real) <= (1-r0)/4
Function is known to be extreme under the conditions:
  • r0 >= 2*z1,
  • 2*r0 + 2*z1 = 1
Examples:

page 186, Fig 5, point o:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # Suppress output in automatic tests.
sage: h1 = mlr_cpl3_o_2_slope(r0=3/8, z1=1/8)
sage: extremality_test(h1, f=3/8)
True
sage: phi = cpl3_function(r0=3/8, z1=1/8, o1=1/2, o2=0) 
sage: fn1 = group_function_from_superadditive_lifting_function(phi)
sage: h1 == fn1
True
sage: h2 = mlr_cpl3_o_2_slope(r0=2/8, z1=3/16,conditioncheck=False)
sage: extremality_test(h2)
False
sage: phi = cpl3_function(r0=2/8, z1=3/16, o1=3/8, o2=1/8)
sage: fn2 = group_function_from_superadditive_lifting_function(phi)
sage: h2 == fn2
True
Reference:
  • [1] L. A. Miller, Y. Li, and J.-P. P. Richard, New Inequalities for Finite and Infinite Group Problems from Approximate Lifting, Naval Research Logistics 55 (2008), no.2, 172-191, doi:10.1002/nav.20275
cutgeneratingfunctionology.igp.mlr_cpl3_p_2_slope(r0=5/12, z1=None, field=None, conditioncheck=True)
_images/igp-77.svg
Summary:
  • The group representation of the continuous piecewise linear lifting (CPL) function.
  • Infinity; Dim = 1; Slopes = 2 ; Continuous.
  • Discovered [1] p.179, Table 3, Ext. pnt p.
  • Proven extreme p.188, thm.19.
Parameters:
  • 0 < r0 (real) < 1,
  • 0 < z1 (real) <= (1-r0)/4
Function is known to be extreme under the conditions:
  • r0 > 2*z1,
  • 2*r0 + 2*z1 = 1
Note:
There is a typo in one of the given slopes [1] p.179, Table 3, Ext. pnt p, s4. The given slope is (2*z1-10*z1*r0+r0)/(r0*(1-2*r0)*(4*z1-1+r0)) while the correct slope is (-r0+2*r0^2-2*z1+8*z1*r0)/(r0*(1-2*r0)*(1-r0-4*z1)).
Examples:

page 186, Fig 5, point p1 and p2:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # Suppress output in automatic tests.
sage: h1 = mlr_cpl3_p_2_slope(r0=5/12, z1=1/12)
sage: extremality_test(h1, f=5/12)
True
sage: phi = cpl3_function(r0=5/12, z1=1/12, o1=1/2, o2=0)
sage: fn = group_function_from_superadditive_lifting_function(phi)
sage: h1 == fn
True
sage: h2 = mlr_cpl3_p_2_slope(r0=7/21, z1=1/6, conditioncheck=False)
sage: extremality_test(h2, f=1/3)
True
sage: phi = cpl3_function(r0=7/21, z1=1/6, o1=1/2, o2=0)
sage: fn2 = group_function_from_superadditive_lifting_function(phi)
sage: h2 == fn2
True
Reference:
  • [1] L. A. Miller, Y. Li, and J.-P. P. Richard, New Inequalities for Finite and Infinite Group Problems from Approximate Lifting, Naval Research Logistics 55 (2008), no.2, 172-191, doi:10.1002/nav.20275
cutgeneratingfunctionology.igp.mlr_cpl3_q_2_slope(r0=5/12, z1=1/8, field=None, conditioncheck=True)
_images/igp-78.svg
Summary:
  • The group representation of the continuous piecewise linear lifting (CPL) function.
  • Infinity; Dim = 1; Slopes = 2 ; Continuous.
  • Discovered [1] p.179, Table 3, Ext. pnt q.
  • Proven extreme p.188, thm.19.
Parameters:
  • 0 < r0 (real) < 1,
  • 0 < z1 (real) <= (1-r0)/4
Function is known to be extreme under the conditions:
  • r0 > 2*z1,
  • r0+4*z1 <= 1 < r0+5*z1
Examples:

page 186, Fig 5, point q:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # Suppress output in automatic tests.
sage: h1 = mlr_cpl3_q_2_slope(r0=5/12, z1=3/24)
sage: extremality_test(h1)
True
sage: phi = cpl3_function(r0=5/12, z1=3/24, o1=3/8, o2=0) 
sage: fn1 = group_function_from_superadditive_lifting_function(phi)
sage: h1 == fn1
True
sage: h2 = mlr_cpl3_q_2_slope(r0=5/12, z1=7/48,conditioncheck=False)
sage: extremality_test(h2)
True
sage: phi = cpl3_function(r0=5/12, z1=7/48, o1=1/2, o2=0)
sage: fn2 = group_function_from_superadditive_lifting_function(phi)
sage: h2 == fn2
True
Reference:
  • [1] L. A. Miller, Y. Li, and J.-P. P. Richard, New Inequalities for Finite and Infinite Group Problems from Approximate Lifting, Naval Research Logistics 55 (2008), no.2, 172-191, doi:10.1002/nav.20275
cutgeneratingfunctionology.igp.mlr_cpl3_r_2_slope(r0=3/7, z1=1/7, field=None, conditioncheck=True)
_images/igp-79.svg
Summary:
  • The group representation of the continuous piecewise linear lifting (CPL) function.
  • Infinity; Dim = 1; Slopes = 2 ; Continuous.
  • Discovered [1] p.179, Table 3, Ext. pnt r.
  • Proven extreme p.188, thm.19.
Parameters:
  • 0 < r0 (real) < 1,
  • 0 < z1 (real) <= (1-r0)/4
Function is known to be extreme under the conditions:
  • r0 > 2*z1,
  • r0+4*z1 <= 1 <= 2*r0+2*z1
Examples:

page 185, Fig , point r:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # Suppress output in automatic tests.
sage: h = mlr_cpl3_r_2_slope(r0=3/7, z1=1/7)
sage: extremality_test(h)
True 
sage: phi = cpl3_function(r0=3/7, z1=1/7, o1=1/2, o2=0) 
sage: fn = group_function_from_superadditive_lifting_function(phi)
sage: h == fn
True
Reference:
  • [1] L. A. Miller, Y. Li, and J.-P. P. Richard, New Inequalities for Finite and Infinite Group Problems from Approximate Lifting, Naval Research Logistics 55 (2008), no.2, 172-191, doi:10.1002/nav.20275
cutgeneratingfunctionology.igp.modified_delta_pi(fn, fn_values, pts, i, j)
cutgeneratingfunctionology.igp.modified_delta_pi2(fn, fn_values2, pts, i, j)
cutgeneratingfunctionology.igp.move_variable(q, x, z)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: move_variable(7, 1/7, 3/7)
'm_1_3'
cutgeneratingfunctionology.igp.multiplication_names

tuple() -> empty tuple tuple(iterable) -> tuple initialized from iterable’s items

If the argument is a tuple, the return value is the same object.

cutgeneratingfunctionology.igp.multiplicative_homomorphism(function, multiplier)
_images/igp-80.svg

Construct the function x -> function(multiplier * x).

multiplier must be a nonzero integer.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # Suppress output in automatic tests.
sage: h = multiplicative_homomorphism(gmic(f=4/5), 3)
sage: extremality_test(h, False, f=4/15) # Provide f to suppress warning
True
sage: h = multiplicative_homomorphism(gmic(f=4/5), -2)
sage: extremality_test(h, False, f=3/5)
True
cutgeneratingfunctionology.igp.nice_field_values(symb_values, field=None)

Coerce the real numbers in the list symb_values into a convenient common field and return a list, parallel to symb_values, of the coerced values.

If \(field\) is \(False\), the given numbers are returned as is.

If all given numbers are rational, the field will be the rational field (QQ).

Otherwise, if the numbers are algebraic, the field will be a suitable algebraic field extension of the rational numbers, embedded into the real numbers, in the form of a RealNumberField.

Otherwise, the given numbers are returned as is.

cutgeneratingfunctionology.igp.no_labels_ticks_keywords(function, y_ticks_for_breakpoints=False)
cutgeneratingfunctionology.igp.not_extreme_1()

A non-extreme, minimal function.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = not_extreme_1()
sage: minimality_test(h, False)
True
sage: extremality_test(h, False)
False
cutgeneratingfunctionology.igp.not_minimal_1()

A non-minimal function.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = not_minimal_1()
sage: minimality_test(h, False)
False
cutgeneratingfunctionology.igp.not_minimal_2()

A non-minimal function.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = not_minimal_2()
sage: minimality_test(h, False)
False
cutgeneratingfunctionology.igp.not_minimal_3()

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO); 
sage: h = not_minimal_3()
sage: minimality_test(h, False)
False
cutgeneratingfunctionology.igp.not_minimal_wrong_range()

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO); 
sage: h = not_minimal_wrong_range()
sage: minimality_test(h, False)
False
cutgeneratingfunctionology.igp.num_slopes_at_best(q, f, covered_intervals, uncovered_intervals=None)

Returns an upper bound on the final number of slopes, given current covered_intervals (and optionally, uncovered_intervals that provides connected components of non-covered intervals).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: covered_intervals = [set([0,2])]
sage: uncovered_intervals = [set([1]), set([3,4])]
sage: num_slopes_at_best(5, 3, covered_intervals)
3
sage: num_slopes_at_best(5, 3, covered_intervals, uncovered_intervals)
3
cutgeneratingfunctionology.igp.number_of_components(fn)

Returns the number of connected covered components of fn.

This is an upper bound on number_of_slopes.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: number_of_components(gmic())
2
sage: number_of_components(gomory_fractional())
1
sage: number_of_slopes(not_extreme_1())
3
sage: number_of_components(not_extreme_1())
4
cutgeneratingfunctionology.igp.number_of_projections_intersecting(F, real_set)

This is the number \(n_F\) from facets-paper.

cutgeneratingfunctionology.igp.number_of_slopes(fn)

Returns the number of different slopes of fn.

If fn is discrete, this is defined as the number of different slopes of its piecewise linear continuous interpolation.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: number_of_slopes(gmic())
2
sage: number_of_slopes(gomory_fractional())
1
sage: number_of_slopes(automorphism(restrict_to_finite_group(gmic(10/11)), 3))
2

For non-piecewise linear functions, this raises an exception:

sage: number_of_slopes(california_ip())
Traceback (most recent call last):
...
ValueError: Nonlinear piece in function
sage: number_of_slopes(bccz_counterexample())
Traceback (most recent call last):
...
AttributeError: ... has no attribute 'is_discrete'
sage: number_of_slopes(bcds_discontinuous_everywhere())
Traceback (most recent call last):
...
AttributeError: ... has no attribute 'is_discrete'
sage: number_of_slopes(kzh_minimal_has_only_crazy_perturbation_1_perturbation())
Traceback (most recent call last):
...
AttributeError: ... has no attribute 'is_discrete'
cutgeneratingfunctionology.igp.only_f_ticks_keywords(function, y_ticks_for_breakpoints=False)
cutgeneratingfunctionology.igp.open_piece(p, q)
cutgeneratingfunctionology.igp.paint_complex_combined_mip(k_slopes, q, f, vertices_color, faces_color, last_covered_intervals, candidate_faces, cs_matrix, sym=False)

Combine ‘heuristic’ backracting search (using MILP library) with vertex enumeration. If q - rank(cs_matrix) <= dim_threshold, stop backtracking search. Enumerate and check vertex functions then.

Similar to paint_complex_combined_pol(). Tests show that paint_complex_combined_mip() is faster if q >= q_threshold = 20.

cutgeneratingfunctionology.igp.paint_complex_combined_pol(k_slopes, q, f, vertices_color, faces_color, last_covered_intervals, candidate_faces, cs, cs_matrix)

Combine ‘heuristic’ backtracking search (using PPL) with vertex enumeration. If q - rank(cs_matrix) <= dim_threshold, stop backtracking search. Enumerate and check vertex functions then.

Similar to paint_complex_combined_mip(). Tests show that paint_complex_combined_pol() is faster if q < q_threshold = 20.

cutgeneratingfunctionology.igp.paint_complex_heuristic(k_slopes, q, f, vertices_color, faces_color, last_covered_intervals, candidate_faces, cs)

Paint triangles green in a 2d-complex, until all intervals are covered.

Return the polytope which defines the feasible region of \((\pi(0), \pi(1/q),\dots,\pi(1))\) for that paint_complex_heuristic

Heuristic:
  • I, J projections of the next face to paint are chosen from currently uncovered intervals.
  • Stop painting immediately once everything is covered.
  • Edges are not considered.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: q = 5; f = 3; k_slopes = 2;
sage: vertices_color = initial_vertices_color(q, f);
sage: faces_color, covered_intervals = initial_faces_color_and_covered_intervals(q, f, vertices_color)
sage: cs = initial_cs(q, f, vertices_color)
sage: candidate_faces = generate_candidate_faces(q, f, covered_intervals)
sage: for result_polytope in paint_complex_heuristic(k_slopes, q, f, vertices_color, faces_color, covered_intervals, candidate_faces, cs):
....:     result_polytope.minimized_generators()
Generator_System {point(0/6, 2/6, 4/6, 6/6, 3/6, 0/6)}
Generator_System {point(0/4, 3/4, 1/4, 4/4, 2/4, 0/4)}
cutgeneratingfunctionology.igp.painted_faces_and_funciton_from_solution(filename, q)

Read the solution file, return colored faces and the function fn (inexact floating point).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: faces, fn = painted_faces_and_funciton_from_solution('solution_2q_example_m4.sol', 37)    # not tested
cutgeneratingfunctionology.igp.param_dict_for_piecewise(h, bkpt_names_dict=None, slope_names_dict={}, extra_names=[], extra_values=[], name_sort_key=None, base_ring=None)
cutgeneratingfunctionology.igp.param_piecewise(h, param_dict=None, bkpt_names_dict=None, slope_names_dict={}, field=None, **param_dict_kwargs)

Replace the piecewise function h by one that renames all breakpoints, and optionally slopes, symbolically. Useful for latexing or plotting functions that do not have convenient parametric descriptions.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)                   # disable output for automatic tests
sage: h = gmic()
sage: hp, K = param_piecewise(h, slope_names_dict={h.functions()[0]._slope: 'c1'})
sage: hp.which_pair(1/10)
((0, (x1)~), <FastLinearFunction ((c1)~)*x + (0)>)
cutgeneratingfunctionology.igp.partition_overlapping_components(given_component, components)
cutgeneratingfunctionology.igp.pattern0_sym_fn(l, sv)
cutgeneratingfunctionology.igp.pattern_additive_vertices(l, pattern)

Return a list of pairs (i, j) of integers i <= j such that (i, j)/q is a prescribed additivity.

These additivities form the additive triangles.

pattern == 0 corresponds to the pattern described in the paper. Remaining patterns are undocumented. In the paper, r is what is called l here.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: additive_vertices = pattern_additive_vertices(1, pattern=0)
sage: len(additive_vertices)
31
cutgeneratingfunctionology.igp.pattern_backtrack_polytope(l, k_slopes)

(MAIN FUNCTION) Look for >= k_slopes vertex-functoins on prescribed painting according to pattern=0 and size parameter \(l\).

Backtrack to find some green points such that they do not create new green edge. Start the vertex-enumeration when exp_dim of the polytope is at most vertex_enumeration_dim_threshold.

Output the >= k_slopes vertex-functions (write to file), and max_num_slopes.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: import cutgeneratingfunctionology.igp as igp
sage: vertex_enumeration_dim_threshold = 1
sage: pattern_backtrack_polytope(1, 6) # long time
#####  ...
6
sage: pattern_backtrack_polytope(1, 8) # long time
cutgeneratingfunctionology.igp.pattern_branch_on_deltafn(positive_deltafn, zero_deltafn, undecided_deltafn, vertices_color, exp_dim)

Backtracking subroutine of pattern_backtrack_polytope().

cutgeneratingfunctionology.igp.pattern_extreme(l, k_slopes, pattern=0, show_plots=False, test_extremality=False, polytope=None, exp_dim=None, more_ini_additive=True, count_components=False, use_sha1=True)

Computes the functions (with >= k_slopes slopes) corresponding to the extreme points of the polytope.

If polytope is None, set up a polytope corresponding to subadditivities and prescribed additivities, according to pattern and size parameter \(l\) (called \(r\) in the paper).

If test_extremality is True (default is False), check extremality.

Prints lines: NUM-SLOPES SV (input to pattern0_sym_fn) DENOMINATOR

Creates files in the directory ‘sym_mode_2d_diagrams/patterns_PATTERN/’ (this directory is created if it does not exist).

Returns the max number of slopes found, regardless of extremality test.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: pattern_extreme(3, 4, 0, test_extremality=True, count_components=True)
#####  ...
q = 130; f = 65; num_components = 8; num_slopes = 8; divisor = 205; extreme = True
l = 3; sv = (49, 9, 9, 3, -19)
h = pattern0_sym_fn(l, sv)
#####  ...
q = 130; f = 65; num_components = 6; num_slopes = 6; divisor = 33; extreme = True
l = 3; sv = (9, 1, 1, 1, -3)
h = pattern0_sym_fn(l, sv)
8
cutgeneratingfunctionology.igp.pattern_fn(l, pattern)

Suppose the prescribed painting (according to pattern and size parameter \(l\)) has c connected components, with slope values q*Variable(0),…, q*Variable(c-1).

Returns a list fn of length (q+1). fn[i] is a Linear_Expression in terms of Variable(0),…, Variable(c-1), for i=0,…,q.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: fn = pattern_fn(1, pattern=0)
sage: fn[28]
2*x0+12*x1+14*x2
sage: len(fn)
59
sage: fn[58]
0
cutgeneratingfunctionology.igp.pattern_glpk_lp(l, more_ini_additive=False, exact_arithmetic=True, simplex_first=True, reconstruct_rational=False, objcoef=None)

Find an extreme point of the polytope corresponding to the prescribed painting (pattern=0 and size parameter \(l\)), by solving the LP (given objective funtion’s coefficient) using glp_simplex (+ glp_exact, with or without retrieving rational solution).

We hope to obtain many-slope vertex functions by choosing objcoef nicely.

Returns:
  • optval: optimal value
  • optsol: optimal solution \(s0, s1, \dots , s_{l+1}\)
  • k_slope: number of slopes of this vertex function
  • v: vertex function’s values at (1/q)Z.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: print("glp_exact noise follows in old sage versions"); optval, optsol, k_slope, v = pattern_glpk_lp(1, objcoef=(12,55,0))
glp_exact...
sage: k_slope
6
sage: optsol
{0: 0.23404255319148934, 1: 0.14893617021276595, 2: -0.10638297872340424}

sage: print("glp_exact noise follows in old sage versions"); optval, optsol, k_slope, v = pattern_glpk_lp(1, reconstruct_rational=True,objcoef=(12,55,0))
glp_exact...
sage: optsol
(11/47, 7/47, -5/47)
cutgeneratingfunctionology.igp.pattern_glpk_test(l_list, more_ini_additive=False, exact_arithmetic=True, simplex_first=True, reconstruct_rational=False)

Test the running times for pattern_glpk_lp() with glp_simplex + glp_exact + reconstruction. See table in trac ticket #18735 comment 7.

Print l, number of slopes for the optimal solution, running time. Return a list of numbers of slopes.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: print("Ignore deprecation warnings for time.clock"); pattern_glpk_test(range(1,4), more_ini_additive=False, exact_arithmetic=False, simplex_first=False, reconstruct_rational=True)
Ignore...
1 2 ...
[2, 2, 2]
cutgeneratingfunctionology.igp.pattern_more_additive_vertices(l, pattern)

Extra additive points, to be added to pattern_additive_vertices to reduce the dimension. Experimental code.

cutgeneratingfunctionology.igp.pattern_polytope(vertices_color, fn)

Set up a PPL polytope with respect to the vertices_color.

fn is a list of Linear_Expressions in terms of Variable(0),…, Variable(c-1), of length (q+1). The polytope has variables {Variable(0),…, Variable(c-1)}.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: vertices_color = pattern_vertices_color(1, pattern=0, more_ini_additive=False)
sage: fn = pattern_fn(1, pattern=0)
sage: pattern_polytope(vertices_color, fn)
A 2-dimensional polyhedron in QQ^3 defined as the convex hull of 6 points
cutgeneratingfunctionology.igp.pattern_positive_zero_undecided_deltafn(vertices_color)

According to the prescribed painting, compute the lists positive_deltafn, zero_deltafn and undecided_deltafn.

zero_deltafn does not include the implied zero deltafn. pattern_lp, vertices_color might be modified.

See also pattern_positive_zero_undecided_deltafn_trivial().

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: l = 1; q, f = pattern_q_and_f(l, 0);
sage: vertices_color = pattern_vertices_color(l, pattern=0, more_ini_additive=False)
sage: print("glp_exact noise follows in old sage versions"); fn = pattern_setup_lp(l)
glp_exact...
sage: print("glp_exact noise follows in old sage versions"); positive_deltafn, zero_deltafn, undecided_deltafn = pattern_positive_zero_undecided_deltafn(vertices_color)
glp_exact...
sage: sorted(positive_deltafn)
[(0, 1, -1), (1, -1, 0), (1, 0, -1), (1, 0, 0), (1, 0, 1), (1, 1, 0)]
sage: zero_deltafn
[(0, 0, 0)]
sage: sorted(undecided_deltafn)
[(1, 1, -2), (1, 2, -3), (1, 2, 5), (1, 7, 12), (1, 8, 13), (1, 11, 14)]
cutgeneratingfunctionology.igp.pattern_positive_zero_undecided_deltafn_trivial(vertices_color)

Compute the list zero_deltafn of deltafn that corresponds to green vertices on the prescribled painting.

The other deltafn are put in the list undecided_deltafn. positive_deltafn is an empty list. Modifiy vertices_color accordingly.

Unlike pattern_positive_zero_undecided_deltafn(), this function does not call glpk_simplex_exact_solve() and pattern_will_form_edge() to compute implied green and explicit white vertices. Therefore, when vertex_enumeration_dim_threshold is large enough for given \(q\) so that no backtracking is needed in pattern_backtrack_polytope(), it will not waste time on exact_solve. In this case, pattern_backtrack_polytope() should perform as good as pattern_glpk_lp(). (Hopefully even better, since same deltafn value is accounted only once in constraints.)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: l = 1; q, f = pattern_q_and_f(l, 0);
sage: vertices_color = pattern_vertices_color(l, pattern=0, more_ini_additive=False)
sage: fn = pattern_setup_lp(l)
sage: positive_deltafn, zero_deltafn, undecided_deltafn = pattern_positive_zero_undecided_deltafn_trivial(vertices_color)
sage: positive_deltafn
[]
sage: zero_deltafn
[(0, 0, 0)]
sage: len(undecided_deltafn)
91
cutgeneratingfunctionology.igp.pattern_ppl_lp(l, more_ini_additive=False, objcoef=None)

Similar to pattern_glpk_lp(). Uses PPL’s MIP_Problem class for solving lp.

Exact arithmetics, but too slow.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: optval, optsol, k_slope, v, v_div = pattern_ppl_lp(1, objcoef=(12,55,0))
sage: k_slope
6
sage: optsol
point(11/47, 7/47, -5/47)
sage: QQ(optval)
11
sage: QQ(v_div)
47
cutgeneratingfunctionology.igp.pattern_ppl_test(l_list, more_ini_additive=False)

Test the performance of pattern_ppl_lp(). Similar to pattern_glpk_test().

cutgeneratingfunctionology.igp.pattern_q_and_f(l, pattern)

Returns the values of q and f for the prescribed pattern.

pattern == 0 corresponds to the pattern described in the paper. In the paper, r is what is called l here.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: pattern_q_and_f(1, pattern=0)
(58, 29)
cutgeneratingfunctionology.igp.pattern_s(l, pattern)

Suppose the prescribed painting (according to pattern and size parameter \(l\)) has c connected components, with slope values q*Variable(0),…, q*Variable(c-1).

Returns a list s of length f. s[i] = fn[i+1]-fn[i] is in {Variable(0),…, Variable(c-1)}, for i=0,…,f-1.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: s = pattern_s(1, pattern=0)
sage: s[0]
x0
sage: len(s)
29
cutgeneratingfunctionology.igp.pattern_setup_lp(l, more_ini_additive=False, objcoef=None, use_auxiliary_delta=True)

Set up a MixedIntegerLinearProgram() with respect to the prescribled painting, where pattern=0, sym=True and the size parameter is \(l\).

Returns:
  • fn: a list of LinearFunction in terms of \(s_0, s_1, \dots , s_{l+1}\), corresponding to the function values at \((1/q)Z\).
Global variables:
  • pattern_lp: MixedIntegerLinearProgram()
  • var_slope: slope variables`s_0, s_1, dots , s_{l+1}`
When use_auxiliary_delta=True:
  • var_delta: auxiliary variables deltafn;
    controle additive/subadd by pattern_lp.set_max(var_delta[deltafn], 0) or pattern_lp.set_max(var_delta[deltafn], None)
  • deltafn_dic: a dictionary, key = delta, value = a list [(i,j) such that `deltapi`[i,j]=key]

EXAMPLES:

sage: import cutgeneratingfunctionology.igp as igp
sage: fn = igp.pattern_setup_lp(1, more_ini_additive=False, objcoef=None)
sage: fn[28]
2*x_0 + 12*x_1 + 14*x_2
sage: igp.pattern_lp.number_of_variables()
95
sage: igp.var_slope
MIPVariable ...
sage: igp.var_delta
MIPVariable ...
sage: len(igp.deltafn_dic.items())
92
sage: igp.deltafn_dic[(2, 10, 13)]
[(25, 29), (25, 33)]
cutgeneratingfunctionology.igp.pattern_vertices_color(l, pattern=0, more_ini_additive=False)

Returns a (q+1)*(q+1) 0-1 array that describes the color of vertices in the prescribed painting according to \(pattern\) and size parameter \(l\).

cutgeneratingfunctionology.igp.pattern_will_form_edge(x, y, vertices_color)

Return whether paiting (x, y) green on vertices_color will create a green edge. Assume x <= y.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: l = 1; q, f = pattern_q_and_f(l, 0);
sage: vertices_color = pattern_vertices_color(l, pattern=0, more_ini_additive=False)
sage: pattern_will_form_edge(1, 1, vertices_color)
True
sage: pattern_will_form_edge(2, q, vertices_color)
True
sage: pattern_will_form_edge(2, q-1, vertices_color)
False
cutgeneratingfunctionology.igp.perturbation_corresponding_to_vertex(perturbs, vertex)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # to disable output in automatic tests.
sage: h = not_extreme_1()
sage: finite_dimensional_extremality_test(h, show_all_perturbations=True)
False
sage: perturbs = h._perturbations
sage: pert_mip = perturbation_mip(h, perturbs, 'ppl')
sage: pert_mip.solve()
0
sage: mip_sol = pert_mip.get_values([pert_mip[0], pert_mip[1]])
sage: mip_sol
[-4/3, -4/3]
sage: perturbation = perturbation_corresponding_to_vertex(perturbs, mip_sol)
sage: h_lift = h + perturbation
sage: extremality_test(h_lift)
True
cutgeneratingfunctionology.igp.perturbation_interior_slopes_bounds(fn, perturbation_components=None)
cutgeneratingfunctionology.igp.perturbation_lim_slopes_mip(fn, perturbation_components=None, solver=None)
cutgeneratingfunctionology.igp.perturbation_mip(fn, perturbs, solver=None, field=None, undefined_ok=False)

Given fn and a list of basic perturbations that are pwl, satisfing the symmetry condition and pert(0)=pert(f)=0. Set up a mip, one dimension for each basic perturbation, with the subadditivities.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # to disable output in automatic tests.
sage: h = not_extreme_1()
sage: finite_dimensional_extremality_test(h, show_all_perturbations=True)
False
sage: len(h._perturbations)
2
sage: pert_mip = perturbation_mip(h, h._perturbations,'ppl')

We set solver=ppl here. Note that we can also set solver=InteractiveLP. The coefficients in the constraints are rational numbers, rather than float used by the default GLPK solver:

sage: pert_mip.show()
Maximization:
<BLANKLINE>
Constraints:
  constraint_0: -1/10 x_0 <= 1/3
  constraint_1: 1/20 x_0 <= 1/3
  constraint_2: -1/20 x_0 <= 2/3
  constraint_3: 1/10 x_0 <= 2/3
  constraint_4: -1/10 x_1 <= 2/3
  constraint_5: 1/20 x_1 <= 2/3
  constraint_6: -1/20 x_1 <= 1/3
  constraint_7: 1/10 x_1 <= 1/3
  constraint_8: -1/4 x_0 <= 1/3
  constraint_9: -1/10 x_0 + 1/10 x_1 <= 2/3
  constraint_10: -1/10 x_0 - 3/20 x_1 <= 1/3
  constraint_11: 3/20 x_0 + 1/10 x_1 <= 1/3
  constraint_12: 1/20 x_0 - 1/20 x_1 <= 2/3
  constraint_13: -1/20 x_0 + 1/20 x_1 <= 4/3
  constraint_14: -1/20 x_0 - 1/5 x_1 <= 1
  constraint_15: 1/5 x_0 + 1/20 x_1 <= 1
  constraint_16: 1/10 x_0 - 1/10 x_1 <= 4/3
  constraint_17: 1/4 x_1 <= 1/3
Variables:
  x_0 is a continuous variable (min=-oo, max=+oo)
  x_1 is a continuous variable (min=-oo, max=+oo)

Since rational coefficients are used in ppl solver, we can ask for the polyhedron defined by the Linear Program. This would fail if we set solver=GLPK and if coefficient are not integers, due to AttributeError: type object 'float' has no attribute 'fraction_field':

sage: pert_poly = pert_mip.polyhedron()
sage: pert_poly
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices
sage: vertices = pert_poly.vertices()
sage: vertices
(A vertex at (20/3, -20/3),
 A vertex at (4/3, 4/3),
 A vertex at (-4/3, 4/3),
 A vertex at (-4/3, -4/3))

Lifting the function by adding a perturbation that corresponds to a vertex, we obtain an extreme function:

sage: h_lift = h + perturbation_corresponding_to_vertex(h._perturbations, vertices[2])
sage: extremality_test(h_lift)
True
cutgeneratingfunctionology.igp.perturbation_polyhedron(fn, perturbs, undefined_ok=False, **kwds)

Given fn and a list of basic perturbations that are pwl, satisfing the symmetry condition and pert(0)=pert(f)=0. Set up a polyhedron, one dimension for each basic perturbation, with the subadditivities.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # to disable output in automatic tests.
sage: h = not_extreme_1()
sage: finite_dimensional_extremality_test(h, show_all_perturbations=True)
False
sage: perturbs = h._perturbations
sage: len(perturbs)
2
sage: pert_polyhedron = perturbation_polyhedron(h, perturbs)
sage: pert_polyhedron
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices
sage: pert_polyhedron.Hrepresentation()
(An inequality (-9, -6) x + 20 >= 0,
 An inequality (6, 9) x + 20 >= 0,
 An inequality (3, 0) x + 4 >= 0,
 An inequality (0, -3) x + 4 >= 0)
sage: pert_polyhedron.Vrepresentation()
(A vertex at (20/3, -20/3),
 A vertex at (4/3, 4/3),
 A vertex at (-4/3, 4/3),
 A vertex at (-4/3, -4/3))

Lift function by adding a perturbtion that corresponds to the vertex (-4/3, 4/3), i.e., set h_lift = h - 4/3*h._perturbations[0] + 4/3*h._perturbations[1]. The lifted function is extreme:

sage: vertex = pert_polyhedron.vertices()[2]
sage: perturbation = perturbation_corresponding_to_vertex(perturbs, vertex)
sage: h_lift = h + perturbation
sage: extremality_test(h_lift)
True

The following function has irrational data:

sage: h = chen_tricky_uncovered_intervals()
sage: finite_dimensional_extremality_test(h, show_all_perturbations=True)
False
sage: perturbs = h._perturbations
sage: pert_polyhedron = perturbation_polyhedron(h, perturbs)
sage: pert_polyhedron
A 2-dimensional polyhedron in (Real Number Field in `a` as the root of the defining polynomial y^2 - 3 near 1.732050807568878?)^2 defined as the convex hull of 4 vertices
sage: pert_polyhedron.Vrepresentation()
(A vertex at (-2.36220486286011?, 0.967307929548895?),
 A vertex at (2.797434948471088?, 0.967307929548895?),
 A vertex at (-3.61183490350498?, -1.248914311409209?),
 A vertex at (1.79481389229748?, -3.45932770938056?))

The following function is 2-sided discontinous at the origin:

sage: h = zhou_two_sided_discontinuous_cannot_assume_any_continuity()
sage: import cutgeneratingfunctionology.igp as igp
sage: igp.generate_symbolic_two_sided_discontinuous_basis_functions = ('slopes', 'jumps')   # Restore classic behavior
sage: finite_dimensional_extremality_test(h, show_all_perturbations=True)
False
sage: perturbs = h._perturbations
sage: pert_polyhedron = perturbation_polyhedron(h, perturbs)
sage: pert_polyhedron
A 1-dimensional polyhedron in QQ^1 defined as the convex hull of 2 vertices
sage: pert_polyhedron.Vrepresentation()
(A vertex at (4/3), A vertex at (-4/9))
sage: h_lift = h + perturbation_corresponding_to_vertex(perturbs, pert_polyhedron.vertices()[0])
sage: extremality_test(h_lift)
True
cutgeneratingfunctionology.igp.perturbation_polyhedron_ieqs_eqns(fn, perturbs, undefined_ok=False)
cutgeneratingfunctionology.igp.phi_s_in_drlm_not_extreme_2(s=10)

Example from S. S. Dey, J.-P. P. Richard, Y. Li, and L. A. Miller, On the extreme inequalities of infinite group problems, Mathematical Programming 121 (2009), no. 1, 145-170, https://doi:10.1007/s10107-008-0229-6. Figure 2.

\(s\) is an integer; \(s > 2\).

phi_s_in_drlm_not_extreme_2(s) is an extreme function. The pointwise limit as \(s\) tends to \(\\infty\) is not extreme. See drlm_not_extreme_2()

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)             # Suppress output in automatic tests.
sage: h = phi_s_in_drlm_not_extreme_2()
sage: extremality_test(h, False)
True
cutgeneratingfunctionology.igp.piecewise_function_from_breakpoints_and_limits(bkpt, limits, field=None, merge=True)

Create a continuous or discontinuous piecewise function from bkpt and limits.

  • bkpt and limits are two parallel lists. Assume that bkpt is a sorted (increasing). limits is a list of tuple of 3 numbers (mid, right, left).
  • The data are coerced into a common convenient field via nice_field_values.
  • If merge is True (the default), adjacent pieces of equal slopes are merged into one.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN) # Suppress output in automatic tests.
sage: bkpt = [0, 1/8, 3/8, 1/2, 5/8, 7/8, 1]
sage: limits = [(0, 0, 1/2), (1/4, 1/4, 3/4), (3/4, 1/4, 3/4), (1, 1/2, 1), (3/4, 3/4, 3/4), (1/4, 1/4, 1/4), (0, 0, 1/2)]
sage: h = piecewise_function_from_breakpoints_and_limits(bkpt, limits)
sage: h  == hildebrand_discont_3_slope_1()
True
sage: h = piecewise_function_from_breakpoints_and_limits(bkpt=[0, 1/5, 2/5, 3/5, 4/5, 1], limits = [{-1:0, 0:0, 1:0},{-1:1, 0:1, 1:1}, {-1:0, 0:2/5, 1:2/5}, {-1:2/5, 0:1/2, 1:3/5}, {-1:3/5, 0:3/5, 1:1}, {-1:0, 0:0, 1:0}])
sage: h.limit(3/5, 1)
3/5
sage: h.limit(3/5, 0)
1/2
sage: h.limit(3/5, -1)
2/5
cutgeneratingfunctionology.igp.piecewise_function_from_breakpoints_and_slopes(bkpt, slopes, field=None, merge=True)

Create a continuous piecewise function from bkpt and slopes.

  • bkpt and slopes are two parallel lists (except that bkpt is one element longer); assuming bpkt is sorted (increasing). The function always has value \(0\) on bkpt[0].
  • The data are coerced into a common convenient field via nice_field_values.
  • If merge is True (the default), adjacent pieces of equal slopes are merged into one.
cutgeneratingfunctionology.igp.piecewise_function_from_breakpoints_and_values(bkpt, values, field=None, merge=True)

Create a continuous piecewise function from bkpt and values.

  • bkpt and values are two parallel lists; assuming bpkt is sorted (increasing).
  • The data are coerced into a common convenient field via nice_field_values.
  • If merge is True (the default), adjacent pieces of equal slopes are merged into one.
cutgeneratingfunctionology.igp.piecewise_function_from_breakpoints_slopes_and_jumps(bkpt, slopes, jumps, field=None, merge=True)

Create a continuous or discontinuous piecewise function from bkpt, slopes and jumps.

  • The function always has value 0 on the first breakpoint \(0\). The list jumps describes the function value jumps on the left and the right endpoints of each slope.
  • The data are coerced into a common convenient field via nice_field_values.
  • If merge is True (the default), adjacent pieces of equal slopes are merged into one.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN) # Suppress output in automatic tests.
sage: bkpt = [0, 1/8, 3/8, 1/2, 5/8, 7/8, 1]
sage: slopes = [6, 2, 6, 2, -2, 2]
sage: jumps = [0, -1/2, 0, 0, -1/2, 0, -1/2, 0, 0, 0, 0, -1/2]
sage: h = piecewise_function_from_breakpoints_slopes_and_jumps(bkpt, slopes, jumps)
cutgeneratingfunctionology.igp.piecewise_function_from_breakpoints_slopes_and_values(bkpt, slopes, values, field=None, merge=True)

Create a continuous piecewise function from bkpt, slopes, and values.

  • bkpt and values are two parallel lists; it is assumed that bkpt is sorted in increasing order.
  • slopes is one element shorter and represents the slopes of the interpolation.
  • The function is overdetermined by these data. The consistency of the data is currently not checked.
  • The data are coerced into a common convenient field via nice_field_values.
  • If merge is True (the default), adjacent pieces of equal slopes are merged into one.
cutgeneratingfunctionology.igp.piecewise_function_from_interval_lengths_and_slopes(interval_lengths, slopes, field=None, merge=True)

Create a continuous piecewise function from interval_lengths and slopes.

  • The function always has value 0 on 0. interval_lengths and slopes are two parallel lists that define the function values to the right of 0.
  • The data are coerced into a common convenient field via nice_field_values.
  • If merge is True (the default), adjacent pieces of equal slopes are merged into one.
cutgeneratingfunctionology.igp.piecewise_function_from_robert_txt_file(filename)

The .txt files have 4 rows.

  • 1st row = \(Y\) values
  • 2nd row = \(X\) values (I do not use these, but I included them in case you want them)
  • 3rd row = \(f\) (the \(x\) coordinate for which I use as \(f\))
  • 4th row = value at \(f\) (I do not normalize this to 1. This allows the \(Y\) values to range from 0 to this values)

Also, I do not include the last value (\(\pi(1)\)) ever because this is the same as \(\pi(0)\) due to periodicity. So, if you need this last value, please attach a 0 to the end of the \(Y\) values and an extra \(x\) value.

cutgeneratingfunctionology.igp.plot_2d_additive_limit_vertices(fn)

Temporary code. Show additivity information on a 2d-diagram

cutgeneratingfunctionology.igp.plot_2d_complex(function, continuous_plot_kwds=None, discontinuous_plot_kwds=None)

Returns a plot of the horizontal lines, vertical lines, and diagonal lines of the complex.

cutgeneratingfunctionology.igp.plot_2d_diagram(fn, show_function=True, show_projections=True, known_minimal=False, f=None, colorful=False, additive_color=None, function_color='blue')

Returns a plot of the 2d complex (\(\\Delta P\)) of fn with shaded additive faces, i.e., faces where \(\\Delta \\pi = 0\).

  • If known_minimal is False (the default), highlight

non-subadditive or non-symmetric vertices of the 2d complex.

  • If show_function is True (the default), plot the function at the left and top borders of the diagram via plot_function_at_borders.
  • If show_projections is True (the default), plot the projections \(p_1(F), p_2(F), p_3(F)\) of

all full-dimensional additive faces via plot_projections_at_borders.

To show only a part of the diagram, use:

sage: from cutgeneratingfunctionology.igp import *
sage: plot_2d_diagram(h).show(xmin=0.25, xmax=0.35, ymin=0.25, ymax=0.35)  # not tested

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = FastPiecewise([[closed_interval(0,1/4), FastLinearFunction(4, 0)],
....:                    [open_interval(1/4, 1), FastLinearFunction(4/3, -1/3)],
....:                    [singleton_interval(1), FastLinearFunction(0,0)]])
sage: plot_2d_diagram(h)
Graphics object ...
sage: h = FastPiecewise([[closed_interval(0,1/4), FastLinearFunction(4, 0)],
....:                    [open_interval(1/4,1/2), FastLinearFunction(3, -3/4)],
....:                    [closed_interval(1/2, 3/4), FastLinearFunction(-2, 7/4)],
....:                    [open_interval(3/4,1), FastLinearFunction(3, -2)],
....:                    [singleton_interval(1), FastLinearFunction(0,0)]])
sage: plot_2d_diagram(h)
Graphics object ...
cutgeneratingfunctionology.igp.plot_2d_diagram_additive_domain_sans_limits(fn, show_function=True, f=None, additive_color='mediumspringgreen', function_color='blue', **kwds)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = hildebrand_discont_3_slope_1()
sage: g = plot_2d_diagram_additive_domain_sans_limits(h)
cutgeneratingfunctionology.igp.plot_2d_diagram_with_cones(fn, show_function=True, f=None, conesize=200, additive_color=None, function_color='blue')
cutgeneratingfunctionology.igp.plot_2d_diagram_with_eps_cones(fn, show_function=True, f=None, conesize=200, additive_color=None, function_color='blue')

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = zhou_two_sided_discontinuous_cannot_assume_any_continuity()
sage: g = plot_2d_diagram_with_eps_cones(h)
sage: h = not_minimal_2()
sage: g = plot_2d_diagram_with_eps_cones(h)
cutgeneratingfunctionology.igp.plot_2d_diagram_with_face_cones(fn, show_function=True, f=None, conesize=200, additive_color=None, function_color='blue')

This shows larger cones, corresponding to enclosing faces rather than cones corresponding to epsilons.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = zhou_two_sided_discontinuous_cannot_assume_any_continuity()
sage: g = plot_2d_diagram_with_face_cones(h)
sage: h = not_minimal_2()
sage: g = plot_2d_diagram_with_face_cones(h)
cutgeneratingfunctionology.igp.plot_2d_regions(fn, colorful=False, search_method='BB', find_min=True, stop_only_if_strict=True, show_plots=True, **kwds)

Visualize the subadditivity test based on spatial branch and bound.

Cells of each diagrams correspond to leaves of the branch and bound tree.

If colorful=True, the plot is done in fried eggs and tomato style: the yellow regions are pruned by indivisibility (i.e., they are faces of \(\Delta\mathcal{P}\)), and the red regions are pruned by bounds.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = kzh_7_slope_1()
sage: plot_2d_regions(h, colorful=True)      # not tested
cutgeneratingfunctionology.igp.plot_2d_regions_in_one_level(node_set, colorful=False, **bound_kwds)
cutgeneratingfunctionology.igp.plot_beams_of_one_face(face)
cutgeneratingfunctionology.igp.plot_completion_diagram(fn, perturbation=None)

Return a plot of the completion diagram.

To view a part only, use:

sage: plot_completion_diagram(h).show(xmin=0.3, xmax=0.55, ymin=0.3, ymax=0.55) # not tested
cutgeneratingfunctionology.igp.plot_completion_diagram_background(fn)
cutgeneratingfunctionology.igp.plot_covered_component_as_rectangles(component, **kwds)
cutgeneratingfunctionology.igp.plot_covered_components_as_rectangles(components, **kwds)
cutgeneratingfunctionology.igp.plot_covered_components_at_borders(fn, covered_components=None, **kwds)

Colorful decoration.

Plot fn on covered intervals with different colors according to slope values, on the upper and the left border of the 2d diagrams.

cutgeneratingfunctionology.igp.plot_covered_intervals(function, covered_components=None, uncovered_color='black', labels=None, show_one_point_overlap_markers=None, **plot_kwds)

Returns a plot of the covered and uncovered intervals of the function.

cutgeneratingfunctionology.igp.plot_cpl_components(components, show_testpoints=False, goto_lower_dim=False)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: regions = cpl_regions_from_arrangement_of_bkpts(3, cpleq=True) # not tested
sage: g = plot_cpl_components(regions)                               # not tested
sage: g.show(xmin=0, xmax=1, ymin=0, ymax=1/4)                       # not tested
cutgeneratingfunctionology.igp.plot_directed_moves(dmoves, **kwds)
cutgeneratingfunctionology.igp.plot_directly_covered_intervals(function, uncovered_color='black', labels=None, **plot_kwds)
cutgeneratingfunctionology.igp.plot_faces(faces, **kwds)
cutgeneratingfunctionology.igp.plot_function_at_borders(fn, color='blue', legend_label='Function pi', covered_components=None, **kwds)

Plot the function twice, on the upper and the left border, to decorate 2d diagrams.

cutgeneratingfunctionology.igp.plot_kwds_hook(kwds)
cutgeneratingfunctionology.igp.plot_kwds_hook_no_legend(kwds)
cutgeneratingfunctionology.igp.plot_limit_cone_of_vertex(x, y, cone, color='red', r=0.0300000000000000, style=None, zorder=None, width=None, vertex_size=None, **kwds)

plot a cone or a ray or a point

cutgeneratingfunctionology.igp.plot_limit_cone_of_vertex_in_face(x, y, F, color='red', **kwds)
cutgeneratingfunctionology.igp.plot_no_legend(f, *args, **kwds)
cutgeneratingfunctionology.igp.plot_painted_faces(q, faces)

(Ignore please.) Return a plot of the 2d complex of q-grid with green faces.

cutgeneratingfunctionology.igp.plot_pattern(l, vertices_color=None, more_ini_additive=True, show_plots=True)

Plots prescribled painting (pattern=0) according to size parameter \(l\) and more_ini_additive. If vertices_color is given, use it.

cutgeneratingfunctionology.igp.plot_perturbation_diagram(fn, perturbation=None, xmin=0, xmax=1)

Plot a perturbation of fn.

perturbation is either a perturbation function, or an integer (which designates a basic perturbation of fn via basic_perturbation). If perturbation is not provided, it defaults to the perturbation indexed 1.

To show only a part of the diagram, use:

sage: plot_perturbation_diagram(h, 1).show(xmin=0.25, xmax=0.35, ymin=0.25, ymax=0.35)  # not tested
cutgeneratingfunctionology.igp.plot_points_of_discontinuity_at_borders(pts_of_discontinuity)
cutgeneratingfunctionology.igp.plot_projections_at_borders(fn)

Plot the projections \(p_1(F), p_2(F), p_3(F)\) of all full-dimensional additive faces \(F\) of fn as gray shadows:

  • \(p_1(F)\) at the top border,
  • \(p_2(F)\) at the left border,
  • \(p_3(F)\) at the bottom and the right borders.
cutgeneratingfunctionology.igp.plot_projections_of_faces(additive_faces, nonsubadditive_vertices=(), end_points=())
cutgeneratingfunctionology.igp.plot_projections_of_one_face(face, IJK_kwds)
cutgeneratingfunctionology.igp.plot_rescaled_perturbation(perturb, xmin=0, xmax=1, **kwds)
cutgeneratingfunctionology.igp.plot_symbolic(sym, indices=None, as_array=True, color='magenta', **kwds)

EXAMPLES:

Basis functions for the continuous case. Note that they are monotonically increasing and therefore not periodic functions:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: h = not_extreme_1()
sage: sym = generate_symbolic(h)
sage: plot_symbolic(sym, thickness=2, **ticks_keywords(h)).show(figsize=(6, 6))  # not tested

Basis functions for the one-sided discontinuous case. The first three are slopes, the last two are jumps. Again they are monotonically increasing:

sage: h = hildebrand_discont_3_slope_1()
sage: sym = generate_symbolic(h)
sage: plot_symbolic(sym, thickness=2, **ticks_keywords(h)).show(figsize=(6, 6))  # not tested

Basis functions for the two-sided discontinuous case. Here we cannot assume continuity at any uncovered breakpoint, so nothing is gained by making them increasing functions. Instead we choose them as local on the components (and therefore periodic):

sage: h = minimal_no_covered_interval()
sage: sym = generate_symbolic(h)
sage: plot_symbolic(sym, thickness=2, **ticks_keywords(h)).show(figsize=(6, 6))  # not tested
cutgeneratingfunctionology.igp.plot_trivial_2d_diagram_with_grid(function, xgrid=None, ygrid=None)

Returns a plot of the 2d complex with vertices marked that have \(\Delta \pi = 0\).

Does not use any complicated code. Mainly used for visually double-checking the computation of maximal additive faces.

cutgeneratingfunctionology.igp.plot_walk(walk_dict, color='black', ymin=0, ymax=1, **kwds)
cutgeneratingfunctionology.igp.plot_walk_in_completion_diagram(seed, walk_dict)
cutgeneratingfunctionology.igp.plot_with_colored_slopes(fn, **plot_kwds)

Returns a plot of fn, with pieces of different slopes in different colors.

cutgeneratingfunctionology.igp.plotting_2d_diagram_bug_example()

This is not a subadditive function. Additivity appears in the interior of some face, but not over the entire face.

It caused a trouble in generate_maximal_additive_faces_continuous and in plotting_2d_diagram. Namely, define face = generate_maximal_additive_faces(h) (see [47]); we observed that face.vertices and face.minimal_triple do not match. The problem has now been fixed.

cutgeneratingfunctionology.igp.ppl_point()

Construct a point.

INPUT:

  • expression – a Linear_Expression or something convertible to it (Variable or integer).
  • divisor – an integer.

OUTPUT:

A new Generator representing the point.

Raises a ValueError` if ``divisor==0.

Examples:

>>> from ppl import Generator, Variable
>>> y = Variable(1)
>>> Generator.point(2*y+7, 3)
point(0/3, 2/3)
>>> Generator.point(y+7, 3)
point(0/3, 1/3)
>>> Generator.point(7, 3)
point()
>>> Generator.point(0, 0)
Traceback (most recent call last):
...
ValueError: PPL::point(e, d):
d == 0.
cutgeneratingfunctionology.igp.print_directly_covered_constraints(filename, q, z)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: print_directly_covered_constraints(sys.stdout, 3, 1/3)
c_1_0 - l_1_0 <= 0
c_1_0 - u_1_0 <= 0
c_1_0 - l_1_1 <= 0
c_1_0 - u_1_1 <= 0
c_1_0 - l_1_2 <= 0
c_1_0 - u_1_2 <= 0
c_1_0 - l_0_1 <= 0
c_1_0 - l_1_0 <= 0
c_1_0 - l_2_2 <= 0
c_1_0 - u_0_0 <= 0
c_1_0 - u_1_2 <= 0
c_1_0 - u_2_1 <= 0
c_1_0 - l_1_0 - u_1_0 - l_1_1 - u_1_1 - l_1_2 - u_1_2 - l_0_1 - l_1_0 - l_2_2 - u_0_0 - u_1_2 - u_2_1 >= -11
cutgeneratingfunctionology.igp.print_fn_bounds(filename, q)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: print_fn_bounds(sys.stdout, 3)
0 <= fn_0 <= 1
0 <= fn_1 <= 1
0 <= fn_2 <= 1
0 <= fn_3 <= 1
cutgeneratingfunctionology.igp.print_fn_minimality_test(filename, q, f, m=0)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: print_fn_minimality_test(sys.stdout, 3, 2/3)
fn_0 = 0
fn_0 + fn_2 = 1
fn_1 + fn_1 = 1
fn_2 + fn_3 = 1
fn_1 + fn_1 - fn_2 >= 0
fn_1 + fn_1 - fn_2 - 2 p_1_1 <= 0
fn_1 + fn_2 - fn_3 >= 0
fn_1 + fn_2 - fn_3 - 2 p_1_2 <= 0
fn_2 + fn_2 - fn_1 >= 0
fn_2 + fn_2 - fn_1 - 2 p_2_2 <= 0
cutgeneratingfunctionology.igp.print_logical_constraints(filename, q, face)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: import sys;
sage: print_logical_constraints(sys.stdout, 7, Face(([1/7, 2/7], [1/7, 2/7], [2/7, 3/7])))
l_1_1 - p_1_1 >= 0
l_1_1 - p_1_2 >= 0
l_1_1 - p_2_1 >= 0
l_1_1 - p_1_1 - p_1_2 - p_2_1 <= 0     
cutgeneratingfunctionology.igp.print_move_constraints(filename, q, x, z)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: print_move_constraints(sys.stdout, 7, 1/7, 3/7)
m_1_3 - h_1_2 <= 0
m_1_3 - v_5_3 <= 0
h_1_2 + v_5_3 - m_1_3 <= 1
sage: print_move_constraints(sys.stdout, 7, 3/7, 1/7)
m_3_1 - h_3_5 <= 0
m_3_1 - v_2_1 <= 0
h_3_5 + v_2_1 - m_3_1 <= 1
cutgeneratingfunctionology.igp.print_no_maximal_faces_0d(filename, q, f, faces_0d)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: q = 3; f = 2/3;
sage: faces_2d, faces_diag, faces_hor, faces_ver, faces_0d = all_faces(q)

sage: print_no_maximal_faces_0d(sys.stdout, q, f, faces_0d)
h_0_1 + h_1_1 + v_1_0 + v_1_1 + d_0_1 + d_1_0 - p_1_1 <= 5
h_0_2 + h_1_2 + v_1_1 + v_1_2 + d_0_2 + d_1_1 - p_1_2 <= 5
h_1_1 + h_2_1 + v_2_0 + v_2_1 + d_1_1 + d_2_0 - p_2_1 <= 5
h_1_2 + h_2_2 + v_2_1 + v_2_2 + d_1_2 + d_2_1 - p_2_2 <= 5
cutgeneratingfunctionology.igp.print_no_maximal_faces_diag(filename, q, f, faces_diag)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: q = 3; f = 2/3;
sage: faces_2d, faces_diag, faces_hor, faces_ver, faces_0d = all_faces(q)
sage: print_no_maximal_faces_diag(sys.stdout, q, f, faces_diag)
l_0_0 + u_0_0 - d_0_0 <= 1
l_0_2 + u_0_2 - d_0_2 <= 1
l_1_1 + u_1_1 - d_1_1 <= 1
l_1_2 + u_1_2 - d_1_2 <= 1
l_2_0 + u_2_0 - d_2_0 <= 1
l_2_1 + u_2_1 - d_2_1 <= 1
cutgeneratingfunctionology.igp.print_no_maximal_faces_hor(filename, q, f, faces_hor)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: q = 3; f = 2/3;
sage: faces_2d, faces_diag, faces_hor, faces_ver, faces_0d = all_faces(q)
sage: print_no_maximal_faces_hor(sys.stdout, q, f, faces_hor)
l_0_1 + u_0_0 - h_0_1 <= 1
l_0_2 + u_0_1 - h_0_2 <= 1
l_1_1 + u_1_0 - h_1_1 <= 1
l_1_2 + u_1_1 - h_1_2 <= 1
l_2_1 + u_2_0 - h_2_1 <= 1
l_2_2 + u_2_1 - h_2_2 <= 1
cutgeneratingfunctionology.igp.print_no_maximal_faces_ver(filename, q, f, faces_ver)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: q = 3; f = 2/3;
sage: faces_2d, faces_diag, faces_hor, faces_ver, faces_0d = all_faces(q)
sage: print_no_maximal_faces_ver(sys.stdout, q, f, faces_ver)
l_1_0 + u_0_0 - v_1_0 <= 1
l_2_0 + u_1_0 - v_2_0 <= 1
l_1_1 + u_0_1 - v_1_1 <= 1
l_2_1 + u_1_1 - v_2_1 <= 1
l_1_2 + u_0_2 - v_1_2 <= 1
l_2_2 + u_1_2 - v_2_2 <= 1
cutgeneratingfunctionology.igp.print_obj_5slope22(filename, q, weight=1)
cutgeneratingfunctionology.igp.print_obj_max_slope_slack(filename, kslopes)

slope_slack = s_0 - s_(kslopes-1)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: print_obj_max_slope_slack(sys.stdout, 5)
s_0 - s_4
cutgeneratingfunctionology.igp.print_obj_max_slope_slack_with_weights(filename, kslopes, weights)

slope_slack_with_weights = sum_{0 <= i <= kslopes-2} {weights[i] * (s_i - s_(i+1))}

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: print_obj_max_slope_slack_with_weights(sys.stdout, 5, [1, 1, 1, 1])
+ 1 s_0 - 1 s_1 + 1 s_1 - 1 s_2 + 1 s_2 - 1 s_3 + 1 s_3 - 1 s_4
sage: print_obj_max_slope_slack_with_weights(sys.stdout, 5, [1, 2, 2, 1])
+ 1 s_0 - 1 s_1 + 2 s_1 - 2 s_2 + 2 s_2 - 2 s_3 + 1 s_3 - 1 s_4
cutgeneratingfunctionology.igp.print_obj_max_subadd_slack(filename, q, weight=1)

subadd_slack = q * (sum_x {fn(x)}) = q * (q - 1)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: print_obj_max_subadd_slack(sys.stdout, 3)
1 fn_0 + 1 fn_1 + 1 fn_2 
cutgeneratingfunctionology.igp.print_obj_min_add_points(filename, q, weight=1)
cutgeneratingfunctionology.igp.print_obj_min_covered_times_max_subadd_slack(filename, q, maxstep=None)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: print_obj_min_covered_times_max_subadd_slack(sys.stdout, 2)
1 fn_0 + 1 fn_1 + 1 l_0_0 + 1 u_0_0 + 1 l_0_1 + 1 u_0_1 + 1 l_1_0 + 1 u_1_0 + 1 l_1_1 + 1 u_1_1 + 
1 t_0_1_1 + 1 r_0_1_1 + 1 t_1_0_1 + 1 r_1_0_1
cutgeneratingfunctionology.igp.print_obj_min_directly_covered_times(filename, q, weight=1)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: print_obj_min_directly_covered_times(sys.stdout, 2)
+ 1 l_0_0 + 1 u_0_0 + 1 l_0_1 + 1 u_0_1 + 1 l_1_0 + 1 u_1_0 + 1 l_1_1 + 1 u_1_1 
cutgeneratingfunctionology.igp.print_obj_min_undirectly_covered_times(filename, q, step=None, weight=1)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: print_obj_min_undirectly_covered_times(sys.stdout, 2)
+ 1 t_0_1_1 + 1 r_0_1_1 + 1 t_1_0_1 + 1 r_1_0_1
cutgeneratingfunctionology.igp.print_reflection_i_constraints(filename, q, x, z, i)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: print_reflection_i_constraints(sys.stdout, 7, 1/7, 3/7, 2)
c_1_1 - r_1_3_2 <= 0
d_1_3 - r_1_3_2 <= 0
r_1_3_2 - c_1_1 - d_1_3 <= 0
cutgeneratingfunctionology.igp.print_sign(epsilon)
cutgeneratingfunctionology.igp.print_slope_bounds(filename, q, kslopes)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: print_slope_bounds(sys.stdout, 3, 3)
-3 <= s_0 <= 3
-3 <= s_1 <= 3
-3 <= s_2 <= 3
cutgeneratingfunctionology.igp.print_slope_constraints(filename, q, kslopes, m=0)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: print_slope_constraints(sys.stdout, 3, 3, m=0)
s_0 - s_1 >= 0
s_1 - s_2 >= 0
s_0 - 3 fn_1 = 0
i_0_s_0 = 1
s_2 + 3 fn_2 = 0
i_2_s_2 = 1
s_0 + 3 fn_1 - 3 fn_2 + 6 i_1_s_0 <= 6
s_0 + 3 fn_1 - 3 fn_2 - 6 i_1_s_0 >= -6
s_1 + 3 fn_1 - 3 fn_2 + 6 i_1_s_1 <= 6
s_1 + 3 fn_1 - 3 fn_2 - 6 i_1_s_1 >= -6
s_2 + 3 fn_1 - 3 fn_2 + 6 i_1_s_2 <= 6
s_2 + 3 fn_1 - 3 fn_2 - 6 i_1_s_2 >= -6
+ i_0_s_0 + i_0_s_1 + i_0_s_2 = 1
+ i_1_s_0 + i_1_s_1 + i_1_s_2 = 1
+ i_2_s_0 + i_2_s_1 + i_2_s_2 = 1
+ i_0_s_0 + i_1_s_0 + i_2_s_0 >= 1
+ i_0_s_1 + i_1_s_1 + i_2_s_1 >= 1
+ i_0_s_2 + i_1_s_2 + i_2_s_2 >= 1
cutgeneratingfunctionology.igp.print_slope_constraints_2q(filename, q, f, a, kslopes, m=0)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: print_slope_constraints_2q(sys.stdout, 4, 3/4, 2/4, 3, m=0)
s_0 - s_1 >= 0
s_1 - s_2 >= 0
s_0 - 4 fn_1 = 0
i_0_s_0 = 1
s_2 + 4 fn_3 = 0
i_3_s_2 = 1
s_0 + 4 fn_1 - 4 fn_2 + 8 i_1_s_0 <= 8
s_0 + 4 fn_1 - 4 fn_2 - 8 i_1_s_0 >= -8
s_1 + 4 fn_1 - 4 fn_2 + 8 i_1_s_1 <= 8
s_1 + 4 fn_1 - 4 fn_2 - 8 i_1_s_1 >= -8
s_2 + 4 fn_1 - 4 fn_2 + 8 i_1_s_2 <= 8
s_2 + 4 fn_1 - 4 fn_2 - 8 i_1_s_2 >= -8
s_0 + 4 fn_2 - 4 fn_3 + 8 i_2_s_0 <= 8
s_0 + 4 fn_2 - 4 fn_3 - 8 i_2_s_0 >= -8
s_1 + 4 fn_2 - 4 fn_3 + 8 i_2_s_1 <= 8
s_1 + 4 fn_2 - 4 fn_3 - 8 i_2_s_1 >= -8
s_2 + 4 fn_2 - 4 fn_3 + 8 i_2_s_2 <= 8
s_2 + 4 fn_2 - 4 fn_3 - 8 i_2_s_2 >= -8
+ i_0_s_0 + i_0_s_1 + i_0_s_2 = 1
+ i_1_s_0 + i_1_s_1 + i_1_s_2 = 1
+ i_2_s_0 + i_2_s_1 + i_2_s_2 = 1
+ i_3_s_0 + i_3_s_1 + i_3_s_2 = 1
+ i_0_s_0 + i_1_s_0 + i_2_s_0 + i_3_s_0 >= 1
+ i_0_s_1 + i_1_s_1 + i_2_s_1 + i_3_s_1 >= 1
+ i_0_s_2 + i_1_s_2 + i_2_s_2 + i_3_s_2 >= 1
i_1_s_0 + i_0_s_0 <= 1
i_1_s_0 - i_1_s_0 = 0
i_1_s_0 + i_2_s_0 <= 1
i_1_s_0 + i_3_s_0 <= 1
i_1_s_1 + i_0_s_1 <= 1
i_1_s_1 - i_1_s_1 = 0
i_1_s_1 + i_2_s_1 <= 1
i_1_s_1 + i_3_s_1 <= 1
i_1_s_2 + i_0_s_2 <= 1
i_1_s_2 - i_1_s_2 = 0
i_1_s_2 + i_2_s_2 <= 1
i_1_s_2 + i_3_s_2 <= 1
cutgeneratingfunctionology.igp.print_translation_i_constraints(filename, q, x, z, i)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: print_translation_i_constraints(sys.stdout, 7, 1/7, 3/7, 2)
c_1_1 - t_1_3_2 <= 0
m_1_3 - t_1_3_2 <= 0
t_1_3_2 - c_1_1 - m_1_3 <= 0
cutgeneratingfunctionology.igp.print_trivial_additive_points(filename, q, f)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: print_trivial_additive_points(sys.stdout, 3, 2/3)
p_0_0 = 0
p_0_1 = 0
p_0_2 = 0
p_0_3 = 0
p_1_3 = 0
p_2_3 = 0
p_3_3 = 0
p_0_2 = 0
p_1_1 = 0
p_2_0 = 0
p_2_3 = 0
p_3_2 = 0
cutgeneratingfunctionology.igp.print_trivial_additive_points_2q(filename, q, f, a)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: print_trivial_additive_points_2q(sys.stdout, 3, 2/3, 1/3)
p_0_0 = 0
p_0_1 = 0
p_0_2 = 0
p_0_3 = 0
p_1_3 = 0
p_2_3 = 0
p_3_3 = 0
p_0_2 = 0
p_1_1 = 0
p_2_0 = 0
p_2_3 = 0
p_3_2 = 0
p_1_0 = 0
p_1_1 = 0
cutgeneratingfunctionology.igp.print_undirectly_covered_i_constraints(filename, q, z, i)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: print_undirectly_covered_i_constraints(sys.stdout, 3, 1/3, 2)
c_1_2 - c_1_1 <= 0
c_1_2 - t_0_1_2 <= 0
c_1_2 - r_0_1_2 <= 0
c_1_2 - t_2_1_2 <= 0
c_1_2 - r_2_1_2 <= 0
c_1_2 - c_1_1 - t_0_1_2 - r_0_1_2 - t_2_1_2 - r_2_1_2 >= -4
cutgeneratingfunctionology.igp.print_xy_swapped_constraints(filename, q, face)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: import sys;
sage: face =Face(([1/7], [2/7], [3/7]))
sage: print_xy_swapped_constraints(sys.stdout, 7, face)
p_1_2 - p_2_1 = 0
cutgeneratingfunctionology.igp.projected_sequential_merge(g, n=1)

Construct the one-dimensional projected sequential merge inequality.

_images/igp-81.svg

\(h = g \lozenge_n^1 gmic\) with \(f = n r\) in the first function \(g\) and \(f = r\) in the second function gmic.

The notation \(\lozenge_n^1\) is given in [39] p.305, def.12 & eq.25 :
\(h(x) = \frac{1}{n+1}\xi(x) + n g(\lfloor(n + 1) x - r \xi(x)\rfloor)\), where \(\xi =\) gmic(r).

Parameters:

  • \(g\) (real) a valid inequality;
  • \(n\) (integer).
Function is known to be extreme under the conditions: cf. [39] p.309, Lemma 1
  1. \(g\) is a facet-defining inequality, with \(f=nr\) ;
  2. \(E(g)\) is unique up to scaling, cf. [39] p.289, def.6 & def.7 ;
  3. \([g]_{nr}\) is nondecreasing, cf. [39] p.290, def.8 (where \(m=1\)).

Note:

  • g = gj_forward_3_slope() does not satisfy condition (3), but
  • g = multiplicative_homomorphism(gj_forward_3_slope(), -1) satisfies (3).

Examples: [39] p.311, fig.5

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: g = multiplicative_homomorphism(gj_forward_3_slope(f=2/3, lambda_1=1/4, lambda_2=1/4), -1)
sage: extremality_test(g, False)
True
sage: h = projected_sequential_merge(g, n=1)
sage: extremality_test(h, False)
True
Reference:
[39] SS Dey, JPP Richard, Relations between facets of low-and high-dimensional group problems,
Mathematical Programming 123 (2), 285-313.
cutgeneratingfunctionology.igp.projection(vertices, linear_form)

Computes the projection of vertices based on the linear form.

vertices is a list of vertices (2-tuples).

linear_form is a 2-element list:

  • Projection on \(x\): \([1,0]\)
  • Projection on \(y\): \([0,1]\)
  • Projection on \(x + y\): \([1,1]\)
cutgeneratingfunctionology.igp.projections(vertices)

Computes \(F(I,J,K)\).

cutgeneratingfunctionology.igp.projections_of_additive_vertices(function)
cutgeneratingfunctionology.igp.random_6_tuple(fn, extra_cosets=[])
cutgeneratingfunctionology.igp.random_piecewise_function(xgrid=10, ygrid=10, continuous_proba=1, symmetry=True)

Return a random, continuous or discontinuous piecewise linear function defined on \([0, 1]\) with breakpoints that are multiples of \(\\frac{1}{xgrid}\) and values that are multiples of \(\\frac{1}{ygrid}\).

  • continuous_proba (a real number in \([0,1]\)) indicates the probability that the function is (left/right) continuous at a breakpoint.
  • Use continuous_proba = 1 (the default) to get a continuous piecewise linear function.
  • Use symmetry = True (the default) to get a symmetric function.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = random_piecewise_function(10, 10)
sage: h = random_piecewise_function(10, 10, continuous_proba=4/5, symmetry=True)
sage: h = random_piecewise_function(10, 10, continuous_proba=4/5, symmetry=False)
cutgeneratingfunctionology.igp.random_test_number(fn, extra_cosets=[])
cutgeneratingfunctionology.igp.read_default_args(function, **opt_non_default)

Return the default values of arguments of the function.

Override the default values if opt_non_default is given.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: read_default_args(gmic)
{'conditioncheck': True, 'f': 4/5, 'field': None}
sage: read_default_args(drlm_backward_3_slope, **{'bkpt': 1/5})
{'bkpt': 1/5, 'conditioncheck': True, 'f': 1/12, 'field': None}
cutgeneratingfunctionology.igp.read_lrs_to_cs_or_gs(fname)
cutgeneratingfunctionology.igp.reduce_covered_components(covered_components)
cutgeneratingfunctionology.igp.refind_function_from_lpsolution(filename, q, f)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h_list = refind_function_from_lpsolution('solution_5slope_fulldim_1.sol', 37, 25/37) # not tested
sage: h_list[0]==kzh_5_slope_fulldim_1() # not tested
True                                     # not tested
cutgeneratingfunctionology.igp.refind_function_from_lpsolution_2q(filename, q, f, a)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = refind_function_from_lpsolution_2q('solution_2q_example_m4.sol', 37, 25/37, 11/37) # not tested
cutgeneratingfunctionology.igp.reflection_i_variable(q, x, z, i)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: reflection_i_variable(7, 1/7, 3/7, 2)
'r_1_3_2'
cutgeneratingfunctionology.igp.remove_redundancy_from_cs(cs, verbose=False, return_lrs=False)

Remove redundant inequalities from cs using the command ‘redund’ from lrslib. Return the new cs without redundancy in ppl format if return_lrs==False (default), or in lrs format if return_lrs==True

cutgeneratingfunctionology.igp.rescale_to_amplitude(perturb, amplitude)

For plotting purposes, rescale the function perturb so that its maximum (supremum) absolute function value is amplitude.

cutgeneratingfunctionology.igp.restrict_to_finite_group(function, f=None, oversampling=None, order=None)

Restrict the given function to the cyclic group of given order.

_images/igp-82.svg

If order is not given, it defaults to the group generated by the breakpoints of function and \(f\) if these data are rational. However, if oversampling is given, it must be a positive integer; then the group generated by the breakpoints of function and \(f\) will be refined by that factor.

If \(f\) is not provided, uses the one found by find_f.

Assume in the following that \(f\) and all breakpoints of function lie in the cyclic group and that function is continuous.

Then the restriction is valid if and only if function is valid. The restriction is minimal if and only if function is minimal. The restriction is extreme if function is extreme. FIXME: Add reference.

_images/igp-83.svg

If, in addition oversampling >= 3, then the following holds: The restriction is extreme if and only if function is extreme. This is Theorem 1.5 in [IR2].

This oversampling factor of 3 is best possible, as demonstrated by function kzh_2q_example_1() from [KZh2015a].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: g = gj_2_slope()
sage: extremality_test(g)
True
sage: gf = restrict_to_finite_group(g)
sage: minimality_test(gf)
True
sage: finite_dimensional_extremality_test(gf)
True
sage: h = drlm_not_extreme_1()
sage: extremality_test(h)
False
sage: h7 = restrict_to_finite_group(h)
sage: h7.end_points()
[0, 1/7, 2/7, 3/7, 4/7, 5/7, 6/7, 1]
sage: minimality_test(h7)
True
sage: finite_dimensional_extremality_test(h7)
True
sage: h21 = restrict_to_finite_group(h, oversampling=3)
sage: minimality_test(h21)
True
sage: finite_dimensional_extremality_test(h21)
False
sage: h28 = restrict_to_finite_group(h, order=28)
sage: minimality_test(h28)
True
sage: finite_dimensional_extremality_test(h28)
False
sage: h5 = restrict_to_finite_group(h, order=5)
sage: minimality_test(h5)
False
Reference:
[IR2] A. Basu, R. Hildebrand, and M. Koeppe, Equivariant perturbation in Gomory and Johnson’s infinite group problem.
  1. The one-dimensional case, Mathematics of Operations Research (2014), doi:10. 1287/moor.2014.0660

[KZh2015a] M. Koeppe and Y. Zhou, New computer-based search strategies for extreme functions of the Gomory–Johnson infinite group problem, 2015, e-print http://arxiv.org/abs/1506.00017 [math.OC].

cutgeneratingfunctionology.igp.result_concrete_value(field, result)

Return the concrete values in result as a tuple. See also result_symbolic_expression().

This function can provided to find_region_type when setting up a SemialgebraicComplex. In this way, one can compare result of type ParametricRealFieldElement or list of ParametricRealFieldElement with the previous elements in region_type_color_map which do not necessarily have the same parent.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: def vol(a,b):
....:     P = Polyhedron(ieqs=[(1,0,-1),(0,0,1),(1,-1,0),(0,1,0),(1,-a,-b)])
....:     return P.volume()
sage: K.<a,b>=ParametricRealField([2,3])
sage: result = vol(a,b)
sage: result_concrete_value(K, result)
(1/12,)
cutgeneratingfunctionology.igp.result_symbolic_expression(field, result)

Return the symbolic expressions in result as a tuple

This function can provided to find_region_type when setting up a SemialgebraicComplex. In this way, one can compare result of type ParametricRealFieldElement or list of ParametricRealFieldElement with the previous elements in region_type_color_map which do not necessarily have the same parent.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: def vol(a,b):
....:     P = Polyhedron(ieqs=[(1,0,-1),(0,0,1),(1,-1,0),(0,1,0),(1,-a,-b)])
....:     return P.volume()
sage: K1.<a,b>=ParametricRealField([2,3])
sage: vol1 = vol(a,b)
sage: sym_exp1 = result_symbolic_expression(K1, vol1)
sage: sym_exp1
(1/(2*a*b),)
sage: K2.<a,b>=ParametricRealField([5,4])
sage: vol2 = vol(a,b)
sage: sym_exp2 = result_symbolic_expression(K2, vol2)
sage: sym_exp2
(1/(2*a*b),)
sage: vol1 == vol2
False
sage: sym_exp1 == sym_exp2
True    
cutgeneratingfunctionology.igp.return_result(field, result)
cutgeneratingfunctionology.igp.right_open_piece(p, q)
cutgeneratingfunctionology.igp.save_cpl_extreme_theta_regions(thetas_and_regions, name='cpl_theta', goto_lower_dim=False)

To plot only blue regions. Get diagrams “cpl_ext_theta_i” that show only blue regions.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: regions = cpl_regions_with_thetas_and_components()             # not tested
sage: thetas_and_regions = cpl_thetas_and_regions_extreme(regions)   # not tested
sage: save_cpl_extreme_theta_regions(thetas_and_regions, name="cpl_ext_theta")  # not tested

To plot colorful regions corresponding to each extreme thetas. Get diagrams “cpl_theta_i”, that show a bit more:

sage: thetas_and_components = cpl_thetas_and_regions(regions, thetas_and_regions) # not tested
sage: save_cpl_extreme_theta_regions(thetas_and_components, name="cpl_theta") # not tested 
(1, (z/(15*z - 2), (6*z - 1)/(15*z - 2)))
(2, ((-2*z)/(f - 1), 0))
(3, (1/4, 1/4))
(4, ((f + z)/(f + 1), z/(f + 1)))
(5, ((-z)/(f + 2*z - 1), 0))
(6, (2*z/(12*z - 1), (z - 1/6)/(2*z - 1/6)))
(7, (1/2, 0))
(8, ((f + 2*z)/(2*f + 2), (f + 2*z)/(2*f + 2)))
(9, ((-z)/(f - 1), (-z)/(f - 1)))

If wall_crossing_method=’mathematica’ in cpl_regions_with_thetas_and_components(), then the output is:

(1, (z/(15*z - 2), (6*z - 1)/(15*z - 2)))
(2, ((-2*z)/(f - 1), 0))
(3, (1/4, 1/4))
(4, ((f + z)/(f + 1), z/(f + 1)))
(5, ((-z)/(f + 2*z - 1), 0))
(6, (2*z/(12*z - 1), (z - 1/6)/(2*z - 1/6)))
(7, ((f + 2*z)/(2*f + 2), (f + 2*z)/(2*f + 2)))
(8, (1/2, 0))
(9, ((-z)/(f - 1), (-z)/(f - 1)))
cutgeneratingfunctionology.igp.save_plot(q, hh, destdir='./sym_mode_2d_diagrams/')
cutgeneratingfunctionology.igp.scan_domains_of_moves(functional_directed_moves)
cutgeneratingfunctionology.igp.scan_zero_perturbation_point(x)
cutgeneratingfunctionology.igp.scan_zero_perturbation_points(zero_perturbation_points)
cutgeneratingfunctionology.igp.search_kslope_example(k_slopes, q, f, mode='combined')

Search for extreme functions that have required number of slope values. Return integer function values at breakpoints.

  • If mode is (defaut) ‘combined’, use paint_complex_combined() to paint a few triangles, then enumerate vertex-functions;
  • If mode is ‘heuristic’, use paint_complex_heuristic() to paint;
  • If mode is ‘naive’, enumerate vertex-fuctions and check whether all invervals are covered;
  • If mode is ‘sym’, restrict to the special 2d-diagram such as kzh_6_slope_fulldim_covers_2() and kzh_6_slope_fulldim_covers_3():
    • \(q = 2f\), \(f \bmod 2 = 1\);
    • symmetry between left and right parts of f;
    • 2d-diagram is white in the middle;

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: q=5; f=3; k_slopes = 2;
sage: list(search_kslope_example(k_slopes, q, f, mode='combined'))
[(0, 2, 4, 6, 3, 0), (0, 3, 1, 4, 2, 0)]
cutgeneratingfunctionology.igp.self_orthogonal_binary_codes
cutgeneratingfunctionology.igp.set_subadd_lower_bound(xxx_todo_changeme2)

Set the triangle to explicitly white by adding the constraint \(\sum_{(x,y) \in \text{vertices}}{\Delta\pi(x,y)} \geq \epsilon\).

cutgeneratingfunctionology.igp.show_approximations(function, pi_pwl, pi_comb, pi_fill_in, pi_sym)

Subfunction of the procedure symmetric_2_slope_fill_in().

cutgeneratingfunctionology.igp.show_plot(graphics, show_plots, tag, object=None, **show_kwds)

Display or save graphics.

show_plots can be one of:

  • False (do nothing),
  • True (use show to display on screen),
  • a string (file name format such as “FILENAME-%s.pdf”, where %s is replaced by tag.
cutgeneratingfunctionology.igp.simple_finite_dimensional_extremality_test(fn, show_plots=False, f=None, oversampling=3, order=None, show_all_perturbations=False, full_certificates=True)

Simple finite dimensional extremality test for fn that does not go through the whole machinery of covered intervals etc., but rather sets up a grid 1/mq, where q is the lcm of the breakpoint denominator and m is the oversampling factor. We prove in Equivariant I that m = 4 always is enough for continuous functions; in the survey we prove that, in fact, m = 3 (the default) suffices.

Instead of the oversampling factor, the code also allows to specify a different grid using parameter order; this is particularly useful for the irrational case.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # to disable output in automatic tests.
sage: h = piecewise_function_from_breakpoints_and_values([0, 1/2, 1], [0, 1, 0])
sage: simple_finite_dimensional_extremality_test(h, False)
True
sage: simple_finite_dimensional_extremality_test(drlm_not_extreme_1(), False, oversampling=1)
True
sage: simple_finite_dimensional_extremality_test(drlm_not_extreme_1(), False, oversampling=2)
False
sage: simple_finite_dimensional_extremality_test(minimal_has_uncovered_interval(), False)
False
sage: simple_finite_dimensional_extremality_test(drlm_not_extreme_2(), False)
False
cutgeneratingfunctionology.igp.simplicial_complexes

Catalog of simplicial complexes

There are two main types: manifolds and examples related to graph theory.

For manifolds, there are functions defining the \(n\)-sphere for any \(n\), the torus, \(n\)-dimensional real projective space for any \(n\), the complex projective plane, surfaces of arbitrary genus, and some other manifolds, all as simplicial complexes.

Aside from surfaces, this file also provides functions for constructing some other simplicial complexes: the simplicial complex of not-\(i\)-connected graphs on \(n\) vertices, the matching complex on n vertices, the chessboard complex for an \(n\) by \(i\) chessboard, and others. These provide examples of large simplicial complexes; for example, simplicial_complexes.NotIConnectedGraphs(7,2) has over a million simplices.

All of these examples are accessible by typing simplicial_complexes.NAME, where NAME is the name of the example.

  • BarnetteSphere()
  • BrucknerGrunbaumSphere()
  • ChessboardComplex()
  • ComplexProjectivePlane()
  • DunceHat()
  • K3Surface()
  • KleinBottle()
  • MatchingComplex()
  • MooreSpace()
  • NotIConnectedGraphs()
  • PoincareHomologyThreeSphere()
  • PseudoQuaternionicProjectivePlane()
  • RandomComplex()
  • RandomTwoSphere()
  • RealProjectivePlane()
  • RealProjectiveSpace()
  • RudinBall()
  • ShiftedComplex()
  • Simplex()
  • Sphere()
  • SumComplex()
  • SurfaceOfGenus()
  • Torus()
  • ZieglerBall()

You can also get a list by typing simplicial_complexes. and hitting the TAB key.

EXAMPLES:

sage: S = simplicial_complexes.Sphere(2) # the 2-sphere
sage: S.homology()
{0: 0, 1: 0, 2: Z}
sage: simplicial_complexes.SurfaceOfGenus(3)
Triangulation of an orientable surface of genus 3
sage: M4 = simplicial_complexes.MooreSpace(4)
sage: M4.homology()
{0: 0, 1: C4, 2: 0}
sage: simplicial_complexes.MatchingComplex(6).homology()
{0: 0, 1: Z^16, 2: 0}
cutgeneratingfunctionology.igp.simplicial_sets

Catalog of simplicial sets

This provides pre-built simplicial sets:

  • the \(n\)-sphere and \(n\)-dimensional real projective space, both (in theory) for any positive integer \(n\). In practice, as \(n\) increases, it takes longer to construct these simplicial sets.
  • the \(n\)-simplex and the horns obtained from it. As \(n\) increases, it takes much longer to construct these simplicial sets, because the number of nondegenerate simplices increases exponentially in \(n\). For example, it is feasible to do simplicial_sets.RealProjectiveSpace(100) since it only has 101 nondegenerate simplices, but simplicial_sets.Simplex(20) is probably a bad idea.
  • \(n\)-dimensional complex projective space for \(n \leq 4\)
  • the classifying space of a finite multiplicative group or monoid
  • the torus and the Klein bottle
  • the point
  • the Hopf map: this is a pre-built morphism, from which one can extract its domain, codomain, mapping cone, etc.

All of these examples are accessible by typing simplicial_sets.NAME, where NAME is the name of the example. Type simplicial_sets.[TAB] for a complete list.

EXAMPLES:

sage: RP10 = simplicial_sets.RealProjectiveSpace(8)
sage: RP10.homology()
{0: 0, 1: C2, 2: 0, 3: C2, 4: 0, 5: C2, 6: 0, 7: C2, 8: 0}

sage: eta = simplicial_sets.HopfMap()
sage: S3 = eta.domain()
sage: S2 = eta.codomain()
sage: S3.wedge(S2).homology()
{0: 0, 1: 0, 2: Z, 3: Z}
cutgeneratingfunctionology.igp.singleton_piece(x, y)
cutgeneratingfunctionology.igp.slope_variable(k)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: slope_variable(3)
's_3'
cutgeneratingfunctionology.igp.slopes_intervals_dict(fn, ignore_nonlinear=False)

Returns a dictionary that maps a slope value to a list of intervals with that slope.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO)
sage: slopes_intervals_dict(gmic(1/2))[2]
[(0, 1/2)]
cutgeneratingfunctionology.igp.solve_mip_with_random_objective_function(mip)
cutgeneratingfunctionology.igp.sort_pair(x, y)
cutgeneratingfunctionology.igp.stab_int_length(x)
cutgeneratingfunctionology.igp.strategic_delta_pi_min(fn, approximation='constant', norm='one', branching_point_selection='median')

Return the minimum of delta_pi.

cutgeneratingfunctionology.igp.stuff_with_random_irrational_function()
cutgeneratingfunctionology.igp.subadditivity_test(fn, full_certificates=True)

Check if fn is subadditive.

cutgeneratingfunctionology.igp.superadditive_lifting_function_from_group_function(fn, f=None)

Convert a standard representation ‘phi’ (a superadditive quasiperiodic function) from a group representation ‘fn’ (a subadditive periodic function).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.INFO) # Suppress output in automatic tests.
sage: fn = mlr_cpl3_d_3_slope(r0=1/7, z1=1/7)
sage: phi = superadditive_lifting_function_from_group_function(fn)
sage: phi_expected = FastPiecewise([[(0, 1/7), FastLinearFunction(0,0)], [(1/7, 2/7), FastLinearFunction(7/4, -1/4)], [(2/7, 3/7), FastLinearFunction(7/12, 1/12)], [(3/7, 5/7), FastLinearFunction(7/6, -1/6)], [(5/7, 6/7), FastLinearFunction(7/12, 1/4)], [(6/7, 1), FastLinearFunction(7/4, -3/4)]])
sage: phi == phi_expected
True
sage: q = plot(phi)
cutgeneratingfunctionology.igp.sym_2_slope_fill_in_given_q(pi_pwl, f, q, epsilon)

Subfunction of the procedure symmetric_2_slope_fill_in().

cutgeneratingfunctionology.igp.symbolic_subbadditivity_constraints_of_cpl_given_region(r)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: regions = cpl_regions_from_arrangement_of_bkpts(3, cpleq=True)  # long time - 30s
sage: r = regions[0]                                                  # long time
sage: symbolic_subbadditivity_constraints_of_cpl_given_region(r)      # long time
[1/f,
 (-o1 + 1)/f,
 (-o1 - o2 + 1)/f,
 (o1 + o2)/f,
 o1/f,
 (-2*o1 + 1)/f,
 (-2*o1 - o2 + 1)/f,
 o2/f,
 (-2*o1 - 2*o2 + 1)/f,
 (o1 - o2)/f,
 (f*o1 + f*o2 + 2*z - o1 - o2)/(f^2 + 4*f*z - f),
 (f*o1 + 2*z*o1 - 2*z*o2 + z - o1)/(f^2 + 4*f*z - f)]
cutgeneratingfunctionology.igp.symmetric_2_slope_fill_in(function, epsilon, show_plots=False, f=None)

Given a continuous strong minimal function for the Gomory and Johnson infinite group problem with \(f \in Q\setminus Z\), return an extreme 2-slope function pi_ext that approximates function with infinity norm distance less than epsilon.

See Theorem 2 [dense-2-slope].

See also: symmetric_2_slope_fill_in_irrational.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: function = piecewise_function_from_breakpoints_and_values([0,1/5,2/5,3/5,4/5,1],[0,1/2,1,1/2,1/2, 0])
sage: extremality_test(function)
False
sage: epsilon = 1/10
sage: pi_sym = symmetric_2_slope_fill_in(function, epsilon)
sage: find_infinity_norm_distance(function, pi_sym) <= epsilon
True
sage: number_of_slopes(pi_sym)
2
sage: extremality_test(pi_sym)
True

Show plots:

sage: from cutgeneratingfunctionology.igp import *
sage: pi_sym = symmetric_2_slope_fill_in(function, 1/8, True) #not tested
sage: pi_sym = symmetric_2_slope_fill_in(function, 1/10, True) #not tested
Reference:
[dense-2-slope] A. Basu, R. Hildebrand, and M. Molinaro, Minimal cut-generating functions are nearly extreme, 2015, http://www.ams.jhu.edu/~abasu9/papers/dense-2-slope.pdf, to appear in Proceedings of IPCO 2016.
cutgeneratingfunctionology.igp.symmetric_2_slope_fill_in_irrational(function, epsilon, show_plots=False, f=None)

Given a continuous piecewise linear strong minimal function for the Gomory and Johnson infinite group problem, return an extreme 2-slope function pi_ext that approximates function with infinity norm distance less than epsilon.

This construction is a variant of Theorem 2 [dense-2-slope] (implemented in symmetric_2_slope_fill_in), proposed by Yuan Zhou (2015, unpublished):

It turns out that if \(\pi\) is piecewise linear, then in Theorem 2, \(b\) does not have to be a rational number. This is because when \(q\) is large enough (precisely, when \(1/q \leq \delta/2\) and \(\max\{s^+, |s^-|\}/q \leq \epsilon/2\), where \(s^+\) and \(s^-\) are the most positive and the most negative slopes of pi_comb), doing a 2-slope fill-in on the pi_comb restricted to the grid (1/q)Z will give a pi_fill_in that always has pi_fill_in(\(b\))=1, even though \(b\) is irrational and thus is not in (1/q)Z. For the same reason, \(\delta\) and other breakpoints of pi_comb in lemma 6 do not have to be rational numbers either. To ensure pi_sym is well defined, consider \(U=(1/q)Z \cup \{b/2, (b+1)/2\}\) when constructing pi_fill_in. The proof follows verbatim.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: function = piecewise_function_from_breakpoints_and_values([0,2/5+1/sqrt(2)/10,3/5+1/sqrt(2)/10,4/5,1],[0,1,1/2,1/2,0])
sage: minimality_test(function)
True
sage: epsilon = 1/10
sage: pi_sym = symmetric_2_slope_fill_in_irrational(function, epsilon)
sage: find_infinity_norm_distance(function, pi_sym) <= epsilon
True
sage: number_of_slopes(pi_sym)
2
sage: extremality_test(pi_sym)
True

sage: h = drlm_backward_3_slope(f=1/sqrt(61), bkpt=3/sqrt(61))
sage: minimality_test(h)
True
sage: extremality_test(h)
False
sage: pi_sym = symmetric_2_slope_fill_in_irrational(h, 1/10)
sage: find_infinity_norm_distance(h, pi_sym) <= 1/10
True
sage: number_of_slopes(pi_sym)
2
sage: extremality_test(pi_sym)
True

Show plots:

sage: pi_sym = symmetric_2_slope_fill_in_irrational(function, 1/10, True) #not tested
Reference:
[dense-2-slope] A. Basu, R. Hildebrand, and M. Molinaro, Minimal cut-generating functions are nearly extreme, 2015, http://www.ams.jhu.edu/~abasu9/papers/dense-2-slope.pdf, to appear in Proceedings of IPCO 2016.
cutgeneratingfunctionology.igp.symmetric_test(fn, f, full_certificates=True)

Check if fn is symmetric.

cutgeneratingfunctionology.igp.test_maximal_additive_faces(fn, **kwds)

Check the difference of maximal additive faces generated by naive and faster algorithms.

cutgeneratingfunctionology.igp.tests

TESTS:

Test the deprecation warnings:

sage: tests.CompleteMatchings
doctest:warning
...
DeprecationWarning:
Importing CompleteMatchings from here is deprecated. If you need to use it, please import it directly from sage.tests.arxiv_0812_2725
See https://trac.sagemath.org/27337 for details.
<function CompleteMatchings at ...>
sage: tests.modsym
doctest:warning
...
DeprecationWarning:
Importing modsym from here is deprecated. If you need to use it, please import it directly from sage.modular.modsym.tests
See https://trac.sagemath.org/27337 for details.
<class ...sage.modular.modsym.tests.Test...>
cutgeneratingfunctionology.igp.ticks_keywords(function, y_ticks_for_breakpoints=False, extra_xticks=[], extra_yticks=[1])

Compute plot keywords for displaying the ticks.

cutgeneratingfunctionology.igp.time_to_find_first_extreme(k, q, f, mode='combined')
cutgeneratingfunctionology.igp.transform_coho_interval(interval, shift, divisor)

Shift interval by shift and then divide it by divisor.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: transform_coho_interval([1, 3], 1, 2)
[1, 2]
sage: transform_coho_interval([1, 3], 1, -1)
[-4, -2]
sage: transform_coho_interval(right_open_interval(-1,1), 1, 2)==right_open_interval(0, 1)
True
sage: transform_coho_interval(right_open_interval(-1,1), 1, -1)==left_open_interval(-2, 0)
True
cutgeneratingfunctionology.igp.transform_piece(piece, shift, divisor)

Transform piece = (interval, function) of a piecewise function by shifting interval by shift and then dividing it by divisor.

cutgeneratingfunctionology.igp.transform_piece_to_interval(piece, new_interval, old_interval=None)
cutgeneratingfunctionology.igp.translation_i_variable(q, x, z, i)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: translation_i_variable(7, 1/7, 3/7, 2)
't_1_3_2'
cutgeneratingfunctionology.igp.translation_pair(x, y, q)

Return the translation (2 components (first < second), they are connected) corresponding to the horizontal edge ( (x, y), (x + 1, y) )

cutgeneratingfunctionology.igp.tuple_of_deltafn(n, linfun)

Convert a Linear Function (with variable index < n) to a n-tuple, dividing by the gcd of all elements.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: fn = pattern_setup_lp(1, more_ini_additive=False, objcoef=None)
sage: linfun = fn[5]; linfun
x_0 + 3*x_1 + x_2
sage: tuple_of_deltafn(3, linfun)
(1, 3, 1)
sage: linfun = fn[18]+fn[19]-fn[37]; linfun
2*x_0 + 8*x_1 + 6*x_2
sage: tuple_of_deltafn(3, linfun)
(1, 4, 3)
cutgeneratingfunctionology.igp.two_slope_fill_in(function, order=None)

Extend the given function to make it a 2-slope function in the infinite group problem.

function may be a function of a finite (cyclic) group problem, represented as a FastPiecewise with singleton intervals within [0,1] as its parts.

(function is actually allowed, however, to be more general; it can be any FastPiecewise. When the given function is a function for the infinite group problem, its restrict_to_finite_group with order=order would be considered.)

[Johnson (1974), section 7; see also Gomory–Johnson (1972, I, II)] If function is a subadditive valid function for the finite group problem, then its 2-slope fill-in is a subadditive valid function for the infinite group problem.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: h_dis = discrete_function_from_points_and_values([0,1/5,2/5,3/5,4/5,1],[0,1/2,1,1/2,1/2,0])
sage: subadditivity_test(h_dis)
True
sage: h_fill = two_slope_fill_in(h_dis)
sage: subadditivity_test(h_fill)
True
sage: number_of_slopes(h_fill)
2

sage: gmic() == two_slope_fill_in(gmic())
True
cutgeneratingfunctionology.igp.two_slope_fill_in_extreme(fn, epsilon=1, show_plots=False)

Input: a (continuous) minimal function fn for the infinite group problem, or a discrete minimal function for the finite group problem, with rational breakpoints in 1/qZ and rational function values at the breakpoints. (weaker condition: rational breakpoints and the set {x: fn_interpolation(x)=1/2} is the union of some rational x and intervals.) Output: a two-slope extreme function fn2 such that fn2 = fn on 1/mqZ (and the infinity norm distance between fn and fn2 is less than epsilon).

The function is obtained by putting upward and downward tents with slopes equal to the limiting slopes of the input function on top of some intervals between the points of the finite group of order mq = injective_2_slope_fill_in_order.

This construction was introduced in [KoppeZ19].

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: logging.disable(logging.WARN)
sage: fn = discrete_function_from_points_and_values([0,1/5,2/5,3/5,4/5,1],[0,1/2,1,1/2,1/2,0])
sage: minimality_test(fn)
True
sage: extremality_test(fn)
False
sage: fn2 = injective_2_slope_fill_in(fn)
sage: extremality_test(fn2)
True

sage: fn = not_extreme_1()
sage: fn2 = injective_2_slope_fill_in(fn)
sage: extremality_test(fn2)
True
sage: find_infinity_norm_distance (fn, fn2)
1/12
sage: fn_app = injective_2_slope_fill_in(fn, epsilon=1/20)
sage: finite_group_order_from_function_f_oversampling_order(fn_app)
160
sage: minimality_test(fn_app)
True
sage: find_infinity_norm_distance (fn, fn_app)
1/48

sage: fn = gmic()
sage: fn2 = injective_2_slope_fill_in(fn)
sage: fn == fn2
True

sage: fn =restrict_to_finite_group(minimal_has_uncovered_interval(), order=8)
sage: fn2 = injective_2_slope_fill_in(fn)
sage: extremality_test(fn2)
True

sage: fn =restrict_to_finite_group(minimal_has_uncovered_interval(), order=16)
sage: fn2 = injective_2_slope_fill_in(fn)
sage: minimality_test(fn2)
True

sage: fn = minimal_has_uncovered_breakpoints()
sage: fn2 = injective_2_slope_fill_in(fn)
sage: minimality_test(fn2)
True

sage: fn = example7slopecoarse2()
sage: fn2 = injective_2_slope_fill_in(fn)
sage: number_of_slopes(fn2)
2
sage: minimality_test(fn2)
True

sage: fn = lift_until_extreme_only_works_with_strict_subset_L()
sage: fn2 = injective_2_slope_fill_in(fn)
sage: number_of_slopes(fn2)
2
sage: minimality_test(fn2)
True
sage: extremality_test(fn2, full_certificates=False)
True

sage: fn = lift_until_extreme_default_style_bug_example()
sage: fn2 = injective_2_slope_fill_in(fn)  # q=52; q2=order=4004
sage: finite_group_order_from_function_f_oversampling_order(fn2)
12012

Systematic testing:

sage: q = 10; f = 1; show_plots=False
sage: for h in generate_extreme_functions_for_finite_group(q, f): #long time
....:     if number_of_slopes(h) > 2:
....:         if show_plots: plot_2d_diagram(h, colorful=True)
....:         order = injective_2_slope_fill_in_order(h)
....:         if order < 1000:
....:             i = injective_2_slope_fill_in(h, show_plots=show_plots)
....:             assert minimality_test(i)
cutgeneratingfunctionology.igp.uncovered_intervals_from_covered_components(covered_components)
cutgeneratingfunctionology.igp.uncovered_intervals_from_covered_intervals(covered_components)
cutgeneratingfunctionology.igp.unique_list(iterator)

Returns the list of the elements in the iterator without repetition.

cutgeneratingfunctionology.igp.update_around_green_face(q, f, vertices_color, faces_color, covered_intervals, xxx_todo_changeme)

Subfunction of paint_complex_combined_mip(), etc.

Painting triangle (x, y, w) from white to green induces some new green triangles around it. Update vertices_color, faces_color, correspondingly. If there is non_candidate among new green faces, return (False, None, changed_vertices, changed_faces). Otherwise, return (True, updated covered_intervals, changed_vertices, changed_faces).

cutgeneratingfunctionology.igp.update_around_green_vertex(q, xxx_todo_changeme1, vertices_color, covered_intervals, uncovered_intervals)

Painting vertex (x, y) from white to green induces some new green triangles and edges around this vertex. Returns new covered_intervals and uncovered_intervals corresponding to these changes.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: q = 5; f = 3;
sage: vertices_color = initial_vertices_color(q, f);
sage: (covered_intervals, uncovered_intervals) = ([set([0, 2]), set([3, 4])], [set([1])]);
sage: x = 1; y = 1;  vertices_color[x, y] = 0;
sage: update_around_green_vertex(q, (x, y), vertices_color, covered_intervals, uncovered_intervals)
([{3, 4}, {0, 1, 2}], [])
sage: vertices_color = initial_vertices_color(q, f);
sage: x = 2; y = 2; vertices_color[x,y]=0
sage: update_around_green_vertex(q, (x, y), vertices_color, covered_intervals, uncovered_intervals)
([{0, 2}, {1, 3, 4}], [])
cutgeneratingfunctionology.igp.update_covered_uncovered_by_adding_edge(last_covered_intervals, last_uncovered_intervals, to_merge_set, q)

Computes incrementally new covered_intervals and new uncovered_intervals, resulting from adding a new green edge that connects the elements in to_merge_set.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: last_covered_intervals = [set([0,2]), set([3,4])]
sage: last_uncovered_intervals = [set([1])]
sage: to_merge_set = set([0, 1])
sage: update_covered_uncovered_by_adding_edge(last_covered_intervals, last_uncovered_intervals, to_merge_set, 5)
([{3, 4}, {0, 1, 2}], [])
cutgeneratingfunctionology.igp.update_covered_uncovered_by_adding_face(last_covered_intervals, last_uncovered_intervals, face, q)

Computes incrementally new covered_intervals and new uncovered_intervals by adding a new green triangle.

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: last_covered_intervals = [set([0,2]), set([3,4])]
sage: last_uncovered_intervals = [set([1])]
sage: face = (1, 1, 1)
sage: update_covered_uncovered_by_adding_face(last_covered_intervals, last_uncovered_intervals, face, 5)
([{0, 2}, {1, 3, 4}], [])
cutgeneratingfunctionology.igp.update_directly_cover(q, x, add_v, was_face, was_connected, covered_intervals, uncovered_intervals)

Subroutine of all_intervals_covered().

Can the interval [x, x+1]/q be directly covered? Bail out if x is covered. Update was_face, was_connected. Return new covered_intervals and uncovered_intervals.

cutgeneratingfunctionology.igp.update_implied_faces_mip(q, f, vertices_color, changed_vertices, faces_color, changed_faces, covered_intervals, sym=False)

Subfunction of paint_complex_combined_mip().

Look for implied additive vertices and faces, given MILP m. Update vertices_color, changed_vertices, faces_color, changed_faces If there is non_candidate among implied green faces, return False. Otherwise, return True and updated covered_intervals.

cutgeneratingfunctionology.igp.update_implied_faces_pol(q, f, vertices_color, changed_vertices, faces_color, changed_faces, covered_intervals, polytope)

Subfunction of paint_complex_combined_pol(), etc.

Look for implied additive vertices and faces, given PPL polytope. Update vertices_color, changed_vertices, faces_color, changed_faces and polytope If there is non_candidate among implied green faces, return False. Otherwise, return True and updated covered_intervals.

cutgeneratingfunctionology.igp.update_undirectly_cover(q, x, add_v, was_face, was_connected, covered_intervals, uncovered_intervals)

Subroutine of all_intervals_covered().

Can the interval [x, x+1]/q be undirectly covered? Bail out if all covered. Update was_face, was_connected. Return new covered_intervals and uncovered_intervals.

cutgeneratingfunctionology.igp.valuations

x.__init__(…) initializes x; see help(type(x)) for signature

cutgeneratingfunctionology.igp.values_of_delta_pi_over_grid(fn, q)

Return a matrix representing the values of delta pi over the grid (1/q)Z*(1/q)Z.

cutgeneratingfunctionology.igp.variable_face(q, s)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: q=7;
sage: variable_face(q, 'h_1_1')
<Face ([1/7, 2/7], [1/7], [2/7, 3/7])>
sage: variable_face(q, 'v_1_1')
<Face ([1/7], [1/7, 2/7], [2/7, 3/7])>
sage: variable_face(q, 'd_1_1')
<Face ([1/7, 2/7], [1/7, 2/7], [3/7])>
sage: variable_face(q, 'l_1_1')
<Face ([1/7, 2/7], [1/7, 2/7], [2/7, 3/7])>
sage: variable_face(q, 'u_1_1')
<Face ([1/7, 2/7], [1/7, 2/7], [3/7, 4/7])>
sage: variable_face(q, 'p_2_2')
<Face ([2/7], [2/7], [4/7])>
cutgeneratingfunctionology.igp.variable_vertex(q, s)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: variable_vertex(7, 'p_1_2')
(1/7, 2/7)
cutgeneratingfunctionology.igp.vertex_enumeration(polytope, exp_dim=-1, vetime=False)

Returns the vertices of the polytope.

  • Do preprocessing if exp_dim >= igp.exp_dim_prep, i.e., call the function redund provided by lrslib to remove redundant inequalities.
  • If normaliz is installed, use it to enumerate vertices after preprocessing, else use lrs vertex enumeration if exp_dim >= exp_dim_lrs.
  • Use ppl vertex enumeration for small dimensions.
  • Print the vertex enumeration running time if vetime is True.

EXAMPLE:

sage: from cutgeneratingfunctionology.igp import *
sage: x = Variable(0)
sage: y = Variable(1)
sage: cs = Constraint_System()
sage: cs.insert(x >= 0)
sage: cs.insert(y >= 0)
sage: cs.insert(x <= 1)
sage: cs.insert(y <= 1)
sage: polytope = C_Polyhedron(cs)
sage: vertex_enumeration(polytope)
Generator_System {point(1/1, 0/1), point(1/1, 1/1), point(0/1, 1/1), point(0/1, 0/1)}
cutgeneratingfunctionology.igp.vertex_variable(q, v)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: vertex_variable(7, (1/7, 2/7))
'p_1_2'
cutgeneratingfunctionology.igp.vertices_of_face(face)

Return 3 vertices of the given triangle face.

cutgeneratingfunctionology.igp.verts(I1, J1, K1)

Computes the vertices based on \(I, J\) and \(K\).

cutgeneratingfunctionology.igp.white_strip(q, f, x, add_v)

Subroutine of all_intervals_covered().

Check if column and diagonal strip of x are all white. If so, x cannot be covered. Vertex function is not extreme.

cutgeneratingfunctionology.igp.write_lpfile(q, f, kslopes, maxstep=None, m=0, type_cover=None, weights=[])

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: write_lpfile(37, 25/37, 5, m=12, type_cover='fulldim') # not tested
cutgeneratingfunctionology.igp.write_lpfile_2q(q, f, a, kslopes, maxstep=None, m=0)

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: write_lpfile_2q(37, 25/37, 11/37, 4, maxstep=2, m=4) # not tested
cutgeneratingfunctionology.igp.write_lrs_format_cs(cs, fname=None)
cutgeneratingfunctionology.igp.write_lrs_ine(q, f, destdir=None)
cutgeneratingfunctionology.igp.write_normaliz_format_cs(cs, fname=None)
cutgeneratingfunctionology.igp.write_normaliz_in(q, f, destdir=None)
cutgeneratingfunctionology.igp.write_normaliz_remove_redund_in(q, f)
cutgeneratingfunctionology.igp.write_panda_format_cs(cs, fname=None, newcode=True)
cutgeneratingfunctionology.igp.write_porta_format_cs(cs, q=None, f=None, fname=None)
cutgeneratingfunctionology.igp.write_porta_ieq(q, f, destdir=None)
cutgeneratingfunctionology.igp.write_stats_detail(q, fdestdir=None)

Provides data for scatter plot.

cutgeneratingfunctionology.igp.x_y_swapped_face(face)
cutgeneratingfunctionology.igp.zero_perturbation_partial_function(components, zero_perturbation_points)

Compute the partial function for which the perturbation, modulo perturbations that are interpolations of values at breakpoints, is known to be zero.

cutgeneratingfunctionology.igp.zhou_two_sided_discontinuous_cannot_assume_any_continuity()

This function is two-sided discontinuous at the origin. The extremality test then cannot assume any left or right continuity of the perturbation function at the breakpoints, even if such one-sided continuity is present in the function.

This example has been constructed by Yuan Zhou (2014).

EXAMPLES:

sage: from cutgeneratingfunctionology.igp import *
sage: h = zhou_two_sided_discontinuous_cannot_assume_any_continuity()
sage: extremality_test(h)
False