Playing with expression optimization using factorsum etc.



Playing a bit with optimizing sums of products....

The result of factorsum when the products share variables depends on
the variable names:

   factorsum((a+b)*(b+c)+a) =>  b*c+a*c+b^2+a*b+a

but

   factorsum((a+b)*(b+c)+c) =>  (b+a+1)*c+b*(b+a)

This is annoying.  What is even more annoying is that there is no way
to adjust this (e.g. by changing ratvars).  Well, you can change the
variable ordering with ordergreat, but you can only do that once.  So
it seems you need to subst in different variables for the various
orders, something like this:

factorsumtry(ex):=
  block([vars: listofvars(ex)],
    setify(
      makelist(
        subst( map("=",perm,vars),
               factorsum(
                 subst(map("=",vars,perm), ex ))),
	perm,
        listify(
          permutations(
            makelist( xxx[i],i,1,length(vars))
                )))))$

examples:

ff: factorsumtry((a+b+c)*(c+d+e)+c) =>
{
 c*a + e*a + d*a + c*b + e*b + d*b + c^2 + e*c + d*c + c,
 c*a + e*a + d*a + c*b + (e + d) * b + c^2 + e*c + d*c + c,
 c*a + (e + d) * a + c*b + e*b + d*b + c^2 + e*c + d*c + c,
 d * (a + b) + c*a + e*a + c*b + e*b + c^2 + e*c + d*c + c,
 e * (a + b) + c*a + d*a + c*b + d*b + c^2 + e*c + d*c + c,
 c * (a + b + c + e + d + 1) + (e + d) * (a + b)
}

Now let's see how many operations they take:

countops(ex):=
  block([m:0,a:0],
        countops1(ex),
        [m,a])$

countops1(ex):=
  if not atom(ex) then
     (maplist(countops1,ex),
      if     inpart(ex,0)="+" then a:a+length(ex)-1
      elseif inpart(ex,0)="*" then m:m+length(ex)-1
      elseif inpart(ex,0)="^" then
m:m+ceiling(log(float(inpart(ex,2)))/log(2.0)))$

map(countops,listify(ff)) =>
  [[9, 9], [8, 9], [8, 9], [8, 9], [8, 9], [2, 8]]

Not quite as good as the original, which was [1,5], but...

Now let's sort by rough cost function:

cost(ex):=block([ops:countops(ex)], ops[1]*5+ops[2])$

sort(listify(ff),lambda([a,b],cost(a)<cost(b))) =>
[
 c * (a + b + c + e + d + 1) + (e + d) * (a + b),
 c*a + e*a + d*a + c*b + (e + d) * b + c^2 + e*c + d*c + c,
 c*a + (e + d) * a + c*b + e*b + d*b + c^2 + e*c + d*c + c,
 d * (a + b) + c*a + e*a + c*b + e*b + c^2 + e*c + d*c + c,
 e * (a + b) + c*a + d*a + c*b + d*b + c^2 + e*c + d*c + c,
 c*a + e*a + d*a + c*b + e*b + d*b + c^2 + e*c + d*c + c
]

We would have done better in this case with the partition approach.

               -s