Skip to content

Commit c0e49a9

Browse files
committed
Trac #21318: decorator minimize_result
1 parent 73fe339 commit c0e49a9

File tree

1 file changed

+112
-19
lines changed

1 file changed

+112
-19
lines changed

src/sage/combinat/recognizable_series.py

Lines changed: 112 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@
7575
# http://www.gnu.org/licenses/
7676
#*****************************************************************************
7777

78+
from functools import wraps
79+
7880
from sage.misc.cachefunc import cached_method
7981
from sage.misc.superseded import experimental
8082
from sage.structure.element import Element
@@ -297,6 +299,75 @@ def prefix_set(self):
297299
if p + a not in self.elements]
298300

299301

302+
def minimize_result(operation):
303+
r"""
304+
A decorator for operations that enables control of
305+
automatic minimization on the result.
306+
307+
INPUT:
308+
309+
- ``operation`` -- a method
310+
311+
OUTPUT:
312+
313+
A method with the following additional argument:
314+
315+
- ``minimize`` -- (default: ``None``) a boolean or ``None``.
316+
If ``True``, then :meth:`minimized` is called after the operation,
317+
if ``False``, then not. If this argument is ``None``, then
318+
the default specified by the parent's ``minimize_results`` is used.
319+
320+
TESTS::
321+
322+
sage: from sage.combinat.recognizable_series import minimize_result
323+
sage: class P(object):
324+
....: pass
325+
sage: p = P()
326+
sage: class S(object):
327+
....: def __init__(self, s):
328+
....: self.s = s
329+
....: def __repr__(self):
330+
....: return self.s
331+
....: def parent(self):
332+
....: return p
333+
....: def minimized(self):
334+
....: return S(self.s + ' minimized')
335+
....: @minimize_result
336+
....: def operation(self):
337+
....: return S(self.s + ' result')
338+
339+
sage: p.minimize_results = True
340+
sage: S('some').operation()
341+
some result minimized
342+
sage: S('some').operation(minimize=True)
343+
some result minimized
344+
sage: S('some').operation(minimize=False)
345+
some result
346+
347+
sage: p.minimize_results = False
348+
sage: S('some').operation()
349+
some result
350+
sage: S('some').operation(minimize=True)
351+
some result minimized
352+
sage: S('some').operation(minimize=False)
353+
some result
354+
"""
355+
@wraps(operation)
356+
def minimized(self, *args, **kwds):
357+
minimize = kwds.pop('minimize', None)
358+
if minimize is None:
359+
minimize = self.parent().minimize_results
360+
361+
result = operation(self, *args, **kwds)
362+
363+
if minimize:
364+
result = result.minimized()
365+
366+
return result
367+
368+
return minimized
369+
370+
300371
class RecognizableSeries(Element):
301372
def __init__(self, parent, mu, left, right):
302373
r"""
@@ -1023,8 +1094,8 @@ def dimension(self):
10231094
"""
10241095
return self.mu.first().nrows()
10251096

