4

我有两个不同的问题,但它们被发布在一起,因为我相信解决方案是相关的。我正在测试牛顿法和割线法(每个方法都是用循环实现的),并在相同的轴上绘制结果与计算时间的关系以比较它们。我希望(离散)牛顿法结果用蓝线连接,割线法结果用红线连接。反过来,这些行由相应的图例注释。这不会发生,因为绘图上的每个点似乎都被考虑在单个对象上,因为它们是单独创建的。该legend命令会显示两个蓝色星号,而不是一个蓝色星号和一个红色星号(我希望我可以在这里发布我的情节,但我还没有图像特权。)

这是我的缩写代码:

f = (x) % define function
figure
hold on

%% Newton
tic
while % terminating condition
    % [Newtons method]

    t = toc;
    plot(t,log(abs(f(z)),'b*-')
end

%% Secant
tic
while % terminating condition
    % [secant method]

    t = toc;
    plot(t,log(abs(f(z)),'r*-')
end

legend('Newton''s','Secant')

不用说,'-'in thelinespec什么都不做,因为只绘制了一个点,而不是一条线。我知道我可以用类似的东西在每次迭代中绘制一个线图plot([t_old t],[log(abs(f(z_old) log(abs(f(z)]),但这并不理想,尤其是因为log(abs(f(z_old)))每次都必须重新评估。此外,这并不能解决传说中的问题。

我认为,如果我能让 MATLAB 了解我正在尝试在轴上创建两个对象,一条蓝线和一条红线,我认为这两个问题都将得到解决。谢谢你。

4

3 回答 3

1

如果您不想将 x/y 数据存储在向量中,然后重新绘制整个向量,则可以使用如下代码添加到绘图线:

hNewton = [];
while % terminating condition
    % [Newtons method]
    t = toc;    
    if isempty(hNewton)
        hNewton = plot(t,log(abs(f(z))),'b*-');  % First time through plot and save the line handle
    else
        % On all subsequent passes, just add to the lines X/Y data
        set(hNewton,'XData',[get(hNewton,'XData')  t]);
        set(hNewton,'YData',[get(hNewton,'YData')  log(abs(f(z)))]);
    end
end

由于现在只有 2 行,因此图例按预期工作。

或者,您可以将代码添加到函数中的现有行

function hLineHandle = AddToLine( hLineHandle, xData, yData, lineStyle )
% AddToLine - Add data to a plotted line
    if isempty(hLineHandle)
        hLineHandle = plot(xData,yData, lineStyle);
    else
        set(hLineHandle,'XData',[get(hLineHandle,'XData')  xData]);
        set(hLineHandle,'YData',[get(hLineHandle,'YData')  yData]);
    end
end

这使得主脚本/函数中的代码更加清晰。

hNewton = [];
while % terminating condition
    % [Newtons method]
    t = toc;    
    hNewton = AddToLine(hNewton,t, log(abs(f(z))),'b*-' );
end
于 2013-09-23T07:40:10.697 回答
1

您可以使用line对象,例如:

f = (x) % define function
figure
hold on
lHandle1 = line(nan, nan); %# Generate a blank line and return the line handle
lHandle2 = line(nan, nan); %# Generate a blank line and return the line handle

%% Newton
tic
while % terminating condition
    % [Newtons method]
    t = get(lHandle1, 'XData');
    Y1 = get(lHandle1, 'YData');

    t = toc;
    Y1 = [Y1 log(abs(f(z)];
    set(lHandle1, 'XData', t, 'YData', Y1, 'LineWidth', 2 ,'Color' , [0 1 0]);

end

%% Secant
tic
while % terminating condition
    % [secant method]
    t = get(lHandle2, 'XData');
    Y2 = get(lHandle2, 'YData');

    t = toc;
    Y2 = [Y2 log(abs(f(z)];
    set(lHandle2, 'XData', t, 'YData', Y2, 'LineWidth', 2 ,'Color' , [1 0 0]);

end

legend('Newton''s','Secant')
于 2013-09-23T07:41:25.700 回答
1

仅显示代码的相关部分以提出问题的好例子。其他人已经解释了让图例按照你的意愿行事的技巧。我会寻求不同的解决方案,将您的测量值保存在向量中并在循环之后绘制图。这有两个优点:您不必对图例进行技巧,但更重要的是,您没有在循环内进行绘图,这可能会花费大量时间。我猜你的时间是由绘图决定的,所以你的算法的影响几乎不会出现在结果中。所以把你的代码改成这样(未经测试):

f = (x) % define function
% preallocate plenty of space
[t_newton, t_secant, f_newton, f_secant] = deal(nan(1, 1000));

%% Newton
tic;
i = 1;
while % terminating condition
    % [Newtons method]
    f_newton(i) = current_result;
    t_newton(i) = toc;
    i = i + 1;
end

%% Secant
tic;
i = 1;
while % terminating condition
    % [secant method]
    f_secant(i) = current_result;    
    t_secant(i) = toc;
    i = i + 1;
end

% trim NaNs (not really needed, not plotted anyhow)
t_newton = t_newton(isfinite(t_newton));
f_newton = f_newton(isfinite(f_newton));
t_secant = t_secant(isfinite(t_secant));
f_secant = f_secant(isfinite(f_secant));

% do the plot
semilogy(t_newton, abs(f_newton), t_secant, abs(f_secant))
legend('Newton''s','Secant')
于 2013-09-23T08:15:06.227 回答