Cluster algebras - Algebras

Skip to content
Back to top
View this page
Edit this page

# Cluster algebras

This file constructs cluster algebras using the Parent-Element framework. The implementation mainly utilizes structural theorems from [FZ2007].

The key points being used here are these:

- cluster variables are parametrized by their g-vectors;

- g-vectors (together with c-vectors) provide a self-standing model for the combinatorics behind any cluster algebra;

- each cluster variable in any cluster algebra can be computed, by the separation of additions formula, from its g-vector and F-polynomial.

Accordingly this file provides three classes:

- `ClusterAlgebra`

- `ClusterAlgebraSeed`

- `ClusterAlgebraElement`

`ClusterAlgebra`, constructed as a subobject of `sage.rings.polynomial.laurent_polynomial_ring.LaurentPolynomialRing_generic`, is the frontend of this implementation. It provides all the algebraic features (like ring morphisms), it computes cluster variables, it is responsible for controlling the exploration of the exchange graph and serves as the repository for all the data recursively computed so far. In particular, all g-vectors and all F-polynomials of known cluster variables as well as a mutation path by which they can be obtained are recorded. In the optic of efficiency, this implementation does not store directly the exchange graph nor the exchange relations. Both of these could be added to `ClusterAlgebra` with minimal effort.

`ClusterAlgebraSeed` provides the combinatorial backbone for `ClusterAlgebra`. It is an auxiliary class and therefore its instances should not be directly created by the user. Rather it should be accessed via `ClusterAlgebra.current_seed()` and `ClusterAlgebra.initial_seed()`. The task of performing current seed mutations is delegated to this class. Seeds are considered equal if they have the same parent cluster algebra and they can be obtained from each other by a permutation of their data (i.e. if they coincide as unlabelled seeds). Cluster algebras whose initial seeds are equal in the above sense are not considered equal but are endowed with coercion maps to each other. More generally, a cluster algebra is endowed with coercion maps from any cluster algebra which is obtained by freezing a collection of initial cluster variables and/or permuting both cluster variables and coefficients.

`ClusterAlgebraElement` is a thin wrapper around `sage.rings.polynomial.laurent_polynomial.LaurentPolynomial` providing all the functions specific to cluster variables. Elements of a cluster algebra with principal coefficients have special methods and these are grouped in the subclass `PrincipalClusterAlgebraElement`.

One more remark about this implementation. Instances of `ClusterAlgebra` are built by identifying the initial cluster variables with the generators of `ClusterAlgebra.ambient()`. In particular, this forces a specific embedding into the ambient field of rational expressions. In view of this, although cluster algebras themselves are independent of the choice of initial seed, `ClusterAlgebra.mutate_initial()` is forced to return a different instance of `ClusterAlgebra`. At the moment there is no coercion implemented among the two instances but this could in principle be added to `ClusterAlgebra.mutate_initial()`.

REFERENCES:

- [FZ2007]

- [LLZ2014]

- [NZ2012]

AUTHORS:

- Dylan Rupel (2015-06-15): initial version

- Salvatore Stella (2015-06-15): initial version

EXAMPLES:

We begin by creating a simple cluster algebra and printing its initial exchange matrix:

Sage

    sage: A = ClusterAlgebra(['A', 2]); A
    A Cluster Algebra with cluster variables x0, x1 and no coefficients over Integer Ring
    sage: A.b_matrix()
    [ 0  1]
    [-1  0]

Python

    >>> from sage.all import *
    >>> A = ClusterAlgebra(['A', Integer(2)]); A
    A Cluster Algebra with cluster variables x0, x1 and no coefficients over Integer Ring
    >>> A.b_matrix()
    [ 0  1]
    [-1  0]

`A` is of finite type so we can explore all its exchange graph:

Sage

    sage: A.explore_to_depth(infinity)

[Python]

    >>> from sage.all import *
    >>> A.explore_to_depth(infinity)

and get all its g-vectors, F-polynomials, and cluster variables:

Sage

    sage: sorted(A.g_vectors_so_far())
    [(-1, 0), (-1, 1), (0, -1), (0, 1), (1, 0)]
    sage: sorted(A.F_polynomials_so_far(), key=str)
    [1, 1, u0 + 1, u0*u1 + u0 + 1, u1 + 1]
    sage: sorted(A.cluster_variables_so_far(), key=str)
    [(x0 + 1)/x1, (x0 + x1 + 1)/(x0*x1), (x1 + 1)/x0, x0, x1]

Python

    >>> from sage.all import *
    >>> sorted(A.g_vectors_so_far())
    [(-1, 0), (-1, 1), (0, -1), (0, 1), (1, 0)]
    >>> sorted(A.F_polynomials_so_far(), key=str)
    [1, 1, u0 + 1, u0*u1 + u0 + 1, u1 + 1]
    >>> sorted(A.cluster_variables_so_far(), key=str)
    [(x0 + 1)/x1, (x0 + x1 + 1)/(x0*x1), (x1 + 1)/x0, x0, x1]

Simple operations among cluster variables behave as expected:

Sage

    sage: s = A.cluster_variable((0, -1)); s
    (x0 + 1)/x1
    sage: t = A.cluster_variable((-1, 1)); t
    (x1 + 1)/x0
    sage: t + s
    (x0^2 + x1^2 + x0 + x1)/(x0*x1)
    sage: _.parent() == A
    True
    sage: t - s
    (-x0^2 + x1^2 - x0 + x1)/(x0*x1)
    sage: _.parent() == A
    True
    sage: t*s
    (x0*x1 + x0 + x1 + 1)/(x0*x1)
    sage: _.parent() == A
    True
    sage: t/s
    (x1^2 + x1)/(x0^2 + x0)
    sage: _.parent() == A
    False

[Python]

    >>> from sage.all import *
    >>> s = A.cluster_variable((Integer(0), -Integer(1))); s
    (x0 + 1)/x1
    >>> t = A.cluster_variable((-Integer(1), Integer(1))); t
    (x1 + 1)/x0
    >>> t + s
    (x0^2 + x1^2 + x0 + x1)/(x0*x1)
    >>> _.parent() == A
    True
    >>> t - s
    (-x0^2 + x1^2 - x0 + x1)/(x0*x1)
    >>> _.parent() == A
    True
    >>> t*s
    (x0*x1 + x0 + x1 + 1)/(x0*x1)
    >>> _.parent() == A
    True
    >>> t/s
    (x1^2 + x1)/(x0^2 + x0)
    >>> _.parent() == A
    False

Division is not guaranteed to yield an element of `A` so it returns an element of `A.ambient().fraction_field()` instead:

Sage

    sage: (t/s).parent() == A.ambient().fraction_field()
    True

Python

    >>> from sage.all import *
    >>> (t/s).parent() == A.ambient().fraction_field()
    True

We can compute denominator vectors of any element of `A`:

Sage

    sage: (t*s).d_vector()
    (1, 1)

[Python]

    >>> from sage.all import *
    >>> (t*s).d_vector()
    (1, 1)

Since we are in rank 2 and we do not have coefficients we can compute the greedy element associated to any denominator vector:

Sage

    sage: A.rank() == 2 and A.coefficients() == ()
    True
    sage: A.greedy_element((1, 1))
    (x0 + x1 + 1)/(x0*x1)
    sage: _ == t*s
    False

Python

    >>> from sage.all import *
    >>> A.rank() == Integer(2) and A.coefficients() == ()
    True
    >>> A.greedy_element((Integer(1), Integer(1)))
    (x0 + x1 + 1)/(x0*x1)
    >>> _ == t*s
    False

not surprising since there is no cluster in `A` containing both `t` and `s`:

Sage

    sage: seeds = A.seeds(mutating_F=false)
    sage: [ S for S in seeds if (0, -1) in S and (-1, 1) in S ]
    []

[Python]

    >>> from sage.all import *
    >>> seeds = A.seeds(mutating_F=false)
    >>> [ S for S in seeds if (Integer(0), -Integer(1)) in S and (-Integer(1), Integer(1)) in S ]
    []

indeed:

Sage

    sage: A.greedy_element((1, 1)) == A.cluster_variable((-1, 0))
    True

Python

    >>> from sage.all import *
    >>> A.greedy_element((Integer(1), Integer(1))) == A.cluster_variable((-Integer(1), Integer(0)))
    True

Disabling F-polynomials in the computation just done was redundant because we already explored the whole exchange graph before. Though in different circumstances it could have saved us considerable time.

g-vectors and F-polynomials can be computed from elements of `A` only if `A` has principal coefficients at the initial seed:

Sage

    sage: (t*s).g_vector()
    Traceback (most recent call last):
    ...
    AttributeError: 'ClusterAlgebra_with_category.element_class' object has no attribute 'g_vector'...
    sage: A = ClusterAlgebra(['A', 2], principal_coefficients=True)
    sage: A.explore_to_depth(infinity)
    sage: s = A.cluster_variable((0, -1)); s
    (x0*y1 + 1)/x1
    sage: t = A.cluster_variable((-1, 1)); t
    (x1 + y0)/x0
    sage: (t*s).g_vector()
    (-1, 0)
    sage: (t*s).F_polynomial()
    u0*u1 + u0 + u1 + 1
    sage: (t*s).is_homogeneous()
    True
    sage: (t+s).is_homogeneous()
    False
    sage: (t+s).homogeneous_components()
    {(-1, 1): (x1 + y0)/x0, (0, -1): (x0*y1 + 1)/x1}

