Establishing an average when counts are portioned - javascript

The problem
I have an array which is a property of the class road, which defines the allowed vehicle types on the road, and supplies an approximate portion each type contributes to traffic:
[[bus,.2],[smallCar,.6],[bigCar,.2]]
I need to calculate the average length of the cars encountered on the road, given the proportion of traffic. (This is needed to do some basic calculations elsewhere in the class.)
What I have tried:
I can't quite wrap my head around a better way to do this. In my solution, fidelity changes with an increase in car count. This seems a really slow, heavy handed approach and not right. The function to improve is named averageVehicleLaneSpace.
A very paired down but working version of much larger classes:
road = function(){};
road.prototype.averageVehicleLaneSpace = function(){
var sum = 0;
var fakeCarCount = 10000;
for( var i = 0; i< this.allowedVehicleTypes.length; i++){
var type = this.allowedVehicleTypes[i][0];
var perc = this.allowedVehicleTypes[i][1];
for(n = 0; n<=fakeCarCount*perc; n++){
sum += vehicle[type].laneSpace;
}
}
return sum/fakeCarCount;
}
//define vehicles
var vehicle = {
bus:{
laneSpace:14
},
smallCar:{
laneSpace:4
},
bigCar:{
laneSpace:4.5
}
};
var t = new road();
t.allowedVehicleTypes = [["bus",.1],["smallCar",.3],["bigCar",.6]];
alert(t.averageVehicleLaneSpace());
The Fiddle:
This Fiddle is the hopeful example above: The fiddle.

The average is the sum of the ratio * laneSpace for each vehicle type. So calculating the average is as simple as:
road.prototype.averageVehicleLaneSpace = function(){
var avg = 0;
for (var i = 0; i < this.allowedVehicleTypes.length; i++) {
var type = this.allowedVehicleTypes[i][0];
var perc = this.allowedVehicleTypes[i][1];
avg += perc * vehicle[type].laneSpace;
}
return avg;
}

Related

Weighted Interpolation using means of circular quantities

I am woking on a project of weighted interpolation. Each station has a coordinate point on the map as shown below.
var stationCoor = [[408,352],[525,348],[535,495],[420,400],[272,145],[175,195],[197,335]];
I am taking points that are located in the lake and I am using those to create weighted averages for inputs from those stations. Here is my function for determining the weighted numbers.
function findWeightSpeed(xPos, yPos){
var totalHypt = 0;
var arrHpyt = [];
var arrWeight = [];
for(var l=0;l<7;l++){
var xDis = Math.abs(xPos-stationCoor[l][0]);
var yDis = Math.abs(yPos-stationCoor[l][1]);
var hptSq = Math.pow(xDis,2)+Math.pow(yDis,2);
var hypt = Math.sqrt(hptSq);
totalHypt = totalHypt+hypt;
arrHpyt.push(hypt);
}
for(var j=0;j<7;j++){
arrWeight.push(arrHpyt[j]/totalHypt)
}
return arrWeight;
}
This finds the hypotenuse between the point (xPos,yPos) and the stations. It then adds the data up and divides each station by the total yielding the weighted numbers.
I need to use these points to weight wind direction from these stations. I was using the funciotn below to calculate an average of points.
function averageAngles(){
var x = 0;
var y = 0;
var pi = 22/7;
var angle = [2.7925,2.8797,2.9670,3.0543, 0.0872]; // 310,320,330,340,10
for(var i = 0; i < angle.length; i++) {
x += Math.cos(angle[i]);
y += Math.sin(angle[i]);
}
var average_angle = Math.atan2(y, x);
console.log((average_angle/pi)*360);
}
This gave me accurate information for a weighted average of .20 for all points. However, the weighted average points for the 7 stations (as seen below on the map) is similar to [0.1076839005418769, 0.08051796093187284, 0.003987308213631277, 0.08458358029618485, 0.2463427297217639, 0.26463834002675196, 0.21224618026791833].
How would I go about making a function that takes the weighted average numbers from the findWeightSpeed() and using that to weight the circular quantities in averageAngles()?
I used this How do you calculate the average of a set of circular data? to make the function for averaging angles.
Many thanks for any suggestions given.
Here is a link I found online that explains the entire procedure.
Computing Weighted Averages for Wind Speed and Direction
The code is similar to this.
function weightAllData(xPos,yPos,windData){
var uVecSum = 0;
var vVecSum = 0;
var arrayWeightSpeed = findWeightSpeed(xPos, yPos); //using weighted interpolation based on distance
var arrayWindSpeed = [WSData];
var arrayWindDirection = [WDData];
for(var m=0;m<7;m++){
uVecSum = uVecSum + (arrayWeightSpeed[m] * getUVector(arrayWindSpeed[m],(arrayWindDirection[m]/180)*Math.PI));
vVecSum = vVecSum + (arrayWeightSpeed[m] * getVVector(arrayWindSpeed[m],(arrayWindDirection[m]/180)*Math.PI));
}
var weightWS = Math.sqrt(Math.pow(uVecSum,2)+Math.pow(vVecSum,2));
if(vVecSum!=0){
weightWDRad = Math.atan(uVecSum/vVecSum);
}
if(vVecSum==0){
weightWDRad = Math.atan(uVecSum/(0.0001+vVecSum));
}
if(weightWDRad<0){
weightWDRad = weightWDRad + Math.PI
}
weightWD = (weightWDRad * (180/Math.PI));
}
Let me know if you want an explanation

