--                                                                    --
--  package                         Copyright (c)  Dmitry A. Kazakov  --
--     Fuzzy.Feature.Handle.Factory                Luebeck            --
--  Interface                                      Spring, 2002       --
--                                                                    --
--                                Last revision :  12:32 10 Jun 2003  --
--                                                                    --
--  This  library  is  free software; you can redistribute it and/or  --
--  modify it under the terms of the GNU General Public  License  as  --
--  published by the Free Software Foundation; either version  2  of  --
--  the License, or (at your option) any later version. This library  --
--  is distributed in the hope that it will be useful,  but  WITHOUT  --
--  ANY   WARRANTY;   without   even   the   implied   warranty   of  --
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  --
--  General  Public  License  for  more  details.  You  should  have  --
--  received  a  copy  of  the GNU General Public License along with  --
--  this library; if not, write to  the  Free  Software  Foundation,  --
--  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.    --
--                                                                    --
--  As a special exception, if other files instantiate generics from  --
--  this unit, or you link this unit with other files to produce  an  --
--  executable, this unit does not by  itself  cause  the  resulting  --
--  executable to be covered by the GNU General Public License. This  --
--  exception  does not however invalidate any other reasons why the  --
--  executable file might be covered by the GNU Public License.       --
--____________________________________________________________________--
--
--  This package provides a fuzzy features factory. The factory contains
--  functions for  creating  new  features  dynamically.  The  following
--  feature types can be generated by the factory:
--
--  (o)  Create_Binary creates a set of derived binary features
--  (o)  Create_Classificatory creates a classificatory feature
--  (o)  Create_Clustering creates a clustering feature
--  (o)  Create_Discrete creates a discrete feature
--  (o)  Create_Float creates a floating-point feature (based Float)
--  (o)  Create_Independent_Binary creates independent binary features
--  (o)  Create_Integer creates an integer feature (based on Integer)
--  (o)  Create_Isosceles_Trapezoids creates a trapezoids feature
--  (o)  Create_Linguistic creates a linguistic feature
--
with Fuzzy.Abstract_Edit.Named;      use Fuzzy.Abstract_Edit.Named;
with Fuzzy.Classifier;               use Fuzzy.Classifier;
with Fuzzy.Classifier.Handle;        use Fuzzy.Classifier.Handle;
with Fuzzy.Feature.Domain_Floats;    use Fuzzy.Feature.Domain_Floats;
with Fuzzy.Feature.Domain_Integers;  use Fuzzy.Feature.Domain_Integers;
with Units;                          use Units;

with Fuzzy.Feature.Classificatory.Clustering;
with Fuzzy.Feature.Float_Handle;
with Fuzzy.Feature.Domain_Floats.Defuzzifiers.Defuzzifier_Handles;
with Fuzzy.Feature.Handle.Bounded_Arrays;
with Fuzzy.Feature.Integer_Handle;
with Fuzzy.Feature.Isosceles_Trapezoids_Handle;
with Fuzzy.Feature.Linguistic_Handle;
with Fuzzy.Feature.Output_Handle;

package Fuzzy.Feature.Handle.Factory is
   pragma Elaborate_Body (Fuzzy.Feature.Handle.Factory);
   use Float_Measures;
   use Variable_Sets;
   use Classificatory.Clustering;
   use Domain_Floats.Defuzzifiers.Defuzzifier_Handles;
   use Handle.Bounded_Arrays;
