2014-09-23 2 views
0

Я пытаюсь проверить эффективность использования двух методов поиска корней функции в Matlab. Для этого я подсчитываю итерации, которые принимает каждый метод, а затем выводит их для разных значений допуска (как близко f (корень) к 0). По какой-то причине, когда я вычисляю значения итерации и сохраняю их в вектор - потому что существуют разные значения для разных допусков - вектор, похоже, заполняется только 0. Я смущен этим, потому что функция, которую я написал, не должна быть возвращая 0 как значение итерации. Вот весь мой код:Вектор в Matlab не заполняет правильные значения

function cooldrive() 
    a = 0.1; b = 3; 
    tol = 0.01; 
    L = 1:0.1:4; 
    r_x = zeros(1, length(L)); 
    ctr = 1; 
    for i=L 
     [x, iter] = bis(a, b, tol, i); 
     r_x(ctr) = x; 
     ctr = ctr+1; 
     b = x; 
    end 

    r_x = r_x.^2; 
    figure 
    plot(L, r_x, '.-b', 'markersize', 16) 
    ylabel('Decay Rate, x^2'), xlabel('Length, L'), title('Cooling Rate') 
    grid 

    x = (a+b)/2; 
    r_iter_newt = zeros(1, 8); 
    r_iter_bis = zeros(1, 8); 
    r_tol = zeros(1, 8); 
    ctr = 1; 
    for j=1:8 
     tol = 10^(-1*j); 
     [x_newt, iter_newt] = newt(x, tol, 1); 
     [x_bis, iter_bis] = bis(a, b, tol, 1); 
     b = x_bis; 
     r_iter_newt(ctr) = iter_newt; 
     r_iter_bis(ctr) = iter_bis; 
     r_tol(ctr) = tol; 
     ctr = ctr+1; 
    end 

    figure 
    plot(r_tol, r_iter_newt, '.-r', 'markersize', 16) 
    hold on 
    plot(r_tol, r_iter_bis, '.-b', 'markersize', 16); 
    hold off 
return 

%% Bisection Method 
function [x, iter] = bis(a, b, tol, L) 
    iter = 0; 
    z1 = coolfun(a, L); 
    z2 = coolfun(b, L); 
    if z1 * z2 > 0 
     disp('Root may not exist') 
     x = NaN; 
     iter = NaN; 
     return 
    end 

    x = (a+b)/2; 

    while abs(coolfun(x, L)) > tol 
     if (coolfun(a,L)*coolfun(x,L)) <= 0 
      b = x; 
     else 
      a = x; 
     end 
     x = (a+b)/2; 
     iter = iter + 1; 
    end 
    %[x, iter] = bis(a, b, tol, L); 
return 

%% Newton's Method 
function [ox, iter] = newt(ix, tol, L) 
    iter = 0; 
    while abs(coolfun(ix, L)) > tol 
     x_j = ix - (coolfun(ix, L)/coolfundx(ix, L)); 
     ix = x_j; 
     iter = iter+1; 
    end 
    ox = ix; 
return 

%% Evaluate function 
function val = coolfun(x, L) 
    val = sin(x*L) + x*cos(x*L); 
return 

%% Evaluate Function's Derivative 
function val = coolfundx(x, L) 
    val = (L*cos(x*L)) - (L*x*sin(x*L)) + cos(x*L); 
return 

В приведенном выше коде, значение iter_bis всегда 0, так что значения в r_iter_bis являются NaN, 0, 0, .... я не вижу причин, почему это происходит.

ответ

1

Проблема заключается в том, что вы проверяете корень fora на существование. У вас есть

z1 = coolfun(a, L); 
z2 = coolfun(b, L); 
if z1 * z2 > 0 
    disp('Root may not exist') 

однако, так как функция, которую вы пытаетесь решить не монотонна, вы можете иметь обе конечные точки положительные, но промежуточные точки отрицательной (или наоборот). В этом случае существует множество нулей, но ваш тест говорит, что они этого не делают, и ваш код остановится там.

Проблема действительно с методом. Метод биссекции не работает для немонотонных функций. Вы должны знать, основываясь на том, является ли ваше значение функции положительным или отрицательным, каким способом двигаться, чтобы приблизиться к нулю, но если ваша функция не монотонна, то вы не знаете.

Вам либо необходимо ограничить домен поиска в режиме биссекции, чтобы функция была монотонной, либо использовала другой метод.

Смежные вопросы