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

 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]
`

```