From 8a24cefe843b7ff22f2455ac6e6d66434039cd82 Mon Sep 17 00:00:00 2001 From: Ben Mares Date: Thu, 30 Jul 2026 02:38:10 +0200 Subject: [PATCH] Guard Giac's RUR variable limit --- dev/extended_ptolemy/complexVolumesClosed.py | 13 +++++++- dev/extended_ptolemy/giac_rur.py | 35 ++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/dev/extended_ptolemy/complexVolumesClosed.py b/dev/extended_ptolemy/complexVolumesClosed.py index 20f7b6139..8fa623319 100644 --- a/dev/extended_ptolemy/complexVolumesClosed.py +++ b/dev/extended_ptolemy/complexVolumesClosed.py @@ -43,7 +43,18 @@ def compute_representative_ptolemys_and_full_var_dict(M, precision = 53): I, full_var_dict = extended.ptolemy_ideal_for_filled( M, return_full_var_dict = 'data', notation = 'full') - rur = giac_rur.rational_univariate_representation(I) + try: + rur = giac_rur.rational_univariate_representation(I) + except giac_rur.GiacRURTooManyVariablesError as error: + raise ValueError( + "The extended Ptolemy ideal for this %d-tetrahedron " + "triangulation has %d variables. Giac %s's RUR " + "implementation crashes for more than %d variables, so this " + "Giac version limits this computation to triangulations with at " + "most 5 tetrahedra." + % (M.num_tetrahedra(), error.number_of_variables, + error.version_string, + giac_rur.GIAC_PRE_2_RUR_MAX_VARIABLES)) from None return [ evaluate_at_roots(numberField, exact_values, precision) diff --git a/dev/extended_ptolemy/giac_rur.py b/dev/extended_ptolemy/giac_rur.py index 6f9299b0b..71fcbcd04 100644 --- a/dev/extended_ptolemy/giac_rur.py +++ b/dev/extended_ptolemy/giac_rur.py @@ -3,9 +3,37 @@ functionality. """ +import re + from sage.all import QQ, PolynomialRing, NumberField from .giac_helper import giac +# Giac before 2.0 corrupts memory in its RUR code above this variable count. +GIAC_PRE_2_RUR_MAX_VARIABLES = 15 + + +class GiacRURTooManyVariablesError(ValueError): + def __init__(self, number_of_variables, version): + self.number_of_variables = number_of_variables + self.version = version + self.version_string = '.'.join(str(part) for part in version) + super().__init__( + "Giac %s's RUR implementation crashes for more than %d " + "variables, and this ideal has %d variables." + % (self.version_string, GIAC_PRE_2_RUR_MAX_VARIABLES, + number_of_variables)) + + +def _giac_version(): + description = repr(giac('version()')) + match = re.search( + r'\bgiac\s+(\d+(?:\.\d+)+)', description, re.IGNORECASE) + if match is None: + raise RuntimeError('Could not determine Giac version from %s.' + % description) + return tuple(int(part) for part in match.group(1).split('.')) + + # The main function of this file is: def rational_univariate_representation(ideal): @@ -61,6 +89,13 @@ def rational_univariate_representation(ideal): """ R = ideal.ring() + number_of_variables = len(R.gens()) + if number_of_variables > GIAC_PRE_2_RUR_MAX_VARIABLES: + version = _giac_version() + if version < (2, 0): + raise GiacRURTooManyVariablesError( + number_of_variables, version) + # A "feature" introduced in Sage-9.4 is that # ideal.gens() vs R.gens() # returns