Why doesn't this javascript work in browser? - javascript

I have the following code in a .js file:
$.extend(KhanUtil, {
// takes a number and returns the sign of that number
steveSign: function(num){
num = parseFloat(num)
if (num>=0){return 1}
else{return -1}
},
// takes a function, a lower bound for a zero,an upper bound for a zero, and locates
// that zero by iteratively halving the interval.
steveRoot: function(f,xmin,xmax){
var l = xmin
var r = xmax
var z = 0
for (i=0;i<6;i++){
z = (l + r)/2
if (KhanUtil.steveSign(f(l)) === KhanUtil.steveSign(f(z))){ l = z}
else{r = z}
}
return z
},
});
In my html file I define var f = function(x){return x**2 - 2} and run steveRoot(f,1,2), but my browser craps out. Why is this happening?
EDIT:
I am posting the entirety of my code, because it was requested in the comments. thanks a bunch for trying to help me out guys. The weird thing is the code runs fine 9 times out of ten. It is just occasionally that it "craps out". There are a lot of random variables in here, but I can't imagine why steveRoot would care about getting a slightly different function. The code works totally fine and never craps out when I don't include a variable which calls steveRoot.
The HTML file:
<!DOCTYPE html>
<html data-require="math graphie graphie-helpers play polynomials steveMath">
<head>
<title>Piecewise-defined function</title>
<script src="../khan-exercise.js"></script>
</head>
<body>
<div class="exercise">
<div class="vars">
<var id = "n">randRange(2,4)</var>
<var id = "abscissas">makeXList()</var>
<var id = "ordinates">makeYList(-9,9,abscissas.length)</var>
<var id = "points">makeCoordinates(abscissas,ordinates)</var>
<var id = "f">(function(x){return niceFunction(x,points)})</var>
<var id = zeros>steveRoot(f,-10,10)</var>
</div>
<div class="problems">
<div id="problem-type-or-description">
<p class="problem">You are going to have to answer 5</p>
<p class="question">Answer 5</p>
<div class="graphie" id="grid">
graphInit({
range: 10,
scale: 20,
tickStep: 1,
axisArrows: "<->"
});
a =style({
stroke: "red",
strokeWidth: 2
}, function() {
plot( function( x ) { return niceFunction(x,points);
}, [ -10, 10 ] );
});;
a.plot();
</div>
<p class="solution">5</p>
</div>
</div>
<div class="hints">
<!-- Any hints to show to the student. -->
</div>
</div>
</body>
The .js file:
$.extend(KhanUtil, {
//randomLines is a piecewise linear function in x, where the partition points are given by list_of_points.
//list_of_points is an array of arrays, for example [[1,5],[2,-1],[3,4]] would indicate the points (1,5), (2,-1), and (3,4)
//are on the curve. The points must be arranged in order of increasing abscissa.
randomLines: function(x,list_of_points)
{
for (i=0;i<list_of_points.length-1;i++)
{
var x_1 = list_of_points[i][0]
var y_1 = list_of_points[i][1]
var x_2 = list_of_points[i+1][0]
var y_2 = list_of_points[i+1][1]
var m = (y_2-y_1)/(x_2-x_1)
var y = m*(x - x_1) + y_1
if (x > x_1 && x <= x_2){return y}
}
if (x<=list_of_points[0][0]){return 0}
if (x>list_of_points[list_of_points.length-1][0]){return 0}
},
//randomLinesFunc: function(list_of_points){
// var f = function(x){
// return randomLines(x,list_of_points)
// }
//
// return f
//},
numInt: function(f,x){
var delta = .01
var sum = 0
var i = 0
while ((delta*i-10)<=x)
{sum = sum+delta*f(-10+i*delta)
i++
}
return sum
},
peace: function(x){return 2},
////////////////////////////////////////////////
//randRangeNZCU takes (min,max,n) and returns an array of nonzero numbers between max and min
//with successive numbers being distinct. For example [-1,2,-1] could show up, but [2,2,5] will not.
// NZCU stands for NonZeroConsecutiveUnique.
randRangeNZCU: function(min,max,n){
excluded = [0]
array = [KhanUtil.randRangeExclude(min,max,excluded)]
for (i=1;i<n;i++){
excluded = [0,array[i-1]]
array.push(KhanUtil.randRangeExclude(min,max,excluded))
}
return array
},
// makeCoordinates takes two arrays of the same length and returns the array of ordered pairs.
// Example: makeCoordinates([1,2,3],[4,5,6]) = [[1,4],[2,5],[3,6]]
makeCoordinates: function(array1,array2){
array = []
for (i=0;i<array1.length;i++){
array.push([array1[i],array2[i]])
}
return array
},
steveCubic: function(x){return -Math.pow(x,3)/2+3*x/2},
//niceFunction is a C^1 function which connects the points in "points". It is designed to be used
//in my "curveSketchingIntuition" exercise. Every point in the list will have 0 slope, except the first and last point.
niceFunction: function(x,points){
len = points.length
var x1 = points[0][0]
var x2 = points[1][0]
var y1 = points[0][1]
var y2 = points[1][1]
var k = (y1 - y2)/Math.pow(x1-x2,2)
if (x<x2){return k*Math.pow(x-x2,2)+y2}
for (i=1;i<len-2;i++){
var x1 = points[i][0]
var x2 = points[i+1][0]
var y1 = points[i][1]
var y2 = points[i+1][1]
xNew = (x-x1)*2/(x2-x1)-1
yNew = (KhanUtil.steveCubic(xNew)+1)*(y2-y1)/2+y1
if (x>=x1 && x<x2){return yNew}
}
var x1 = points[len-2][0]
var x2 = points[len-1][0]
var y1 = points[len-2][1]
var y2 = points[len-1][1]
var k = (y2 - y1)/Math.pow(x1-x2,2)
if (x>=x1){return k*Math.pow(x-x1,2)+y1}
},
makeXList: function(){
array = [-10]
i=0
while(array[i]<10){
x = array[i]+3*KhanUtil.randRange(1,3)
if (x<10){array.push(x)}
i=i+1
}
array.push(10)
return array
},
makeYList:function(min,max,n){
excluded = [0]
array = [KhanUtil.randRangeExclude(min,max,excluded)]
excluded.push(array[0])
array.push[KhanUtil.randRangeExclude(min,max,excluded)]
excluded = [0]
for (i=1;i<n;i++){
if (array[i-2]<array[i-1]){
array.push(KhanUtil.randRangeExclude(min,array[i-1]-1,excluded))
}
else{array.push(KhanUtil.randRangeExclude(array[i-1]+1,max,excluded))}
}
return array
},
newtonRoot: function(f,a){
var z = a
var m = (f(z+.01)-f(z-.01))/.02
for(i=0;i<2;i++){
z = z-f(z)/m
m = (f(z+.01)-f(z-.01))/.02
}
return z
},
steveSign: function(num){
num = parseFloat(num)
if (num>=0){return 1}
else{return -1}
},
steveRoot: function(f,xmin,xmax){
var l = xmin
var r = xmax
var z = 0
for (i=0;i<6;i++){
z = (l + r)/2
if (KhanUtil.steveSign(f(l)) === KhanUtil.steveSign(f(z))){ l = z}
else{r = z}
}
return z
},
locateZeros: function(f,points){
var len = points.length
var list = []
for(i=0;i<len-1;i++){
var x0 = points[i][0]
var x1 = points[i+1][0]
var y0 = points[i][1]
var y1 = points[i+1][1]
// var m = (y1-y0)/(x1-x0)
// var a = -y0/m+x0
// var z = KhanUtil.steveRoot(f,1,2)
list.push(KhanUtil.steveSign(f(x0)))
}
return list
},
});

