mirror of
https://github.com/marcin-szczepanski/jFuzzyLogic.git
synced 2024-12-18 16:35:27 +01:00
FCL compiler - JavaScript
This commit is contained in:
parent
a034eb2f68
commit
3bfa35fa40
@ -113,6 +113,7 @@
|
|||||||
<tr> <td valign=top> Helano Póvoas de Lima </td> <td> DefuzzifierContinuous graphic bug. </td> </tr>
|
<tr> <td valign=top> Helano Póvoas de Lima </td> <td> DefuzzifierContinuous graphic bug. </td> </tr>
|
||||||
<tr> <td valign=top> Nikola Nikolovski </td> <td> RuleBlock name bug.</td> </tr>
|
<tr> <td valign=top> Nikola Nikolovski </td> <td> RuleBlock name bug.</td> </tr>
|
||||||
<tr> <td valign=top> Ivan De Falco </td> <td> "AND Bounded Diff" bug. </td> </tr>
|
<tr> <td valign=top> Ivan De Falco </td> <td> "AND Bounded Diff" bug. </td> </tr>
|
||||||
|
<tr> <td valign=top> Marcin Szczepanski </td> <td> FCL Compiler (JavaScript). </td> </tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
// Code generated by jFuzzyLogic
|
// Code generated by jFuzzyLogic
|
||||||
// jFuzzyLogic Version : JFuzzyLogic 3.2g (build 2013-10-20), by Pablo Cingolani
|
// jFuzzyLogic Version : JFuzzyLogic 4.0 (build 2022-05-12), by Pablo Cingolani
|
||||||
// jFuzzyLogic creted by Pablo Cingolani
|
// jFuzzyLogic created by Pablo Cingolani
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
208
html/fcl/tipper.js
Normal file
208
html/fcl/tipper.js
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
// Code generated by jFuzzyLogic
|
||||||
|
// jFuzzyLogic Version : JFuzzyLogic 4.0 (build 2022-05-12), by Pablo Cingolani
|
||||||
|
// jFuzzyLogic created by Pablo Cingolani
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function ruleAccumulationMethod_max(defuzzifierValue, valueToAggregate) {
|
||||||
|
return (defuzzifierValue > valueToAggregate ? defuzzifierValue : valueToAggregate);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ruleActivationMethod_min(degreeOfSupport, membership) {
|
||||||
|
return (degreeOfSupport < membership ? degreeOfSupport : membership);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ruleConnectionMethod_and(antecedent1, antecedent2) {
|
||||||
|
return (antecedent1 < antecedent2 ? antecedent1 : antecedent2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ruleConnectionMethod_or(antecedent1, antecedent2) {
|
||||||
|
return (antecedent1 > antecedent2 ? antecedent1 : antecedent2);
|
||||||
|
}
|
||||||
|
|
||||||
|
class FunctionBlock_tipper {
|
||||||
|
|
||||||
|
// VAR_INPUT
|
||||||
|
food;
|
||||||
|
service;
|
||||||
|
|
||||||
|
// VAR_OUTPUT
|
||||||
|
tip;
|
||||||
|
|
||||||
|
// FUZZIFY food
|
||||||
|
food_delicious;
|
||||||
|
food_rancid;
|
||||||
|
|
||||||
|
// FUZZIFY service
|
||||||
|
service_excellent;
|
||||||
|
service_good;
|
||||||
|
service_poor;
|
||||||
|
|
||||||
|
// DEFUZZIFY tip
|
||||||
|
defuzzify_tip;
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
constructor() {
|
||||||
|
this.tip = 0.0;
|
||||||
|
this.defuzzify_tip = new Array(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate function block
|
||||||
|
calc() {
|
||||||
|
this.reset();
|
||||||
|
this.fuzzify();
|
||||||
|
this.calc_No1();
|
||||||
|
this.defuzzify();
|
||||||
|
}
|
||||||
|
|
||||||
|
// RULEBLOCK No1
|
||||||
|
calc_No1() {
|
||||||
|
// RULE 1 : IF (service IS poor) OR (food IS rancid) THEN tip IS cheap;
|
||||||
|
let degreeOfSupport_1 = 1.0 * (ruleConnectionMethod_or(this.service_poor, this.food_rancid));
|
||||||
|
if (degreeOfSupport_1 > 0) {
|
||||||
|
for (let i = 0; i < 1000; i++) {
|
||||||
|
let x = 0.0 + i * 0.03;
|
||||||
|
let membership = this.membership_tip_cheap(x);
|
||||||
|
let y = ruleActivationMethod_min(degreeOfSupport_1 , membership);
|
||||||
|
this.defuzzify_tip[i] = ruleAccumulationMethod_max(this.defuzzify_tip[i], y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RULE 2 : IF service IS good THEN tip IS average;
|
||||||
|
let degreeOfSupport_2 = 1.0 * (this.service_good);
|
||||||
|
if (degreeOfSupport_2 > 0) {
|
||||||
|
for (let i = 0; i < 1000; i++) {
|
||||||
|
let x = 0.0 + i * 0.03;
|
||||||
|
let membership = this.membership_tip_average(x);
|
||||||
|
let y = ruleActivationMethod_min(degreeOfSupport_2 , membership);
|
||||||
|
this.defuzzify_tip[i] = ruleAccumulationMethod_max(this.defuzzify_tip[i], y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RULE 3 : IF (service IS excellent) AND (food IS delicious) THEN tip IS generous;
|
||||||
|
let degreeOfSupport_3 = 1.0 * (ruleConnectionMethod_and(this.service_excellent, this.food_delicious));
|
||||||
|
if (degreeOfSupport_3 > 0) {
|
||||||
|
for (let i = 0; i < 1000; i++) {
|
||||||
|
let x = 0.0 + i * 0.03;
|
||||||
|
let membership = this.membership_tip_generous(x);
|
||||||
|
let y = ruleActivationMethod_min(degreeOfSupport_3 , membership);
|
||||||
|
this.defuzzify_tip[i] = ruleAccumulationMethod_max(this.defuzzify_tip[i], y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defuzzify
|
||||||
|
defuzzify() {
|
||||||
|
let sum_tip = 0.0;
|
||||||
|
let wsum_tip = 0.0;
|
||||||
|
let x;
|
||||||
|
for (let i = 0; i < 1000; i++) {
|
||||||
|
x = 0.0 + i * 0.03;
|
||||||
|
sum_tip += this.defuzzify_tip[i];
|
||||||
|
wsum_tip += x * this.defuzzify_tip[i];
|
||||||
|
}
|
||||||
|
this.tip = wsum_tip / sum_tip;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fuzzify all variables
|
||||||
|
fuzzify() {
|
||||||
|
this.food_delicious = this.membership_food_delicious(this.food);
|
||||||
|
this.food_rancid = this.membership_food_rancid(this.food);
|
||||||
|
this.service_excellent = this.membership_service_excellent(this.service);
|
||||||
|
this.service_good = this.membership_service_good(this.service);
|
||||||
|
this.service_poor = this.membership_service_poor(this.service);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Membership functions
|
||||||
|
membership_food_delicious(x) {
|
||||||
|
if (x <= 7.0) return 0.0;
|
||||||
|
if (x > 9.0) return 1.0;
|
||||||
|
if (x <= 9.0) return 0.0 + (1.0 - 0.0) * ((x - 7.0) / (9.0 - 7.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
membership_food_rancid(x) {
|
||||||
|
if (x <= 0.0) return 1.0;
|
||||||
|
if (x > 3.0) return 0.0;
|
||||||
|
if (x <= 1.0) return 1.0 + (1.0 - 1.0) * ((x - 0.0) / (1.0 - 0.0));
|
||||||
|
if (x <= 3.0) return 1.0 + (0.0 - 1.0) * ((x - 1.0) / (3.0 - 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
membership_service_excellent(x) {
|
||||||
|
if (x <= 6.0) return 0.0;
|
||||||
|
if (x > 9.0) return 1.0;
|
||||||
|
if (x <= 9.0) return 0.0 + (1.0 - 0.0) * ((x - 6.0) / (9.0 - 6.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
membership_service_good(x) {
|
||||||
|
if (x <= 1.0) return 0.0;
|
||||||
|
if (x > 9.0) return 0.0;
|
||||||
|
if (x <= 4.0) return 0.0 + (1.0 - 0.0) * ((x - 1.0) / (4.0 - 1.0));
|
||||||
|
if (x <= 6.0) return 1.0 + (1.0 - 1.0) * ((x - 4.0) / (6.0 - 4.0));
|
||||||
|
if (x <= 9.0) return 1.0 + (0.0 - 1.0) * ((x - 6.0) / (9.0 - 6.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
membership_service_poor(x) {
|
||||||
|
if (x <= 0.0) return 1.0;
|
||||||
|
if (x > 4.0) return 0.0;
|
||||||
|
if (x <= 4.0) return 1.0 + (0.0 - 1.0) * ((x - 0.0) / (4.0 - 0.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
membership_tip_average(x) {
|
||||||
|
if (x <= 10.0) return 0.0;
|
||||||
|
if (x > 20.0) return 0.0;
|
||||||
|
if (x <= 15.0) return 0.0 + (1.0 - 0.0) * ((x - 10.0) / (15.0 - 10.0));
|
||||||
|
if (x <= 20.0) return 1.0 + (0.0 - 1.0) * ((x - 15.0) / (20.0 - 15.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
membership_tip_cheap(x) {
|
||||||
|
if (x <= 0.0) return 0.0;
|
||||||
|
if (x > 10.0) return 0.0;
|
||||||
|
if (x <= 5.0) return 0.0 + (1.0 - 0.0) * ((x - 0.0) / (5.0 - 0.0));
|
||||||
|
if (x <= 10.0) return 1.0 + (0.0 - 1.0) * ((x - 5.0) / (10.0 - 5.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
membership_tip_generous(x) {
|
||||||
|
if (x <= 20.0) return 0.0;
|
||||||
|
if (x > 30.0) return 0.0;
|
||||||
|
if (x <= 25.0) return 0.0 + (1.0 - 0.0) * ((x - 20.0) / (25.0 - 20.0));
|
||||||
|
if (x <= 30.0) return 1.0 + (0.0 - 1.0) * ((x - 25.0) / (30.0 - 25.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Print
|
||||||
|
print() {
|
||||||
|
console.log("Function block tipper:\n");
|
||||||
|
console.log(" Input %s: %f\n", "food" , this.food);
|
||||||
|
console.log(" %s: %f\n", "food_delicious" , this.food_delicious);
|
||||||
|
console.log(" %s: %f\n", "food_rancid" , this.food_rancid);
|
||||||
|
console.log(" Input %s: %f\n", "service" , this.service);
|
||||||
|
console.log(" %s: %f\n", "service_excellent" , this.service_excellent);
|
||||||
|
console.log(" %s: %f\n", "service_good" , this.service_good);
|
||||||
|
console.log(" %s: %f\n", "service_poor" , this.service_poor);
|
||||||
|
console.log(" Output %s: %f\n", "tip" , this.tip);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset output
|
||||||
|
reset() {
|
||||||
|
for (let i = 0 ; i < 1000; i++) {
|
||||||
|
this.defuzzify_tip[i] = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
function main(food, service) {
|
||||||
|
// Create function blocks
|
||||||
|
const tipper = new FunctionBlock_tipper();
|
||||||
|
|
||||||
|
// Parse input
|
||||||
|
tipper.food = food;
|
||||||
|
tipper.service = service;
|
||||||
|
|
||||||
|
// Calculate
|
||||||
|
tipper.calc();
|
||||||
|
|
||||||
|
// Show results
|
||||||
|
tipper.print();
|
||||||
|
}
|
BIN
html/images/js.png
Normal file
BIN
html/images/js.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 71 KiB |
@ -180,6 +180,7 @@
|
|||||||
<p class="lead">Tons of advanced features
|
<p class="lead">Tons of advanced features
|
||||||
<ul>
|
<ul>
|
||||||
<li> C++ compiler (convert FCL to C++)
|
<li> C++ compiler (convert FCL to C++)
|
||||||
|
<li> JavaScript compiler (convert FCL to JavaScript)
|
||||||
<li> Core library available for Android developers <img src="images/android.png">
|
<li> Core library available for Android developers <img src="images/android.png">
|
||||||
<li> Parameter optimization
|
<li> Parameter optimization
|
||||||
<li> Parametric membership functions
|
<li> Parametric membership functions
|
||||||
|
@ -86,6 +86,7 @@
|
|||||||
<a class="list-group-item" href="#using">Using jFuzzyLogic in projects</a>
|
<a class="list-group-item" href="#using">Using jFuzzyLogic in projects</a>
|
||||||
<a class="list-group-item" href="#plugin">Eclipse plug-in</a>
|
<a class="list-group-item" href="#plugin">Eclipse plug-in</a>
|
||||||
<a class="list-group-item" href="#compiler">FCL compiler</a>
|
<a class="list-group-item" href="#compiler">FCL compiler</a>
|
||||||
|
<a class="list-group-item" href="#compilerJS">FCL compiler (JavaScript)</a>
|
||||||
<a class="list-group-item" href="#optim">Parameter optimization</a>
|
<a class="list-group-item" href="#optim">Parameter optimization</a>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@ -956,11 +957,32 @@ java -jar jFuzzyLogic.jar -c tipper.fcl > tipper.cpp
|
|||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section id="compilerJS">
|
||||||
|
<div class="page-header">
|
||||||
|
<h1>10. FCL compiler (JavaScript)</h1>
|
||||||
|
</div>
|
||||||
|
<p class="lead">
|
||||||
|
jFuzzyLogic can compile FCL into JavaScript code.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
A built in compiler allows to compiler FCL code into JavaScript.
|
||||||
|
For instance, by simply running the following command, we can create a JavaScript program that has the same functionality as the FCL program:
|
||||||
|
<pre>
|
||||||
|
java -jar jFuzzyLogic.jar -j tipper.fcl > tipper.js
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
The previous command creates <a href="fcl/tipper.js">this JavaScript code</a>.
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<img src="images/js.png">
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
<!-- Parameter optimization
|
<!-- Parameter optimization
|
||||||
================================================== -->
|
================================================== -->
|
||||||
<section id="optim">
|
<section id="optim">
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h1>10. Parameter optimization</h1>
|
<h1>11. Parameter optimization</h1>
|
||||||
</div>
|
</div>
|
||||||
<p class="lead">
|
<p class="lead">
|
||||||
jFuzzyLogic provides a parameter optimization framework, allowing to learn or refine fuzzy parameters using machine learning algorithms.
|
jFuzzyLogic provides a parameter optimization framework, allowing to learn or refine fuzzy parameters using machine learning algorithms.
|
||||||
|
Binary file not shown.
11
src/main/java/net/sourceforge/jFuzzyLogic/CompileJS.java
Normal file
11
src/main/java/net/sourceforge/jFuzzyLogic/CompileJS.java
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package net.sourceforge.jFuzzyLogic;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create JS code
|
||||||
|
*
|
||||||
|
* @author marcin-szczepanski
|
||||||
|
*/
|
||||||
|
public interface CompileJS {
|
||||||
|
|
||||||
|
public String toStringJS();
|
||||||
|
}
|
@ -257,7 +257,7 @@ public class FIS extends FclObject implements Iterable<FunctionBlock>, CompileCp
|
|||||||
out.append("//--------------------------------------------------------------------------------\n");
|
out.append("//--------------------------------------------------------------------------------\n");
|
||||||
out.append("// Code generated by jFuzzyLogic\n");
|
out.append("// Code generated by jFuzzyLogic\n");
|
||||||
out.append("// jFuzzyLogic Version : " + JFuzzyLogic.VERSION + " \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\n");
|
||||||
out.append("\n#include <stdio.h>\n");
|
out.append("\n#include <stdio.h>\n");
|
||||||
out.append("\n#include <stdlib.h>\n");
|
out.append("\n#include <stdlib.h>\n");
|
||||||
@ -337,6 +337,117 @@ public class FIS extends FclObject implements Iterable<FunctionBlock>, CompileCp
|
|||||||
return out.toString();
|
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<String> fbNames = new ArrayList<String>(functionBlocks.keySet());
|
||||||
|
Collections.sort(fbNames);
|
||||||
|
|
||||||
|
// Ge all activations and accumulation methods
|
||||||
|
HashSet<RuleAccumulationMethod> raccs = new HashSet<RuleAccumulationMethod>();
|
||||||
|
HashSet<RuleActivationMethod> racts = new HashSet<RuleActivationMethod>();
|
||||||
|
HashSet<RuleConnectionMethod> rcons = new HashSet<RuleConnectionMethod>();
|
||||||
|
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
|
@Override
|
||||||
public String toStringFcl() {
|
public String toStringFcl() {
|
||||||
StringBuffer out = new StringBuffer();
|
StringBuffer out = new StringBuffer();
|
||||||
|
@ -740,6 +740,131 @@ public class FunctionBlock extends FclObject implements Iterable<RuleBlock>, 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
|
@Override
|
||||||
public String toStringFcl() {
|
public String toStringFcl() {
|
||||||
StringBuffer varsIn = new StringBuffer();
|
StringBuffer varsIn = new StringBuffer();
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.sourceforge.jFuzzyLogic;
|
package net.sourceforge.jFuzzyLogic;
|
||||||
|
|
||||||
import net.sourceforge.jFuzzyLogic.ruleConnectionMethod.Szczepanski;
|
|
||||||
import org.antlr.runtime.RecognitionException;
|
import org.antlr.runtime.RecognitionException;
|
||||||
|
|
||||||
import net.sourceforge.jFuzzyLogic.demo.tipper.TipperAnimation;
|
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 BUILD = "2022-05-12";
|
||||||
public static final String VERSION_MAJOR = "4.0";
|
public static final String VERSION_MAJOR = "4.0";
|
||||||
public static final String VERSION_SHORT = VERSION_MAJOR + REVISION;
|
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 final String VERSION = SOFTWARE_NAME + " " + VERSION_NO_NAME;
|
||||||
|
|
||||||
public static boolean debug = false;
|
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
|
* Run demo
|
||||||
*/
|
*/
|
||||||
@ -170,6 +184,11 @@ public class JFuzzyLogic {
|
|||||||
String fileName = args[++i];
|
String fileName = args[++i];
|
||||||
compile(fileName);
|
compile(fileName);
|
||||||
return;
|
return;
|
||||||
|
} else if (arg.equals("-j")) {
|
||||||
|
// Sanity check
|
||||||
|
String fileName = args[++i];
|
||||||
|
compileJS(fileName);
|
||||||
|
return;
|
||||||
} else if (arg.equals("-e")) {
|
} else if (arg.equals("-e")) {
|
||||||
evaluate(i + 1);
|
evaluate(i + 1);
|
||||||
return;
|
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("Usage: java -jar jFuzzyLogic.jar [-noCharts] [{-e|-c}] file.fcl [in_1 ... in_N]");
|
||||||
System.err.println("Options:");
|
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-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-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("\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);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,4 +68,9 @@ public abstract class Defuzzifier extends FclObject {
|
|||||||
public String toStringCpp() {
|
public String toStringCpp() {
|
||||||
throw new RuntimeException("Unimplemented method for class " + this.getClass().getCanonicalName());
|
throw new RuntimeException("Unimplemented method for class " + this.getClass().getCanonicalName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toStringJS() {
|
||||||
|
throw new RuntimeException("Unimplemented method for class " + this.getClass().getCanonicalName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,27 @@ public class DefuzzifierCenterOfGravity extends DefuzzifierContinuous {
|
|||||||
return out.toString();
|
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
|
@Override
|
||||||
public String toStringFcl() {
|
public String toStringFcl() {
|
||||||
return "METHOD : COG;";
|
return "METHOD : COG;";
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package net.sourceforge.jFuzzyLogic.fcl;
|
package net.sourceforge.jFuzzyLogic.fcl;
|
||||||
|
|
||||||
import net.sourceforge.jFuzzyLogic.CompileCpp;
|
import net.sourceforge.jFuzzyLogic.CompileCpp;
|
||||||
|
import net.sourceforge.jFuzzyLogic.CompileJS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The root of all FCL objects
|
* The root of all FCL objects
|
||||||
@ -8,7 +9,7 @@ import net.sourceforge.jFuzzyLogic.CompileCpp;
|
|||||||
* @author pcingola
|
* @author pcingola
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public abstract class FclObject implements CompileCpp {
|
public abstract class FclObject implements CompileCpp, CompileJS {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
@ -20,5 +21,10 @@ public abstract class FclObject implements CompileCpp {
|
|||||||
return "// " + this.getClass().getName();
|
return "// " + this.getClass().getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toStringJS() {
|
||||||
|
return "// " + this.getClass().getName();
|
||||||
|
}
|
||||||
|
|
||||||
public abstract String toStringFcl();
|
public abstract String toStringFcl();
|
||||||
}
|
}
|
||||||
|
@ -110,6 +110,11 @@ public abstract class MembershipFunction extends FclObject {
|
|||||||
throw new RuntimeException("Unimplemented method 'toStringCpp()' for class " + this.getClass().getCanonicalName());
|
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
|
@Override
|
||||||
public String toStringFcl() {
|
public String toStringFcl() {
|
||||||
return getName();
|
return getName();
|
||||||
|
@ -157,6 +157,17 @@ public class MembershipFunctionPieceWiseLinear extends MembershipFunctionContinu
|
|||||||
return sb.toString();
|
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 */
|
/** FCL representation */
|
||||||
@Override
|
@Override
|
||||||
public String toStringFcl() {
|
public String toStringFcl() {
|
||||||
|
@ -116,6 +116,18 @@ public abstract class MffFunction extends FclObject {
|
|||||||
return out + ")";
|
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
|
@Override
|
||||||
public String toStringFcl() {
|
public String toStringFcl() {
|
||||||
if (terms == null) return "";
|
if (terms == null) return "";
|
||||||
|
@ -59,10 +59,22 @@ public class LinguisticTerm extends FclObject implements Comparable<LinguisticTe
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toStringJS(Variable var) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("\t" + toStringJSMethodName(var) + "(x) {\n");
|
||||||
|
sb.append(membershipFunction.toStringJS());
|
||||||
|
sb.append("\t}\n");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
public String toStringCppMethodName(Variable var) {
|
public String toStringCppMethodName(Variable var) {
|
||||||
return "membership_" + var.getName() + "_" + getTermName();
|
return "membership_" + var.getName() + "_" + getTermName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toStringJSMethodName(Variable var) {
|
||||||
|
return "membership_" + var.getName() + "_" + getTermName();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toStringFcl() {
|
public String toStringFcl() {
|
||||||
return "TERM " + termName + " := " + membershipFunction.toStringFcl() + ";";
|
return "TERM " + termName + " := " + membershipFunction.toStringFcl() + ";";
|
||||||
|
@ -187,6 +187,24 @@ public class Rule extends FclObject implements CompileCpp {
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toStringJS() {
|
||||||
|
RuleActivationMethod ruleActivationMethod = ruleBlock.getRuleActivationMethod();
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
// Show antecedents
|
||||||
|
String dosName = "degreeOfSupport_" + name;
|
||||||
|
sb.append("\t\tlet " + dosName + " = " + weight + " * (" + antecedents.toStringJS() + ");\n");
|
||||||
|
|
||||||
|
// Accumulate & activate
|
||||||
|
RuleAccumulationMethod ruleAccumulationMethod = ruleBlock.getRuleAccumulationMethod();
|
||||||
|
for (RuleTerm term : consequents)
|
||||||
|
sb.append(ruleActivationMethod.toStringJS(term, ruleAccumulationMethod, dosName) + "\n");
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toStringFcl() {
|
public String toStringFcl() {
|
||||||
String strAnt = "", strCon = "";
|
String strAnt = "", strCon = "";
|
||||||
|
@ -441,6 +441,28 @@ public class RuleBlock extends FclObject implements Iterable<Rule>, Comparable<R
|
|||||||
return rb.toString();
|
return rb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toStringJS() {
|
||||||
|
StringBuffer rb = new StringBuffer();
|
||||||
|
rb.append("\t// RULEBLOCK " + name + "\n");
|
||||||
|
rb.append("\tcalc_" + name + "() {\n");
|
||||||
|
|
||||||
|
// Show rules
|
||||||
|
int ruleNum = 1;
|
||||||
|
for (Rule rule : rules) {
|
||||||
|
// Rule name/number
|
||||||
|
String name = rule.getName();
|
||||||
|
if ((name == null) || (name.equals(""))) name = Integer.toString(ruleNum);
|
||||||
|
|
||||||
|
rb.append("\t\t// RULE " + name + " : " + rule.toStringFcl() + "\n");
|
||||||
|
rb.append(rule.toStringJS());
|
||||||
|
ruleNum++;
|
||||||
|
}
|
||||||
|
|
||||||
|
rb.append("\t}\n");
|
||||||
|
|
||||||
|
return rb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toStringFcl() {
|
public String toStringFcl() {
|
||||||
StringBuffer rb = new StringBuffer();
|
StringBuffer rb = new StringBuffer();
|
||||||
|
@ -237,6 +237,35 @@ public class RuleExpression extends FclObject implements Iterable<Variable>, Com
|
|||||||
return str;
|
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
|
@Override
|
||||||
public String toStringFcl() {
|
public String toStringFcl() {
|
||||||
String str = "";
|
String str = "";
|
||||||
|
@ -73,10 +73,21 @@ public class RuleTerm extends FclObject {
|
|||||||
return neg + variable.getName() + "_" + termName;
|
return neg + variable.getName() + "_" + termName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toStringJS() {
|
||||||
|
String neg = "";
|
||||||
|
if (negated) neg = "1 -";
|
||||||
|
return neg + "this." + variable.getName() + "_" + termName;
|
||||||
|
}
|
||||||
|
|
||||||
public String toStringCppDeffName() {
|
public String toStringCppDeffName() {
|
||||||
return getVariable().getName() + "_" + getTermName();
|
return getVariable().getName() + "_" + getTermName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toStringJSDeffName() {
|
||||||
|
return getVariable().getName() + "_" + getTermName();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toStringFcl() {
|
public String toStringFcl() {
|
||||||
String is = "IS";
|
String is = "IS";
|
||||||
|
@ -338,6 +338,27 @@ public class Variable extends FclObject implements Comparable<Variable>, Iterabl
|
|||||||
return "defuzzify_" + getName();
|
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
|
@Override
|
||||||
public String toStringFcl() {
|
public String toStringFcl() {
|
||||||
return name;
|
return name;
|
||||||
|
@ -49,8 +49,17 @@ public abstract class RuleAccumulationMethod extends FclObject {
|
|||||||
return "ruleAccumulationMethod_" + getName();
|
return "ruleAccumulationMethod_" + getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toStringJS() {
|
||||||
|
return "ruleAccumulationMethod_" + getName();
|
||||||
|
}
|
||||||
|
|
||||||
public String toStringCppFunction() {
|
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
|
@Override
|
||||||
|
@ -24,6 +24,11 @@ public class RuleAccumulationMethodMax extends RuleAccumulationMethod {
|
|||||||
return "double " + toStringCpp() + "(double defuzzifierValue, double valueToAggregate)\t{ return ( defuzzifierValue > valueToAggregate ? defuzzifierValue : valueToAggregate ); }\n";
|
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()
|
* @see net.sourceforge.jFuzzyLogic.ruleAccumulationMethod.RuleAccumulationMethod#toStringFcl()
|
||||||
*/
|
*/
|
||||||
|
@ -157,7 +157,49 @@ public abstract class RuleActivationMethod extends FclObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String toStringCppFunction() {
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,11 @@ public class RuleActivationMethodMin extends RuleActivationMethod {
|
|||||||
return "double " + toStringCpp() + "(double degreeOfSupport, double membership)\t{ return (degreeOfSupport < membership ? degreeOfSupport : membership); }\n";
|
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 */
|
/** Printable FCL version */
|
||||||
@Override
|
@Override
|
||||||
public String toStringFcl() {
|
public String toStringFcl() {
|
||||||
|
@ -40,8 +40,17 @@ public abstract class RuleConnectionMethod extends FclObject {
|
|||||||
return "ruleConnectionMethod_" + name;
|
return "ruleConnectionMethod_" + name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toStringJS() {
|
||||||
|
return "ruleConnectionMethod_" + name;
|
||||||
|
}
|
||||||
|
|
||||||
public String toStringCppFunction() {
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,11 @@ public class RuleConnectionMethodAndMin extends RuleConnectionMethod {
|
|||||||
return "double " + toStringCpp() + "(double antecedent1, double antecedent2)\t{ return (antecedent1 < antecedent2 ? antecedent1 : antecedent2); }\n";
|
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
|
@Override
|
||||||
public String toStringFcl() {
|
public String toStringFcl() {
|
||||||
return "AND : MIN;";
|
return "AND : MIN;";
|
||||||
|
@ -31,6 +31,11 @@ public class RuleConnectionMethodOrMax extends RuleConnectionMethod {
|
|||||||
return "double " + toStringCpp() + "(double antecedent1, double antecedent2)\t{ return (antecedent1 > antecedent2 ? antecedent1 : antecedent2); }\n";
|
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
|
@Override
|
||||||
public String toStringFcl() {
|
public String toStringFcl() {
|
||||||
return "OR: MAX;";
|
return "OR: MAX;";
|
||||||
|
@ -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";
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user