home Forums # Technical Support Map getOutputValue() to the concerned membership function

Viewing 9 posts - 1 through 9 (of 9 total)
• Author
Posts
• #1826
senabhishek
Participant

Hi Juan,

First off, I must say thank you very much for developing this amazing tool. I had zero hesitation in buying the licensed version of this application. I am running FLC models on iOS and although it took a bit of tinkering, I was able to successfully integrate all the source code into my iOS project (with Swift) and am currently using it for my Master’s thesis.

Getting to the point, my FLC model is shown below:

Engine: IndoorOutdoor
InputVariable: Brightness
enabled: true
range: 0.000 1.000
term: Dark PiShape 0.000 0.000 0.050 0.200
term: Medium PiShape 0.100 0.200 0.400 0.600
term: Bright SShape 0.450 0.750
InputVariable: TimeOfDay
enabled: true
range: 0.000 1.000
term: Daytime Triangle 0.000 0.250 0.500
term: NightTime Triangle 0.500 0.750 1.000
InputVariable: MagneticVariance
enabled: true
range: 0.000 1.000
term: High PiShape 0.050 0.200 1.000 1.000
term: Low PiShape 0.000 0.000 0.050 0.100
InputVariable: DeviceMovement
enabled: true
range: 0.000 1.000
term: Moving Triangle 0.000 0.250 0.500
term: NotMoving Triangle 0.500 0.750 1.000
OutputVariable: BrightnessIndoorOutdoor
enabled: true
range: 0.000 1.000
accumulation: Maximum
defuzzifier: Centroid 200
default: nan
lock-previous: false
lock-range: false
term: SemiOutdoor Triangle 0.250 0.500 0.750
term: Indoor Triangle 0.000 0.250 0.500
term: Outdoor Triangle 0.500 0.750 1.000
OutputVariable: MagneticIndoorOutdoor
enabled: true
range: 0.000 1.000
accumulation: Maximum
defuzzifier: Centroid 200
default: nan
lock-previous: false
lock-range: false
term: SemiOutdoor Triangle 0.250 0.500 0.750
term: Indoor Triangle 0.000 0.250 0.500
term: Outdoor Triangle 0.500 0.750 1.000
RuleBlock: BrightnessIndoorOutdoorRB
enabled: true
conjunction: Minimum
disjunction: Maximum
activation: Minimum
rule: if Brightness is Dark and TimeOfDay is Daytime then BrightnessIndoorOutdoor is Indoor
rule: if Brightness is Dark and TimeOfDay is NightTime then BrightnessIndoorOutdoor is Outdoor with 0.75
rule: if Brightness is Dark and TimeOfDay is NightTime then BrightnessIndoorOutdoor is SemiOutdoor with 0.25
rule: if Brightness is Medium and TimeOfDay is Daytime then BrightnessIndoorOutdoor is Indoor
rule: if Brightness is Medium and TimeOfDay is NightTime then BrightnessIndoorOutdoor is Indoor with 0.5
rule: if Brightness is Bright and TimeOfDay is Daytime then BrightnessIndoorOutdoor is Outdoor with 0.75
rule: if Brightness is Bright and TimeOfDay is Daytime then BrightnessIndoorOutdoor is SemiOutdoor with 0.25
rule: if Brightness is Bright and TimeOfDay is NightTime then BrightnessIndoorOutdoor is Outdoor with 0.25
rule: if Brightness is Bright and TimeOfDay is NightTime then BrightnessIndoorOutdoor is SemiOutdoor with 0.75
RuleBlock: MagneticIndoorOutdoorRB
enabled: true
conjunction: Minimum
disjunction: Maximum
activation: Minimum
rule: if MagneticVariance is Low and DeviceMovement is Moving then MagneticIndoorOutdoor is Outdoor
rule: if MagneticVariance is High and DeviceMovement is Moving then MagneticIndoorOutdoor is Indoor with 0.75
rule: if MagneticVariance is High and DeviceMovement is Moving then MagneticIndoorOutdoor is SemiOutdoor with 0.25


My C++ code to process incoming data is:

if (data->input_data.movement == DEVICE_MOVEMENT_MOVING) {
indoorOutdoorEngine->getInputVariable("DeviceMovement")->setInputValue(DEVICE_MOVEMENT_MOVING_FLC_VALUE);
} else {
indoorOutdoorEngine->getInputVariable("DeviceMovement")->setInputValue(DEVICE_MOVEMENT_NOT_MOVING_FLC_VALUE);
}
indoorOutdoorEngine->getInputVariable("Brightness")->setInputValue(data->input_data.brightness);
if (data->input_data.daytime_or_nighttime) {
indoorOutdoorEngine->getInputVariable("TimeOfDay")->setInputValue(DAYTIME_CATEGORY_DAYTIME_FLC_VALUE);
} else {
indoorOutdoorEngine->getInputVariable("TimeOfDay")->setInputValue(DAYTIME_CATEGORY_NIGHTTIME_FLC_VALUE);
}
indoorOutdoorEngine->getInputVariable("MagneticVariance")->setInputValue(data->input_data.magnetic_variance);
indoorOutdoorEngine->process();
data->output_data.results[0] = indoorOutdoorEngine->getOutputValue("BrightnessIndoorOutdoor");
data->output_data.results_count++;
data->output_data.results[1] = indoorOutdoorEngine->getOutputValue("MagneticIndoorOutdoor");
data->output_data.results_count++;


