Ticket #7643: trac_7643.patch
File trac_7643.patch, 23.4 KB (added by , 13 years ago) |
---|
-
sage/rings/number_field/number_field.py
# HG changeset patch # User Francis Clarke <F.Clarke@Swansea.ac.uk> # Date 1260823202 0 # Node ID e839322b0afc60fb94d29d3e617f9ee50ee07c2c # Parent 964c2f4ce74db0417a771de0b0cfc951b1fab73c Improved composita diff -r 964c2f4ce74d -r e839322b0afc sage/rings/number_field/number_field.py
a b 166 166 from sage.categories.fields import Fields 167 167 return codomain in Fields() 168 168 169 from sage.rings.number_field.morphism import RelativeNumberFieldHomomorphism_from_abs 170 169 171 def proof_flag(t): 170 172 """ 171 173 Used for easily determining the correct proof flag to use. … … 2548 2550 def composite_fields(self, other, names=None, both_maps=False, preserve_embedding=True): 2549 2551 """ 2550 2552 List of all possible composite number fields formed from self and 2551 other, as well as possibly embeddings into the compositum. See the2552 documentation for both_maps below.2553 2554 If preserve_embedding is ``True`` and if self and other *both*have2555 embeddings into the same ambient field, o nly compositums respecting2556 both embeddings are returned. If one (or both) of self or other does2557 not have an embedding, or they do not have embeddings into the same2558 ambient field, or preserve_embedding is not ``True`` all possible2559 composite number fields are returned.2553 other, together with (optionally) embeddings into the compositum; 2554 see the documentation for both_maps below. 2555 2556 If preserve_embedding is True and if self and other both have 2557 embeddings into the same ambient field, or into fields which are 2558 contained in a common field, only the compositum respecting 2559 both embeddings is returned. If one (or both) of self or other 2560 does not have an embedding or preserve_embedding is False, 2561 all possible composite number fields are returned. 2560 2562 2561 2563 INPUT: 2562 2564 … … 2564 2566 2565 2567 - ``names`` - generator name for composite fields 2566 2568 2567 - ``both_maps`` - (default: False) if True, return quadruples (F, 2568 self_into_F, other_into_F, k) such that self_into_F maps self into 2569 F, other_into_F maps other into F, and k is an integer such that 2570 other_into_F(other.gen()) + k*self_into_F(self.gen()) == F.gen() 2571 2572 - ``preserve_embedding`` - (default: True) return only compositums with 2573 compatible ambient embeddings. 2569 - ``both_maps`` - (default: False) if True, return quadruples 2570 (F, self_into_F, other_into_F, k) such that self_into_F is an 2571 embedding of self in F, other_into_F is an embedding of in F, 2572 and k is an integer such that F.gen() equals 2573 other_into_F(other.gen()) + k*self_into_F(self.gen()) 2574 If both self and other have embeddings into an ambient field, then 2575 F will have an embedding with respect to which both self_into_F 2576 and other_into_F will be compatible with the ambient embeddings. 2577 2578 - ``preserve_embedding`` - (default: True) if self and other have 2579 ambient embeddings, then return only the compatible compositum. 2574 2580 2575 2581 OUTPUT: 2576 2582 2577 2578 2583 - ``list`` - list of the composite fields, possibly with maps. 2579 2584 2580 2585 … … 2582 2587 2583 2588 sage: K.<a> = NumberField(x^4 - 2) 2584 2589 sage: K.composite_fields(K) 2590 [Number Field in a0 with defining polynomial x^4 - 162, 2591 Number Field in a1 with defining polynomial x^8 + 28*x^4 + 2500] 2592 2593 A particular compositum is selected, together with compatible maps 2594 into the compositum, if the fields are endowed with a real or 2595 complex embedding:: 2596 2597 sage: K1 = NumberField(x^4 - 2, 'a', embedding=RR(2^(1/4))) 2598 sage: K2 = NumberField(x^4 - 2, 'a', embedding=RR(-2^(1/4))) 2599 sage: K1.composite_fields(K2) 2600 [Number Field in a0 with defining polynomial x^4 - 162] 2601 sage: [F, f, g, k], = K1.composite_fields(K2, both_maps=True); F 2602 Number Field in a0 with defining polynomial x^4 - 162 2603 sage: f(K1.0), g(K2.0) 2604 (-1/3*a0, 1/3*a0) 2605 2606 With preserve_embedding set to False, the embeddings are ignored:: 2607 2608 sage: K1.composite_fields(K2, preserve_embedding=False) 2585 2609 [Number Field in a0 with defining polynomial x^4 - 162, 2586 Number Field in a1 with defining polynomial x^4 - 2, 2587 Number Field in a2 with defining polynomial x^8 + 28*x^4 + 2500] 2588 sage: k.<a> = NumberField(x^3 + 2) 2589 sage: m.<b> = NumberField(x^3 + 2) 2590 sage: k.composite_fields(m, 'c') 2591 [Number Field in c0 with defining polynomial x^3 - 2, 2592 Number Field in c1 with defining polynomial x^6 - 40*x^3 + 1372] 2593 2594 Let's get the maps as well:: 2595 2596 sage: Q1.<a> = NumberField(x^2 + 2, 'b').extension(x^2 + 3, 'c').absolute_field() 2597 sage: Q2.<b> = NumberField(x^2 + 3, 'a').extension(x^2 + 5, 'c').absolute_field() 2598 sage: Q1.composite_fields(Q2) 2599 [Number Field in ab0 with defining polynomial x^8 + 64*x^6 + 904*x^4 + 3840*x^2 + 3600, 2600 Number Field in ab1 with defining polynomial x^8 + 160*x^6 + 6472*x^4 + 74880*x^2 + 1296] 2601 2602 sage: F, Q1_into_F, Q2_into_F, k = Q1.composite_fields(Q2, both_maps=True)[0] 2603 sage: F 2604 Number Field in ab0 with defining polynomial x^8 + 64*x^6 + 904*x^4 + 3840*x^2 + 3600 2610 Number Field in a1 with defining polynomial x^8 + 28*x^4 + 2500] 2611 2612 Changing the embedding selects a different compositum:: 2613 2614 sage: K3 = NumberField(x^4 - 2, 'a', embedding=CC(2^(1/4)*I)) 2615 sage: [F, f, g, k], = K1.composite_fields(K3, both_maps=True); F 2616 Number Field in a0 with defining polynomial x^8 + 28*x^4 + 2500 2617 sage: f(K1.0), g(K3.0) 2618 (1/240*a0^5 - 41/120*a0, 1/120*a0^5 + 19/60*a0) 2619 2620 If no embeddings are specified, the maps into the composite are chosen arbitrarily:: 2621 2622 sage: Q1.<a> = NumberField(x^4 + 10*x^2 + 1) 2623 sage: Q2.<b> = NumberField(x^4 + 16*x^2 + 4) 2624 sage: Q1.composite_fields(Q2, 'c') 2625 [Number Field in c with defining polynomial x^8 + 64*x^6 + 904*x^4 + 3840*x^2 + 3600] 2626 sage: F, Q1_into_F, Q2_into_F, k = Q1.composite_fields(Q2, 'c', both_maps=True)[0] 2605 2627 sage: Q1_into_F 2606 2628 Ring morphism: 2607 2629 From: Number Field in a with defining polynomial x^4 + 10*x^2 + 1 2608 To: Number Field in ab0 with defining polynomial x^8 + 64*x^6 + 904*x^4 + 3840*x^2 + 3600 2609 Defn: a |--> 19/14400*ab0^7 + 137/1800*ab0^5 + 2599/3600*ab0^3 + 8/15*ab0 2610 sage: Q2_into_F 2611 Ring morphism: 2612 From: Number Field in b with defining polynomial x^4 + 16*x^2 + 4 2613 To: Number Field in ab0 with defining polynomial x^8 + 64*x^6 + 904*x^4 + 3840*x^2 + 3600 2614 Defn: b |--> 19/7200*ab0^7 + 137/900*ab0^5 + 2599/1800*ab0^3 + 31/15*ab0 2615 2616 sage: Q1_into_F.domain() is Q1 2617 True 2618 sage: Q2_into_F(b) + k*Q1_into_F(a) == F.gen() 2619 True 2620 2621 Let's check something about the "other" composite field:: 2622 2623 sage: F, Q1_into_F, Q2_into_F, k = Q1.composite_fields(Q2, both_maps=True)[1] 2624 sage: Q1_into_F.domain() is Q1 2625 True 2626 sage: Q2_into_F(b) + k*Q1_into_F(a) == F.gen() 2627 True 2630 To: Number Field in c with defining polynomial x^8 + 64*x^6 + 904*x^4 + 3840*x^2 + 3600 2631 Defn: a |--> 19/14400*c^7 + 137/1800*c^5 + 2599/3600*c^3 + 8/15*c 2632 2633 This is just one of four embeddings of Q1 into F:: 2634 sage: Hom(Q1, F).order() 2635 4 2628 2636 2629 2637 TESTS: 2630 2638 … … 2634 2642 sage: K0.<b> = CyclotomicField(7, 'a').subfields(3)[0][0].change_names() 2635 2643 sage: K1.<a1> = K0.extension(x^2 - 2*b^2, 'a1').absolute_field() 2636 2644 sage: K2.<a2> = K0.extension(x^2 - 3*b^2, 'a2').absolute_field() 2637 sage: K12638 Number Field in a1 with defining polynomial x^6 - 10*x^4 + 24*x^2 - 82639 sage: K22640 Number Field in a2 with defining polynomial x^6 - 15*x^4 + 54*x^2 - 272641 sage: K1.is_isomorphic(K2)2642 False2643 2645 2644 2646 We need embeddings, so we redefine:: 2645 2647 2646 2648 sage: L1.<a1> = NumberField(K1.polynomial(), 'a1', embedding=CC.0) 2647 sage: CDF(a1)2648 -0.6293842454262649 2649 sage: L2.<a2> = NumberField(K2.polynomial(), 'a2', embedding=CC.0) 2650 sage: CDF(a2) 2651 -0.77083512672 2650 sage: [CDF(a1), CDF(a2)] 2651 [-0.629384245426, -0.77083512672] 2652 2653 and we get the same embeddings via the compositum:: 2652 2654 2653 2655 sage: F, L1_into_F, L2_into_F, k = L1.composite_fields(L2, both_maps=True)[0] 2654 sage: CDF(F.gen()) 2655 -0.141450881294 2656 2657 Both subfield generators have correct embeddings:: 2658 2659 sage: CDF(L1_into_F(L1.gen())), CDF(L1.gen()) 2660 (-0.629384245426, -0.629384245426) 2661 sage: CDF(L2_into_F(L2.gen())), CDF(L2.gen()) 2662 (-0.77083512672, -0.77083512672) 2663 2664 On the other hand, without embeddings, there are more composite fields:: 2665 2666 sage: M1.<a1> = NumberField(L1.polynomial(), 'a1') 2667 sage: M2.<a2> = NumberField(L2.polynomial(), 'a2') 2668 sage: M1.composite_fields(M2) 2669 [Number Field in a1a20 with defining polynomial x^12 - 50*x^10 + 613*x^8 - 1270*x^6 + 526*x^4 - 60*x^2 + 1, 2670 Number Field in a1a21 with defining polynomial x^12 - 50*x^10 + 865*x^8 - 6730*x^6 + 24970*x^4 - 43152*x^2 + 27889, 2671 Number Field in a1a22 with defining polynomial x^12 - 50*x^10 + 865*x^8 - 6310*x^6 + 18670*x^4 - 14928*x^2 + 1849] 2672 2673 Here's another example:: 2674 2675 sage: Q1.<a> = NumberField(x^4 + 10*x^2 + 1, embedding=CC.0); Q1, CDF(a) 2676 (Number Field in a with defining polynomial x^4 + 10*x^2 + 1, 0.317837245196*I) 2677 sage: Q2.<b> = NumberField(x^4 + 16*x^2 + 4, embedding=CC.0); Q2, CDF(b) 2678 (Number Field in b with defining polynomial x^4 + 16*x^2 + 4, 0.504017169931*I) 2679 2680 sage: len(Q1.composite_fields(Q2)) 2681 1 2682 sage: F, Q1_into_F, Q2_into_F, k2 = Q1.composite_fields(Q2, both_maps=True)[0] 2683 sage: F, CDF(F.gen()) 2684 (Number Field in ab1 with defining polynomial x^8 + 160*x^6 + 6472*x^4 + 74880*x^2 + 1296, 2685 -0.131657320461*I) 2686 2687 sage: t = Q2_into_F(Q2.gen()) + k2*Q1_into_F(Q1.gen()); t, CDF(t) 2688 (ab1, -0.131657320461*I) 2689 sage: abs(t.minpoly()(CDF(t))) < 1e-8 2690 True 2691 2692 Let's check that the preserve_embedding flag is respected:: 2693 2694 sage: len(Q1.composite_fields(Q2)) 2695 1 2696 sage: len(Q1.composite_fields(Q2, preserve_embedding=False)) 2697 2 2656 sage: [CDF(L1_into_F(L1.gen())), CDF(L2_into_F(L2.gen()))] 2657 [-0.629384245426, -0.77083512672] 2698 2658 2699 2659 Let's check that if only one field has an embedding, the resulting 2700 fields do not have an embedding:: 2701 2702 sage: Q2.<b> = NumberField(x^4 + 16*x^2 + 4) 2703 sage: Q2.coerce_embedding() is None 2704 True 2705 2706 sage: Q1.composite_fields(Q2) 2707 [Number Field in ab0 with defining polynomial x^8 + 64*x^6 + 904*x^4 + 3840*x^2 + 3600, 2708 Number Field in ab1 with defining polynomial x^8 + 160*x^6 + 6472*x^4 + 74880*x^2 + 1296] 2709 sage: Q1.composite_fields(Q2)[0].coerce_embedding() is None 2710 True 2711 """ 2712 if names is None: 2713 sv = self.variable_name(); ov = other.variable_name() 2714 names = sv + (ov if ov != sv else "") 2660 fields do not have embeddings:: 2661 2662 sage: L1.composite_fields(K2)[0].coerce_embedding() is None 2663 True 2664 sage: L2.composite_fields(K1)[0].coerce_embedding() is None 2665 True 2666 2667 We check that other can be a relative number field:: 2668 2669 sage: L.<a, b> = NumberField([x^3 - 5, x^2 + 3]) 2670 sage: CyclotomicField(3, 'w').composite_fields(L, both_maps=True) 2671 [(Number Field in wa with defining polynomial x^6 - 3*x^5 + 6*x^4 - 17*x^3 + 21*x^2 + 12*x + 16, Ring morphism: 2672 From: Cyclotomic Field of order 3 and degree 2 2673 To: Number Field in wa with defining polynomial x^6 - 3*x^5 + 6*x^4 - 17*x^3 + 21*x^2 + 12*x + 16 2674 Defn: w |--> -1/36*wa^5 + 5/36*wa^4 - 5/18*wa^3 + 25/36*wa^2 - 35/36*wa - 5/9, Relative number field morphism: 2675 From: Number Field in a with defining polynomial x^3 - 5 over its base field 2676 To: Number Field in wa with defining polynomial x^6 - 3*x^5 + 6*x^4 - 17*x^3 + 21*x^2 + 12*x + 16 2677 Defn: a |--> 1/36*wa^5 - 5/36*wa^4 + 5/18*wa^3 - 25/36*wa^2 + 71/36*wa - 4/9 2678 b |--> 1/18*wa^5 - 5/18*wa^4 + 5/9*wa^3 - 25/18*wa^2 + 35/18*wa + 1/9, -1)] 2679 """ 2715 2680 if not isinstance(other, NumberField_generic): 2716 2681 raise TypeError, "other must be a number field." 2717 f = self.pari_polynomial() 2718 g = other.pari_polynomial()2719 2720 R = self.absolute_polynomial().parent()2682 2683 sv = self.variable_name(); ov = other.variable_name() 2684 if names is None: 2685 names = sv + (ov if ov != sv else "") 2721 2686 name = sage.structure.parent_gens.normalize_names(1, names)[0] 2722 2687 2723 2688 # should we try to preserve embeddings? … … 2727 2692 if other.coerce_embedding() is None: 2728 2693 subfields_have_embeddings = False 2729 2694 if subfields_have_embeddings: 2730 if self.coerce_embedding().codomain() is not other.coerce_embedding().codomain(): 2695 try: 2696 from sage.categories.pushout import pushout 2697 ambient_field = pushout(self.coerce_embedding().codomain(), other.coerce_embedding().codomain()) 2698 except CoercionException: 2699 ambient_field = None 2700 if ambient_field is None: 2731 2701 subfields_have_embeddings = False 2732 2702 2703 f = self.pari_polynomial() 2704 g = other.pari_polynomial() 2705 R = self.absolute_polynomial().parent() 2706 2733 2707 if not both_maps and not subfields_have_embeddings: 2734 2708 # short cut! 2735 C = map(R, f.polcompositum(g)) 2736 return [ NumberField(C[i], name + str(i)) for i in range(len(C)) ] 2737 2738 # If flag = 1, outputs a vector of 4-component vectors [R, a, b, 2739 # k], where R ranges through the list of all possible compositums 2709 # eliminate duplicates from the fields given by polcompositum 2710 # and return the resulting number fields. There is no need to 2711 # check that the polynomials are irreducible. 2712 C = [] 2713 for r in f.polcompositum(g): 2714 if not any(r.nfisisom(s) for s in C): 2715 C.append(r) 2716 C = map(R, C) 2717 2718 if len(C) == 1 and name != sv and name != ov: 2719 names =[name] 2720 else: 2721 names = [name + str(i) for i in range(len(C))] 2722 2723 return [ NumberField(r, names[i], check=False) for i, r in enumerate(C) ] 2724 2725 # If flag = 1, polcompositum outputs a vector of 4-component vectors 2726 # [R, a, b, k], where R ranges through the list of all possible compositums 2740 2727 # as above, and a (resp. b) expresses the root of P (resp. Q) as 2741 2728 # an element of Q(X )/(R). Finally, k is a small integer such that 2742 # b + ka = X modulo R. 2743 C = f.polcompositum(g, 1) 2744 rets = [] 2745 2746 embedding = None 2729 # b + ka = X modulo R. 2730 # In this case duplicates must only be eliminated if embeddings are going 2731 # to be preserved. 2732 C = [] 2733 for v in f.polcompositum(g, 1): 2734 if subfields_have_embeddings or not any(v[0].nfisisom(u[0]) for u in C): 2735 C.append(v) 2736 2747 2737 a = self.gen() 2748 2738 b = other.gen() 2749 for i in range(len(C)): 2750 r, a_in_F, b_in_F, k = C[i] 2739 2740 # If both subfields are provided with embeddings, then we must select 2741 # the compositum which corresponds to these embeddings. We do this by 2742 # evaluating the given polynomials at the corresponding embedded values. 2743 # For the case we want the result will be zero, but rounding errors are 2744 # difficult to predict, so we just take the field which yields the 2745 # mimumum value. 2746 if subfields_have_embeddings: 2747 poly_vals = [] 2748 for r, _, _, k in C: 2749 r = R(r) 2750 k = ZZ(k) # essential 2751 embedding = other.coerce_embedding()(b) + k*self.coerce_embedding()(a) 2752 poly_vals.append(sage.rings.complex_double.CDF(r(embedding)).abs()) 2753 i = poly_vals.index(min(poly_vals)) 2754 C = [C[i]] 2755 2756 if len(C) == 1 and name != sv and name != ov: 2757 names =[name] 2758 else: 2759 names = [name + str(i) for i in range(len(C))] 2760 2761 if both_maps and not other.is_absolute(): 2762 other_abs = other.absolute_field('z') 2763 _, to_other_abs = other_abs.structure() 2764 2765 embedding = None 2766 rets = [] 2767 for i, [r, a_in_F, b_in_F, k] in enumerate(C): 2751 2768 r = R(r) 2752 k = ZZ(k) 2753 2769 k = ZZ(k) # essential 2754 2770 if subfields_have_embeddings: 2755 2771 embedding = other.coerce_embedding()(b) + k*self.coerce_embedding()(a) 2756 if r(embedding) > 1e-30: # XXX how to do this more generally? 2757 continue 2758 2759 F = NumberField(r, name + str(i), embedding=embedding) 2760 a_in_F = F(a_in_F) 2761 b_in_F = F(b_in_F) 2762 into_F1 = self.hom ([a_in_F], check=True) 2763 into_F2 = other.hom([b_in_F], check=True) 2764 assert into_F2(b) + k*into_F1(a) == F.gen() 2765 rets.append( (F, into_F1, into_F2, k) ) 2766 2767 if not both_maps: 2768 return [ F for F, _, _, _ in rets ] 2769 else: 2770 return rets 2772 F = NumberField(r, names[i], check=False, embedding=embedding) 2773 if both_maps: 2774 self_to_F = self.hom ([F(a_in_F)]) 2775 if other.is_absolute(): 2776 other_to_F = other.hom([F(b_in_F)]) 2777 else: 2778 other_abs_to_F = other_abs.hom([F(b_in_F)]) 2779 other_to_F = RelativeNumberFieldHomomorphism_from_abs(other.Hom(F), other_abs_to_F*to_other_abs) 2780 rets.append( (F, self_to_F, other_to_F, k) ) 2781 else: 2782 rets.append(F) 2783 return rets 2771 2784 2772 2785 def absolute_degree(self): 2773 2786 """ -
sage/rings/number_field/number_field_rel.py
diff -r 964c2f4ce74d -r e839322b0afc sage/rings/number_field/number_field_rel.py
a b 511 511 sage: K.<a,b> = NumberField([x^4 + 3, x^2 + 2]); K 512 512 Number Field in a with defining polynomial x^4 + 3 over its base field 513 513 sage: K.galois_closure('c') 514 Number Field in c with defining polynomial x^16 + 1 44*x^14 + 8988*x^12 + 329616*x^10 + 7824006*x^8 + 113989680*x^6 + 1360354716*x^4 + 3470308272*x^2 + 9407642049514 Number Field in c with defining polynomial x^16 + 16*x^14 + 28*x^12 + 784*x^10 + 19846*x^8 - 595280*x^6 + 2744476*x^4 + 3212848*x^2 + 29953729 515 515 """ 516 516 return self.absolute_field('a').galois_closure(names=names) 517 517 518 def composite_fields(self, other, names=None, both_maps=False, preserve_embedding=True): 519 """ 520 List of all possible composite number fields formed from self and 521 other, together with (optionally) embeddings into the compositum; 522 see the documentation for both_maps below. 523 524 Since relative fields do not have ambient embeddings, 525 preserve_embedding has no effect. In every case all possible 526 composite number fields are returned. 527 528 INPUT: 529 530 - ``other`` - a number field 531 532 - ``names`` - generator name for composite fields 533 534 - ``both_maps`` - (default: False) if True, return quadruples 535 (F, self_into_F, other_into_F, k) such that self_into_F maps self into 536 F, other_into_F maps other into F, and k is an integer such that 537 other_into_F(other.gen()) + k*self_into_F(self.gen()) == F.gen() 538 If both self and other have embeddings into an ambient field, then 539 F will have an embedding with respect to which both self_into_F 540 and other_into_F will be compatible with the ambient embeddings. 541 542 - ``preserve_embedding`` - (default: True) has no effect, but is kept 543 for compatibility with the absolute version of this function. In every 544 case the list of all possible compositums is returned. 545 546 OUTPUT: 547 548 - ``list`` - list of the composite fields, possibly with maps. 549 550 551 EXAMPLES:: 552 553 sage: K.<a, b> = NumberField([x^2 + 5, x^2 - 2]) 554 sage: L.<c, d> = NumberField([x^2 + 5, x^2 - 3]) 555 sage: K.composite_fields(L) 556 [Number Field in ac with defining polynomial x^8 - 24*x^6 + 464*x^4 + 3840*x^2 + 25600] 557 sage: K.composite_fields(L, both_maps=True) 558 [[Number Field in ac with defining polynomial x^8 - 24*x^6 + 464*x^4 + 3840*x^2 + 25600, 559 Relative number field morphism: 560 From: Number Field in a with defining polynomial x^2 + 5 over its base field 561 To: Number Field in ac with defining polynomial x^8 - 24*x^6 + 464*x^4 + 3840*x^2 + 25600 562 Defn: a |--> -9/66560*ac^7 + 11/4160*ac^5 - 241/4160*ac^3 - 101/104*ac 563 b |--> -21/166400*ac^7 + 73/20800*ac^5 - 779/10400*ac^3 + 7/260*ac, 564 Relative number field morphism: 565 From: Number Field in c with defining polynomial x^2 + 5 over its base field 566 To: Number Field in ac with defining polynomial x^8 - 24*x^6 + 464*x^4 + 3840*x^2 + 25600 567 Defn: c |--> -9/66560*ac^7 + 11/4160*ac^5 - 241/4160*ac^3 - 101/104*ac 568 d |--> -3/25600*ac^7 + 7/1600*ac^5 - 147/1600*ac^3 + 1/40*ac, 569 -2]] 570 """ 571 if not isinstance(other, NumberField_generic): 572 raise TypeError, "other must be a number field." 573 if names is None: 574 sv = self.variable_name(); ov = other.variable_name() 575 names = sv + (ov if ov != sv else "") 576 577 self_abs = self.absolute_field('w') 578 abs_composites = self_abs.composite_fields(other, names=names, both_maps=both_maps) 579 580 if not both_maps: 581 return abs_composites 582 583 _, to_self_abs = self_abs.structure() 584 585 rets = [] 586 for F, self_abs_to_F, other_to_F, k in abs_composites: 587 self_to_F = RelativeNumberFieldHomomorphism_from_abs(self.Hom(F), self_abs_to_F*to_self_abs) 588 rets.append([F, self_to_F, other_to_F, k]) 589 return rets 590 518 591 def absolute_degree(self): 519 592 """ 520 593 The degree of this relative number field over the rational field.