[Python]

    >>> from sage.all import *
    >>> (t*s).g_vector()
    Traceback (most recent call last):
    ...
    AttributeError: 'ClusterAlgebra_with_category.element_class' object has no attribute 'g_vector'...
    >>> A = ClusterAlgebra(['A', Integer(2)], principal_coefficients=True)
    >>> A.explore_to_depth(infinity)
    >>> s = A.cluster_variable((Integer(0), -Integer(1))); s
    (x0*y1 + 1)/x1
    >>> t = A.cluster_variable((-Integer(1), Integer(1))); t
    (x1 + y0)/x0
    >>> (t*s).g_vector()
    (-1, 0)
    >>> (t*s).F_polynomial()
    u0*u1 + u0 + u1 + 1
    >>> (t*s).is_homogeneous()
    True
    >>> (t+s).is_homogeneous()
    False
    >>> (t+s).homogeneous_components()
    {(-1, 1): (x1 + y0)/x0, (0, -1): (x0*y1 + 1)/x1}

Each cluster algebra is endowed with a reference to a current seed; it could be useful to assign a name to it:

Sage

    sage: A = ClusterAlgebra(['F', 4])
    sage: len(A.g_vectors_so_far())
    4
    sage: A.current_seed()
    The initial seed of a Cluster Algebra with cluster variables x0, x1, x2, x3
     and no coefficients over Integer Ring
    sage: A.current_seed() == A.initial_seed()
    True
    sage: S = A.current_seed()
    sage: S.b_matrix()
    [ 0  1  0  0]
    [-1  0 -1  0]
    [ 0  2  0  1]
    [ 0  0 -1  0]
    sage: S.g_matrix()
    [1 0 0 0]
    [0 1 0 0]
    [0 0 1 0]
    [0 0 0 1]
    sage: S.cluster_variables()
    [x0, x1, x2, x3]

Python

    >>> from sage.all import *
    >>> A = ClusterAlgebra(['F', Integer(4)])
    >>> len(A.g_vectors_so_far())
    4
    >>> A.current_seed()
    The initial seed of a Cluster Algebra with cluster variables x0, x1, x2, x3
     and no coefficients over Integer Ring
    >>> A.current_seed() == A.initial_seed()
    True
    >>> S = A.current_seed()
    >>> S.b_matrix()
    [ 0  1  0  0]
    [-1  0 -1  0]
    [ 0  2  0  1]
    [ 0  0 -1  0]
    >>> S.g_matrix()
    [1 0 0 0]
    [0 1 0 0]
    [0 0 1 0]
    [0 0 0 1]
    >>> S.cluster_variables()
    [x0, x1, x2, x3]

and use `S` to walk around the exchange graph of `A`:

Sage

    sage: S.mutate(0); S
    The seed of a Cluster Algebra with cluster variables x0, x1, x2, x3
     and no coefficients over Integer Ring obtained from the initial
     by mutating in direction 0
    sage: S.b_matrix()
    [ 0 -1  0  0]
    [ 1  0 -1  0]
    [ 0  2  0  1]
    [ 0  0 -1  0]
    sage: S.g_matrix()
    [-1  0  0  0]
    [ 1  1  0  0]
    [ 0  0  1  0]
    [ 0  0  0  1]
    sage: S.cluster_variables()
    [(x1 + 1)/x0, x1, x2, x3]
    sage: S.mutate('sinks'); S
    The seed of a Cluster Algebra with cluster variables x0, x1, x2, x3
     and no coefficients over Integer Ring obtained from the initial
     by mutating along the sequence [0, 2]
    sage: S.mutate([2, 3, 2, 1, 0]); S
    The seed of a Cluster Algebra with cluster variables x0, x1, x2, x3
     and no coefficients over Integer Ring obtained from the initial
     by mutating along the sequence [0, 3, 2, 1, 0]
    sage: S.g_vectors()
    [(0, 1, -2, 0), (-1, 2, -2, 0), (0, 1, -1, 0), (0, 0, 0, -1)]
    sage: S.cluster_variable(3)
    (x2 + 1)/x3

[Python]

    >>> from sage.all import *
    >>> S.mutate(Integer(0)); S
    The seed of a Cluster Algebra with cluster variables x0, x1, x2, x3
     and no coefficients over Integer Ring obtained from the initial
     by mutating in direction 0
    >>> S.b_matrix()
    [ 0 -1  0  0]
    [ 1  0 -1  0]
    [ 0  2  0  1]
    [ 0  0 -1  0]
    >>> S.g_matrix()
    [-1  0  0  0]
    [ 1  1  0  0]
    [ 0  0  1  0]
    [ 0  0  0  1]
    >>> S.cluster_variables()
    [(x1 + 1)/x0, x1, x2, x3]
    >>> S.mutate('sinks'); S
    The seed of a Cluster Algebra with cluster variables x0, x1, x2, x3
     and no coefficients over Integer Ring obtained from the initial
     by mutating along the sequence [0, 2]
    >>> S.mutate([Integer(2), Integer(3), Integer(2), Integer(1), Integer(0)]); S
    The seed of a Cluster Algebra with cluster variables x0, x1, x2, x3
     and no coefficients over Integer Ring obtained from the initial
     by mutating along the sequence [0, 3, 2, 1, 0]
    >>> S.g_vectors()
    [(0, 1, -2, 0), (-1, 2, -2, 0), (0, 1, -1, 0), (0, 0, 0, -1)]
    >>> S.cluster_variable(Integer(3))
    (x2 + 1)/x3

Walking around by mutating `S` updates the information stored in `A`:

Sage

    sage: len(A.g_vectors_so_far())
    10
    sage: A.current_seed().path_from_initial_seed()
    [0, 3, 2, 1, 0]
    sage: A.current_seed() == S
    True

Python

    >>> from sage.all import *
    >>> len(A.g_vectors_so_far())
    10
    >>> A.current_seed().path_from_initial_seed()
    [0, 3, 2, 1, 0]
    >>> A.current_seed() == S
    True

Starting from `A.initial_seed()` still records data in `A` but does not update `A.current_seed()`:

Sage

    sage: S1 = A.initial_seed()
    sage: S1.mutate([2, 1, 3])
    sage: len(A.g_vectors_so_far())
    11
    sage: S1 == A.current_seed()
    False

[Python]

    >>> from sage.all import *
    >>> S1 = A.initial_seed()
    >>> S1.mutate([Integer(2), Integer(1), Integer(3)])
    >>> len(A.g_vectors_so_far())
    11
    >>> S1 == A.current_seed()
    False

Since `ClusterAlgebra` inherits from `UniqueRepresentation`, computed data is shared across instances:

Sage

    sage: A1 = ClusterAlgebra(['F', 4])
    sage: A1 is A
    True
    sage: len(A1.g_vectors_so_far())
    11

Python

    >>> from sage.all import *
    >>> A1 = ClusterAlgebra(['F', Integer(4)])
    >>> A1 is A
    True
    >>> len(A1.g_vectors_so_far())
    11

It can be useful, at times to forget all computed data. Because of `UniqueRepresentation` this cannot be achieved by simply creating a new instance; instead it has to be manually triggered by:

Sage

    sage: A.clear_computed_data()
    sage: len(A.g_vectors_so_far())
    4

[Python]

    >>> from sage.all import *
    >>> A.clear_computed_data()
    >>> len(A.g_vectors_so_far())
    4

Given a cluster algebra `A` we may be looking for a specific cluster variable:

Sage

    sage: A = ClusterAlgebra(['E', 8, 1])
    sage: v = (-1, 1, -1, 1, -1, 1, 0, 0, 1)
    sage: A.find_g_vector(v, depth=2)
    sage: seq = A.find_g_vector(v); seq  # random
    [0, 1, 2, 4, 3]
    sage: v in A.initial_seed().mutate(seq, inplace=False).g_vectors()
    True

Python

    >>> from sage.all import *
    >>> A = ClusterAlgebra(['E', Integer(8), Integer(1)])
    >>> v = (-Integer(1), Integer(1), -Integer(1), Integer(1), -Integer(1), Integer(1), Integer(0), Integer(0), Integer(1))
    >>> A.find_g_vector(v, depth=Integer(2))
    >>> seq = A.find_g_vector(v); seq  # random
    [0, 1, 2, 4, 3]
    >>> v in A.initial_seed().mutate(seq, inplace=False).g_vectors()
    True

This also performs mutations of F-polynomials:

Sage

    sage: A.F_polynomial((-1, 1, -1, 1, -1, 1, 0, 0, 1))
    u0*u1*u2*u3*u4 + u0*u1*u2*u4 + u0*u2*u3*u4 + u0*u1*u2 + u0*u2*u4
     + u2*u3*u4 + u0*u2 + u0*u4 + u2*u4 + u0 + u2 + u4 + 1

[Python]

    >>> from sage.all import *
    >>> A.F_polynomial((-Integer(1), Integer(1), -Integer(1), Integer(1), -Integer(1), Integer(1), Integer(0), Integer(0), Integer(1)))
    u0*u1*u2*u3*u4 + u0*u1*u2*u4 + u0*u2*u3*u4 + u0*u1*u2 + u0*u2*u4
     + u2*u3*u4 + u0*u2 + u0*u4 + u2*u4 + u0 + u2 + u4 + 1

which might not be a good idea in algebras that are too big. One workaround is to first disable F-polynomials and then recompute only the desired mutations:

Sage

    sage: # long time
    sage: A.reset_exploring_iterator(mutating_F=False)
    sage: v = (-1, 1, -2, 2, -1, 1, -1, 1, 1)
    sage: seq = A.find_g_vector(v); seq  # random
    [1, 0, 2, 6, 5, 4, 3, 8, 1]
    sage: S = A.initial_seed().mutate(seq, inplace=False)
    sage: v in S.g_vectors()
    True
    sage: A.current_seed().mutate(seq)
    sage: A.F_polynomial((-1, 1, -2, 2, -1, 1, -1, 1, 1))
    u0*u1^2*u2^2*u3*u4*u5*u6*u8 +
    ...
    2*u2 + u4 + u6 + 1