In javascript x**2 is not valid. (SyntaxError: Unexpected token *)
You need to run KhanUtil.steveRoot(f,1,2); not just steveRoot(f,1,2);.

Related

Array of objects properties become NaN between function calls in Html Javascript

This code is done in HTML javascript.
The following functions (placero() and runro()) are called in that order. placero() seems to initialize the xs and ys of the object list correctly, but by the time the first line of runro() is called, all of the xs and ys have become NaN.
The goal of the code was to make a program that creates rooms and connects them with corridors. Previous steps have inititalized the rooms and corridor layout, but the job of placero() is to place each room somewhere random on the map.
the code is as follows:
runm does all the initial setting code(such as the room member initialization) and does all the other work before placero(). I have been clicking the buttons in the intended order(sequentially), so that shouldnt be the problem.
var roomes = new Array(0);
function randIntBetween(min, max) { // min and max included
return Math.floor(Math.random() * (max - min + 1) + min);
}
//before any function calls, rooms is initialized as follows(well after the input has been entered, in most cases):
roomMax = document.getElementById("inp1").value; //this is the inputted number of rooms being made
for (var k = 0; k < roomMax; k++) {
var obj = {
ind: k,
x: -1,
y: -1,
neighb: Array(0)
}
roomes.push(obj);
}
//then some work is done, placing the indexes of other rooms in the neighbors array in each room.
//none of the in-between code edits x or y.
function placero() {
for (var kis = 0; kis < roomes.length; kis++) {
var x = randIntBetween(5, mapX - 5); //get a random x and y for room position
var y = randIntBetween(5, 5);
roomes[kis].x = x;
roomes[kis].y = y;
}
console.log(roomes); //prints a correct array
}
function runro() {
console.log(roomes); //prints an incorrect array
var iterCount = 2;
//this code aims to place rooms closer to their neighbors, by averaging a rooms position with that of its neighbors and moving it half the way in that direction.
for (var ki = 0; ki < iterCount; ki++) { //for each iteration in which the rooms are moved,
for (var kt = 0; kt < roomes.length; kt++) { //for each room
var coun = NeighbCount(roomes[kt]); //get number of neighbors(will be used for averageing)
console.log(coun);
var sumx = 0;
var sumy = 0;
for (var km = 0; km < coun; km++) { //for each neighbor,
sumx = sumx + roomes[roomes[kt].neighb[km]].x; //add its position to the sum position
sumy = sumy + roomes[roomes[kt].neighb[km]].y;
}
sumx = sumx / coun; //then divide by number of neighbors to get new position
sumy = sumy / coun;
console.log(sumx + " " + roomes[kt].x); //troubleshooting
console.log(sumy + " " + roomes[kt].y);
roomes[kt].x = sumx / 2 + roomes[kt].x / 2; //setting new positions
roomes[kt].y = sumy / 2 + roomes[kt].y / 2;
}
}
}
<div>
<input type="number" id="inp1" name="inp1"><br>
</div>
<button onclick="runm()">Make room map</button>
<button onclick="placero()">place rooms</button>
<button onclick="runro()">Make rooms</button>
You're probably getting the error because roomMax is of string type and not number type. To solve this, make the following modifications to your code:
roomMax = parseInt(document.getElementById("inp1").value);
The value from an input will always be a string. The code above changes the type.
Look through your code to see if you have any similar mistakes.

