diff --git a/html/about.html b/html/about.html
index 6356580..9721c32 100644
--- a/html/about.html
+++ b/html/about.html
@@ -113,6 +113,7 @@
jFuzzyLogic provides a parameter optimization framework, allowing to learn or refine fuzzy parameters using machine learning algorithms.
diff --git a/out/artifacts/jFuzzyLogic_jar/jFuzzyLogic.jar b/out/artifacts/jFuzzyLogic_jar/jFuzzyLogic.jar
index 7887a30..685a68e 100644
Binary files a/out/artifacts/jFuzzyLogic_jar/jFuzzyLogic.jar and b/out/artifacts/jFuzzyLogic_jar/jFuzzyLogic.jar differ
diff --git a/src/main/java/net/sourceforge/jFuzzyLogic/CompileJS.java b/src/main/java/net/sourceforge/jFuzzyLogic/CompileJS.java
new file mode 100644
index 0000000..247cff5
--- /dev/null
+++ b/src/main/java/net/sourceforge/jFuzzyLogic/CompileJS.java
@@ -0,0 +1,11 @@
+package net.sourceforge.jFuzzyLogic;
+
+/**
+ * Create JS code
+ *
+ * @author marcin-szczepanski
+ */
+public interface CompileJS {
+
+ public String toStringJS();
+}
diff --git a/src/main/java/net/sourceforge/jFuzzyLogic/FIS.java b/src/main/java/net/sourceforge/jFuzzyLogic/FIS.java
index c4e8ce2..fae55c3 100644
--- a/src/main/java/net/sourceforge/jFuzzyLogic/FIS.java
+++ b/src/main/java/net/sourceforge/jFuzzyLogic/FIS.java
@@ -257,7 +257,7 @@ public class FIS extends FclObject implements Iterable, CompileCp
out.append("//--------------------------------------------------------------------------------\n");
out.append("// Code generated by jFuzzyLogic\n");
out.append("// jFuzzyLogic Version : " + JFuzzyLogic.VERSION + " \n");
- out.append("// jFuzzyLogic creted by Pablo Cingolani\n");
+ out.append("// jFuzzyLogic created by Pablo Cingolani\n");
out.append("//--------------------------------------------------------------------------------\n\n");
out.append("\n#include \n");
out.append("\n#include \n");
@@ -337,6 +337,117 @@ public class FIS extends FclObject implements Iterable, CompileCp
return out.toString();
}
+ /**
+ * Create a JS code for this FIS
+ * @return
+ */
+ @Override
+ public String toStringJS() {
+ StringBuffer out = new StringBuffer();
+
+ out.append("//--------------------------------------------------------------------------------\n");
+ out.append("// Code generated by jFuzzyLogic\n");
+ out.append("// jFuzzyLogic Version : " + JFuzzyLogic.VERSION + " \n");
+ out.append("// jFuzzyLogic created by Pablo Cingolani\n");
+ out.append("//--------------------------------------------------------------------------------\n\n");
+
+ // Sort function blocks by name
+ ArrayList fbNames = new ArrayList(functionBlocks.keySet());
+ Collections.sort(fbNames);
+
+ // Ge all activations and accumulation methods
+ HashSet raccs = new HashSet();
+ HashSet racts = new HashSet();
+ HashSet rcons = new HashSet();
+ for (String name : fbNames) {
+ FunctionBlock functionBlock = getFunctionBlock(name);
+
+ for (RuleBlock rb : functionBlock.getRuleBlocks().values()) {
+ raccs.add(rb.getRuleAccumulationMethod());
+ racts.add(rb.getRuleActivationMethod());
+ for (Rule r : rb) {
+ RuleExpression rexp = r.getAntecedents();
+ rcons.addAll(rexp.getRuleConnectionMethods());
+ }
+ }
+ }
+
+ // Show code
+ for (RuleAccumulationMethod racc : raccs)
+ out.append(racc.toStringJSFunction() + "\n");
+
+ for (RuleActivationMethod ract : racts)
+ out.append(ract.toStringJSFunction() + "\n");
+
+ for (RuleConnectionMethod rcon : rcons)
+ out.append(rcon.toStringJSFunction() + "\n");
+
+ // Iterate over each function block and append it to output string
+ for (String name : fbNames) {
+ FunctionBlock functionBlock = getFunctionBlock(name);
+ out.append(functionBlock.toStringJS());
+ }
+
+ // Main method
+ out.append("function main(");
+
+ int inV = 0;
+ for (String name : fbNames) {
+ FunctionBlock functionBlock = getFunctionBlock(name);
+ for (Variable var : functionBlock.variablesSorted()) {
+ if (var.isInput()) {
+ out.append(var.getName());
+ if (inV < (functionBlock.variablesSorted().size() - 1)) {
+ out.append(", ");
+ }
+ inV++;
+ }
+ }
+ }
+
+ String outWithMainStr = out.toString();
+ if (outWithMainStr.endsWith(", ")) {
+ outWithMainStr = outWithMainStr.substring(0, outWithMainStr.length() - 2);
+ out = new StringBuffer(outWithMainStr);
+ }
+
+ out.append(") {\n");
+
+ // Create function blocks
+ out.append("\t// Create function blocks\n");
+ for (String name : fbNames)
+ out.append("\tconst " + name + " = new FunctionBlock_" + name + "();\n");
+ out.append("\n");
+
+ // Assign values
+ out.append("\t// Parse input\n");
+ int inVar = 1;
+ for (String name : fbNames) {
+ FunctionBlock functionBlock = getFunctionBlock(name);
+ for (Variable var : functionBlock.variablesSorted()) {
+ if (var.isInput()) {
+ out.append("\t" + name + "." + var.getName() + " = " + var.getName() + ";\n");
+ inVar++;
+ }
+ }
+ }
+ out.append("\n");
+
+ // Calculate
+ out.append("\t// Calculate\n");
+ for (String name : fbNames)
+ out.append("\t" + name + ".calc();\n");
+ out.append("\n");
+
+ // Show results
+ out.append("\t// Show results\n");
+ for (String name : fbNames)
+ out.append("\t" + name + ".print();\n");
+ out.append("}");
+
+ return out.toString();
+ }
+
@Override
public String toStringFcl() {
StringBuffer out = new StringBuffer();
diff --git a/src/main/java/net/sourceforge/jFuzzyLogic/FunctionBlock.java b/src/main/java/net/sourceforge/jFuzzyLogic/FunctionBlock.java
index 827f73c..888d98d 100644
--- a/src/main/java/net/sourceforge/jFuzzyLogic/FunctionBlock.java
+++ b/src/main/java/net/sourceforge/jFuzzyLogic/FunctionBlock.java
@@ -740,6 +740,131 @@ public class FunctionBlock extends FclObject implements Iterable, Com
; //
}
+ @Override
+ public String toStringJS() {
+ StringBuffer calcMethod = new StringBuffer(); // Method calc()
+ StringBuffer constructor = new StringBuffer(); // Constructor
+ StringBuffer defuzzifyMethod = new StringBuffer(); // Method defuzzify()
+ StringBuffer fuzzifyMethod = new StringBuffer(); // Fuzzify method
+ StringBuffer membershipMethods = new StringBuffer(); // All membership functions
+ StringBuffer printMethod = new StringBuffer(); // Method print()
+ StringBuffer resetMethod = new StringBuffer(); // Method reset()
+ StringBuffer varDefuzzifiers = new StringBuffer(); // All defuzzifier variables
+ StringBuffer varsFuzzify = new StringBuffer(); // Fuzzify variables
+ StringBuffer varsIn = new StringBuffer(); // Input vars
+ StringBuffer varsOut = new StringBuffer(); // Output vars
+
+ varsIn.append("\t// VAR_INPUT\n");
+ varsOut.append("\t// VAR_OUTPUT\n");
+
+ // Methods
+ String className = "FunctionBlock_" + name;
+ calcMethod.append("\t// Calculate function block\n\tcalc() {\n\t\tthis.reset();\n\t\tthis.fuzzify();\n");
+ constructor.append("\t// Constructor\n\tconstructor() {\n");
+ defuzzifyMethod.append("\t// Defuzzify \n\tdefuzzify() {\n");
+ fuzzifyMethod.append("\t// Fuzzify all variables\n\tfuzzify() {\n");
+ membershipMethods.append("\t// Membership functions \n");
+ printMethod.append("\t// Print \n\tprint() {\n\t\tconsole.log(\"Function block " + name + ":\\n\");\n");
+ resetMethod.append("\t// Reset output\n\treset() {\n");
+
+ //---
+ // Show variables (sorted by name)
+ //---
+ for (Variable var : variablesSorted()) {
+ var.estimateUniverse();
+
+ if (!Double.isNaN(var.getDefaultValue())) constructor.append("\t\tthis." + var.getName() + " = " + var.getDefaultValue() + ";\n");
+
+ if (var.isInput()) {
+ // Add input variables
+ varsIn.append("\t" + var.getName());
+ varsIn.append(";\n");
+
+ // Add to print method
+ printMethod.append("\t\tconsole.log(\"\tInput %s: %f\\n\", \"" + var.getName() + "\" , this." + var.getName() + ");\n");
+
+ // Add fuzzyfiers
+ varsFuzzify.append("\t// FUZZIFY " + var.getName() + "\n");
+ for (LinguisticTerm linguisticTerm : var.linguisticTermsSorted()) {
+ String ltVar = var.getName() + "_" + linguisticTerm.getTermName();
+ varsFuzzify.append("\t" + ltVar + ";\n");
+ fuzzifyMethod.append("\t\tthis." + ltVar + " = this." + linguisticTerm.toStringJSMethodName(var) + "(this." + var.getName() + ");\n");
+
+ // Membership function
+ membershipMethods.append(linguisticTerm.toStringJS(var) + "\n");
+
+ // Add to print method
+ printMethod.append("\t\tconsole.log(\"\t %s: %f\\n\", \"" + ltVar + "\" , this." + ltVar + ");\n");
+ }
+ varsFuzzify.append("\n");
+
+ } else {
+ int len = ((DefuzzifierContinuous) var.getDefuzzifier()).getLength();
+
+
+ constructor.append("\t\tthis." + var.toStringJSDefuzzifyVarName() + " = new Array(" + len + ");\n");
+
+ // Add output variables
+ varsOut.append("\t" + var.getName());
+ varsOut.append(";\n");
+
+ // Add to print method
+ printMethod.append("\t\tconsole.log(\"\tOutput %s: %f\\n\", \"" + var.getName() + "\" , this." + var.getName() + ");\n");
+
+ // Add defuzzyfier variable
+ varDefuzzifiers.append("\t// DEFUZZIFY " + var.getName() + "\n");
+ varDefuzzifiers.append("\t" + var.toStringJSDefuzzifyVarName() + ";\n");
+
+ // Add to reset method
+ resetMethod.append("\t\tfor (let i = 0 ; i < " + len + "; i++) {\n\t\t\tthis." + var.toStringJSDefuzzifyVarName() + "[i] = 0.0;\n\t\t}\n");
+
+ for (LinguisticTerm linguisticTerm : var.linguisticTermsSorted()) {
+ // Membership function
+ membershipMethods.append(linguisticTerm.toStringJS(var) + "\n");
+
+ }
+ varDefuzzifiers.append("\n");
+
+ defuzzifyMethod.append(var.getDefuzzifier().toStringJS());
+ }
+ }
+
+ //---
+ // Iterate over each ruleSet and append it to output string
+ // Sort ruleBlocks by name
+ //---
+ StringBuffer ruleBlocksStr = new StringBuffer();
+ for (RuleBlock ruleBlock : ruleBlocksSorted()) {
+ ruleBlocksStr.append(ruleBlock.toStringJS());
+ calcMethod.append("\t\tthis.calc_" + ruleBlock.getName() + "();\n");
+ }
+
+ constructor.append("\t}\n");
+ calcMethod.append("\t\tthis.defuzzify();\n\t}\n");
+ defuzzifyMethod.append("\t}\n");
+ fuzzifyMethod.append("\t}\n");
+ printMethod.append("\t}\n");
+ resetMethod.append("\t}\n");
+
+ // Build the whole thing
+ return "class FunctionBlock_" + name + " {\n\n" //
+ + varsIn + "\n" //
+ + varsOut //
+ + "\n" //
+ + varsFuzzify //
+ + varDefuzzifiers //
+ + constructor + "\n" //
+ + calcMethod + "\n" //
+ + ruleBlocksStr + "\n" //
+ + defuzzifyMethod + "\n" //
+ + fuzzifyMethod + "\n" //
+ + membershipMethods + "\n" //
+ + printMethod + "\n" //
+ + resetMethod + "\n" //
+ + "};\n\n" //
+ ; //
+ }
+
@Override
public String toStringFcl() {
StringBuffer varsIn = new StringBuffer();
diff --git a/src/main/java/net/sourceforge/jFuzzyLogic/JFuzzyLogic.java b/src/main/java/net/sourceforge/jFuzzyLogic/JFuzzyLogic.java
index d28a34f..dadb6e1 100644
--- a/src/main/java/net/sourceforge/jFuzzyLogic/JFuzzyLogic.java
+++ b/src/main/java/net/sourceforge/jFuzzyLogic/JFuzzyLogic.java
@@ -1,6 +1,5 @@
package net.sourceforge.jFuzzyLogic;
-import net.sourceforge.jFuzzyLogic.ruleConnectionMethod.Szczepanski;
import org.antlr.runtime.RecognitionException;
import net.sourceforge.jFuzzyLogic.demo.tipper.TipperAnimation;
@@ -24,7 +23,7 @@ public class JFuzzyLogic {
public static final String BUILD = "2022-05-12";
public static final String VERSION_MAJOR = "4.0";
public static final String VERSION_SHORT = VERSION_MAJOR + REVISION;
- public static final String VERSION_NO_NAME = VERSION_SHORT + " (build " + BUILD + "), by " + Pcingola.BY + " and " + Szczepanski.BY;
+ public static final String VERSION_NO_NAME = VERSION_SHORT + " (build " + BUILD + "), by " + Pcingola.BY;
public static final String VERSION = SOFTWARE_NAME + " " + VERSION_NO_NAME;
public static boolean debug = false;
@@ -56,6 +55,21 @@ public class JFuzzyLogic {
}
}
+ /**
+ * Compile an FCL program into JavaScript
+ */
+ void compileJS(String fileName) {
+ load(fileName); // Read FIS
+ System.out.println(fis.toStringJS()); // Show JS code
+
+ // Dump JS code to a file (debug)
+ if (debug) {
+ String jsfile = Gpr.HOME + "/x.js";
+ Gpr.debug("Writing to file " + jsfile);
+ Gpr.toFile(jsfile, fis.toStringJS());
+ }
+ }
+
/**
* Run demo
*/
@@ -170,6 +184,11 @@ public class JFuzzyLogic {
String fileName = args[++i];
compile(fileName);
return;
+ } else if (arg.equals("-j")) {
+ // Sanity check
+ String fileName = args[++i];
+ compileJS(fileName);
+ return;
} else if (arg.equals("-e")) {
evaluate(i + 1);
return;
@@ -202,11 +221,12 @@ public class JFuzzyLogic {
System.err.println("Usage: java -jar jFuzzyLogic.jar [-noCharts] [{-e|-c}] file.fcl [in_1 ... in_N]");
System.err.println("Options:");
- System.err.println("\t file.fcl : Load FCL file and show memebership functions (default, when no option is provided).");
+ System.err.println("\t file.fcl : Load FCL file and show membership functions (default, when no option is provided).");
System.err.println("\t-c file.fcl : Compile. Generate C++ code from FCL file (to STDOUT)");
+ System.err.println("\t-j file.fcl : Compile. Generate JavaScript code from FCL file (to STDOUT)");
System.err.println("\t-e file.fcl in_1 in_2 ... in_N : Evaluate. Load FCL file, assign inputs i_1, i_2, ..., i_n and evaluate (variables sorted alphabetically).");
System.err.println("\t-noCharts : Use a mock class for charts. This is used when not compiled using JFreeCharts.");
- System.err.println("\tdemo : Run a demo exmaple (tipper.fcl)");
+ System.err.println("\tdemo : Run a demo example (tipper.fcl)");
System.exit(1);
}
}
diff --git a/src/main/java/net/sourceforge/jFuzzyLogic/defuzzifier/Defuzzifier.java b/src/main/java/net/sourceforge/jFuzzyLogic/defuzzifier/Defuzzifier.java
index 71f81e4..8059749 100644
--- a/src/main/java/net/sourceforge/jFuzzyLogic/defuzzifier/Defuzzifier.java
+++ b/src/main/java/net/sourceforge/jFuzzyLogic/defuzzifier/Defuzzifier.java
@@ -68,4 +68,9 @@ public abstract class Defuzzifier extends FclObject {
public String toStringCpp() {
throw new RuntimeException("Unimplemented method for class " + this.getClass().getCanonicalName());
}
+
+ @Override
+ public String toStringJS() {
+ throw new RuntimeException("Unimplemented method for class " + this.getClass().getCanonicalName());
+ }
}
diff --git a/src/main/java/net/sourceforge/jFuzzyLogic/defuzzifier/DefuzzifierCenterOfGravity.java b/src/main/java/net/sourceforge/jFuzzyLogic/defuzzifier/DefuzzifierCenterOfGravity.java
index 25ac828..bb98cd5 100644
--- a/src/main/java/net/sourceforge/jFuzzyLogic/defuzzifier/DefuzzifierCenterOfGravity.java
+++ b/src/main/java/net/sourceforge/jFuzzyLogic/defuzzifier/DefuzzifierCenterOfGravity.java
@@ -51,6 +51,27 @@ public class DefuzzifierCenterOfGravity extends DefuzzifierContinuous {
return out.toString();
}
+ @Override
+ public String toStringJS() {
+ StringBuilder out = new StringBuilder();
+
+ String defuzzName = "defuzzify_" + variable.getName();
+ String sumName = "sum_" + variable.getName();
+ String wsumName = "wsum_" + variable.getName();
+
+ out.append("\t\tlet " + sumName + " = 0.0;\n");
+ out.append("\t\tlet " + wsumName + " = 0.0;\n");
+ out.append("\t\tlet x;\n");
+
+ out.append("\t\tfor (let i = 0; i < " + getLength() + "; i++) {\n");
+ out.append("\t\t\tx = " + min + " + i * " + stepSize + ";\n");
+ out.append("\t\t\t" + sumName + " += this." + defuzzName + "[i];\n");
+ out.append("\t\t\t" + wsumName + " += x * this." + defuzzName + "[i];\n");
+ out.append("\t\t}\n");
+ out.append("\t\tthis." + variable.getName() + " = " + wsumName + " / " + sumName + ";\n");
+ return out.toString();
+ }
+
@Override
public String toStringFcl() {
return "METHOD : COG;";
diff --git a/src/main/java/net/sourceforge/jFuzzyLogic/fcl/FclObject.java b/src/main/java/net/sourceforge/jFuzzyLogic/fcl/FclObject.java
index 1067940..0ebc160 100644
--- a/src/main/java/net/sourceforge/jFuzzyLogic/fcl/FclObject.java
+++ b/src/main/java/net/sourceforge/jFuzzyLogic/fcl/FclObject.java
@@ -1,6 +1,7 @@
package net.sourceforge.jFuzzyLogic.fcl;
import net.sourceforge.jFuzzyLogic.CompileCpp;
+import net.sourceforge.jFuzzyLogic.CompileJS;
/**
* The root of all FCL objects
@@ -8,7 +9,7 @@ import net.sourceforge.jFuzzyLogic.CompileCpp;
* @author pcingola
*
*/
-public abstract class FclObject implements CompileCpp {
+public abstract class FclObject implements CompileCpp, CompileJS {
@Override
public String toString() {
@@ -20,5 +21,10 @@ public abstract class FclObject implements CompileCpp {
return "// " + this.getClass().getName();
}
+ @Override
+ public String toStringJS() {
+ return "// " + this.getClass().getName();
+ }
+
public abstract String toStringFcl();
}
diff --git a/src/main/java/net/sourceforge/jFuzzyLogic/membership/MembershipFunction.java b/src/main/java/net/sourceforge/jFuzzyLogic/membership/MembershipFunction.java
index b58f47b..8b8906f 100644
--- a/src/main/java/net/sourceforge/jFuzzyLogic/membership/MembershipFunction.java
+++ b/src/main/java/net/sourceforge/jFuzzyLogic/membership/MembershipFunction.java
@@ -110,6 +110,11 @@ public abstract class MembershipFunction extends FclObject {
throw new RuntimeException("Unimplemented method 'toStringCpp()' for class " + this.getClass().getCanonicalName());
}
+ @Override
+ public String toStringJS() {
+ throw new RuntimeException("Unimplemented method 'toStringJS()' for class " + this.getClass().getCanonicalName());
+ }
+
@Override
public String toStringFcl() {
return getName();
diff --git a/src/main/java/net/sourceforge/jFuzzyLogic/membership/MembershipFunctionPieceWiseLinear.java b/src/main/java/net/sourceforge/jFuzzyLogic/membership/MembershipFunctionPieceWiseLinear.java
index 42b5472..0e082f2 100644
--- a/src/main/java/net/sourceforge/jFuzzyLogic/membership/MembershipFunctionPieceWiseLinear.java
+++ b/src/main/java/net/sourceforge/jFuzzyLogic/membership/MembershipFunctionPieceWiseLinear.java
@@ -157,6 +157,17 @@ public class MembershipFunctionPieceWiseLinear extends MembershipFunctionContinu
return sb.toString();
}
+ @Override
+ public String toStringJS() {
+ StringBuilder sb = new StringBuilder();
+ int i, len = x.length;
+ sb.append("\t\tif (x <= " + x[0].getValue() + ")\t\treturn " + y[0].getValue() + ";\n");
+ sb.append("\t\tif (x > " + x[len - 1].getValue() + ")\t\treturn " + y[len - 1].getValue() + ";\n");
+ for (i = 1; i < len; i++)
+ sb.append("\t\tif (x <= " + x[i].getValue() + ")\t\treturn " + y[i - 1].getValue() + " + (" + y[i].getValue() + " - " + y[i - 1].getValue() + ") * ((x - " + x[i - 1].getValue() + ") / (" + x[i].getValue() + " - " + x[i - 1].getValue() + "));\n");
+ return sb.toString();
+ }
+
/** FCL representation */
@Override
public String toStringFcl() {
diff --git a/src/main/java/net/sourceforge/jFuzzyLogic/membership/functions/MffFunction.java b/src/main/java/net/sourceforge/jFuzzyLogic/membership/functions/MffFunction.java
index 5d00e1b..eb08146 100644
--- a/src/main/java/net/sourceforge/jFuzzyLogic/membership/functions/MffFunction.java
+++ b/src/main/java/net/sourceforge/jFuzzyLogic/membership/functions/MffFunction.java
@@ -116,6 +116,18 @@ public abstract class MffFunction extends FclObject {
return out + ")";
}
+ @Override
+ public String toStringJS() {
+ if (terms == null) return "";
+ String out = this.getClass().getSimpleName() + "(";
+ for (int i = 0; i < terms.length; i++) {
+ out += terms[i].toStringFcl();
+ if (i < terms.length - 1) out += ", ";
+ }
+
+ return out + ")";
+ }
+
@Override
public String toStringFcl() {
if (terms == null) return "";
diff --git a/src/main/java/net/sourceforge/jFuzzyLogic/rule/LinguisticTerm.java b/src/main/java/net/sourceforge/jFuzzyLogic/rule/LinguisticTerm.java
index 00f87a5..4fb36cb 100644
--- a/src/main/java/net/sourceforge/jFuzzyLogic/rule/LinguisticTerm.java
+++ b/src/main/java/net/sourceforge/jFuzzyLogic/rule/LinguisticTerm.java
@@ -59,10 +59,22 @@ public class LinguisticTerm extends FclObject implements Comparable, Comparable, Com
return str;
}
+ @Override
+ public String toStringJS() {
+ String str = "";
+ String connector = ruleConnectionMethod.toStringJS();
+
+ if ((term1 == null) || (term2 == null)) {
+ // Only one term?
+ if (term1 != null) str += term1.toStringJS();
+ if (term2 != null) str += term2.toStringJS();
+ } else {
+ str += connector + "(";
+
+ // Both terms connected
+ if (isFuzzyRuleExpression(term1)) str += ((RuleExpression) term1).toStringJS();
+ else if (isFuzzyRuleTerm(term1)) str += ((RuleTerm) term1).toStringJS();
+
+ str += ", ";
+
+ if (isFuzzyRuleExpression(term2)) str += ((RuleExpression) term2).toStringJS();
+ else if (isFuzzyRuleTerm(term2)) str += ((RuleTerm) term2).toStringJS();
+
+ str += ")";
+ }
+
+ if (negated) str = "1.0 - (" + str + ")";
+
+ return str;
+ }
+
@Override
public String toStringFcl() {
String str = "";
diff --git a/src/main/java/net/sourceforge/jFuzzyLogic/rule/RuleTerm.java b/src/main/java/net/sourceforge/jFuzzyLogic/rule/RuleTerm.java
index b472633..dda33fa 100644
--- a/src/main/java/net/sourceforge/jFuzzyLogic/rule/RuleTerm.java
+++ b/src/main/java/net/sourceforge/jFuzzyLogic/rule/RuleTerm.java
@@ -73,10 +73,21 @@ public class RuleTerm extends FclObject {
return neg + variable.getName() + "_" + termName;
}
+ @Override
+ public String toStringJS() {
+ String neg = "";
+ if (negated) neg = "1 -";
+ return neg + "this." + variable.getName() + "_" + termName;
+ }
+
public String toStringCppDeffName() {
return getVariable().getName() + "_" + getTermName();
}
+ public String toStringJSDeffName() {
+ return getVariable().getName() + "_" + getTermName();
+ }
+
@Override
public String toStringFcl() {
String is = "IS";
diff --git a/src/main/java/net/sourceforge/jFuzzyLogic/rule/Variable.java b/src/main/java/net/sourceforge/jFuzzyLogic/rule/Variable.java
index 8446405..4ed2f71 100644
--- a/src/main/java/net/sourceforge/jFuzzyLogic/rule/Variable.java
+++ b/src/main/java/net/sourceforge/jFuzzyLogic/rule/Variable.java
@@ -338,6 +338,27 @@ public class Variable extends FclObject implements Comparable, Iterabl
return "defuzzify_" + getName();
}
+ @Override
+ public String toStringJS() {
+ String str = name + " : \n";
+
+ // Show defuzifier for "output" variables, value for "input" variables
+ if (defuzzifier != null) str += "\tDefuzzifier : " + defuzzifier.toString() + "\n\tLatest defuzzified value: " + latestDefuzzifiedValue + "\n";
+ else str += "\tValue: " + value + "\n";
+
+ if (!Double.isNaN(defaultValue)) str += "\tDefault value: " + defaultValue + "\n";
+
+ // Show each 'termName' and it's membership function
+ for (LinguisticTerm linguisticTerm : this)
+ str += "\t" + linguisticTerm.toString(value) + "\n";
+
+ return str;
+ }
+
+ public String toStringJSDefuzzifyVarName() {
+ return "defuzzify_" + getName();
+ }
+
@Override
public String toStringFcl() {
return name;
diff --git a/src/main/java/net/sourceforge/jFuzzyLogic/ruleAccumulationMethod/RuleAccumulationMethod.java b/src/main/java/net/sourceforge/jFuzzyLogic/ruleAccumulationMethod/RuleAccumulationMethod.java
index 09edb03..64be3e7 100644
--- a/src/main/java/net/sourceforge/jFuzzyLogic/ruleAccumulationMethod/RuleAccumulationMethod.java
+++ b/src/main/java/net/sourceforge/jFuzzyLogic/ruleAccumulationMethod/RuleAccumulationMethod.java
@@ -49,8 +49,17 @@ public abstract class RuleAccumulationMethod extends FclObject {
return "ruleAccumulationMethod_" + getName();
}
+ @Override
+ public String toStringJS() {
+ return "ruleAccumulationMethod_" + getName();
+ }
+
public String toStringCppFunction() {
- throw new RuntimeException("Unimplemented method foe class " + this.getClass().getCanonicalName());
+ throw new RuntimeException("Unimplemented method for class " + this.getClass().getCanonicalName());
+ }
+
+ public String toStringJSFunction() {
+ throw new RuntimeException("Unimplemented method for class " + this.getClass().getCanonicalName());
}
@Override
diff --git a/src/main/java/net/sourceforge/jFuzzyLogic/ruleAccumulationMethod/RuleAccumulationMethodMax.java b/src/main/java/net/sourceforge/jFuzzyLogic/ruleAccumulationMethod/RuleAccumulationMethodMax.java
index 0b2d23e..953625b 100644
--- a/src/main/java/net/sourceforge/jFuzzyLogic/ruleAccumulationMethod/RuleAccumulationMethodMax.java
+++ b/src/main/java/net/sourceforge/jFuzzyLogic/ruleAccumulationMethod/RuleAccumulationMethodMax.java
@@ -24,6 +24,11 @@ public class RuleAccumulationMethodMax extends RuleAccumulationMethod {
return "double " + toStringCpp() + "(double defuzzifierValue, double valueToAggregate)\t{ return ( defuzzifierValue > valueToAggregate ? defuzzifierValue : valueToAggregate ); }\n";
}
+ @Override
+ public String toStringJSFunction() {
+ return "function " + toStringJS() + "(defuzzifierValue, valueToAggregate) {\n\treturn (defuzzifierValue > valueToAggregate ? defuzzifierValue : valueToAggregate);\n}\n";
+ }
+
/**
* @see net.sourceforge.jFuzzyLogic.ruleAccumulationMethod.RuleAccumulationMethod#toStringFcl()
*/
diff --git a/src/main/java/net/sourceforge/jFuzzyLogic/ruleActivationMethod/RuleActivationMethod.java b/src/main/java/net/sourceforge/jFuzzyLogic/ruleActivationMethod/RuleActivationMethod.java
index 91a3748..5ce3e83 100644
--- a/src/main/java/net/sourceforge/jFuzzyLogic/ruleActivationMethod/RuleActivationMethod.java
+++ b/src/main/java/net/sourceforge/jFuzzyLogic/ruleActivationMethod/RuleActivationMethod.java
@@ -157,7 +157,49 @@ public abstract class RuleActivationMethod extends FclObject {
}
public String toStringCppFunction() {
- throw new RuntimeException("Unimplemented method foe class " + this.getClass().getCanonicalName());
+ throw new RuntimeException("Unimplemented method for class " + this.getClass().getCanonicalName());
+ }
+
+ @Override
+ public String toStringJS() {
+ return "ruleActivationMethod_" + name;
+ }
+
+ public String toStringJS(RuleTerm fuzzyRuleTerm, RuleAccumulationMethod ruleAccumulationMethod, String degreeOfSupportName) {
+ StringBuilder out = new StringBuilder();
+
+ Variable variable = fuzzyRuleTerm.getVariable();
+ Defuzzifier defuzzifier = variable.getDefuzzifier();
+
+ if (fuzzyRuleTerm.getMembershipFunction().isDiscrete()) {
+ throw new RuntimeException("Unimplemented for discre cases!");
+ } else {
+ //---
+ // Continuous case
+ //---
+ DefuzzifierContinuous defuzzifierContinuous = (DefuzzifierContinuous) defuzzifier;
+
+ // Add membership function to defuzzifier
+ out.append("\t\tif (" + degreeOfSupportName + " > 0) {\n");
+ out.append("\t\t\tfor (let i = 0; i < " + defuzzifierContinuous.getLength() + "; i++) {\n");
+ out.append("\t\t\t\tlet x = " + defuzzifierContinuous.getMin() + " + i * " + defuzzifierContinuous.getStepSize() + ";\n");
+ // Is term negated?
+ if (fuzzyRuleTerm.isNegated()) out.append("\t\t\tlet membership = 1 - mf.membership(x);\n");
+ else out.append("\t\t\t\tlet membership = this." + fuzzyRuleTerm.getLinguisticTerm().toStringJSMethodName(fuzzyRuleTerm.getVariable()) + "(x);\n");
+
+ out.append("\t\t\t\tlet y = " + toStringJS() + "(" + degreeOfSupportName + " , membership);\n");
+
+ // Aggregate value
+ out.append("\t\t\t\tthis." + variable.toStringJSDefuzzifyVarName() + "[i] = " + ruleAccumulationMethod.toStringJS() + "(this." + variable.toStringJSDefuzzifyVarName() + "[i], y);\n");
+ out.append("\t\t\t}\n");
+ out.append("\t\t}\n");
+ }
+
+ return out.toString();
+ }
+
+ public String toStringJSFunction() {
+ throw new RuntimeException("Unimplemented method for class " + this.getClass().getCanonicalName());
}
}
diff --git a/src/main/java/net/sourceforge/jFuzzyLogic/ruleActivationMethod/RuleActivationMethodMin.java b/src/main/java/net/sourceforge/jFuzzyLogic/ruleActivationMethod/RuleActivationMethodMin.java
index 2cfe1e5..3fa60ac 100644
--- a/src/main/java/net/sourceforge/jFuzzyLogic/ruleActivationMethod/RuleActivationMethodMin.java
+++ b/src/main/java/net/sourceforge/jFuzzyLogic/ruleActivationMethod/RuleActivationMethodMin.java
@@ -22,6 +22,11 @@ public class RuleActivationMethodMin extends RuleActivationMethod {
return "double " + toStringCpp() + "(double degreeOfSupport, double membership)\t{ return (degreeOfSupport < membership ? degreeOfSupport : membership); }\n";
}
+ @Override
+ public String toStringJSFunction() {
+ return "function " + toStringJS() + "(degreeOfSupport, membership) {\n\treturn (degreeOfSupport < membership ? degreeOfSupport : membership);\n}\n";
+ }
+
/** Printable FCL version */
@Override
public String toStringFcl() {
diff --git a/src/main/java/net/sourceforge/jFuzzyLogic/ruleConnectionMethod/RuleConnectionMethod.java b/src/main/java/net/sourceforge/jFuzzyLogic/ruleConnectionMethod/RuleConnectionMethod.java
index 655da22..c6a64a1 100644
--- a/src/main/java/net/sourceforge/jFuzzyLogic/ruleConnectionMethod/RuleConnectionMethod.java
+++ b/src/main/java/net/sourceforge/jFuzzyLogic/ruleConnectionMethod/RuleConnectionMethod.java
@@ -40,8 +40,17 @@ public abstract class RuleConnectionMethod extends FclObject {
return "ruleConnectionMethod_" + name;
}
+ @Override
+ public String toStringJS() {
+ return "ruleConnectionMethod_" + name;
+ }
+
public String toStringCppFunction() {
- throw new RuntimeException("Unimplemented method foe class " + this.getClass().getCanonicalName());
+ throw new RuntimeException("Unimplemented method for class " + this.getClass().getCanonicalName());
+ }
+
+ public String toStringJSFunction() {
+ throw new RuntimeException("Unimplemented method for class " + this.getClass().getCanonicalName());
}
}
diff --git a/src/main/java/net/sourceforge/jFuzzyLogic/ruleConnectionMethod/RuleConnectionMethodAndMin.java b/src/main/java/net/sourceforge/jFuzzyLogic/ruleConnectionMethod/RuleConnectionMethodAndMin.java
index 151881a..5995ee1 100644
--- a/src/main/java/net/sourceforge/jFuzzyLogic/ruleConnectionMethod/RuleConnectionMethodAndMin.java
+++ b/src/main/java/net/sourceforge/jFuzzyLogic/ruleConnectionMethod/RuleConnectionMethodAndMin.java
@@ -31,6 +31,11 @@ public class RuleConnectionMethodAndMin extends RuleConnectionMethod {
return "double " + toStringCpp() + "(double antecedent1, double antecedent2)\t{ return (antecedent1 < antecedent2 ? antecedent1 : antecedent2); }\n";
}
+ @Override
+ public String toStringJSFunction() {
+ return "function " + toStringJS() + "(antecedent1, antecedent2) {\n\treturn (antecedent1 < antecedent2 ? antecedent1 : antecedent2);\n}\n";
+ }
+
@Override
public String toStringFcl() {
return "AND : MIN;";
diff --git a/src/main/java/net/sourceforge/jFuzzyLogic/ruleConnectionMethod/RuleConnectionMethodOrMax.java b/src/main/java/net/sourceforge/jFuzzyLogic/ruleConnectionMethod/RuleConnectionMethodOrMax.java
index a1af61e..83f38b7 100644
--- a/src/main/java/net/sourceforge/jFuzzyLogic/ruleConnectionMethod/RuleConnectionMethodOrMax.java
+++ b/src/main/java/net/sourceforge/jFuzzyLogic/ruleConnectionMethod/RuleConnectionMethodOrMax.java
@@ -31,6 +31,11 @@ public class RuleConnectionMethodOrMax extends RuleConnectionMethod {
return "double " + toStringCpp() + "(double antecedent1, double antecedent2)\t{ return (antecedent1 > antecedent2 ? antecedent1 : antecedent2); }\n";
}
+ @Override
+ public String toStringJSFunction() {
+ return "function " + toStringJS() + "(antecedent1, antecedent2) {\n\treturn (antecedent1 > antecedent2 ? antecedent1 : antecedent2);\n}\n";
+ }
+
@Override
public String toStringFcl() {
return "OR: MAX;";
diff --git a/src/main/java/net/sourceforge/jFuzzyLogic/ruleConnectionMethod/Szczepanski.java b/src/main/java/net/sourceforge/jFuzzyLogic/ruleConnectionMethod/Szczepanski.java
deleted file mode 100644
index a77d999..0000000
--- a/src/main/java/net/sourceforge/jFuzzyLogic/ruleConnectionMethod/Szczepanski.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package net.sourceforge.jFuzzyLogic.ruleConnectionMethod;
-
-/**
- * Author's data
- * @author marcin-szczepanski
- */
-public class Szczepanski {
-
- public static final String EMAIL = "marcin.szczepanski@amu.edu.pl";
- public static final String BY = "Marcin Szczepanski";
-}