Documentation contents

atlas Library · Script File

lazy_lists.at

This file demonstrates how axis can handle lazy infinite lists (of any type)
Source
atlas-scripts/lazy_lists.at (334 lines)
Definitions
48
Loads
Loaded by
number_theory.at exp-generating-series.at

Definitions in source order

infinite_list, infinite_node type

L5
set_type T [
  infinite_list
    = (->infinite_node) { defers creating of |inf_node| until called with () }
, infinite_node
    = (T head, infinite_list thunk) { initial term, thunk for remaining terms }
]

Fields: head, thunk

inf_list type

L12
set_type inf_list = infinite_list<int>

inf_node type

L13
set_type inf_node = infinite_node<int>
Commented-out code, lines 15–21 (6 lines)
One may for instance define, to get an infinite list of entries 1:

set rec_fun ones () = inf_node: (1,ones)

and then refer to it as |ones@void|, since |set| stores this function in the
overload table. The following defines a variable instead, by avoiding |set|

series

L25any_type Tseries ((int->T) coef) = infinite_list<T>

initial

L29any_type Tinitial (int n) = (infinite_list<T>->[T])
get initial |n| terms of the list, and return them as ordinary list

prepend

L33any_type Tprepend (T c,infinite_list<T> F) = infinite_list<T>

shift

L34any_type Tshift(int n,infinite_list<T> F) = infinite_list<T>

also defined in hodge_tensor.at, hodgeParamPol.at, laurentPolynomial.at

constant_term

L37any_type Tconstant_term (infinite_list<T> F) = T

coefficient

L38any_type Tcoefficient(int i,infinite_list<T> F) = T

also defined in hodgeParamLaurentPol.at, hodgeParamPol.at, hodge_functions.at

extend

L40any_type Textend ([T] pol,T zero) = infinite_list<T>

extend_0

L48extend_0 ([int] pol) = inf_list

series_0

L50series_0 : inf_list
additive unit for power series

series_1

L51series_1 : inf_list
multiplicative unit for power series

X

L52X : inf_list
neutral element for power series composition

also defined in cyclotomic_Lie_algebra.at, bracket.at

inf_ones

L53inf_ones : inf_list
infinite list of '1', algebraically 1/(1-X)

arithmetic_progression

L56arithmetic_progression (int stride)
more general then |ones|, we can define arithmetic and geometric progressions

geometric_progression

L59geometric_progression (int lambda)
It can be important to avoid evaluating the thunk defining an infinite list
more than once, but instead store the values that have already been computed.
Indeed this will make it possible to define a non-pure function as thunk that
simply assumes that each successive call is done to produce the coefficient
following the one of the previous call; this assumes that no access to the
function is exported other than the one given to the |memoize| function below.

Another application is when we want to solve a recursion like that of
Fibonacci by directly referring, via a |shift|, to previous values of the list
under construction. This remains delicate, since a simple application of
|memoize| will not suffice, and probably will not often prove to be the best
choice of strategy to solve a recurrence relation.

The function |memoize| adds the necessary storage on top of an infinite list:
before actually calling the thunk, it defines a variable that can store the
node produced, but initially stores nothing. The first time the memoized
function is called, the thunk is called and the result stored, from which
further calls will retrieve it. The magic comes from applying |memoize|
recursively to the tail, before storage.
L62

memoize

L84any_type Trec_fun memoize (infinite_list<T> L) = infinite_list<T>
Formal power series
L94

sum

L97rec_fun sum (inf_list f, inf_list g) = inf_list
lazy sum of two infinite lists

also defined in basic.at, sommers.at, character_tables.at, cyclotomic_Lie_algebra.at

scale_by

L100scale_by (int a) = (inf_list->inf_list)

downscale_by

L107downscale_by (int n) = (inf_list->inf_list)

+

L114+ = sum@(inf_list,inf_list)

also in this file at line 116, line 117; also defined in basic.at, extParamPol.at, modules.at, ratmat.at, cyclotomic.at, polynomial.at, hodgeParamLaurentPol.at, hodgeParamPol.at, laurentPolynomial.at, cyclotomic_Lie_algebra.at, cyclotomicMat.at, bracket.at, hodge_functions.at

-

L115- = (inf_list->inf_list)