Python

    >>> from sage.all import *
    >>> # long time
    >>> A.reset_exploring_iterator(mutating_F=False)
    >>> v = (-Integer(1), Integer(1), -Integer(2), Integer(2), -Integer(1), Integer(1), -Integer(1), Integer(1), Integer(1))
    >>> seq = A.find_g_vector(v); seq  # random
    [1, 0, 2, 6, 5, 4, 3, 8, 1]
    >>> S = A.initial_seed().mutate(seq, inplace=False)
    >>> v in S.g_vectors()
    True
    >>> A.current_seed().mutate(seq)
    >>> A.F_polynomial((-Integer(1), Integer(1), -Integer(2), Integer(2), -Integer(1), Integer(1), -Integer(1), Integer(1), Integer(1)))
    u0*u1^2*u2^2*u3*u4*u5*u6*u8 +
    ...
    2*u2 + u4 + u6 + 1

We can manually freeze cluster variables and get coercions in between the two algebras:

Sage

    sage: A = ClusterAlgebra(['F', 4]); A
    A Cluster Algebra with cluster variables x0, x1, x2, x3 and no coefficients
     over Integer Ring
    sage: A1 = ClusterAlgebra(A.b_matrix().matrix_from_columns([0, 1, 2]), coefficient_prefix='x'); A1
    A Cluster Algebra with cluster variables x0, x1, x2 and coefficient x3
     over Integer Ring
    sage: A.has_coerce_map_from(A1)
    True

[Python]

    >>> from sage.all import *
    >>> A = ClusterAlgebra(['F', Integer(4)]); A
    A Cluster Algebra with cluster variables x0, x1, x2, x3 and no coefficients
     over Integer Ring
    >>> A1 = ClusterAlgebra(A.b_matrix().matrix_from_columns([Integer(0), Integer(1), Integer(2)]), coefficient_prefix='x'); A1
    A Cluster Algebra with cluster variables x0, x1, x2 and coefficient x3
     over Integer Ring
    >>> A.has_coerce_map_from(A1)
    True

and we also have an immersion of `A.base()` into `A` and of `A` into `A.ambient()`:

Sage

    sage: A.has_coerce_map_from(A.base())
    True
    sage: A.ambient().has_coerce_map_from(A)
    True

Python

    >>> from sage.all import *
    >>> A.has_coerce_map_from(A.base())
    True
    >>> A.ambient().has_coerce_map_from(A)
    True

but there is currently no coercion in between algebras obtained by mutating at the initial seed:

Sage

    sage: A1 = A.mutate_initial(0); A1
    A Cluster Algebra with cluster variables x4, x1, x2, x3 and no coefficients
     over Integer Ring
    sage: A.b_matrix() == A1.b_matrix()
    False
    sage: [X.has_coerce_map_from(Y) for X, Y in [(A, A1), (A1, A)]]
    [False, False]

[Python]

    >>> from sage.all import *
    >>> A1 = A.mutate_initial(Integer(0)); A1
    A Cluster Algebra with cluster variables x4, x1, x2, x3 and no coefficients
     over Integer Ring
    >>> A.b_matrix() == A1.b_matrix()
    False
    >>> [X.has_coerce_map_from(Y) for X, Y in [(A, A1), (A1, A)]]
    [False, False]

