es6-fuzz icon indicating copy to clipboard operation
es6-fuzz copied to clipboard

Wrong evaluation at limit of trapezoid

Open skanderturki opened this issue 2 years ago • 7 comments

Hi, I am trying to use this library, the fuzzification is quite clear but the defuzzification step is not clear to me using this library, anyways, I have this code that gives a wrong evaluation at the upper limit of a trapezoid, It seems to come from this library not from boon-js:

I have this function with two input fuzzy variables (likelihood and impact), the fifth evaluator function is the one that returns True when the input is assess(5, 10), while 10 as a value for impact should trigger the seventh evaluator to return true (securityTest_moderate_restricted ) and this should lead to have the function an output of "high", I tried to slightly modify the trapezoid declaration to make it work by cheating a little bit and pushing the last point of the trapezoid to 11: const restrictedImpact = new fuzzy.Trapezoid(7.5, 8.5, 10, 11); And this gave me a correct result, which makes me think that there is a problem at the higher limit of the trapezoid.

Thanks,

This is the function:

const assess = (likelihood, impact) => {
  var logicLikelihood = new fuzzy.Logic();
  const lowLikelihood = new fuzzy.Trapezoid(0, 0, 2, 3);
  const moderateLikelihood = new fuzzy.Trapezoid(2, 3, 7, 8);
  const highLikelihood = new fuzzy.Trapezoid(7, 8, 10, 10);

  logicLikelihood.init('low', lowLikelihood)
  logicLikelihood.or('moderate', moderateLikelihood)
  logicLikelihood.or('high', highLikelihood);

  var logicImpact = new fuzzy.Logic();
  const publicImpact = new fuzzy.Trapezoid(0, 0, 1.5, 2.5);
  const internalImpact = new fuzzy.Trapezoid(1.5, 2.5, 4.5, 5.5);
  const confidentialImpact = new fuzzy.Trapezoid(4.5, 5.5, 7.5, 8.5);
  const restrictedImpact = new fuzzy.Trapezoid(7.5, 8.5, 10, 10);

  logicImpact.init('public', publicImpact)
  logicImpact.or('internal', internalImpact)
  logicImpact.or('confidential', confidentialImpact);
  logicImpact.or('restricted', restrictedImpact);

  const tests = [];
    // assessment very low
  const securityTest_low_public = boon.getEvaluator('likelihood.low AND impact.public');
  tests.push(securityTest_low_public);
    // assessment low
  const securityTest_low_internal = boon.getEvaluator('likelihood.low AND impact.internal');
  tests.push(securityTest_low_internal);
    // assessment medium
  const securityTest_low_confidential = boon.getEvaluator('likelihood.low AND impact.confidential');
  tests.push(securityTest_low_confidential);
    // assessment high
  const securityTest_low_restricted = boon.getEvaluator('likelihood.low AND impact.restricted');
  tests.push(securityTest_low_restricted);
    // assessment low
  const securityTest_moderate_public = boon.getEvaluator('likelihood.moderate AND impact.public');
  tests.push(securityTest_moderate_public);
    // assessment medium
  const securityTest_moderate_internal = boon.getEvaluator('likelihood.moderate AND impact.internal');
  tests.push(securityTest_moderate_internal);
    // assessment high
  const securityTest_moderate_confidential = boon.getEvaluator('likelihood.moderate AND impact.confidential');
  tests.push(securityTest_moderate_confidential);
    // assessment very high
  const securityTest_moderate_restricted = boon.getEvaluator('likelihood.moderate AND impact.restricted');
  tests.push(securityTest_moderate_restricted);
    // assessment low
  const securityTest_high_public = boon.getEvaluator('likelihood.high AND impact.public');
  tests.push(securityTest_high_public);
    // assessment medium
  const securityTest_high_internal = boon.getEvaluator('likelihood.high AND impact.internal');
  tests.push(securityTest_high_internal);
    // assessment high
  const securityTest_high_confidential = boon.getEvaluator('likelihood.high AND impact.confidential');
  tests.push(securityTest_high_confidential);
    // assessment very high
  const securityTest_high_restricted = boon.getEvaluator('likelihood.high AND impact.restricted');
  tests.push(securityTest_high_restricted);

  const resLikelihood = logicLikelihood.defuzzify(likelihood, 'likelihood');
  const resImpact = logicImpact.defuzzify(impact, 'impact');

  const jsBoonInput = { ...resLikelihood.boonJsInputs, ...resImpact.boonJsInputs }

  const results = [];
  for(let i = 0; i < tests.length; i++){
    results.push( tests[i](jsBoonInput) );
  }

  if(results[0]) return "very low";
  else if(results[1]) return "low";
  else if(results[2]) return "medium";
  else if(results[3]) return "high";
  else if(results[4]) return "low";
  else if(results[5]) return "medium";
  else if(results[6]) return "high";
  else if(results[7]) return "high";
  else if(results[8]) return "low";
  else if(results[9]) return "medium";
  else if(results[10]) return "high";
  else if(results[11]) return "very high";
  else return "Unknown";
}

skanderturki avatar Jan 16 '23 12:01 skanderturki

Hi

I will investigate this as soon as possible. Sorry for the inconvenience. As for the unclear defuzz step: please tell me more why it is unclear.

sebs avatar Jan 17 '23 07:01 sebs

you are right about the right corner. But it is kind of connected to the fact that this is a special trapezoid on the side: the last two X coordinates are the same. Since these are the outer limits, you can always choose (7, 8, 10, 11) and (7.5, 8.5, 10, 11) to get the result from a trapezoid you want in your case

Another working solution would be to use a triangle as outer bound or stacking 2 triangles here. it is basically what you want to express here.

looking at trapezoid edge cases I am thinking I missed those as the whole api is a very very basic implementation.

sebs avatar Jan 17 '23 22:01 sebs

Thanks a lot for this explanation, I used the trapezoid with 10.1 coordinate and I am having a working solution, I will try the triangle solution also.

Instead of the code that I posted above, I have developed a class that would make the code much cleaner, I can send you the code and maybe if you like it, I can contribute it to your nice framework so that the user can concentrate only on the rules. ([email protected])

Thanks

skanderturki avatar Jan 18 '23 15:01 skanderturki

fork it and contribute back .... we can talk about any proposal. Maybe start small and then get bigger.

I think I will have to talk to someone who actually saw a university from inside and enjoyed maths (looking at your cv this might be you) if I can pick the 1 in our case (and what to do with the other trapezoid forms).

sebs avatar Jan 18 '23 17:01 sebs

will keep this open until I have at least added a explanation and documentation.

sebs avatar Jan 18 '23 17:01 sebs

I will fork it as you said, and show you the "small" contribution, it is a simple way to associate rules to evaluations to outputs (3-tuples of { rule, evaluation, output } ) + a batch evaluation loop that would fill the evaluation member, which makes the client code much shorter than the one I have added above. Regarding the math issue, I do not remember much about my "logique floue" course (fuzzy logic in french) I took a long time ago, but we'll see as I need it currently for this small project....

skanderturki avatar Jan 19 '23 05:01 skanderturki

This comment from @JK-0 came to email from [email protected]. It's also not the first spam email I've received recently. Most are for crypto nonsense, others are for repos I've never interacted with or seen. If I unsubscribe from [email protected] I assume I'll miss out on real and needed emails. Has anyone else experienced this before?

sturgeonphillip avatar Feb 23 '24 17:02 sturgeonphillip