compute determinant of a matrix - javascript

I'm trying to compute determinant of a matrix in JS. I used algorithm from http://www.sanfoundry.com/java-program-compute-determinant-matrix/ but I lost my mind on the last condition. I just do not understand. Can you help me?
This is how looks like my code right now. In another function I create an empty 2d array and then copy it to det function. Next I retrieve values from html and then trying to compute determinant of a matrix. The first 2 cases are simple but I have a problem with the last one. I couldn't find working example in JS.
function det() {
var det = 0;
var array1 = array.slice();
for (i = 0; i < array1.length; i++) {
for (j = 0; j < array1[i].length; j++) {
array1[i][j] = parseInt(document.getElementById("element" + (i + 1) + (j + 1)).value, 10);
}
}
if (array1.length == 1) {
det = array1[0][0];
} else if (array1.length == 2) {
det = (array1[0][0] * array1[1][1]) - (array1[1][0] * array1[0][1]);
} else {
}
}

I may suggest my solution, based on recursive algorithm, which takes only few lines of code and, I guess, will suit most of practical applications:
const determinant = m =>
m.length == 1 ?
m[0][0] :
m.length == 2 ?
m[0][0]*m[1][1]-m[0][1]*m[1][0] :
m[0].reduce((r,e,i) =>
r+(-1)**(i+2)*e*determinant(m.slice(1).map(c =>
c.filter((_,j) => i != j))),0)
const test1 = [[3]] // 3
const test2 = [[3,-2],[7,4]] // 26
const test3 = [[1,3,7],[2,-1,4],[5,0,2]] // 81
console.log(determinant(test1))
console.log(determinant(test2))
console.log(determinant(test3))
.as-console-wrapper {min-height: 100%}

I created a Matrix class with some function for the basic operations, one of them the determinant calculation
Here we have the constructor
constructor(rows,cols) {
this.rows = rows;
this.cols = cols;
this.vals = new Array(rows*cols);
for(let i = 0; i < this.vals.length; i++) this.vals[i] = 0;
}
and here the determinant function
determinant() {
if (this.rows != this.cols ) {
console.log("Matrix must be square");
return;
}
let size = this.rows;
if (size == 1) return this.vals[0];
if (size == 2) return this.vals[0]*this.vals[3]-this.vals[1]*this.vals[2];
let sign = 1;
let result = 0;
for (let k = 0 ; k < size ; k++){
let cofactors = new Matrix(size-1,size-1);
cofactors.vals = this.vals.slice(size,size*size).filter((_,index)=>index%size!=k);
result += sign * this.vals[k] * cofactors.determinant();
sign*=(-1);
}
return result;
}

You can see definition of the determinant for square matrix here https://en.wikipedia.org/wiki/Determinant#n_.C3.97_n_matrices.
Algorithm used in http://www.sanfoundry.com/java-program-compute-determinant-matrix/ use some properties of determinat to calculate it in recursive way as sum over all permutations. In this way you get N * N! operations! It is very big even for small N.
For solving this problem you can first transform matrix to triangular with the same determinant and after that calculate determinant as product of all diagonal elements.

Related

Move an array in the place of another array

