                   Intuitionistic fuzzy PostgreSQL (IFPG) 1.1



  Contents:

  1. Introduction
  2. Background - intuitionistic fuzzy relational algebra
    2.1. Predicates
    2.2. Operation selection
    2.3. Operation Cartesian product
    2.4. Modifiers
  3. SQL features
    3.1. Database template _ifs_template
    3.2. Type _ifs.bool
    3.3. Modifiers
    3.4. Database type
  4. Intuitionistic fuzzy SQL
    4.1. CREATE DATABASE
    4.2. CREATE TABLE
    4.3. CREATE PREDICATE
    4.4. CREATE MODIFIER
    4.5. SELECT
      4.5.1. Target list
      4.5.2. FROM clause
      4.5.3. WHERE clause
      4.5.4. GROUP BY clause
      4.5.5. HAVING clause
      4.5.6. MODIFY BY clause
      4.5.7. Set operations - UNION and INTERSECT
    4.6. UPDATE
    4.7. Crisp relations
    4.8. Setting the database type
  5. Enabling IFSQL support
    5.1. Enabling IFSQL support for a single command
  6. Example
  7. Internals
  8. TODO list
  9. Changes from 1.0


1. Introduction
    The theory of intuitionistic fuzzy sets (IFS) is proposed by K. Atanassov in [1] as
  an extension of the classical fuzzy sets theory. Each element of an intuitionistic
  fuzzy set has degrees of membership (mu) and non-membership (nu), which don't
  sum up to 1 thus leaving a degree of indefiniteness (pi = 1-mu-nu). A classical fuzzy
  set is a particular case of an IFS, where pi = 0.
      0 <= mu <= 1
      0 <= nu <= 1
      0 <= mu+nu <= 1
    Let A = { <x, mu, nu> / x belongs to X } and B = { <x, mu, nu> / x belongs to X }
  are intuitionistic fuzzy sets over the universe X.
    Here are the definitions of the operations "union" and "intersection":
      - A union B = { <x, max (A.mu, B.mu), min (A.nu, B.nu)> / x belongs to X }
      - A intersection B = { <x, min (A.mu, B.mu), max (A.nu, B.nu)> / x belongs to X }
    Following are some of the operators defined over IFSs:
      - necessity A = { <x, mu, 1-nu> / x belongs to X}
      - possibility A = { <x, 1-mu, nu> / x belongs to X}
      - D (A, alpha) = { <x, mu + alpha*pi, nu + (1-alpha)*pi> / x belongs to X}
          (0 <= alpha <= 1)
      - F (A, alpha, beta) = {<x, mu + alpha*pi, nu + beta*pi> / x belongs to X}
          (0 <= alpha <= 1, 0 <= beta <= 1, 0 <= alpha+beta <= 1)
      - G (A, alpha, beta) = {<x, alpha*mu, beta*nu> / x belongs to X}
          (0 <= alpha <= 1, 0 <= beta <= 1)
      - H (A, alpha, beta) = {<x, alpha*mu, nu + beta*pi> / x belongs to X}
          (0 <= alpha <= 1, 0 <= beta <= 1)
      - H*(A, alpha, beta) = {<x, alpha*mu, nu + beta*(1 - alpha*mu - nu)> / x belongs to X}
          (0 <= alpha <= 1, 0 <= beta <= 1)
      - J (A, alpha, beta) = {<x, mu + alpha*pi, beta*nu> / x belongs to X}
          (0 <= alpha <= 1, 0 <= beta <= 1)
      - J*(A, alpha, beta) = {<x, mu + alpha*(1 - mu - beta*nu), beta*nu> / x belongs to X}
          (0 <= alpha <= 1, 0 <= beta <= 1)
    One can easily see that the first three operators transform an IFS to a classical fuzzy
  set, and the other ones just modify the degrees of membership and non-membership.
    Let a and b are intuitionistic fuzzy logical statements with estimations respectively
  <a.mu, a.nu> and <b.mu, b.nu>, where a.mu is the degree of truth and a.nu is the degree of
  falsity of statement a. The logical operations AND, OR and NOT are defined as follows:
      - a AND b = < min (a.mu, b.mu), max (a.nu, b.nu) >
      - a OR b  = < max (a.mu, b.mu), min (a.nu, b.nu) >
      - NOT a = < a.nu, a.mu >
    There are another variants of the logical operations AND and OR, which we will call
  probabilistic:
      - a AND b = < a.mu * b.mu, a.nu + b.nu - a.nu * b.nu >
      - a OR b  = < a.mu + b.mu - a.mu * b.mu, a.nu * b.nu >
    For more details on IFS theory, see [1].
    Intuitionistic fuzzy PostgreSQL is a patch, which supplements PostgreSQL with the
  functionality of an intuitionistic fuzzy relational database management system
  (IFRDBMS). IFPG defines an extension of the SQL (IFSQL) in order to manage with
  intuitionistic fuzzy queries and relations. IFPG module in PostgreSQL handles an
  IFSQL statement, translates the statement to an SQL statement and then passes
  the result to PostgreSQL for further processing (see Chapter 7).
  
  
