Author Topic: Just a Fun Little Program  (Read 2855 times)

0 Members and 1 Guest are viewing this topic.

Offline Thaeris

  • Can take his lumps
  • 211
  • Away in Limbo
Just a Fun Little Program
I usually will say that I hate Matlab hands down, but the symbolic math toolbox is a tremendous asset to use. The project for which this thread is the subject is a bit... overdue, but using Matlab as more of a conventional programming language is nice for a change. Essentially, the program accepts any function in terms of 'x' (and just 'x,' as coded) and uses Newton's Method to find the zeros or roots of the function, at least any root closest to the user input. I'll go over bugs later...

Code: [Select]
function [ f, df, n, ntest, c, flag ] = NewtonZeros()
syms x f df; %Initialize symbolic math variables.
f = input('Enter a function in terms of x: '); %Input a function 'f' here in terms of 'x.'
df = diff(f, 'x'); %Differentiates function 'f' in terms of 'x.'
n = input('Give an estimate of the function zeroes: '); %Zero or root estimate for 'x' - this value will be sustituted in for 'x.'
flag = 0; %Initializes the loop flag.
c = 0; %Initializes the count value.
while flag ~= 1 %Begin primary loop: looking for closest zero to 'n' input.
    n = n - ((subs(f,x,n))/(subs(df,x,n))); %Perform Newton zero function.
    if c == 0 %Initiate precision check data insertion.
        ntest = n;
    end %End data insertion.
    c = c + 1; %Augment count.
    if c == 4 %Initiate precision check sequence.
        ntest = (round( ntest * 100000 )/round( n * 100000 )); %Comparator: precision met if 'ntest' == 1.
        if ntest == 1 %Ends loop if comparator precision == 1.
            flag = 1;
        else % Resets count and data insertion phase if precsion is not met.
            c = 0;
        end
    end %End precision check sequence.
end %End primary loop: value found.
n %Return value.
end

Now, the program will go into an infinite loop if you happen to select a discontinuity and will only find one zero at a time. There certainly must be methods of sorting such problems out, but I think that's beyond the scope of this project. Perhaps I'll finish playing with it at some later date.  :)
"trolls are clearly social rejects and therefore should be isolated from society, or perhaps impaled."

-Nuke



"Look on the bright side, how many release dates have been given for Doomsday, and it still isn't out yet.

It's the Duke Nukem Forever of prophecies..."


"Jesus saves.

Everyone else takes normal damage.
"

-Flipside

"pirating software is a lesser evil than stealing but its still evil. but since i pride myself for being evil, almost anything is fair game."


"i never understood why women get the creeps so ****ing easily. i mean most serial killers act perfectly normal, until they kill you."


-Nuke

 

Offline Thaeris

  • Can take his lumps
  • 211
  • Away in Limbo
Re: Just a Fun Little Program
Oh God, why did this take so long to finish?

Regardless, after many hours of pondering on how to optimize the algorithms/code, I finally have a pretty efficient code which bisects a given function to find a function zero:

Code: [Select]
function [ f, n1, n2, n3, a, b, c ] = BisectZeros()
syms f x; %Initialize symbolic values. This will enable easy function manipulation.
f = input('Enter a function in terms of x: '); %Enables universal usage of function input.
c = 0; %Initialize 'c' for loop test. This variable will be used again later.
while c ~= 1 %'Bound input' tester start.
    n1 = input('Give a value for the lower bound of the target region: '); %User enters first x-coordinate value.
    n2 = input('Give a value for the upper bound of the target region: '); %User enters second x-coordinate value.
    a = subs(f,x,n1); %Initialize 'a' as a test value. This variable will be re-used later.
    b = subs(f,x,n2); %Initialize 'b' as a test value. This variable will be re-used later.
    if a < 0 %Initiate a process to create a test value for the lower initial bound of the target region.
        a = 0;
    else
        a = 1;
    end %Test value for 'n1' established.
    if b < 0 %Initiate a process to create a test value for the upper initial bound of the target region.
        b = 0;
    else
        b = 1;
    end %Test value for 'n2' established.
    if a + b ~= 1 %User feedback function.
        disp('The current set of values will not find a function zero. Please select a new set of values.');
    else %Only if 'a' + 'b' == 1 will the input tester end, returning 'c' = 1, ending the loop.
        c = 1;
    end