Is this a neural network

I've spent the last 2 days watching youtube videos on neural networks.
In particular, I've been trying to implement a genetic algorithm that will evolve over time, however, most videos seem to be focused on neural networks that are trained, and then used for classification.
Being confused, I decided to simply try to implement the basic structure of the network, and have coded this - in JS, for convenience.
function sigmoid (x) { return 1 / (1 + Math.E ** -x); }
function Brain(inputs, hiddens, outputs) {
this.weights = {
hidden: [],
output: []
};
for (var i = hiddens; i--;) {
this.weights.hidden[i] = [];
for (var w = inputs; w--;) this.weights.hidden[i].push(Math.random());
}
for (var i = outputs; i--;) {
this.weights.output[i] = [];
for (var w = hiddens; w--;) this.weights.output[i].push(Math.random());
}
}
Brain.prototype.compute = function(inputs) {
var hiddenInputs = [];
for (var i = this.weights.hidden.length; i--;) {
var dot = 0;
for (var w = inputs.length; w--;) dot += inputs[w] * this.weights.hidden[i][w];
hiddenInputs[i] = sigmoid(dot);
}
var outputs = [];
for (var i = this.weights.output.length; i--;) {
var dot = 0;
for (var w = this.weights.hidden.length; w--;) dot += hiddenInputs[w] * this.weights.output[i][w];
outputs[i] = sigmoid(dot);
}
return outputs;
}
var brain = new Brain(1,2,1);
brain.compute([1]);
I successfully get values between 0 and 1. And, when I use specific weights, I get the same value each time, for a constant input.
Is the terminology I'm using in code good?
I fear I may simply be observing false positives, and am not actually feeding forward.
Is the sigmoid function appropriately? Should I be using it for a genetic / evolving algorithm?
I noticed that I'm getting results only between 0.5 and 1;
To combine a neural network with a genetic algorithm your best shot is probably NEAT. There is a very good implementation of this algorithm in JS called 'Neataptic', you should be able to fint it on github.
When combining GA with ANN you generally want to not only adjust the weights, but the structure as well.
Sigmoid activation is OK for GA, but in many cases you also want other activation functions, you can find a small list of activation functions on wikipedia or create your own ones.

How could I correctly total the points?