2. Background - intuitionistic fuzzy relational algebra
    An intuitionistic fuzzy relation (IFR) is a relation, each tuple of which belongs to
  the relation with certain degrees of membership and non-membership:
      R = { <x, mu, nu> / x belongs to X },
  where X is a relation in the terms of classical relational algebra.
  
  2.1. Predicates
      From a programmer's point of view an intuitionistic fuzzy predicate (IFP) is a
    function which returns intuitionistic fuzzy boolean (IFB) value. This is a value
    with two components - degree of truth and degree of falsity.
        p (x) --> <mu, nu>
    
  2.2. Operation selection
      A selection operation applies condition (predicate) to each record in a relation.
    In other words, it modifies the degrees of membership and non-membership of the record.
    There are two variants of the selection operation:
        sel (R, p) = { < x, min (R.mu, p(x).mu), max (R.nu, p(x).nu) > / x belongs to X }
        sel (R, p) = { < x, R.mu * p(x).mu, R.nu + p(x).nu - R.nu * p(x).nu > / x belongs to X }
      The second one we will call the probabilistic selection.
    
  2.3. Operation Cartesian product
      Let S = { <y, mu, nu> / y belongs to Y }. There are two variants of the Cartesian
    product operation:
        RxS = { <<x, y>, min (R.mu, S.mu), max (R.nu, R.nu)> / <x, y> belongs to XxY }
        RxS = { <<x, y>, R.mu * S.mu, R.nu + R.nu - R.nu * R.nu> / <x, y> belongs to XxY }
      The second one we will call the probabilistic Cartesian product.
    
  2.4. Modifiers
      We use the term "modifier" to represent the operators from the IFS theory, because
    in SQL the term "operator" has special meaning. The modifier modifies the degrees of
    membership and non-membership of the elements of a relation.
    

3. SQL features
    Each intuitionistic fuzzy relational database (IFRDB) contains the schema _ifs,
  where objects necessary for the processing of IFSQL statements are defined and stored.
  
  3.1. Database template _ifs_template
      Each IFRDB is created using the template database _ifs_template, which contains
    the _ifs schema.
    
  3.2. Type _ifs.bool
      This is a composite type with two components - mu and nu of type double precision,
    which represents the intuitionistic fuzzy boolean type.
    
  3.3. Modifiers
      Operators necessity, possibility, D, F, G, H, H*, J and J* from the IFS theory
    are defined in the _ifs schema. User defined modifiers may be created as well (see 4.4.)
    
  3.4. Database type
      The database can be one of the two types - fuzzy or probabilistic. If the type is
    probabilistic, IFRDBMS uses the probabilistic variants of:
        - the logical AND and OR operations (in WHERE clauses, see the introduction)
        - the selection operation (see 2.2)
        - the Cartesian product operation (see 2.3)
    