1026-
1027-
def _add_(self, other, minimize=True):
1097+
@minimize_result
1098+
def _add_(self, other):
10281099
r"""
10291100
Return the sum of this recognizable series and the ``other``
10301101
recognizable series.
@@ -1034,8 +1105,10 @@ def _add_(self, other, minimize=True):
10341105
- ``other`` -- a :class:`RecognizableSeries` with the same parent
10351106
as this recognizable series.
10361107
1037-
- ``minimize`` -- (default: ``True``) a boolean. If set, then
1038-
:meth:`minimized` is called after the operation.
1108+
- ``minimize`` -- (default: ``None``) a boolean or ``None``.
1109+
If ``True``, then :meth:`minimized` is called after the operation,
1110+
if ``False``, then not. If this argument is ``None``, then
1111+
the default specified by the parent's ``minimize_results`` is used.
10391112
10401113
OUTPUT:
10411114
@@ -1067,10 +1140,7 @@ def _add_(self, other, minimize=True):
10671140
vector(tuple(self.left) + tuple(other.left)),
10681141
vector(tuple(self.right) + tuple(other.right)))
10691142

1070-
if minimize:
1071-
return result.minimized()
1072-
else:
1073-
return result
1143+
return result
10741144

10751145

10761146
def _neg_(self):
@@ -1165,8 +1235,8 @@ def _lmul_(self, other):
11651235
P = self.parent()
11661236
return P.element_class(P, self.mu, other*self.left, self.right)
11671237

1168-
1169-
def hadamard_product(self, other, minimize=True):
1238+
@minimize_result
1239+
def hadamard_product(self, other):
11701240
r"""
11711241
Return the Hadamard product of this recognizable series
11721242
and the ``other`` recognizable series, i.e., multiply the two
@@ -1177,8 +1247,10 @@ def hadamard_product(self, other, minimize=True):
11771247
- ``other`` -- a :class:`RecognizableSeries` with the same parent
11781248
as this recognizable series.
11791249
1180-
- ``minimize`` -- (default: ``True``) a boolean. If set, then
1181-
:meth:`minimized` is called after the operation.
1250+
- ``minimize`` -- (default: ``None``) a boolean or ``None``.
1251+
If ``True``, then :meth:`minimized` is called after the operation,
1252+
if ``False``, then not. If this argument is ``None``, then
1253+
the default specified by the parent's ``minimize_results`` is used.
11821254
11831255
OUTPUT:
11841256
@@ -1259,10 +1331,7 @@ def hadamard_product(self, other, minimize=True):
12591331
vector(self.left.outer_product(other.left).list()),
12601332
vector(self.right.outer_product(other.right).list()))
12611333

1262-
if minimize:
1263-
return result.minimized()
1264-
else:
1265-
return result
1334+
return result
12661335

12671336

12681337

@@ -1349,7 +1418,8 @@ def __classcall__(cls, *args, **kwds):
13491418
def __normalize__(cls,
13501419
coefficient_ring=None,
13511420
alphabet=None, indices=None,
1352-
category=None):
1421+
category=None,
1422+
minimize_results=True):
13531423
r"""
13541424
Normalizes the input in order to ensure a unique
13551425
representation.
@@ -1405,10 +1475,10 @@ def __normalize__(cls,
14051475
from sage.categories.modules import Modules
14061476
category = category or Modules(coefficient_ring)
14071477

1408-
return (coefficient_ring, indices, category)
1478+
return (coefficient_ring, indices, category, minimize_results)
14091479

14101480
@experimental(trac_number=21202)
1411-
def __init__(self, coefficient_ring, indices, category):
1481+
def __init__(self, coefficient_ring, indices, category, minimize_results):
14121482
r"""
14131483
See :class:`RecognizableSeriesSpace` for details.
14141484
@@ -1421,12 +1491,17 @@ def __init__(self, coefficient_ring, indices, category):
14211491
- ``category`` -- (default: ``None``) the category of this
14221492
space
14231493
1494+
- ``minimize_results`` -- (default: ``True``) a boolean. If set, then
1495+
:meth:`RecognizableSeries.minimized` is automatically called
1496+
after performing operations.
1497+
14241498
TESTS::
14251499
14261500
sage: RecognizableSeriesSpace(ZZ, [0, 1])
14271501
Space of recognizable series on {0, 1} with coefficients in Integer Ring
14281502
"""
14291503
self._indices_ = indices
1504+
self._minimize_results_ = minimize_results
14301505
super(RecognizableSeriesSpace, self).__init__(
14311506
category=category, base=coefficient_ring)
14321507

@@ -1480,6 +1555,24 @@ def coefficient_ring(self):
14801555
"""
14811556
return self.base()
14821557

1558+
@property
1559+
def minimize_results(self):
1560+
r"""
1561+
A boolean indicating whether
1562+
:meth:`RecognizableSeries.minimized` is automatically called
1563+
after performing operations.
1564+
1565+
TESTS::
1566+
1567+
sage: RecognizableSeriesSpace(ZZ, [0, 1]).minimize_results
1568+
True
1569+
sage: RecognizableSeriesSpace(ZZ, [0, 1], minimize_results=True).minimize_results
1570+
True
1571+
sage: RecognizableSeriesSpace(ZZ, [0, 1], minimize_results=False).minimize_results
1572+
False
1573+
"""
1574+
return self._minimize_results_
1575+
14831576
def _repr_(self):
14841577
r"""
14851578
Return a representation string of this recognizable sequence

0 commit comments

Comments
 (0)