8

exponential equation

I'm trying to solve this exponential equation like this:

my ($l,$r);

for (1 .. 100) -> $x {
    $l = $x * e ** $x;
    $r = 5 * (e ** $x - 1);
    say $x if $l == $r;
    }

But it doesn't work. How to solve it in a straightforward and comprehensive fashion?

Sebastian
  • 676
  • 1
  • 13
Lars Malmsteen
  • 1,819
  • 2
  • 13
  • 1
    Differentiate this equation and then solve the quadratic equation. I am not sure, if Raku can help you directly with it. Would you expect Raku to analyze this algebraic expression or give you a numerical solution? Are you looking for existing libraries or want to program something yourself? Only for this specific equation? – Sebastian Apr 05 '20 at 22:31
  • 3
    Try [`Math::Symbolic`](https://github.com/raydiak/Math-Symbolic). Looks like `.new` and `.isolate` might do the trick. – raiph Apr 06 '20 at 00:10
  • @Sebastian I was wondering if there's a neat and concise solution to it. – Lars Malmsteen Apr 06 '20 at 00:20
  • 1
    I think currently there is no general solution to any exponential equation in Raku. Math::Symbolic has logarithms marked as NYI (not yet implemented). If you were asking not just for interest, but needing the solution to this or a group of similar equations, one could do the first step by hand, and let Raku do the rest, that would be possible. Then you should state, what could change, e.g. which coefficients are variable. If you just need to solve this specific equation, then you could also do it outside Raku (e.g. Wolfram Alpha). – Sebastian Apr 06 '20 at 08:00
  • The basic idea for this kind of equations is to differentiate both sides once (product rule, chain rule). Afterwards each term has e^x as factor. Factor this out and you get (quadratic equation) times e^x = 0; e^x never is 0. So you just have to solve the quadratic equation. Raku could help with parsing the equation in the first place, analyzing it, whether differentiation is the correct step, transforming it and calculating the result. – Sebastian Apr 06 '20 at 08:06
  • Hi @Sebastian. Thanks for checking out the pure raku `Math::Symbolic` and noting it doesn't do logarithms, I didn't pay enough attention. Given that the OP equation is a polynomial, perhaps [`Math::Libgsl::Polynomial`](https://github.com/frithnanth/raku-Math-Libgsl-Polynomial) is appropriate? I'm out of my depth -- I just know how to search, I don't know how to use symbolic math systems -- but I think, if someone can confirm it works well enough to solve this equation, it would be nice if that was posted as an answer (regardless of whether or not anyone views it "a neat and concise solution"). – raiph Apr 06 '20 at 09:18
  • 2
    Do you seek an algebraic or a numeric solution? – Sebastian Apr 06 '20 at 10:17
  • @Sebastian Back to using libs... And/or maybe [`use Math::Polynomial:from`](https://metacpan.org/pod/Math::Polynomial) would work well? At first glance this perl module looks notably mature *and* well maintained. It's essentially a 23 year old codebase, with two lead authors, continual commits, the latest commit a couple months ago, and "no known unresolved issues". The raku module `Math::Libgsl::Polynomial` is a brand new wrapper of a C library of about the same vintage. I think of this as a really nice contrast/compare situation; there's scope here for a definitive SO on this topic. – raiph Apr 06 '20 at 10:55
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/211059/discussion-between-raiph-and-sebastian). – raiph Apr 06 '20 at 11:21
  • This equation was posted on a foreign board and the OP was asking how to solve it in Python. This sort of problems are usually solved in Python, Matlab, Scilab, etc. I just wondered if there was a good way of solving such kind of math problems in Raku. Doesn't matter if it's algebraic or numeric. The only matter is that it be neat and comprehensive. – Lars Malmsteen Apr 06 '20 at 11:55
  • @LarsMalmsteen The problem with the code is, you only check for integer solutions, and they would have to be absolutely exact. Calculations as the exp() often have rounding errors (Raku supports rational numbers, but this formula has no rational solution). See new answer at the end for a solution. – Sebastian Apr 08 '20 at 17:50

2 Answers2

5

Sorry for the double-answering.
But here is a totally different much simpler approach solved in Raku.
(It probably can be formulated more elegant.)

#!/usr/bin/env raku

sub solver ($equ, $acc, $lower0, $upper0) {
    my Real $lower = $lower0;
    my Real $upper = $upper0;
    my Real $middle = ($lower + $upper) / 2;

    # zero must be in between
    sign($equ($lower)) != sign($equ($upper)) || die 'Bad interval!';

    for ^$acc {                                          # accuracy steps
        if sign($equ($lower)) != sign($equ($middle))
            { $upper = $middle }
        else
            { $lower = $middle }
        $middle = ($upper + $lower) / 2;
    }
    return $middle;
}

my $equ = -> $x { $x * e ** $x  -  5 * (e ** $x - 1) };  # left side - right side
my $acc = 64;                                            # 64 bit accuracy
my Real $lower = 1;                                      # start search here
my Real $upper = 100;                                    # end search here

my $solution = solver $equ, $acc, $lower, $upper;

say 'result is ', $solution;
say 'Inserted in equation calculates to ', $equ($solution), ' (hopefully nearly zero)'
Sebastian
  • 676
  • 1
  • 13
2

For Perl 5 there is Math::GSL::Roots - Find roots of arbitrary 1-D functions

https://metacpan.org/pod/Math::GSL::Roots

Raku has support for using Perl 5 code or can access the GSL C library directly, can't it?

$fspec = sub {
       my ( $x ) = shift;

       # here the function has to be inserted in the format 
       # return leftside - rightside;

       return  ($x + $x**2) - 4;


     };

gsl_root_fsolver_alloc($T); # where T is the solver algorithm, see link for the 6 type constants, e.g. $$gsl_root_fsolver_brent
gsl_root_fsolver_set( $s, $fspec, $x_lower, $x_upper ); # [$x_lower; $x_upper] is search interval
gsl_root_fsolver_iterate($s);
gsl_root_fsolver_iterate($s);
gsl_root_fsolver_iterate($s);
gsl_root_fsolver_iterate($s);
gsl_root_fsolver_iterate($s);
my $result = gsl_root_fsolver_root($s);
gsl_root_fsolver_free (s);

There are enhanced algorithms available (gsl_root_fdfsolver_*), if the derivative of a function is available.

See also https://www.gnu.org/software/gsl/doc/html/roots.html#examples for general usage

Sebastian
  • 676
  • 1
  • 13