4. Intuitionistic fuzzy SQL
    The IFSQL defines extensions and modifications of the syntax of SQL statements. Below
  is a short description of the IFSQL specific commands. For further details refer to the
  documentation of SQL commands [2].
  
  4.1. CREATE DATABASE
      Creates an IFRDB - uses the template _ifs_template. The syntax is not changed except
    for the TEMPLATE clause, which is missing. IFRDBs don't have templates, because they
    are created with the template _ifs_template.
      NOTE: If you did not create the database using the IFSQL CREATE DATABASE statement,
    you can make the database intuitionistic fuzzy later by running the script ifpg-fuzzifydb.
    
  4.2. CREATE TABLE
      Creates an IFR - adds to the newly created table the columns mship and nmship with
    the relevant constraints.
      NOTE: The table may be created as crisp (ordinary, not fuzzy) depending on the table name
    (see 4.7)
      
  4.3. CREATE PREDICATE
      Creates an intuitionistic fuzzy predicate. The predicate is a function, which returns
    _ifs.bool. The syntax is the same as the one of the CREATE FUNCTION statement but without
    the RESULT clause. CREATE PREDICATE is equal to CREATE FUNCTION ... RETURNS _ifs.bool.
    Predicates can be used in the WHERE clause of the SELECT statement along with ordinary
    boolean expressions (see 4.5.3)
    
  4.4. CREATE MODIFIER
      Creates a user defined intuitionistic fuzzy modifier. The modifier is a function,
    which returns _ifs.bool and accepts _ifs.bool as the first parameter. The definition of
    the function shall modify the intuitionistic fuzzy boolean value specified as the first
    parameter using the other parameters, if any, and return the modified value. The syntax
    is the same as the one of the CREATE FUNCTION statement but without the RESULT clause.
        CREATE MODIFIER func_name (...) is equal to
        CREATE FUNCTION func_name (_ifs.bool, ...) ... RETURNS _ifs.bool
      In the definition of the modifier, truth and falsity degrees can be accessed using
    $1.mu and $1.nu . The parameters, if any, start from $2.
    
  4.5. SELECT
      Retrieves rows applying the operations selection and Cartesian product, if required.
    First, if the relations in the FROM clause are more than one, the Cartesian product
    operation is applied to them. Then, if WHERE clause is present, the selection operation
    is applied to the relation (or Cartesian product of relations) specified in the FROM
    clause.
      New keywords MSHIP and NMSHIP are introduced. If used in the target list or the HAVING
    clause, they have the special meaning of "the degrees of membership and non-membership
    of the target relation (the result set)". Otherwise, they are interpreted as the names
    of regular columns from the source relation (the FROM clause relation).
      The syntax of all clauses is not changed, except for the MODIFY BY clause, which is
    a new one. Only IFSQL specifics are pointed in the descriptions below.
    
    4.5.1. Target list
        The list of columns to be viewed. May include the keywords MSHIP and NMSHIP in order
      to present the degrees of membership and non-membership of each record in separate
      columns.
        NOTE: To display the proper values, keywords MSHIP and NMSHIP must neither participate
      in expressions nor be aliased. If you want to display an expression with the degree of
      membership (for example), you must use sub-selects:
      SELECT ..., MSHIP / 2 AS expr FROM (SELECT ..., MSHIP FROM ...)
        instead of
      SELECT ..., MSHIP / 2 AS expr FROM ...
      
    4.5.2. FROM clause
        Each relation (table or view) in FROM clause must include MSHIP and NMSHIP columns
      in order the Cartesian product to be computed. That is, if a view or sub-select
      participates in the FROM clause, the columns with names MSHIP and NMSHIP must be
      defined in the view (sub-select) and these columns must define the degrees of
      membership and non-membership of the view (sub-select).
        For outer joins, it is assumed that the missing records of the inner table have degrees
      of membership and non-membership respectively 0 and 1.
      
    4.5.3. WHERE clause
        The condition to be applied to the records in the relation. May contain intuitionistic
      fuzzy predicates, as well as ordinary boolean expressions. Also may include operations
      between IFPs and/or ordinary boolean expressions, e.g. the expression "pred (x) and c > 0",
      where pred is an IFP, is a regular WHERE clause condition.
        The columns MSHIP and NMSHIP must not participate in the expression in the WHERE clause.
      If you want to filter the result records depending on the degrees of membership and/or
      non-membership of the records, you must specify the filter condition in the HAVING clause
      (see 4.5.5)
      
    4.5.4. GROUP BY clause
        Must not include the columns MSHIP and NMSHIP. If GROUP BY clause is present, the degrees
      of membership/non-membership of a grouped record are computed as the average of the degrees
      of membership/non-membership of each record in the group.
      
    4.5.5. HAVING clause
        An ordinary boolean expression (the same as in SQL, IFPs not allowed here).
      May include the columns MSHIP and NMSHIP in order to apply a filter upon the displayed
      records depending on their degrees of membership and/or non-membership. IFPs cannot be used.
      
    4.5.6. MODIFY BY clause (new)
        Syntax:      MODIFY BY modifier_name ([arg[,...]]) [,...]
        Description: Specifies a modifier (or a series of modifiers) to be applied to the result
      relation. The modifiers are applied in the order they are specified. Built-in modifiers are
      nec(), poss(), d(alpha), f(alpha,beta), g(alpha,beta), h(alpha,beta), hs(alpha,beta),
      j(alpha,beta) and js(alpha,beta), which implement respectively the operators necessity,
      possibility, D, F, G, H, H*, J and J* from IFS theory.
      
    4.5.7. Set operations - UNION and INTERSECT
        The operations union and intersection are implemented in IFSQL. The syntax is the same
      as the ordinary UNION and INTERSECT operations in SQL with the limitation that the column
      names in the both relations must match exactly (make sure to do this taking advantage of
      column aliases) and the remark that if the columns MSHIP and/or NMSHIP exist in the source
      relations, in the target relation they will contain the corresponding values obtained as
      a result from the operation (union or intersection, see [1]).
      
  4.6. UPDATE
      A variant of the UPDATE statement is introduced in the IFSQL (except for the well-known
    UPDATE ... SET statement):
      Syntax:      UPDATE table_name MODIFY BY modifier_name ([arg[,...]]) [,...]
      Description: The MODIFY BY clause specifies a modifier (or a series of modifiers) to be
    applied to the table specified by table_name. The modifiers are applied in the order they
    are specified.

  4.7. Crisp relations
      A table is considered crisp (not intuitionistic fuzzy), if its name begins with one of
    the prefixes "sql_", "pg_" and "crisp_". Crisp tables are processed as ordinary tables in
    the SELECT statement, although they may participate in the FROM clause along with IFRs.
    If the name of the table in CREATE TABLE statement begins with one of the above-mentioned
    prefixes, the table is created as crisp, i.e. no additional columns are added.
  
  4.8. Setting the database type
      The user is able to set the type of the database (see 3.4) through the statement
    SET DATABASE TYPE
      Syntax:      SET DATABASE TYPE = dbtype
      Description: The statement sets the type of the current database to dbtype. The set of
    possible values for dbtype is: fuzzy, possibilistic. By default, the database is created
    with fuzzy type.
      The user can query the type of the database using the statement SHOW DATABASE TYPE.


