1

let's say I have a class Part with 3 properties x,y,z:

class Part {
 constructor(x, y, z) {
    this.x = x
    this.y = y
    this.z = z
  }

  createNewFromParts(...parts){

  }
}

I want that the createNewFromParts function that will get x parts and will find a constant number for each part to duplicate his properties with, so after all of the parts will be duplicated, the sum of each property value from all of the parts will the closest to the original part property. I also want to log the percentage of success. The percentage of success will be calculated by all of the 3 properties together regard to the previous values, not by individuals.

for example :

const whole = new Part(4,6,10);
const part1 = new Part(1,2,4);
const part2 = new Part(2,2,3);

in this example this is easy: multiply part1 in 1 and part2 in 2 and it the result of the addition will be (5,6,10) which is probebly the best match.

Lets say There will be something like this:

const whole = new Part(32,10,27);
const part1 = new Part(10,7,15);
const part2 = new Part(15,5,22);

How will I found the constants to duplicate each part to get the best match?

I want to findan algorithm that will find a constant for each part to duplicate with to get the best match which is the closest to the original.

Appriciate the help :)

jo_va
  • 13,504
  • 3
  • 23
  • 47
Tal
  • 613
  • 1
  • 7
  • 19
  • 1
    If you search on the phrase "linear programming with constraints", you’ll find resources that can explain it much better than we can in an answer here. – Prune Mar 20 '19 at 21:24
  • What @Prune said: this is a classical linear optimisation problem. The [simplex algorithm](https://en.wikipedia.org/wiki/Simplex_algorithm) will be able to solve it. – Bergi Mar 20 '19 at 21:40

1 Answers1

2

Here is a Least Squares approach, which is only one of many ways to solve the problem

If you consider each of your parts as a vector with 3 elements, e.g part 1 would be:

enter image description here

Then you can write a linear system that relates the parts P to the whole part Y through a vector of coefficients A:

enter image description here

You can then find the vector of coefficients A that minimizes the sum of squared residuals:

enter image description here

The sum of squared residuals r is the sum of the squared differences between your whole part Y and the 'best' estimated part enter image description here where the hat means 'estimated'.

The solution to this squared residuals minimization problem are the estimated coefficients obtained with this equation:

enter image description here

Once you have an estimate of the coefficients, you can then calculate the Mean Absoute Percentage Error (MAPE) like this:

enter image description here

Here is an implementation using math.js that works with any number of parts.

function findCoeffs(Y, parts) {
  const P = math.transpose(parts);
  const Pt = parts;
  const PtPinv = math.inv(math.multiply(Pt, P));
  const PtPinvPt = math.multiply(PtPinv, Pt);
  return math.multiply(PtPinvPt, Y);
}

function test(Y, ...parts) {
  const coeffs = findCoeffs(Y, parts);
  const round = n => +n.toFixed(2);
  const disp = ns => JSON.stringify(ns.map(n => Array.isArray(n) ? n.map(round) : round(n)));
  const actual = math.multiply(coeffs, parts);
  const error = math.subtract(Y, actual);
  const errorPercent = error.map((e, i) => Math.abs(e / actual[i]));
  const totalErrorPercent = errorPercent.reduce((sum, e) => sum + e, 0) * 100 / coeffs.length;
  console.log('--------------------------');
  console.log('expected    (Y)  ', disp(Y));
  console.log('parts       (P)  ', disp(parts));
  console.log('coeffs      (A)  ', disp(coeffs));
  console.log('actual      (PA) ', disp(actual));
  console.log('coeff error      ', disp(errorPercent));
  console.log('mean error (MAPE)', round(totalErrorPercent) + '%');
}

test([4, 6, 10], [1, 2, 4], [2, 2, 3]);
test([32, 10, 27], [10, 7, 15], [15, 5, 22]);
test([3.2, 3, 5], [1.1, 1, 1], [1.1, 2, 3], [1, -1, 1]);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script language="JavaScript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/5.8.0/math.min.js"></script>
jo_va
  • 13,504
  • 3
  • 23
  • 47