end %'Bound input' tester restart or end point.
while b ~= 2 %Primary evaluation loop start. By setting the end condition to '2' for variable 'b,' we do not need to add another line to reset the value.
    n3 = ( n1 + n2 )/2; %Finds the 'x'-coordinate of the bisection value.
    c = subs(f,x,n3); %Redefine 'c' for boolean testing.
    if c < 0 %Initiate process to make 'c' a boolean value.
        c = 0;
    else
        c = 1;
    end %End process to make 'c' a boolean value.
    if a + c == 1 %Initiates 'target bounding region' test.
        n2 = n3;
    else %This substitues in corresponding logic from the condition 'if b + c == 1, n1 = n3,' where variable 'b' was the one used in the 'bound input tester' loop.
        n1 = n3;
    end %Ends 'target bounding region' test.
    a = subs(f,x,n1); %Variable 'a' is re-used as a value testing function.
    if a < 0 %Re-use of variable 'a' as a test value for 'n1.'
        a = 0;
    else
        a = 1;
    end %Test value for 'n1' established.
    if round( subs(f,x,n3) * 100000 ) == 0 %Precision test conditional checking device. If the zero has been found within the tolerance range, the function ends: 'b' set to '2.'
        b = 2;
    end
end %End evaluation loop.
n3 %Output.
end

I mean seriously, I feel like a moron. This is simple garbage, but IT TOOK FOR-EVER!  :mad:
"trolls are clearly social rejects and therefore should be isolated from society, or perhaps impaled."

-Nuke



"Look on the bright side, how many release dates have been given for Doomsday, and it still isn't out yet.

It's the Duke Nukem Forever of prophecies..."


"Jesus saves.

Everyone else takes normal damage.
"

-Flipside

"pirating software is a lesser evil than stealing but its still evil. but since i pride myself for being evil, almost anything is fair game."


"i never understood why women get the creeps so ****ing easily. i mean most serial killers act perfectly normal, until they kill you."


-Nuke

 

Offline Mika

  • 28
Re: Just a Fun Little Program
Was there a reason for not using FMINUNC or FZERO?
Relaxed movement is always more effective than forced movement.

  

Offline Thaeris

  • Can take his lumps
  • 211
  • Away in Limbo
Re: Just a Fun Little Program
Whoa, that was unexpected.  :)

Thanks for dropping in. No, those pre-built functions were not used as the point of the project was to code a solution to finding the zeros by means of more standard coding practices. I kind of... bypassed some of that as I used the symbolic math toolbox (you know, the stuff which almost makes MATLAB cool...) for easy function manipulation - that makes the programs pretty much universal, which was the idea.

Looking back, they are a little buggy depending on the input, and I should have added more checking features if I'd have known what to do at the time. For example, adding a flag tied to a while loop with regards to the function input for the bisection method would have been a good idea (yeah, that's a mouthful...), as using symbolic math's ability to differentiate a function would make you change the function if you accidentally entered a function which was constant (I did that once and had to restart MATLAB...). Using "isnan()" on Newton's method would have let me fix a bug which would leave the program in an infinte loop if you entered the test input as a point of discontinuity. Just little things like that...

The important thing is that the class is over. I got an A in the class, so I'm happy. And I still dislike MATLAB. :p
"trolls are clearly social rejects and therefore should be isolated from society, or perhaps impaled."

-Nuke



"Look on the bright side, how many release dates have been given for Doomsday, and it still isn't out yet.

It's the Duke Nukem Forever of prophecies..."


"Jesus saves.

Everyone else takes normal damage.
"

-Flipside

"pirating software is a lesser evil than stealing but its still evil. but since i pride myself for being evil, almost anything is fair game."


"i never understood why women get the creeps so ****ing easily. i mean most serial killers act perfectly normal, until they kill you."


-Nuke

 

Offline CP5670

  • Dr. Evil
  • Global Moderator
  • 212
Re: Just a Fun Little Program
If you want to do symbolic math, I think Mathematica is far better for that than Matlab. However, for what you were trying to do, there is a technique called automatic differentiation that works better than finding symbolic derivatives. There are several free Matlab packages for doing AD.

In practice, zero-finding algorithms use a combination of both of the methods you studied. Bisection is used a few times to get sufficiently close to the zero, followed by Newton's method to get an accurate result.