class sage.algebras.cluster_algebra.ClusterAlgebra(B, **kwargs)

  Bases: `Parent`, `UniqueRepresentation`

  A Cluster Algebra.

  INPUT:

  - `data` – some data defining a cluster algebra; it can be anything that can be parsed by `ClusterQuiver`

  - `scalars` – a ring (default: \(\ZZ\)); the scalars over which the cluster algebra is defined

  - `cluster_variable_prefix` – string (default: `'x'`); it needs to be a valid variable name

  - `cluster_variable_names` – list of strings; each element needs to be a valid variable name; supersedes `cluster_variable_prefix`

  - `coefficient_prefix` – string (default: `'y'`); it needs to be a valid variable name

  - `coefficient_names` – list of strings; each element needs to be a valid variable name; supersedes `cluster_variable_prefix`

  - `principal_coefficients` – boolean (default: `False`); supersedes any coefficient defined by `data`

  ALGORITHM:

  The implementation is mainly based on [FZ2007] and [NZ2012].

  EXAMPLES:

  Sage

      sage: B = matrix([(0, 1, 0, 0), (-1, 0, -1, 0), (0, 1, 0, 1), (0, 0, -2, 0), (-1, 0, 0, 0), (0, -1, 0, 0)])
      sage: A = ClusterAlgebra(B); A
      A Cluster Algebra with cluster variables x0, x1, x2, x3
       and coefficients y0, y1 over Integer Ring
      sage: A.gens()
      (x0, x1, x2, x3, y0, y1)
      sage: A = ClusterAlgebra(['A', 2]); A
      A Cluster Algebra with cluster variables x0, x1 and no coefficients
       over Integer Ring
      sage: A = ClusterAlgebra(['A', 2], principal_coefficients=True); A.gens()
      (x0, x1, y0, y1)
      sage: A = ClusterAlgebra(['A', 2], principal_coefficients=True, coefficient_prefix='x'); A.gens()
      (x0, x1, x2, x3)
      sage: A = ClusterAlgebra(['A', 3], principal_coefficients=True, cluster_variable_names=['a', 'b', 'c']); A.gens()
      (a, b, c, y0, y1, y2)
      sage: A = ClusterAlgebra(['A', 3], principal_coefficients=True, cluster_variable_names=['a', 'b'])
      Traceback (most recent call last):
      ...
      ValueError: cluster_variable_names should be an iterable of 3 valid variable names
      sage: A = ClusterAlgebra(['A', 3], principal_coefficients=True, coefficient_names=['a', 'b', 'c']); A.gens()
      (x0, x1, x2, a, b, c)
      sage: A = ClusterAlgebra(['A', 3], principal_coefficients=True, coefficient_names=['a', 'b'])
      Traceback (most recent call last):
      ...
      ValueError: coefficient_names should be an iterable of 3 valid variable names

  Python

      >>> from sage.all import *
      >>> B = matrix([(Integer(0), Integer(1), Integer(0), Integer(0)), (-Integer(1), Integer(0), -Integer(1), Integer(0)), (Integer(0), Integer(1), Integer(0), Integer(1)), (Integer(0), Integer(0), -Integer(2), Integer(0)), (-Integer(1), Integer(0), Integer(0), Integer(0)), (Integer(0), -Integer(1), Integer(0), Integer(0))])
      >>> A = ClusterAlgebra(B); A
      A Cluster Algebra with cluster variables x0, x1, x2, x3
       and coefficients y0, y1 over Integer Ring
      >>> A.gens()
      (x0, x1, x2, x3, y0, y1)
      >>> A = ClusterAlgebra(['A', Integer(2)]); A
      A Cluster Algebra with cluster variables x0, x1 and no coefficients
       over Integer Ring
      >>> A = ClusterAlgebra(['A', Integer(2)], principal_coefficients=True); A.gens()
      (x0, x1, y0, y1)
      >>> A = ClusterAlgebra(['A', Integer(2)], principal_coefficients=True, coefficient_prefix='x'); A.gens()
      (x0, x1, x2, x3)
      >>> A = ClusterAlgebra(['A', Integer(3)], principal_coefficients=True, cluster_variable_names=['a', 'b', 'c']); A.gens()
      (a, b, c, y0, y1, y2)
      >>> A = ClusterAlgebra(['A', Integer(3)], principal_coefficients=True, cluster_variable_names=['a', 'b'])
      Traceback (most recent call last):
      ...
      ValueError: cluster_variable_names should be an iterable of 3 valid variable names
      >>> A = ClusterAlgebra(['A', Integer(3)], principal_coefficients=True, coefficient_names=['a', 'b', 'c']); A.gens()
      (x0, x1, x2, a, b, c)
      >>> A = ClusterAlgebra(['A', Integer(3)], principal_coefficients=True, coefficient_names=['a', 'b'])
      Traceback (most recent call last):
      ...
      ValueError: coefficient_names should be an iterable of 3 valid variable names

  F_polynomial(g_vector)

    Return the F-polynomial with g-vector `g_vector` if it has been found.

    INPUT:

    - `g_vector` – tuple; the g-vector of the F-polynomial to return

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2])
        sage: A.clear_computed_data()
        sage: A.F_polynomial((-1, 1))
        Traceback (most recent call last):
        ...
        KeyError: 'the g-vector (-1, 1) has not been found yet'
        sage: A.initial_seed().mutate(0, mutating_F=False)
        sage: A.F_polynomial((-1, 1))
        Traceback (most recent call last):
        ...
        KeyError: 'the F-polynomial with g-vector (-1, 1) has not been computed yet;
         you can compute it by mutating from the initial seed along the sequence [0]'
        sage: A.initial_seed().mutate(0)
        sage: A.F_polynomial((-1, 1))
        u0 + 1

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)])
        >>> A.clear_computed_data()
        >>> A.F_polynomial((-Integer(1), Integer(1)))
        Traceback (most recent call last):
        ...
        KeyError: 'the g-vector (-1, 1) has not been found yet'
        >>> A.initial_seed().mutate(Integer(0), mutating_F=False)
        >>> A.F_polynomial((-Integer(1), Integer(1)))
        Traceback (most recent call last):
        ...
        KeyError: 'the F-polynomial with g-vector (-1, 1) has not been computed yet;
         you can compute it by mutating from the initial seed along the sequence [0]'
        >>> A.initial_seed().mutate(Integer(0))
        >>> A.F_polynomial((-Integer(1), Integer(1)))
        u0 + 1

  F_polynomials()

    Return an iterator producing all the F_polynomials of `self`.

    ALGORITHM:

    This method does not use the caching framework provided by `self`, but recomputes all the F-polynomials from scratch. On the other hand it stores the results so that other methods like `F_polynomials_so_far()` can access them afterwards.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 3])
        sage: len(list(A.F_polynomials()))
        9

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(3)])
        >>> len(list(A.F_polynomials()))
        9

  F_polynomials_so_far()

    Return a list of the F-polynomials encountered so far.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2])
        sage: A.clear_computed_data()
        sage: A.current_seed().mutate(0)
        sage: sorted(A.F_polynomials_so_far(), key=str)
        [1, 1, u0 + 1]

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)])
        >>> A.clear_computed_data()
        >>> A.current_seed().mutate(Integer(0))
        >>> sorted(A.F_polynomials_so_far(), key=str)
        [1, 1, u0 + 1]

  ambient()

    Return the Laurent polynomial ring containing `self`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2], principal_coefficients=True)
        sage: A.ambient()
        Multivariate Laurent Polynomial Ring in x0, x1, y0, y1 over Integer Ring

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)], principal_coefficients=True)
        >>> A.ambient()
        Multivariate Laurent Polynomial Ring in x0, x1, y0, y1 over Integer Ring

  b_matrix()

    Return the initial exchange matrix of `self`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2])
        sage: A.b_matrix()
        [ 0  1]
        [-1  0]

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)])
        >>> A.b_matrix()
        [ 0  1]
        [-1  0]

  clear_computed_data()

    Clear the cache of computed g-vectors and F-polynomials and reset both the current seed and the exploring iterator.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2])
        sage: A.clear_computed_data()
        sage: sorted(A.g_vectors_so_far())
        [(0, 1), (1, 0)]
        sage: A.current_seed().mutate([1, 0])
        sage: sorted(A.g_vectors_so_far())
        [(-1, 0), (0, -1), (0, 1), (1, 0)]
        sage: A.clear_computed_data()
        sage: sorted(A.g_vectors_so_far())
        [(0, 1), (1, 0)]

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)])
        >>> A.clear_computed_data()
        >>> sorted(A.g_vectors_so_far())
        [(0, 1), (1, 0)]
        >>> A.current_seed().mutate([Integer(1), Integer(0)])
        >>> sorted(A.g_vectors_so_far())
        [(-1, 0), (0, -1), (0, 1), (1, 0)]
        >>> A.clear_computed_data()
        >>> sorted(A.g_vectors_so_far())
        [(0, 1), (1, 0)]

  cluster_fan(depth=+Infinity)

    Return the cluster fan (the fan of g-vectors) of `self`.

    INPUT:

    - `depth` – positive integer or infinity (default: `infinity`); the maximum depth at which to compute

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2])
        sage: A.cluster_fan()
        Rational polyhedral fan in 2-d lattice N

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)])
        >>> A.cluster_fan()
        Rational polyhedral fan in 2-d lattice N

  cluster_variable(g_vector)

    Return the cluster variable with g-vector `g_vector` if it has been found.

    INPUT:

    - `g_vector` – tuple; the g-vector of the cluster variable to return

    ALGORITHM:

    This function computes cluster variables from their g-vectors and F-polynomials using the “separation of additions” formula of Theorem 3.7 in [FZ2007].

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2])
        sage: A.initial_seed().mutate(0)
        sage: A.cluster_variable((-1, 1))
        (x1 + 1)/x0

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)])
        >>> A.initial_seed().mutate(Integer(0))
        >>> A.cluster_variable((-Integer(1), Integer(1)))
        (x1 + 1)/x0

  cluster_variables()

    Return an iterator producing all the cluster variables of `self`.

    ALGORITHM:

    This method does not use the caching framework provided by `self`, but recomputes all the cluster variables from scratch. On the other hand it stores the results so that other methods like `cluster_variables_so_far()` can access them afterwards.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 3])
        sage: len(list(A.cluster_variables()))
        9

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(3)])
        >>> len(list(A.cluster_variables()))
        9

  cluster_variables_so_far()

    Return a list of the cluster variables encountered so far.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2])
        sage: A.clear_computed_data()
        sage: A.current_seed().mutate(0)
        sage: sorted(A.cluster_variables_so_far(), key=str)
        [(x1 + 1)/x0, x0, x1]

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)])
        >>> A.clear_computed_data()
        >>> A.current_seed().mutate(Integer(0))
        >>> sorted(A.cluster_variables_so_far(), key=str)
        [(x1 + 1)/x0, x0, x1]

  coefficient(j)

    Return the `j`-th coefficient of `self`.

    INPUT:

    - `j` – integer in `range(self.parent().rank())`; the index of the coefficient to return

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2], principal_coefficients=True)
        sage: A.coefficient(0)
        y0

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)], principal_coefficients=True)
        >>> A.coefficient(Integer(0))
        y0

  coefficient_names()

    Return the list of coefficient names.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 3])
        sage: A.coefficient_names()
        ()
        sage: A1 = ClusterAlgebra(['B', 2], principal_coefficients=True)
        sage: A1.coefficient_names()
        ('y0', 'y1')
        sage: A2 = ClusterAlgebra(['C', 3], principal_coefficients=True, coefficient_prefix='x')
        sage: A2.coefficient_names()
        ('x3', 'x4', 'x5')

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(3)])
        >>> A.coefficient_names()
        ()
        >>> A1 = ClusterAlgebra(['B', Integer(2)], principal_coefficients=True)
        >>> A1.coefficient_names()
        ('y0', 'y1')
        >>> A2 = ClusterAlgebra(['C', Integer(3)], principal_coefficients=True, coefficient_prefix='x')
        >>> A2.coefficient_names()
        ('x3', 'x4', 'x5')

  coefficients()

    Return the list of coefficients of `self`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2], principal_coefficients=True)
        sage: A.coefficients()
        (y0, y1)
        sage: A1 = ClusterAlgebra(['B', 2])
        sage: A1.coefficients()
        ()

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)], principal_coefficients=True)
        >>> A.coefficients()
        (y0, y1)
        >>> A1 = ClusterAlgebra(['B', Integer(2)])
        >>> A1.coefficients()
        ()

  contains_seed(seed)

    Test if `seed` is a seed of `self`.

    INPUT:

    - `seed` – a `ClusterAlgebraSeed`

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2], principal_coefficients=True); A
        A Cluster Algebra with cluster variables x0, x1 and coefficients y0, y1 over Integer Ring
        sage: S = copy(A.current_seed())
        sage: A.contains_seed(S)
        True

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)], principal_coefficients=True); A
        A Cluster Algebra with cluster variables x0, x1 and coefficients y0, y1 over Integer Ring
        >>> S = copy(A.current_seed())
        >>> A.contains_seed(S)
        True

  coxeter_element()

    Return the Coxeter element associated to the initial exchange matrix, if acyclic.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(matrix([[0,1,1],[-1,0,1],[-1,-1,0]]))
        sage: A.coxeter_element()
        [0, 1, 2]

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(matrix([[Integer(0),Integer(1),Integer(1)],[-Integer(1),Integer(0),Integer(1)],[-Integer(1),-Integer(1),Integer(0)]]))
        >>> A.coxeter_element()
        [0, 1, 2]

    Raise an error if the initial exchange matrix is not acyclic:

    Sage

        sage: A = ClusterAlgebra(matrix([[0,1,-1],[-1,0,1],[1,-1,0]]))
        sage: A.coxeter_element()
        Traceback (most recent call last):
        ...
        ValueError: the initial exchange matrix is not acyclic

    [Python]

        >>> from sage.all import *
        >>> A = ClusterAlgebra(matrix([[Integer(0),Integer(1),-Integer(1)],[-Integer(1),Integer(0),Integer(1)],[Integer(1),-Integer(1),Integer(0)]]))
        >>> A.coxeter_element()
        Traceback (most recent call last):
        ...
        ValueError: the initial exchange matrix is not acyclic

  current_seed()

    Return the current seed of `self`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2])
        sage: A.clear_computed_data()
        sage: A.current_seed()
        The initial seed of a Cluster Algebra with cluster variables x0, x1
         and no coefficients over Integer Ring

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)])
        >>> A.clear_computed_data()
        >>> A.current_seed()
        The initial seed of a Cluster Algebra with cluster variables x0, x1
         and no coefficients over Integer Ring

  d_vector_to_g_vector(d)

    Return the g-vector of an element of `self` having d-vector `d`

    INPUT:

    - `d` – the d-vector

    ALGORITHM:

    > This method implements the piecewise-linear map \(\\nu_c\) introduced in Section 9.1 of [ReSt2020].

    Warning

    This implementation works only when the initial exchange matrix is acyclic.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(matrix([[0,1,1],[-1,0,1],[-1,-1,0]]))
        sage: A.d_vector_to_g_vector((1,0,-1))
        (-1, 1, 2)

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(matrix([[Integer(0),Integer(1),Integer(1)],[-Integer(1),Integer(0),Integer(1)],[-Integer(1),-Integer(1),Integer(0)]]))
        >>> A.d_vector_to_g_vector((Integer(1),Integer(0),-Integer(1)))
        (-1, 1, 2)

  euler_matrix()

    Return the Euler matrix associated to `self`.

    ALGORITHM:

    > This method returns the matrix of the bilinear form defined in Equation (2.1) of [ReSt2020] .

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(matrix([[0,1,1],[-1,0,1],[-1,-1,0]]))
        sage: A.euler_matrix()
        [ 1  0  0]
        [-1  1  0]
        [-1 -1  1]

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(matrix([[Integer(0),Integer(1),Integer(1)],[-Integer(1),Integer(0),Integer(1)],[-Integer(1),-Integer(1),Integer(0)]]))
        >>> A.euler_matrix()
        [ 1  0  0]
        [-1  1  0]
        [-1 -1  1]

    Raise an error if the initial exchange matrix is not acyclic:

    Sage

        sage: A = ClusterAlgebra(matrix([[0,1,-1],[-1,0,1],[1,-1,0]]))
        sage: A.euler_matrix()
        Traceback (most recent call last):
        ...
        ValueError: the initial exchange matrix is not acyclic

    [Python]

        >>> from sage.all import *
        >>> A = ClusterAlgebra(matrix([[Integer(0),Integer(1),-Integer(1)],[-Integer(1),Integer(0),Integer(1)],[Integer(1),-Integer(1),Integer(0)]]))
        >>> A.euler_matrix()
        Traceback (most recent call last):
        ...
        ValueError: the initial exchange matrix is not acyclic

  explore_to_depth(depth)

    Explore the exchange graph of `self` up to distance `depth` from the initial seed.

    INPUT:

    - `depth` – positive integer or infinity; the maximum depth at which to stop searching

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 4])
        sage: A.explore_to_depth(infinity)
        sage: len(A.g_vectors_so_far())
        14

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(4)])
        >>> A.explore_to_depth(infinity)
        >>> len(A.g_vectors_so_far())
        14

  find_g_vector(g_vector, depth=+Infinity)

    Return a mutation sequence to obtain a seed containing the g-vector `g_vector` from the initial seed.

    INPUT:

    - `g_vector` – tuple; the g-vector to find

    - `depth` – positive integer or infinity (default: `infinity`); the maximum distance from `self.current_seed` to reach

    OUTPUT:

    This function returns a list of integers if it can find `g_vector`, otherwise it returns `None`. If the exploring iterator stops, it means that the algebra is of finite type and `g_vector` is not the g-vector of any cluster variable. In this case the function resets the iterator and raises an error.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['G', 2], principal_coefficients=True)
        sage: A.clear_computed_data()
        sage: A.find_g_vector((-2, 3), depth=2)
        sage: A.find_g_vector((-2, 3), depth=3)
        [0, 1, 0]
        sage: A.find_g_vector((1, 1), depth=3)
        sage: A.find_g_vector((1, 1), depth=4)
        Traceback (most recent call last):
        ...
        ValueError: (1, 1) is not the g-vector of any cluster variable of a
         Cluster Algebra with cluster variables x0, x1 and coefficients y0, y1
         over Integer Ring

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['G', Integer(2)], principal_coefficients=True)
        >>> A.clear_computed_data()
        >>> A.find_g_vector((-Integer(2), Integer(3)), depth=Integer(2))
        >>> A.find_g_vector((-Integer(2), Integer(3)), depth=Integer(3))
        [0, 1, 0]
        >>> A.find_g_vector((Integer(1), Integer(1)), depth=Integer(3))
        >>> A.find_g_vector((Integer(1), Integer(1)), depth=Integer(4))
        Traceback (most recent call last):
        ...
        ValueError: (1, 1) is not the g-vector of any cluster variable of a
         Cluster Algebra with cluster variables x0, x1 and coefficients y0, y1
         over Integer Ring

  g_vector_to_d_vector(g)

    Return the d-vector of an element of `self` having g-vector `g`

    INPUT:

    - `g` – the g-vector

    ALGORITHM:

    > This method implements the inverse of the piecewise-linear map \(\\nu_c\) introduced in Section 9.1 of [ReSt2020].

    Warning

    This implementation works only when the initial exchange matrix is acyclic.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(matrix([[0,1,1],[-1,0,1],[-1,-1,0]]))
        sage: A.g_vector_to_d_vector((-1,1,2))
        (1, 0, -1)

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(matrix([[Integer(0),Integer(1),Integer(1)],[-Integer(1),Integer(0),Integer(1)],[-Integer(1),-Integer(1),Integer(0)]]))
        >>> A.g_vector_to_d_vector((-Integer(1),Integer(1),Integer(2)))
        (1, 0, -1)

  g_vectors(mutating_F=True)

    Return an iterator producing all the g-vectors of `self`.

    INPUT:

    - `mutating_F` – boolean (default: `True`); whether to compute F-polynomials; disable this for speed considerations

    ALGORITHM:

    This method does not use the caching framework provided by `self`, but recomputes all the g-vectors from scratch. On the other hand it stores the results so that other methods like `g_vectors_so_far()` can access them afterwards.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 3])
        sage: len(list(A.g_vectors()))
        9

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(3)])
        >>> len(list(A.g_vectors()))
        9

  g_vectors_so_far()

    Return a list of the g-vectors of cluster variables encountered so far.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2])
        sage: A.clear_computed_data()
        sage: A.current_seed().mutate(0)
        sage: sorted(A.g_vectors_so_far())
        [(-1, 1), (0, 1), (1, 0)]

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)])
        >>> A.clear_computed_data()
        >>> A.current_seed().mutate(Integer(0))
        >>> sorted(A.g_vectors_so_far())
        [(-1, 1), (0, 1), (1, 0)]

  gens()

    Return the list of initial cluster variables and coefficients of `self`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2], principal_coefficients=True)
        sage: A.gens()
        (x0, x1, y0, y1)
        sage: A = ClusterAlgebra(['A', 2], principal_coefficients=True, coefficient_prefix='x')
        sage: A.gens()
        (x0, x1, x2, x3)

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)], principal_coefficients=True)
        >>> A.gens()
        (x0, x1, y0, y1)
        >>> A = ClusterAlgebra(['A', Integer(2)], principal_coefficients=True, coefficient_prefix='x')
        >>> A.gens()
        (x0, x1, x2, x3)

  greedy_element(d_vector)

    Return the greedy element with denominator vector `d_vector`.

    INPUT:

    - `d_vector` – tuple of 2 integers; the denominator vector of the element to compute

    ALGORITHM:

    This implements greedy elements of a rank 2 cluster algebra using Equation (1.5) from [LLZ2014].

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', [1, 1], 1])
        sage: A.greedy_element((1, 1))
        (x0^2 + x1^2 + 1)/(x0*x1)

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', [Integer(1), Integer(1)], Integer(1)])
        >>> A.greedy_element((Integer(1), Integer(1)))
        (x0^2 + x1^2 + 1)/(x0*x1)

  initial_cluster_variable(j)

    Return the `j`-th initial cluster variable of `self`.

    INPUT:

    - `j` – integer in `range(self.parent().rank())`; the index of the cluster variable to return

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2], principal_coefficients=True)
        sage: A.initial_cluster_variable(0)
        x0

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)], principal_coefficients=True)
        >>> A.initial_cluster_variable(Integer(0))
        x0

  initial_cluster_variable_names()

    Return the list of initial cluster variable names.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2], principal_coefficients=True)
        sage: A.initial_cluster_variable_names()
        ('x0', 'x1')
        sage: A1 = ClusterAlgebra(['B', 2], cluster_variable_prefix='a')
        sage: A1.initial_cluster_variable_names()
        ('a0', 'a1')

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)], principal_coefficients=True)
        >>> A.initial_cluster_variable_names()
        ('x0', 'x1')
        >>> A1 = ClusterAlgebra(['B', Integer(2)], cluster_variable_prefix='a')
        >>> A1.initial_cluster_variable_names()
        ('a0', 'a1')

  initial_cluster_variables()

    Return the list of initial cluster variables of `self`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2], principal_coefficients=True)
        sage: A.initial_cluster_variables()
        (x0, x1)

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)], principal_coefficients=True)
        >>> A.initial_cluster_variables()
        (x0, x1)

  initial_seed()

    Return the initial seed of `self`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2])
        sage: A.initial_seed()
        The initial seed of a Cluster Algebra with cluster variables x0, x1 and no coefficients over Integer Ring

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)])
        >>> A.initial_seed()
        The initial seed of a Cluster Algebra with cluster variables x0, x1 and no coefficients over Integer Ring

  is_acyclic()

    Return `True` if the exchange matrix in the initial seed is acyclic, `False` otherwise.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(matrix([[0,1,1],[-1,0,1],[-1,-1,0]]))
        sage: A.is_acyclic()
        True
        sage: A = ClusterAlgebra(matrix([[0,1,-1],[-1,0,1],[1,-1,0]]))
        sage: A.is_acyclic()
        False

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(matrix([[Integer(0),Integer(1),Integer(1)],[-Integer(1),Integer(0),Integer(1)],[-Integer(1),-Integer(1),Integer(0)]]))
        >>> A.is_acyclic()
        True
        >>> A = ClusterAlgebra(matrix([[Integer(0),Integer(1),-Integer(1)],[-Integer(1),Integer(0),Integer(1)],[Integer(1),-Integer(1),Integer(0)]]))
        >>> A.is_acyclic()
        False

  lift(x)

    Return `x` as an element of `ambient()`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2], principal_coefficients=True)
        sage: x = A.cluster_variable((1, 0))
        sage: A.lift(x).parent()
        Multivariate Laurent Polynomial Ring in x0, x1, y0, y1 over Integer Ring

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)], principal_coefficients=True)
        >>> x = A.cluster_variable((Integer(1), Integer(0)))
        >>> A.lift(x).parent()
        Multivariate Laurent Polynomial Ring in x0, x1, y0, y1 over Integer Ring

  lower_bound()

    Return the lower bound associated to `self`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['F', 4])
        sage: A.lower_bound()
        Traceback (most recent call last):
        ...
        NotImplementedError: not implemented yet

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['F', Integer(4)])
        >>> A.lower_bound()
        Traceback (most recent call last):
        ...
        NotImplementedError: not implemented yet

  mutate_initial(direction, **kwargs)

    Return the cluster algebra obtained by mutating `self` at the initial seed.

    Warning

    This method is significantly slower than `ClusterAlgebraSeed.mutate()`. It is therefore advisable to use the latter for exploration purposes.

    INPUT:

    - `direction` – in which direction(s) to mutate, it can be:

      - an integer in `range(self.rank())` to mutate in one direction only

      - an iterable of such integers to mutate along a sequence

      - a string “sinks” or “sources” to mutate at all sinks or sources simultaneously

    - `mutating_F` – boolean (default: `True`); whether to compute F-polynomials while mutating

    Note

    While knowing F-polynomials is essential to computing cluster variables, the process of mutating them is quite slow. If you care only about combinatorial data like g-vectors and c-vectors, setting `mutating_F=False` yields significant benefits in terms of speed.

    ALGORITHM:

    This function computes data for the new algebra from known data for the old algebra using Equation (4.2) from [NZ2012] for g-vectors, and Equation (6.21) from [FZ2007] for F-polynomials. The exponent \(h\) in the formula for F-polynomials is `-min(0, old_g_vect[k])` due to [NZ2012] Proposition 4.2.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['F', 4])
        sage: A.explore_to_depth(infinity)
        sage: B = A.b_matrix()
        sage: B.mutate(0)
        sage: A1 = ClusterAlgebra(B)
        sage: A1.explore_to_depth(infinity)
        sage: A2 = A1.mutate_initial(0)
        sage: A2._F_poly_dict == A._F_poly_dict
        True

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['F', Integer(4)])
        >>> A.explore_to_depth(infinity)
        >>> B = A.b_matrix()
        >>> B.mutate(Integer(0))
        >>> A1 = ClusterAlgebra(B)
        >>> A1.explore_to_depth(infinity)
        >>> A2 = A1.mutate_initial(Integer(0))
        >>> A2._F_poly_dict == A._F_poly_dict
        True

    Check that we did not mess up the original algebra because of `UniqueRepresentation`:

    Sage

        sage: A = ClusterAlgebra(['A',2])
        sage: A.mutate_initial(0) is A
        False

    [Python]

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A',Integer(2)])
        >>> A.mutate_initial(Integer(0)) is A
        False

    A faster example without recomputing F-polynomials:

    Sage

        sage: A = ClusterAlgebra(matrix([[0,5],[-5,0]]))
        sage: A.mutate_initial([0,1]*10, mutating_F=False)
        A Cluster Algebra with cluster variables x20, x21 and no coefficients over Integer Ring

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(matrix([[Integer(0),Integer(5)],[-Integer(5),Integer(0)]]))
        >>> A.mutate_initial([Integer(0),Integer(1)]*Integer(10), mutating_F=False)
        A Cluster Algebra with cluster variables x20, x21 and no coefficients over Integer Ring

    Check that Issue #28176 is fixed:

    Sage

        sage: A = ClusterAlgebra( matrix(5,[0,1,-1,1,-1]), cluster_variable_names=['p13'], coefficient_names=['p12','p23','p34','p41']); A
        A Cluster Algebra with cluster variable p13 and coefficients p12, p23, p34, p41 over Integer Ring
        sage: A.mutate_initial(0)
        A Cluster Algebra with cluster variable x0 and coefficients p12, p23, p34, p41 over Integer Ring

        sage: A1 = ClusterAlgebra(['A',[2,1],1])
        sage: A2 = A1.mutate_initial([0,1,0])
        sage: len(A2.g_vectors_so_far()) == len(A2.F_polynomials_so_far())
        True
        sage: all(parent(f) == A2._U for f in A2.F_polynomials_so_far())
        True
        sage: A2.find_g_vector((0,0,1)) == []
        True

    [Python]

        >>> from sage.all import *
        >>> A = ClusterAlgebra( matrix(Integer(5),[Integer(0),Integer(1),-Integer(1),Integer(1),-Integer(1)]), cluster_variable_names=['p13'], coefficient_names=['p12','p23','p34','p41']); A
        A Cluster Algebra with cluster variable p13 and coefficients p12, p23, p34, p41 over Integer Ring
        >>> A.mutate_initial(Integer(0))
        A Cluster Algebra with cluster variable x0 and coefficients p12, p23, p34, p41 over Integer Ring

        >>> A1 = ClusterAlgebra(['A',[Integer(2),Integer(1)],Integer(1)])
        >>> A2 = A1.mutate_initial([Integer(0),Integer(1),Integer(0)])
        >>> len(A2.g_vectors_so_far()) == len(A2.F_polynomials_so_far())
        True
        >>> all(parent(f) == A2._U for f in A2.F_polynomials_so_far())
        True
        >>> A2.find_g_vector((Integer(0),Integer(0),Integer(1))) == []
        True

  rank()

    Return the rank of `self`, i.e. the number of cluster variables in any seed.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2], principal_coefficients=True); A
        A Cluster Algebra with cluster variables x0, x1
         and coefficients y0, y1 over Integer Ring
        sage: A.rank()
        2

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)], principal_coefficients=True); A
        A Cluster Algebra with cluster variables x0, x1
         and coefficients y0, y1 over Integer Ring
        >>> A.rank()
        2

  reset_current_seed()

    Reset the value reported by `current_seed()` to `initial_seed()`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2])
        sage: A.clear_computed_data()
        sage: A.current_seed().mutate([1, 0])
        sage: A.current_seed() == A.initial_seed()
        False
        sage: A.reset_current_seed()
        sage: A.current_seed() == A.initial_seed()
        True

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)])
        >>> A.clear_computed_data()
        >>> A.current_seed().mutate([Integer(1), Integer(0)])
        >>> A.current_seed() == A.initial_seed()
        False
        >>> A.reset_current_seed()
        >>> A.current_seed() == A.initial_seed()
        True

  reset_exploring_iterator(mutating_F=True)

    Reset the iterator used to explore `self`.

    INPUT:

    - `mutating_F` – boolean (default: `True`); whether to also compute F-polynomials; disable this for speed considerations

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 4])
        sage: A.clear_computed_data()
        sage: A.reset_exploring_iterator(mutating_F=False)
        sage: A.explore_to_depth(infinity)
        sage: len(A.g_vectors_so_far())
        14
        sage: len(A.F_polynomials_so_far())
        4

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(4)])
        >>> A.clear_computed_data()
        >>> A.reset_exploring_iterator(mutating_F=False)
        >>> A.explore_to_depth(infinity)
        >>> len(A.g_vectors_so_far())
        14
        >>> len(A.F_polynomials_so_far())
        4

  retract(x)

    Return `x` as an element of `self`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2], principal_coefficients=True)
        sage: L = A.ambient()
        sage: x = L.gen(0)
        sage: A.retract(x).parent()
        A Cluster Algebra with cluster variables x0, x1 and coefficients y0, y1 over Integer Ring

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)], principal_coefficients=True)
        >>> L = A.ambient()
        >>> x = L.gen(Integer(0))
        >>> A.retract(x).parent()
        A Cluster Algebra with cluster variables x0, x1 and coefficients y0, y1 over Integer Ring

  scalars()

    Return the ring of scalars over which `self` is defined.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2])
        sage: A.scalars()
        Integer Ring

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)])
        >>> A.scalars()
        Integer Ring

  seeds(**kwargs)

    Return an iterator running over seeds of `self`.

    INPUT:

    - `from_current_seed` – boolean (default: `False`); whether to start the iterator from `current_seed()` or `initial_seed()`

    - `mutating_F` – boolean (default: `True`); whether to compute F-polynomials also; disable this for speed considerations

    - `allowed_directions` – iterable of integers (default: `range(self.rank())`); the directions in which to mutate

    - `depth` – positive integer or infinity (default: `infinity`); the maximum depth at which to stop searching

    - `catch_KeyboardInterrupt` – boolean (default: `False`); whether to catch `KeyboardInterrupt` and return it rather then raising an exception – this allows the iterator returned by this method to be resumed after being interrupted

    ALGORITHM:

    This function traverses the exchange graph in a breadth-first search.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 4])
        sage: A.clear_computed_data()
        sage: seeds = A.seeds(allowed_directions=[3, 0, 1])
        sage: _ = list(seeds)
        sage: sorted(A.g_vectors_so_far())
        [(-1, 0, 0, 0),
         (-1, 1, 0, 0),
         (0, -1, 0, 0),
         (0, 0, 0, -1),
         (0, 0, 0, 1),
         (0, 0, 1, 0),
         (0, 1, 0, 0),
         (1, 0, 0, 0)]

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(4)])
        >>> A.clear_computed_data()
        >>> seeds = A.seeds(allowed_directions=[Integer(3), Integer(0), Integer(1)])
        >>> _ = list(seeds)
        >>> sorted(A.g_vectors_so_far())
        [(-1, 0, 0, 0),
         (-1, 1, 0, 0),
         (0, -1, 0, 0),
         (0, 0, 0, -1),
         (0, 0, 0, 1),
         (0, 0, 1, 0),
         (0, 1, 0, 0),
         (1, 0, 0, 0)]

  set_current_seed(seed)

    Set the value reported by `current_seed()` to `seed`, if it makes sense.

    INPUT:

    - `seed` – a `ClusterAlgebraSeed`

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2])
        sage: A.clear_computed_data()
        sage: S = copy(A.current_seed())
        sage: S.mutate([0, 1, 0])
        sage: A.current_seed() == S
        False
        sage: A.set_current_seed(S)
        sage: A.current_seed() == S
        True
        sage: A1 = ClusterAlgebra(['B', 2])
        sage: A.set_current_seed(A1.initial_seed())
        Traceback (most recent call last):
        ...
        ValueError: this is not a seed in this cluster algebra

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)])
        >>> A.clear_computed_data()
        >>> S = copy(A.current_seed())
        >>> S.mutate([Integer(0), Integer(1), Integer(0)])
        >>> A.current_seed() == S
        False
        >>> A.set_current_seed(S)
        >>> A.current_seed() == S
        True
        >>> A1 = ClusterAlgebra(['B', Integer(2)])
        >>> A.set_current_seed(A1.initial_seed())
        Traceback (most recent call last):
        ...
        ValueError: this is not a seed in this cluster algebra

  theta_basis_F_polynomial(g_vector)

    Return the F-polynomial of the element of the theta basis of `self` with g-vector `g_vector`.

    INPUT:

    - `g_vector` – tuple; the g-vector of the F-polynomial to compute

    Warning

    Elements of the theta basis do not satisfy a separation of additions formula. See the implementation of `sage.algebras.cluster_algebra.theta_basis_F_polynomial()` for further details.

    ALGORITHM:

    This method uses the fact that the greedy basis and the theta basis coincide in rank 2 and uses the former defining recursion (Equation (1.5) from [LLZ2014]) to compute.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(matrix([[0,-3],[2,0]]), principal_coefficients=True)
        sage: A.theta_basis_F_polynomial((-1,-1))
        u0^4*u1 + 4*u0^3*u1 + 6*u0^2*u1 + 4*u0*u1 + u0 + u1 + 1

        sage: A = ClusterAlgebra(['F', 4])
        sage: A.theta_basis_F_polynomial((1, 0, 0, 0))
        Traceback (most recent call last):
        ...
        NotImplementedError: currently only implemented for cluster algebras of rank 2

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(matrix([[Integer(0),-Integer(3)],[Integer(2),Integer(0)]]), principal_coefficients=True)
        >>> A.theta_basis_F_polynomial((-Integer(1),-Integer(1)))
        u0^4*u1 + 4*u0^3*u1 + 6*u0^2*u1 + 4*u0*u1 + u0 + u1 + 1

        >>> A = ClusterAlgebra(['F', Integer(4)])
        >>> A.theta_basis_F_polynomial((Integer(1), Integer(0), Integer(0), Integer(0)))
        Traceback (most recent call last):
        ...
        NotImplementedError: currently only implemented for cluster algebras of rank 2

  theta_basis_element(g_vector)

    Return the element of the theta basis of `self` with g-vector `g_vector`.

    INPUT:

    - `g_vector` – tuple; the g-vector of the element to compute

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(matrix([[0,-3],[2,0]]), principal_coefficients=True)
        sage: A.theta_basis_element((-1,-1))
        (x1^8*y0^4*y1 + 4*x1^6*y0^3*y1 + 6*x1^4*y0^2*y1 + x0^3*x1^2*y0 + 4*x1^2*y0*y1 + x0^3 + y1)/(x0^4*x1)

        sage: A = ClusterAlgebra(['F', 4])
        sage: A.theta_basis_element((1, 0, 0, 0))
        Traceback (most recent call last):
        ...
        NotImplementedError: currently only implemented for cluster algebras of rank 2

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(matrix([[Integer(0),-Integer(3)],[Integer(2),Integer(0)]]), principal_coefficients=True)
        >>> A.theta_basis_element((-Integer(1),-Integer(1)))
        (x1^8*y0^4*y1 + 4*x1^6*y0^3*y1 + 6*x1^4*y0^2*y1 + x0^3*x1^2*y0 + 4*x1^2*y0*y1 + x0^3 + y1)/(x0^4*x1)

        >>> A = ClusterAlgebra(['F', Integer(4)])
        >>> A.theta_basis_element((Integer(1), Integer(0), Integer(0), Integer(0)))
        Traceback (most recent call last):
        ...
        NotImplementedError: currently only implemented for cluster algebras of rank 2

    Note

    Elements of the theta basis correspond with the associated cluster monomial only for appropriate coefficient choices. For example:

    Sage

        sage: A = ClusterAlgebra(matrix([[0,-1],[1,0],[-1,0]]))
        sage: A.theta_basis_element((-1,0))
        (x1 + y0)/(x0*y0)

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(matrix([[Integer(0),-Integer(1)],[Integer(1),Integer(0)],[-Integer(1),Integer(0)]]))
        >>> A.theta_basis_element((-Integer(1),Integer(0)))
        (x1 + y0)/(x0*y0)

    while:

    Sage

        sage: _ = A.find_g_vector((-1,0));
        sage: A.cluster_variable((-1,0))
        (x1 + y0)/x0

    [Python]

        >>> from sage.all import *
        >>> _ = A.find_g_vector((-Integer(1),Integer(0)));
        >>> A.cluster_variable((-Integer(1),Integer(0)))
        (x1 + y0)/x0

    In particular theta basis elements do not satisfy a separation of additions formula.

    Warning

    Currently only cluster algebras of rank 2 are supported

    See also

    `sage.algebras.cluster_algebra.theta_basis_F_polynomial()`

  upper_bound()

    Return the upper bound associated to `self`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['F', 4])
        sage: A.upper_bound()
        Traceback (most recent call last):
        ...
        NotImplementedError: not implemented yet

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['F', Integer(4)])
        >>> A.upper_bound()
        Traceback (most recent call last):
        ...
        NotImplementedError: not implemented yet

  upper_cluster_algebra()

    Return the upper cluster algebra associated to `self`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['F', 4])
        sage: A.upper_cluster_algebra()
        Traceback (most recent call last):
        ...
        NotImplementedError: not implemented yet

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['F', Integer(4)])
        >>> A.upper_cluster_algebra()
        Traceback (most recent call last):
        ...
        NotImplementedError: not implemented yet