also in this file at line 119, line 120, line 121; also defined in basic.at, extParamPol.at, modules.at, ratmat.at, cyclotomic.at, polynomial.at, hodgeParamLaurentPol.at, hodgeParamPol.at, laurentPolynomial.at, cyclotomicMat.at, hodge_functions.at

+ 2 overloads

L116+ (int n,inf_list f) = inf_list
L117+ (inf_list f,int n) = inf_list

also in this file at line 114; also defined in basic.at, extParamPol.at, modules.at, ratmat.at, cyclotomic.at, polynomial.at, hodgeParamLaurentPol.at, hodgeParamPol.at, laurentPolynomial.at, cyclotomic_Lie_algebra.at, cyclotomicMat.at, bracket.at, hodge_functions.at

*

L118* (int n,inf_list f) = inf_list

also in this file at line 135; also defined in basic.at, extParamPol.at, complex.at, modules.at, hodge_tensor.at, tits_centralizer.at, stable.at, synthetic.at, Weylgroup.at, group_operations.at, ratmat.at, tits.at, twisted_root_datum.at, cyclotomic.at, polynomial.at, hodgeParamLaurentPol.at, hodgeParamPol.at, laurentPolynomial.at, cyclotomic_Lie_algebra.at, cyclotomicMat.at, bracket.at, hodge_functions.at, sparse.at

- 3 overloads

L119- (int n,inf_list f) = inf_list
L120- (inf_list f,int n) = inf_list
L121- (inf_list f,inf_list g) = inf_list

also in this file at line 115; also defined in basic.at, extParamPol.at, modules.at, ratmat.at, cyclotomic.at, polynomial.at, hodgeParamLaurentPol.at, hodgeParamPol.at, laurentPolynomial.at, cyclotomicMat.at, hodge_functions.at

\

L122\ (inf_list f,int n) = inf_list

also defined in basic.at, polynomial.at

arithmetic of $\Z[[X]]$, using |inf_list| to represent the elements
L124

multiply

L126multiply (inf_list f, inf_list g) = inf_list

also defined in tits.at

*

L135* = multiply@(inf_list,inf_list)

also in this file at line 118; also defined in basic.at, extParamPol.at, complex.at, modules.at, hodge_tensor.at, tits_centralizer.at, stable.at, synthetic.at, Weylgroup.at, group_operations.at, ratmat.at, tits.at, twisted_root_datum.at, cyclotomic.at, polynomial.at, hodgeParamLaurentPol.at, hodgeParamPol.at, laurentPolynomial.at, cyclotomic_Lie_algebra.at, cyclotomicMat.at, bracket.at, hodge_functions.at, sparse.at

multiply_by

L137multiply_by ([int] pol) = (inf_list->inf_list)

divide_by

L157divide_by ([int] pol) = (inf_list->inf_list)

also in this file at line 202; also defined in basic.at, polynomial.at

divide

L189divide (inf_list N, inf_list denom) = inf_list
We provide two ways to divide power series $N$ by $D$, with constant term $1$.
The first is done similarly to |multiply|, but instead of retaining an
increasing number of coefficients from both arguments, we retain them from $D$
and from the quotient $Q$; those from $N$ can be forgotten once used. As in
|multiply|, this imperative style together with |memoize| allow the thunk
being used to actually be the same non-pure function |m| at all levels.

The second is more slick and pure, producing the thunk by calls of a recursive
function with different arguments (representing the remainder at each step),
each next one being produced from the previous by a transformation involving
|sum| and |scale_by|. We need to ensure $D$ can be traversed multiple
times without needlessly repeating its computation, which is done by applying
|memoize| to the tail of $D$ (this can be unnecessary depending on how $D$
was constructed, but whether that is the case cannot be found out here). The
ever more complicated thunk represents another, hidden, form of storage use
that goes on here. All in all, while slick, this might be less efficient.

also defined in polynomial.at

divide_by

L202divide_by (inf_list f) = (inf_list->inf_list)

also in this file at line 157; also defined in basic.at, polynomial.at

here the final result is not passed through |memoize|; if that is desired
the caller should take care to do so
L207

inverse

L210inverse (inf_list f) = inf_list

also defined in basic.at, combinatorics.at, ratmat.at, parameters.at, tits.at, affine.at, cyclotomic.at, Gaussian_elim.at, cyclotomic_Gaussian_elim.at

/ 3 overloads

