89
89
90
90
from numbers import Integral
91
91
92
- from sage .categories .fields import Fields
92
+ from sage .categories .rings import Rings
93
93
from sage .misc .inherit_comparison import InheritComparisonClasscallMetaclass
94
- from sage .rings .ring import CommutativeRing
95
94
from sage .rings .integer_ring import ZZ
96
95
from sage .rings .rational_field import QQ
97
96
from sage .rings .polynomial .polynomial_ring_constructor import PolynomialRing
100
99
from sage .rings .power_series_ring import PowerSeriesRing
101
100
from sage .rings .fraction_field import FractionField
102
101
from sage .structure .element import FieldElement , parent
102
+ from sage .structure .parent import Parent
103
103
from sage .structure .unique_representation import UniqueRepresentation
104
104
105
105
from sage .interfaces .gp import Gp
110
110
111
111
def CFiniteSequences (base_ring , names = None , category = None ):
112
112
r"""
113
- Return the ring of C-Finite sequences.
113
+ Return the commutative ring of C-Finite sequences.
114
114
115
115
The ring is defined over a base ring (`\ZZ` or `\QQ` )
116
116
and each element is represented by its ordinary generating function (ogf)
@@ -154,15 +154,15 @@ def CFiniteSequences(base_ring, names=None, category=None):
154
154
elif len (names ) > 1 :
155
155
raise NotImplementedError ("Multidimensional o.g.f. not implemented." )
156
156
if category is None :
157
- category = Fields ()
158
- if not ( base_ring in ( QQ , ZZ )) :
157
+ category = Rings (). Commutative ()
158
+ if base_ring not in [ QQ , ZZ ] :
159
159
raise ValueError ("O.g.f. base not rational." )
160
160
polynomial_ring = PolynomialRing (base_ring , names )
161
161
return CFiniteSequences_generic (polynomial_ring , category )
162
162
163
163
164
164
class CFiniteSequence (FieldElement ,
165
- metaclass = InheritComparisonClasscallMetaclass ):
165
+ metaclass = InheritComparisonClasscallMetaclass ):
166
166
r"""
167
167
Create a C-finite sequence given its ordinary generating function.
168
168
@@ -174,7 +174,7 @@ class CFiniteSequence(FieldElement,
174
174
175
175
OUTPUT:
176
176
177
- - A CFiniteSequence object
177
+ A CFiniteSequence object
178
178
179
179
EXAMPLES::
180
180
@@ -247,7 +247,7 @@ class CFiniteSequence(FieldElement,
247
247
@staticmethod
248
248
def __classcall_private__ (cls , ogf ):
249
249
r"""
250
- Ensures that elements created by :class:`CFiniteSequence` have the same
250
+ Ensure that elements created by :class:`CFiniteSequence` have the same
251
251
parent than the ones created by the parent itself and follow the category
252
252
framework (they should be instance of :class:`CFiniteSequences` automatic
253
253
element class).
@@ -299,9 +299,8 @@ def __classcall_private__(cls, ogf):
299
299
sage: f4.parent()
300
300
The ring of C-Finite sequences in y over Rational Field
301
301
"""
302
-
303
302
br = ogf .base_ring ()
304
- if not ( br in ( QQ , ZZ )) :
303
+ if br not in [ QQ , ZZ ] :
305
304
br = QQ # if the base ring of the o.g.f is not QQ, we force it to QQ and see if the o.g.f converts nicely
306
305
307
306
# trying to figure out the ogf variables
@@ -388,7 +387,6 @@ def __init__(self, parent, ogf):
388
387
# determine start values (may be different from _get_item_ values)
389
388
alen = max (self ._deg , num .degree () + 1 )
390
389
R = LaurentSeriesRing (br , parent .variable_name (), default_prec = alen )
391
- rem = num % den
392
390
if den != 1 :
393
391
self ._a = R (num / den ).list ()
394
392
else :
@@ -400,7 +398,7 @@ def __init__(self, parent, ogf):
400
398
401
399
self ._ogf = ogf
402
400
403
- def _repr_ (self ):
401
+ def _repr_ (self ) -> str :
404
402
"""
405
403
Return textual definition of sequence.
406
404
@@ -414,10 +412,8 @@ def _repr_(self):
414
412
if self ._deg == 0 :
415
413
if self .ogf () == 0 :
416
414
return 'Constant infinite sequence 0.'
417
- else :
418
- return 'Finite sequence ' + str (self ._a ) + ', offset = ' + str (self ._off )
419
- else :
420
- return 'C-finite sequence, generated by ' + str (self .ogf ())
415
+ return 'Finite sequence ' + str (self ._a ) + ', offset = ' + str (self ._off )
416
+ return 'C-finite sequence, generated by ' + str (self .ogf ())
421
417
422
418
def __hash__ (self ):
423
419
r"""
@@ -656,7 +652,8 @@ def __getitem__(self, key):
656
652
if isinstance (key , slice ):
657
653
m = max (key .start , key .stop )
658
654
return [self [ii ] for ii in range (* key .indices (m + 1 ))]
659
- elif isinstance (key , Integral ):
655
+
656
+ if isinstance (key , Integral ):
660
657
n = key - self ._off
661
658
if n < 0 :
662
659
return 0
@@ -679,8 +676,8 @@ def __getitem__(self, key):
679
676
den = P ((den * nden ).list ()[::2 ])
680
677
n //= 2
681
678
return wp + num [0 ] / den [0 ]
682
- else :
683
- raise TypeError ("invalid argument type" )
679
+
680
+ raise TypeError ("invalid argument type" )
684
681
685
682
def ogf (self ):
686
683
"""
@@ -726,14 +723,14 @@ def denominator(self):
726
723
"""
727
724
return self .ogf ().denominator ()
728
725
729
- def recurrence_repr (self ):
726
+ def recurrence_repr (self ) -> str :
730
727
"""
731
728
Return a string with the recurrence representation of
732
729
the C-finite sequence.
733
730
734
731
OUTPUT:
735
732
736
- - A string
733
+ A string
737
734
738
735
EXAMPLES::
739
736
@@ -892,7 +889,7 @@ def closed_form(self, n='n'):
892
889
return expr
893
890
894
891
895
- class CFiniteSequences_generic (CommutativeRing , UniqueRepresentation ):
892
+ class CFiniteSequences_generic (Parent , UniqueRepresentation ):
896
893
r"""
897
894
The class representing the ring of C-Finite Sequences
898
895
@@ -912,13 +909,13 @@ class CFiniteSequences_generic(CommutativeRing, UniqueRepresentation):
912
909
913
910
def __init__ (self , polynomial_ring , category ):
914
911
r"""
915
- Create the ring of CFiniteSequences over ``base_ring``
912
+ Create the ring of CFiniteSequences over ``base_ring``.
916
913
917
914
INPUT:
918
915
919
916
- ``base_ring`` -- the base ring for the o.g.f (either ``QQ`` or ``ZZ``)
920
917
- ``names`` -- an iterable of variables (should contain only one variable)
921
- - ``category`` -- the category of the ring (default: ``Fields ()``)
918
+ - ``category`` -- the category of the ring (default: ``Rings().Commutative ()``)
922
919
923
920
TESTS::
924
921
@@ -940,11 +937,14 @@ def __init__(self, polynomial_ring, category):
940
937
base_ring = polynomial_ring .base_ring ()
941
938
self ._polynomial_ring = polynomial_ring
942
939
self ._fraction_field = FractionField (self ._polynomial_ring )
943
- CommutativeRing .__init__ (self , base_ring , self ._polynomial_ring .gens (), category )
940
+ if category is None :
941
+ category = Rings ().Commutative ()
942
+ Parent .__init__ (self , base_ring , names = self ._polynomial_ring .gens (),
943
+ category = category )
944
944
945
945
def _repr_ (self ):
946
946
r"""
947
- Return the string representation of ``self``
947
+ Return the string representation of ``self``.
948
948
949
949
EXAMPLES::
950
950
@@ -956,7 +956,7 @@ def _repr_(self):
956
956
957
957
def _element_constructor_ (self , ogf ):
958
958
r"""
959
- Construct a C-Finite Sequence
959
+ Construct a C-Finite Sequence.
960
960
961
961
INPUT:
962
962
@@ -986,9 +986,9 @@ def _element_constructor_(self, ogf):
986
986
ogf = self .fraction_field ()(ogf )
987
987
return self .element_class (self , ogf )
988
988
989
- def ngens (self ):
989
+ def ngens (self ) -> int :
990
990
r"""
991
- Return the number of generators of ``self``
991
+ Return the number of generators of ``self``.
992
992
993
993
EXAMPLES::
994
994
@@ -1026,6 +1026,18 @@ def gen(self, i=0):
1026
1026
raise ValueError ("{} has only one generator (i=0)" .format (self ))
1027
1027
return self .polynomial_ring ().gen ()
1028
1028
1029
+ def gens (self ) -> tuple :
1030
+ """
1031
+ Return the generators of ``self``.
1032
+
1033
+ EXAMPLES::
1034
+
1035
+ sage: C.<x> = CFiniteSequences(QQ)
1036
+ sage: C.gens()
1037
+ (x,)
1038
+ """
1039
+ return (self .gen (0 ),)
1040
+
1029
1041
def an_element (self ):
1030
1042
r"""
1031
1043
Return an element of C-Finite Sequences.
@@ -1043,7 +1055,7 @@ def an_element(self):
1043
1055
x = self .gen ()
1044
1056
return self ((2 - x ) / (1 - x - x ** 2 ))
1045
1057
1046
- def __contains__ (self , x ):
1058
+ def __contains__ (self , x ) -> bool :
1047
1059
"""
1048
1060
Return ``True`` if x is an element of ``CFiniteSequences`` or
1049
1061
canonically coerces to this ring.
@@ -1194,7 +1206,7 @@ def guess(self, sequence, algorithm='sage'):
1194
1206
sage: r = C.guess([1,2,3,4,5])
1195
1207
Traceback (most recent call last):
1196
1208
...
1197
- ValueError: Sequence too short for guessing.
1209
+ ValueError: sequence too short for guessing
1198
1210
1199
1211
With Berlekamp-Massey, if an odd number of values is given, the last one is dropped.
1200
1212
So with an odd number of values the result may not generate the last value::
@@ -1205,10 +1217,11 @@ def guess(self, sequence, algorithm='sage'):
1205
1217
[1, 2, 4, 8, 16]
1206
1218
"""
1207
1219
S = self .polynomial_ring ()
1220
+
1208
1221
if algorithm == 'bm' :
1209
1222
from sage .matrix .berlekamp_massey import berlekamp_massey
1210
1223
if len (sequence ) < 2 :
1211
- raise ValueError ('Sequence too short for guessing. ' )
1224
+ raise ValueError ('sequence too short for guessing' )
1212
1225
R = PowerSeriesRing (QQ , 'x' )
1213
1226
if len (sequence ) % 2 :
1214
1227
sequence .pop ()
@@ -1217,10 +1230,11 @@ def guess(self, sequence, algorithm='sage'):
1217
1230
numerator = R (S (sequence ) * denominator , prec = l ).truncate ()
1218
1231
1219
1232
return CFiniteSequence (numerator / denominator )
1220
- elif algorithm == 'pari' :
1233
+
1234
+ if algorithm == 'pari' :
1221
1235
global _gp
1222
1236
if len (sequence ) < 6 :
1223
- raise ValueError ('Sequence too short for guessing. ' )
1237
+ raise ValueError ('sequence too short for guessing' )
1224
1238
if _gp is None :
1225
1239
_gp = Gp ()
1226
1240
_gp ("ggf(v)=local(l,m,p,q,B);l=length(v);B=floor(l/2);\
@@ -1236,37 +1250,35 @@ def guess(self, sequence, algorithm='sage'):
1236
1250
den = S (sage_eval (_gp .eval ("Vec(denominator(gf))" ))[::- 1 ])
1237
1251
if num == 0 :
1238
1252
return 0
1239
- else :
1240
- return CFiniteSequence (num / den )
1241
- else :
1242
- from sage .matrix .constructor import matrix
1243
- from sage .arith .misc import integer_ceil as ceil
1244
- from numpy import trim_zeros
1245
- seq = sequence [:]
1246
- while seq and sequence [- 1 ] == 0 :
1247
- seq .pop ()
1248
- l = len (seq )
1249
- if l == 0 :
1250
- return 0
1251
- if l < 6 :
1252
- raise ValueError ('Sequence too short for guessing.' )
1253
-
1254
- hl = ceil (ZZ (l ) / 2 )
1255
- A = matrix ([sequence [k : k + hl ] for k in range (hl )])
1256
- K = A .kernel ()
1257
- if K .dimension () == 0 :
1258
- return 0
1259
- R = PolynomialRing (QQ , 'x' )
1260
- den = R (trim_zeros (K .basis ()[- 1 ].list ()[::- 1 ]))
1261
- if den == 1 :
1262
- return 0
1263
- offset = next ((i for i , x in enumerate (sequence ) if x ), None )
1264
- S = PowerSeriesRing (QQ , 'x' , default_prec = l - offset )
1265
- num = S (R (sequence ) * den ).truncate (ZZ (l ) // 2 + 1 )
1266
- if num == 0 or sequence != S (num / den ).list ():
1267
- return 0
1268
- else :
1269
- return CFiniteSequence (num / den )
1253
+ return CFiniteSequence (num / den )
1254
+
1255
+ from sage .matrix .constructor import matrix
1256
+ from sage .arith .misc import integer_ceil as ceil
1257
+ from numpy import trim_zeros
1258
+ seq = sequence [:]
1259
+ while seq and sequence [- 1 ] == 0 :
1260
+ seq .pop ()
1261
+ l = len (seq )
1262
+ if l == 0 :
1263
+ return 0
1264
+ if l < 6 :
1265
+ raise ValueError ('sequence too short for guessing' )
1266
+
1267
+ hl = ceil (ZZ (l ) / 2 )
1268
+ A = matrix ([sequence [k : k + hl ] for k in range (hl )])
1269
+ K = A .kernel ()
1270
+ if K .dimension () == 0 :
1271
+ return 0
1272
+ R = PolynomialRing (QQ , 'x' )
1273
+ den = R (trim_zeros (K .basis ()[- 1 ].list ()[::- 1 ]))
1274
+ if den == 1 :
1275
+ return 0
1276
+ offset = next ((i for i , x in enumerate (sequence ) if x ), None )
1277
+ S = PowerSeriesRing (QQ , 'x' , default_prec = l - offset )
1278
+ num = S (R (sequence ) * den ).truncate (ZZ (l ) // 2 + 1 )
1279
+ if num == 0 or sequence != S (num / den ).list ():
1280
+ return 0
1281
+ return CFiniteSequence (num / den )
1270
1282
1271
1283
1272
1284
r"""
0 commit comments