简体   繁体   中英

Cannot use log terms in Algorithm::CurveFit

I'm attempting to use Algorithm::CurveFit to fit some numbers. I have an unusual installation, as I had problems installing Algorithm::CurveFit: CPAN fails to install Algorithm::CurveFit so my installation looks different than the standard by necessity.

the code looks like:

sub curvefit {
    my ($args) = @_;
    my @undef_args = grep { !defined $args->{$_}} ('formula', 'parameters', 'x', 'y');
    if (scalar @undef_args > 0) {
        p @undef_args;
        die 'the above args are necessary, but were not defined.';
    }
    foreach my $key ('x', 'y') {
        if (scalar @{ $args->{$key} } == 0) {
            return 'no valid points'
        }
    }
    if ($args->{formula} !~ m/x/) {
        die "$args->{formula} must contain \"x\" in order to be interpreted."
    }
    $args->{max_iter} = $args->{max_iter} // 100; # maximum iterations
    my $square_residual = CurveFit->curve_fit( # "Algorithm::CurveFit" for users who could install the module
         formula            => $args->{formula}, # may be a Math::Symbolic tree instead
         params             => $args->{parameters},
         variable           => 'x',
         xdata              => $args->{x},
         ydata              => $args->{y},
         maximum_iterations => $args->{max_iter},
    );
    my %fit;
    $fit{function} = $args->{formula};
    foreach my $var (@{ $args->{parameters} }) {
        $fit{$var->[0]}{best}  = $var->[1];
        $fit{$var->[0]}{error} = $var->[2];
        $fit{function} =~ s/$var->[0]/$var->[1]/;
    }
    $fit{square_residual} = $square_residual;
    return \%fit
}

my @x = (1,2,3); # ensuring that 0 won't be fed to log to produce negative infinity
my @y = (10, 19, 33);

my $log_fit = curvefit({
    formula    => 'a * log(x) + b',
    parameters => [
    # name, guess, sufficient accuracy
        ['a', 0, 0.01],
        ['b', 1, 0.01],
    ],
    'x'        => \@x,
    'y'        => \@y
});

and produces the error in the Math::Symbolic package:

Can't call method "term_type" on an undefined value at /home/con/perl5/perlbrew/perls/perl-5.34.0/lib/site_perl/5.34.0/Math/Symbolic/Operator.pm line 595.
    Math::Symbolic::Operator::simplify(Math::Symbolic::Operator=HASH(0x564d6cebb830), 1) called at /home/con/perl5/perlbrew/perls/perl-5.34.0/lib/site_perl/5.34.0/Math/Symbolic/Operator.pm line 589
    Math::Symbolic::Operator::simplify(Math::Symbolic::Operator=HASH(0x564d6cebc470), 1) called at /home/con/perl5/perlbrew/perls/perl-5.34.0/lib/site_perl/5.34.0/Math/Symbolic/Operator.pm line 589
    Math::Symbolic::Operator::simplify(Math::Symbolic::Operator=HASH(0x564d6cebeed8), 1) called at /home/con/perl5/perlbrew/perls/perl-5.34.0/lib/site_perl/5.34.0/Math/Symbolic/Operator.pm line 589
    Math::Symbolic::Operator::simplify(Math::Symbolic::Operator=HASH(0x564d6bd209d8)) called at /home/con/perl5/perlbrew/perls/perl-5.34.0/lib/site_perl/5.34.0/x86_64-linux/CurveFit.pm line 123
    CurveFit::curve_fit("CurveFit", "formula", "a * log(x) + b", "params", ARRAY(0x564d6bcb2650), "variable", "x", "xdata", ...) called at 5.all.valid.pl line 33
    main::curvefit(HASH(0x564d6bcb26c8)) called at 5.all.valid.pl line 48
Command exited with non-zero status 255

going to that line in Math::Symbolic :

    my $tt2  = $o2->term_type();

I don't see how that helps to debug the problem.

Furthermore, Math::Symbolic seems to imply that I can use log terms: https://metacpan.org/pod/Math::Symbolic

How can I use a logarithm in the CurveFit subroutine?

From Math::Symbolic::Operator ,

Supported operator symbols: (number of operands and their function in parens)

 ... log => logarithm (2: base, function)...

The correct usage for the natural log would therefore be log(2.7182818284590452, x)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM