Numerical Methods: Bisection Method Using Scilab - Labratsgonewild

Saturday, October 5, 2013

Numerical Methods: Bisection Method Using Scilab

Bisection Method of finding the roots of an equation is both simple and straight forward - I really enjoyed playing with bisection back in college (oooh yeah ES84 days) and I decided to make a post and implement bisection in scilab.

I also included a helper function that will plot the equation and will illustrate where the roots are by also plotting [latex] y = 0 [/latex] :)

First lets define bisection, here is what wikipedia has to say
The bisection method in mathematics is a root-finding method which repeatedly bisects an interval and then selects a subinterval in which a root must lie for further processing.

But first! What is a root? Here's how algebra.com defines it:
A number is called a root of an equation if when the number is substituted into the equation and both sides simplified, the result is an identity, such as 2=2 or 8=8, etc.

I remember roots as the numbers you get when you equate a factor to zero and solve for x, (x-1) will result into a root of 1.

When put into a graphe a root will look like this:
Source: codecogs

The numbers that correspond to a, b, and c above are the roots - it can also be observed that these are the values in which the line (function) crosses zero :) Bisection's root finding is then based on the principle that if there is a root between two points (it passes zero) then multiplying the result of the equation using those two points will result into a negative number!

Here is how bisection goes:

  1. There is a given equation and a range where we want to find the roots

  2. Evaluate the equation on both ends of the range - there must be a change of signs, if there is no change in signs then its either have no roots in the interval or you fell into a bisection pitfall. Note 1.

  3.  If there is a change of sign then it means that there is atleast one root in the interval - lets iterate to find the root. Note 2.

  4. Get the center of the interval.[latex] center = \frac{upperLimit}{lowerLimi}[/latex]

  5. Check the two new sub-ranges, (lowerLimit,center) and (center,upperLimit), do step 2 on the two ranges, if the first subrange results into a change of sign then [latex] upperLimit = center[/latex]

  6. Evaluate the relative error of the result and if the error is with in bounds then [latex] root = center [/latex], if not then repeat step 4 (on the new interval) until error is met.

We now have our algorithm! Lets program! I would like you guys to program this by yourselves, in case your pressed for time you can get the code below to try it out. I also created a helper .sci file so that you can visualize the root and how many roots are there in that interval.

Lets program!

//The Bisectfunction will do bisection method in the expression 'theFunction'
// - using 'xLeft' and 'xRight' as the interval of interest
// - it will use the 'acceptableErrorInPercent' variable as the stopping criterion

//Note: xRight must be greater than xLeft for things to make sense
//PS. Please put us as a source when you use our code below :)

//This function will use plotThatThing which is declareed on a different .sci file please load it first
function [root]=MyOwnBisection(theFunction, xLeft, xRight, acceptableErrorInPercent)

    //plot the function to get a look on how should it look
    plotThatThing(theFunction, xLeft, xRight,0.001);

    x = xRight;
    fOfRight = evstr(theFunction); //Evaluate theFunction using the value at the right for the [xLeft,xRight] pair
    x = xLeft;
    fOfLeft = evstr(theFunction);  //Evaluate theFunction using the value at the right for the [xLeft,xRight] pair

    //Before trying to loop through the values, check first if there is a root in the interval 
    //- please take note that this check may fail when there are even number of roots in the given interval

    if (fOfRight*fOfLeft >= 0) then
        root = "There is no root between " + string(xLeft) + " and " + string(xRight) + "Or there might be an even number of roots in the said interval";
    else
        //There is a root! The number of roots can either be 1 or any odd number
        exactSolution = 'not yet found';
        howFarAreWeInPercent = 100;     //Lets start with 100% away
        midX =(xRight + xLeft)/2;

        //Now lets start the loop - this will search for the root in the given interval
        while howFarAreWeInPercent > acceptableErrorInPercent & exactSolution == 'not yet found',
            x = midX;
            fr = evstr(theFunction);
            x = xLeft;
            fOfLeft = evstr(theFunction);

            //Choose the next subinterval to do bisection
            if(fOfLeft*fr < 0) then
                xRight = midX;                  
            elseif(fOfLeft*fr > 0) then
                xLeft = midX;
            elseif(fOfLeft*fr == 0) then
                root = midX;
                exactSolution = 'found';
            end 

            //Check for the darn error!
            previousMidX = midX;
            midX =(xRight + xLeft)/2;
            howFarAreWeInPercent = abs((midX - previousMidX)/midX)*100;
        end

        //the current midX is assumed to be the nearest number to the target value 
        if (exactSolution == 'not yet found') then
            root = midX;
        end
    end
 endfunction

This function uses plotThatThing.sci which is the code below
//this will plot the given function/expression in the given interval
function plotThatThing(theFunction, xLeft, xRight, theStepSize)
    x = xLeft : theStepSize : xRight;
    y = evstr(theFunction);
    plot(x, y, x, 0); 
endfunction
Pitfalls of the bisection method:

  1. It wont be able to detect roots if there is an even number of roots in the given interval this is Note 1.

  2. When the sign changes in a particular interval there could be more than 1 root, however bisection will only give you one.

  3. Im still thinking if you have more to add please leave a comment and ill add it to the list :)



Featured image is from Code Project

6 comments:

  1. Hi there, can you please give an example with a function, how should be on the command line? [root]=MyOwnBisection(x^2+log(x), 0.5, 1, 10^-4)
    is this a right way to call a function? I get "Undefined variable: x"!
    Thanks.

    ReplyDelete
  2. Hi Sam,

    You will need to make sure that the functions (plotThatThing and MyOwnBisection) are loaded in scilab.

    The command above is close you will just need to add quotes to the functions so it will end up like this:

    --> root = MyOwnBisection('x^2+log(x)', 0.5, 1, 10^-4)

    this is so because the MyOwnBisection function makes use of evstr which evaluates a string thus the first argument must be a string :)

    cheers!

    ReplyDelete
  3. Hi,
    I did load the functions beforehand.
    I tried the line you said, now I get the following error:
    "!--error 2 Invalid factor."
    Can you explain please?
    Thanks,

    ReplyDelete
  4. Hi Sam,

    Just replace the single quotes with double quotes :)

    -->root = MyOwnBisection("x^2+log(x)", 0.5, 1, 10^-4)
    root =

    0.6529183

    ReplyDelete