I am javascript learner struggling to design a small javascript game for my kids (5 to 10 years old) in which points are based on time elapsed. But, I cannot figure out a way to total the points. I have managed the code below but the result is not accurate. Probably the program is totalling all the items in array with each click. Can anybody help please? I am a newbie and there will be many mistakes or absurdities in here, I request you to be helpful politely while correcting me. Any help is appreciated..
document.getElementById("box1").onclick = function() {
clickT = Date.now();
reactT = (clickT - createdT) / 1000; //gets the time difference for reaction.
points = reactT * 1000;
points = 2000 - points;
pRecord.push(points); //add points to array.
for (i = 0; i < pRecord.length; i++) {
totalpoints += pRecord[i];
}
document.getElementById("time").innerHTML = reactT;
this.style.display = "none";
document.getElementById("score").innerHTML = totalpoints;
}
Just set totalpoints to zero before you sum the points:
document.getElementById("box1").onclick = function() {
var clickT = Date.now();
var reactT = (clickT - createdT) / 1000; //gets the time difference for reaction.
var points = reactT * 1000;
points = 2000 - points;
pRecord.push(points); //add points to array.
var totalpoints = 0;
for (var i = 0; i < pRecord.length; i++){
totalpoints += pRecord[i];
}
document.getElementById("time").innerHTML = reactT;
this.style.display = "none";
document.getElementById("score").innerHTML = totalpoints;
}
And also I don't know if you defined your variables in the outer scope, but I guess you did not, so I added var before every variable creation.
Here is an improved version of your code that also properly registers the reaction times, capping the maximum allowed reaction time to a configured value.
In your original implementation you could get bad readings if the reaction time was greater than 2 seconds.
Also, in your original code, you don`t need to divide by 1000 and then multiply back, since you end up with milliseconds anyway.
This is it:
document.getElementById("box1").addEventListener("click", function() {
clickT = Date.now();
// Gets the time difference in milliseconds for reaction.
reactT = clickT - createdT;
// Maximum allowed reaction time after which we give no more points.
var maxPoints = 2000;
// We cap the registered reaction time to the maximum allowed.
points = Math.max(reactT, maxPoints);
// We score the reaction time based
points = maxPoints - points;
// Add points to array.
pRecord.push(points);
// Compute the total points.
var totalpoints = 0;
for (i = 0; i < pRecord.length; i++){
totalpoints += pRecord[i];
}
document.getElementById("time").innerHTML = reactT;
this.style.display = "none";
document.getElementById("score").innerHTML = totalpoints;
}
You can notice that I have defined the totalpoints variable (and initialized it with 0), as otherwise, at each click, all your scores were re-added, not just the last one.
I have made the assumption that totalpoints was not already defined before the code you have pasted. Should this assumption be wrong and you have already initialized totalpoints before, in your code, then you need to replace the following piece from my code:
// Compute the total points.
var totalpoints = 0;
for (i = 0; i < pRecord.length; i++){
totalpoints += pRecord[i];
}
...with:
// Add the new points to the total.
totalpoints += points;

d3 how to turn a set of numbers into a larger set representative of the first set

Say I have array [1,2,5,18,17,8] and I want to turn that into an array of length 40 that follows the same path.
a = [1,2,5,18,17,8];
stepSize = 1 / (40 / a.length);
then i think i could do something like
steps = [];
for( var i = 0; i < 1; i+= stepSize) {
steps.push(d3.interpolate(a[0],a[1])(i));
}
and then repeat that for all the elements. My question is there a better way to do this?
I can only guess what your real problem is but I think you want to plot these values and have a smooth curve. In that case use line.interpolate() https://github.com/mbostock/d3/wiki/SVG-Shapes#line_interpolate
In case you DO know what you need and your solution works for you, take this tip:
Never iterate over stepSize. Calculate it once and multiply it with i in every loop where i goes from 0 to 40. This way you work around precision problems.
Your algorithm cleaned up, tested and working:
var a = [1,5,12,76,1,2];
var steps = 24;
var ss = (a.length-1) / (steps-1);
var result = new Array(steps);
for (var i=0; i<steps; i++) {
var progress = ss * i;
var left = Math.floor(progress);
var right = Math.ceil(progress);
var factor = progress - left;
result[i] = (1 - factor) * a[left] + (factor) * a[right];
// alternative that actually works the same:
//result[i] = d3.interpolateNumber(a[left], a[right], factor);
}
console.log(result);

Calculating a percentage, is there a more optimised way?

var q3a1 = parseInt(valueOne); //get variables
var q3a2 = parseInt(valueTwo);
var q3a3 = parseInt(valueThree);
var totalAmountThree = Math.ceil((q3a1+q3a2+q3a3) / 100)*100; //round to nearest 100
var percentOnec = ((q3a1 / totalAmountThree) * 100); //calculate percentage
var percentTwoc = ((q3a2 / totalAmountThree) * 100);
var percentThreec = ((q3a3 / totalAmountThree) * 100);
alert("1: "+percentOnec);
alert("2: "+percentTwoc);
alert("3: "+percentThreec);
Is there a better way for me to be calculating a percentage?
(Fiddle with me: http://jsfiddle.net/neuroflux/Sez3Q/)
You could optimize this by calculating the factor, needed to scale to percentage directly:
S = A+B+C
p(x)=100*x / S
so the 'factor' is 100/(A+B+C):
var total = a+b+c;
var scale = 100/total;
function pct(x) { return x*scale; }
And it can be generalized, of course, to work with an array of input values etc...
function toPctFn( values ) {
var sum = 0;
for( var i = 0; i != values.length; ++i ) { sum = sum + values[i]; }
var scale = 100/sum;
return function( x ){
return x*scale;
};
}
var inputs=[1,2,40,44,23];
var toPct=toPctFn(inputs);
for( var i = 0; i != inputs.length; ++i ) {
alert(""+i+": "+toPct(inputs[i])) ;
}
(see jsFiddle)
Also, it's quite important to postpone rounding to the displaying code. This way you don't introduce unnecessary errors in the calculation.
you're introducing rounding off errors, first on the line using Math.ceil(). If there's no reason to round off to the nearest hundred first, it's better to leave it out. It's possible to have a significant (depending on what you're calculating) disparity between the 'real' value and your calculation.

Categories

Resources