--
-- Create_[Independent_]Binary -- Create a set of binary features
--
--    Feature - A feature handle
--
-- This function creates all possible derived  binary  features  of  the
-- feature  specified  by  the  parameter  Feature.  The  newly  created
-- features will have names of the source feature with the  suffix  ".n"
-- added, where n is the order of the created feature. The domain  of  a
-- binary feature is {0,1}. There are n different binary features  of  a
-- source  feature,  where  n  is binary logarithm of the feature domain
-- cardinality. The first binary feature has the value  of  the  highest
-- order  bit  of the binary representation of the source feature domain
-- value index. For instance, if a feature X has the cardinality 5, then
-- there  are  three  derived  binary  features X.1, X.2, X.3 having the
-- following values:
--
--    X  X.1 X.2 X.3
--    -  -----------
--    1   0   0   0
--    2   0   0   1
--    3   0   1   0
--    4   0   1   1
--    5   1   0   0
--
-- The  binary  features  created  by  the  function  Create_Binary  are
-- dependent. It means that the features  corresponding  to  lower  bits
-- depend  on  the  realizations  the features of higher order. Thus the
-- functions  Get_Necessity  and  Get_Possibility may have side effects.
-- Let's the feature X has the following distribution of possibilities:
--
--    X  P(X)
--    -  ----
--    1   1
--    2   1
--    3   0
--    4   0
--    5   0
--
-- The  highest order binary feature X.1 does not depend on other binary
-- features, so Get_Possibility will give for it:
--
--    X.1  P(X.1)
--    ---  ------
--     1   1 = P(X)(1..4)
--     2   0 = P(X)(5)
--
-- The  result of Get_Possibility for X.2 will depend on the latest call
-- Get_Possibility (a form with the parameter Value) for X.1:
--
--    X.2  P(X.2|X.1=1)   P(X.2|X.1=2)
--    ---  -------------  ----------------
--     1   1 = P(X)(1,2)  0 = P(X)(5)
--     2   0 = P(X)(3,4)  0 = P(X)(<empty>)
--
-- If the form with no parameter Value was used then the result will be:
--
--    X.2  P(X.2)
--    ---  ----------------
--     1   1 = P(X)(1,2,5)
--     2   0 = P(X)(3,4)
--
-- The  features  created  by the function Create_Independent_Binary are
-- mutually independent.
--
-- Returns :
--
--    The array of handles to created derived binary features
--
-- Exceptions :
--
--    Constraint_Error - Invalid handle
--
   function Create_Binary (Feature : Feature_Handle)
      return Bounded_Array;
   function Create_Binary (Feature : Feature_Handle)
      return Feature_Array;
   function Create_Independent_Binary (Feature : Feature_Handle)
      return Bounded_Array;
   function Create_Independent_Binary (Feature : Feature_Handle)
      return Feature_Array;
--
-- Create_[Independent_]Binary -- Create a binary feature
--
--    Name           - Of the result
--    Feature        - A feature handle
--  [ Bit_Position ] - Bit position MSB is 0
--
-- This function creates a single derived binary feature.  When  Feature
-- indicates  a  non-binary  feature,  the  result  is  the first binary
-- feature derived from it. When feature indicates a binary feature, the
-- result  is  the  binary  feature  second  to  it.  The parameter Name
-- specifies the name of the result. End_Error is  propagated  when  the
-- feature cannot  be  created  because  Feature  is  already  the  last
-- possible binary feature.
--
-- Returns :
--
--    A handle to the created derived binary feature
--
-- Exceptions :
--
--    Constraint_Error - Invalid handle
--    End_Error        - No more binary features, invalid bit position
--
   function Create_Binary
            (  Name    : String;
               Feature : Feature_Handle
            )  return Feature_Handle;
   function Create_Binary
            (  Name         : String;
               Feature      : Feature_Handle;
               Bit_Position : Natural
            )  return Feature_Handle;
   function Create_Independent_Binary
            (  Name    : String;
               Feature : Feature_Handle
            )  return Feature_Handle;
   function Create_Independent_Binary
            (  Name         : String;
               Feature      : Feature_Handle;
               Bit_Position : Natural
            )  return Feature_Handle;