L212/ = (inf_list->inf_list)
L213/ (int n,inf_list f) = inf_list
L215/ (inf_list f,inf_list g) = inf_list

also defined in basic.at, ratmat.at, cyclotomic.at, polynomial.at

^

L228^ (inf_list F,int n) = inf_list

also defined in basic.at, ratmat.at, tits.at, cyclotomic.at, polynomial.at, sparse.at

As a proof of concept we show how an infinite list can be recursively
defined using itself (taking care to not make any coefficient require itself)
and use |memoize| to avoid re-evaluating previous terms while computing new
ones. The standard example is to compute the Fibonacci sequence F as 0, 1,
followed by |sum(f,shift(1,F))| (where the first argument to |sum| gives the
coefficient two steps before, the second argument the preceding coefficient).

Using |memoize| remains delicate here, since the |rec_fun| syntax does not
allow anything being done before introducing arguments, as might be thought:
|rec_fun signs = inf_list: memoize(@:(1,@:(-1,signs)))| (NOT SYNTACTIC).
And calling |memoize| inside the function body, necessarily multiple times
if there are multiple recursive uses as is the case for Fibinacci, creates
separate memo tables for each call (even with identical arguments) which
solves nothing (as a general rule, the argument to |memoize| should not be
allowed to be named and accessed elsewhere, lest the efficiency be lost when
those other accessed recompute anyway what |memoize| stores). A solution is
to tie the recursive knot by hand, rather than have |rec_fun| do it for us.
L240

Fibonacci

L262Fibonacci = inf_list
the Fibonacci sequence can be defined |divide_by([1,-1,-1])(extend_0([0,1]))|,
however we now show how it can be defined in a directly recursive fashion
Note that leaving out |memoize| would be possible here, but makes the runtime
increase exponentially with the list length because of repeated evaluations of
the same list elements. That inefficient version would also be obtained by
| set rec_fun Fibo () = inf_node:(0,@:(1,sum(Fibo,shift(1,Fibo))))) |
L265
and note Fibonacci is also |inverse([1,-1,-1].extend_0)|, easy and efficient
L271
The pentagonal numbers are those obtained by adding to a perfect square $k^2$
either the "lower" |binom(k,2)| or "upper" |binom(n+1,2)| triangular number;
call these the lower and uppoer pentagonal numbers for $k$.
Euler's pentagonal series has entries $(-1)^k$ at indices the lower and upper
pentagonal numbers for $k$, for every $k\in\N$, and $0$ at all other indices.
The relavance of Euler's pentagonal  series is that its inverse is the
generating series for the number of partitions of a natural number.

A practical way to generate it is to start at index 0, the upper pentagonal
number for 0, with variables k=0, lower=false and a timer i=1. Then to
generate a term, decrement the timer; if still positive return a term 0.
Otherwise return (-1)^k, and if lower holds set the timer i:=k else (not lower)
increment k and set i to the sum of the old and new values of k; also invert
lower in all productive cases. The code below is a bit slicker and clearer.
L273

pentagonal_series

L290pentagonal_series : inf_list

n_partitions

L305n_partitions = (int->int)

substitute

L310substitute (inf_list g) = (inf_list->inf_list)
f->f[X:=g]
e.g., |substitute ([0,1,1].extend_0)(ones)| gives series 1/(1-X-X^2)
L316

compositional_inverse

L318compositional_inverse (inf_list g) = inf_list
e.g., compositional_inverse([0,1,-1].extend_0) solves $f-f^2=X$
L329

series_precision

L331series_precision = 12

show

L332any_type Tshow(infinite_list<T> f) = [T]
use |series_precision| only when |f| is there

also defined in modules.at, K_Nilpotent.at, good_W_representatives.at, arthur_parameters.at, sub_cells.at, associated_variety_annihilator.at, geck_generic.at, L_packet.at, ratmat.at, Levi_subgroups.at, nilpotent_orbits.at, subgroups.at, poset.at, cyclotomic.at, polynomial.at, character_tables.at, springer_tables.at, hodgeParamLaurentPol.at, hodgeParamPol.at, laurentPolynomial.at, weak_packets.at, cyclotomic_Lie_algebra.at, cyclotomicMat.at, bracket.at, exceptional.at, nilpotent_posets.at

Generated from atlas-scripts at commit 648506c (2026-10-13).