I am in the making of an apps script, that takes a specified range, divides it into subranges of 4 values each, and returns the array. It looks like this:
Code that follows that to divide it into said subranges:
function sort() {
const chunks = (range, size) =>
Array.from(
new Array(Math.ceil(range.length / size)),
(_, i) => range.slice(i * size, i * size + size)
);
let range = ranges.getValues().flat();
var array = chunks(range, 4)
}
}
}
}
Now, what I want to do with these, is that when someone removes data from one of the subranges, the ones below will go up, so that there are no gaps between the subranges. What I mean by that, is in the case of someone clearing data from, for example, the second subrange, all the ones that are below will go up.
NOTE: It is just a function that I later use in onChange(), and the ranges variable was called earlier throughout the code, and it's just a named range.
So far I've got this piece of code, but it doesn't seem to work:
for (let i = 0; i < array.length; i++) {
for (let j = 0; j < 4; j++) {
var equ = 0;
var mult = 0;
equ += array[i][j];
mult += array[i+1][j];
if (equ == 0 || "" && mult != "" && 0) {
array[i+1].copyTo(array[i], {contentsOnly:true})
}
}

How to find all possible combinations of triplets equaling a given sum in JavaScript? ('Stars and Bars' or 'Balls and Bins' problem)

I found a similar post on StackOverflow that answers the question but in Python, and I'm looking for a solution for javascript (google script editor for a google sheet).
Balls and Bins problem
How can I solve this using JavaScript?
Figured it out using nested for loops. How to output arrays of all triples which equal to sum (numSum) by interval.
The reason I used an internal is because I am using much bigger numbers to calculate these for monetary loans, so the interval lets me calculate by $100 chunk instead of each dollar of a huge sum.
function calcSum(SUM, INTERVAL) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var dataSheet = ss.getSheetByName('Data');
var sumNum = SUM/INTERVAL
var a = 0
var b = 0
var c = sumNum
var aTicker = 0
var bTicker = sumNum
var cTicker = sumNum
//Loop through all triple combinations of sumNum
for (i = 0; i < sumNum + 1; i++) {
for (j = aTicker; j < sumNum + 1; j++) {
var array = [];
array.push(a * INTERVAL, b * INTERVAL, c * INTERVAL);
dataSheet.getRange("A" + rowCounter + ":D" + rowCounter).setValues([array]);
rowCounter++;
}
if (b < bTicker) {
b++;
} else {
b = 0;
bTicker--;
}
if (c > 0){
c--;
} else {
cTicker--;
c = cTicker;
}
}
a++;
aTicker++;
}
}

Neural network in JS does not train

I am trying to create a simple neural network in javascript with 2 inputs, 3 hidden and 1 output neurons that use matrixes of neurons and weights to pass forward, and backpropagation training to solve XOR problem for example. The problem is I get weights always fading to 0 fast and as a result I thing outputs equal to sigmoid(0) 0.5 value or really close. I am using a sigmoid function for activation while finding neuron values like this:
var multyplayMatrix = (a,b) => {
if(a.length !== b.length) return "length of matrix1 !== height of matrix2 :(";
let c = [];
let temp = 0;
for(var n = 0; n < b[0].length; n++){
for(var nn = 0; nn < a.length; nn++){
temp = temp + (a[nn] * b[nn][n]);
}
//sigmoid
c.push( 1 / (1 + Math.exp(-temp)) );
temp = 0;
}
return c;
}
After finding output from training data input I compare it with training data desired output and calculate error and weights delta with this:
var getError = () => {
let predicted;
if(desiredOutput !== undefined){
predicted = net.neurons[net.neurons.length-1][0]
}else{
return console.log("desired output not defined")
}
let error = predicted - desiredOutput[0];
let weights_delta = error * (predicted * (1 - predicted));
console.log("output error weight delta = " + weights_delta)
propogateBackward(weights_delta);
};
and start backpropagating with some learning rate - My backdrop function looks like this:
var learningRate = 0.5;
var propogateBackward = (output_weights_delta) => {
for(var n = 0; n < 3; n ++ ){
net.weights[net.weights.length-(1 + n)][0] = (net.weights[net.weights.length-(1 + n)][0] - net.neurons[net.neurons.length-2][2-n]) * output_weights_delta * learningRate;
}
let neuronErrors = [];
for(var n = 0; n < 3; n ++ ){
let hiddenError = output_weights_delta * net.weights[net.weights.length-(1 + n)][0];
let hidden_weights_delta = hiddenError * (net.neurons[net.neurons.length-2][2-n] * (1 - net.neurons[net.neurons.length-2][2-n]));
neuronErrors.push(hidden_weights_delta);
}
for(var n = 0; n < 3; n++){
for(var nn = 0; nn < 2; nn++){
net.weights[net.weights.length-(4 + nn)][n] = (net.weights[net.weights.length-(4 + nn)][0] - net.neurons[net.neurons.length-3][1-nn]) * neuronErrors[n] * learningRate;
}
}
draw();
}
Im using this function and XOR dataset to make a iteration/training loop like this and just after some iterations it already coverges close to 0.5
var train = (iterations) => {
for(var it = 0; it < iterations;it++){
for(var n = 0; n < dataset.length; n++){
addInput(dataset[n].inputs);
addOutput(dataset[n].outputs);
activate();
getError();
}
}
}
After googling most similar problems are connected with weight initiation in longer/deeper neural networks but that does not help here, and I did a couple of different variants of this net all get similar result so I'm probably loose on my theory/math..but where?:(
I'm just learning stats and this can be confusing, for me so excuse me if I didn't make 2 much sense - You can check the js live implementation here: https://codepen.io/sanchopanza/pen/MWaZJJe

