home › Forums › # Technical Support › Map getOutputValue() to the concerned membership function
Tagged: iOS swift getOutputValue
- This topic has 8 replies, 2 voices, and was last updated 8 years, 3 months ago by
Juan Rada-Vilela (admin).
-
AuthorPosts
-
May 27, 2015 at 07:38 #1826
Unknown
MemberHi 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.May 27, 2015 at 13:17 #1827Juan Rada-Vilela (admin)
KeymasterHi 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 valuey=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 utilisingTerm* term = outputVariable->highestMembershipFunction(y);
. Optionally, you can passscalar 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).Please, let me know if this answers your question.
Cheers.
May 27, 2015 at 23:02 #1828Unknown
MemberHey 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.June 2, 2015 at 18:16 #1842Juan Rada-Vilela (admin)
KeymasterHi 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.
June 2, 2015 at 18:17 #1843Juan Rada-Vilela (admin)
KeymasterOh,
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.
June 9, 2015 at 02:03 #1852Unknown
MemberHey 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.June 9, 2015 at 17:13 #1853Juan Rada-Vilela (admin)
KeymasterHi,
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.
June 10, 2015 at 01:03 #1854Unknown
MemberHey 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.June 10, 2015 at 12:53 #1855Juan Rada-Vilela (admin)
KeymasterHi 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 :).
thanks again for your contribution!
Cheers.
-
AuthorPosts
- You must be logged in to reply to this topic.