Search code examples
mathmaximawxmaxima

Intervals for term structures


For a student learning platform (mathematics) we have managed to include Maxima and evaluate terms/equations/numbers on equivalence. For this we have programmed an algorithm randomly choosing numbers for all the variables and then comparing the two results whether they lead to the same values or not (more mathematically speaking we are seeing the terms as functions and comparing them at specific places).

Now the problem comes: Unfortunately, there must be the possibility to define ranges for coefficients of variables. So e.g. the correct solution [4,5]x^2-[3,4]x at the position x=10 leads to [4,5]*10^2-[3,4]*10. Here we have to find the minimum/maximum of this expression with e.g. the range of 4 to 5 as the coefficient before x^2. I have not been able to do this with native Maxima functions, so I am asking here for help. I am also wondering whether this is possible to combine with other functions such as sin, e etc. or whether this makes the whole optimisation problem too complex (and we should only allow polynomials).

Your help is greatly appreciated!

Best, Leon


Solution

  • To summarize what we said in the comments, we have something like sum(a[k]*e[k], k, 1, n) where coefficients a[k] are constrained by intervals I[k] and e[k] is an expression in x. Given that x is a specific value, then the sum is a linear combination of the a[k] and the extreme values are at the corners of the hypercube given by the Cartesian product of the intervals.

    A simple solution is to just enumerate the corners of the hypercube and evaluate the sum at each corner, and see which is greatest. (If there are ties, that means that the sum is not actually a function of some coefficient. Given the problem statement, that means the corresponding e[k] is zero. Let's look for and omit such coefficients, then there can only be a unique maximum.)

    Here's my attempt at a solution, hope I've understood what's going on and what needs to happen. Assume without checking that a, e, and I are all the same length, namely n.

    find_maximum_corner (a, e, I, x, x1) :=
        block ([n, ee, ii_omit, a_omit, ii_keep, a_keep, e_keep, I_keep,
                corners_positions, corners_equations, corners_values,
                maximum_value, ii_maximum_value],
               n: length(a),
               ee: subst (x = x1, sum (a[k]*e[k], k, 1, n)),
               ii_omit: sublist_indices (e, lambda ([e1], subst (x = x1, e1) = 0)),
               a_omit: makelist (a[i], i, ii_omit),
               ii_keep: sublist (makelist (i, i, 1, n), lambda ([i1], not member (i1, ii_omit))),
               a_keep: makelist (a[i], i, ii_keep),
               e_keep: makelist (e[i], i, ii_keep),
               I_keep: makelist (I[i], i, ii_keep),
               corners_positions: apply (cartesian_product_list, I_keep),
               corners_equations: map (lambda ([l], map (lambda ([a1, l1], a1 = l1), a_keep, l)), corners_positions),
               corners_values: map (lambda ([eqs], subst (eqs, ee)), corners_equations),
               maximum_value: lmax (corners_values),
               ii_maximum_value: sublist_indices (corners_values, lambda ([v], v = maximum_value)),
               [maximum_value, corners_equations[ii_maximum_value[1]], a_omit]);
    

    That returns a list comprising the maximum value, the corner at which the sum reaches its maximum, and the list of variables omitted because the corresponding e[k] is zero at x = x1.

    This solution makes use of cartesian_product_list which was recently added (in Maxima 5.43). If you are working with a version older than 5.43, I can write out a simple implementation of it.

    With this solution I get:

    (%i6) find_maximum_corner ([a, b, c], [x, -x^2, x^3], [[3, 4], [-2, 2], [4, 5]], x, 3);
    (%o6)          [165, [a = 4, b = - 2, c = 5], []]
    (%i7) find_maximum_corner ([a, b, c], [x, -(x - 3)^2, x^3], [[3, 4], [-2, 2], [4, 5]], x, 3);
    (%o7)              [147, [a = 4, c = 5], [b]]
    

    the second example showing a variable that drops out because the corresponding expression is zero.

    It's not necessary for the expressions e[k] to be polynomials; they can be any functions of x (provided that subst(x = x1, e[k]) simplifies to a number when x1 is a number -- this is the case for most or all of the built-in math functions).