// FILE. . . . . d:/hak/hlt/src/hlt/math/fuzzy/FuzzyAlgebra.java
// EDIT BY . . . Hassan Ait-Kaci
// ON MACHINE. . Hp-Zbook
// STARTED ON. . Sun May  6 08:23:47 2018

package hlt.math.fuzzy;

/**
 * This class provides definitions for two dual fuzzy operations
 * <tt>sup</tt> (<tt>&or;</tt>) and <tt>inf</tt> (<tt>&and;</tt>) on a
 * pair of fuzzy values <tt>a</tt> and <tt>b</tt>. The arguments and the
 * value returned are of type <tt>double</tt>, but if the arguments are
 * in <tt>[0,1]</tt>, then so is the value returned. However, the
 * arguments' values are not checked. Unless redefined otherwise, these
 * operations default respectively to <tt>Math.max</tt> and
 * <tt>Math.min</tt>; <i>i.e.</i>,
 *
 * <ul>
 * <li><tt>a &or; b = Math.max(a,b)</tt></li>
 * <li><tt>a &and; b = Math.min(a,b)</tt></li>
 * </ul>
 *
 * But this class also defines two other dual pairs of fuzzy operations:
 * <tt>product</tt> (or <tt>probabilistic</tt>); <i>i.e.</i>,
 *
 * <ul>
 * <li><tt>a &or; b = a + b - a*b</tt></li>
 * <li><tt>a &and; b = a*b</tt></li>
 * </ul>
 *
 * and <tt>lukasievicz</tt> (or <tt>luka</tt>); <i>i.e.</i>,
 *
 * <ul>
 * <li><tt>a &or; b = Math.min(a+b,1)</tt></li>
 * <li><tt>a &and; b = Math.max(0,a+b-1)</tt></li>
 * </ul>
 *
 * which can be set with the method <tt>setFuzzyAlgebra(String)</tt>
 * with argument <tt>"maxmin"</tt> (the default), <tt>"product"</tt>, or
 * "<tt>luka</tt>".
 *
 * @see         FuzzyMatrix
 *
 * @version     Last modified on Thu Mar 28 11:53:46 2019 by hak
 * @author      <a href="mailto:hak@acm.org">Hassan A&iuml;t-Kaci</a>
 * @copyright   &copy; <a href="http://www.hassan-ait-kaci.net/">by the author</a>
 */
public class FuzzyAlgebra implements FuzzyOperations
{
  static private final int maxmin = 0;
  static private final int product = 1;
  static private final int luka = 2;

  static private int fuzzyAlgebra = maxmin;

  /**
   * Sets the current fuzzy algebra to the one corresponding to the
   * given string. If no known fuzzy algebra corresponds to the
   * string, this sets it to max/min and issues a warning.
   */
  static public void setFuzzyAlgebra (String algebra)
  {
    fuzzyAlgebra = algebraKind(algebra);
    System.out.println("Current fuzzy algebra set to: "+stringForm(fuzzyAlgebra));
  }

  static private String stringForm (int algebra)
  {
    switch (algebra)
      {
      case maxmin:
	return "Max/Min";
      case product:
	return "Product (Probabilistic)";
      case luka:
	return "Lukasiewicz";
      }
    return "Max/Min";
  }

  /**
   * Returns an <tt>int</tt> identifying the fuzzy algebra corresponding
   * to the given <tt>kind</tt> string.
   */
  static private int algebraKind (String kind)
  {
    switch (kind)
      {
      case "MaxMin": case "maxmin":
      case "MinMax": case "minmax":
      case "Default": case "default":
  	return maxmin;
      case "Probabilistic": case "probabilistic":
      case "Product": case "product":
  	return product;
      case "Luka": case "luka":
      case "Lukasiewicz": case "lukasiewicz":
  	return luka;
      default:
  	System.err.println("Warning! Unsupported fuzzy algebra: " + kind + "; using default (\"MaxMin\")");
      }
    return maxmin;   
  }

  /**
   * Returns the supremum of the arguments in the current fuzzy algebra.
   */
  public double sup (double left, double right)
  {
    switch (fuzzyAlgebra)
      {
      case product:
	return left + right - left*right;
      case luka:
	return Math.min(left+right,1);
      }

    return Math.max(left,right);	
  }

  /**
   * Returns the infimum of the arguments in the current fuzzy algebra.
   */
  public double inf (double left, double right)
  {
    switch (fuzzyAlgebra)
      {
      case product:
	return left*right;
      case luka:
	return Math.max(0,left+right-1);
      }

    return Math.min(left,right);	
  }

}