--
-- Create_Classificatory -- Create a classificatory feature
--
--    Name       - Of the feature
--    Classifier - A handle to a classifier
--    Generalize - Generalization mode
--    Threshold  - The threshold to use for classifications
--
-- This  function  creates  a  classificatory  feature  which  will  use
-- Classifier for classification. A classificatory feature  encapsulates
-- a the classifier to produce its realizations. The domain set  of  the
-- feature is the set of the classes of the classifier.  The  images  of
-- the feature are defined by the classification of the event behind the
-- given   example   (Has_In   and   not  Has_Not  images)  and  by  the
-- classification of the event's complement (Has_Out and not Has_Not_Out
-- images). The parameters Generalize and Threshold are ones  passed  to
-- Classify as described in Fuzzy.Classifier.Handle.
--
-- Returns :
--
--    A handles to the created feature
--
-- Exceptions :
--
--    Constraint_Error - Invalid handle or node
--
   function Create_Classificatory
            (  Name       : String;
               Classifier : Classifier_Handle;
               Generalize : Generalization_Mode := Linear;
               Threshold  : Confidence          := Confidence'First
            )  return Feature_Handle;
--
-- Create_Clustering -- Create a clustering feature
--
--    Name        - Of the feature
--    Classifier  - A handle to a classifier
--    Generalize  - Generalization mode
--    Threshold   - The threshold to use for classifications
--    Equivalence - The confidence interval
--
-- This  function creates a clustering feature which will use Classifier
-- for clustering training examples. A clustering  feature  is  used  to
-- split  the  feature  space into clusters corresponding to some random
-- events. Upon training clusters  are  usually  trained  independently.
-- Upon classification the cluster of the most frequency is used, so the
-- feature  value  is not queried upon. The domain set of the feature is
-- the  set  of the classes of the classifier. The images of the feature
-- are  defined  by  the  classification  of  the event behind the given
-- example (Has_In and not Has_Not images) and by the classification  of
-- the event's complement (Has_Out  and  not  Has_Not_Out  images).  The
-- parameters  Generalize  and  Threshold are ones passed to Classify as
-- described  in  Fuzzy.Classifier.Handle.  The  parameter   Equivalence
-- specifies   the   interval   in   which  frequencies  are  considered
-- equivalent.
--
-- Returns :
--
--    A handles to the created feature
--
-- Exceptions :
--
--    Constraint_Error - Invalid handle or node
--
   function Create_Clustering
            (  Name        : String;
               Classifier  : Classifier_Handle;
               Generalize  : Generalization_Mode := Linear;
               Threshold   : Confidence          := Confidence'First;
               Equivalence : Cluster_Frequency   := Cluster_Equivalence
            )  return Feature_Handle;
--
-- Create_Discrete -- Create a discrete feature
--
--    Name   - Of the feature
--    Domain - Of the domain set of the feature
--
-- The parameter Domain is the list  of  feature  domain  element  names
-- separated  by  commas.  A name should start with a letter and contain
-- only letters, digits, underline and spaces. The last character cannot
-- be  a  space  or  underline. If a space or underline appears the next
-- character shall differ. Commas in Domain can be surrounded by  spaces
-- and  tabs.  The  whole  string  Domain  shall  be matched. Otherwise,
-- Data_Error  is  propagated.  It  is  also propagated if Name contains
-- duplicated element names.
--
-- Returns :
--
--    The handle to the newly created feature
--
-- Exceptions :
--
--    Data_Error - Syntax error of the string Domain
--    End_Error  - No elements found in the string Domain
--
   function Create_Discrete (Name : String; Domain : String)
      return Feature_Handle;
--
-- Create -- Create a discrete feature
--
--    Name   - Of the feature
--    Domain - Of the domain set of the feature
--
-- The   parameter   Domain  is  the  feature  domain  as  described  in
-- Fuzzy.Abstract_Edit.Named.
--
-- Returns :
--
--    The handle to the newly created feature
--
-- Exceptions :
--
--    Constraint_Error - No elements found in Domain
--
   function Create_Discrete
            (  Name   : String;
               Domain : Domain_Description'Class
            )  return Feature_Handle;
