開発環境
- OS X El Capitan - Apple (OS)
- Emacs (Text Editor)
- JavaScript (プログラミング言語)
- kjs-array (JavaScript Library)
- D3.js (JavaScript Library)
- Safari(Web browser)
- JavaScript 第6版 (David Flanagan(著)、村上 列(翻訳)、オライリージャパン)(参考書籍)
- JavaScriptリファレンス 第6版(David Flanagan(著)、木下 哲也(翻訳)、オライリージャパン)(参考書籍)
Pythonからはじめる数学入門 (Amit Saha (著)、黒川 利明 (翻訳)、オライリージャパン)の7章(初等解析問題を解く)、7.6(勾配上昇法を用いて最大値を求める)をJavaScriptで取り組んでみる。
7.6(勾配上昇法を用いて最大値を求める)
コード(Emacs)
HTML5
<div id="graph0"></div>
<div id="output0"></div>
<label for="initial0">
初期値:
</label>
<input id="initial0" type="number" min="0" value="0.05729577951308232">
<br>
<label for="step0">
ステップサイズ:
</label>
<input id="step0" type="number" min="0" value="0.005729577951308233">
<br>
<label for="epsilon0">
ε =
</label>
<input id="epsilon0" type="number" min="0">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.2/d3.min.js"></script>
<script src="array.js"></script>
<script src="grad_ascent.js"></script>
JavaScript
(function () {
'use strict';
var g = 9.8,
u = 25,
degrees = range(0, 90, 1e-2),
width = 600,
height = 600,
padding = 50,
xscale,
yscale,
xaxis,
yaxis,
div_graph = document.querySelector('#graph0'),
div_output = document.querySelector('#output0'),
input_initial = document.querySelector('#initial0'),
input_step = document.querySelector('#step0'),
input_epsilon = document.querySelector('#epsilon0'),
inputs = [input_initial, input_step, input_epsilon],
toRadian,
calcDistance,
derivDistance,
getPoints0,
getPoints1,
output;
input_epsilon.value = Number.EPSILON;
toRadian = function (degree) {
return degree * Math.PI / 180;
};
xscale = d3.scaleLinear()
.domain([0, 90])
.range([padding, width - padding]);
yscale = d3.scaleLinear()
.domain([0, 70])
.range([height - padding, padding]);
xaxis = d3.axisBottom().scale(xscale);
yaxis = d3.axisLeft().scale(yscale);
calcDistance = function (theta) {
return Math.pow(u, 2) * Math.sin(2 * theta) / g;
};
derivDistance = function (theta) {
return Math.pow(u, 2) * 2 * Math.cos(2 * theta) / g;
};
getPoints0 = function () {
return degrees.map(function (degree) {
return [degree, calcDistance(toRadian(degree)), 1, 'blue'];
});
};
getPoints1 = function () {
var points = [],
step_size = toRadian(parseFloat(input_step.value)),
x_old = toRadian(parseFloat(input_initial.value)),
epsilon = toRadian(parseFloat(input_epsilon.value)),
x_new = x_old + step_size * derivDistance(x_old);
points.push([x_new * 180 / Math.PI, calcDistance(x_new), 5, 'green']);
for (; Math.abs(x_old - x_new) > epsilon; ) {
x_old = x_new;
x_new = x_old + step_size * derivDistance(x_old);
points.push(
[x_new * 180 / Math.PI, calcDistance(x_new), 5,'green']);
}
return points;
};
output = function () {
var svg,
points0 = getPoints0(),
points1 = getPoints1(),
points = points0.concat(points1),
degree = points1[points1.length - 1][0];
div_graph.innerHTML = '';
svg = d3.select('#graph0')
.append('svg')
.attr('width', width)
.attr('height', height);
svg.selectAll('circle')
.data(points)
.enter()
.append('circle')
.attr('cx', function (d) {
return xscale(d[0]);
})
.attr('cy', function (d) {
return yscale(d[1]);
})
.attr('r', function (d) {
return d[2];
})
.attr('fill', function (d) {
return d[3];
});
svg.append('g')
.attr('transform', 'translate(0, ' + (height - padding) + ')')
.call(xaxis);
svg.append('g')
.attr('transform', 'translate(' + padding + ', 0)')
.call(yaxis);
div_output.innerHTML =
'Theta: ' + degree + '<br>' +
'Maximum Range: ' + calcDistance(toRadian(degree)) + '<br>';
};
inputs.forEach(function (input) {
input.onchange = output;
});
output();
}());
0 コメント:
コメントを投稿