Сорри за комментарии, какие-то проблемы с кодировками, решать их некогда, поэтому лучше удалю их вообще...
Нечеткая модель (пока реализована только модель Мамдани):
## Код:
```
MODULE FuzzyModel;

   IMPORT FuzzySets, FuzzyFIS;

      
   
   TYPE

      Rule = RECORD
         Prem, Concl: POINTER TO ARRAY OF Label; 
         PremMethod: PROCEDURE (x, y: REAL): REAL 
      END;


      Label = RECORD
         ToLingVar, ToTerm: INTEGER;
      END;
      
      

   TYPE   

      InLingVar = EXTENSIBLE RECORD
         Term: POINTER TO ARRAY OF POINTER TO FuzzySets.FuzzySet;
      END;
      

      OutLingVar = RECORD (InLingVar)
         Min, Max, dx : REAL;
      END;
      
   

   
   TYPE
      
      Model* = ABSTRACT RECORD
         
         Rule: POINTER TO ARRAY OF Rule;
         InVar: POINTER TO ARRAY OF InLingVar;
         OutVar: POINTER TO ARRAY OF OutLingVar;
         ImplMethod: PROCEDURE (x, y: REAL): REAL; 
      END;
      
      
      SugenoModel* = RECORD (Model)
      END;
      
      
      MamdaniModel* = RECORD (Model)
         
         Figure: POINTER TO ARRAY OF POINTER TO Figure;
         NoNul: POINTER TO ARRAY OF BOOLEAN;
         AggMethod: PROCEDURE (x, y: REAL): REAL;
         DefuzzMethod: PROCEDURE (IN figure: Figure; min, dx: REAL): REAL
      END;
      
   
   TYPE
      
      Figure = ARRAY OF REAL; (*ìàññèâ òî÷åê*)

   
   
   
   PROCEDURE Min (x, y: REAL): REAL;
   BEGIN
      RETURN MIN(x, y)
   END Min;
   
   PROCEDURE Max (x, y: REAL): REAL;
   BEGIN
      RETURN MAX(x, y)
   END Max;
   
   
   PROCEDURE (VAR this: Model) Implication (IN InVars: ARRAY OF REAL; IN rule: Rule): REAL, NEW;
      VAR i, v, t: INTEGER;
         mf, val: REAL;
   BEGIN
      v := rule.Prem[0].ToLingVar;
      t := rule.Prem[0].ToTerm;
      IF t > 0 THEN
         val := this.InVar[v].Term[t-1].MF(InVars[v]);    
      ELSE
         val := 1 - this.InVar[v].Term[2*t-t-1].MF(InVars[v]);
      END;
      FOR i := 1 TO LEN(rule.Prem) - 1 DO
         v := rule.Prem[i].ToLingVar;
         t := rule.Prem[i].ToTerm;
         IF t > 0 THEN
            mf := this.InVar[v].Term[t - 1].MF(InVars[v]);    
         ELSE
            mf := 1 - this.InVar[v].Term[ABS(t) - 1].MF(InVars[v]);
         END;
         val := rule.PremMethod(val, mf);
      END; 
      RETURN val;
   END Implication;
   
   PROCEDURE Yes (VAR this: MamdaniModel; v, t: INTEGER; x: REAL): REAL;
   BEGIN
      RETURN (this.OutVar[v].Term[t-1].MF(x))
   END Yes;
   
   PROCEDURE Not (VAR this: MamdaniModel; v, t: INTEGER; x: REAL): REAL;
   BEGIN
      RETURN (1 - this.OutVar[v].Term[ABS(t) - 1].MF(x))
   END Not;   
   
   PROCEDURE (VAR this: MamdaniModel) NewFigure (cut: REAL; OUT figure: Figure; ToOutVar: Label), NEW;   
      VAR i, v, t: INTEGER;
         mf, x: REAL; met: PROCEDURE (VAR this: MamdaniModel; v, t: INTEGER; x: REAL): REAL;
   BEGIN
      v := ToOutVar.ToLingVar; t := ToOutVar.ToTerm;
      IF t > 0 THEN met := Yes ELSE met := Not END;
      FOR i := 0 TO LEN(figure) - 1 DO
         x := this.OutVar[v].Min + i*this.OutVar[v].dx;
         mf := met(this, v, t, x);
         (*îcóùåñòâëÿåì èìïëèêàöèþ*)
         figure[i] := this.ImplMethod(cut, mf);
      END;
   END NewFigure;
   
   PROCEDURE (VAR this: MamdaniModel) Aggregation (cut: REAL; VAR figure: Figure; ToOutVar: Label), NEW;
      VAR i, v, t: INTEGER; x, mf, impl: REAL;
         met: PROCEDURE (VAR this: MamdaniModel; v, t: INTEGER; x: REAL): REAL;
   BEGIN
      v := ToOutVar.ToLingVar; t := ToOutVar.ToTerm;
      IF t > 0 THEN met := Yes ELSE met := Not END;
      FOR i := 0 TO LEN(figure) - 1 DO
         x := this.OutVar[v].Min + i*this.OutVar[v].dx;
         mf := met(this, v, t, x);
         impl := this.ImplMethod(cut, mf);
         figure[i] := this.AggMethod(impl, figure[i]);
      END;
   END Aggregation;
   
   
   PROCEDURE (VAR m: Model) Compute* (IN InVars: ARRAY OF REAL; OUT OutVars: ARRAY OF REAL), NEW, ABSTRACT;
   
   PROCEDURE (VAR m: SugenoModel) Compute* (IN InVars: ARRAY OF REAL; OUT OutVars:   ARRAY OF REAL);
      VAR i: INTEGER;
   BEGIN
   END Compute;   
   
   PROCEDURE (VAR this: MamdaniModel) Compute*  (IN InVars: ARRAY OF REAL; OUT OutVars: ARRAY OF REAL);
      VAR i, j, k: INTEGER;
         cut: REAL;
   BEGIN
      ASSERT((LEN(InVars) = LEN(this.InVar)) & (LEN(OutVars) = LEN(this.OutVar)));
      FOR i := 0 TO LEN(this.Rule) - 1 DO
         cut := this.Implication(InVars, this.Rule[i]);
         FOR j := 0 TO LEN(this.Rule[i].Concl) - 1 DO
            k := 0;
            WHILE (k < LEN(this.OutVar)) & (ABS(this.Rule[i].Concl[j].ToLingVar) # k) DO
               INC(k)
            END;
            IF ABS(this.Rule[i].Concl[j].ToLingVar) = k THEN
               IF ~this.NoNul[k] THEN 
                  this.NewFigure(cut, this.Figure[k], this.Rule[i].Concl[j]);
                  this.NoNul[k] := TRUE
               ELSE
                  this.Aggregation(cut, this.Figure[k], this.Rule[i].Concl[j])
               END;
            END;
         END;
      END;
      FOR i := 0 TO LEN(this.OutVar) - 1 DO
         IF this.Figure[i] # NIL THEN
            OutVars[i] := this.DefuzzMethod(this.Figure[i], this.OutVar[i].Min, this.OutVar[i].dx)
         END;
      END;
      FOR i := 0 TO LEN(this.OutVar) - 1 DO this.NoNul[i] := FALSE END;
   END Compute;
   
   PROCEDURE Centroid (IN figure: Figure; min, dx: REAL): REAL;
      VAR i: INTEGER;
            x, num, den: REAL;
   BEGIN
      num := 0; den := 0;
      FOR i := 0 TO LEN(figure) - 1 DO
         den := den + figure[i];
         num := num + figure[i] * (min + dx*i);
      END;
      RETURN (num/den);
   END Centroid;
   
   
   PROCEDURE (VAR m: MamdaniModel) Init* (IN fis: FuzzyFIS.FIS), NEW;
      VAR i, j, NumLabel, k: INTEGER;
   BEGIN   
      ASSERT(fis.ModelType = 'mamdani');      
      NEW(m.InVar, LEN(fis.InMFsParamReal));
      NEW(m.OutVar, LEN(fis.OutMFsParamReal));
      FOR i := 0 TO LEN(m.InVar) - 1 DO
         NEW(m.InVar[i].Term, LEN(fis.InMFsParamReal[i]));
         FOR j := 0 TO LEN(m.InVar[i].Term) - 1 DO
            IF fis.InMFsType[i, j] = 'trimf' THEN
               m.InVar[i].Term[j] := FuzzySets.NewTriangle(
                  fis.InMFsParamReal[i, j, 0], fis.InMFsParamReal[i, j, 1], fis.InMFsParamReal[i, j, 2])
            ELSIF fis.InMFsType[i, j] = 'trapmf' THEN
               m.InVar[i].Term[j] := FuzzySets.NewTrapezoid(
                  fis.InMFsParamReal[i, j, 0], fis.InMFsParamReal[i, j, 1],
                  fis.InMFsParamReal[i, j, 2], fis.InMFsParamReal[i, j, 3])
            ELSE
               HALT(0)
            END;   
         END;
      END;
      NEW(m.Figure, LEN(m.OutVar));
      NEW(m.NoNul, LEN(m.OutVar));
      FOR i := 0 TO LEN(m.OutVar) - 1 DO
         NEW(m.OutVar[i].Term, LEN(fis.OutMFsParamReal[i]));
         FOR j := 0 TO LEN(m.OutVar[i].Term) - 1 DO
            IF fis.OutMFsType[i, j] = 'trimf' THEN
               m.OutVar[i].Term[j] := FuzzySets.NewTriangle(
                  fis.OutMFsParamReal[i, j, 0], fis.OutMFsParamReal[i, j, 1],
                  fis.OutMFsParamReal[i, j, 2])
            ELSIF fis.OutMFsType[i, j] = 'trapmf' THEN
               m.OutVar[i].Term[j] := FuzzySets.NewTrapezoid(
                  fis.OutMFsParamReal[i, j, 0], fis.OutMFsParamReal[i, j, 1],
                  fis.OutMFsParamReal[i, j, 2], fis.OutMFsParamReal[i, j, 3])
            ELSE
               HALT(0)
            END;      
         END;
         m.NoNul[i] := FALSE;
         m.OutVar[i].Min := fis.OutRange[i, 0];
         m.OutVar[i].Max := fis.OutRange[i, 1];   
         NEW(m.Figure[i], (1000*LEN(m.OutVar[i].Term)));
         m.OutVar[i].dx := (m.OutVar[i].Max - m.OutVar[i].Min)/LEN(m.Figure[i]);
      END;
      NEW(m.Rule, LEN(fis.TypeImpl));
      FOR i := 0 TO LEN(m.Rule) - 1 DO
         NumLabel := 0;
         FOR j := 0 TO LEN(m.InVar) - 1 DO
            IF fis.InRuleLabel[i, j] # 0 THEN INC(NumLabel) END;
         END;
         NEW(m.Rule[i].Prem, NumLabel);
         NEW(m.Rule[i].Concl, NumLabel);
         k := 0;
         FOR j := 0 TO LEN(m.InVar) - 1 DO
            IF fis.InRuleLabel[i, j] # 0 THEN
               m.Rule[i].Prem[k].ToLingVar := j;
               m.Rule[i].Prem[k].ToTerm := fis.InRuleLabel[i, j];
               INC(k);
            END;
         END;
         NumLabel := 0;
         FOR j := 0 TO LEN(m.OutVar) - 1 DO
            IF fis.OutRuleLabel[i, j] # 0 THEN INC(NumLabel) END;
         END;
         NEW(m.Rule[i].Concl, NumLabel);
         NEW(m.Rule[i].Concl, NumLabel);
         k := 0;
         FOR j := 0 TO LEN(m.OutVar) - 1 DO
            IF fis.OutRuleLabel[i, j] # 0 THEN
               m.Rule[i].Concl[k].ToLingVar := j;
               m.Rule[i].Concl[k].ToTerm := fis.OutRuleLabel[i, j];
               INC(k);
            END;
         END;
         CASE fis.TypeImpl[i] OF
            1: m.Rule[i].PremMethod := Min;  
         |  2: m.Rule[i].PremMethod := Max;
         ELSE
            HALT(0)
         END
      END;
      IF fis.AggMethod = "max" THEN m.AggMethod := Max
      ELSIF fis.AggMethod = "min" THEN m.AggMethod := Min
      ELSE HALT(0) END;
      IF fis.DefuzzMethod = "centroid" THEN m.DefuzzMethod := Centroid;
      ELSE HALT(0) END; 
      IF fis.ImpMethod = "max" THEN m.ImplMethod := Max
      ELSIF fis.ImpMethod = "min" THEN m.ImplMethod := Min
      ELSE HALT(0) END;
   END Init;
      
END FuzzyModel.
```