--
-- Create_Float -- Create an floating-point feature
--
--    Name        - Of the feature
--    Cardinality - Of the feature (number of elementary intervals)
--    From        - The lower boundary of the feature values range
--    To          - The upper boundary
--    Scale       - Of the feature values
--  [ Mode ]      - Code set used in dimension unit specification
--
-- The parameters From and To determine the range of the feature domain.
-- The feature domain is the interval [From..To], the of union of domain
-- elmentary   intervals   [Li,  Ui],  i=1..Cardinality.  Li+1=Ui.  Each
-- elementary interval has the width (To  -  From)  /  Cardinality.  The
-- parameter  Scale  is the feature values scale. It is specified either
-- as a measure or as a string which is parsed using the function Value.
-- The  scale  shall  have  positive  gain,  Unit_Error  is   propagated
-- otherwise.  The  parameter Mode is the character set used for parsing
-- Scale. The feature scale influences values I/O as  described  in  the
-- package Fuzzy.Features.Generic_Float.
--
-- Returns :
--
--    The handle to the newly created feature
--
-- Exceptions :
--
--    Constraint_Error - From = To and Cardinality is not 1
--    End_Error        - Empty domain (To < From)
--    Unit_Error       - Wrong Scale
--
   function Create_Float
            (  Name        : String;
               Cardinality : Positive;
               From        : Domain_Float;
               To          : Domain_Float;
               Scale       : Measure := Np
            )  return Feature_Handle renames
                      Fuzzy.Feature.Float_Handle.Create;
   function Create_Float
            (  Name        : String;
               Cardinality : Positive;
               From        : Domain_Float;
               To          : Domain_Float;
               Scale       : String;
               Mode        : Code_Set := UTF8_Set
            )  return Feature_Handle renames
                      Fuzzy.Feature.Float_Handle.Create;
--
-- Create_Integer -- Create an integer feature
--
--    Name - Of the feature
--    From - The lower boundary of the feature values range
--    To   - The upper boundary
--
-- The parameters From and To determine the range of the feature domain.
-- Its cardinality will be To - From + 1.
--
-- Returns :
--
--    The handle to the newly created feature
--
-- Exceptions :
--
--    End_Error - Empty domain (To < From)
--
   function Create_Integer
            (  Name : String;
               From : Domain_Integer;
               To   : Domain_Integer
            )  return Feature_Handle renames
                      Fuzzy.Feature.Integer_Handle.Create;
--
-- Create_Isosceles_Trapezoids -- Create a isosceles trapezoids feature
--
--    Name        - Of the feature
--    Cardinality - Of the feature (number of elementary intervals)
--    From        - The lower boundary of the feature values range
--    To          - The upper boundary
--    Shoulder    - The length of the trapezoid's shoulders
--    Scale       - The scale of the feature values
--  [ Mode ]      - Scale character set
--
-- The  feature  domain  of  created  linguistic feature consists of two
-- shoulders  and  Cardinality  -  2 isosceles trapezoids. The following
-- figure illustrates the case for the Cardinality = 4.
--
--                            Variable names
--    _____
--         \                  L
--          \______________
--         ____
--        /    \              T1
--    ___/      \__________
--             ____
--            /    \          T2
--    _______/      \______
--                 ________
--                /           R
--    ___________/
--         |     | |
--         |   ->| |<- Shoulder
--       From      To
--
-- The parameter Scale is the feature  values  scale.  It  is  specified
-- either as a measure  or  as  a  string  which  is  then  parsed.  The
-- parameter  Mode is the character set used for parsing a string Scale.
-- The  scale  shall  have  positive  gain,  Unit_Error  is   propagated
-- otherwise. When From < To, Cardinality should be  at  least  3.  When
-- From = To, then Cardinality should be 2.  Otherwise  Constraint_Error
-- is propagated. It is also propagated when Shoulder is negative.
--
-- Returns :
--
--    The handle to the newly created feature
--
-- Exceptions :
--
--    Constraint_Error - From = To and Cardinality is less than 2
--    End_Error        - Empty domain (To < From)
--    Unit_Error       - Wrong Scale
--
   function Create_Isosceles_Trapezoids
            (  Name        : String;
               Cardinality : Positive;
               From        : Domain_Float;
               To          : Domain_Float;
               Shoulder    : Domain_Float;
               Scale       : Measure := Np
            )  return Feature_Handle renames
                      Fuzzy.Feature.Isosceles_Trapezoids_Handle.Create;
   function Create_Isosceles_Trapezoids
            (  Name        : String;
               Cardinality : Positive;
               From        : Domain_Float;
               To          : Domain_Float;
               Shoulder    : Domain_Float;
               Scale       : String;
               Mode        : Code_Set := UTF8_Set
            )  return Feature_Handle renames
                      Fuzzy.Feature.Isosceles_Trapezoids_Handle.Create;
