如何解决错误“[不是向量]”

问题描述 投票:0回答:2

我运行这段代码来查找二阶数域的一些基本单位的范数,但我遇到了以下问题

for (q=5, 200,  for(p=q+1, 200,  if (isprime(p)==1 && isprime(q)==1 ,k1=bnfinit(y^2-2*p,1); k2=bnfinit(y^2-q,1);  k3=bnfinit(y^2-2*p*q,1); ep1=k1[8][5][1]; ep2=k2[8][5][1]; ep3=k3[8][5][1]; normep1=nfeltnorm(k1,ep1); normep2=nfeltnorm(k2,ep2); normep3=nfeltnorm(k3,ep3); li=[[q,p], [normep1, normep2, normep3]]; lis4=concat(lis4,[li]))))

它适用于小 p 和 q。但是,当我对大于 150 的 p 和 q 运行该计算时,会出现以下错误:

首先,我没有使用 bnf 的

flag=1
,但添加后,仍然出现相同的错误。

number-theory pari-gp
2个回答
1
投票

请不要使用像

...[8][5][1]
这样的索引来获取基本单位 (FU)。似乎
bnfinit
省略了某些
p
q
的 FU 矩阵。相反,使用成员函数
fu
来接收 FU。请找到下面的示例:


> [q, p] = [23, 109];
> k = bnfinit(y^2 - 2*p*q, 1);
> k[8][5]
[;]
> k[8][5][1]  \\ you will get the error here trying to index the empty matrix.
...
incorrect type in _[_] OCcompo1 [not a vector] (t_MAT).

> k.fu
[Mod(-355285121749346859670064114879166870*y - 25157598731408198132266996072608016699, y^2 - 5014)]
> norm(k.fu[1])
1

1
投票
  1. 您收到错误的原因是,默认情况下

    bnfinit
    不会非常努力地精确计算基本单位,因为结果可能很大(其大小可能是判别式大小的指数),因此计算成本非常昂贵计算甚至溢出代数数实现的可能性。当单位变大时,简单的默认方法将失败,并且
    bnfinit
    结果将不包含单位,而是包含哨兵值(空矩阵)。因此你会得到一个例外。

  2. 有一些简单的方法来修复你的代码,我不会推荐这些方法。首先,您可以检查哨兵值,甚至使用

    iferr
    捕获异常,并在这种情况下执行不同的操作。或者,如 Piotr(更有帮助)的答案所示,您可以将标志
    1
    添加到 bnfinit。这使用更复杂的内部代码,特别是数量的精确表示,而不是更快但不太可靠的浮点近似值。这仍然不会计算大型基本单位(因此使用
    k[5][8][1]
    仍然会失败),但将允许
    .fu
    方法这样做(在这种情况下,结果将被缓存并且不会被重新计算)。

  3. 为什么还是不好?好吧,如上所述,结果可能太大,以至于再次失败:因为 PARI 无法表示足够大的整数来写下您请求的结果。而且,它完全没用:你不需要那个单位,只需要它的标准! PARI 始终将

    bnfinit(,1)
    的单位计算为精确代数数,但采用因式分解形式,而不是扩展值。想一想像
    2^2^100
    这样的漂亮而紧凑的答案与其扩展的十进制表示之间的区别(顺便说一句,如果你尝试它,它会溢出;PARI 不能表示 length
    2^100
    位的整数)。

  4. 因子形式的单位可从

    bnfunits
    获得,我们可以轻松地计算它们的范数,因为后者是乘法的。函数
    nfeltnorm(bnf, x)
    可以透明地为您处理所有这些事情,因此比
    norm
    更好。您可以以任何表示形式给出
    x
    (作为有理数、整数基的列向量、多项式或表示这些元素的乘积的因式分解矩阵)。这是最好的解决方案:

     [q, p] = [23, 109];
     k = bnfinit(y^2 - 2*p*q, 1);
     u = bnfunits(k)[1]; \\ trailing elements are technical, for bnfisunit()
     nfeltnorm(k, u[1])  \\ u[2] is the torsion unit, so -1 
    

答案是

1
,就像 Piotr 的答案一样。

附注请注意,您的双循环效率低下。与

q
对应的数据应在
p
循环之外计算。您还应该使用列表,并且 PARI 本身提供了素数循环。这里有一个建议

  Normu(D) = my(k = bnfinit(y^2-D, 1), u = bnfunits(k)[1][1]); nfeltnorm(k, u); 
  {
    L = List();
    forprime (q = 5, 200,
      N2 = Normu(q);
      forprime(p = q+1, 200,
        N1 = Normu(2*p);
        N3 = Normu(2*p*q);
        listput(L, [[q,p], [N1, N2, N3]])));
  }
© www.soinside.com 2019 - 2024. All rights reserved.