Currently the fuzzy logic’s output result is simply a scalar – for example 0.25 or 0.33. Because the conjunction operator is Minimum, disjunction is Maximum, I want to know how can I map this scalar value back to the concerned fuzzy membership function? For example, with my logic, if the engine output is 0.25 – how do I know if it is indoor or outdoor or semi-outdoor?

Thanks,
Abhishek.

#1827

Hi Abhishek,

thank you for your kind words and contribution.

First, the output of your controller is a fuzzy value. For example, \tilde{y} = 0.3/indoor+0.4/outdoor+0.2/semioutdoor. This fuzzy output is then defuzzified, which results in the scalar value y=0.33 that you mention.

You are asking to find out whether your fuzzy output is indoor, outdoor, semioutdoor. And the answer is: it is likely to be a fuzzy value including all options. Having this in mind, I think what you may be after is what is the "truncated" output? removing all fuzziness.

You have two options.

(1) Fuzzification after Defuzzification: You take the output value y=2.5, and you find the Term in the OutputVariable with highest membership function for y, that is, the term with the highest \mu(y). You can do this by utilising Term* term = outputVariable->highestMembershipFunction(y);. Optionally, you can pass scalar highest to store the highest \mu(y): Term* term = outputVariable->highestMembershipFunction(y, &highest);. This will iterate over the terms in the OutputVariable and return the one with the highest \mu.

(2) FuzzyOutput. You find the term with the highest accumulated activation degree in your outputVariable->fuzzyOutput().

 scalar highestActivation = -fl::inf; scalar highestTerm = fl::null;
for const Term* term in OutputVariable:
scalar accumulatedActivation = outputVariable->fuzzyOutput()->activationDegree(term);
if (accumulatedActivation > highestActivation){
highestActivation = accumulatedActivation;
highestTerm = term;
}


I prefer (2) over (1) because in (1) you lose information after defuzzification.

Methods (1) and (2) can be clearly seen in QtFuzzyLite 5. In main window, on your OutputVariable, click on ỹ in ỹ=0.000/LOW + 0.320/MEDIUM + 0.680/HIGH. This will swap to μ(y)=0.000/LOW + 0.352/MEDIUM + 0.648/HIGH. As you can see, ỹ is (2), and μ(y) is (1).

Cheers.

#1828
senabhishek
Participant

Hey Juan,

Thanks a lot for the prompt answer! Yes – I was exactly looking for this. A couple of questions:

1. I will definitely go for approach since with approach 1 you will lose information as you mention. However, my question is what are some considerations one takes when you pick a specific methods of defuzzification and accumulation? In most of my models I am simply using Centroid for defuzzification and minimum for accumulation. Can you share some insight on this?
2. I am planning on using the accumulated activation degree as sort of a confidence rating for my outputs – any thoughts on this?

Cheers,
Abhishek.

#1842

Hi Abisheik,

(1) I think the best configuration is depends on the problem. Experiment and choose what you find better suits the problem. If you do not have a criteria to what suits your problem, I would suggest to continue using the Centroid, the Minimum (or AlgebraicProduct) as implication, and the Maximum (or AlgebraicSum) as the Accumulation.

(2) I think this depends on the problem too. Just remember that the output is fuzzy, and you are choosing only a part of the output to represent it. I think with this method you also lose information, as you are ignoring the membership functions of the other terms. Just be aware of this.

Cheers.

#1843

Oh,

could you please provide some information regarding what you did to incorporate fuzzylite in your Swift project? I would greatly appreciate any useful tips to achieve so.

#1852
senabhishek
Participant

Hey Juan,

To help you out I’ve created a sample Swift project that includes your source code (in the project). The model used is the default one available when you open the QT FuzzyLite application i.e. Ambient –> Power.

I’ve created a github repository at https://github.com/senabhishek/fuzzyliteAndSwift so enjoy! Once again, thank!

Cheers,
Abhishek.

#1853

Hi,

thank you for your time providing the details of using fuzzylite in Swift.

Could you please add all the *necessary* files regarding authorship and licensing of fuzzylite to your copy located in https://github.com/senabhishek/fuzzyliteAndSwift/tree/master/FuzzyLiteTemplate/fuzzylite? Otherwise, it is a violation of the licensing terms.

You may find the files in https://github.com/fuzzylite/fuzzylite.

Thanks.

#1854
senabhishek
Participant

Hey Juan,

I’ve added the necessary files to the repo and also referenced this site and the github repo for FuzzyLite in the README. Let me know if that’s fine.

Cheers,
Abhishek.

#1855

Hi Abhisek,

thank you for your prompt response.

The files should be within the fuzzylite folder (i.e., https://github.com/senabhishek/fuzzyliteAndSwift/tree/master/FuzzyLiteTemplate/fuzzylite) as you are the author of the swift template. Other than that, it is all good :).