Iterate through all potential starting positions in Held-karp algorithm utilizing a bit-mask

I am interested in implementing the held-karp algorithm based on a C implementation found here: https://www.math.uwaterloo.ca/~bico/papers/comp_chapterDP.pdf in javascript. However, this implementation uses only a single starting position. I have tried numerous methods for moving through all starting positions (all nodes in the graph), however, because the implementation uses a bitmask as the set of visited nodes, starting positions 1 and 0 will not change through each call of the function solve because 0 & anynumber will always be 0.
function tsp_hk(dist){
let n = dist.length;
let opt = []; //array [endPoint][set] representing the optimum paths
//Initialize array values
for(let i = 0; i < n; i++){
opt[i] = [];
opt[i][1 << (i)] = dist[i][n-1];
}
function solve(set, end){
if(opt[end][set] === undefined){
let R = set & ~(1 << end);
let minv = 99999;
for (let i = 0; i < n; i++){
if(!(R & (1 << i))) continue;
let s = solve(R, i);
let v = s + dist[i][end];
if(v < minv) minv = v;
}
opt[end][set] = minv;
}
return opt[end][set];
}
let bestlen = 99999;
let N = (1 << (n-1))-1;
for(let t = 0; t < n-1; t++){
let s = solve(N,t);
let len = s + dist[t][n-1];
if(len < bestlen) bestlen = len;
}
return bestlen;
}
If the first node is node 0 and you want node 2 as your start node, then just interchange row 0 and row 2, and column 0 and column 2. Modify the adjacency matrix instead of modifying the algorithm.

Factorializing a number by creating an array and multiplying it

I am going through one of the FreeCodeCamp challenges.
" Return the factorial of the provided integer.
If the integer is represented with the letter n, a factorial is the
product of all positive integers less than or equal to n.
Factorials are often represented with the shorthand notation n!
For example: 5! = 1 * 2 * 3 * 4 * 5 = 120 "
I already know that the easiest way is to use recursion but by the moment I've discovered this fact I was already trying to solve the problem by creating an array, pushing numbers in it and multiplying them. However I got stuck on this step. I have created an array with the number of digits depending on the function factorialize argument, but I can't get the product of those digits. What did I do wrong:
function factorialize(num) {
var array = [];
var product;
for(i = 0; i<=num;i++) {
array.push(i);
for (j=0; j < array.length; j++) {
product *= array[j];
}
return product;
}
}
factorialize(5);
I think the easiest way would be to create a range and reduce that:
var n = 5;
function factorize(max) {
return [...Array(max).keys()].reduce((a,b) => a * (b + 1), 1);
}
console.log(factorize(n));
It looks like you missed a close parenthesis
function factorialize(num) {
var array = [];
var product = 1;
for(i = 0; i<=num;i++) {
array.push(i);
} //right here!!! <----
for (j=0; j < array.length; j++) {
product *= array[j];
}
return product;
}
factorialize(5);
but as stated in the comments, you should change i = 0 to i = 1 not just because it would change the final result(which it does for all num ) but because it also doesn't follow the factorial algorithm.
1) You need initial value 'product' variable
2) You should change i = 0 to 1. You multiply by 0 in the loop
3) You don't need nested loop
function factorialize(num) {
var array = [];
var product = 1;
for(var i = 1; i <= num; i++) {
array.push(i);
}
for (j=0; j < array.length; j++) {
product *= array[j];
}
return product;
}
You only need one loop for that,
from 1 to the maximum number, then you multiply them up,
just a little clean up from your code
fact variable will contain the string version of the individual numbers making up the sum
if m is 5 you'll fact will be 1*2*3*4*5
function factorialize(num) {
var product = 1;
var fact = ""
for (i = 1; i <= num; i++) {
product *= i;
fact += i + "*"
}
fact = fact.substring(0, fact.length - 1)
console.log(fact)
return product;
}
console.log(factorialize(5));

Categories

Resources