5. Enabling IFSQL support
    The support for IFSQL commands in PostgreSQL must be explicitly enabled by setting the
  value of the run-time parameter intuitionistic_fuzzy to on. When a session is open on the
  PostgreSQL server, this support is off by default. You should run the command
      SET intuitionistic_fuzzy = on;
  in order to enable it. Otherwise, PostgreSQL will consider all the commands in the session
  as ordinary SQL commands. Of course, you can disable it anytime by setting the option to off.
  You can take full advantage of the syntax of the SET command [2], e.g. if you want to enable
  the IFSQL support only for the current transaction (LOCAL) or for the entire session (GLOBAL).
    The reason for making it is that most of the frontends implicitly send a few SQL commands
  to the server immediately after the connection is done and they don't expect the PostgreSQL
  to interpret the commands as IFSQL commands. If you want to use such frontends to make IFSQL
  queries, it is possible, just enable the IFSQL support.

  5.1. Enabling IFSQL support for a single command
      To enable the support for a single command, add the prefix "[IFSQL]" to the command and
    IFPG will consider it an IFSQL command. For example:
        [IFSQL] SELECT a, b, MSHIP FROM tbl;
      NOTE: The prefix is case-sensitive.


6. Example
    This example shows how to create a database and use the IFSQL commands. First, create the
  database using the regular CREATE DATABASE command. If you enabled IFSQL support, the database
  is created as an IFRDB and you can make IFSQL queries to it. If IFSQL was disabled, you can
  fuzzify the database running the script ifpg-fuzzifydb database user, where the command line
  parameters "database" and "user" are respectively the name of the database to be fuzzified
  and a user with the required priviledges to the database.
    The easiest way is to connect to an existing database (e.g. template1) and then execute the
  command:
      [IFSQL] CREATE DATABASE dbname;
    Now connect to the new database and enable IFSQL support:
      SET intuitionistic_fuzzy = on;
    
    Let team_results be a table with 5 columns: team_name, league, wins, losses, draws.
  The table contains information about a team - in which league (championship) how many matches
  the team won, lost and drew. The table is created with the statement:
      CREATE TABLE team_results (
        team_name character varying,
        league character varying,
        wins integer,
        losses integer,
        draws integer
      );
    
    Let strong_team (wins, losses, draws) be a predicate, which answers the question "How strong is
  the team?" The answer is an intuitionistic fuzzy value, where the degrees of truth and falsity
  are computed by the formula:
      mu = wins / (wins+losses+draws)
      nu = losses / (wins+losses+draws)
  i.e. the truth degree is proportional to the number of won matches, the falsity degree is
  proportional to the number of lost matches and the indefiniteness is proportional to the
  number of draw games. We create the predicate using the following statement:
      CREATE PREDICATE strong_team (integer, integer, integer)
        AS 'SELECT $1 / ($1+$2+$3)::double precision, $2 / ($1+$2+$3)::double precision'
        LANGUAGE sql;

    Let's fill the table with some data:
      INSERT INTO team_results (team_name, league, wins, losses, draws)
        VALUES ('Liverpool', 'England', 5, 3, 2);
      INSERT INTO team_results (team_name, league, wins, losses, draws)
        VALUES ('Arsenal', 'England', 5, 2, 3);
      INSERT INTO team_results (team_name, league, wins, losses, draws)
        VALUES ('Chelsea', 'England', 4, 5, 1);

      INSERT INTO team_results (team_name, league, wins, losses, draws)
        VALUES ('Roma', 'Italy', 3, 3, 4);
      INSERT INTO team_results (team_name, league, wins, losses, draws)
        VALUES ('Milan', 'Italy', 4, 3, 3);

      INSERT INTO team_results (team_name, league, wins, losses, draws)
        VALUES ('Arsenal', 'ChampionsLeague', 4, 2, 4);
      INSERT INTO team_results (team_name, league, wins, losses, draws)
        VALUES ('Chelsea', 'ChampionsLeague', 2, 4, 4);
      INSERT INTO team_results (team_name, league, wins, losses, draws)
        VALUES ('Milan', 'ChampionsLeague', 3, 4, 3);

    Well, here is the result of the statement which runs the command "List the strong teams in
  all leagues!":
    SELECT team_name, league, MSHIP, NMSHIP FROM team_results WHERE strong_team (wins, losses, draws);
      
      team_name |     league      | mship | nmship
      -----------+-----------------+-------+--------
      Liverpool | England         |   0.5 |    0.3
      Arsenal   | England         |   0.5 |    0.2
      Chelsea   | England         |   0.4 |    0.5
      Roma      | Italy           |   0.3 |    0.3
      Milan     | Italy           |   0.4 |    0.3
      Arsenal   | ChampionsLeague |   0.4 |    0.2
      Milan     | ChampionsLeague |   0.3 |    0.4
      Chelsea   | ChampionsLeague |   0.2 |    0.4
      
    Now, we can list the strong teams in England:
    SELECT team_name, MSHIP, NMSHIP FROM team_results 
      WHERE league = 'England' AND strong_team (wins, losses, draws);
    
      team_name | mship | nmship
     -----------+-------+--------
      Liverpool |   0.5 |    0.3
      Arsenal   |   0.5 |    0.2
      Chelsea   |   0.4 |    0.5
    
    We can create an IFR containing the strong teams in england using the following statements:
    CREATE TABLE strong_english_teams (team_name character varying);
    INSERT INTO strong_english_teams (team_name, "mship", "nmship")
      SELECT team_name, MSHIP, NMSHIP FROM team_results 
      WHERE league = 'England' AND strong_team (wins, losses, draws);
    
    We can display all teams which are strong either in England or in the Champion's League
  using the UNION operation:
    SELECT team_name, MSHIP, NMSHIP FROM strong_english_teams UNION
    SELECT team_name, MSHIP, NMSHIP FROM team_results
      WHERE league = 'ChampionsLeague' AND strong_team (wins, losses, draws);
      
      team_name | mship | nmship
     -----------+-------+--------
      Liverpool |   0.5 |    0.3
      Chelsea   |   0.4 |    0.4
      Milan     |   0.3 |    0.4
      Arsenal   |   0.5 |    0.2

    Display all teams which are strong in England but weak in the Champion's League
  using the INTERSECT operation:
    SELECT team_name, MSHIP, NMSHIP FROM strong_english_teams INTERSECT
    SELECT team_name, MSHIP, NMSHIP FROM team_results
      WHERE league = 'ChampionsLeague' AND NOT strong_team (wins, losses, draws);
  
      team_name | mship | nmship
     -----------+-------+--------
      Chelsea   |   0.4 |    0.5
      Arsenal   |   0.2 |    0.4

    The above results may be achieved by using the Cartesian product operation (JOIN)
  between the IFRs "strong english teams" and "strong champions league's teams":

    SELECT strong_english_teams.team_name, MSHIP, NMSHIP
    FROM strong_english_teams, team_results
    WHERE strong_english_teams.team_name = team_results.team_name
      AND team_results.league = 'ChampionsLeague'
      AND NOT strong_team (team_results.wins, team_results.losses, team_results.draws);

    Now we can filter the results using the HAVING clause:
    
    SELECT strong_english_teams.team_name, MSHIP, NMSHIP
    FROM strong_english_teams, team_results
    WHERE strong_english_teams.team_name = team_results.team_name
      AND team_results.league = 'ChampionsLeague'
      AND NOT strong_team (team_results.wins, team_results.losses, team_results.draws)
    HAVING MSHIP > 0.3;
    
       team_name | mship | nmship
      -----------+-------+--------
       Chelsea   |   0.4 |    0.5
    
    We can apply a modifier using the MODIFY BY clause:
    
    SELECT strong_english_teams.team_name, MSHIP, NMSHIP
    FROM strong_english_teams, team_results
    WHERE strong_english_teams.team_name = team_results.team_name
      AND team_results.league = 'ChampionsLeague'
      AND NOT strong_team (team_results.wins, team_results.losses, team_results.draws)
    HAVING MSHIP > 0.3
    MODIFY BY f(0.2,0.3);
       team_name | mship | nmship
      -----------+-------+--------
       Chelsea   |  0.42 |   0.53
      
      or a series of modifiers:
    
    SELECT strong_english_teams.team_name, MSHIP, NMSHIP
    FROM strong_english_teams, team_results
    WHERE strong_english_teams.team_name = team_results.team_name
      AND team_results.league = 'ChampionsLeague'
      AND NOT strong_team (team_results.wins, team_results.losses, team_results.draws)
    HAVING MSHIP > 0.3
    MODIFY BY f(0.2,0.3), nec();
       team_name | mship | nmship
      -----------+-------+--------
       Chelsea   |  0.42 |   0.58

    So far, so good, we saw a complete example of how to use the IFSQL SELECT statement.
  Now, assuming that the criteria for estimating whether an english team is strong have
  changed, we should update the relation strong_english_teams. If we use the modifier G,
  the statement looks like this:
      UPDATE strong_english_teams MODIFY BY g(0.5,0.7);
  and the contents of the table is the following:
      SELECT team_name, mship, nmship FROM strong_english_teams;
       team_name | mship | nmship
      -----------+-------+--------
       Liverpool |  0.25 |   0.21
       Arsenal   |  0.25 |   0.14
       Chelsea   |  0.2  |   0.35
    