class sage.algebras.cluster_algebra.ClusterAlgebraElement

  Bases: `ElementWrapper`

  An element of a cluster algebra.

  d_vector()

    Return the denominator vector of `self` as a tuple of integers.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['F', 4], principal_coefficients=True)
        sage: A.current_seed().mutate([0, 2, 1])
        sage: x = A.cluster_variable((-1, 2, -2, 2)) * A.cluster_variable((0, 0, 0, 1))**2
        sage: x.d_vector()
        (1, 1, 2, -2)

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['F', Integer(4)], principal_coefficients=True)
        >>> A.current_seed().mutate([Integer(0), Integer(2), Integer(1)])
        >>> x = A.cluster_variable((-Integer(1), Integer(2), -Integer(2), Integer(2))) * A.cluster_variable((Integer(0), Integer(0), Integer(0), Integer(1)))**Integer(2)
        >>> x.d_vector()
        (1, 1, 2, -2)

class sage.algebras.cluster_algebra.ClusterAlgebraSeed(B, C, G, parent, **kwargs)

  Bases: `SageObject`

  A seed in a Cluster Algebra.

  INPUT:

  - `B` – a skew-symmetrizable integer matrix

  - `C` – the matrix of c-vectors of `self`

  - `G` – the matrix of g-vectors of `self`

  - `parent` – `ClusterAlgebra`; the algebra to which the seed belongs

  - `path` – list (default: `[]`); the mutation sequence from the initial seed of `parent` to `self`

  Warning

  Seeds should not be created manually: no test is performed to assert that they are built from consistent data nor that they really are seeds of `parent`. If you create seeds with inconsistent data all sort of things can go wrong, even `__eq__()` is no longer guaranteed to give correct answers. Use at your own risk.

  F_polynomial(j)

    Return the `j`-th F-polynomial of `self`.

    INPUT:

    - `j` – integer in `range(self.parent().rank())`; the index of the F-polynomial to return

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 3])
        sage: S = A.initial_seed()
        sage: S.F_polynomial(0)
        1

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(3)])
        >>> S = A.initial_seed()
        >>> S.F_polynomial(Integer(0))
        1

  F_polynomials()

    Return all the F-polynomials of `self`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 3])
        sage: S = A.initial_seed()
        sage: S.F_polynomials()
        [1, 1, 1]

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(3)])
        >>> S = A.initial_seed()
        >>> S.F_polynomials()
        [1, 1, 1]

  b_matrix()

    Return the exchange matrix of `self`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 3])
        sage: S = A.initial_seed()
        sage: S.b_matrix()
        [ 0  1  0]
        [-1  0 -1]
        [ 0  1  0]

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(3)])
        >>> S = A.initial_seed()
        >>> S.b_matrix()
        [ 0  1  0]
        [-1  0 -1]
        [ 0  1  0]

  c_matrix()

    Return the matrix whose columns are the c-vectors of `self`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 3])
        sage: S = A.initial_seed()
        sage: S.c_matrix()
        [1 0 0]
        [0 1 0]
        [0 0 1]

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(3)])
        >>> S = A.initial_seed()
        >>> S.c_matrix()
        [1 0 0]
        [0 1 0]
        [0 0 1]

  c_vector(j)

    Return the `j`-th c-vector of `self`.

    INPUT:

    - `j` – integer in `range(self.parent().rank())`; the index of the c-vector to return

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 3])
        sage: S = A.initial_seed()
        sage: S.c_vector(0)
        (1, 0, 0)
        sage: S.mutate(0)
        sage: S.c_vector(0)
        (-1, 0, 0)
        sage: S.c_vector(1)
        (1, 1, 0)

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(3)])
        >>> S = A.initial_seed()
        >>> S.c_vector(Integer(0))
        (1, 0, 0)
        >>> S.mutate(Integer(0))
        >>> S.c_vector(Integer(0))
        (-1, 0, 0)
        >>> S.c_vector(Integer(1))
        (1, 1, 0)

  c_vectors()

    Return all the c-vectors of `self`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 3])
        sage: S = A.initial_seed()
        sage: S.c_vectors()
        [(1, 0, 0), (0, 1, 0), (0, 0, 1)]

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(3)])
        >>> S = A.initial_seed()
        >>> S.c_vectors()
        [(1, 0, 0), (0, 1, 0), (0, 0, 1)]

  cluster_variable(j)

    Return the `j`-th cluster variable of `self`.

    INPUT:

    - `j` – integer in `range(self.parent().rank())`; the index of the cluster variable to return

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 3])
        sage: S = A.initial_seed()
        sage: S.cluster_variable(0)
        x0
        sage: S.mutate(0)
        sage: S.cluster_variable(0)
        (x1 + 1)/x0

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(3)])
        >>> S = A.initial_seed()
        >>> S.cluster_variable(Integer(0))
        x0
        >>> S.mutate(Integer(0))
        >>> S.cluster_variable(Integer(0))
        (x1 + 1)/x0

  cluster_variables()

    Return all the cluster variables of `self`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 3])
        sage: S = A.initial_seed()
        sage: S.cluster_variables()
        [x0, x1, x2]

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(3)])
        >>> S = A.initial_seed()
        >>> S.cluster_variables()
        [x0, x1, x2]

  depth()
    Return the length of a mutation sequence from the initial seed

      of `parent()` to `self`.

    Warning

    This is the length of the mutation sequence returned by `path_from_initial_seed()`, which need not be the shortest possible.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2])
        sage: S1 = A.initial_seed()
        sage: S1.mutate([0, 1, 0, 1])
        sage: S1.depth()
        4
        sage: S2 = A.initial_seed()
        sage: S2.mutate(1)
        sage: S2.depth()
        1
        sage: S1 == S2
        True

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)])
        >>> S1 = A.initial_seed()
        >>> S1.mutate([Integer(0), Integer(1), Integer(0), Integer(1)])
        >>> S1.depth()
        4
        >>> S2 = A.initial_seed()
        >>> S2.mutate(Integer(1))
        >>> S2.depth()
        1
        >>> S1 == S2
        True

  g_matrix()

    Return the matrix whose columns are the g-vectors of `self`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 3])
        sage: S = A.initial_seed()
        sage: S.g_matrix()
        [1 0 0]
        [0 1 0]
        [0 0 1]

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(3)])
        >>> S = A.initial_seed()
        >>> S.g_matrix()
        [1 0 0]
        [0 1 0]
        [0 0 1]

  g_vector(j)

    Return the `j`-th g-vector of `self`.

    INPUT:

    - `j` – integer in `range(self.parent().rank())`; the index of the g-vector to return

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 3])
        sage: S = A.initial_seed()
        sage: S.g_vector(0)
        (1, 0, 0)

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(3)])
        >>> S = A.initial_seed()
        >>> S.g_vector(Integer(0))
        (1, 0, 0)

  g_vectors()

    Return all the g-vectors of `self`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 3])
        sage: S = A.initial_seed()
        sage: S.g_vectors()
        [(1, 0, 0), (0, 1, 0), (0, 0, 1)]

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(3)])
        >>> S = A.initial_seed()
        >>> S.g_vectors()
        [(1, 0, 0), (0, 1, 0), (0, 0, 1)]

  mutate(direction, **kwargs)

    Mutate `self`.

    INPUT:

    - `direction` – in which direction(s) to mutate, it can be:

      - an integer in `range(self.rank())` to mutate in one direction only

      - an iterable of such integers to mutate along a sequence

      - a string “sinks” or “sources” to mutate at all sinks or sources simultaneously

    - `inplace` – boolean (default: `True`); whether to mutate in place or to return a new object

    - `mutating_F` – boolean (default: `True`); whether to compute F-polynomials while mutating

    Note

    While knowing F-polynomials is essential to computing cluster variables, the process of mutating them is quite slow. If you care only about combinatorial data like g-vectors and c-vectors, setting `mutating_F=False` yields significant benefits in terms of speed.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2])
        sage: S = A.initial_seed()
        sage: S.mutate(0); S
        The seed of a Cluster Algebra with cluster variables x0, x1
         and no coefficients over Integer Ring obtained from the initial
         by mutating in direction 0
        sage: S.mutate(5)
        Traceback (most recent call last):
        ...
        ValueError: cannot mutate in direction 5

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)])
        >>> S = A.initial_seed()
        >>> S.mutate(Integer(0)); S
        The seed of a Cluster Algebra with cluster variables x0, x1
         and no coefficients over Integer Ring obtained from the initial
         by mutating in direction 0
        >>> S.mutate(Integer(5))
        Traceback (most recent call last):
        ...
        ValueError: cannot mutate in direction 5

  parent()

    Return the parent of `self`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['B', 3])
        sage: A.current_seed().parent() == A
        True

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['B', Integer(3)])
        >>> A.current_seed().parent() == A
        True

  path_from_initial_seed()

    Return a mutation sequence from the initial seed of `parent()` to `self`.

    Warning

    This is the path used to compute `self` and it does not have to be the shortest possible.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['A', 2])
        sage: S1 = A.initial_seed()
        sage: S1.mutate([0, 1, 0, 1])
        sage: S1.path_from_initial_seed()
        [0, 1, 0, 1]
        sage: S2 = A.initial_seed()
        sage: S2.mutate(1)
        sage: S2.path_from_initial_seed()
        [1]
        sage: S1 == S2
        True

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['A', Integer(2)])
        >>> S1 = A.initial_seed()
        >>> S1.mutate([Integer(0), Integer(1), Integer(0), Integer(1)])
        >>> S1.path_from_initial_seed()
        [0, 1, 0, 1]
        >>> S2 = A.initial_seed()
        >>> S2.mutate(Integer(1))
        >>> S2.path_from_initial_seed()
        [1]
        >>> S1 == S2
        True

