Karim Belabas on Wed, 07 Aug 2013 22:42:52 +0200


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: Variable checker


* Dirk Laurie [2013-08-07 16:26]:
> I have written a routine that for a given expression checks whether
> it contains any variables that are not in a given list. It works.
> 
> Only problem is, I don't understand why.
> 
> { foreign(expr,vars) =
>   if (type(expr)=="t_RFRAC",
>     return(foreign(numerator(expr)) || foreign(denominator(expr))));
>   my(var=trap(,,variable(expr)));
>   print(expr", "var);
>   if(!var, return(0));  \\ expr is scalar
>   if(subst(vars,var,0)==vars, return(var));  \\ var is not present in vars
>   foreign(polcoeff(expr,0),vars) }

Why do you only check the degree 0 coefficient ?

 ? foreign(x^3 + b*x^2 + a*x, [x,a])
 %1 = 0

Independently, if I build the expression in a slightly different way, it
will no longer work:

 ? foreign(Pol([1,a,b]), [x,a])
 %2 = 0

> ? foreign(x^2+a*x+b,[x,b])
> x^2 + a*x + b, x
> b, a
> %2 = a
> 
> The value of 'expr' on the recursive call is 'b'. There's no 'a' in
> it. Yet variable(expr) returns 'a'.
> 
> I'm grateful it does. But it baffles me.

In 2.6.*, you can use 

  dbg_x(expr)    \\ programmatic equivalent of \x applied to 'expr'

to debug such problems. In the recursive call, it prints

[&=00007ffff64de508] POL(lg=3):1400000000000003 (+,varn=24):4006000000000000 00007ffff64de4e8 
  coef of degree 0 = [&=00007ffff64de4e8] POL(lg=4):1400000000000004 (+,varn=25):4006400000000000 00000000007dd620 00007ffff64de4d0 
    coef of degree 0 = gen_0
    coef of degree 1 = [&=00007ffff64de4d0] INT(lg=3):0200000000000003 (+,lgefint=3):4000000000000003 0000000000000001 


which is a little hard to read, but corresponds to a t_POL with t_POL
coefficients, actually equal to

  (0 + 1*b) * a^0

so variable(expr) is correct in returning 'a'.


My approach for this, would be to write a function

  variables(expr)

returning a Set() of all variables occuring in 'expr'. Then one could use

  setminus(variables(expr), Set(vars))    

(or 'vars' by itself if we can assume that it's already a Set).


Using 2.6.* syntax (iferr() instead of trap(), now deprecated...) :

  variables(expr) =
  { my(v, L);
    if (type(expr) == "t_RFRAC",
      my (n = numerator(expr), d = denominator(expr));
      return (setunion(variables(n), variables(d)))
    );
    v = Vec(expr); if (v === [expr], return ([]) /*scalar*/);
    L = iferr([variable(expr)], E, []);
    for (i = 1, #v, L = setunion(L, variables(v[i])));
    L;
  }
  foreign(expr, vars) =  setminus(variables(expr), Set(vars));

  ? expr = [x^2+a*x, 1/t; u + O(z), "STR"];
  ? variables(expr)
  %2 = [x, z, t, a, u]
  ? foreign(expr, [a,u,v])
  %3 = [x, z, t]

(Quick, mostly untested, hack. Possibly not entirely foolproof :-)

Cheers,

    K.B.

P.S. it's awkward to have variable() raise an error when no variable can be
associated to the argument. It would be more useful to have it return a
sentinel value such as '0'.

--
Karim Belabas, IMB (UMR 5251)  Tel: (+33) (0)5 40 00 26 17
Universite Bordeaux 1          Fax: (+33) (0)5 40 00 69 50
351, cours de la Liberation    http://www.math.u-bordeaux1.fr/~kbelabas/
F-33405 Talence (France)       http://pari.math.u-bordeaux1.fr/  [PARI/GP]
`