Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the Links-Gould polynomial invariant for links #33798

Closed
soehms opened this issue May 4, 2022 · 24 comments
Closed

Implement the Links-Gould polynomial invariant for links #33798

soehms opened this issue May 4, 2022 · 24 comments

Comments

@soehms
Copy link
Member

soehms commented May 4, 2022

At the moment there doesn't seem to be any public available calculator for this invariant. We will implement it straight forward according to the definition given in A CUBIC DEFINING ALGEBRA FOR THE LINKS-GOULD POLYNOMIAL by Marin and Wagner, section 3. Calculations are done on sparse matrices over a univariate quotient polynomial ring over a two variate Laurent polynomial ring since the square-roots of a non monomial polynomial are involved. This is just necessary for the calculation. The result simplifies to a proper two variate Laurent polynomial. As the dimension of these matrices are given by 4^num_strands the performance slows down accordingly.

In a second step we could try to figure out if the approach followed in a 2013 paper of David de Witt respective a 2019 paper of Cristina Ana-Maria Anghel would improve performance.

Some examples: On an i7 CPU the calculation for three strand braids need less than a second. For four strand braids it takes between two and six seconds whereas for five strand braids between one and two minutes are needed. For example K8_1 takes one and a half minute. Braids with six strands need more than than 20 minutes (for example K10_1 22 minutes).

Component: algebraic topology

Keywords: Links-Gould polynomial knots links

Author: Sebastian Oehms

Branch/Commit: 08e3bfe

Reviewer: Travis Scrimshaw

Issue created by migration from https://trac.sagemath.org/ticket/33798

@soehms soehms added this to the sage-9.7 milestone May 4, 2022
@soehms
Copy link
Member Author

soehms commented May 4, 2022

Branch: u/soehms/links_gould_poly_33798

@soehms
Copy link
Member Author

soehms commented May 4, 2022

Commit: 73412bf

@soehms
Copy link
Member Author

soehms commented May 4, 2022

Author: Sebastian Oehms

@soehms
Copy link
Member Author

soehms commented May 4, 2022

New commits:

73412bf33798: initial version

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Jun 8, 2022

Branch pushed to git repo; I updated commit sha1. New commits:

0ab620cMerge branch 'u/soehms/links_gould_poly_33798' of trac.sagemath.org:sage into links_gould_poly_33798

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Jun 8, 2022

Changed commit from 73412bf to 0ab620c

@soehms
Copy link
Member Author

soehms commented Jun 8, 2022

comment:4

I just fixed a merge conflict.

@tscrim
Copy link
Collaborator

tscrim commented Jun 16, 2022

comment:5

Since everything only involves square roots of the variables, wouldn't it be better to replace t_i with t_i^2? That way you can do everything in polynomial rings, which should be much faster. Afterwards you could then substitute back.

@soehms
Copy link
Member Author

soehms commented Jun 17, 2022

comment:6

Replying to @tscrim:

Since everything only involves square roots of the variables, wouldn't it be better to replace t_i with t_i^2? That way you can do everything in polynomial rings, which should be much faster. Afterwards you could then substitute back.

Maybe I don't understand your idea exactly. I've tried to use a quotient ring over a three variate polynomial ring the third variable of which corresponding to the term abbreviated Y in Ivan Marin's paper. At the moment I don't have access to my notes about that, since I'm on vacation. But this was even slower than using the symbolic ring.

@tscrim
Copy link
Collaborator

tscrim commented Jun 17, 2022

comment:7

Replying to @soehms:

Replying to @tscrim:

Since everything only involves square roots of the variables, wouldn't it be better to replace t_i with t_i^2? That way you can do everything in polynomial rings, which should be much faster. Afterwards you could then substitute back.

Maybe I don't understand your idea exactly. I've tried to use a quotient ring over a three variate polynomial ring the third variable of which corresponding to the term abbreviated Y in Ivan Marin's paper.

I am not suggesting that. In the description, you say you use SR since for the Laurent polynomial ring variables "x,y", you use x1/2 and y1/2 in the computations. I am just saying use the variables t0 = x1/2 and t1 = y1/2 for the computations to avoid SR. Then in the final computation, you just rescale all of the exponents by 1/2 since the result is a polynomial. Although we could just output with the squared variables with a .. WARNING:: indicating the change in convention.

At the moment I don't have access to my notes about that, since I'm on vacation. But this was even slower than using the symbolic ring.

No problem. Enjoy your vacation.

I would have the internal cached method use fixed variable names and then do a substitution for different user input to not redo the computation just because the variable names change.

Also, typo: beeing.

@soehms
Copy link
Member Author

soehms commented Jun 17, 2022

comment:8

Replying to @tscrim:

Replying to @soehms:

Replying to @tscrim:

Since everything only involves square roots of the variables, wouldn't it be better to replace t_i with t_i^2? That way you can do everything in polynomial rings, which should be much faster. Afterwards you could then substitute back.

Maybe I don't understand your idea exactly. I've tried to use a quotient ring over a three variate polynomial ring the third variable of which corresponding to the term abbreviated Y in Ivan Marin's paper.

