172 |
--------------------------------------------------------------------------------
/public/assets/graph.js:
--------------------------------------------------------------------------------
1 | var seed = 17;
2 | function random() {
3 | var x = Math.sin(seed++) * 10000;
4 | return x - Math.floor(x);
5 | }
6 |
7 | function generateGraph(svg, graph, linklength, strength) {
8 |
9 | var width = 300;
10 | var height = 200;
11 |
12 | var simulation = d3.forceSimulation()
13 | .force("link", d3.forceLink().id(function(d) { return d.id; })
14 | .strength(2)
15 | .distance(function() {return linklength}))
16 | .force("charge", d3.forceManyBody().strength(-110))
17 | .force("center", d3.forceCenter(width / 2, height / 2))
18 | .force("x",d3.forceX(1000).strength(strength))
19 | .force("y",d3.forceY(1000).strength(strength))
20 | .stop()
21 | var link = svg.append("g")
22 | .attr("class", "links")
23 | .selectAll("line")
24 | .data(graph.links)
25 | .enter().append("line")
26 | .attr("stroke-width", 1)
27 | .attr("stroke","black")
28 |
29 | var node = svg.append("g")
30 | .attr("class", "nodes")
31 |
32 |
33 | var nodedata = node
34 | .selectAll("circle")
35 | .data(graph.nodes)
36 | .enter().append("circle")
37 | .attr("r", 3)
38 | .attr("fill", "black")
39 |
40 | nodedata.append("title")
41 | .text(function(d) { return d.id; });
42 |
43 | simulation
44 | .nodes(graph.nodes)
45 | .on("tick", ticked);
46 |
47 | simulation.force("link")
48 | .links(graph.links);
49 |
50 | for (var i = 0; i < 200; ++i) {
51 | simulation.tick();
52 | }
53 |
54 | function ticked() {
55 | link.attr("x1", function(d) { return d.source.x; })
56 | .attr("y1", function(d) { return d.source.y; })
57 | .attr("x2", function(d) { return d.target.x; })
58 | .attr("y2", function(d) { return d.target.y; });
59 |
60 | nodedata.attr("cx", function(d) { return d.x; })
61 | .attr("cy", function(d) { return d.y; });
62 | }
63 |
64 | var updateColors = function (update) {
65 | node.selectAll("circle")
66 | .data(update)
67 | .attr("fill", function(d,i) { return d})
68 | }
69 |
70 | ticked()
71 |
72 | return updateColors
73 | };
74 |
75 |
76 | function genGrid(svg) {
77 |
78 | var data = {"nodes": [],"links": []}
79 | var id = {}
80 |
81 | var n = 6
82 | var c = 0
83 | for (var i = 0; i < n; i ++) {
84 | for (var j = 0; j < n; j ++) {
85 | data.nodes.push({"id": i + "," + j})
86 | id[i + "," + j] = c
87 | c++
88 | }
89 | }
90 |
91 | var L = zeros2D(c,c)
92 |
93 | for (var i = 0; i < n; i++) {
94 | for (var j = 0; j < n; j++){
95 | if (j < (n-1)) {
96 | data.links.push({"source":i + "," + j, "target": i + "," + (j + 1)})
97 | L[id[i + "," + j]][id[i + "," + (j+1)]] = -1
98 | L[id[i + "," + (j+1)]][id[i + "," + j]] = -1
99 | }
100 | if (i < (n-1)) {
101 | data.links.push({"source":i + "," + j, "target": (i + 1) + "," + j})
102 | L[id[i + "," + j]][id[(i+1) + "," + j]] = -1
103 | L[id[(i+1) + "," + j]][id[i + "," + j]] = -1
104 | }
105 | }
106 | }
107 |
108 | for (var i = 0; i < c; i++) {
109 | L[i][i] = -numeric.sum(L[i]) + ((i == 0) ? 1 : 0)
110 | }
111 |
112 | colorbrewer.Spectral[3]
113 | var divergent = d3.scaleLinear().domain([-0.1,0,0.1]).range(["#fc8d59", "#e6e600", "#99d594"]);
114 |
115 | var E = eigSym(L)
116 |
117 | var update = generateGraph(svg, data,2,0.2)
118 |
119 | var colors = []
120 | for (var i = 0; i < c; i++) {
121 | colors.push(divergent(E.U[34][i]))
122 | }
123 | update(colors)
124 |
125 |
126 | }
127 |
128 |
129 | function genPath(svg) {
130 | var data = {"nodes": [], "links": []}
131 |
132 | var n = 36
133 | var L = zeros2D(n,n)
134 | for (var i = 0; i < n; i ++) {
135 | data.nodes.push({"id": i})
136 | if (i < (n-1)){
137 | data.links.push({"source":i, "target": i+1})
138 | L[i][i+1] = -1
139 | L[i+1][i] = -1
140 | }
141 | }
142 |
143 | for (var i = 0; i < 3; i++){
144 | var s = Math.floor(random()*36)
145 | var t = Math.floor(random()*36)
146 | data.links.push({"source":s, "target": t})
147 | L[s][t] = -1
148 | L[t][s] = -1
149 | }
150 |
151 | for (var i = 0; i < n; i++) {
152 | L[i][i] = -numeric.sum(L[i]) + ((i == 0) ? 1 : 0)
153 | }
154 |
155 | var divergent = d3.scaleLinear().domain([-0.1,0,0.1]).range(["#fc8d59", "#e6e600", "#99d594"]);
156 |
157 | var E = eigSym(L)
158 |
159 | var update = generateGraph(svg, data, 3, 0.43)
160 | var colors = []
161 | for (var i = 0; i < n; i++) {
162 | colors.push(divergent(E.U[34][i]))
163 | }
164 | update(colors)
165 |
166 |
167 | }
168 |
169 |
170 | function genExpander(svg) {
171 | var data = {"nodes": [], "links": []}
172 | var n = 36
173 | var L = zeros2D(n,n)
174 |
175 | for (var i = 0; i < n; i ++) {
176 | data.nodes.push({"id": i})
177 | }
178 |
179 | for (var i = 0; i < 80; i++){
180 | var s = Math.floor(random()*36);
181 | var t = Math.floor(random()*36)
182 | data.links.push({"source":s, "target": t})
183 | L[s][t] = -1
184 | L[t][s] = -1
185 | }
186 |
187 | for (var i = 0; i < n; i++) {
188 | L[i][i] = -numeric.sum(L[i]) + ((i == 0) ? 1 : 0)
189 | }
190 | var divergent = d3.scaleLinear().domain([-0.1,0,0.1]).range(["#fc8d59", "#e6e600", "#99d594"]);
191 |
192 | var E = eigSym(L)
193 | var update = generateGraph(svg, data, 20, 0.2)
194 | var colors = []
195 | for (var i = 0; i < n; i++) {
196 | colors.push(divergent(E.U[34][i]))
197 | }
198 | update(colors)
199 | }
200 |
201 |
--------------------------------------------------------------------------------
/public/assets/images/levelsets1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/images/levelsets1.png
--------------------------------------------------------------------------------
/public/assets/images/levelsets2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/images/levelsets2.png
--------------------------------------------------------------------------------
/public/assets/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
19 |
Hello World
20 |
A description of the article
21 |
22 |
This is the first paragraph of the article.
23 |
We can also cite external publications.
24 |
25 |
26 |
--------------------------------------------------------------------------------
/public/assets/iterates.js:
--------------------------------------------------------------------------------
1 | /*
2 | Make a standard "path of descent" plot which shows iterates
3 | on a 2D optimization landscape
4 |
5 | Takes in : f, the objective function
6 | Name of div where the graphic is rendered
7 | update, which gets passed in the objective
8 | values at every iteration
9 |
10 | Returns : callback `changeParams` to change alpha, beta
11 | */
12 | function genIterDiagram(f, xstar, axis, optMethod, showSolution, showStartingPoint, totalIters) {
13 |
14 | /*
15 | Configurable Parameters
16 | */
17 | var w = 984
18 | var h = 300
19 | var state_beta = 0.0
20 | var state_alpha = 0.001
21 | var num_contours = 15
22 | var onDrag = function() {}
23 | var w0 =[-1.21, 0.853]
24 | var strokeColor = "#ff6600"
25 | var showOptimum = true
26 | var pathWidth = 1.5
27 | var circleRadius = 2
28 | var pointerScale = 1
29 |
30 | function renderIterates(div) {
31 |
32 | // Render the other stuff
33 | var intDiv = div.style("width", w + "px")
34 | .style("height", h + "px")
35 |
36 | // Render Contours
37 | var plotCon = contour_plot.ContourPlot(w,h)
38 | .f(function(x,y) { return f([x,y])[0] })
39 | .drawAxis(false)
40 | .xDomain(axis[0])
41 | .yDomain(axis[1])
42 | .contourCount(num_contours)
43 | .minima([{x:xstar[0], y:xstar[1]}]);
44 |
45 | var elements = plotCon(intDiv);
46 |
47 | var svg = intDiv.append("div")
48 | .append("svg")
49 | .style("position", 'absolute')
50 | .style("left", 0)
51 | .style("top", 0)
52 | .style("width", w + "px")
53 | .style("height", h + "px")
54 | .style("z-index", 2)
55 |
56 | var X = d3.scaleLinear().domain(axis[0]).range([0, w])
57 | var Y = d3.scaleLinear().domain(axis[1]).range([0, h])
58 |
59 | // Rendeer Draggable dot
60 | var circ = svg.append("g") //use xlink:href="cafe-18.svg#svg4619">
61 | .attr("transform", "translate(" + X(w0[0]) + "," + Y(w0[1]) + ")")
62 | .call(d3.drag().on("drag", function() {
63 | var pt = d3.mouse(svg.node())
64 | var x = X.invert(pt[0])
65 | var y = Y.invert(pt[1])
66 | this.setAttribute("transform","translate(" + pt[0] + "," + pt[1] + ")")
67 | w0 = [x,y]
68 | onDrag(w0)
69 | iter(state_alpha, state_beta, w0);
70 | }))
71 |
72 | if (showStartingPoint) {
73 | circ.append("use")
74 | .style("cursor", "pointer")
75 | .attr("xlink:href", "#pointerThingy")
76 | .attr("transform", "scale(" + pointerScale + ")")
77 |
78 | circ.append("text")
79 | .style("cursor", "pointer")
80 | .attr("class", "figtext")
81 | .attr("transform", "translate(20,3)")
82 | .html("Starting Point")
83 | }
84 |
85 | var iterColor = d3.scaleLinear().domain([0, totalIters]).range([strokeColor, strokeColor])
86 |
87 | var update2D = plot2dGen(X, Y, iterColor)
88 | .stroke(strokeColor)
89 | .pathWidth(pathWidth)
90 | .circleRadius(circleRadius)(svg)
91 |
92 |
93 | if (showOptimum) {
94 | // Append x^s var showSolution = falsetar
95 | var pxstar = ringPathGen(7,50,14)([X(xstar[0]), Y(xstar[1])],
96 | [X(xstar[0]), Y(xstar[1]) - 15])
97 | svg.append("circle").attr("cx", X(xstar[0])).attr("cy", Y(xstar[1])).attr("r", 7).attr("stroke","#3f5b75").attr("stroke-width",1).attr("fill","none")
98 | svg.append("path").attr("d", pxstar.d).attr("stroke","#3f5b75").attr("stroke-width",1).attr("fill","none")
99 | svg.append("text")
100 | .attr("class","figtext")
101 | .attr("transform", "translate(" + pxstar.label[0] + "," + (pxstar.label[1]) + ")" )
102 | .html("Optimum")
103 | }
104 |
105 |
106 | if (showSolution) {
107 | var pxsol = ringPathGen(7,43.36,14)([X(0), Y(0)],
108 | [X(0), Y(0) + 20])
109 | var solcirc = svg.append("circle").attr("cx", X(0)).attr("cy", Y(0)).attr("r", 7).attr("stroke",strokeColor).attr("stroke-width",1).attr("fill","none")
110 | var solpath = svg.append("path").attr("d", pxsol.d).attr("stroke",strokeColor).attr("stroke-width",1).attr("fill","none")
111 | var sollabel = svg.append("text")
112 | .attr("class","figtext")
113 | .attr("transform", "translate(" + pxsol.label[0] + "," + (pxsol.label[1]) + ")" )
114 | .html("Solution")
115 | }
116 | function updateSol(x,y) {
117 | if (showSolution) {
118 | var pxsol = ringPathGen(7,50,14)([X(x), Y(y)], [X(x), Y(y) + 15])
119 | solcirc.attr("cx", X(x)).attr("cy", Y(y))
120 | solpath.attr("d", pxsol.d)
121 | sollabel.attr("transform", "translate(" + pxsol.label[0] + "," + (pxsol.label[1]) + ")" )
122 | }
123 | }
124 |
125 | // svg.append("rect")
126 | // .attr("width", 50)
127 | // .attr("height",14)
128 | // .attr("x", pxstar.label[0] )
129 | // .attr("y", pxstar.label[1])
130 |
131 | function iter(alpha, beta, w0) {
132 |
133 | // Update Internal state of alpha and beta
134 | state_alpha = alpha
135 | state_beta = beta
136 |
137 | // Generate iterates
138 | if (optMethod != null) {
139 | var OW = optMethod(f, w0, alpha, totalIters)
140 | var W = OW[1]
141 |
142 | update2D(W)
143 |
144 | updateSol(OW[1][OW[1].length - 1][0], OW[1][OW[1].length - 1][1])
145 | circ.attr("transform", "translate(" + X(w0[0]) + "," + Y(w0[1]) + ")" )
146 | circ.moveToFront()
147 | }
148 |
149 | }
150 |
151 | if (optMethod != null) {
152 | iter(state_alpha, state_beta, w0);
153 | }
154 |
155 | return { control:iter,
156 | w0:function() { return w0 },
157 | alpha:function() { return state_alpha },
158 | beta:function() {return state_beta} }
159 |
160 | }
161 |
162 | renderIterates.showStartingPoint = function(_) {
163 | showStartingPoint = _; return renderIterates;
164 | }
165 |
166 | renderIterates.pointerScale = function(_) {
167 | pointerScale = _; return renderIterates;
168 | }
169 |
170 | renderIterates.circleRadius = function(_) {
171 | circleRadius = _; return renderIterates;
172 | }
173 |
174 | renderIterates.pathWidth = function(_) {
175 | pathWidth = _; return renderIterates;
176 | }
177 |
178 | renderIterates.showSolution = function(_) {
179 | showSolution = _; return renderIterates;
180 | }
181 |
182 | renderIterates.showOptimum = function(_) {
183 | showOptimum = _; return renderIterates;
184 | }
185 |
186 | renderIterates.strokeColor = function(_) {
187 | strokeColor = _; return renderIterates;
188 | }
189 |
190 | renderIterates.width = function (_) {
191 | w = _; return renderIterates;
192 | }
193 |
194 | renderIterates.height = function (_) {
195 | h = _; return renderIterates;
196 | }
197 |
198 | renderIterates.iters = function (_) {
199 | totalIters = _; return renderIterates;
200 | }
201 |
202 | renderIterates.drag = function (_) {
203 | onDrag = _; return renderIterates;
204 | }
205 |
206 | renderIterates.init = function (_) {
207 | w0 = _; return renderIterates;
208 | }
209 |
210 | renderIterates.alpha = function (_) {
211 | state_alpha = _; return renderIterates;
212 | }
213 |
214 | renderIterates.beta = function (_) {
215 | state_beta = _; return renderIterates;
216 | }
217 |
218 | return renderIterates
219 |
220 | }
221 |
--------------------------------------------------------------------------------
/public/assets/lib/auto-render.min.js:
--------------------------------------------------------------------------------
1 | (function(e){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=e()}else if(typeof define==="function"&&define.amd){define([],e)}else{var t;if(typeof window!=="undefined"){t=window}else if(typeof global!=="undefined"){t=global}else if(typeof self!=="undefined"){t=self}else{t=this}t.renderMathInElement=e()}})(function(){var e,t,r;return function n(e,t,r){function a(o,l){if(!t[o]){if(!e[o]){var f=typeof require=="function"&&require;if(!l&&f)return f(o,!0);if(i)return i(o,!0);var d=new Error("Cannot find module '"+o+"'");throw d.code="MODULE_NOT_FOUND",d}var s=t[o]={exports:{}};e[o][0].call(s.exports,function(t){var r=e[o][1][t];return a(r?r:t)},s,s.exports,n,e,t,r)}return t[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) return;
36 | if(abs(dp0) < epsMin) return v;
37 | var n = opt.maxTry || 25;
38 | function zoom(low,high){
39 | if(low.f === undefined) low.f = f(low.x);
40 | if(high.f === undefined) high.f = f(high.x);
41 | while(true){
42 | var nv = {};
43 | var a = nv.a = 0.5*(low.a+high.a);
44 | nv.s = mul(nv.a,d);
45 | nv.x = add(v.x,nv.s);
46 | var p = nv.f = f(nv.x);
47 | if(!n--) return lineSearchSimple(v,d);
48 | if(p > p0+c1*a*dp0 || p >= low.f){
49 | high = nv;
50 | }else{
51 | nv.df = df(nv.x);
52 | var dp = nv.dp = sum(mul(nv.df,d));
53 | if(abs(dp) <= -c2*dp0) return nv;
54 | if(dp*(high.a-low.a) >= 0) high = low;
55 | low = nv;
56 | }
57 | }
58 | }
59 | var nv = {a:1};
60 | var ov = {x:v.x,a:0};
61 | var op;
62 | while(true){
63 | nv.s = mul(nv.a,d);
64 | nv.x = add(v.x,nv.s);
65 | var a = nv.a;
66 | var p = nv.f = f(nv.x);
67 | if(p > p0+c1*a*dp0 || (op !== undefined && p > op)) return zoom(ov,nv);
68 | nv.df = df(nv.x);
69 | var dp = nv.dp = sum(mul(nv.df,d));
70 | if(abs(dp) <= -c2*dp0) return nv;
71 | if(dp >= 0) return zoom(nv,ov);
72 | ov.x = nv.x;
73 | ov.a = nv.a;
74 | ov.f = nv.f;
75 | ov.df = nv.df;
76 | ov.s = nv.s;
77 | op = p;
78 | nv.a = 0.5*(a+max);
79 | if(!n--) return lineSearchSimple(v,d);
80 | }
81 | }
82 | function lineSearchSimple(v,d){
83 | var p0 = v.f;
84 | var dp0 = sum(mul(v.df,d));
85 | if(abs(dp0) < epsMin) return v;
86 | var n = opt.maxTry || 25;
87 | var nv = {a:dp0>0?-1:1};
88 | while(true){
89 | nv.s = mul(nv.a,d);
90 | nv.x = add(v.x,nv.s);
91 | var a = nv.a;
92 | var p = nv.f = f(nv.x);
93 | if(p < p0+c1*a*dp0){
94 | nv.df = df(nv.x);
95 | return nv;
96 | }
97 | nv.a *= 0.5;
98 | if(!n--) throw "too much step, during line search";
99 | }
100 | }
101 |
102 | for(var i=0;i opt.maxNormDir) d = mul(d,opt.maxNormDir/normDir);
107 | }
108 |
109 | W.push(v.x); Obj.push(v.f);
110 | var og = v.df;
111 | var nv = lineSearch(v,d); // compute step length
112 | if(nv === undefined){ // SemiPositiveness lost
113 | B = numeric.identity(guess.length);
114 | continue;
115 | }
116 | if(nv == v) return [Obj, W]; // max precision
117 | v = nv;
118 | if(norm2(v.df) < eps) return [Obj, W];
119 | /* start: refresh Jacobian */
120 | var y = sub(v.df,og);
121 | var vs = trsp([v.s]);
122 | var ts = [v.s];
123 | var vy = trsp([y]);
124 | var ty = [y];
125 | subeq(B,mul(1/dot(ts,dot(B,vs)),dot(B,dot(vs,dot(ts,B)))));
126 | addeq(B,mul(1/dot(ty,vs),dot(vy,ty)));
127 | /* end: refresh Jacobian */
128 | }
129 | debugger;
130 | return [Obj, W]
131 |
132 | }
133 |
134 | function runBFGS2(func, w0, alpha, totalIters) {
135 | function f1(w){
136 | return func(w)[0]
137 | }
138 | function df1(w) {
139 | return func(w)[1]
140 | }
141 | return _bfgs(w0, {f:f1, df: df1}, totalIters, 10e-16)
142 | }
143 | //
144 | //
145 | // globalScope.bfgs = bfgs;
146 | // globalScobe.runBFGS2 = runBFGS2;
147 | // }).call(this);
148 |
--------------------------------------------------------------------------------
/public/assets/lib/contour_plot.js:
--------------------------------------------------------------------------------
1 | (function (global, factory) {
2 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3 | typeof define === 'function' && define.amd ? define('contour_plot', ['exports'], factory) :
4 | factory((global.contour_plot = {}));
5 | }(this, function (exports) { 'use strict';
6 |
7 | /** finds the zeros of a function, given two starting points (which must
8 | * have opposite signs */
9 | function bisect(f, a, b, parameters) {
10 | parameters = parameters || {};
11 | var maxIterations = parameters.maxIterations || 100,
12 | tolerance = parameters.tolerance || 1e-10,
13 | fA = f(a),
14 | fB = f(b),
15 | delta = b - a;
16 |
17 | if (fA * fB > 0) {
18 | throw "Initial bisect points must have opposite signs";
19 | }
20 |
21 | if (fA === 0) return a;
22 | if (fB === 0) return b;
23 |
24 | for (var i = 0; i < maxIterations; ++i) {
25 | delta /= 2;
26 | var mid = a + delta,
27 | fMid = f(mid);
28 |
29 | if (fMid * fA >= 0) {
30 | a = mid;
31 | }
32 |
33 | if ((Math.abs(delta) < tolerance) || (fMid === 0)) {
34 | return mid;
35 | }
36 | }
37 | return a + delta;
38 | }
39 |
40 | // This file is modified from the d3.geom.contour
41 | // plugin found here https://github.com/d3/d3-plugins/tree/master/geom/contour
42 |
43 | /*
44 | Copyright (c) 2012-2015, Michael Bostock
45 | All rights reserved.
46 |
47 | Redistribution and use in source and binary forms, with or without
48 | modification, are permitted provided that the following conditions are met:
49 |
50 | * Redistributions of source code must retain the above copyright notice, this
51 | list of conditions and the following disclaimer.
52 |
53 | * Redistributions in binary form must reproduce the above copyright notice,
54 | this list of conditions and the following disclaimer in the documentation
55 | and/or other materials provided with the distribution.
56 |
57 | * The name Michael Bostock may not be used to endorse or promote products
58 | derived from this software without specific prior written permission.
59 |
60 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
61 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
62 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
63 | DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
64 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
65 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
66 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
67 | OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
68 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
69 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
70 | */
71 |
72 | function d3_contour(grid, start) {
73 | var s = start || d3_geom_contourStart(grid), // starting point
74 | c = [], // contour polygon
75 | x = s[0], // current x position
76 | y = s[1], // current y position
77 | dx = 0, // next x direction
78 | dy = 0, // next y direction
79 | pdx = NaN, // previous x direction
80 | pdy = NaN, // previous y direction
81 | i = 0;
82 |
83 | do {
84 | // determine marching squares index
85 | i = 0;
86 | if (grid(x-1, y-1)) i += 1;
87 | if (grid(x, y-1)) i += 2;
88 | if (grid(x-1, y )) i += 4;
89 | if (grid(x, y )) i += 8;
90 |
91 | // determine next direction
92 | if (i === 6) {
93 | dx = pdy === -1 ? -1 : 1;
94 | dy = 0;
95 | } else if (i === 9) {
96 | dx = 0;
97 | dy = pdx === 1 ? -1 : 1;
98 | } else {
99 | dx = d3_geom_contourDx[i];
100 | dy = d3_geom_contourDy[i];
101 | }
102 |
103 | // update contour polygon
104 | if (dx != pdx && dy != pdy) {
105 | c.push([x, y]);
106 | pdx = dx;
107 | pdy = dy;
108 | } else {
109 | c.push([x, y]);
110 | }
111 |
112 | x += dx;
113 | y += dy;
114 | } while (s[0] != x || s[1] != y);
115 |
116 | return c;
117 | }
118 |
119 | // lookup tables for marching directions
120 | var d3_geom_contourDx = [1, 0, 1, 1,-1, 0,-1, 1,0, 0,0,0,-1, 0,-1,NaN];
121 | var d3_geom_contourDy = [0,-1, 0, 0, 0,-1, 0, 0,1,-1,1,1, 0,-1, 0,NaN];
122 | function d3_geom_contourStart(grid) {
123 | var x = 0,
124 | y = 0;
125 |
126 | // search for a starting point; begin at origin
127 | // and proceed along outward-expanding diagonals
128 | while (true) {
129 | if (grid(x,y)) {
130 | return [x,y];
131 | }
132 | if (x === 0) {
133 | x = y + 1;
134 | y = 0;
135 | } else {
136 | x = x - 1;
137 | y = y + 1;
138 | }
139 | }
140 | }
141 |
142 | function isoline(f, value, xScale, yScale) {
143 | var xRange = xScale.range(), yRange = yScale.range();
144 | return function(x, y) {
145 | if ((x < xRange[0]) || (x > xRange[1]) ||
146 | (y < yRange[0]) || (y > yRange[1])) return false;
147 | return f(xScale.invert(x), yScale.invert(y)) < value;
148 | };
149 | }
150 |
151 | function smoothPoints(f, points, level, xScale, yScale) {
152 | var xRange = xScale.range(), yRange = yScale.range();
153 | var ySmooth = function(y) {
154 | return f(xScale.invert(x), yScale.invert(y)) - level;
155 | };
156 | var xSmooth = function(x) {
157 | return f(xScale.invert(x), yScale.invert(y)) - level;
158 | };
159 | for (var k = 0; k < points.length; ++k) {
160 | var point = points[k],
161 | x = point[0], y = point[1];
162 |
163 | if ((x <= xRange[0]) || (x >= xRange[1]) ||
164 | (y <= yRange[0]) || (y >= yRange[1])) continue;
165 |
166 | var currentSmooth = ySmooth(y);
167 |
168 | var p = {'maxIterations' : 9};
169 | for (var delta = 0.5; delta <= 3; delta += 0.5) {
170 | if (ySmooth(y - delta) * currentSmooth < 0) {
171 | y = bisect(ySmooth, y, y - delta, p);
172 | } else if (xSmooth(x - delta) * currentSmooth < 0) {
173 | x = bisect(xSmooth, x, x - delta, p);
174 | } else if (ySmooth(y + delta) * currentSmooth < 0) {
175 | y = bisect(ySmooth, y, y + delta, p);
176 | } else if (xSmooth(x + delta) * currentSmooth < 0) {
177 | x = bisect(xSmooth, x, x + delta, p);
178 | } else {
179 | continue;
180 | }
181 | break;
182 | }
183 |
184 | point[0] = x;
185 | point[1] = y;
186 | }
187 | }
188 |
189 | function getLogLevels(f, xScale, yScale, count) {
190 | var xRange = xScale.range(), yRange = yScale.range();
191 |
192 | // figure out min/max values by sampling pointson a grid
193 | var maxValue, minValue, value;
194 | maxValue = minValue = f(xScale.invert(xRange[0]), yScale.invert(yRange[0]));
195 | for (var y = yRange[0]; y < yRange[1]+1; ++y) {
196 | for (var x = xRange[0]; x < xRange[1]+1; ++x) {
197 | value = f(xScale.invert(x),yScale.invert(y));
198 | minValue = Math.min(value, minValue);
199 | maxValue = Math.max(value, maxValue);
200 | }
201 | }
202 |
203 | // lets get contour lines on a log scale, keeping
204 | // values on an integer scale (if possible)
205 | var levels = [];
206 | var logRange = Math.log(maxValue - Math.floor(minValue));
207 | var base = Math.ceil(Math.exp(logRange / (count))),
208 | upper = Math.pow(base, Math.ceil(logRange / Math.log(base)));
209 |
210 | for (var i = 0; i < count; ++i) {
211 | var current = Math.floor(minValue) + upper;
212 | if (current < minValue) {
213 | break;
214 | }
215 | levels.push(current);
216 | upper /= base;
217 | }
218 |
219 | return levels;
220 | }
221 |
222 | function getStartingPoint(lineFunc, x, y) {
223 | x = Math.floor(x);
224 | y = Math.floor(y);
225 | var j = 0;
226 | while (true) {
227 | j += 1;
228 | if (!lineFunc(x+j, y)) {
229 | return [x+j, y];
230 | }
231 | if (!lineFunc(x, y+j)) {
232 | return [x, y+j];
233 | }
234 | }
235 | }
236 |
237 | function getContours(f, xScale, yScale, count, minima) {
238 | // figure out even distribution in log space of values
239 | var levels = getLogLevels(f, xScale, yScale, count);
240 |
241 | // use marching squares algo from d3.geom.contour to build up a series of paths
242 | var ret = [];
243 | for (var i = 0; i < levels.length; ++i) {
244 | var level = levels[i];
245 | var lineFunc = isoline(f, level, xScale, yScale);
246 |
247 | var points= [];
248 | if (minima) {
249 | var initialPoints = [];
250 | for (var m = 0; m < minima.length; ++m) {
251 | var initial = getStartingPoint(lineFunc, xScale(minima[m].x), yScale(minima[m].y));
252 | var current = d3_contour(lineFunc, initial);
253 |
254 | // don't add points if already seen
255 | var duplicate = false;
256 | for (var j = 0 ; j < current.length; ++j) {
257 | var point = current[j];
258 | for (var k = 0; k < initialPoints.length; ++k) {
259 | var other = initialPoints[k];
260 | if ((point[0] == other[0]) &&
261 | (point[1] == other[1])) {
262 | duplicate = true;
263 | break;
264 | }
265 | }
266 | if (duplicate) break;
267 | }
268 | if (duplicate) continue;
269 |
270 | initialPoints.push(initial);
271 |
272 | smoothPoints(f, current, level, xScale, yScale);
273 | if (points.length) points.push(null);
274 | points = points.concat(current);
275 | }
276 | } else {
277 | points = d3_contour(lineFunc);
278 | smoothPoints(f, points, level, xScale, yScale);
279 |
280 | }
281 |
282 | ret.push(points);
283 | }
284 |
285 | // return the contours
286 | return {'paths': ret, 'levels': levels};
287 | }
288 |
289 | function ContourPlot(width, height) {
290 |
291 | var drawAxis = false,
292 | f = function (x, y) { return (1 - x) * (1 - x) + 100 * (y - x * x) * ( y - x * x); },
293 | yDomain = [3, -3],
294 | xDomain = [-2, 2],
295 | minima = null,
296 | contourCount = 14,
297 | colourScale = d3.scaleLinear().domain([1, contourCount/3, contourCount-1]).range(["rgb(240,244,246)", "rgb(217,225,232)", "#aec0ce"]),
298 | colourScaleBorder = d3.scaleLinear().domain([0, contourCount]).range(["lightgray", "darkgray"]),
299 | aspect_ratio = 0.4;
300 |
301 | // todo: resolution independent (sample say 200x200)
302 | // todo: handle function with multiple local minima
303 |
304 | function chart(selection) {
305 | var padding = (drawAxis) ? 24 : 0,
306 | yScale = d3.scaleLinear()
307 | .range([padding, height - padding])
308 | .domain(yDomain),
309 |
310 | xScale = d3.scaleLinear()
311 | .range([padding, width - padding])
312 | .domain(xDomain);
313 |
314 | // create tooltip if doesn't exist
315 | d3.select("body").selectAll(".contour_tooltip").data([0]).enter()
316 | .append("div")
317 | .attr("class", "contour_tooltip")
318 | .style("font-size", "12px")
319 | .style("position", "absolute")
320 | .style("text-align", "center")
321 | .style("width", "128px")
322 | .style("height", "32px")
323 | .style("background", "#333")
324 | .style("color", "#ddd")
325 | .style("padding", "0px")
326 | .style("border", "0px")
327 | .style("border-radius", "8px")
328 | .style("opacity", "0");
329 |
330 | var tooltip = d3.selectAll(".contour_tooltip");
331 |
332 | // create the svg element if it doesn't already exist
333 | selection.selectAll("svg").data([0]).enter().append("svg");
334 | var svg = selection.selectAll("svg").data([0]);
335 |
336 | svg.attr("width", width)
337 | .attr("height", height)
338 |
339 | var contours = getContours(f, xScale, yScale, contourCount, minima);
340 | var paths = contours.paths,
341 | levels = contours.levels;
342 |
343 | var line = d3.line()
344 | .x(function(d) { return d[0]; })
345 | .y(function(d) { return d[1]; })
346 | .curve(d3.curveLinearClosed)
347 | .defined(function(d) { return d; });
348 |
349 | var pathGroup = svg.append("g");
350 |
351 | pathGroup.selectAll("path").data(paths).enter()
352 | .append("path")
353 | .attr("d", line)
354 | .style("fill", function(d, i) { return colourScale(i); })
355 | .style("stroke-width", 0.8)
356 | .style("stroke", "#225577")
357 | .style("stroke-opacity","0.2")
358 | // .attr("transform", "translate(4,4)")
359 | .on("mouseover", function() {
360 | //d3.select(this).style("stroke-width", "4");
361 | })
362 | .on("mouseout", function() {
363 | //d3.select(this).style("stroke-width", "1.5");
364 | });
365 |
366 | // draw axii
367 | if (drawAxis) {
368 | var xAxis = d3.axisBottom().scale(xScale),
369 | yAxis = d3.axisLeft().scale(yScale);
370 |
371 | svg.append("g")
372 | .attr("class", "axis")
373 | .attr("transform", "translate(0," + (height - 1.0 * padding) + ")")
374 | .call(xAxis);
375 |
376 | svg.append("g")
377 | .attr("class", "axis")
378 | .attr("transform", "translate(" + (padding) + ",0)")
379 | .call(yAxis);
380 | }
381 |
382 | return {'xScale' : xScale, 'yScale' : yScale, 'svg' : svg};
383 | }
384 | chart.drawAxis = function(_) {
385 | if (!arguments.length) return drawAxis;
386 | drawAxis = _;
387 | return chart;
388 | };
389 |
390 | chart.xDomain = function(_) {
391 | if (!arguments.length) return xDomain;
392 | xDomain = _;
393 | return chart;
394 | };
395 |
396 | chart.yDomain = function(_) {
397 | if (!arguments.length) return yDomain;
398 | yDomain = _;
399 | return chart;
400 | };
401 |
402 | chart.colourScale = function(_) {
403 | if (!arguments.length) return colourScale;
404 | colourScale = _;
405 | return chart;
406 | };
407 |
408 | chart.contourCount = function(_) {
409 | if (!arguments.length) return contourCount;
410 | contourCount = _;
411 | return chart;
412 | };
413 |
414 | chart.minima = function(_) {
415 | if (!arguments.length) return minima;
416 | minima = _;
417 | return chart;
418 | };
419 |
420 | chart.f = function(_) {
421 | if (!arguments.length) return f;
422 | f = _;
423 | return chart;
424 | };
425 |
426 | return chart;
427 | }
428 |
429 | var version = "0.0.1";
430 |
431 | exports.version = version;
432 | exports.isoline = isoline;
433 | exports.smoothPoints = smoothPoints;
434 | exports.getLogLevels = getLogLevels;
435 | exports.getContours = getContours;
436 | exports.ContourPlot = ContourPlot;
437 |
438 | }));
439 |
--------------------------------------------------------------------------------
/public/assets/lib/contrib/auto-render.min.js:
--------------------------------------------------------------------------------
1 | (function(e){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=e()}else if(typeof define==="function"&&define.amd){define([],e)}else{var t;if(typeof window!=="undefined"){t=window}else if(typeof global!=="undefined"){t=global}else if(typeof self!=="undefined"){t=self}else{t=this}t.renderMathInElement=e()}})(function(){var e,t,r;return function n(e,t,r){function a(o,l){if(!t[o]){if(!e[o]){var f=typeof require=="function"&&require;if(!l&&f)return f(o,!0);if(i)return i(o,!0);var d=new Error("Cannot find module '"+o+"'");throw d.code="MODULE_NOT_FOUND",d}var s=t[o]={exports:{}};e[o][0].call(s.exports,function(t){var r=e[o][1][t];return a(r?r:t)},s,s.exports,n,e,t,r)}return t[o].exports}var i=typeof require=="function"&&require;for(var o=0;o px) {
88 | // East
89 | if (y > py) return "SE";
90 | if (y < -py) return "NE";
91 | if (x > r) return "E";
92 | return null;
93 | }
94 | else if (x < -px) {
95 | // West
96 | if (y > py) return "SW";
97 | if (y < -py) return "NW";
98 | if (x < -r) return "W";
99 | return null;
100 | }
101 | else {
102 | // Center
103 | if (y > r) return "S";
104 | if (y < -r) return "N";
105 | }
106 | }
107 | }
108 |
109 | function dragmoveCenter(d) {
110 | var gRingNote = d3.select(this.parentNode.parentNode);
111 |
112 | d.cx += d3.event.x;
113 | d.cy += d3.event.y;
114 |
115 | gRingNote
116 | .attr("transform", function(d) {
117 | return "translate(" + d.cx + "," + d.cy + ")";
118 | });
119 | }
120 |
121 | function dragmoveRadius(d) {
122 | var gRingNote = d3.select(this.parentNode.parentNode),
123 | gAnnotation = gRingNote.select(".annotation"),
124 | circle = gAnnotation.select("circle"),
125 | line = gAnnotation.select("path"),
126 | text = gAnnotation.select("text"),
127 | radius = d3.select(this);
128 |
129 | d.r += d3.event.dx;
130 |
131 | circle.attr("r", function(d) { return d.r; });
132 | radius.attr("cx", function(d) { return d.r; });
133 | line.call(updateLine);
134 | text.call(updateText);
135 | }
136 |
137 | function dragmoveText(d) {
138 | var gAnnotation = d3.select(this.parentNode),
139 | line = gAnnotation.select("path"),
140 | text = d3.select(this);
141 |
142 | d.textOffset[0] += d3.event.dx;
143 | d.textOffset[1] += d3.event.dy;
144 |
145 | text.call(updateText);
146 | line.call(updateLine);
147 | }
148 |
149 | function updateLine(selection) {
150 | return selection.attr("d", function(d) {
151 | var x = d.textOffset[0],
152 | y = d.textOffset[1],
153 | lineData = getLineData(x, y, d.r);
154 | return path(lineData);
155 | });
156 | }
157 |
158 | function getLineData(x, y, r) {
159 | var region = getRegion(x, y, r);
160 |
161 | if (region == null) {
162 | // No line if text is inside the circle
163 | return [];
164 | }
165 | else {
166 | // Cardinal directions
167 | if (region == "N") return [[0, -r], [0, y]];
168 | if (region == "E") return [[r, 0], [x, 0]];
169 | if (region == "S") return [[0, r], [0, y]];
170 | if (region == "W") return [[-r, 0],[x, 0]];
171 |
172 | var d0 = r * Math.cos(Math.PI/4),
173 | d1 = Math.min(Math.abs(x), Math.abs(y)) - d0;
174 |
175 | // Intermediate directions
176 | if (region == "NE") return [[ d0, -d0], [ d0 + d1, -d0 - d1], [x, y]];
177 | if (region == "SE") return [[ d0, d0], [ d0 + d1, d0 + d1], [x, y]];
178 | if (region == "SW") return [[-d0, d0], [-d0 - d1, d0 + d1], [x, y]];
179 | if (region == "NW") return [[-d0, -d0], [-d0 - d1, -d0 - d1], [x, y]];
180 | }
181 | }
182 |
183 | function updateText(selection) {
184 | return selection.each(function(d) {
185 | var x = d.textOffset[0],
186 | y = d.textOffset[1],
187 | region = getRegion(x, y, d.r),
188 | textCoords = getTextCoords(x, y, region);
189 |
190 | d3.select(this)
191 | .attr("x", textCoords.x)
192 | .attr("y", textCoords.y)
193 | .text(d.text)
194 | .each(function(d) {
195 | var x = d.textOffset[0],
196 | y = d.textOffset[1],
197 | textAnchor = getTextAnchor(x, y, region);
198 |
199 | var dx = textAnchor == "start" ? "0.33em" :
200 | textAnchor == "end" ? "-0.33em" : "0";
201 |
202 | var dy = textAnchor !== "middle" ? ".33em" :
203 | ["NW", "N", "NE"].indexOf(region) !== -1 ? "-.33em" : "1em";
204 |
205 | var orientation = textAnchor !== "middle" ? undefined :
206 | ["NW", "N", "NE"].indexOf(region) !== -1 ? "bottom" : "top";
207 |
208 | d3.select(this)
209 | .style("text-anchor", textAnchor)
210 | .attr("dx", dx)
211 | .attr("dy", dy)
212 | .call(wrapText, d.textWidth || 960, orientation);
213 | });
214 | });
215 | }
216 |
217 | function getTextCoords(x, y, region) {
218 | if (region == "N") return { x: 0, y: y };
219 | if (region == "E") return { x: x, y: 0 };
220 | if (region == "S") return { x: 0, y: y };
221 | if (region == "W") return { x: x, y: 0 };
222 | return { x: x, y: y };
223 | }
224 |
225 | function getTextAnchor(x, y, region) {
226 | if (region == null) {
227 | return "middle";
228 | }
229 | else {
230 | // Cardinal directions
231 | if (region == "N") return "middle";
232 | if (region == "E") return "start";
233 | if (region == "S") return "middle";
234 | if (region == "W") return "end";
235 |
236 | var xLonger = Math.abs(x) > Math.abs(y);
237 |
238 | // Intermediate directions`
239 | if (region == "NE") return xLonger ? "start" : "middle";
240 | if (region == "SE") return xLonger ? "start" : "middle";
241 | if (region == "SW") return xLonger ? "end" : "middle";
242 | if (region == "NW") return xLonger ? "end" : "middle";
243 | }
244 | }
245 |
246 | // Adapted from: https://bl.ocks.org/mbostock/7555321
247 | function wrapText(text, width, orientation) {
248 | text.each(function(d) {
249 | var text = d3.select(this),
250 | words = text.text().split(/\s+/).reverse(),
251 | word,
252 | line = [],
253 | lineNumber = 1,
254 | lineHeight = 1.1, // ems
255 | x = text.attr("x"),
256 | dx = text.attr("dx"),
257 | tspan = text.text(null).append("tspan").attr("x", x).attr("dx", dx);
258 | while (word = words.pop()) {
259 | line.push(word);
260 | tspan.text(line.join(" "));
261 | if (tspan.node().getComputedTextLength() > width) {
262 | line.pop();
263 | tspan.text(line.join(" "));
264 | line = [word];
265 | tspan = text.append("tspan")
266 | .attr("x", x)
267 | .attr("dx", dx)
268 | .attr("dy", lineHeight + "em")
269 | .text(word);
270 | lineNumber++;
271 | }
272 | }
273 |
274 | var dy;
275 | if (orientation == "bottom") {
276 | dy = -lineHeight * (lineNumber-1) - .33;
277 | }
278 | else if (orientation == "top") {
279 | dy = 1;
280 | }
281 | else {
282 | dy = -lineHeight * ((lineNumber-1) / 2) + .33;
283 | }
284 | text.attr("dy", dy + "em");
285 |
286 | });
287 | }
288 |
289 | function styleControl(selection) {
290 | selection
291 | .attr("r", controlRadius)
292 | .style("fill-opacity", "0")
293 | .style("stroke", "black")
294 | .style("stroke-dasharray", "3, 3")
295 | .style("cursor", "move");
296 | }
297 |
298 | return draw;
299 | };
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_AMS-Regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_AMS-Regular.eot
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_AMS-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_AMS-Regular.ttf
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_AMS-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_AMS-Regular.woff
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_AMS-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_AMS-Regular.woff2
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Caligraphic-Bold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Caligraphic-Bold.eot
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Caligraphic-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Caligraphic-Bold.ttf
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Caligraphic-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Caligraphic-Bold.woff
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Caligraphic-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Caligraphic-Bold.woff2
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Caligraphic-Regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Caligraphic-Regular.eot
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Caligraphic-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Caligraphic-Regular.ttf
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Caligraphic-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Caligraphic-Regular.woff
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Caligraphic-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Caligraphic-Regular.woff2
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Fraktur-Bold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Fraktur-Bold.eot
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Fraktur-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Fraktur-Bold.ttf
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Fraktur-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Fraktur-Bold.woff
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Fraktur-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Fraktur-Bold.woff2
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Fraktur-Regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Fraktur-Regular.eot
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Fraktur-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Fraktur-Regular.ttf
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Fraktur-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Fraktur-Regular.woff
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Fraktur-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Fraktur-Regular.woff2
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Main-Bold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Main-Bold.eot
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Main-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Main-Bold.ttf
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Main-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Main-Bold.woff
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Main-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Main-Bold.woff2
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Main-Italic.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Main-Italic.eot
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Main-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Main-Italic.ttf
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Main-Italic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Main-Italic.woff
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Main-Italic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Main-Italic.woff2
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Main-Regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Main-Regular.eot
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Main-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Main-Regular.ttf
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Main-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Main-Regular.woff
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Main-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Main-Regular.woff2
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Math-BoldItalic.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Math-BoldItalic.eot
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Math-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Math-BoldItalic.ttf
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Math-BoldItalic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Math-BoldItalic.woff
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Math-BoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Math-BoldItalic.woff2
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Math-Italic.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Math-Italic.eot
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Math-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Math-Italic.ttf
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Math-Italic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Math-Italic.woff
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Math-Italic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Math-Italic.woff2
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Math-Regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Math-Regular.eot
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Math-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Math-Regular.ttf
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Math-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Math-Regular.woff
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Math-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Math-Regular.woff2
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_SansSerif-Bold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_SansSerif-Bold.eot
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_SansSerif-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_SansSerif-Bold.ttf
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_SansSerif-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_SansSerif-Bold.woff
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_SansSerif-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_SansSerif-Bold.woff2
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_SansSerif-Italic.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_SansSerif-Italic.eot
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_SansSerif-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_SansSerif-Italic.ttf
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_SansSerif-Italic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_SansSerif-Italic.woff
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_SansSerif-Italic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_SansSerif-Italic.woff2
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_SansSerif-Regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_SansSerif-Regular.eot
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_SansSerif-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_SansSerif-Regular.ttf
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_SansSerif-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_SansSerif-Regular.woff
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_SansSerif-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_SansSerif-Regular.woff2
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Script-Regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Script-Regular.eot
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Script-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Script-Regular.ttf
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Script-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Script-Regular.woff
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Script-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Script-Regular.woff2
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Size1-Regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Size1-Regular.eot
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Size1-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Size1-Regular.ttf
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Size1-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Size1-Regular.woff
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Size1-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Size1-Regular.woff2
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Size2-Regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Size2-Regular.eot
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Size2-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Size2-Regular.ttf
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Size2-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Size2-Regular.woff
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Size2-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Size2-Regular.woff2
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Size3-Regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Size3-Regular.eot
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Size3-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Size3-Regular.ttf
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Size3-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Size3-Regular.woff
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Size3-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Size3-Regular.woff2
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Size4-Regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Size4-Regular.eot
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Size4-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Size4-Regular.ttf
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Size4-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Size4-Regular.woff
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Size4-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Size4-Regular.woff2
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Typewriter-Regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Typewriter-Regular.eot
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Typewriter-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Typewriter-Regular.ttf
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Typewriter-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Typewriter-Regular.woff
--------------------------------------------------------------------------------
/public/assets/lib/fonts/KaTeX_Typewriter-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fabianp/overview_optalgs/5712df1eee023ac4214ebf15c43945dcc35a44e7/public/assets/lib/fonts/KaTeX_Typewriter-Regular.woff2
--------------------------------------------------------------------------------
/public/assets/milestones.js:
--------------------------------------------------------------------------------
1 | function renderMilestones(div, updateTick) {
2 | var lambda = [1,10,100]
3 | var totalIters = 151
4 |
5 | div.append("defs").append("marker")
6 | .attr("id", "arrowhead")
7 | .attr("refX", 3)
8 | .attr("refY", 2)
9 | .attr("markerWidth", 4)
10 | .attr("markerHeight", 4)
11 | .attr("orient", "auto")
12 | .append("path")
13 | .attr("d", "M 0,0 V 4 L4,2 Z"); //this is actual shape for arrowhead
14 |
15 | var markers = []
16 | for (var i = 0; i < 3; i ++) {
17 | var marker = div.append("defs").append("marker")
18 | .attr("id", "arrowhead" + i)
19 | .attr("refX", 0)
20 | .attr("refY", 1)
21 | .attr("markerWidth", 4)
22 | .attr("markerHeight", 4)
23 | .attr("orient", "auto")
24 | .append("path")
25 | .attr("d", "M 0,0 V 2 L2,1 Z") //this is actual shape for arrowhead
26 | .attr("fill", colorbrewer.RdPu[3][i])
27 | markers.push(marker)
28 | }
29 |
30 | var f = function(x) {
31 | var fx = 0.5*(lambda[0]*x[0]*x[0] + lambda[1]*x[1]*x[1] + lambda[2]*x[2]*x[2])
32 | var g = [lambda[0]*x[0], lambda[1]*x[1], lambda[2]*x[2]]
33 | return [fx, g]
34 | }
35 |
36 | /*
37 | Gets information about iterates with certain parameter alpha and beta.
38 | > v = getTrace(0.5, 0)
39 | v[0] -> z iterates
40 | v[1] -> w iterates
41 | v[2] -> [c1, c2, c3] where c1, c2, c3 are the contributions to the loss
42 | */
43 | function getTrace(alpha, beta) {
44 | var w0 = [1,1/Math.sqrt(lambda[1]),1/Math.sqrt(lambda[2])]
45 | var v = runMomentum(f, w0, alpha, beta, totalIters)
46 | var fxstack = []
47 | // Add contributions to the objective
48 | for (var i = 0; i < v[0].length; i++) {
49 | var x = v[1][i]
50 | fxstack.push([lambda[0]*x[0]*x[0]/2, lambda[1]*x[1]*x[1]/2, lambda[2]*x[2]*x[2]/2 ])
51 | }
52 | v.push(fxstack)
53 | return v
54 | }
55 |
56 | var stackedBar = stackedBarchartGen(totalIters, 3)(div)
57 |
58 | var seperation = 14
59 |
60 | var r = []
61 | var lines = []
62 |
63 | var progressmeter = div.append("g")
64 | for (var i = 0; i < 3; i ++) {
65 | var ri = progressmeter.append("line")
66 | .attr("x1", stackedBar.X(-1) + "px")
67 | .attr("y1", (202 + i*seperation)+ "px")
68 | .attr("stroke", colorbrewer.RdPu[3][i])
69 | .attr("y2", (202 + i*seperation) + "px")
70 | .attr("stroke-width", 4)
71 | r.push(ri)
72 |
73 | var linei = progressmeter.append("line")
74 | .style("stroke", "black")
75 | .style("stroke-width",1.5)
76 | .attr("marker-end", "url(#arrowhead)")
77 | .attr("opacity", 0.6)
78 | lines.push(linei)
79 |
80 | progressmeter.append("text")
81 | .attr("class", "figtext2")
82 | .attr("x", 0)
83 | .attr("y", 206 + i*seperation)
84 | .attr("text-anchor", "end")
85 | .attr("fill", "gray")
86 | .html((i == 0) ? "Eigenvalue " + (i+1) : (i+1) )
87 | }
88 |
89 |
90 | var updateStep = function(alpha, beta) {
91 | var trace = getTrace(alpha/lambda[2], beta)
92 | // Update the milestones on the slider
93 | var milestones = [0,0,0]
94 | for (var i = 0; i < trace[1].length; i++) {
95 | if (trace[2][i][0] > 0.01) { milestones[2] = i }
96 | if (trace[2][i][1] > 0.01) { milestones[1] = i }
97 | if (trace[2][i][2] > 0.01) { milestones[0] = i }
98 | }
99 | stackedBar.update(trace[2], milestones)
100 |
101 | for (var i = 0; i < 3; i++) {
102 |
103 | var endpoint = stackedBar.stack[i].selectAll("line").nodes()[milestones[2-i]]
104 | var stack = endpoint.getBBox()
105 | var ctm = endpoint.getCTM()
106 | if (milestones[2-i] < 150) {
107 | lines[i].attr("x2", stack.x)
108 | .attr("y2", stack.y + 5)
109 | .attr("x1", stack.x)
110 | .attr("y1", 203.5 + seperation*(i))
111 | .style("visibility", "visible")
112 | r[i].attr("marker-end", "url()")
113 | } else {
114 | lines[i].style("visibility", "hidden")
115 | r[i].attr("marker-end", "url(#arrowhead" + i + ")")
116 | }
117 | //setTM(lines[i].node(), ctm) // transform the lines into stackedplot space
118 | r[i].attr("x2", (stackedBar.X(milestones[2-i]) - 2) + "px")
119 |
120 | //setTM(r[i].node(), ctm) // transform the lines into stackedplot space
121 | setTM(progressmeter.node(), ctm)
122 | }
123 | }
124 |
125 | updateStep(100*2/(101.5), 0)
126 |
127 | return updateStep
128 | }
--------------------------------------------------------------------------------
/public/assets/momentum.js:
--------------------------------------------------------------------------------
1 | /*
2 | Render an overlay layer
3 | */
4 |
5 | function renderOverlay(svg, nodes) {
6 |
7 | var ringPath = ringPathGen(5, 0, 0)
8 |
9 | var updates = []
10 |
11 | for (var i = 0; i < 5; i++) {
12 |
13 | var adjust = [0,0,0,0,0][i]
14 | var x1 = nodes[i].offsetLeft + 15
15 | var y1 = nodes[i].offsetTop + adjust
16 |
17 | var line = svg.append("line")
18 | .style("stroke", "black")
19 | .style("stroke-width", "1px")
20 | // .attr("stroke-dasharray", "2,2")
21 | .attr("opacity", 0.7)
22 | .attr("x1", x1)
23 | .attr("y1", y1)
24 | .attr("x2", x1)
25 | .attr("y2", y1 - adjust)
26 | .attr("shape-rendering", "crispEdges")
27 |
28 | var paths = svg.append("g");
29 |
30 | paths.append("path")
31 | .attr("class", "leader-line")
32 | .attr("d", ringPath([110,110],[x1,y1]).d)
33 | .style("stroke-width", "3px")
34 | .style("fill", "none")
35 | .attr("stroke", "white")
36 | // .attr("stroke-dasharray", "2,2")
37 | .attr("stroke-opacity", 0.4)
38 | .attr("shape-rendering", "crispEdges");
39 |
40 | paths.append("path")
41 | .attr("class", "leader-line")
42 | .attr("d", ringPath([110,110],[x1,y1]).d)
43 | .style("stroke-width", "1px")
44 | .style("fill", "none")
45 | .attr("stroke", "black")
46 | // .attr("stroke-dasharray", "2,2")
47 | .attr("stroke-opacity", 0.3)
48 | .attr("shape-rendering", "crispEdges");
49 |
50 | var path = paths.selectAll(".leader-line")
51 |
52 | var circ = svg.append("g")
53 | .attr("transform", "translate(" + x1 + "," + y1 + ")");
54 |
55 | circ.append("circle")
56 | .attr("r", 5)
57 | .attr("fill","none")
58 | .attr("stroke", "white")
59 | .attr("stroke-width", 4)
60 | .attr("stroke-opacity", 0.5);
61 |
62 | circ.append("circle")
63 | .attr("r", 5)
64 | .attr("fill","none")
65 | .attr("stroke", "black")
66 | .attr("stroke-width", 1);
67 |
68 | n = nodes
69 | var updatePath = (function(xin, yin, pathin, circin,i, aline) {
70 | return function(x2, y2, bold) {
71 |
72 | if (!bold) {
73 | d3.select(nodes[i]).style("opacity", 0.1)
74 | } else {
75 | d3.select(nodes[i]).style("opacity", 1)
76 | }
77 |
78 | circin.attr("transform", "translate(" + x2 + "," + y2 + ")");
79 |
80 | if (i < 2) {
81 | pathin.attr("d", ringPath([x2, y2],[xin, yin]).d);
82 | } else {
83 | pathin.attr("d", ringPath([xin + 5, yin + 5],[x2 + 4, y2]).d);
84 | }
85 | aline.attr("opacity", bold? 1 : 0.7).style("stroke-width", bold? 1:1).style("stroke", "rgb(150, 150, 150)")
86 | }
87 | })(x1, y1, path, circ,i,line)
88 |
89 | updates.push(updatePath)
90 | }
91 |
92 | return updates
93 | }
94 |
95 | /*
96 | Render the whole momentum widget
97 | */
98 | function renderTaxonomy(div) {
99 |
100 | var valueline = d3.line()
101 | .x(function(d) { return d[0]; })
102 | .y(function(d) { return d[1]; });
103 |
104 | function drawPath(svg, s1, s2, e1, e2) {
105 |
106 | svg.append("path")
107 | .attr("opacity", 1)
108 | .style("stroke", "black")
109 | .style("stroke-width", "1px")
110 | .style("stroke-linecap","round")
111 | .attr("d", genPath( s1, s2, e1, e2 ))
112 |
113 | }
114 |
115 | var num_iters = 40
116 |
117 | function getTrace(alpha, beta, xy, coord) {
118 | var m = []
119 | var lambda = [1,100]
120 | var iter = geniterMomentum([[1, 0],[0, 1]], lambda, lambda, alpha, beta).iter
121 | // run for 500 iterations
122 | for (var i = 0; i <= num_iters; i++) {
123 | if (xy == 1) { m.push(numeric.add(iter(i)[xy],-1)) }
124 | if (xy == 0) { m.push(numeric.mul(iter(i)[xy],0.005)) }
125 | }
126 | return numeric.transpose(m)[coord]
127 | }
128 |
129 | div.style("display", "block")
130 | .style("margin-left","auto")
131 | .style("margin-right","auto")
132 | .style("position", "relative")
133 | .style("border-radius", "5px")
134 |
135 | var divs = []
136 | function genPhase(i,t,l, range,title,text) {
137 |
138 | var outdiv = div.append("div")
139 | .style("position", "absolute")
140 | .style("top", t +"px")
141 | .style("left", l +"px")
142 | .style("width", "180px")
143 | .style("height", "300px")
144 | .style("border-top", "1px solid #ccc")
145 |
146 | divs.push(outdiv.node())
147 |
148 | var updatePath = stemGraphGen(170, 120, num_iters)
149 | .radius1(1)
150 | .axis(range)
151 | .labelSize("0px")
152 | .numTicks(2)
153 | .borderTop(30)
154 | (outdiv)
155 |
156 | outdiv.append("span")
157 | .style("position", "absolute")
158 | .style("top","8px")
159 | .style("width", "150px")
160 | .style("height", "130px")
161 | .style("font-size", "13px")
162 | .attr("class", "figtext")
163 | .style("text-align", "left")
164 | .html(""+title+"")
165 |
166 | outdiv.append("figcaption")
167 | .style("position", "absolute")
168 | .style("top","160px")
169 | .style("width", "160px")
170 | .style("height", "130px")
171 | .style("text-align", "left")
172 | .html(text)
173 |
174 |
175 | return updatePath
176 | }
177 |
178 | var top = 270
179 | var spacing = 190
180 | var updateDR = genPhase(0,top,0, [-1.4,1.4], "Ripples", "R's eigenvalues are complex, and the iterates display low frequency ripples. Surprisingly, the convergence rate " + MathCache("two-sqrt-beta") + " is independent of " + MathCache("alpha") + " and " + MathCache("lambda-i") + ".")
181 | updateDR(getTrace(0.0017,0.94,1,1))
182 |
183 | var updateMC = genPhase(1,top,spacing*1,[-1.4,1.4], "Monotonic Decrease", "R's eigenvalues are both real, are positive, and have norm less than one. The behavior here resembles gradient descent.")
184 | updateMC(getTrace(0.00093, 0.16,1,1))
185 |
186 | var updateD = genPhase(2,top,spacing*2,[-1.4,1.4], "1-Step Convergence", "When " + MathCache("alpha-equals-one-over-lambda-i") + ", and " + MathCache("beta-equals-zero") + ", we converge in one step. This is a very special point, and kills the error in the eigenspace completely.")
187 | updateD(getTrace(0.0213, 0.06,1,1))
188 |
189 | var updateIC = genPhase(3,top,spacing*3,[-1.4,1.4], "Monotonic Oscillations", "When " + MathCache("alpha-gt-one-over-lambda-i") + ", the iterates flip between " + MathCache("plus") + " and " + MathCache("minus") + " at each iteration. These are often referred to as 'oscillations' in gradient descent.")
190 | updateIC(getTrace(0.01, 0.0001,1,1))
191 |
192 | var updateMO = genPhase(4,top,spacing*4,[-5,5], "Divergence", "When " + MathCache("max-sigma-one") + ", the iterates diverge. ")
193 | updateMO(getTrace(0.02, 0.045,1,1))
194 |
195 | var svg = div.append("svg")
196 | .style("position", "absolute")
197 | .style("width","920px")
198 | .style("height","500px")
199 | .style("z-index", 3)
200 | .style("pointer-events","none")
201 |
202 | function wrap(f) {
203 | return function(alpha, beta) {
204 | return f(getTrace(alpha, beta, 1,1))
205 | }
206 | }
207 |
208 | return {update:[wrap(updateDR), wrap(updateMC), wrap(updateD), wrap(updateIC), wrap(updateMO)], div:divs }
209 | }
210 |
211 | /*
212 | Render 2D slider thingy to the right.
213 | */
214 | function render2DSliderGen(updateDR, updateMC, updateIC, updateMO, updateD,
215 | defaults) {
216 |
217 | var slider2Dtop = 10 // Margin at top
218 | var slider2D_size = 200; // Dimensions (square) of 2D Slider
219 | var slider2Dleft = 0 // How far to the left to put the 2D Slider
220 |
221 | function render2DSlider(divin){
222 |
223 | function getEigs(alpha, beta,lambda) {
224 | var E = [[ beta , lambda ],
225 | [ -1*alpha*beta , 1 - alpha*lambda]]
226 | return numeric.eig(E)["lambda"]
227 | }
228 |
229 | var div = divin
230 | .append("div")
231 | .style("position","absolute")
232 | .attr("class", "d3-tip n")
233 | .style("z-index", 2)
234 | .html("s1 = s2 = complex")
235 | .style("opacity",0)
236 |
237 | var ybeta = d3.scaleLinear().domain([1,0]).range([0, slider2D_size]);
238 | var xalpha = d3.scaleLinear().domain([0,4/100]).range([0, 2*slider2D_size]);
239 |
240 | var prevregime = ""
241 | var canvas = divin
242 | .append('canvas')
243 | .style("position", 'absolute')
244 | .style("left", 137 + "px")
245 | .style("top", slider2Dtop + "px")
246 | .style("width", 2*slider2D_size)
247 | .style("height", slider2D_size)
248 | .attr("width", 2*slider2D_size/1)
249 | .attr("height", slider2D_size/1)
250 | .style("z-index", 1)
251 | .style("border","solid 1px black")
252 | // .style("box-shadow","0px 3px 10px rgba(0, 0, 0, 0.4)")
253 | .on("mousemove", function() {
254 |
255 | var pt = d3.mouse(this)
256 |
257 | var alpha = Math.max(0,xalpha.invert(pt[0]))
258 | var beta = ybeta.invert(pt[1])
259 |
260 | var xy = convert(alpha, beta)
261 |
262 | xAxis.select("circle").attr("cx", pt[0]).style("visibility","visible")
263 | yAxis.select("circle").attr("cy", pt[1]).style("visibility","visible")
264 |
265 | var e = getEigs(alpha,beta, 100)
266 | var n1 = 0
267 | var n2 = 0
268 | var regime = ""
269 | var regime2 = "convergent"
270 | if (e.y === undefined) {
271 | n1 = Math.abs(e.x[0])
272 | n2 = Math.abs(e.x[1])
273 | regime = "real"
274 | } else {
275 | n1 = numeric.norm2(e.x[0], e.y[0])
276 | n2 = numeric.norm2(e.x[1], e.y[1])
277 | regime = "complex"
278 | }
279 |
280 | if (Math.max(n1,n2) < 1.0001) {
281 | regime2 = "convergent"
282 | } else {
283 | regime2 = "divergent"
284 | }
285 |
286 | if (alpha < 1/100) {
287 | regime3 = "short"
288 | } else if (alpha < 2/100) {
289 | regime3 = "long"
290 | } else {
291 | regime3 = "verylong"
292 | }
293 |
294 | if (regime == "real" && regime3 != "short" && regime2 != "divergent") {
295 | if (prevregime != "MO") {
296 | updateDR(defaults[0][0], defaults[0][1], false)
297 | updateMC(defaults[1][0], defaults[1][1], false)
298 | updateIC(defaults[2][0], defaults[2][1], false)
299 | updateD( defaults[4][0], defaults[4][1], false)
300 | }
301 | updateMO(alpha,beta, true)
302 | prevregime = "MO"
303 | }
304 |
305 | if (regime == "real" && regime3 == "short") {
306 | if (prevregime != "MC") {
307 | updateDR(defaults[0][0], defaults[0][1], false)
308 | updateIC(defaults[2][0], defaults[2][1], false)
309 | updateMO(defaults[3][0], defaults[3][1], false)
310 | updateD( defaults[4][0], defaults[4][1], false)
311 | }
312 | updateMC(alpha,beta, true)
313 | prevregime = "MC"
314 | }
315 |
316 | if (regime == "complex") {
317 | if (prevregime != "DR") {
318 | updateMC(defaults[1][0], defaults[1][1], false)
319 | updateIC(defaults[2][0], defaults[2][1], false)
320 | updateMO(defaults[3][0], defaults[3][1], false)
321 | updateD( defaults[4][0], defaults[4][1], false)
322 | }
323 | updateDR(alpha,beta, true)
324 | prevregime = "DR"
325 | }
326 |
327 | if (regime2 == "divergent") {
328 | if (prevregime != "D") {
329 | updateDR(defaults[0][0], defaults[0][1], false)
330 | updateMC(defaults[1][0], defaults[1][1], false)
331 | updateIC(defaults[2][0], defaults[2][1], false)
332 | updateMO(defaults[3][0], defaults[3][1], false)
333 | }
334 | updateD(alpha,beta, true)
335 | prevregime = "D"
336 | }
337 |
338 | }).on("mouseout", function() {
339 | updateDR(defaults[0][0], defaults[0][1], true)
340 | updateMC(defaults[1][0], defaults[1][1], true)
341 | updateIC(defaults[2][0], defaults[2][1], true)
342 | updateMO(defaults[3][0], defaults[3][1], true)
343 | updateD( defaults[4][0], defaults[4][1], true)
344 | xAxis.select("circle").style("visibility","hidden")
345 | yAxis.select("circle").style("visibility","hidden")
346 |
347 | prevregime = ""
348 | }
349 |
350 |
351 | )
352 | .node();
353 |
354 | var convert = function(alpha, beta) {
355 | return [xalpha(alpha) + canvas.offsetLeft + divin.node().offsetLeft,
356 | ybeta(beta) + canvas.offsetTop + divin.node().offsetTop]
357 | }
358 |
359 | renderHeatmap(canvas, function(i,j) {
360 | var e = getEigs(4*i,1-j, 1)
361 | return Math.max(e.getRow(0).norm2(), e.getRow(1).norm2());
362 | }, d3.scaleLinear().domain([0,0.3,0.5,0.7,1,1.01]).range(colorbrewer.YlGnBu[5].concat(["black"])))
363 |
364 | // /* Axis */
365 | var canvasaxis = divin.append("svg").style("z-index", 0)
366 | .style("position","absolute")
367 | .style("left","86px")
368 | .style("top", (-20 + slider2Dtop) + "px")
369 | .style("width",2*slider2D_size + 70)
370 | .style("height",slider2D_size + 60)
371 |
372 | var xAxis = canvasaxis.append("g")
373 | xAxis.append("circle").attr("fill", "black").attr("r", 2).style("visibility","hidden")
374 | xAxis.attr("class", "grid figtext")
375 | .attr("transform", "translate(51,"+(slider2D_size + 25) +")")
376 | .call(d3.axisBottom(d3.scaleLinear().domain([0,4]).range([0, 2*slider2D_size]))
377 | .ticks(2)
378 | .tickSize(4))
379 |
380 | var yAxis = canvasaxis.append("g")
381 | yAxis.append("circle").style("fill", "black").attr("r", 2).style("visibility","hidden")
382 | yAxis.attr("class", "grid figtext")
383 | .attr("transform", "translate(46,20)")
384 | .call(d3.axisLeft(ybeta).ticks(1).tickSize(4))
385 |
386 |
387 | var html = MathCache("beta-equals");
388 | divin
389 | .append("text")
390 | .style("position","absolute")
391 | .style("left", "23px")
392 | .style("width", "90px")
393 | .style("top", slider2Dtop -9 + "px")
394 | .attr("class", "figtext")
395 | .html("Momentum " + html)
396 |
397 | var html = MathCache("alpha-equals");
398 | divin
399 | .append("text")
400 | .style("position","absolute")
401 | .style("left", "450px")
402 | .style("width", "90px")
403 | .style("top", slider2Dtop + 208 + "px")
404 | .attr("class", "figtext")
405 | .html("Step-size " + html)
406 |
407 | // Returns a function which converts alpha, beta into the parents
408 | // coordinate space
409 | return convert
410 |
411 | }
412 |
413 | render2DSlider.size = function (_) {
414 | slider2D_size = _; return render2DSlider
415 | }
416 |
417 | return render2DSlider
418 | }
--------------------------------------------------------------------------------
/public/assets/phasediagram.js:
--------------------------------------------------------------------------------
1 | function phaseDiagram(divin) {
2 |
3 | var totalIters = 100
4 | var default_underdamp = 0.97
5 | var default_overdamp = 0.05
6 |
7 | function getTrace(alpha, beta, coord, sign) {
8 | var m = []
9 | var lambda = [1,100]
10 | var iter = geniterMomentum([[1, 0],[0, 1]], lambda, [1,sign*100], alpha, beta).iter
11 | // run for 500 iterations
12 | for (var i = 0; i <= totalIters; i++) {
13 | var x = numeric.add(iter(i)[1],-sign*1)
14 | var y = numeric.mul(iter(i)[0],(1/200))
15 | m.push([y[coord], x[coord]])
16 | }
17 | mG = m
18 | return m
19 | }
20 |
21 | var textCaptions = ["
Overdamping
When " + MathCache("beta") + " is too small (e.g. in Gradient Descent, " + MathCache("beta-equals-zero") + "), we're over-damping. The particle is immersed in a viscous fluid which saps it of its kinetic energy at every timestep.",
22 | "
Critical Damping
The best value of " + MathCache("beta") + " lies in the middle of the two extremes. This sweet spot happens when the eigenvalues of " + MathCache("r") + " are repeated, when " + MathCache("beta-equals-one-minus") + ".",
23 | "
Credits. This material was created by Fabian Pedregosa for an invied lecture at McGill University.
155 | Source code can be found here.
156 | The template and the visualizations are modified from the distill article How momentum really works. Some parts of the knowing your problem section are based on the scipy lecture notes.
178 | In Newton's method, we approximate the objective with a quadratic surrogate of the form
179 | \begin{equation}
180 | Q_t(\xx) = c_t + \boldsymbol{g}_t^T(\xx - \xx_t) + \frac{1}{2 \gamma}(\xx - \xx_t)^T \boldsymbol{H}_t (\xx - \xx_t)~.
181 | \end{equation}
182 | Compared to gradient descent, the quadratic term is not fixed the be the identity but instead can incorporate an arbitrary (positive semi-definite) matrix $\boldsymbol{H}_t$.
183 |
184 |
A reasonable condition to impose on this surrogate function is that it at $\xx_t$ it coincides with $f$ in its value and first derivative, that is:
185 | \begin{align}
186 | Q_t(\xx_t) &= f(\xx_t) \implies c_t = f(\xx_t)\\
187 | \nabla Q_t(\xx_t) &= \nabla f(\xx_t) \implies \boldsymbol{g}_t = \nabla f(\xx_t)\\
188 | \nabla^2 Q_t(\xx_t) &= \nabla^2 f(\xx_t) \implies \boldsymbol{H}_t = \nabla^2 f(\xx_t)~,
189 | \end{align}
190 | where $\nabla^2 f(\xx_t)$ is the Hessian of $f$:
191 | \begin{equation}
192 | \nabla^2 f(\xx_t)= \begin{bmatrix}
193 | \dfrac{\partial^2 f}{\partial x_1^2} & \dfrac{\partial^2 f}{\partial x_1\,\partial x_2} & \cdots & \dfrac{\partial^2 f}{\partial x_1\,\partial x_n} \\[2.2ex]
194 | \dfrac{\partial^2 f}{\partial x_2\,\partial x_1} & \dfrac{\partial^2 f}{\partial x_2^2} & \cdots & \dfrac{\partial^2 f}{\partial x_2\,\partial x_n} \\[2.2ex]
195 | \vdots & \vdots & \ddots & \vdots \\[2.2ex]
196 | \dfrac{\partial^2 f}{\partial x_n\,\partial x_1} & \dfrac{\partial^2 f}{\partial x_n\,\partial x_2} & \cdots & \dfrac{\partial^2 f}{\partial x_n^2}
197 | \end{bmatrix}~,
198 | \end{equation}
199 | where in this last equation the subindex refers to the entries in the vector and not to the iterates.
200 |
201 | Alternatively, you might also see $Q_t$ as the second-order Taylor expansion of $f$ at $\xx_t$. In all, we have the following surrogate function:
202 | \begin{equation}
203 | Q_t(\xx_t) = f(\xx_t) + \nabla f(\xx_t)^T (\xx - \xx) + \frac{1}{2 \gamma}(\xx - \xx_t)^T \nabla^2 f(\xx_t) (\xx - \xx_t)~.
204 | \end{equation}
205 |
206 |
207 | We can find the optimum of the function deriving and equating to zero. This way we find (assuming the Hessian is invertible)
208 | \begin{equation}
209 | \xx_{t+1} = \argmin_{\xx} Q_t(\xx) = \xx_t - \gamma [\nabla^2 f(\xx_t)]^{-1} \nabla f(\xx_t)
210 | \end{equation}
211 |
212 |
213 |
214 | Where applicable, Newton's method converges much faster towards a local maximum or minimum than gradient descent. In fact, every local minimum has a neighborhood such that, if we start within this neighborbood, Newton's method with step size $\gamma=1$ converges quadratically assuming the Hessian is invertible and Lipschitz continuous.
215 |
216 |
217 |
The biggest drawback of Newton's method is that finding the inverse of the Hessian in high dimensions can be an expensive operation. In such cases, instead of directly inverting the Hessian it's better to calculate the vector $\boldsymbol\Delta$ as the solution to the system of linear equations
218 |
219 | $$\nabla^2 f(\mathbf{x}_t) \boldsymbol{\Delta} = -\nabla f(\mathbf{x}_t)
220 | $$
221 |
222 | which may be solved by various factorizations or approximately (but to great accuracy).
223 |
224 |
225 |
226 |
Examples
227 |
228 |
229 |
230 | Step-size α = 1
231 |
232 |
233 | In this case the approximation is exact and we converge on a single iteration.
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 | Step-size α = 1
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 | Step-size α = 1
253 |
254 |
255 | When the Hessian is close to singular there might be some numerical instabilities.
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
357 |
358 |
359 |
360 |
394 |
395 |
A key idea is to start at an initial estimate $\xx_0$ and successively minimize an approximating function $Q_t(\xx)$:
176 | \begin{equation}
177 | \xx_{t+1} = \argmin_{\xx \in \RR^p} Q_t(\xx)~.
178 | \end{equation}
179 |
180 |
We will call $Q_t$ a surrogate function. It is also known as merit function.
181 |
How to find such surrogate function?
182 |
A good surrogate function should:
183 |
184 |
Approximate the objective function.
185 |
Easy to optimize.
186 |
187 |
188 |
Linear surrogates
189 |
The simplest class of surrogates we can think of are linear surrogates, that is, functions of the form
190 | $$
191 | Q_t(\xx) = (\xx - \xx_t)^T \boldsymbol{b}_t + c_t~.
192 | $$
193 |
194 |
While simple, they are general unbounded, making thir minimization problematic -- although they do have some uses in constrained optimization
195 |
196 |
Quadratic surrogates
197 |
Slightly more complex are quadratic functions. These are of the form
198 | $$
199 | Q_t(\xx) = (\xx - \xx_t)^T \boldsymbol{A} (\xx - \xx_t) + \boldsymbol{b}_t^T (\xx - \xx_t) + c_t.
200 | $$
201 |
202 |
Yes! Many examples: Gradient descent, Newton, etc.