sagemath / sage

Main repository of SageMath
https://www.sagemath.org
Other
1.46k stars 485 forks source link

Interval sets cannot be constructed from embedded number field elements #34438

Open saraedum opened 2 years ago

saraedum commented 2 years ago

Currently, the following fails:

sage: K.<a> = NumberField(x^2 - 2, embedding=1)
sage: RealSet.unbounded_below_closed(a)
AttributeError: 'sage.rings.real_lazy.LazyBinop' object has no attribute '_value'

However, this works:

sage: RealSet.unbounded_below_closed(AA(a))
(-oo, 1.414213562373095?]

CC: @videlec @slel @yuan-zhou

Component: number fields

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

saraedum commented 2 years ago
comment:1

This affects the hyperbolic code at https://github.com/flatsurf/sage-flatsurf/pull/158.

videlec commented 2 years ago
comment:2

There are two problems.

First of all, the difference of treatment between number fields and AA is not desirable

sage: type(RealLazyField()(a))
<class 'sage.rings.real_lazy.LazyBinop'>
sage: type(RealLazyField()(AA(a)))
<class 'sage.rings.real_lazy.LazyWrapper'>

Furthermore, the conversion from number field is extremly weird

sage: RLF = RealLazyField()
sage: x = RLF(a) # this is ((1 * a) + 0)
sage: x._op
<built-in function add>
sage: (x._left, type(x._left))
(1.414213562373095?, <class 'sage.rings.real_lazy.LazyBinop'>)
sage: (x._right, type(x._right))
(0, <class 'sage.rings.real_lazy.LazyWrapper'>)
sage: (x._left._left, type(x._left._left))
(1, <class 'sage.rings.real_lazy.LazyWrapper'>)
sage: (x._left._right, type(x._left._right))
(1.414213562373095?, <class 'sage.rings.real_lazy.LazyAlgebraic'>)

The conversions indeed differ

sage: type(RLF.convert_map_from(AA))
<class 'sage.rings.real_lazy.LazyWrapperMorphism'>
sage: type(RLF.convert_map_from(K))
<class 'sage.rings.number_field.number_field_morphisms.NumberFieldEmbedding'>

And the conversion from the number field works as a.polynomial()(K_gen_image) which is less efficient than the AA version which directly wraps the element.

Secondly, the one can not assume that the RealLazyField element at hand is a LazyWrapper with an underlying _value.

videlec commented 2 years ago
comment:4

The underlying problem for the conversion is that the conversion to RR goes via RLF.

sage: RR.coerce_map_from(K)
Composite map:
  From: Number Field in a with defining polynomial x^2 - 2 with a = 1.414213562373095?
  To:   Real Field with 53 bits of precision
  Defn:   Generic morphism:
          From: Number Field in a with defining polynomial x^2 - 2 with a = 1.414213562373095?
          To:   Real Lazy Field
          Defn: a -> 1.414213562373095?
        then
          Conversion via _mpfr_ method map:
          From: Real Lazy Field
          To:   Real Field with 53 bits of precision

The code path in LazyField._coerce_map_from_ (sage/rings/real_lazy.pyx lines 128-183) refuses to use wrapper in this situation.

saraedum commented 2 years ago
comment:5

The trick is probably to implement the coercion from number fields to the real field. I'll give it a try.

videlec commented 2 years ago
comment:6

Replying to @saraedum:

The trick is probably to implement the coercion from number fields to the real field. I'll give it a try.

Ideally this should go via the NumberFieldElement._mpfr_ method (as the _arb_ coercion does). Though