7. Internals
    IFPG is linked to PostgreSQL executable. When a query arrives at the server, IFPG
  determines whether it is an IFSQL query (see chapter 5) and if it is, passes the query
  to the IFSQL translator. The latter translates the query to a regular SQL query and
  passes it to PostgreSQL parser for further processing. The translator uses auxiliary
  objects defined in _ifs schema (see schema.sql for details). There are three variants
  of the function make_bool, which returns an IFB value from different sources. Also,
  the functions ifand, ifor and ifnot are defined, which implement the Intuitionistic
  fuzzy logical operations AND, OR and NOT. Functions get_mu and get_nu return respectively
  the degrees of truth and falsity of an IFB.
    The most common and most complicated (from IFSQL translator's point of view) command
  is SELECT. Below is a short description of the essence of the algorithm for translating
  the SELECT statement:
  
      SELECT a, b, MSHIP, NMSHIP
      FROM x, y
      WHERE p OR q AND s
      HAVING d AND MSHIP > 0.5
      MODIFY BY f (f1, f2), d (d1)
  
  is translated to:
  
      SELECT a, b, _ifs.get_mu ($MC_MMSHIP) AS MSHIP, _ifs.get_nu ($MC_MMSHIP) AS NMSHIP
      FROM x, y
      WHERE _ifs.get_nu ($MMSHIP) < 1
      HAVING d AND _ifs.get_mu ($GC_MMSHIP) > 0.5
      
  where $MMSHIP, $GC_MMSHIP and $MC_MMSHIP are the following strings:
  - $MMSHIP (formed of FROM and WHERE clauses):
    _ifs.ifand (
      _ifs.ifand (
        _ifs.make_bool (coalesce (x.mship, 0), coalesce (x.nmship, 1)),
        _ifs.make_bool (coalesce (y.mship, 0), coalesce (y.nmship, 1))
      ) -- from FROM clause
      , _ifs.ifor (
          _ifs.make_bool (p), 
          _ifs.ifand (_ifs.make_bool (q), _ifs.make_bool (s))
        ) -- from WHERE clause
    )
  - if GROUP BY clause is not present, $GC_MMSHIP = $MMSHIP, otherwise
      $GC_MMSHIP = _ifs.make_bool (avg(_ifs.get_mu($MMSHIP)), avg(_ifs.get_nu($MMSHIP)))
  - $MC_MMSHIP (formed of MODIFY BY clause) = _ifs.modif_d (_ifs.modif_f ($GC_MMSHIP, f1, f2), d1)
  
    For further details, review the source code. The file ifsql/gram.y contains rules from
  the context-free gramar of IFSQL. All tokens and non-terminals are of type string and all
  actions just make translations. The default action of bison's output file is modified
  to just concatenate the components of the rule (see DEFAULT_TRANSLATION_ACTION macro).
    In order to test how translator works, you can run the translator as an executable
  (see installation guide).


8. TODO list (functionality issues)
  8.1. Error messages - If translation was OK, but an error occurred afterwards, the printed
    message is not comprehensible.
  8.2. Classical fuzzy implementation - Implement a language which processes fuzzy (not
    intuitionistic fuzzy) queries.
  8.3. Features, introduced in PostgreSQL 8.0.0, aren't supported yet, e.g. dollar-quoted string
    constants and tablespaces.
  8.4. Several types of union and intersection operations (e.g. with probabilistic support)
  8.5. Ability to apply a user-specified aggregate function to obtain the degrees of membership
    and non-membership of a grouped record (see 4.5.4).


9. Changes from 1.0
  Added probabilistic database support:
  - defined probabilistic variants of the operations: logical AND and OR (see 1), selection (see 2.2)
    and Cartesian product (see 2.3)
  - defined SET DATABASE TYPE statement to set the type of the database (fuzzy or brobabilistic)


Abbreviations
  IFB      Intuitionistic Fuzzy Boolean
  IFP      Intuitionistic Fuzzy Predicate
  IFPG     Intuitionistic Fuzzy PostGreSQL
  IFR      Intuitionistic Fuzzy Relation
  IFRDB    Intuitionistic Fuzzy Relational DataBase
  IFRDBMS  Intuitionistic Fuzzy Relational DataBase Management System
  IFS      Intuitionistic Fuzzy Set
  IFSQL    Intuitionistic Fuzzy Structured Query Language

References
  [1] Atanassov K., Intuitionistic Fuzzy Sets, Springer-Verlag, Heidelberg, 1999
  [2] PostgreSQL Documentation, http://borg.postgresql.org/docs/
  [3] Intuitionistic Fuzzy Sets Research Group,
        http://www.clbme.bas.bg/Projects/gnifs/ifs/Group.html

Author
  Boyan Kolev
  Central Laboratory for Biomedical Engineering "Prof. Ivan Daskalov"
  Bulgarian Academy of Sciences
  Acad.G.Bonchev Str., Bl.105
  Sofia-1113, BULGARIA
  E-mail: bik@clbme.bas.bg
  http://www.clbme.bas.bg/