class sage.algebras.cluster_algebra.PrincipalClusterAlgebraElement

  Bases: `ClusterAlgebraElement`

  An element in a cluster algebra with principle coefficients.

  F_polynomial()

    Return the F-polynomial of `self`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['B', 2], principal_coefficients=True)
        sage: S = A.initial_seed()
        sage: S.mutate([0, 1, 0])
        sage: S.cluster_variable(0).F_polynomial() == S.F_polynomial(0)
        True
        sage: sum(A.initial_cluster_variables()).F_polynomial()
        Traceback (most recent call last):
        ...
        ValueError: this element does not have a well defined g-vector

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['B', Integer(2)], principal_coefficients=True)
        >>> S = A.initial_seed()
        >>> S.mutate([Integer(0), Integer(1), Integer(0)])
        >>> S.cluster_variable(Integer(0)).F_polynomial() == S.F_polynomial(Integer(0))
        True
        >>> sum(A.initial_cluster_variables()).F_polynomial()
        Traceback (most recent call last):
        ...
        ValueError: this element does not have a well defined g-vector

  g_vector()

    Return the g-vector of `self`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['B', 2], principal_coefficients=True)
        sage: A.cluster_variable((1, 0)).g_vector() == (1, 0)
        True
        sage: sum(A.initial_cluster_variables()).g_vector()
        Traceback (most recent call last):
        ...
        ValueError: this element does not have a well defined g-vector

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['B', Integer(2)], principal_coefficients=True)
        >>> A.cluster_variable((Integer(1), Integer(0))).g_vector() == (Integer(1), Integer(0))
        True
        >>> sum(A.initial_cluster_variables()).g_vector()
        Traceback (most recent call last):
        ...
        ValueError: this element does not have a well defined g-vector

  homogeneous_components()

    Return a dictionary of the homogeneous components of `self`.

    OUTPUT:

    A dictionary whose keys are homogeneous degrees and whose values are the summands of `self` of the given degree.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['B', 2], principal_coefficients=True)
        sage: x = A.cluster_variable((1, 0)) + A.cluster_variable((0, 1))
        sage: x.homogeneous_components()
        {(0, 1): x1, (1, 0): x0}

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['B', Integer(2)], principal_coefficients=True)
        >>> x = A.cluster_variable((Integer(1), Integer(0))) + A.cluster_variable((Integer(0), Integer(1)))
        >>> x.homogeneous_components()
        {(0, 1): x1, (1, 0): x0}

  is_homogeneous()

    Return `True` if `self` is a homogeneous element of `self.parent()`.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(['B', 2], principal_coefficients=True)
        sage: A.cluster_variable((1, 0)).is_homogeneous()
        True
        sage: x = A.cluster_variable((1, 0)) + A.cluster_variable((0, 1))
        sage: x.is_homogeneous()
        False

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(['B', Integer(2)], principal_coefficients=True)
        >>> A.cluster_variable((Integer(1), Integer(0))).is_homogeneous()
        True
        >>> x = A.cluster_variable((Integer(1), Integer(0))) + A.cluster_variable((Integer(0), Integer(1)))
        >>> x.is_homogeneous()
        False

  theta_basis_decomposition()

    Return the decomposition of `self` in the theta basis.

    OUTPUT:

    A dictionary whose keys are the g-vectors and whose values are the coefficients in the decomposition of `self` in the theta basis.

    EXAMPLES:

    Sage

        sage: A = ClusterAlgebra(matrix([[0,-2],[3,0]]), principal_coefficients=True)
        sage: f = (A.theta_basis_element((1,0)) + A.theta_basis_element((0,1)))**2 + A.coefficient(1)* A.theta_basis_element((1,1))
        sage: decomposition = f.theta_basis_decomposition()
        sage: sum(decomposition[g] * A.theta_basis_element(g) for g in decomposition) == f
        True
        sage: f = A.theta_basis_element((4,-4))*A.theta_basis_element((1,-1))
        sage: decomposition =  f.theta_basis_decomposition()
        sage: sum(decomposition[g] * A.theta_basis_element(g) for g in decomposition) == f
        True

    Python

        >>> from sage.all import *
        >>> A = ClusterAlgebra(matrix([[Integer(0),-Integer(2)],[Integer(3),Integer(0)]]), principal_coefficients=True)
        >>> f = (A.theta_basis_element((Integer(1),Integer(0))) + A.theta_basis_element((Integer(0),Integer(1))))**Integer(2) + A.coefficient(Integer(1))* A.theta_basis_element((Integer(1),Integer(1)))
        >>> decomposition = f.theta_basis_decomposition()
        >>> sum(decomposition[g] * A.theta_basis_element(g) for g in decomposition) == f
        True
        >>> f = A.theta_basis_element((Integer(4),-Integer(4)))*A.theta_basis_element((Integer(1),-Integer(1)))
        >>> decomposition =  f.theta_basis_decomposition()
        >>> sum(decomposition[g] * A.theta_basis_element(g) for g in decomposition) == f
        True