Giter Club home page Giter Club logo

durand-kerner's Introduction

durand-kerner

Finds all the roots of a polynomial by Weierstrass' method (or known in Abramowitz&Stegun as the Durand-Kerner method). This is basically a generalization of Newton's method that works for multiple roots.

build status

Example

To find the roots for 1 + 1*x - 1*x^2:

var findRoots = require("durand-kerner")

var roots = findRoots([1, 1, -1])

// Now:
//      roots[0] = real part of roots
//      roots[1] = imaginary part of roots

for(var i=0; i<roots.length; ++i) {
  console.log(roots[0][i] + "+" + roots[1][i] + "i")
}

Output

 1.618033988749895+0i
-0.6180339887498949+0i

Install

Install using npm:

npm install durand-kerner

API

require("durand-kerner")(r_coeff[, i_coeff, n_iters, tolerance, initial])

Finds the roots of a polynomial whose real coefficients are given by r_coeff and imaginary coefficients by i_coeff.

  • r_coeff - the real part of the polynomial's coefficients, stored in an array
  • i_coeff - the imaginary part of the polynomial's coefficients (default all 0)
  • n_iters - Maximum number of iterations to run before bailout. Default is 100 * n * n
  • tolerance - Stopping threshold. Default is 1e-6
  • initial - Initial guess for solution vector (must have the same length as r_coeff). This also gets the solution (optional)

Returns An array of roots.

License

(c) 2013 Mikola Lysenko. MIT License

durand-kerner's People

Contributors

jaspervdg avatar mikolalysenko avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

durand-kerner's Issues

Non-deterministic behavior

I ran a performance test on this package and incidentally found that the results of the root finding are not deterministic (the performance results are great, btw).

If I run the code below 200000 times there are usually one or two cases when the algorithm fails to find the real root, Sometimes none of the found roots is not even close to the correct result, which is at 0.409458563186124. Changing tolerance values did not help so far.

for (let i = 0; i< 200000; i++) {
     window.r = [];
     let r = findRoots([1, 9, 36, 69, 36, -2043, 3747, -7092, 5328, -3520]);
     let realR = [];
     for (let j = 0; j < r[0].length; j++) {
         if (Math.abs(r[1][j]) < 1e-10) {
             realR.push(r[0][j]);
         }
     }
     if (realR.length == 0) {
         console.log("failed", r, window.r);

     }
 }
 console.log("done")

This non-deterministic if caused by the use of Math.random(). I recorded the generated random values to see if they are special in the failing cases, but I could not see a pattern at all.

My question are

  1. Can I do something to make the algorithm fail less often?
  2. Is it possible to make the algorithm deterministic?
  3. Is there a better algorithm for my case (only real roots needed, always polynomials of degree 9)

Prevent avoidable loss of precision that results in non-convergence

I ran a couple of tests against another implementation of the Weierstrass / Durand-Kerner method and noticed non-convergence in the JS code. The JS code computes the reciprocal of (a,b) for the denominator:

      //Compute reciprocal
      k1 = a*a + b*b
      if(abs(k1) > EPSILON) {
        a /=  k1
        b /= -k1
      } else {
        a = 1.0
        b = 0.0
      }

This operation when combined with the multiplication by the numerator (na,nb) can lead to loss of precision! To avoid this:

        // compute (qa,qb)=(na,nb)/(a,b) without loss of precision, overflow/underflow
        if (abs(a) >= abs(b)) {
          k1 = b/a
          k2 = a + k1*b
          qa = (na + k1*nb)/k2
          qb = (nb - k1*na)/k2
        } else {
          k1 = a/b
          k2 = k1*a + b
          qa = (k1*na + nb)/k2
          qb = (k1*nb - na)/k2
        }

To verify and compare the correction, use a polynomial of high degree with small coefficients. For example, a 100 degree polynomial with all coefficients set to 1 (that is, zr[] has 101 ones and zi[] has 101 zeros).

To complete this change, it may still be good to check that a*a + b*b <= EPSILON by adding this guard:

      k1 = a*a + b*b
      if(abs(k1) > EPSILON) {
        // compute (qa,qb)=(na,nb)/(a,b) without loss of precision, overflow/underflow
        if (abs(a) >= abs(b)) {
          k1 = b/a
          k2 = a + k1*b
          qa = (na + k1*nb)/k2
          qb = (nb - k1*na)/k2
        } else {
          k1 = a/b
          k2 = k1*a + b
          qa = (k1*na + nb)/k2
          qb = (k1*nb - na)/k2
        }
      } else {
        qa = na
        qb = nb
      }

Meaning of EPSILON and Tolerance?

Hello,

I've been using this package to compute roots with varying succes
(x+1)^3 for instance did not always return {-1,-1,-1} but had {-0.9995-0.005403i, -1.004+0.001627i,-0.9948+0.003137i} for 100nn iterations and tolerance of 1e-9.

By increasing the EPSILON from 1e-8 tot 2e-16 (the machine epsilon of Javascript) inside the package itself, I've managed to get {1,1,1}.

Can you perhaps explain why EPSILON has this effect and if I should do this a different way?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.