data_set.f90 Source File

Source Code

!
!  data_set.f90
!  This file is part of FIAT.
!
!  Copyright 2016 Christopher MacMackin <cmacmackin@gmail.com>
!  
!  This program is free software; you can redistribute it and/or modify
!  it under the terms of the GNU Lesser General Public License as
!  published by the Free Software Foundation; either version 3 of the 
!  License, or (at your option) any later version.
!  
!  This program 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 Lesser General Public License for more details.
!  
!  You should have received a copy of the GNU Lesser General Public
!  License along with this program; if not, write to the Free Software
!  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
!  MA 02110-1301, USA.
!  

module data_set_mod
  !* Author: Chris MacMackin
  !  Date: March 2016
  !  License: LGPLv3
  !
  ! Provides an abstract type for the set data structure. Such sets
  ! support similar operations to their mathematical counterparts.
  ! This class, and its descendents, have a comparable set of methods
  ! to those in the Python 
  ! [frozenset](https://docs.python.org/2/library/stdtypes.html#frozenset)
  ! type.
  !
  use abstract_container_mod, only: container, test_func, &
                                    addition_func, subtraction_func, &
                                    comparison_func,  action_sub
  use countable_mod, only: countable
  use array_list_mod, only: array_list
  implicit none
  private

  type, public, extends(countable), abstract :: data_set
    !* Author: Chris MacMackin
    !  Date: March 2016
    !
    ! An abstract type for set data structures. These sets support a 
    ! similar selection of operations as do their mathematical
    ! counterparts. The collection of methods for this type waas inspired
    ! by those available for the
    ! [frozenset](https://docs.python.org/2/library/stdtypes.html#frozenset)
    ! type in Python.
    !
  contains
    procedure(union_func), deferred :: union
      !! Returns a set containing the items held in this set and the
      !! passed set.
    generic :: operator(+) => union
      !! Returns the union of the two sets
    procedure(intersect_func), deferred :: intersection
      !! Returns a set containing only the items present in both this
      !! set and the argument
    procedure(diff_func), deferred :: difference
      !! Returns a set containing the item present in this set but not
      !! present in the argument
    generic :: operator(-) => difference
        !! Returns the difference between the two sets
    procedure(pure_diff_func), deferred :: symmetric_difference
      !! Returns a set containing those items present either only in 
      !! this set or only in the argument
    procedure(relation_func), deferred :: is_disjoint
      !! True if none of the items in this set are present in the 
      !! argument
    procedure(relation_func), deferred :: is_subset
      !! True if every element in this set is also in the argument
    procedure(relation_func), deferred :: is_proper_subset
      !! True if every element in this set is also in the argument and
      !! this set is not equal to the argument
    procedure(relation_func), deferred :: is_superset
      !! True if every element in the argument is also present in this
      !! set.
    procedure(relation_func), deferred :: is_proper_superset
      !! True if every element in the argument is also present in this
      !! set and the argument is not equal to this set.
    procedure(relation_func), deferred :: is_equal
      !! True if this set and the argument contain only the same items.
    generic :: operator(<=) => is_subset
      !! True if every element in this set is also in the argument
    generic :: operator(<) => is_proper_subset
      !! True if every element in this set is also in the argument and
      !! this set is not equal to the argument
    generic :: operator(>=) => is_superset
      !! True if every element in the argument is also present in this
      !! set.
    generic :: operator(>) => is_proper_superset
      !! True if every element in the argument is also present in this
      !! set and the argument is not equal to this set.
    generic :: operator(==) => is_equal
      !! True if this set and the argument contain only the same items.
    procedure(has_func), deferred :: has
      !! True if the argument is present in the set
    procedure(empty_func), deferred :: is_empty
      !! True if the set contains no items
    procedure(peek_func), deferred :: peek
      !! Returns an item, at random, from the set
    procedure(filter_func), deferred :: filter
      !! Returns a set containing all elements from this set for which
      !! the provided test procedure returns `.true.`
    procedure(enum_func), deferred :: enumerate
      !! Returns an [array_list] containing all of the items present
      !! in this set.
    procedure(min_func), deferred :: min
      !! Returns the smallest item in the set as determined using the
      !! provided comparison procedure
    procedure(max_func), deferred :: max
      !! Returns the largest item in the set as determined using the
      !! provided comparison procedure
    procedure(nearest_func), deferred :: nearest
      !! Returns the item in the set for which the provided subtraction
      !! procedure returns the smallest absolute value
    procedure(sum_func), deferred :: sum
      !! Returns an item representing the sum as determined by
      !! iteratively applying the provided addition procedure to all
      !! items in the set
  end type data_set

  abstract interface
    pure function union_func(this, other)
      import :: data_set
      class(data_set), intent(in) :: this, other !! A second set
      class(data_set), allocatable :: union_func
        !! A set containing all elements found in this one and the other
    end function union_func
    
    pure function intersect_func(this, other)
      import :: data_set
      class(data_set), intent(in) :: this, other !! A second set
      class(data_set), allocatable :: union_func
        !! A set containing all elements found both in this one and 
        !! the other
    end function intersect_func
    
    pure function diff_func(this, other)
      import :: data_set
      class(data_set), intent(in) :: this, other !! A second set
      class(data_set), allocatable :: diff_func
        !! A set containing elements found in this one and not the other
    end function diff_func
    
    pure function pure_diff_func(this, other)
      import :: data_set
      class(data_set), intent(in) :: this, other !! A second set
      class(data_set), allocatable :: pure_diff_func
        !! A set containing elements found in one, but not both, of this
        !! set or the other set
    end function pure_diff_func
    
    pure function relation_func(this, other)
      import :: data_set
      class(data_set), intent(in) :: this, other !! A second set
      logical :: relation_func
        !! Whether the relationship between `this` and `other` is true
    end function relation_func
    
    pure function has_func(this, item)
      import :: data_set
      class(data_set), intent(in) :: this
      class(*), intent(in) :: item
        !! An item which may be contained in the set
      logical :: has_func
        !! Whether `item` is present in this set
    end function has_func
    
    pure function empty_func(this)
      import :: data_set
      class(data_set), intent(in) :: this
      logical :: empty_func
        !! `.true.` if this set contains no items
    end function empty_func
    
    pure function peek_func(this)
      import :: data_set
      import :: container
      class(data_set), intent(in) :: this
      class(container), allocatable :: peek_func
        !! An item contained within the set. Is unallocated if the set
        !! is empty.
    end function peek_func
    
    pure function filter_func(this, test)
      import :: data_set
      import :: test_func
      class(data_set), intent(in) :: this
      procedure(test_func) :: test
        !! A test for which the values that pass will be returned in a
        !! new list
      class(data_set), allocatable :: filter_func
        !! Contains those items in this set for which `test` returns
        !! `.true.`
    end function filter_func

    pure function enum_func(this)
      import :: data_set
      import :: array_list
      class(data_set), intent(in) :: this
      type(array_list) :: enum_func
        !! A list containing copies of all of the items in this set
    end function enum_func
    
    pure function min_func(this, comparison)
      import :: data_set
      import :: comparison_func
      import :: container
      class(data_set), intent(in) :: this
      procedure(comparison_func) :: comparison
        !! A procedure which evaluates whether a [[container]] object is
        !! less than, equal to, or greater than another    
      class(container), allocatable :: min_func
        !! The smallest item in the set, as determined by the
        !! `comparison` function
    end function min_func
 
    pure function max_func(this, comparison)
      import :: data_set
      import :: comparison_func
      import :: container
      class(data_set), intent(in) :: this
      procedure(comparison_func) :: comparison
        !! A procedure which evaluates whether a [[container]] object is
        !! less than, equal to, or greater than another    
      class(container), allocatable :: max_func
        !! The largest item in the set, as determined by the
        !! `comparison` function
    end function max_func
    
    pure function nearest_func(this, item, subtraction)
      import :: data_set
      import :: container
      import :: subtraction_func
      class(data_set), intent(in) :: this
      class(*), intent(in) :: item
        !! The value which those in the set are being compared to
      procedure(subtraction_func) :: subtraction
        !! A function determining the magnitude of the difference
        !! between two items
      class(container), allocatable :: nearest_func
        !! The value from the set which, when passed to `subtraction`
        !! with `item` as the other argument, returns the smallest value
    end function nearest_func
    
    pure function sum_func(this, addition)
      import :: data_set
      import :: container
      import :: addition_func
      class(data_set), intent(in) :: this
      procedure(addition_func) :: addition
        !! A procedure performing addition between two [[container]]
        !! objects and returning the result in another container
      class(container), allocatable :: sum_func
        !! A container holding the sum of all of the items held within
        !! this set
    end function sum_func
  end interface
  
end module data_set_mod