Backpropagation in an Tensorflow.js Neural Network

When I have been attempting to implement this function tf.train.stg(learningRate).minimize(loss)into my code in order to conduct back-propagation. I have been getting multiple errors such The f passed in variableGrads(f) must be a function. How would I implement the function above into the code bellow successfully? and Why does this error even occur?
Neural Network:
var X = tf.tensor([[1,2,3], [4,5,6], [7,8,9], [10,11,12]])
var Y = tf.tensor([[0,0,0],[0,0,0], [1,1,1]])
var m = X.shape[0]
var a0 = tf.zeros([1,3])
var y_hat = tf.zeros([1,3])
var parameters = {
"Wax": tf.randomUniform([1,3]),
"Waa": tf.randomUniform([3,3]),
"ba": tf.zeros([1,3]),
"Wya": tf.randomUniform([3,3]),
"by": tf.zeros([1,3])
}
function RNN_cell_Foward(xt, a_prev, parameters){
var Wax = parameters["Wax"]
var Waa = parameters["Waa"]
var ba = parameters["ba"]
var a_next = tf.sigmoid(tf.add(tf.add(tf.matMul(xt, Wax), tf.matMul(a_prev , Waa)),ba))
return a_next
}
function RNN_FowardProp(X, a0, parameters){
var T_x = X.shape[0]
var a_next = a0
var i = 1
var Wya = parameters["Wya"]
var by = parameters["by"]
var l = 1
for(; i <= T_x; i++){
var X_i = X.slice([i-1,0],[1,-1])
for(; l <= X.shape[1]; l++){
var xt = X_i.slice([0,l-1],[1,1])
var a_next = RNN_cell_Foward(xt, a_next, parameters)
}
var y_pred = tf.sigmoid((tf.add(tf.matMul(a_next, Wya), by)))
l = 1
if (i == 1){
var y_pred1 = y_pred
} else if (i == 2) {
var y_pred2 = y_pred
} else if (i == 3) {
var y_pred3 = y_pred
}
}
var y_predx = tf.concat([y_pred1, y_pred2, y_pred3])
return y_predx
}
const learningRate = 0.01;
var optimizer = tf.train.sgd(learningRate);
var model = RNN_FowardProp(X, a0, parameters)
var loss = tf.losses.meanSquaredError(Y, model)
for (let f = 0; f < 10; f++) {
optimizer.minimize(loss)
}
This is a neural network for sentiment classification which has a many to one structure.
The error says it all:
The f passed in variableGrads(f) must be a function
optimizer.minimize is expecting a function as parameter and not a tensor. Since the code is trying to minimize the meanSquaredError, the argument of minimize can be a function that computes the meanSquaredError between the predicted value and the expected one.
const loss = (pred, label) => pred.sub(label).square().mean();
for (let f = 0; f < 10; f++) {
optimizer.minimize(() => tf.losses.meanSquaredError(Y, model))
}
Does it solve the issue, not completely yet ? The error will change for something like:
variableGrads() expects at least one of the input variables to be trainable
What does it mean ? When the optimizer is used, it expects the function passed as argument to contains variables whose values will be updated to minimize the function output.
Here is the changes to be made:
var Y = tf.tensor([[0,0,0],[0,0,0], [1,1,1]]).variable() // a variable instead
// var loss = tf.losses.meanSquaredError(Y, model)
// computed below in the minimize function
const learningRate = 0.01;
var optimizer = tf.train.sgd(learningRate);
var model = RNN_FowardProp(X, a0, parameters);
const loss = (pred, label) => pred.sub(label).square().mean();
for (let f = 0; f < 10; f++) {
optimizer.minimize(() => tf.losses.meanSquaredError(Y, model))
}

