How to resolve the algorithm Formal power series step by step in the Raku programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Formal power series step by step in the Raku programming language

Table of Contents

Problem Statement

A power series is an infinite sum of the form

a

0

a

1

⋅ x +

a

2

x

2

a

3

x

3

{\displaystyle a_{0}+a_{1}\cdot x+a_{2}\cdot x^{2}+a_{3}\cdot x^{3}+\cdots }

The ai are called the coefficients of the series. Such sums can be added, multiplied etc., where the new coefficients of the powers of x are calculated according to the usual rules. If one is not interested in evaluating such a series for particular values of x, or in other words, if convergence doesn't play a role, then such a collection of coefficients is called formal power series. It can be treated like a new kind of number. Task: Implement formal power series as a numeric type. Operations should at least include addition, multiplication, division and additionally non-numeric operations like differentiation and integration (with an integration constant of zero). Take care that your implementation deals with the potentially infinite number of coefficients. As an example, define the power series of sine and cosine in terms of each other using integration, as in

sin ⁡ x

0

x

cos ⁡ t

d t

{\displaystyle \sin x=\int _{0}^{x}\cos t,dt}

cos ⁡ x

1 −

0

x

sin ⁡ t

d t

{\displaystyle \cos x=1-\int _{0}^{x}\sin t,dt}

Goals: Demonstrate how the language handles new numeric types and delayed (or lazy) evaluation.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Formal power series step by step in the Raku programming language

Source code in the raku programming language

class DerFPS { ... }
class IntFPS { ... }

role FPS {
    method coeffs        { ... }
    method differentiate { DerFPS.new(:x(self)) }
    method integrate     { IntFPS.new(:x(self)) }

    method pretty($n) {
        sub super($i) { $i.trans('0123456789' => '⁰¹²³⁴⁵⁶⁷⁸⁹') }
        my $str = $.coeffs[0];
        for flat 1..$n Z $.coeffs[1..$n] -> $p, $c {
            when $c > 0 { $str ~= " + { $c .nude.join: '/'}∙x{super($p)}" }
            when $c < 0 { $str ~= " - {-$c .nude.join: '/'}∙x{super($p)}" }
        }
        $str;
    }
}

class ExplicitFPS does FPS { has @.coeffs }

class SumFPS does FPS {
    has FPS ($.x, $.y);
    method coeffs { $.x.coeffs Z+ $.y.coeffs }
}

class DifFPS does FPS {
    has FPS ($.x, $.y);
    method coeffs { $.x.coeffs Z- $.y.coeffs }
}

class ProFPS does FPS {
    has FPS ($.x, $.y);
    method coeffs { (0..*).map: { [+] ($.x.coeffs[0..$_] Z* $.y.coeffs[$_...0]) } }
}

class InvFPS does FPS {
    has FPS $.x;
    method coeffs {
        # see http://en.wikipedia.org/wiki/Formal_power_series#Inverting_series
        flat gather {
            my @a = $.x.coeffs;
            @a[0] != 0 or fail "Cannot invert power series with zero constant term.";
            take my @b = (1 / @a[0]);
            take @b[$_] = -@b[0] * [+] (@a[1..$_] Z* @b[$_-1...0]) for 1..*;
        }
    }
}

class DerFPS does FPS {
    has FPS $.x;
    method coeffs { (1..*).map: { $_ * $.x.coeffs[$_] } }
}

class IntFPS does FPS {
    has FPS $.x;
    method coeffs { 0, |(0..*).map: { $.x.coeffs[$_] / ($_+1) } }
}

class DeferredFPS does FPS {
    has FPS $.realized is rw;
    method coeffs { $.realized.coeffs }
}

# some arithmetic operations for formal power series
multi infix:<+>(FPS $x, FPS $y) { SumFPS.new(:$x, :$y) }
multi infix:<->(FPS $x, FPS $y) { DifFPS.new(:$x, :$y) }
multi infix:<*>(FPS $x, FPS $y) { ProFPS.new(:$x, :$y) }
multi infix:(FPS $x, FPS $y) { $x * InvFPS.new(:x($y)) }

# an example of a mixed-type operator:
multi infix:<->(Numeric $x, FPS $y) { ExplicitFPS.new(:coeffs(lazy flat $x, 0 xx *)) - $y }

# define sine and cosine in terms of each other
my $sin       = DeferredFPS.new;
my $cos       = 1 - $sin.integrate;
$sin.realized = $cos.integrate;

# define tangent in terms of sine and cosine
my $tan       = $sin / $cos;

say 'sin(x) ≈ ' ~ $sin.pretty(10);
say 'cos(x) ≈ ' ~ $cos.pretty(10);
say 'tan(x) ≈ ' ~ $tan.pretty(10);


  

You may also check:How to resolve the algorithm Count in factors step by step in the R programming language
You may also check:How to resolve the algorithm War card game step by step in the Nim programming language
You may also check:How to resolve the algorithm Order two numerical lists step by step in the AWK programming language
You may also check:How to resolve the algorithm Detect division by zero step by step in the PL/I programming language
You may also check:How to resolve the algorithm Generate Chess960 starting position step by step in the UNIX Shell programming language