I am not suggesting that. In the description, you say you use SR since for the Laurent polynomial ring variables "x,y", you use x1/2 and y1/2 in the computations. I am just saying use the variables t0 = x1/2 and t1 = y1/2 for the computations to avoid SR. Then in the final computation, you just rescale all of the exponents by 1/2 since the result is a polynomial. Although we could just output with the squared variables with a .. WARNING:: indicating the change in convention.

It's not just squares of the variables, there are also squares of non monomial Laurent polynomials (see the Y). Apparently it's a non-trivial fact that the result always simplifies to Laurent polynomials.

Anyway, I will think about this once again, when I'm back home. Thanks for looking at the ticket!

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Jul 4, 2022

Changed commit from 0ab620c to 18bbfda

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Jul 4, 2022

Branch pushed to git repo; I updated commit sha1. New commits:

7785b48Merge branch 'u/soehms/links_gould_poly_33798' of trac.sagemath.org:sage into links_gould_poly_33798
18bbfda33798: use quotient ring of Laurent polynomials

@soehms

This comment has been minimized.

@soehms
Copy link
Member Author

soehms commented Jul 4, 2022

comment:10

Travis, you are right! Indeed, the quotient ring leads to a faster implementation. It seems that I didn't use sparse matrices for this ring in my former tests (note that for symbolics there is no proper sparse implementation and thus dense matrices perform better in this setting).

Nevertheless I keep the usage of the symbolic ring as a second implementation option, since it might be useful for cross checks and verifications.

@tscrim
Copy link
Collaborator

tscrim commented Jul 15, 2022

comment:11

Sorry for taking so long to get to this.

I am glad you were able to speed it up. How does it compare to doing computations in

            LC = LaurentPolynomialRing(ZZ, 's0r, s1r')
            s0r, s1r = LC.gens()
            LR = PolynomialRing(LC 'Yr')
            Yr = LR.gen()
            pqr = Yr**2 + (s0r**2-1)*(s1r**2 -1)

This way it is the quotient ring of a univariate polynomial ring. I would think working with quotients there would be faster since the data type is more simple.

Also, I would have

def links_gould_polynomial(self, varnames=None, use_symbolics=False):
    if varnames is not None:
         poly = links_gould_polynomial(use_symbolics=use_symbolics)
         R = PolynomialRing(ZZ, varnames)
         t0, t1 = R.gens()
         return poly(t0=t0, t1=t1)
    varnames = 't0, t1'

to not do the full computation again when only the variable names have changed.

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Jul 18, 2022

Changed commit from 18bbfda to 08e3bfe

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Jul 18, 2022

Branch pushed to git repo; I updated commit sha1. New commits:

ed115d5Merge branch 'u/soehms/links_gould_poly_33798' of trac.sagemath.org:sage into links_gould_poly_33798
08e3bfe33798: improving performance once more

@soehms
Copy link
Member Author

soehms commented Jul 18, 2022

comment:13

Replying to @tscrim:

Sorry for taking so long to get to this.

No problem!

I am glad you were able to speed it up. How does it compare to doing computations in

            LC = LaurentPolynomialRing(ZZ, 's0r, s1r')
            s0r, s1r = LC.gens()
            LR = PolynomialRing(LC 'Yr')
            Yr = LR.gen()
            pqr = Yr**2 + (s0r**2-1)*(s1r**2 -1)

This way it is the quotient ring of a univariate polynomial ring. I would think working with quotients there would be faster since the data type is more simple.

Many thanks for this useful suggestion. Once again, I could achieve a remarkable improvement of performance with it. The calculation for knot K10_1 which didn't terminate using symbolics within a day, now needs 22 minutes. With the former quotient ring version it has been 4 hours.

Furthermore, I now could successfully run a crosscheck over all links listed in the KnotInfo and LinkInfo databases having less than 5 strands (3342 in sum) against the according specialization of the formal Markov trace on the cubic Hecke algebra (see method formal_markov_trace of class CubicHeckeElement in ticket #29717) in less than 5.5 hours.

Also, I would have

def links_gould_polynomial(self, varnames=None, use_symbolics=False):
    if varnames is not None:
         poly = links_gould_polynomial(use_symbolics=use_symbolics)
         R = PolynomialRing(ZZ, varnames)
         t0, t1 = R.gens()
         return poly(t0=t0, t1=t1)
    varnames = 't0, t1'

to not do the full computation again when only the variable names have changed.

This is done now, as well!

BTW: You may have asked why I wrote (R1*R2*R1 - R2*R1*R2).is_zero()) before. The reason was that comparison in quotient rings over multivariate Laurent polynomial rings doesn't work. I will open a corresponding ticket about that, soon.

@soehms

This comment has been minimized.

@tscrim
Copy link
Collaborator

tscrim commented Jul 19, 2022

comment:15

Thank you. I am glad it was useful. LGTM.

@tscrim
Copy link
Collaborator

tscrim commented Jul 19, 2022

Reviewer: Travis Scrimshaw

@soehms
Copy link
Member Author

soehms commented Jul 19, 2022

comment:16

Replying to @tscrim:

Thank you. I am glad it was useful. LGTM.

I'm also glad. Thank you, too!

@vbraun
Copy link
Member

vbraun commented Jul 28, 2022

Changed branch from u/soehms/links_gould_poly_33798 to 08e3bfe

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants