forked from MCLF/henselization
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
378 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from .trac_25226 import * | ||
from .trac_22983 import * | ||
from .trac_24934 import * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
#***************************************************************************** | ||
# Copyright (C) 2018 Julian Rüth <julian.rueth@fsfe.org> | ||
# | ||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 2 of the License, or | ||
# (at your option) any later version. | ||
# http://www.gnu.org/licenses/ | ||
#***************************************************************************** | ||
|
||
from .util import AbstractMonkey | ||
|
||
class Monkey(AbstractMonkey): | ||
_trac = "https://trac.sagemath.org/ticket/22983" | ||
|
||
def _test(self): | ||
from sage.all import QQ, PolynomialRing | ||
R = PolynomialRing(QQ, 'x') | ||
x = R.gen() | ||
if R.quo(x) is not R.quo(x): | ||
raise Exception("#22983 has not been fixed") | ||
|
||
def _patch(self): | ||
import sage.rings.polynomial.polynomial_quotient_ring | ||
sage.rings.polynomial.polynomial_quotient_ring.PolynomialQuotientRingFactory = PolynomialQuotientRingFactory | ||
sage.rings.polynomial.polynomial_quotient_ring.PolynomialQuotientRing = PolynomialQuotientRingFactory("sage.rings.polynomial.polynomial_quotient_ring.PolynomialQuotientRing") | ||
del sage.rings.polynomial.polynomial_quotient_ring.PolynomialQuotientRing_generic.__reduce__ | ||
del sage.rings.polynomial.polynomial_quotient_ring.PolynomialQuotientRing_domain.__reduce__ | ||
del sage.rings.polynomial.polynomial_quotient_ring.PolynomialQuotientRing_field.__reduce__ | ||
|
||
from sage.structure.factory import UniqueFactory | ||
class PolynomialQuotientRingFactory(UniqueFactory): | ||
def create_key(self, ring, polynomial, names=None): | ||
from sage.rings.polynomial.polynomial_ring import PolynomialRing_commutative | ||
if not isinstance(ring, PolynomialRing_commutative): | ||
raise TypeError("ring must be a polynomial ring") | ||
from sage.rings.polynomial.polynomial_element import Polynomial | ||
if not isinstance(polynomial, Polynomial): | ||
raise TypeError("must be a polynomial") | ||
if not polynomial.parent() is ring: | ||
raise TypeError("polynomial must be in ring") | ||
|
||
c = polynomial.leading_coefficient() | ||
if not c.is_unit(): | ||
raise TypeError("polynomial must have unit leading coefficient") | ||
|
||
if names is None: | ||
names = tuple([x + 'bar' for x in ring.variable_names()]) | ||
else: | ||
from sage.rings.polynomial.polynomial_quotient_ring import normalize_names | ||
names = normalize_names(ring.ngens(), names) | ||
|
||
return ring, polynomial, names | ||
|
||
def create_object(self, version, key): | ||
ring, polynomial, names = key | ||
|
||
R = ring.base_ring() | ||
from sage.categories.all import IntegralDomains | ||
if R in IntegralDomains(): | ||
try: | ||
is_irreducible = polynomial.is_irreducible() | ||
except NotImplementedError: # is_irreducible sometimes not implemented | ||
pass | ||
else: | ||
if is_irreducible: | ||
from sage.categories.all import Fields | ||
if R in Fields(): | ||
from sage.rings.polynomial.polynomial_quotient_ring import PolynomialQuotientRing_field | ||
return PolynomialQuotientRing_field(ring, polynomial, names) | ||
else: | ||
from sage.rings.polynomial.polynomial_quotient_ring import PolynomialQuotientRing_domain | ||
return PolynomialQuotientRing_domain(ring, polynomial, names) | ||
from sage.rings.polynomial.polynomial_quotient_ring import PolynomialQuotientRing_generic | ||
return PolynomialQuotientRing_generic(ring, polynomial, names) | ||
|
||
Monkey().patch() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
#***************************************************************************** | ||
# Copyright (C) 2018 Julian Rüth <julian.rueth@fsfe.org> | ||
# | ||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 2 of the License, or | ||
# (at your option) any later version. | ||
# http://www.gnu.org/licenses/ | ||
#***************************************************************************** | ||
|
||
from .util import AbstractMonkey | ||
|
||
class Monkey(AbstractMonkey): | ||
_trac = "https://trac.sagemath.org/ticket/24934" | ||
|
||
def _test(self): | ||
from sage.all import QuadraticField, loads, dumps | ||
K = QuadraticField(-1, 'i') | ||
if loads(dumps(K.maximal_order())) is not K.maximal_order(): | ||
raise Exception("#24934 has not been fixed") | ||
|
||
def _patch(self): | ||
import sage.rings.number_field.order | ||
sage.rings.number_field.order.AbsoluteOrderFactory = AbsoluteOrderFactory | ||
sage.rings.number_field.order.absolute_order_from_module_generators = AbsoluteOrderFactory("sage.rings.number_field.order.absolute_order_from_module_generators") | ||
sage.rings.number_field.order.RelativeOrderFactory = RelativeOrderFactory | ||
sage.rings.number_field.order.relative_order_from_ring_generators = RelativeOrderFactory("sage.rings.number_field.order.relative_order_from_ring_generators") | ||
del sage.rings.number_field.order.AbsoluteOrder.__reduce__ | ||
del sage.rings.number_field.order.RelativeOrder.__reduce__ | ||
|
||
|
||
from sage.structure.factory import UniqueFactory | ||
class AbsoluteOrderFactory(UniqueFactory): | ||
def create_key_and_extra_args(self, gens, check_integral=True, check_rank=True, check_is_ring=True, is_maximal=None, allow_subfield=False): | ||
if allow_subfield: | ||
raise NotImplementedError("the allow_subfield parameter is not supported yet") | ||
if len(gens) == 0: | ||
raise ValueError("gens must span an order over ZZ") | ||
|
||
from sage.all import Sequence | ||
gens = Sequence(gens) | ||
|
||
K = gens.universe() | ||
from sage.rings.number_field.order import is_NumberFieldOrder | ||
if is_NumberFieldOrder(K): | ||
K = K.number_field() | ||
gens = frozenset([K(g) for g in gens]) | ||
return (K, gens), {"check_integral": check_integral, | ||
"check_rank": check_rank, | ||
"check_is_ring": check_is_ring, | ||
"is_maximal": is_maximal} | ||
|
||
def create_object(self, version, key, check_integral, check_rank, check_is_ring, is_maximal): | ||
K, gens = key | ||
|
||
from sage.rings.number_field.order import each_is_integral | ||
if check_integral and not each_is_integral(gens): | ||
raise ValueError("each generator must be integral") | ||
|
||
K = iter(gens).next().parent() | ||
V, from_V, to_V = K.vector_space() | ||
mod_gens = [to_V(x) for x in gens] | ||
|
||
from sage.all import ZZ | ||
ambient = ZZ**V.dimension() | ||
W = ambient.span(mod_gens) | ||
|
||
if check_rank: | ||
if W.rank() != K.degree(): | ||
raise ValueError("the rank of the span of gens is wrong") | ||
|
||
if check_is_ring: | ||
# Is there a faster way? | ||
from sage.rings.monomials import monomials | ||
alg = [to_V(x) for x in monomials(gens, [f.absolute_minpoly().degree() for f in gens])] | ||
if ambient.span(alg) != W: | ||
raise ValueError("the module span of the gens is not closed under multiplication.") | ||
|
||
from sage.rings.number_field.order import AbsoluteOrder | ||
return AbsoluteOrder(K, W, check=False, is_maximal=is_maximal) # we have already checked everything | ||
|
||
class RelativeOrderFactory(UniqueFactory): | ||
def create_key_and_extra_args(self, gens, check_is_integral=True, check_rank=True, is_maximal = None, allow_subfield=False): | ||
if allow_subfield: | ||
raise NotImplementedError("the allow_subfield parameter is not supported yet") | ||
|
||
from sage.all import Sequence | ||
gens = Sequence(gens) | ||
|
||
K = gens.universe() | ||
from sage.rings.number_field.order import is_NumberFieldOrder | ||
if is_NumberFieldOrder(K): | ||
K = K.number_field() | ||
gens = frozenset([K(g) for g in gens]) | ||
|
||
return (K, gens), {"check_is_integral": check_is_integral, | ||
"check_rank": check_rank, | ||
"is_maximal": is_maximal} | ||
|
||
def create_object(self, version, key, check_is_integral, check_rank, is_maximal): | ||
K, gens = key | ||
|
||
from sage.rings.number_field.order import each_is_integral | ||
if check_is_integral and not each_is_integral(gens): | ||
raise ValueError("each generator must be integral") | ||
|
||
# The top number field that contains the order. | ||
K = iter(gens).next().parent() | ||
|
||
# The absolute version of that field. | ||
Kabs = K.absolute_field('z') | ||
from_Kabs, to_Kabs = Kabs.structure() | ||
|
||
module_gens = [to_Kabs(a) for a in gens] | ||
n = [a.absolute_minpoly().degree() for a in gens] | ||
from sage.rings.monomials import monomials | ||
absolute_order_module_gens = monomials(module_gens, n) | ||
|
||
from sage.rings.number_field.order import absolute_order_from_module_generators | ||
abs_order = absolute_order_from_module_generators(absolute_order_module_gens, | ||
check_integral=False, check_is_ring=False, | ||
check_rank=check_rank) | ||
|
||
from sage.rings.number_field.order import RelativeOrder | ||
return RelativeOrder(K, abs_order, check=False, is_maximal=is_maximal) | ||
|
||
|
||
Monkey().patch() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
#***************************************************************************** | ||
# Copyright (C) 2018 Julian Rüth <julian.rueth@fsfe.org> | ||
# | ||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 2 of the License, or | ||
# (at your option) any later version. | ||
# http://www.gnu.org/licenses/ | ||
#***************************************************************************** | ||
|
||
from .util import AbstractMonkey | ||
|
||
class Monkey(AbstractMonkey): | ||
_trac = "https://trac.sagemath.org/ticket/25226" | ||
|
||
def _test(self): | ||
# not testable, see #25226 | ||
pass | ||
|
||
def _patch(self): | ||
import patchy | ||
import sage.rings.valuation.inductive_valuation | ||
patchy.patch(sage.rings.valuation.inductive_valuation.NonFinalInductiveValuation.equivalence_decomposition, r""" | ||
@@ -1209,7 +1209,7 @@ class NonFinalInductiveValuation(FiniteInductiveValuation, DiscreteValuation): | ||
v = self.extension(domain) | ||
ret = v.equivalence_decomposition(v.domain()(f)) | ||
return Factorization([(self._eliminate_denominators(g), e) | ||
- for (g,e) in ret], unit=self._eliminate_denominators(ret.unit())) | ||
+ for (g,e) in ret], unit=self._eliminate_denominators(ret.unit()), sort=False) | ||
""") | ||
|
||
|
||
Monkey().patch() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
# -*- coding: utf-8 -*- | ||
r""" | ||
Shared monkey patching utilities | ||
""" | ||
#***************************************************************************** | ||
# Copyright (C) 2018 Julian Rüth <julian.rueth@fsfe.org> | ||
# | ||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 2 of the License, or | ||
# (at your option) any later version. | ||
# http://www.gnu.org/licenses/ | ||
#***************************************************************************** | ||
|
||
class AbstractMonkey: | ||
r""" | ||
Derived monkeys must implement ``_test()`` and ``_patch()`` to test whether | ||
the feature to be patched has been fixed already and to perform the actual | ||
patching. | ||
EXAMPLES:: | ||
sage: from henselization.monkey.util import AbstractMonkey | ||
sage: class Monkey(AbstractMonkey): | ||
....: _trac = "https://trac.sagemath.org/..." | ||
....: def _test(self): | ||
....: pass # run tests here | ||
....: def _patch(self): | ||
....: pass # call patchy.patch() here | ||
sage: Monkey().patch() | ||
When patching fails, we run ``_test()`` to check whether the patch is | ||
necessary at all:: | ||
sage: class Monkey(AbstractMonkey): | ||
....: _trac = "https://trac.sagemath.org/..." | ||
....: def _test(self): | ||
....: pass # run tests here | ||
....: def _patch(self): | ||
....: raise NotImplementedError("call patchy.patch() here") | ||
sage: Monkey().patch() | ||
sage: class Monkey(AbstractMonkey): | ||
....: _trac = "https://trac.sagemath.org/..." | ||
....: def _test(self): | ||
....: raise Exception("test failed") | ||
....: def _patch(self): | ||
....: raise NotImplementedError("call patchy.patch() here") | ||
sage: Monkey().patch() | ||
Your installation of Sage has a known issue: https://trac.sagemath.org/.... We tried to install a workaround for this problem but failed to do so. Please make sure that you are using the latest stable version of Sage. If you are using the latest stable version of Sage already, please report this issue at https://github.com/MCLF/henselization/issues including the traceback below. | ||
Traceback (most recent call last): | ||
... | ||
NotImplementedError: call patchy.patch() here | ||
We do not trust our patches. Tests are always run to check that | ||
``_patch()`` did the right thing:: | ||
sage: from henselization.monkey.util import AbstractMonkey | ||
sage: class Monkey(AbstractMonkey): | ||
....: _trac = "https://trac.sagemath.org/..." | ||
....: def _test(self): | ||
....: raise Exception("test failed") | ||
....: def _patch(self): | ||
....: pass # call patchy.patch() here | ||
sage: Monkey().patch() | ||
Your installation of Sage has a known issue: https://trac.sagemath.org/.... We thought that we had installed a workaround but apparently failed to do so. Please report this issue at https://github.com/MCLF/henselization/issues including the traceback below. | ||
Traceback (most recent call last): | ||
... | ||
Exception: test failed | ||
""" | ||
def patch(self): | ||
r""" | ||
Run ``_patch()`` with a more pretty error handling. | ||
""" | ||
try: | ||
import patchy | ||
patchy; # silence pyflakes "imported but not used" | ||
except Exception: | ||
if not self.is_fixed(): | ||
import warnings | ||
warnings.warn("Your installation of Sage has a known issue: %s. Please install patchy with `sage -pip install patchy` to fix this problem."%(self._trac,)) | ||
return | ||
|
||
try: | ||
self._patch() | ||
except Exception: | ||
if not self.is_fixed(): | ||
print("Your installation of Sage has a known issue: %s. We tried to install a workaround for this problem but failed to do so. Please make sure that you are using the latest stable version of Sage. If you are using the latest stable version of Sage already, please report this issue at https://github.com/MCLF/henselization/issues including the traceback below."%(self._trac,)) | ||
import traceback | ||
traceback.print_exc() | ||
else: | ||
try: | ||
self._test() | ||
except: | ||
print("Your installation of Sage has a known issue: %s. We thought that we had installed a workaround but apparently failed to do so. Please report this issue at https://github.com/MCLF/henselization/issues including the traceback below."%(self._trac,)) | ||
import traceback | ||
traceback.print_exc() | ||
|
||
def is_fixed(self): | ||
r""" | ||
Return whether ``_test()`` did not throw an exception. | ||
""" | ||
try: | ||
self._test() | ||
except Exception: | ||
return False | ||
else: | ||
return True |
Oops, something went wrong.