0

I have a system of resistors, something like this: Resistor schematic

I made a website which renders diagrams like this one (not this one exactly). The user can change resistance of each resistor. I want to calculate every current in the system.

I found a solution using Kirchhoff's laws, which gave me a system of linear equations. I solved it with math.js using inverse matrix. This approach worked well on smaller circuits.

In this circuit, i have more equations, than variables, which means that I cannot compute inverse matrix, to solve them. Simplifying them manually, to match the number of unknowns is an option, but that would require a human. The website should be able to calculate everything on its own.

Now I am looking for a way to solve a system of linear equations, which cannot be represented as a square matrix. Any suggestions?

Thanx!

Edit:

My current approach looks like this.

let R1 = 3;
let R2 = 10;
let R3 = 3;
let R4 = 2;
let R5 = 4;
let R6 = 4;
let V1 = 5;

let I1 = 0;
let I2 = 0;
let I3 = 0;
let I4 = 0;
let I5 = 0;
let I6 = 0;

const matrix = [
  [-1, 1, 1, 0, 0, 0],
  [1, -1, 0, 0, 0, -1],
  [0, 0, -1, 1, 1, 0],
  [0, -R2, 0, 0, 0, 0],
  [0, 0, 0, -R6, -R5, 0],
  [0, 0, -R1, -R6, 0, -(R3 + R4)]
];
const result = [0, 0, 0, -V1, 0, -V1];

const inverse = math.inv(matrix);
const currents = math.multiply(inverse, result);

console.log(currents);
[I1, I2, I3, I4, I5, I6] = currents;
<script src="https://cdn.jsdelivr.net/npm/mathjs@9.4.4/lib/browser/math.min.js"></script>

The issue is that in this example, I get wrong solution. I narrowed it down to missing conditions (equations).

I have 6 currents, which means I can have only 6 equations to be able to calculate inverse matrix... But in this case and many others that I have, 6 equations are not enough.

The issue is that I need a computer to make sense out of that. Not a human. So, I need to find a way to solve this kind of problem for 6 variables, but with more than 6 equations.

  • Hi Juraj, I think if you took some time to provide some of your own attempts (in the code), what research you've done, and your current approach to solving this and reframed your question for improvement suggestions rather than 'how do I do this?' - you'd get better results. I have to agree with Jeremy's comment. – AlexanderGriffin Jul 10 '21 at 15:05

3 Answers3

1

You can solve a matrix using LU decomposition if the number of equations and unknowns are equal.

You use least squares if the number of equations is more than the number of unknowns.

You use singular value decomposition if the number of equations is less than the number of unknowns.

Here is an example of how it's done using R. I'm sure Python, JAMA, and other libraries have SVD solvers. I don't know about Javascript.

duffymo
  • 305,152
  • 44
  • 369
  • 561
0
  • This approach makes a row reduction of the matrix, and gives as a result an string with the unknown values. In case the system has infinite resolutions, this would returns simplified equations so you can parameterize later.

EDIT : Independent terms are in the last column of the array.

let eq = [
  [1, 0, 1],
  [1, -2, 0],
  [0, 2, 1]
];

console.log(rowReduction());

function rowReduction() {
  for (let columnIndex = 0; columnIndex < eq[0].length; columnIndex++) {
    if (columnIndex < eq.length) {
      let rowCheck = 0;
      while (isEqual(eq[columnIndex][columnIndex], 0) && rowCheck < eq.length) {
        if (rowCheck !== columnIndex) {
          eq[columnIndex] = eq[rowCheck].map((e, i) => eq[columnIndex][i] + e);
        }
        rowCheck++;
      }
    }
  }
  for (let columnIndex = 0; columnIndex < eq[0].length; columnIndex++) {
    if (columnIndex < eq.length) {
      let diagElement = eq[columnIndex][columnIndex];
      if (nonEqual(diagElement, 0)) {
        eq[columnIndex] = eq[columnIndex].map((e, i) => e / diagElement);
      }
      for (let rowIndex = 0; rowIndex < eq.length; rowIndex++) {
        if (rowIndex !== columnIndex && nonEqual(eq[rowIndex][columnIndex], 0)) {
          const opuesto = -eq[rowIndex][columnIndex];
          eq[rowIndex] = eq[columnIndex].map((e, i) => eq[rowIndex][i] + opuesto * e);
        }
      }
    }
  }
  let compatible = true;
  for (let f = 0; f < eq.length; f++) {
    let nulo = true;
    for (let c = 0; c < eq[f].length - 1; c++) {
      if (nonEqual(eq[f][c], 0)) nulo = false;
    }
    if (nulo && nonEqual(eq[f][eq[f].length - 1], 0)) compatible = false;
  }
  return compatible ? evaluateEq() : "Incompatible system";

  function evaluateEq() {
    let str = "";
    eq.forEach(function a(row, i) {
      //avoid null rows
      if (nonEqual(row.reduce((l, n) => l + Math.abs(n), 0), 0)) {
        row.forEach(function b(e, j) {
          e = e.toFixed(3); //decimals after comma
          if (j + 1 === row.length) { //independent term
            str += " = " + e;
          } else if (nonEqual(e, 0)) {
            str += " + ";
            if (nonEqual(e, 1)) str += "(" + e + ")*";
            str += "x[" + j + "]";
          }
        });
        str += "\n";
      }
    });
    return str;
  }

  //to avoid problems due to margin error
  function isEqual(n, target) {
    return parseFloat(n).toFixed(8) == target;
  }

  function nonEqual(n, target) {
    return parseFloat(n).toFixed(8) != target;
  }
}
AlexSp3
  • 2,201
  • 2
  • 7
  • 24
  • Your solution does not seem to solve the problem. I have more equations than variables, not the other way around. Your output creates a general solution for 4 variables and 3 equations. I need the opposite. *Exact solution with 3 variables and 4 equations* – Juraj Petráš Jul 10 '21 at 20:52
  • It also works for more equations than variables – AlexSp3 Jul 10 '21 at 21:13
0

After a lot of trial and error I found out that the solve function in ml-matrix allows for more than N equations with N variables.

I also tried the approach with pseudo-inverse, but that also required the matrix to be square.