I am trying to convert a dynamic formula in Javascript

this is not a regular JS tasks as I need help with JS and maths little bit. I got the math formula done but now I'm trying to get it in javascript.
I writing a calculator so I got var a,b,c and D.
D is the sum of A,B,C (Currently it is 825)
I changed the D from 825 to 600 so everything should reduce propotionaly but not B. B should stay as it is and A and C should reduce.
The following code below calculate correctly but I want to make it dynamic fully. Var newA and newC I can't seem to get the right variable in it as I need the newA to dive by 6 and New C to divide by 5/6.
Is there any genius good in math and javascript?
I also attached an image of the math formula if anyone can maybe write a better JS.
The idea is if that I can after add more variables and when I reduce the D it will let me know how much are the elements that can be reduced.
Here is the code:
// Variables
var a = 100;
var b = 225; // this variable does not change.
var c = 500;
// Container sum
var containerSum = a + b + c ;
// New container sum
var newContainerSum = 600;
// 825 - (100 + 500) = 225
var fixedElement = b;
// 600 - 225 = 375
var remainingElementsTotal = newContainerSum - fixedElement;
//Propotion calculate 100/500 = 1/5 = 0.2
var propotions = a/c;
var remainingPropotions = 1 - propotions;
var newA = remainingElementsTotal/6;
var newC = remainingElementsTotal * (5/6);
Here is a general function that takes the original array of values (vals), the index of the fixed value (fixedIndex), and the new sum (newSum); and returns a new array with suitably modified values:
function calc(vals, fixedIndex, newSum) {
var initSum = vals.reduce(function (prev, cur) {return prev + cur;}, 0);
var fixedElement = vals[fixedIndex];
var initRemainingSum = initSum - fixedElement;
var endRemainingSum = newSum - fixedElement;
return vals.map(function(cur, index) {return index === fixedIndex ? cur : endRemainingSum*(cur/initRemainingSum);})
}
For example:
calc([100, 225, 500], 1, 600)
returns:
[ 62.5, 225, 312.5 ]
[EDITED]
To answer your follow-on question in the comments, if you want to specify an array of fixed indices (fixedIndices), this should work:
function calc2(vals, fixedIndices, newSum) {
var initSum = vals.reduce(function (prev, cur) {return prev + cur;}, 0);
var fixedSum = fixedIndices.reduce(function (prev, cur, index) {return prev + vals[cur];}, 0);
var initRemainingSum = initSum - fixedSum;
var endRemainingSum = newSum - fixedSum;
return vals.map(function(cur, index) {return fixedIndices.indexOf(index) === -1 ? endRemainingSum*(cur/initRemainingSum) : cur;})
}
For example:
calc2([100, 225, 500], [1,2], 600)
returns:
[ -125, 225, 500 ]
I believe this is what you seeking for.
var elements = [100, 300, 225, 560, 900],newElements=[];
var containerSum = elements.reduce(function(prev, cur) {
return prev + cur;
});
var newContainerSum = 1500;
var indexToBeFixed = 1;
var remainingElementsTotal = newContainerSum - elements[indexToBeFixed];
for (var i = 0; i < elements.length; i++) {
newElements.push(i !== indexToBeFixed?(elements[i] * remainingElementsTotal) / (containerSum - elements[indexToBeFixed]):elements[i] );
}
console.log(newElements);
/*
[ 67.22689075630252,
300,
151.26050420168067,
376.47058823529414,
605.0420168067227 ]
*/
Update
elements array will be modified.