--
-- Create_Linguistic -- Create a linguistic feature
--
--    Name   - Of the feature
--    Domain - Of the domain set of the feature
--    Scale  - Of the feature values
--  [ Mode ] - Character set used in unit specification
--
-- A linguistic feature is similar to a discrete  feature.  It  has  two
-- domains. One is the set of dimensioned real  numbers.  Another  is  a
-- discrete set of named elements as in case of discrete  feature.  Each
-- named element is called a linguistic variable and represents a  fuzzy
-- subset  of  dimensioned  real  numbers.  The membership function of a
-- linguistic variable consists of points and linear segments.
--
-- The  parameter  Domain  specifies  the feature domain. It is either a
-- fuzzy linguistic set or a string which has the syntax  described  for
-- the procedure Get in Fuzzy.Linguistics.Sets.Edit:
--
--    <list>    ::= <element> [,<list>]
--    <element> ::= <name> (<variable>)
--
-- The parameter Scale is the feature  values  scale.  It  is  specified
-- either as a string which is parsed using the function Value or  as  a
-- measure. The scale shall have positive gain, Unit_Error is propagated
-- otherwise.  The  parameter  Mode is the character set used for I/O of
-- the measurement units.
--
-- Returns :
--
--    The handle to the newly created feature
--
-- Exceptions :
--
--    Constraint_Error - A number is out of range
--    Data_Error       - Syntax error of the string Domain
--    End_Error        - No elements found in the string Domain
--    Unit_Error       - Error in units
--
   function Create_Linguistic
            (  Name   : String;
               Domain : String;
               Scale  : Measure := Np
            )  return Feature_Handle renames
                      Fuzzy.Feature.Linguistic_Handle.Create;
   function Create_Linguistic
            (  Name   : String;
               Domain : Linguistic_Set;
               Scale  : Measure := Np
            )  return Feature_Handle renames
                      Fuzzy.Feature.Linguistic_Handle.Create;
   function Create_Linguistic
            (  Name   : String;
               Domain : String;
               Scale  : String;
               Mode   : Code_Set := UTF8_Set
            )  return Feature_Handle renames
                      Fuzzy.Feature.Linguistic_Handle.Create;
   function Create_Linguistic
            (  Name   : String;
               Domain : Linguistic_Set;
               Scale  : String;
               Mode   : Code_Set := UTF8_Set
            )  return Feature_Handle renames
                      Fuzzy.Feature.Linguistic_Handle.Create;
--
-- Create_Output -- Create an output feature
--
--    Name    - Of the feature
--    Source  - A handle to the feature to defuzzify
--    Method  - The defuzzification method
--    Default - The default used when defuzzification fails
--
-- The  parameter  Name  is  the  feature  name. Source is a handle to a
-- feature  with  a  floating-point domain. The newly created feature is
-- exactly Source but also suports defuzzification  by  the  defuzzifier
-- which handle is Method. Deafult is the defuzzification default.
--
-- Returns :
--
--    The handle to the newly created feature
--
-- Exceptions :
--
--    Constraint_Error - An invalid handle or not a float feature
--    Unit_Error       - Incompatible units of Source and Default
--
   function Create_Output
            (  Name    : String;
               Feature : Feature_Handle;
               Method  : Defuzzifier_Handle;
               Default : Measure
            )  return Feature_Handle renames
                      Fuzzy.Feature.Output_Handle.Create;

end Fuzzy.Feature.Handle.Factory;
