Changeset 791 for cpp/frams/neuro


Ignore:
Timestamp:
05/29/18 16:24:39 (7 years ago)
Author:
Maciej Komosinski
Message:

Code formatting

Location:
cpp/frams/neuro/impl
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • cpp/frams/neuro/impl/neuroimpl-body-sdk.h

    r288 r791  
    88#include <frams/neuro/neuroimpl.h>
    99
    10 class NI_Gyro: public NeuroImpl
     10class NI_Gyro : public NeuroImpl
    1111{
    1212public:
    13 NeuroImpl* makeNew(){return new NI_Gyro();} // for NeuroFactory
    14 int lateinit() {if (!neuro->joint) return 0; simorder=0; return 1;}
    15 void go() {setState(0);}
     13        NeuroImpl* makeNew(){ return new NI_Gyro(); } // for NeuroFactory
     14        int lateinit() { if (!neuro->joint) return 0; simorder = 0; return 1; }
     15        void go() { setState(0); }
    1616};
    1717
    1818extern ParamEntry NI_Touch_tab[];
    19 class NI_Touch: public NeuroImpl
     19class NI_Touch : public NeuroImpl
    2020{
    2121public:
    22 double range;
    23 NeuroImpl* makeNew(){return new NI_Touch();} // for NeuroFactory
    24 int lateinit() {if (!neuro->part) return 0; simorder=0; return 1;}
    25 void go() {setState(0);}
    26 NI_Touch():range(1) {paramentries=NI_Touch_tab;}
     22        double range;
     23        NeuroImpl* makeNew(){ return new NI_Touch(); } // for NeuroFactory
     24        int lateinit() { if (!neuro->part) return 0; simorder = 0; return 1; }
     25        void go() { setState(0); }
     26        NI_Touch() :range(1) { paramentries = NI_Touch_tab; }
    2727};
    2828
    29 class NI_Smell: public NeuroImpl
     29class NI_Smell : public NeuroImpl
    3030{
    3131public:
    32 NeuroImpl* makeNew(){return new NI_Smell();} // for NeuroFactory
    33 void go() {setState(0);}
    34 int lateinit() {if (!neuro->part) return 0; simorder=0; return 1;}
     32        NeuroImpl* makeNew(){ return new NI_Smell(); } // for NeuroFactory
     33        void go() { setState(0); }
     34        int lateinit() { if (!neuro->part) return 0; simorder = 0; return 1; }
    3535};
    3636
    3737extern ParamEntry NI_BendMuscle_tab[];
    38 class NI_BendMuscle: public NeuroImpl
     38class NI_BendMuscle : public NeuroImpl
    3939{
    4040public:
    41 double power,bendrange;
    42 NeuroImpl* makeNew(){return new NI_BendMuscle();} // for NeuroFactory
    43 NI_BendMuscle() {paramentries=NI_BendMuscle_tab;}
    44 int lateinit() {if (!neuro->joint) return 0; simorder=2; return 1;}
    45 void go() {}
     41        double power, bendrange;
     42        NeuroImpl* makeNew(){ return new NI_BendMuscle(); } // for NeuroFactory
     43        NI_BendMuscle() { paramentries = NI_BendMuscle_tab; }
     44        int lateinit() { if (!neuro->joint) return 0; simorder = 2; return 1; }
     45        void go() {}
    4646};
    4747
    4848extern ParamEntry NI_RotMuscle_tab[];
    49 class NI_RotMuscle: public NeuroImpl
     49class NI_RotMuscle : public NeuroImpl
    5050{
    5151public:
    52 double power;
    53 NeuroImpl* makeNew(){return new NI_RotMuscle();} // for NeuroFactory
    54 NI_RotMuscle() {paramentries=NI_RotMuscle_tab;}
    55 int lateinit() {if (!neuro->joint) return 0; simorder=2; return 1;}
    56 void go() {}
     52        double power;
     53        NeuroImpl* makeNew(){ return new NI_RotMuscle(); } // for NeuroFactory
     54        NI_RotMuscle() { paramentries = NI_RotMuscle_tab; }
     55        int lateinit() { if (!neuro->joint) return 0; simorder = 2; return 1; }
     56        void go() {}
    5757};
    5858
    5959extern ParamEntry NI_LinearMuscle_tab[];
    60 class NI_LinearMuscle: public NeuroImpl
     60class NI_LinearMuscle : public NeuroImpl
    6161{
    6262public:
    63 double power;
    64 NeuroImpl* makeNew(){return new NI_RotMuscle();} // for NeuroFactory
    65 NI_LinearMuscle() {paramentries=NI_RotMuscle_tab;}
    66 int lateinit() {if (!neuro->joint) return 0; simorder=2; return 1;}
    67 void go() {}
     63        double power;
     64        NeuroImpl* makeNew(){ return new NI_RotMuscle(); } // for NeuroFactory
     65        NI_LinearMuscle() { paramentries = NI_RotMuscle_tab; }
     66        int lateinit() { if (!neuro->joint) return 0; simorder = 2; return 1; }
     67        void go() {}
    6868};
    6969
    70 class NI_Sticky: public NeuroImpl
     70class NI_Sticky : public NeuroImpl
    7171{
    7272public:
    73 double power;
    74 NeuroImpl* makeNew(){return new NI_Sticky();} // for NeuroFactory
    75 int lateinit() {if (!neuro->part) return 0; simorder=0; return 1;}
    76 void go() {}
     73        double power;
     74        NeuroImpl* makeNew(){ return new NI_Sticky(); } // for NeuroFactory
     75        int lateinit() { if (!neuro->part) return 0; simorder = 0; return 1; }
     76        void go() {}
    7777};
    7878
    79 class NI_WaterDetect: public NeuroImpl
     79class NI_WaterDetect : public NeuroImpl
    8080{
    8181public:
    82 NeuroImpl* makeNew(){return new NI_WaterDetect();} // for NeuroFactory
    83 int lateinit() {if (!neuro->part) return 0; simorder=0; return 1;}
    84 void go() {setState(0);}
     82        NeuroImpl* makeNew(){ return new NI_WaterDetect(); } // for NeuroFactory
     83        int lateinit() { if (!neuro->part) return 0; simorder = 0; return 1; }
     84        void go() { setState(0); }
    8585};
    8686
    87 class NI_Energy: public NeuroImpl
     87class NI_Energy : public NeuroImpl
    8888{
    8989public:
    90 NeuroImpl* makeNew(){return new NI_Energy();} // for NeuroFactory
    91 void go() {setState(0);}
     90        NeuroImpl* makeNew(){ return new NI_Energy(); } // for NeuroFactory
     91        void go() { setState(0); }
    9292};
    9393
    9494#endif
    95 
  • cpp/frams/neuro/impl/neuroimpl-channels.cpp

    r286 r791  
    88void NI_Channelize::go()
    99{
    10 setChannelCount(getInputCount());
    11 for(int i=0;i<getInputCount();i++)
    12         setState(getWeightedInputState(i),i);
     10        setChannelCount(getInputCount());
     11        for (int i = 0; i < getInputCount(); i++)
     12                setState(getWeightedInputState(i), i);
    1313}
    1414
    1515void NI_ChMux::go()
    1616{
    17 int c=getInputChannelCount(1);
    18 if (c<2) {setState(getWeightedInputState(1)); return;}
    19 double s=getWeightedInputState(0);
    20 s=(max(-1.0,min(1.0,s))+1.0)/2.0; // 0..1
    21 int i1;
    22 i1=(int)(s*(c-1)); i1=max(0,min(i1,c-2));
    23 double sw=1.0/(c-1);
    24 double s1=sw*i1;
    25 double w1=fabs((s-s1)/sw);
    26 double w2=1.0-w1;
    27 double is1=getWeightedInputState(1,i1);
    28 double is2=getWeightedInputState(1,i1+1);
    29 setState(is1*w2 + is2*w1);
     17        int c = getInputChannelCount(1);
     18        if (c < 2) { setState(getWeightedInputState(1)); return; }
     19        double s = getWeightedInputState(0);
     20        s = (max(-1.0, min(1.0, s)) + 1.0) / 2.0; // 0..1
     21        int i1;
     22        i1 = (int)(s*(c - 1)); i1 = max(0, min(i1, c - 2));
     23        double sw = 1.0 / (c - 1);
     24        double s1 = sw*i1;
     25        double w1 = fabs((s - s1) / sw);
     26        double w2 = 1.0 - w1;
     27        double is1 = getWeightedInputState(1, i1);
     28        double is2 = getWeightedInputState(1, i1 + 1);
     29        setState(is1*w2 + is2*w1);
    3030}
    3131
    3232void NI_ChSel::go()
    3333{
    34 setState(getWeightedInputState(0,ch));
     34        setState(getWeightedInputState(0, ch));
    3535}
  • cpp/frams/neuro/impl/neuroimpl-channels.h

    r286 r791  
    88#include <frams/neuro/neuroimpl.h>
    99
    10 class NI_Channelize: public NeuroImpl
     10class NI_Channelize : public NeuroImpl
    1111{
    1212public:
    13 NeuroImpl* makeNew(){return new NI_Channelize();} // for NeuroFactory
    14 void go();
     13        NeuroImpl* makeNew(){ return new NI_Channelize(); } // for NeuroFactory
     14        void go();
    1515};
    1616
    17 class NI_ChMux: public NeuroImpl
     17class NI_ChMux : public NeuroImpl
    1818{
    1919public:
    20 NeuroImpl* makeNew(){return new NI_ChMux();} // for NeuroFactory
    21 void go();
     20        NeuroImpl* makeNew(){ return new NI_ChMux(); } // for NeuroFactory
     21        void go();
    2222};
    2323
    2424extern ParamEntry NI_ChSel_tab[];
    2525
    26 class NI_ChSel: public NeuroImpl
     26class NI_ChSel : public NeuroImpl
    2727{
    2828public:
    29 int ch; // channel
    30 NI_ChSel():ch(0) {paramentries=NI_ChSel_tab;}
    31 NeuroImpl* makeNew(){return new NI_ChSel();} // for NeuroFactory
    32 void go();
     29        int ch; // channel
     30        NI_ChSel() :ch(0) { paramentries = NI_ChSel_tab; }
     31        NeuroImpl* makeNew(){ return new NI_ChSel(); } // for NeuroFactory
     32        void go();
    3333};
    3434
     
    3636#endif
    3737
    38 
    39 
  • cpp/frams/neuro/impl/neuroimpl-fuzzy-f0.cpp

    r348 r791  
    1414int FuzzyF0String::convertStrToSets(const SString& str, double numbers[], int nrOfSets)
    1515{
    16   int pos=0;
    17   SString t;
    18   int have=0;
    19   int maxnumbers=4*nrOfSets; //number of semicolons should be equal 4*nrOfSets
     16        int pos = 0;
     17        SString t;
     18        int have = 0;
     19        int maxnumbers = 4 * nrOfSets; //number of semicolons should be equal 4*nrOfSets
    2020
    21   while (str.getNextToken(pos,t,';'))
    22     if (have>=maxnumbers)
    23       break;
    24     else
    25       numbers[have++]=atof(t.c_str());
     21        while (str.getNextToken(pos, t, ';'))
     22                if (have >= maxnumbers)
     23                        break;
     24                else
     25                        numbers[have++] = atof(t.c_str());
    2626
    27   //check if number of read numbers (separated with semicolon) is equal to declared
    28   if (have != 4*nrOfSets)
    29     return -1; //number of sets found is lower than declared!
     27        //check if number of read numbers (separated with semicolon) is equal to declared
     28        if (have != 4 * nrOfSets)
     29                return -1; //number of sets found is lower than declared!
    3030
    31   //check corectness of sets - must not be decreasing
    32   for(int i=0;i<nrOfSets;i++)
    33     if((numbers[4*i]>numbers[4*i+1])||(numbers[4*i+1]>numbers[4*i+2])||(numbers[4*i+2]>numbers[4*i+3]))
    34       return -2; //error
     31        //check corectness of sets - must not be decreasing
     32        for (int i = 0; i < nrOfSets; i++)
     33                if ((numbers[4 * i] > numbers[4 * i + 1]) || (numbers[4 * i + 1] > numbers[4 * i + 2]) || (numbers[4 * i + 2] > numbers[4 * i + 3]))
     34                        return -2; //error
    3535
    36   return 0;
     36        return 0;
    3737}
    3838
     
    4747int FuzzyF0String::countInputsOutputs(const char* str, int ruldef[], int rulesNr)
    4848{ //ruledef will remember counted number of inputs and outputs for every rule
    49   const char* t;
    50   int separators=0, inouts=0;
     49        const char* t;
     50        int separators = 0, inouts = 0;
    5151
    52   for(t=str;*t;t++)
    53   {
    54     while(isdigit(*t))
    55       t++; //only count, does not care about numbers now
    56     if (!*t)
    57       break; //end of the string - get out of 'for' loop
    58     if ( (*t==';')||(*t==':')||(*t=='/') ) //found sth different than digit - it must be a separator
    59     {
    60       separators++; //one of separators
    61       if (*t!=';') // end of [conditional part of] rule
    62       {
    63         if (inouts >= 2*rulesNr) //more rules declared in string than declared in rulesNr
    64           return -2;
    65         ruldef[inouts]=(separators+1)/2; //cause fuzzy sets - for 1 in/out there are 2 semicolons
    66         separators=0;  //begin counting number of in/out from zero
    67         inouts++; //next part of rule / or next rule
    68       }
    69     }
    70     else // illegal character
    71       return -1;
    72   }
     52        for (t = str; *t; t++)
     53        {
     54                while (isdigit(*t))
     55                        t++; //only count, does not care about numbers now
     56                if (!*t)
     57                        break; //end of the string - get out of 'for' loop
     58                if ((*t == ';') || (*t == ':') || (*t == '/')) //found sth different than digit - it must be a separator
     59                {
     60                        separators++; //one of separators
     61                        if (*t != ';') // end of [conditional part of] rule
     62                        {
     63                                if (inouts >= 2 * rulesNr) //more rules declared in string than declared in rulesNr
     64                                        return -2;
     65                                ruldef[inouts] = (separators + 1) / 2; //cause fuzzy sets - for 1 in/out there are 2 semicolons
     66                                separators = 0;  //begin counting number of in/out from zero
     67                                inouts++; //next part of rule / or next rule
     68                        }
     69                }
     70                else // illegal character
     71                        return -1;
     72        }
    7373
    74   //check, if nr of found rules is equal to declared
    75   if (inouts == 2*rulesNr) //each rule has a conditional part (inputs) and decisional part (outputs)
    76     return 0;
    77   else
    78     return -5; // ShowMessage("Inconsistent number of rules!");
     74        //check, if nr of found rules is equal to declared
     75        if (inouts == 2 * rulesNr) //each rule has a conditional part (inputs) and decisional part (outputs)
     76                return 0;
     77        else
     78                return -5; // ShowMessage("Inconsistent number of rules!");
    7979}
    8080
     
    8383int FuzzyF0String::convertStrToRules(const SString& str, const int ruledef[], int **rules, int setsNr, int rulesNr, int &maxOutputNr)
    8484{
    85   int pos=0, j, k, len=str.len();
    86   int dNr=0, sNr=0;
    87   int inNr, outNr; //number of inputs/outputs and corresponding fuzzy sets
    88   SString t;
    89   bool conditional=true; //which part of rule: conditional or decisional
     85        int pos = 0, j, k, len = str.len();
     86        int dNr = 0, sNr = 0;
     87        int inNr, outNr; //number of inputs/outputs and corresponding fuzzy sets
     88        SString t;
     89        bool conditional = true; //which part of rule: conditional or decisional
    9090
    91   maxOutputNr=0; //sets maximum output nr found in rules string
     91        maxOutputNr = 0; //sets maximum output nr found in rules string
    9292
    93   //check corectness of the string: number semicolon ... separated with colon or slash
    94   while(pos<len)
    95   {
    96     while((pos<len)&&(isdigit(str.charAt(pos)))) pos++;
    97     if(!(pos<len))
    98       break; //end of the string
    99     if(str.charAt(pos)!=';')
    100       if((str.charAt(pos)==':')&&(conditional))
    101         {sNr++; conditional=false;}
    102       else if((str.charAt(pos)=='/')&&(!conditional))
    103         {dNr++; conditional=true;}
    104       else
    105         return -4; //error - illegal character
    106     pos++;
    107   }
    108   if( (dNr!=sNr) || (dNr!=rulesNr) )
    109     return -5; //error - wrong number of rules
     93        //check corectness of the string: number semicolon ... separated with colon or slash
     94        while (pos < len)
     95        {
     96                while ((pos < len) && (isdigit(str.charAt(pos)))) pos++;
     97                if (!(pos < len))
     98                        break; //end of the string
     99                if (str.charAt(pos) != ';')
     100                        if ((str.charAt(pos) == ':') && (conditional))
     101                        {
     102                        sNr++; conditional = false;
     103                        }
     104                        else if ((str.charAt(pos) == '/') && (!conditional))
     105                        {
     106                                dNr++; conditional = true;
     107                        }
     108                        else
     109                                return -4; //error - illegal character
     110                        pos++;
     111        }
     112        if ((dNr != sNr) || (dNr != rulesNr))
     113                return -5; //error - wrong number of rules
    110114
    111   pos=0;
     115        pos = 0;
    112116
    113   for(j=0;j<rulesNr;j++)
    114   { //sum of inputs and outputs
    115     inNr = 2*ruledef[2*j];
    116     outNr = 2*ruledef[2*j+1];
    117     for(k=0;k<inNr+outNr;k++)
    118     {
    119       t = ""; //clear previous value
    120       //cuts next integer values
    121       while ( (pos<len)&&(isdigit(str.charAt(pos))) )
    122         t += str.charAt(pos++);
    123       pos++;
    124       rules[j][k]=atol(t.c_str()); //convert cut out string into number
    125       //fuzzy sets - odd index table - are counted from 0,
    126       //so if 5 fuzzy sets declared, values acceptable are 0,1,2,3,4
    127       if ( ((k%2)!=0) && (rules[j][k] >= setsNr) )
    128         return -1;
    129       if((k>=inNr)&&((k%2)==0))
    130         maxOutputNr=max(maxOutputNr,rules[j][k]);
    131     }
    132   }
    133   return 0;
     117        for (j = 0; j < rulesNr; j++)
     118        { //sum of inputs and outputs
     119                inNr = 2 * ruledef[2 * j];
     120                outNr = 2 * ruledef[2 * j + 1];
     121                for (k = 0; k < inNr + outNr; k++)
     122                {
     123                        t = ""; //clear previous value
     124                        //cuts next integer values
     125                        while ((pos < len) && (isdigit(str.charAt(pos))))
     126                                t += str.charAt(pos++);
     127                        pos++;
     128                        rules[j][k] = atol(t.c_str()); //convert cut out string into number
     129                        //fuzzy sets - odd index table - are counted from 0,
     130                        //so if 5 fuzzy sets declared, values acceptable are 0,1,2,3,4
     131                        if (((k % 2) != 0) && (rules[j][k] >= setsNr))
     132                                return -1;
     133                        if ((k >= inNr) && ((k % 2) == 0))
     134                                maxOutputNr = max(maxOutputNr, rules[j][k]);
     135                }
     136        }
     137        return 0;
    134138}
    135 
  • cpp/frams/neuro/impl/neuroimpl-fuzzy-f0.h

    r286 r791  
    33// See LICENSE.txt for details.
    44
    5 /// this is a module included into neuroimpl-fuzzy
    6 /// it converts string parameters - fuzzy sets and fuzzy rules - into appropriate variables
     5/// This is a module included into neuroimpl-fuzzy.
     6/// It converts string parameters (fuzzy sets and fuzzy rules) into appropriate variables.
    77
    88#ifndef _neuroimpl_fuzzy_f0_h
     
    1414class FuzzyF0String
    1515{
    16   public:
    17   static int convertStrToSets(const SString& str, double numbers[], int nrOfSets);
    18   static int countInputsOutputs(const char* str, int ruldef[], int rulesNr);
    19   static int convertStrToRules(const SString& str, const int ruledef[], int **rules, int setsNr, int rulesNr, int &maxOutputNr);
     16public:
     17        static int convertStrToSets(const SString& str, double numbers[], int nrOfSets);
     18        static int countInputsOutputs(const char* str, int ruldef[], int rulesNr);
     19        static int convertStrToRules(const SString& str, const int ruledef[], int **rules, int setsNr, int rulesNr, int &maxOutputNr);
    2020};
    2121
  • cpp/frams/neuro/impl/neuroimpl-fuzzy.cpp

    r348 r791  
    99int NI_FuzzyNeuro::countOuts(const Model *m, const Neuro *fuzzy)
    1010{
    11   int outputs=0;
    12   for(int i=0;i<m->getNeuroCount();i++)
    13      for(int in=0;in<m->getNeuro(i)->getInputCount();in++)
    14         if (m->getNeuro(i)->getInput(in)==fuzzy) outputs++;
    15   return outputs;
     11        int outputs = 0;
     12        for (int i = 0; i < m->getNeuroCount(); i++)
     13                for (int in = 0; in < m->getNeuro(i)->getInputCount(); in++)
     14                        if (m->getNeuro(i)->getInput(in) == fuzzy) outputs++;
     15        return outputs;
    1616}
    1717
    1818int NI_FuzzyNeuro::lateinit()
    1919{
    20   int i, maxOutputNr;
    21 
    22   //check correctness of given parameters: string must not be null, sets&rules number > 0
    23   if((fuzzySetsNr<1)||(rulesNr<1)||(fuzzySetString.len()==0)||(fuzzyRulesString.len()==0))
    24     return 0; //error
    25 
    26   // this part contains transformation of fuzzy sets
    27   fuzzySets = new double[4*fuzzySetsNr]; //because every fuzzy set consist of 4 numbers
    28   // converts fuzzy string from f0 to table of fuzzy numbers type 'double'
    29   // (fill created space with numbers taken from string)
    30   // also checks whether number of fuzzy sets in the string equals declared in the definition
    31   if (FuzzyF0String::convertStrToSets(fuzzySetString, fuzzySets, fuzzySetsNr) != 0)
    32     return 0; //error
    33 
    34   // this part contains transformation of fuzzy rules and defuzzyfication parameters
    35   rulesDef = new int[2*rulesNr];    //for each rule remembers number of inputs and outputs
    36   //check correctness of string and fill in the rulesDef
    37   if (FuzzyF0String::countInputsOutputs(fuzzyRulesString.c_str(), rulesDef, rulesNr) == 0)
    38   {
    39     defuzzParam = new double[rulesNr]; // parameters used in defuzyfication process
    40     // create space for rules according to rulesDef
    41     rules = new int*[rulesNr];   //list of rules...
    42     for (i=0; i<rulesNr; i++)    //...that contains rules body
    43     {
    44       rules[i] = new int[2*(rulesDef[2*i]+rulesDef[2*i+1])];  //each rule can have different number of inputs and outputs
    45       defuzzParam[i] = 0; //should be done a little bit earlier, but why do not use this loop?
    46     }
    47     // fill created space with numbers taken from string
    48     if (FuzzyF0String::convertStrToRules(fuzzyRulesString, rulesDef, rules, fuzzySetsNr, rulesNr, maxOutputNr) != 0)
    49       return 0; //error
    50   }
    51   else
    52     return 0; //error
    53 
    54   setChannelCount(countOuts(neuro->owner, neuro));
    55   return 1; //success
     20        int i, maxOutputNr;
     21
     22        //check correctness of given parameters: string must not be null, sets&rules number > 0
     23        if ((fuzzySetsNr < 1) || (rulesNr < 1) || (fuzzySetString.len() == 0) || (fuzzyRulesString.len() == 0))
     24                return 0; //error
     25
     26        // this part contains transformation of fuzzy sets
     27        fuzzySets = new double[4 * fuzzySetsNr]; //because every fuzzy set consist of 4 numbers
     28        // converts fuzzy string from f0 to table of fuzzy numbers type 'double'
     29        // (fill created space with numbers taken from string)
     30        // also checks whether number of fuzzy sets in the string equals declared in the definition
     31        if (FuzzyF0String::convertStrToSets(fuzzySetString, fuzzySets, fuzzySetsNr) != 0)
     32                return 0; //error
     33
     34        // this part contains transformation of fuzzy rules and defuzzyfication parameters
     35        rulesDef = new int[2 * rulesNr];    //for each rule remembers number of inputs and outputs
     36        //check correctness of string and fill in the rulesDef
     37        if (FuzzyF0String::countInputsOutputs(fuzzyRulesString.c_str(), rulesDef, rulesNr) == 0)
     38        {
     39                defuzzParam = new double[rulesNr]; // parameters used in defuzyfication process
     40                // create space for rules according to rulesDef
     41                rules = new int*[rulesNr];   //list of rules...
     42                for (i = 0; i < rulesNr; i++)    //...that contains rules body
     43                {
     44                        rules[i] = new int[2 * (rulesDef[2 * i] + rulesDef[2 * i + 1])];  //each rule can have different number of inputs and outputs
     45                        defuzzParam[i] = 0; //should be done a little bit earlier, but why do not use this loop?
     46                }
     47                // fill created space with numbers taken from string
     48                if (FuzzyF0String::convertStrToRules(fuzzyRulesString, rulesDef, rules, fuzzySetsNr, rulesNr, maxOutputNr) != 0)
     49                        return 0; //error
     50        }
     51        else
     52                return 0; //error
     53
     54        setChannelCount(countOuts(neuro->owner, neuro));
     55        return 1; //success
    5656}
    5757
    5858NI_FuzzyNeuro::~NI_FuzzyNeuro()
    5959{
    60   if(rules) //delete rows and columns of **rules
    61   {
    62     for (int i=0; i<rulesNr; i++) SAFEDELETEARRAY(rules[i])
    63     SAFEDELETEARRAY(rules)
    64   }
    65   SAFEDELETEARRAY(defuzzParam)
    66   SAFEDELETEARRAY(rulesDef)
    67   SAFEDELETEARRAY(fuzzySets)
     60        if (rules) //delete rows and columns of **rules
     61        {
     62                for (int i = 0; i < rulesNr; i++) SAFEDELETEARRAY(rules[i])
     63                        SAFEDELETEARRAY(rules)
     64        }
     65        SAFEDELETEARRAY(defuzzParam)
     66                SAFEDELETEARRAY(rulesDef)
     67                SAFEDELETEARRAY(fuzzySets)
    6868}
    6969
    7070int NI_FuzzyNeuro::GetFuzzySetParam(int set_nr, double &left, double &midleft, double &midright, double &right)
    7171{
    72   if ( (set_nr>=0) && (set_nr<fuzzySetsNr) )
    73   {
    74     left = fuzzySets[4*set_nr];
    75     midleft = fuzzySets[4*set_nr+1];
    76     midright = fuzzySets[4*set_nr+2];
    77     right = fuzzySets[4*set_nr+3];
    78     return 0;
    79   }
    80   else
    81     return 1;
     72        if ((set_nr >= 0) && (set_nr < fuzzySetsNr))
     73        {
     74                left = fuzzySets[4 * set_nr];
     75                midleft = fuzzySets[4 * set_nr + 1];
     76                midright = fuzzySets[4 * set_nr + 2];
     77                right = fuzzySets[4 * set_nr + 3];
     78                return 0;
     79        }
     80        else
     81                return 1;
    8282}
    8383
     
    8585void NI_FuzzyNeuro::go()
    8686{
    87   if (Fuzzyfication()!=0)
    88     return;
    89   if (Defuzzyfication()!=0)
    90     return;
     87        if (Fuzzyfication() != 0)
     88                return;
     89        if (Defuzzyfication() != 0)
     90                return;
    9191}
    9292
     
    9797int NI_FuzzyNeuro::Fuzzyfication()
    9898{
    99   int i, j, nrIn, inputNr, nrFuzzySet;
    100   double minimumCut; // actual minimal level of cut (= min. membership function)
    101 
    102   // sets defuzzyfication parameters for each rule:
    103   for (i=0; i<rulesNr; i++)
    104   {
    105     nrIn = rulesDef[2*i]; // nr of inputs in rule #i
    106     minimumCut = 2; // the highest value of membership function is 1.0, so this value will definitely change
    107     for (j=0; (j<nrIn)&&(minimumCut>0); j++) //minimumCut can not be <0, so if =0 then stop calculations
    108     {
    109       nrFuzzySet = rules[i][j*2 + 1]; // j*2 moves pointer through each output, +1 moves to nr of fuzzy set
    110       inputNr = rules[i][j*2]; // as above but gives input number
    111       minimumCut = min( minimumCut, TrapeziumFuzz(nrFuzzySet, getWeightedInputState(inputNr))); // value of membership function for this input and given fuzzy set
    112     }
    113     if ( (minimumCut>1) || (minimumCut<0) )
    114       return 1;
    115     defuzzParam[i] = minimumCut;
    116   }
    117   return 0;
     99        int i, j, nrIn, inputNr, nrFuzzySet;
     100        double minimumCut; // actual minimal level of cut (= min. membership function)
     101
     102        // sets defuzzyfication parameters for each rule:
     103        for (i = 0; i < rulesNr; i++)
     104        {
     105                nrIn = rulesDef[2 * i]; // nr of inputs in rule #i
     106                minimumCut = 2; // the highest value of membership function is 1.0, so this value will definitely change
     107                for (j = 0; (j < nrIn) && (minimumCut>0); j++) //minimumCut can not be <0, so if =0 then stop calculations
     108                {
     109                        nrFuzzySet = rules[i][j * 2 + 1]; // j*2 moves pointer through each output, +1 moves to nr of fuzzy set
     110                        inputNr = rules[i][j * 2]; // as above but gives input number
     111                        minimumCut = min(minimumCut, TrapeziumFuzz(nrFuzzySet, getWeightedInputState(inputNr))); // value of membership function for this input and given fuzzy set
     112                }
     113                if ((minimumCut>1) || (minimumCut < 0))
     114                        return 1;
     115                defuzzParam[i] = minimumCut;
     116        }
     117        return 0;
    118118}
    119119
     
    127127double NI_FuzzyNeuro::TrapeziumFuzz(int which_fuzzy_set, double input_val)
    128128{
    129   double range=0, left=0, midleft=0, midright=0, right=0;
    130 
    131   if ( (which_fuzzy_set < 0) || (which_fuzzy_set > fuzzySetsNr) )
    132     return -2;
    133   if ( (input_val < -1) || (input_val > 1) )
    134     return -3;
    135 
    136   if (GetFuzzySetParam(which_fuzzy_set, left, midleft, midright, right) != 0)
    137     return -4;
    138 
    139   if ( (input_val < left) || (input_val > right) ) // greather than right value
    140     return 0;
    141   else if ( (input_val >= midleft) && (input_val <= midright) ) // in the core of fuzzy set
    142     return 1;
    143   else if ( (input_val >= left) && (input_val < midleft) ) // at the left side of trapezium
    144   {
    145     range = fabs(midleft - left);
    146     return fabs(input_val-left)/((range>0)?range:1); // quotient of distance between input and extreme left point of trapezium and range of rising side, or 1
    147   }
    148   else if ( (input_val > midright) && (input_val <= right) ) // at the right side of trapezium
    149   {
    150     range = fabs(right - midright);
    151     return fabs(right-input_val)/((range>0)?range:1); // quotient of distance between input and extreme right point of trapezium and range of falling side, or 1
    152   };
    153 
    154   // should not occur
    155   return 0;
     129        double range = 0, left = 0, midleft = 0, midright = 0, right = 0;
     130
     131        if ((which_fuzzy_set < 0) || (which_fuzzy_set > fuzzySetsNr))
     132                return -2;
     133        if ((input_val < -1) || (input_val > 1))
     134                return -3;
     135
     136        if (GetFuzzySetParam(which_fuzzy_set, left, midleft, midright, right) != 0)
     137                return -4;
     138
     139        if ((input_val < left) || (input_val > right)) // greather than right value
     140                return 0;
     141        else if ((input_val >= midleft) && (input_val <= midright)) // in the core of fuzzy set
     142                return 1;
     143        else if ((input_val >= left) && (input_val < midleft)) // at the left side of trapezium
     144        {
     145                range = fabs(midleft - left);
     146                return fabs(input_val - left) / ((range > 0) ? range : 1); // quotient of distance between input and extreme left point of trapezium and range of rising side, or 1
     147        }
     148        else if ((input_val > midright) && (input_val <= right)) // at the right side of trapezium
     149        {
     150                range = fabs(right - midright);
     151                return fabs(right - input_val) / ((range > 0) ? range : 1); // quotient of distance between input and extreme right point of trapezium and range of falling side, or 1
     152        };
     153
     154        // should not occur
     155        return 0;
    156156
    157157}
     
    165165int NI_FuzzyNeuro::Defuzzyfication()
    166166{
    167   int i, j, nrIn, nrOut, out, set, outputsNr;
    168   double *numerators, *denominators, midleft, midright, unimp;
    169 
    170   outputsNr = getChannelCount();
    171 
    172   numerators = new double[outputsNr];
    173   denominators = new double[outputsNr];
    174 
    175   for(i=0;i<outputsNr;i++) numerators[i] = denominators[i] = 0;
    176 
    177   // for each rule...
    178   for (i=0; i<rulesNr; i++)
    179   {
    180     nrIn = rulesDef[2*i]; // number of inputs in rule #i
    181     nrOut = rulesDef[2*i + 1]; // number of outputs in rule #i
    182     // ...calculate each output's product of middle fuzzy set value and minimum membership function (numerator) and sum of minimum membership function (denominator)
    183     for (j=0; j<nrOut; j++)
    184     {
    185       out = rules[i][2*nrIn + 2*j]; //number of j-output
    186       set = rules[i][2*nrIn + 2*j + 1]; //number of fuzzy set attributed to j-output
    187       if (GetFuzzySetParam(set, unimp, midleft, midright, unimp) != 0) // gets range of core of given fuzzy set
    188         { SAFEDELETEARRAY(denominators) SAFEDELETEARRAY(numerators) return 1; }
    189       //defuzzParam[i] = minimum membership function for rule #i - calculated in fuzzyfication block
    190       // defuzzyfication method of singletons (high): (fuzzy set modal value) * (minimum membership value)
    191       numerators[out] += ((midleft + midright)/2.0) * defuzzParam[i];
    192       denominators[out] += defuzzParam[i];
    193     }
    194   }
    195 
    196   for (i=0; i<outputsNr; i++)
    197   {
    198     if (denominators[i] == 0)
    199       setState(0, i);
    200     else
    201       setState(numerators[i]/denominators[i], i);
    202   }
    203 
    204   SAFEDELETEARRAY(denominators)
    205   SAFEDELETEARRAY(numerators)
    206 
    207   return 0;
    208 }
    209 
     167        int i, j, nrIn, nrOut, out, set, outputsNr;
     168        double *numerators, *denominators, midleft, midright, unimp;
     169
     170        outputsNr = getChannelCount();
     171
     172        numerators = new double[outputsNr];
     173        denominators = new double[outputsNr];
     174
     175        for (i = 0; i < outputsNr; i++) numerators[i] = denominators[i] = 0;
     176
     177        // for each rule...
     178        for (i = 0; i < rulesNr; i++)
     179        {
     180                nrIn = rulesDef[2 * i]; // number of inputs in rule #i
     181                nrOut = rulesDef[2 * i + 1]; // number of outputs in rule #i
     182                // ...calculate each output's product of middle fuzzy set value and minimum membership function (numerator) and sum of minimum membership function (denominator)
     183                for (j = 0; j < nrOut; j++)
     184                {
     185                        out = rules[i][2 * nrIn + 2 * j]; //number of j-output
     186                        set = rules[i][2 * nrIn + 2 * j + 1]; //number of fuzzy set attributed to j-output
     187                        if (GetFuzzySetParam(set, unimp, midleft, midright, unimp) != 0) // gets range of core of given fuzzy set
     188                        {
     189                                SAFEDELETEARRAY(denominators) SAFEDELETEARRAY(numerators) return 1;
     190                        }
     191                        //defuzzParam[i] = minimum membership function for rule #i - calculated in fuzzyfication block
     192                        // defuzzyfication method of singletons (high): (fuzzy set modal value) * (minimum membership value)
     193                        numerators[out] += ((midleft + midright) / 2.0) * defuzzParam[i];
     194                        denominators[out] += defuzzParam[i];
     195                }
     196        }
     197
     198        for (i = 0; i < outputsNr; i++)
     199        {
     200                if (denominators[i] == 0)
     201                        setState(0, i);
     202                else
     203                        setState(numerators[i] / denominators[i], i);
     204        }
     205
     206        SAFEDELETEARRAY(denominators)
     207                SAFEDELETEARRAY(numerators)
     208
     209                return 0;
     210}
  • cpp/frams/neuro/impl/neuroimpl-fuzzy.h

    r286 r791  
    2020private:
    2121
    22   double *fuzzySets;    /// list of four digits which represents fuzzy sets: [0]-l, [1]-m, [2]-n, [3]-r, ...  fuzzySet[4*i] = left, fuzzySet[4*i + 1] = midleft, fuzzySet[4*i + 2] = midright, fuzzySet[4*i + 3] = right
     22        double *fuzzySets;    /// list of four digits which represents fuzzy sets: [0]-l, [1]-m, [2]-n, [3]-r, ...  fuzzySet[4*i] = left, fuzzySet[4*i + 1] = midleft, fuzzySet[4*i + 2] = midright, fuzzySet[4*i + 3] = right
    2323
    24   /** Determines, which fuzzy set is connected with each input of neuron. For instance third rule:
    25   *   'IF input3 = fuzzy set #3 AND input5 = fuzzy set #1 then output2 = fuzzy set #6 AND output7 = fuzzy set #5'
    26   *   the variables shoul have values as shown below:
    27   *   RulesDef[4]=2; RulesDef[5]=2; //rule 3: 2 inputs, 2 outputs
    28   *   Rules[2][0]=3, Rules[2][1]=3, Rules[2][2]=5, Rules[2][3]=1, Rules[2][4]=2, Rules[2][5]=6, Rules[2][6]=7, Rules[2][3]=5
    29   */
    30   int *rulesDef;    ///list of rules definitions: nr of inputs in rule 1, nr of outputs in rule 1, ... and so on for each rule
    31   int **rules;      ///list of rules body: input nr, fuzzy set nr, ... , output nr, fuzzy set nr, ... and so on for each rule
     24        /** Determines, which fuzzy set is connected with each input of neuron. For instance third rule:
     25        *   'IF input3 = fuzzy set #3 AND input5 = fuzzy set #1 then output2 = fuzzy set #6 AND output7 = fuzzy set #5'
     26        *   the variables shoul have values as shown below:
     27        *   RulesDef[4]=2; RulesDef[5]=2; //rule 3: 2 inputs, 2 outputs
     28        *   Rules[2][0]=3, Rules[2][1]=3, Rules[2][2]=5, Rules[2][3]=1, Rules[2][4]=2, Rules[2][5]=6, Rules[2][6]=7, Rules[2][3]=5
     29        */
     30        int *rulesDef;    ///list of rules definitions: nr of inputs in rule 1, nr of outputs in rule 1, ... and so on for each rule
     31        int **rules;      ///list of rules body: input nr, fuzzy set nr, ... , output nr, fuzzy set nr, ... and so on for each rule
    3232
    33   /**
    34   *  Sets defuzzyfication parameters: determines - for each rule - cut level <0;1> (minimum membership function of current rule).
    35   *  In fact, defuzzParam remembers the values from 'first layer' - fuzzyfication layer (see neuron at documentation)
    36   *  i.e. rule 1: defuzzParam[0] = 0.3522
    37   */
    38   double *defuzzParam; /// i.e.: defuzParam[5] = 0.455 means that rule #6 has got a minimum membership function (of given inputs set for this rule) at value 0.455 (it's cut level)
     33        /**
     34        *  Sets defuzzyfication parameters: determines - for each rule - cut level <0;1> (minimum membership function of current rule).
     35        *  In fact, defuzzParam remembers the values from 'first layer' - fuzzyfication layer (see neuron at documentation)
     36        *  i.e. rule 1: defuzzParam[0] = 0.3522
     37        */
     38        double *defuzzParam; /// i.e.: defuzParam[5] = 0.455 means that rule #6 has got a minimum membership function (of given inputs set for this rule) at value 0.455 (it's cut level)
    3939
    4040protected:
    4141
    42   ///Fuzzy functions
    43   double TrapeziumFuzz(int which_fuzzy_set, double input_val);
    44   int Fuzzyfication();
    45   int Defuzzyfication();
    46   int GetFuzzySetParam(int set_nr, double &left, double &midleft, double &midright, double &right);
     42        ///Fuzzy functions
     43        double TrapeziumFuzz(int which_fuzzy_set, double input_val);
     44        int Fuzzyfication();
     45        int Defuzzyfication();
     46        int GetFuzzySetParam(int set_nr, double &left, double &midleft, double &midright, double &right);
    4747
    4848public:
    4949
    50   int fuzzySetsNr;      /// number of fuzzy sets
    51   int rulesNr;      ///number of rules
    52   SString fuzzySetString; /// strings containing all fuzzy sets given in f0
    53   SString fuzzyRulesString; /// strings containing all fuzzy rules given in f0
     50        int fuzzySetsNr;      /// number of fuzzy sets
     51        int rulesNr;      ///number of rules
     52        SString fuzzySetString; /// strings containing all fuzzy sets given in f0
     53        SString fuzzyRulesString; /// strings containing all fuzzy rules given in f0
    5454
    55   NI_FuzzyNeuro() {paramentries=NI_FuzzyNeuro_tab; fuzzySets=defuzzParam=NULL; rulesDef=NULL; rules=NULL;}
    56   ~NI_FuzzyNeuro();
    57   NeuroImpl* makeNew() { return new NI_FuzzyNeuro(); };
    58   void go();
    59   int lateinit();
    60   /** Function build model based on given genotype and conts number of neurons connected with fuzzy neuro,
    61     also checks number of fuzzy neuron inputs.
    62     \param genotype genotype to be scanned
    63     \param inputs number of fuzzy neuron inputs
    64     \param output number of fuzzy neuron outputs (= number of neurons connected to fuzzy neuron)
    65     @return success or failure
    66   **/
    67   static int countOuts(const Model *m, const Neuro *fuzzy);
    68  
     55        NI_FuzzyNeuro() { paramentries = NI_FuzzyNeuro_tab; fuzzySets = defuzzParam = NULL; rulesDef = NULL; rules = NULL; }
     56        ~NI_FuzzyNeuro();
     57        NeuroImpl* makeNew() { return new NI_FuzzyNeuro(); };
     58        void go();
     59        int lateinit();
     60        /** Function build model based on given genotype and conts number of neurons connected with fuzzy neuro,
     61          also checks number of fuzzy neuron inputs.
     62          \param genotype genotype to be scanned
     63          \param inputs number of fuzzy neuron inputs
     64          \param output number of fuzzy neuron outputs (= number of neurons connected to fuzzy neuron)
     65          @return success or failure
     66          **/
     67        static int countOuts(const Model *m, const Neuro *fuzzy);
     68
    6969};
    7070
  • cpp/frams/neuro/impl/neuroimpl-simple.cpp

    r726 r791  
    1212int NI_StdNeuron::lateinit()
    1313{
    14 istate=newstate+neuro->state; // neuro->state -> random initialization
    15 calcOutput();
    16 neuro->state=newstate;
    17 return 1;
     14        istate = newstate + neuro->state; // neuro->state -> random initialization
     15        calcOutput();
     16        neuro->state = newstate;
     17        return 1;
    1818}
    1919
    2020void NI_StdNeuron::calcInternalState()
    2121{
    22 double sum=getWeightedInputSum();
    23 velocity=force*(sum-istate)+inertia*velocity;
    24 istate+=velocity;
    25 if (istate>NEURO_MAX) istate=NEURO_MAX;
    26 else if (istate<-NEURO_MAX) istate=-NEURO_MAX;
     22        double sum = getWeightedInputSum();
     23        velocity = force*(sum - istate) + inertia*velocity;
     24        istate += velocity;
     25        if (istate > NEURO_MAX) istate = NEURO_MAX;
     26        else if (istate < -NEURO_MAX) istate = -NEURO_MAX;
    2727}
    2828
    2929void NI_StdNeuron::go()
    3030{
    31 calcInternalState();
    32 calcOutput();
     31        calcInternalState();
     32        calcOutput();
    3333}
    3434
    3535void NI_StdNeuron::calcOutput()
    3636{
    37 double s=istate * sigmo;
    38 if (s<-30.0) setState(-1);
    39 else setState(2.0/(1.0+exp(-s))-1.0); // -1...1
     37        double s = istate * sigmo;
     38        if (s < -30.0) setState(-1);
     39        else setState(2.0 / (1.0 + exp(-s)) - 1.0); // -1...1
    4040}
    4141
    4242void NI_StdUNeuron::calcOutput()
    4343{
    44 double s=istate * sigmo;
    45 if (s<-30.0) setState(0);
    46 else setState(1.0/(1.0+exp(-s))); // 0...1
     44        double s = istate * sigmo;
     45        if (s < -30.0) setState(0);
     46        else setState(1.0 / (1.0 + exp(-s))); // 0...1
    4747}
  • cpp/frams/neuro/impl/neuroimpl-simple.h

    r726 r791  
    1111extern ParamEntry NI_StdNeuron_tab[];
    1212
    13 class NI_StdNeuron: public NeuroImpl
     13class NI_StdNeuron : public NeuroImpl
    1414{
    15   protected:
    16 double istate, velocity;
    17 void calcInternalState();
    18 virtual void calcOutput();
    19   public:
    20 double inertia,force,sigmo;
    21 NI_StdNeuron():velocity(0),inertia(0),force(0),sigmo(0)
    22         {paramentries=NI_StdNeuron_tab;}
    23 NeuroImpl* makeNew(){return new NI_StdNeuron();} // for NeuroFactory
    24 int lateinit();
    25 void go();
     15protected:
     16        double istate, velocity;
     17        void calcInternalState();
     18        virtual void calcOutput();
     19public:
     20        double inertia, force, sigmo;
     21        NI_StdNeuron() :velocity(0), inertia(0), force(0), sigmo(0)
     22        {
     23                paramentries = NI_StdNeuron_tab;
     24        }
     25        NeuroImpl* makeNew(){ return new NI_StdNeuron(); } // for NeuroFactory
     26        int lateinit();
     27        void go();
    2628};
    2729
    2830extern ParamEntry NI_StdUNeuron_tab[];
    2931
    30 class NI_StdUNeuron: public NI_StdNeuron
     32class NI_StdUNeuron : public NI_StdNeuron
    3133{
    32   public:
    33 NI_StdUNeuron()
    34         {paramentries=NI_StdUNeuron_tab;}
    35 NeuroImpl* makeNew(){return new NI_StdUNeuron();} // for NeuroFactory
    36 void calcOutput();
     34public:
     35        NI_StdUNeuron()
     36        {
     37                paramentries = NI_StdUNeuron_tab;
     38        }
     39        NeuroImpl* makeNew(){ return new NI_StdUNeuron(); } // for NeuroFactory
     40        void calcOutput();
    3741};
    3842
    39 class NI_Const: public NeuroImpl
     43class NI_Const : public NeuroImpl
    4044{
    4145public:
    42 NeuroImpl* makeNew(){return new NI_Const();} // for NeuroFactory
    43 int lateinit()
     46        NeuroImpl* makeNew(){ return new NI_Const(); } // for NeuroFactory
     47        int lateinit()
    4448        {
    45         neuro->state=newstate=1.0;
    46         simorder=0;
    47         return 1;
     49                neuro->state = newstate = 1.0;
     50                simorder = 0;
     51                return 1;
    4852        }
    4953};
     
    5155class NI_Diff : public NeuroImpl
    5256{
    53 double previous;     
    54   public:
    55 NeuroImpl* makeNew() { return new NI_Diff(); };
     57        double previous;
     58public:
     59        NeuroImpl* makeNew() { return new NI_Diff(); };
    5660
    57 void go()
     61        void go()
    5862        {
    59         double s=getWeightedInputSum();
    60         setState(s-previous);
    61         previous=s;
     63                double s = getWeightedInputSum();
     64                setState(s - previous);
     65                previous = s;
    6266        }
    63 int lateinit()
     67        int lateinit()
    6468        {
    65         NeuroImpl::lateinit();
    66         previous=neuro->state;
    67         return 1;
     69                NeuroImpl::lateinit();
     70                previous = neuro->state;
     71                return 1;
    6872        }
    6973};
     
    7175class NI_Random : public NeuroImpl
    7276{
    73   public:
    74 NeuroImpl* makeNew() { return new NI_Random(); };
    75 void go() {setState(rnd01*2.0-1.0);}
     77public:
     78        NeuroImpl* makeNew() { return new NI_Random(); };
     79        void go() { setState(rnd01*2.0 - 1.0); }
    7680};
    7781
     
    8084class NI_Sinus : public NeuroImpl
    8185{
    82   public:
    83 double f0,t;
    84 NeuroImpl* makeNew() { return new NI_Sinus(); };
    85 NI_Sinus():f0(0),t(0)
    86         {paramentries=NI_Sinus_tab;}
    87 void go()
     86public:
     87        double f0, t;
     88        NeuroImpl* makeNew() { return new NI_Sinus(); };
     89        NI_Sinus() :f0(0), t(0)
    8890        {
    89         t+=f0+getWeightedInputSum();
    90         setState(sin(t));
     91                paramentries = NI_Sinus_tab;
     92        }
     93        void go()
     94        {
     95                t += f0 + getWeightedInputSum();
     96                setState(sin(t));
    9197        }
    9298};
    9399
    94100#endif
    95 
Note: See TracChangeset for help on using the changeset viewer.