limit the query exactly with 8 and 7 digits in javascript

i have a little question:
how i can limit or generate the result of a query in 7 or 8 digits
example:
var x = 3143284294
var y = 387520525892
var z = -7632489234892
var w = 34563
result:
var x = 3143284
var y = 3875205
var z = -763248
var w = 3456300 (fill whit "0")
What function or prefix in javascript will use?
tnks(and sorry for my english)
This converts the number to a string and performs string operations on it. Note that repeat is a fairly recent feature of ECMAScript.
function cutNum(n, limit) {
n = n + '';
n = n.substr(0, limit);
if (n.length < limit) {
n = n + '0'.repeat(limit - n.length);
}
return parseInt(n, 10);
}
var x = 3143284294;
cutNum(x, 7); // 3143284
var z = -7632489234892;
cutNum(z, 7); // -763248
var w = 34563;
cutNum(w, 7); // 3456300
Take a look at the slice() method.
var numbers = "01234567890";
var res = numbers.slice(0,6);
alert(res);
Since your sample also includes that are less than 7 digits, you will want to run a logic check first prior to the slice.
var x = "01"
if(x.length < 7)
x = x + "0000000";
x = x.slice(0,6);
alert(x);

Multi-dimensional Javascript open array

I have difficulty with assigning and retrieving the values of elements in the open array, the array size and dimensions are not fixed so its due to expand or shrink during the iteration. I declare the array as var NODES[[]]; trying to assign, retrieving values and obtaining the length of any dimension in array results wrong values. Especially with the var le = NODES[0].length ; code I 'd expect to see the total length of first dimension.
var NODES =[[]]
scene = editor.scene;
scene.traverse( function(e) {
if ( (e instanceof THREE.Line) && (e.name = 'main line' ) )
{
for (i=0; i<e.geometry.vertices.length; i++){
var x = e.position.x+ e.geometry.vertices[i].x
var y = e.position.y+ e.geometry.vertices[i].y
var z = e.position.z+ e.geometry.vertices[i].z
NODES[node_cnt,0] = x;
NODES[node_cnt,1] = y;
NODES[node_cnt,2] = z;
node_cnt++;
}
cnt++;
};
var le = NODES[0].length ;
EXPECTED RESULT
NODES[0][0] = 10; NODES[0][1] = 20; NODES[0][3] = 30;
NODES[1][0] = 40; NODES[1][1] = 50; NODES[1][3] = 60;
NODES[2][0] = 70; NODES[2][1] = 80; NODES[2][3] = 90;
with `var le = NODES[0].length ;` I expect to see 3 because I'm requesting the length of 1st dimension
This is the javascript interpretation of multi dimensional array, NODES is an array which contains actually 3 array, every array contained in NODES contain a string:
var NODES = [[],[],[]];
for (var i = 0; i < 10 ; i++) {
NODES[0].push(i + 'x');
NODES[1].push(i + 'y');
NODES[2].push(i + 'z');
}
console.log(NODES[0].lenght);
If every contained array should contain one another array the sintax to do this should be:
NODES[0].push([i + 'x']);
Sorry, I'm not understand clearly what mean node_cnt and cnt, but I think you should do something like this:
var NODES =[[],[],[]]
scene = editor.scene;
scene.traverse( function(e) {
if ( (e instanceof THREE.Line) && (e.name = 'main line' ) )
{
for (i=0; i<e.geometry.vertices.length; i++){
var x = e.position.x+ e.geometry.vertices[i].x
var y = e.position.y+ e.geometry.vertices[i].y
var z = e.position.z+ e.geometry.vertices[i].z
NODES[0].push(x);
NODES[1].push(y);
NODES[2].push(z);
node_cnt++;
}
cnt++;
};
var le = NODES[0].length ;

Categories