arruda / scikit_fuzzy_fcl

A plugin for scikit-fuzzy that provides a parser for Fuzzy Control Language (as described in IEC 61131-7)
MIT License
2 stars 1 forks source link

Defining best way to read the mf values #2

Closed arruda closed 7 years ago

arruda commented 7 years ago

Description

I'm trying to find out how would be the best approach to instantiating the MFs of a Antecessor while parsing the FCL.

After messing with some code, and numpy.interp function, I've come to the conclusion that the best way to instantiate a Antecedent with the given MF's is to put the MF's information in some dict-like var when read (in the enterLinguistic_term and in the mf's own listener method, like enterPiece_wise_linear). In this information I could store for example the function that should be called to generate the values for the given MF. After that, in the exitLinguistic_term method, I can walk through all the MF's information and define the actual size of the MF's universe.

Then each MF type would have a function that can generate the pertinent values based on the final universe of the Antecedent. Ex: The piece wise function would do a simple np.interp with the values of x and y it had defined in the FCL, and the final universe of the the Antecedent: np.interp(universe, x_values, y_values) (need to put 0s outside of the defined x_values).

Not sure how this would be done with other functions, but I'm pretty sure I'll only have to put zeroes where values of x are not present in the MF X range, and then call the function for the given MF in the x values that are present in the MF definition.

JDWarner commented 7 years ago

I'm not familiar with the inner workings of the FCL format, so pardon me for misunderstanding or if these are obvious questions.

If the first point (paired values) above is true, then you can simply append values as obtained into two lists, one for membership values and the other for corresponding universe values. Once all relevant points are read in, these can be passed directly in to an Antecedent object. That is, if they were read in monotonically increasing order on the universe.

If they are not guaranteed to be in monotonically increasing order on the universe, you can use np.asarray and sort the array using np.argsort, i.e.

idx = np.argsort(np.asarray(raw_universe))
sorted_universe = raw_universe[idx]
sorted_mf = raw_mf[idx]  # sorts the mf values appropriately

I ask about discontinuities because there is at present no provision for a true discontinuity in skfuzzy.control.

If the above approach is used, I don't think you'd need to interpolate anything at all. scikit-fuzzy takes care of this as needed during computation. Simply toss in the data from the FCL and go (unless I'm missing something, entirely possible).

Regarding storing results temporarily in a dictionary - this worries me because dictionaries do not guarantee ordered iteration. If you want to be able to iterate back through them in the same order, that would require an OrderedDict object. But, as above, I'm not sure you need anything more complex than two lists.

arruda commented 7 years ago

Hi there @JDWarner, thank's for the tips . So answering your questions:

How is the actual MF data stored and read from an FCL file? It seems there would have to be pairs of values, one with the universe point and the other with the corresponding membership at that value.

Yes and no. The simplest way one can define a MF is to define this points. But one could also define them as a function and they're parameters. ex:

        FUNCTION_BLOCK f_block
            FUZZIFY some_antecedent
                TERM mf := GAUSS 10 20;
            END_FUZZIFY
        END_FUNCTION_BLOCK

If there are pairs of points, are they arranged in monotonically increasing order on the universe?

I don't recall seen this in the IEC description, so for now I'm sorting the values to guarantee they that they are ordered by their value in the (value, MF value) pair.

Are there provisions for discontinuities?

Some one can define a Antecedent like this:

        FUNCTION_BLOCK my_system
            FUZZIFY antecedent1
                TERM mf1 := (0, 1) (0.5, 0);
                TERM mf2 := (1, 0.3) (2, 0) (3, 1);
                TERM mf3 := (2, 0.4) (4, 1) (5, 1);
            END_FUZZIFY
        END_FUNCTION_BLOCK

In this case the universe for the antecedent should be [0, 0.5, 1, 2, 3, 4, 5] But the term mf3 don't have anything defined for the value 3. So what I thought was to make, in the term mf3 for example, it's MF's value like this: [0, 0, 0, 0.4, X, 1, 1] Where X would be a interpolation of (2, 0.4) and (4, 1) and all for all other values universe that were not defined in the MF (in the FCL) would be set to 0.

Regarding storing results temporarily in a dictionary - this worries me because dictionaries do not guarantee ordered iteration. If you want to be able to iterate back through them in the same order, that would require an OrderedDict object. But, as above, I'm not sure you need anything more complex than two lists.

I was thinking in a OnderedDict, I'm just trying out with piece wise MFs, but for other types (COSINE, GAUSS and etc) I'm not sure it will be just two list. And using a OrderedDict I can also easily access a term by it's ID or get the last one by the keys order :smile: .

Another think that I'll have to take into consideration is that a given Antecedent could be defined by different types os MF:

        FUNCTION_BLOCK f_block
            FUZZIFY antecedent_1
                TERM mf1 := GAUSS a b;  // a , b ,c ,d ,e   are the numbers used as args for this functions
                TERM mf2 := GBELL c d e;
            END_FUZZIFY
        END_FUNCTION_BLOCK
arruda commented 7 years ago

Arg... ok... So there is a problem in what I was doing... I was basing myself in JFuzzyLogic grammar for FCL... And I'm not sure what parts of it are compliant to FCL and what parts where added to simplify the reading of the FCL to JFuzzyLogic's classes.

After some a long time of thinking I've decided to re-read the IEC 61131-7 version that's available for free...And considering this version only I can say that JFuzzyLogic's grammar is full of different things...

The problem is that IEC61131 is a paid publication, and this free version is just the draft for the version 1 release in 1997. So I'm not sure if what's present in JFuzzyLogic's grammar is part of the complete version of this IEC document, or just stuff the author created to make his work easier.

But, there is a light in the end of the tunnel. In the Free Fuzzy Logic Library page there's some information regarding what they've done for their FCL part. There they say that they only comply with the Table 6.1-1: FCL Basic Level language elements (mandatory), and after that they make it very clear what part of the FCL definition is missing from their software and what are additions that they've made.

This is very nice because it gives more tips on the FCL definition for certain parts that are not very clear in the draft version (ex: input/outpur vars's range).

And according to the draft Table 6.1-3: Examples of List with Open Level language elements:

free input/output membership functions (e.g. Gaussian, exponential) more than four membership function points please dream on .....

And if we consider this tips from FFLL and the draft version, then one can conclude that the MF's types used in the JFuzzyLogic were additions made by the tool author that would fit in the Open Level Language Elements. While the minimum compliance for a MF type is by using a singleton or pointwise: membership_function ::= singleton | points.

So for now I'll just consider piecewise and singleton as possible MF's types in the FCL declaration, and in the future, if needed, it should be possible to add more function types as we see fit, and by the "please dream on" statement I conclude that you can define freely anything you can think of.