├── agd3d.gif ├── gd3d.gif ├── contour.gif ├── saddle1.png ├── saddle2.png ├── saddle3.png ├── saddle4.png ├── saddle5.png ├── saddle6.png ├── alpha_over.png ├── threeAlphas.gif ├── security.md ├── gra_des.m ├── license.txt ├── test.m ├── README.md └── animateGraDes.m /agd3d.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MATLAB-Graphics-and-App-Building/Animated-Gradient-Descent/HEAD/agd3d.gif -------------------------------------------------------------------------------- /gd3d.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MATLAB-Graphics-and-App-Building/Animated-Gradient-Descent/HEAD/gd3d.gif -------------------------------------------------------------------------------- /contour.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MATLAB-Graphics-and-App-Building/Animated-Gradient-Descent/HEAD/contour.gif -------------------------------------------------------------------------------- /saddle1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MATLAB-Graphics-and-App-Building/Animated-Gradient-Descent/HEAD/saddle1.png -------------------------------------------------------------------------------- /saddle2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MATLAB-Graphics-and-App-Building/Animated-Gradient-Descent/HEAD/saddle2.png -------------------------------------------------------------------------------- /saddle3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MATLAB-Graphics-and-App-Building/Animated-Gradient-Descent/HEAD/saddle3.png -------------------------------------------------------------------------------- /saddle4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MATLAB-Graphics-and-App-Building/Animated-Gradient-Descent/HEAD/saddle4.png -------------------------------------------------------------------------------- /saddle5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MATLAB-Graphics-and-App-Building/Animated-Gradient-Descent/HEAD/saddle5.png -------------------------------------------------------------------------------- /saddle6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MATLAB-Graphics-and-App-Building/Animated-Gradient-Descent/HEAD/saddle6.png -------------------------------------------------------------------------------- /alpha_over.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MATLAB-Graphics-and-App-Building/Animated-Gradient-Descent/HEAD/alpha_over.png -------------------------------------------------------------------------------- /threeAlphas.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MATLAB-Graphics-and-App-Building/Animated-Gradient-Descent/HEAD/threeAlphas.gif -------------------------------------------------------------------------------- /security.md: -------------------------------------------------------------------------------- 1 | # Reporting Security Vulnerabilities 2 | 3 | If you believe you have discovered a security vulnerability, please report it to 4 | [security@mathworks.com](mailto:security@mathworks.com). Please see 5 | [MathWorks Vulnerability Disclosure Policy for Security Researchers](https://www.mathworks.com/company/aboutus/policies_statements/vulnerability-disclosure-policy.html) 6 | for additional information. -------------------------------------------------------------------------------- /gra_des.m: -------------------------------------------------------------------------------- 1 | clear all 2 | close all 3 | clc 4 | x=-10:1:10; 5 | y=-10:1:10; 6 | alpha=0.02; 7 | [X Y] = meshgrid(x,y); 8 | Z = X.^2 + Y.^2; 9 | surf(X,Y,Z,'FaceAlpha','flat','AlphaDataMapping','scaled','AlphaData',gradient(Z)) 10 | hold on; 11 | colormap(gray); 12 | meshgrid off 13 | x0 = zeros(1000,2); 14 | %x0(1,:) = randint(1,2,10); 15 | x0(1,:) = [10 10]; 16 | x0(1,:) 17 | plot3(x0(1,1),x0(1,2),(x0(1,1).^2 + x0(1,2).^2),'m*','MarkerSize',20); 18 | i=2; 19 | while(1) 20 | pause 21 | % Gradient descent equation.. 22 | x0(i,:) = x0(i-1,:) - alpha.*2.*(x0(i-1,:)); 23 | x0(i,:) 24 | plot3(x0(i,1),x0(i,2),(x0(i,1).^2 + x0(i,2).^2),'m*','MarkerSize',20) 25 | i=i+1; 26 | end -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021, The MathWorks, Inc. 2 | All rights reserved. 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 5 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 6 | 3. In all cases, the software is, and all modifications and derivatives of the software shall be, licensed to you solely for use in conjunction with MathWorks products and service offerings. 7 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test.m: -------------------------------------------------------------------------------- 1 | % Getting Started examples for animateGraDes 2 | % Copyright 2021 The MathWorks, Inc. 3 | 4 | % Example 1: Simplest 5 | %-------------------- 6 | agd = animateGraDes(); % instantiate. Draw 3D 7 | agd.funcStr='x^2+2*x*y+3*y^2+4*x+5*y+6'; % cost function is required 8 | agd.animate(); % start 9 | 10 | % Example 2: Alpha overshooting 11 | %------------------------------- 12 | agd = animateGraDes(); % instantiate, draw2D contour 13 | agd.funcStr='x^2+2*x*y+3*y^2+4*x+5*y+6'; % cost function is required 14 | % other optional parameters 15 | agd.alpha = 0.2; % big alpha 16 | agd.drawContour = true; % contour plot 17 | agd.animate(); 18 | % 19 | % Example 3: saddle point 20 | %------------------------ 21 | agd = animateGraDes(); % draw2D contour 22 | agd.alpha=0.15; % learning rate 23 | agd.funcStr='x^4-2*x^2+y^2'; % special function with saddle points 24 | agd.startPoint=[1.5 1.5]; % point not on the ridge 25 | agd.drawContour = true; % contour plot 26 | agd.xrange=-2:0.1:2; % xrange covers local min and start point 27 | agd.yrange=-2:0.1:2; % yrange covers local min and start point 28 | agd.animate(); 29 | 30 | % Example 4: Compare different learning rates 31 | %-------------------------------------------- 32 | agd = animateGraDes(); % draw2D contour 33 | agd.alpha = [0.05 0.18 0.22]; % compare four alpha values 34 | agd.funcStr='x^4-2*x^2+y^2'; % special function with saddle points 35 | agd.startPoint=[1.5 1.5]; % point not on the ridge 36 | agd.drawContour = true; % contour plot 37 | agd.xrange=-2:0.1:2; % xrange covers local min and start point 38 | agd.yrange=-2:0.1:2; % yrange covers local min and start point 39 | agd.outfile = 'threeAlphas.gif'; % generate animation gif 40 | agd.animate(); 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Animated Gradient Desent 2 | [![View Animated-Gradient-Descent on File Exchange](https://www.mathworks.com/matlabcentral/images/matlab-file-exchange.svg)](https://www.mathworks.com/matlabcentral/fileexchange/99094-animated-gradient-descent) 3 | ## Overview 4 | Gradient Descent can be considered as one of 5 | the most important algorithms in machine learning and deep learning. It is widely 6 | used in training simple machine learning models to complex deep learning networks. 7 | 8 | This matlab script can generate an animation gif which visualizes how gradient descent works in a 3D or contour plot. 9 | This can be very helpful for beginners of machine learning. 10 | 11 | In addition, user can set the cost funciton, the learning rate (alpha), and starting point of gradient descent. 12 | This allows advanced users to demonstrate or investigate the impact of these factors in training a machine learning model. 13 | 14 | Please refresh your browser to restart the animation gifs below. 15 | ### 3D plot 16 | ![gd3d](./agd3d.gif) 17 | ### Contour plot 18 | ![Contour](./threeAlphas.gif) 19 | 20 | Important features: 21 | * Support both 3D surface plot and contour plot 22 | * Allow user to enter the (cost) function to plot 23 | * Allow user to adjust learning rate to understand the effect of it 24 | * Allow user to set starting point of gradient descent, so as to investigate saddle point effect 25 | * Allow user to set the maximum steps and stop threshold 26 | * Allow user to set an array of leaning rates to compare 27 | * Use either 2D contourf or 2D contour 28 | * Generate animation GIF which can be inserted into webpage and presentation 29 | 30 | ## Usage 31 | Please refer to [test.m](./test.m) for getting started examples. 32 | 33 | ### instantiate 34 | ``` 35 | agd = animateGraDes(); 36 | ``` 37 | ### Required parameter 38 | Need to set the (cost) function for gradient descent. This is required. 39 | ``` 40 | agd.funcStr='x^2+2*x*y+3*y^2+4*x+5*y+6'; 41 | ``` 42 | This is the function used to generate the animation GIF of the contour plot above. 43 | 44 | If no more optional parameters are needed to set, just call 45 | 46 | ``` 47 | agd.animate(); 48 | ``` 49 | 50 | This starts the gradient descent. Once the local min is found, an annotation text box 51 | is shown in the figure. It includes the alpha value being used and the local min it found. 52 | 53 | ### Optional parameters 54 | All these parameters are optional. If they are not set, the default values are used. Note these need to be 55 | set before calling agd.animate() to take effect. 56 | 57 | #### range of plot 58 | This is the range for plotting the function. IMPORTANT, you need to make sure the local min and the start point of 59 | gradient descent are both within this range. Otherwise they won't be shown. 60 | You set the x (or y) range by giving the min, the increment, and the max. For example the value below means min=-10, increment=1 61 | and max = 10; 62 | 63 | ``` 64 | agd.xrange = -10:1:10; 65 | agd.yrange = -10:1:10; 66 | ``` 67 | 68 | #### learning rate 69 | ##### Single alpha 70 | Learning rate alpha is an important tuning factor when training a model. By using 71 | different values of alpha, animateGraDes can show how it affects the training. 72 | For example, if we change alpha from 0.1 to 0.2, we will get this contour plot instead. 73 | 74 | ``` 75 | agd.alpha = 0.2; 76 | ``` 77 | 78 | ![alpha_over](./alpha_over.png) 79 | 80 | The first contour plot uses alpha=0.1, and this contour plot shows alpha=0.2. This contour plot shows the effect of overshooting. 81 | 82 | Setting alpha greater than 0.3 for this cost function will make gradient descent diverge. It is getting away from the local min, and it will 83 | never reach there. 84 | 85 | The default learning rate is set to 0.1, if not set. 86 | 87 | ##### Compare different alpha values 88 | Set an array of alphas 89 | 90 | ``` 91 | agd.alpha = [0.05 0.1 0.2]; 92 | ``` 93 | 94 | 95 | #### starting point 96 | If the starting point is too far away from the local min, it could take a long time for 97 | gradient descent to reach the local min. In addition, if there are more than one local 98 | mins, the starting point might decide which local min gradient descent is going to reach. 99 | 100 | Starting point is an [x y] array: 101 | ``` 102 | agd.startPoint=[2 3]; 103 | ``` 104 | 105 | By using different function and different starting point, animateGraDes can also show the effect of 106 | saddle points. 107 | 108 | The following plots are generated using the example of this [paper](https://www.offconvex.org/2016/03/22/saddlepoints/) 109 | ``` 110 | agd = animateGraDes(); 111 | agd.alpha=0.15; 112 | agd.funcStr='x^4-2*x^2+y^2'; % this the function with saddle points 113 | agd.startPoint=[1.5 1.5]; 114 | agd.drawContour=false; 115 | agd.xrange=-2:0.1:2; 116 | agd.yrange=-2:0.1:2; 117 | agd.animate(); 118 | ``` 119 | A starting point of [1.5 1.5] avoids the saddle points and gradient decent can reach the local min [1 0] successfully. 120 | 121 | ![saddle](./saddle1.png) 122 | ![saddle](./saddle4.png) 123 | 124 | Another starting point of [-1.5 -1.5]. It can also avoid the saddle point. But it ends up in another local min [-1 0]. 125 | 126 | ``` 127 | agd.startPoint=[-1.5 -1.5]; 128 | ``` 129 | 130 | ![saddle poing](./saddle5.png) 131 | ![saddle point](./saddle6.png) 132 | 133 | Now change the starting point to [0 1.5]. This time the starting point is right on the ridge that separates those two local mins. 134 | ``` 135 | agd.startPoint=[0 1.5]; 136 | ``` 137 | Now gradient descent stops at the saddle point [0 0]: 138 | 139 | ![saddle2](./saddle2.png) ![saddle3](./saddle3.png) 140 | 141 | From physics point of view, a local min is a stable balance point, while a saddle point is an unstable balance point. Thus a 142 | small perturbation can break the balance of an unstable point. This can be used to escape the saddle point. 143 | 144 | #### stopThreshold 145 | When gradient descent gets closer to the local min, the gradient is getting smaller and smaller. This means the step gets 146 | shorter when it gets closer to the local min. A stropThreshold can be set to stop gradient descent. 147 | 148 | The default is `1E-10`. To get better accuracy set this to a smaller value. 149 | 150 | ``` 151 | agd.stopThreshold = 1E-16; 152 | ``` 153 | Keep in mind that a smaller stopThreshold can give beeter accuracy, but it will take (much) longer for gradient descent to 154 | reach the answer. 155 | 156 | #### Use contourf or contour 157 | It is an optional flag, and default to false. 158 | 159 | ``` 160 | agd.fillContour = true 161 | ``` 162 | 163 | #### outfile 164 | This optional parameter is used to output an animation gif file. It can be set like this: 165 | 166 | ``` 167 | agd.outfile='animateGraDes.gif'; 168 | ``` 169 | By default, this is empty, and no animation gif will be generated. You can still save the resulted figure into a PNG file. 170 | 171 | 172 | 173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /animateGraDes.m: -------------------------------------------------------------------------------- 1 | classdef animateGraDes < matlab.graphics.chartcontainer.ChartContainer 2 | % Copyright 2021 The MathWorks, Inc. 3 | 4 | properties (Access=public) 5 | funcStr; % Function of x, y in String 6 | alpha; % alpha(s) for gradient descent 7 | startPoint; % start point for gradient descent 8 | maxStepCount; % Stop after # steps even if min is smaller than threshold 9 | stopThreshold; % when distance is smaller than this, stop 10 | drawContour; % true for drawing 2D contour, false (default) for 3D 11 | fillContour; % use contourf instead of contour for contour plot 12 | 13 | xrange; % x range for showing funcStr 14 | yrange; % y range for showing funStr 15 | showAnnotation; % show annotation or not 16 | 17 | stepsPerSecond; % advance # steps each second 18 | outfile; % output an animation GIF if set to a filename 19 | end 20 | 21 | % protected properties for internal use only 22 | properties (Access=protected) 23 | func; % function handler of funcStr 24 | xPartial; % x partial derivative of func 25 | yPartial; % y partial derivative of func 26 | doneGraDes; % gradient descent finished 27 | readyUpdate; % All inited, ready for update 28 | 29 | FuncPlot; % 3D surface or 2D Contour 30 | PathPlots; % Gradient Descent path plot 31 | Annot; % Annotation 32 | end 33 | 34 | methods(Access=protected) 35 | function setup(~) 36 | % noop 37 | end 38 | function update(~) 39 | % noop 40 | end 41 | function setupChartContainer(obj) 42 | newcolors = [0.99 0.00 0.00 % red 43 | 0.48 0.77 0.18 % green 44 | 0.99 0.00 0.99 % magenta 45 | 0.00 0.99 0.99]; % cyan 46 | 47 | colororder(newcolors); 48 | ax = getAxes(obj); 49 | pathCount = length(obj.alpha); 50 | obj.doneGraDes = false(1, pathCount); 51 | if obj.drawContour 52 | % 2D contour and 2D path plot 53 | if obj.fillContour 54 | [~, obj.FuncPlot] = contourf(ax, [], [], [], 'ShowText', 'on'); 55 | else 56 | [~, obj.FuncPlot] = contour(ax, [], [], [], 'ShowText', 'on'); 57 | end 58 | hold(ax, 'on'); 59 | for i=1:pathCount 60 | obj.PathPlots = [obj.PathPlots plot(ax, NaN, NaN, '-*')]; 61 | end 62 | hold(ax, 'off'); 63 | else 64 | % 3D surface and 3D path plot 65 | obj.FuncPlot = surf(ax, [], [], []); 66 | alpha(obj.FuncPlot, 0.5); 67 | hold(ax, 'on'); 68 | for i=1:pathCount 69 | obj.PathPlots = [obj.PathPlots, plot3(ax, NaN, NaN, NaN, '-*')]; 70 | end 71 | hold(ax, 'off'); 72 | end 73 | end 74 | 75 | function moveOneStep(obj) 76 | if ~isempty(obj.func) && obj.readyUpdate 77 | if isscalar(obj.PathPlots) 78 | obj.doneGraDes = obj.updateApathPlot(obj.PathPlots, obj.alpha); 79 | else 80 | numPaths = length(obj.alpha); 81 | for i=1:numPaths 82 | if ~obj.doneGraDes(i) 83 | obj.doneGraDes(i) = obj.updateApathPlot(obj.PathPlots(i), obj.alpha(i)); 84 | end 85 | end 86 | end 87 | % update animation gif if necessary 88 | obj.updateGIF(); 89 | else 90 | % Not ready to update yet 91 | end 92 | end 93 | 94 | function initApathPlot(obj, plot) 95 | xStart = obj.startPoint(1); 96 | yStart = obj.startPoint(2); 97 | zStart = obj.func(xStart, yStart); 98 | plot.XData = xStart; 99 | plot.YData = yStart; 100 | if ~obj.drawContour 101 | plot.ZData = zStart; 102 | end 103 | end 104 | 105 | function done = updateApathPlot(obj, plot, alpha) 106 | done = false; 107 | xStart = plot.XData(end); 108 | yStart = plot.YData(end); 109 | zStart = obj.func(xStart, yStart); 110 | xEnd = double(xStart - obj.getXpartial(xStart, yStart, alpha)); 111 | yEnd = double(yStart - obj.getYpartial(xStart, yStart, alpha)); 112 | zEnd = double(obj.func(xEnd, yEnd)); 113 | plot.XData = [plot.XData xEnd]; 114 | plot.YData = [plot.YData yEnd]; 115 | if ~obj.drawContour 116 | plot.ZData = [plot.ZData zEnd]; 117 | end 118 | 119 | if obj.checkStop(xStart, xEnd, yStart, yEnd, zStart, zEnd) 120 | done = true; 121 | end 122 | end 123 | 124 | function initGIF(obj) 125 | if ~isempty(obj.outfile) 126 | [img, map] = rgb2ind(frame2im( getframe(gcf)),256); 127 | imwrite(img,map,obj.outfile,'gif','DelayTime',0.5); 128 | end 129 | end 130 | 131 | function updateGIF(obj) 132 | pauseInSec = 1/obj.stepsPerSecond; 133 | if ~isempty(obj.outfile) 134 | [img, map] = rgb2ind(frame2im( getframe(gcf)),256); 135 | imwrite(img,map,obj.outfile,'gif','writemode', 'append','delaytime',pauseInSec); 136 | else 137 | pause(pauseInSec); 138 | end 139 | end 140 | 141 | function showResult(obj, i) 142 | pauseInSec = 1/obj.stepsPerSecond; 143 | if obj.showAnnotation 144 | if ~isempty(obj.Annot) 145 | if length(obj.PathPlots) == 1 146 | xEnd = obj.PathPlots.XData(end); 147 | yEnd = obj.PathPlots.YData(end); 148 | zEnd = double(obj.func(xEnd, yEnd)); 149 | strDisplay = {['\alpha : ' num2str(obj.alpha)], ... 150 | ['step count: ' num2str(i)], ... 151 | ['Min: (' num2str(xEnd) ', ' num2str(yEnd) ', ' num2str(zEnd) ')']}; 152 | else 153 | strDisplay = {}; 154 | colors = {'red', 'green', 'magenta', 'cyan'}; 155 | numColors = length(colors); 156 | for i=1:length(obj.PathPlots) 157 | color = colors{mod(i-1, numColors)+1}; 158 | xEnd = obj.PathPlots(i).XData(end); 159 | yEnd = obj.PathPlots(i).YData(end); 160 | zEnd = double(obj.func(xEnd, yEnd)); 161 | strDisplay{end+1} = ['\color{' color '}\alpha: ' num2str(obj.alpha(i)) '; min: ' num2str(zEnd)]; %#ok 162 | end 163 | end 164 | obj.Annot.String = strDisplay; 165 | end 166 | 167 | if ~isempty(obj.outfile) 168 | [img, map] = rgb2ind(frame2im( getframe(gcf)),256); 169 | imwrite(img,map,obj.outfile,'gif','writemode', 'append','delaytime',pauseInSec); 170 | end 171 | end 172 | end 173 | % template method design pattern for subclass 174 | function preGraDes(obj) 175 | % no op 176 | end 177 | end 178 | 179 | methods(Access=public) 180 | function agd = animateGraDes() 181 | clf 182 | % set default values. User can overwrite after instantiation 183 | agd.drawContour = false; 184 | agd.stepsPerSecond = 5; 185 | agd.alpha = 0.1; 186 | agd.startPoint = [5 5]; 187 | agd.xrange = -10:1:10; 188 | agd.yrange = -10:1:10; 189 | agd.maxStepCount = 100; 190 | agd.stopThreshold = 1E-10; 191 | agd.showAnnotation = true; 192 | agd.outfile = []; 193 | agd.doneGraDes = false; 194 | agd.Annot = []; 195 | agd.fillContour = false; 196 | end 197 | 198 | function animate(obj) 199 | obj.setupChartContainer(); 200 | obj.initGIF(); 201 | try 202 | obj.func = str2func(['@(x, y)' obj.funcStr]); 203 | symFunc = sym(obj.func); 204 | syms x y 205 | obj.xPartial = diff(symFunc, x); 206 | obj.yPartial = diff(symFunc, y); 207 | catch ME 208 | disp(ME); 209 | return; 210 | end 211 | 212 | 213 | [X, Y] = meshgrid(obj.xrange, obj.yrange); 214 | Z = obj.computeZ(X, Y); 215 | 216 | obj.FuncPlot.XData = X; 217 | obj.FuncPlot.YData = Y; 218 | obj.FuncPlot.ZData = Z; 219 | 220 | if isscalar(obj.PathPlots) 221 | obj.initApathPlot(obj.PathPlots); 222 | else 223 | numPaths = length(obj.alpha); 224 | for i=1:numPaths 225 | obj.initApathPlot(obj.PathPlots(i)); 226 | end 227 | end 228 | 229 | if obj.showAnnotation 230 | dim = [0.05 0.81 0.38 0.13]; 231 | strDisplay = 'Running ...'; 232 | obj.Annot = annotation('textbox', dim, ... 233 | 'String', strDisplay,'BackgroundColor','white', ... 234 | 'FitBoxToText', 'on',... 235 | 'interpreter', 'tex'); 236 | end 237 | obj.preGraDes(); 238 | obj.readyUpdate = true; 239 | for i=0:obj.maxStepCount 240 | obj.moveOneStep(); 241 | if all(obj.doneGraDes) 242 | break; 243 | end 244 | if obj.showAnnotation 245 | obj.Annot.String = ['Running ' num2str(i) '/' num2str(obj.maxStepCount)]; 246 | end 247 | end 248 | 249 | obj.showResult(i); 250 | end 251 | 252 | % Utility functions 253 | function zValue = getYpartial(obj, xIn, yIn, alpha) 254 | syms x y 255 | x = xIn; 256 | y = yIn; 257 | zValue = alpha*subs(obj.yPartial); 258 | end 259 | 260 | function zValue = getXpartial(obj, xIn, yIn, alpha) 261 | syms x y 262 | x = xIn; 263 | y = yIn; 264 | zValue = alpha*subs(obj.xPartial); 265 | end 266 | 267 | function Z = computeZ(obj, X, Y) 268 | sz = size(X); 269 | Z = zeros(sz(1), sz(2)); 270 | 271 | for i=1:sz(1) 272 | for j=1:sz(2) 273 | Z(i, j) = obj.func(X(i, j), Y(i, j)); 274 | end 275 | end 276 | end 277 | 278 | function done = checkStop(obj, xStart, xEnd, yStart, yEnd, zStart, zEnd) 279 | done = false; 280 | dis = (xStart-xEnd)^2+(yStart-yEnd)^2+(zStart-zEnd)^2; 281 | if dis