| 1 | initial version |
A lazy alternative to @Max Alekseyev's excellent answer is to use one of Sage's symbolic solvers
| 2 | No.2 Revision |
A lazy alternative to @Max Alekseyev's excellent answer is to use one of Sage's symbolic solvers and to filter out the undeterminates returned by these solvers.
After running :
SymUnk=list(map(SR, (x, y, z)))
def foo():
Sols=[]
for fff in Combinations(Lf, 3):
if len((B:=RR.ideal(fff).groebner_basis()))==3:
SSol=solve([SR(u)==0 for u in B],
SymUnk,
solution_dict=True)
Sol=[]
for S in SSol:
SRR={}
for u in S.keys():
try:
SRR|={RR(u):RR(S[u])}
except:
continue
Sol+=[SRR]
Sols+=[Sol]
return Sols
Running :
sage: %time Sols=foo()
CPU times: user 2min 1s, sys: 105 ms, total: 2min 1s
Wall time: 1min 48s
sage: len(Sols)
245
returns 245 solutions. However, many of them are duplicates, as can be shown by indexing them on the `groebner_b
| 3 | No.3 Revision |
A lazy alternative to @Max Alekseyev's excellent answer is to use one of Sage's symbolic solvers solvers, which already take care of non-zero-dimension solutions, and to filter out the undeterminates returned by these solvers.
After running :
SymUnk=list(map(SR, (x, y, z)))
def foo():
Sols=[]
for fff in Combinations(Lf, 3):
if len((B:=RR.ideal(fff).groebner_basis()))==3:
SSol=solve([SR(u)==0 for u in B],
SymUnk,
solution_dict=True)
Sol=[]
for S in SSol:
SRR={}
for u in S.keys():
try:
SRR|={RR(u):RR(S[u])}
except:
continue
Sol+=[SRR]
Sols+=[Sol]
return Sols
Running :
sage: %time Sols=foo()
CPU times: user 2min 1s, sys: 105 ms, total: 2min 1s
Wall time: 1min 48s
sage: len(Sols)
245
returns 245 solutions. However, many of them are duplicates, as can be shown by indexing them on the `groebner_bgroebner_basis() solved :
def bar():
Sols={}
for fff in Combinations(Lf, 3):
if len((B:=RR.ideal(fff).groebner_basis()))==3:
SSol=solve([SR(u)==0 for u in B],
SymUnk,
solution_dict=True)
Sol=[]
for S in SSol:
SRR={}
for u in S.keys():
try:
SRR|={RR(u):RR(S[u])}
except:
continue
Sol+=[SRR]
Sols|={B:Sol}
return Sols
sage: %time DSols=bar()
CPU times: user 2min 2s, sys: 84.4 ms, total: 2min 2s
Wall time: 1min 49s
sage: len(DSols)
156
These solutions to 156 distinct Groebner bases give 260 solutions :
sage: Set(flatten(list(DSols.values()))).cardinality()
260
In the present case, the laziness isn' too costly (2 minutes is way less than the time necessary tio rig up a general solution with polynomial rings tools...).
HTH
| 4 | No.4 Revision |
A lazy alternative to @Max Alekseyev's excellent answer is to use one of Sage's symbolic solvers, which already take care of non-zero-dimension solutions, and to filter out the undeterminates returned by these solvers.
After running :
SymUnk=list(map(SR, (x, y, z)))
def foo():
Sols=[]
for fff in Combinations(Lf, 3):
if len((B:=RR.ideal(fff).groebner_basis()))==3:
SSol=solve([SR(u)==0 for u in B],
SymUnk,
solution_dict=True)
Sol=[]
for S in SSol:
SRR={}
for u in S.keys():
try:
SRR|={RR(u):RR(S[u])}
except:
continue
Sol+=[SRR]
Sols+=[Sol]
return Sols
Running :
sage: %time Sols=foo()
CPU times: user 2min 1s, sys: 105 ms, total: 2min 1s
Wall time: 1min 48s
sage: len(Sols)
245
returns 245 solutions. However, many of them are duplicates, as can be shown by indexing them on the groebner_basis() solved :
def bar():
Sols={}
for fff in Combinations(Lf, 3):
if len((B:=RR.ideal(fff).groebner_basis()))==3:
SSol=solve([SR(u)==0 for u in B],
SymUnk,
solution_dict=True)
Sol=[]
for S in SSol:
SRR={}
for u in S.keys():
try:
SRR|={RR(u):RR(S[u])}
except:
continue
Sol+=[SRR]
Sols|={B:Sol}
return Sols
sage: %time DSols=bar()
CPU times: user 2min 2s, sys: 84.4 ms, total: 2min 2s
Wall time: 1min 49s
sage: len(DSols)
156
These solutions to 156 distinct Groebner bases give 260 solutions :
sage: Set(flatten(list(DSols.values()))).cardinality()
260
In the present case, the laziness isn' too isn't too costly (2 minutes is way less than the time necessary tio to rig up a general solution with polynomial rings tools...).
HTH
| 5 | No.5 Revision |
A lazy alternative to @Max Alekseyev's excellent answer is to use one of Sage's symbolic solvers, which already take care of non-zero-dimension solutions, and to filter out the undeterminates returned by these solvers.
After running :
SymUnk=list(map(SR, (x, y, z)))
def foo():
Sols=[]
for fff in Combinations(Lf, 3):
if len((B:=RR.ideal(fff).groebner_basis()))==3:
SSol=solve([SR(u)==0 for u in B],
SymUnk,
solution_dict=True)
Sol=[]
for S in SSol:
SRR={}
for u in S.keys():
try:
SRR|={RR(u):RR(S[u])}
except:
continue
Sol+=[SRR]
Sols+=[Sol]
return Sols
Running :
sage: %time Sols=foo()
CPU times: user 2min 1s, sys: 105 ms, total: 2min 1s
Wall time: 1min 48s
sage: len(Sols)
245
returns 245 solutions. However, many of them are duplicates, as can be shown by indexing them on the groebner_basis() solved :
def bar():
Sols={}
for fff in Combinations(Lf, 3):
if len((B:=RR.ideal(fff).groebner_basis()))==3:
SSol=solve([SR(u)==0 for u in B],
SymUnk,
solution_dict=True)
Sol=[]
for S in SSol:
SRR={}
for u in S.keys():
try:
SRR|={RR(u):RR(S[u])}
except:
continue
Sol+=[SRR]
Sols|={B:Sol}
return Sols
sage: %time DSols=bar()
CPU times: user 2min 2s, sys: 84.4 ms, total: 2min 2s
Wall time: 1min 49s
sage: len(DSols)
156
These solutions to 156 distinct Groebner bases give 260 solutions :
sage: Set(flatten(list(DSols.values()))).cardinality()
260
In the present case, the laziness isn't too costly (2 minutes is way less than the time necessary to rig up a general solution with polynomial rings tools...).
UPDATE :
It turns out that Sympy's solver does a better job than Sage's for dimension>0 ideals. An alternative way to write the solutions is :
# List of pairs (triplets, base) with Groebnar base of length 3
Triplets = [[u, b]
for u in Combinations(Lf, 3)
if len(b:=Rr.ideal(u).groebner_basis())==3]
# List of *distinct* bases
Bases = list(uniq([u[1] for u in Triplets]))
# Solve them *IN SR* using sympy :
# Precompute the unknowns
Unk = list(map(lambda u:SR(u), Rr.gens()))
# Solve
SSols = [solve([SR(u) for u in v], Unk, algorithm="sympy") for v in Bases]
FWIW :
sage: %time SSols = [solve([SR(u) for u in v], Unk, algorithm="sympy") for v in Bases]
CPU times: user 3.27 s, sys: 0 ns, total: 3.27 s
Wall time: 3.27 s
Sympy's solver seems also faster than Sage's...
Since neither the triplets nor the bases can be used as dictionary keys ("unhashable"), we need a bit of record-keeping :
# Record the base-solutions link
BS=list(map(list, zip(Bases, SSols)))
# Link triplets to their solutions
TBS=[[u[0]]+BS[Bases.index(u[1])] for u in Triplets]
Expressing the SR solutions in the original ring is lazily left to the reader...
HTH
Copyright Sage, 2010. Some rights reserved under creative commons license. Content on this site is licensed under a Creative Commons Attribution Share Alike 3.0 license.