Skip to content

Commit 1a466be

Browse files
committed
Final version - 1.0.
1 parent af1e741 commit 1a466be

File tree

6 files changed

+356
-0
lines changed

6 files changed

+356
-0
lines changed

.gitignore

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
### Haskell template
2+
dist
3+
cabal-dev
4+
*.o
5+
*.hi
6+
*.chi
7+
*.chs.h
8+
*.dyn_o
9+
*.dyn_hi
10+
.hpc
11+
.hsenv
12+
.cabal-sandbox/
13+
cabal.sandbox.config
14+
*.prof
15+
*.aux
16+
*.hp
17+
.stack-work/
18+
### Emacs template
19+
# -*- mode: gitignore; -*-
20+
*~
21+
\#*\#
22+
/.emacs.desktop
23+
/.emacs.desktop.lock
24+
*.elc
25+
auto-save-list
26+
tramp
27+
.\#*
28+
29+
# Org-mode
30+
.org-id-locations
31+
*_archive
32+
33+
# flymake-mode
34+
*_flymake.*
35+
36+
# eshell files
37+
/eshell/history
38+
/eshell/lastdir
39+
40+
# elpa packages
41+
/elpa/
42+
43+
# reftex files
44+
*.rel
45+
46+
# AUCTeX auto folder
47+
/auto/
48+
49+
# cask packages
50+
.cask/
51+
### JetBrains template
52+
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
53+
54+
*.iml
55+
56+
## Directory-based project format:
57+
.idea/
58+
# if you remove the above rule, at least ignore the following:
59+
60+
# User-specific stuff:
61+
# .idea/workspace.xml
62+
# .idea/tasks.xml
63+
# .idea/dictionaries
64+
65+
# Sensitive or high-churn files:
66+
# .idea/dataSources.ids
67+
# .idea/dataSources.xml
68+
# .idea/sqlDataSources.xml
69+
# .idea/dynamic.xml
70+
# .idea/uiDesigner.xml
71+
72+
# Gradle:
73+
# .idea/gradle.xml
74+
# .idea/libraries
75+
76+
# Mongo Explorer plugin:
77+
# .idea/mongoSettings.xml
78+
79+
## File-based project format:
80+
*.ipr
81+
*.iws
82+
83+
## Plugin-specific files:
84+
85+
# IntelliJ
86+
/out/
87+
88+
# mpeltonen/sbt-idea plugin
89+
.idea_modules/
90+
91+
# JIRA plugin
92+
atlassian-ide-plugin.xml
93+
94+
# Crashlytics plugin (for Android Studio and IntelliJ)
95+
com_crashlytics_export_strings.xml
96+
crashlytics.properties
97+
crashlytics-build.properties
98+
99+
# Created by .ignore support plugin (hsz.mobi)

FST/FuzzySet.hs

+167
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
{-# LANGUAGE ConstraintKinds #-}
2+
{-# LANGUAGE TypeFamilies #-}
3+
{-# LANGUAGE MultiParamTypeClasses #-}
4+
{-# LANGUAGE FlexibleInstances #-}
5+
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
6+
7+
-- | If X is a collection of objects denoted generically by x, then a fuzzy set F(A) in X is a set of ordered pairs.
8+
-- Each of them consists of an element x and a membership function which maps x to the membership space M.
9+
module FuzzySet
10+
( FuzzySet (..)
11+
, preimage
12+
, empty
13+
, add
14+
, support
15+
, mu
16+
, core
17+
, alphaCut
18+
, fromList
19+
, map1
20+
, map2
21+
, union
22+
, intersection
23+
, complement
24+
, algebraicSum
25+
, algebraicProduct
26+
, generalizedProduct
27+
, ExoFunctor (..)
28+
) where
29+
30+
import Prelude hiding (fmap)
31+
import GHC.Exts (Constraint)
32+
import qualified Algebra.Lattice as L
33+
import qualified Data.List as List
34+
import qualified Data.Map as Map
35+
import qualified Data.Maybe as Maybe ()
36+
37+
-- $setup
38+
-- >>> import Membership
39+
-- >>> let zfs1 = fromList [(1, Z 0.2), (2, Z 0.5)]
40+
-- >>> let zfs2 = fromList [(2, Z 0.2), (3, Z 0.2)]
41+
-- >>> let pfs1 = fromList [(1, PA 0.2), (2, PA 0.5)]
42+
-- >>> let pfs2 = fromList [(2, PA 0.2), (3, PA 0.2)]
43+
44+
-- | Returns the preimage of the given set in input
45+
-- prop> preimage (^2) 25 [1..5] == [5]
46+
preimage :: (Eq i, Eq j) => (i -> j) -> j -> [i] -> [i]
47+
preimage f y xs = [x | x <- xs, f x == y]
48+
49+
-- | FuzzySet type definition
50+
newtype FuzzySet m i = FS (Map.Map i m) deriving (Eq, Ord)
51+
52+
instance (Ord i, L.BoundedLattice m, Show i, Show m) => Show (FuzzySet m i) where
53+
show (FS fs) = "FuzzySet {" ++ List.intercalate "," [show p | p <- Map.assocs fs] ++ "}"
54+
55+
-- | Returns an empty fuzzy set
56+
empty :: (Ord i, L.BoundedLattice m) => FuzzySet m i
57+
empty = FS Map.empty
58+
59+
-- | Inserts a new pair (i, m) to the fuzzy set
60+
-- prop> add zfs1 (i, L.bottom) == zfs1
61+
-- prop> add pfs1 (i, L.bottom) == pfs1
62+
add :: (Ord i, Eq m, L.BoundedLattice m) => FuzzySet m i -> (i, m) -> FuzzySet m i
63+
add (FS fs) (i, m) = if m == L.bottom then FS fs else FS (Map.insert i m fs)
64+
65+
-- | Returns the fuzzy set's support
66+
-- prop> support zfs1 == [1, 2]
67+
-- prop> support pfs1 == [1, 2]
68+
support :: (Ord i, L.BoundedLattice m) => FuzzySet m i -> [i]
69+
support (FS fs) = Map.keys fs
70+
71+
-- | Returns the element i's membership
72+
-- if i belongs to the support returns its membership, otherwise returns bottom lattice value
73+
-- prop> mu zfs1 1 == Z 0.2
74+
-- prop> mu zfs1 10 == L.bottom
75+
-- prop> mu pfs1 1 == PA 0.2
76+
-- prop> mu pfs1 10 == L.bottom
77+
mu :: (Ord i, L.BoundedLattice m) => FuzzySet m i -> i -> m
78+
mu (FS fs) i = case result of
79+
Nothing -> L.bottom
80+
(Just m) -> m
81+
where result = Map.lookup i fs
82+
83+
-- | Returns the crisp subset of given fuzzy set consisting of all elements with membership equals to one
84+
-- prop> core (fromList [(-1, Z 0.5), (0, Z 0.8), (1, Z 1.0), (2, Z 0.4)]) == [1]
85+
-- prop> core (fromList [(-1, PA 0.5), (0, PA 0.8), (1, PA 1.0), (2, PA 0.4)]) == [1]
86+
core :: (Ord i, Eq m, L.BoundedLattice m) => FuzzySet m i -> [i]
87+
core fs = preimage (mu fs) L.top (support fs)
88+
89+
-- | Returns those elements whose memberships are greater or equal than the given alpha
90+
-- prop> alphaCut (fromList [(-1, Z 0.5), (0, Z 0.8), (1, Z 1.0), (2, Z 0.4)]) (Z 0.5) == [-1, 0, 1]
91+
-- prop> alphaCut (fromList [(-1, PA 0.5), (0, PA 0.8), (1, PA 1.0), (2, PA 0.4)]) (PA 0.5) == [-1, 0, 1]
92+
alphaCut :: (Ord i, Ord m, L.BoundedLattice m) => FuzzySet m i -> m -> [i]
93+
alphaCut fs alpha = [i | i <- support fs, mu fs i >= alpha]
94+
95+
-- | Builds a fuzzy set from a list of pairs
96+
-- prop> fromList [(1, Z 0.2)] == add empty (1, Z 0.2)
97+
-- prop> fromList [(1, PA 0.2)] == add empty (1, PA 0.2)
98+
fromList :: (Ord i, Eq m, L.BoundedLattice m) => [(i, m)] -> FuzzySet m i
99+
fromList = foldl add empty
100+
101+
-- | Applies a unary function to the specified fuzzy set
102+
-- prop> map1 (*2) zfs1 == fromList [(1, Z 0.4), (2, Z 1.0)]
103+
-- prop> map1 (*2) pfs1 == fromList [(1, PA 0.4), (2, PA 1.0)]
104+
map1 :: (Ord i, Eq m, L.BoundedLattice m) => (m -> m) -> FuzzySet m i -> FuzzySet m i
105+
map1 f fs = fromList [(i, f (mu fs i)) | i <- support fs]
106+
107+
-- | Applies a binary function to the two specified fuzzy sets
108+
-- prop> map2 (+) zfs1 zfs2 == fromList [(1, Z 0.2), (2, Z 0.7), (3, Z 0.2)]
109+
-- prop> map2 (+) pfs1 pfs2 == fromList [(1, PA 0.2), (2, PA 0.7), (3, PA 0.2)]
110+
map2 :: (Ord i, Eq m, L.BoundedLattice m) => (m -> m -> m) -> FuzzySet m i -> FuzzySet m i -> FuzzySet m i
111+
map2 f fs1 fs2 = fromList [(i, f (mu fs1 i) (mu fs2 i))| i <- union_support]
112+
where union_support = support fs1 `List.union` support fs2
113+
114+
-- | Returns the union between the two specified fuzzy sets
115+
-- prop> union zfs1 zfs2 == fromList [(1, Z 0.2), (2, Z 0.5), (3, Z 0.2)]
116+
-- prop> union pfs1 pfs2 == fromList [(1,PA 0.2),(2,PA 0.6),(3,PA 0.2)]
117+
union :: (Ord i, Eq m, L.BoundedLattice m) => FuzzySet m i -> FuzzySet m i -> FuzzySet m i
118+
union = map2 (L.\/)
119+
120+
-- | Returns the intersection between the two specified fuzzy sets
121+
-- prop> intersection zfs1 zfs2 == fromList [(2, Z 0.2)]
122+
-- prop> intersection pfs1 pfs2 == fromList [(2, PA 0.1)]
123+
intersection :: (Ord i, Eq m, L.BoundedLattice m) => FuzzySet m i -> FuzzySet m i -> FuzzySet m i
124+
intersection = map2 (L./\)
125+
126+
-- | Returns the complement of the specified fuzzy set
127+
-- prop> complement zfs1 == fromList [(1, Z 0.8), (2, Z 0.5)]
128+
-- prop> complement pfs1 == fromList [(1, PA 0.8), (2, PA 0.5)]
129+
complement :: (Ord i, Num m, Eq m, L.BoundedLattice m) => FuzzySet m i -> FuzzySet m i
130+
complement fs = fromList [(x, L.top - mu fs x) | x <- support fs]
131+
132+
-- | Returns the algebraic sum between the two specified fuzzy sets
133+
-- prop> algebraicSum zfs1 zfs2 == fromList [(1, Z 0.2), (2, Z 0.7), (3, Z 0.2)]
134+
-- prop> algebraicSum pfs1 pfs2 == fromList [(1, PA 0.2), (2, PA 0.7), (3, PA 0.2)]
135+
algebraicSum :: (Ord i, Eq m, Num m, L.BoundedLattice m) => FuzzySet m i -> FuzzySet m i -> FuzzySet m i
136+
algebraicSum = map2 (+)
137+
138+
-- | Returns the algebraic product between the two specified fuzzy sets
139+
-- prop> algebraicProduct zfs1 zfs2 == fromList [(2, Z 0.1)]
140+
-- prop> algebraicProduct pfs1 pfs2 == fromList [(2, PA 0.1)]
141+
algebraicProduct :: (Ord i, Eq m, Num m, L.BoundedLattice m) => FuzzySet m i -> FuzzySet m i -> FuzzySet m i
142+
algebraicProduct = map2 (*)
143+
144+
-- | Returns the cartesian product between two fuzzy sets using the specified function
145+
-- prop> generalizedProduct (+) zfs1 zfs2 == fromList [((1, 2), Z 0.4), ((1, 3), Z 0.4), ((2, 2), Z 0.7), ((2, 3), Z 0.7)]
146+
-- prop> generalizedProduct (+) pfs1 pfs2 == fromList [((1, 2), PA 0.4), ((1, 3), PA 0.4), ((2, 2), PA 0.7), ((2, 3), PA 0.7)]
147+
generalizedProduct :: (Ord i, Ord j, Eq m, L.BoundedLattice m) => (m -> m -> m) -> FuzzySet m i -> FuzzySet m j -> FuzzySet m (i, j)
148+
generalizedProduct f fs1 fs2 = fromList [((x1, x2), f (mu fs1 x1) (mu fs2 x2) )| x1 <- support fs1, x2 <- support fs2]
149+
150+
-- | Defines a mapping between sub-categories preserving morphisms
151+
class ExoFunctor f i where
152+
type SubCatConstraintI f i :: Constraint
153+
type SubCatConstraintI f i = ()
154+
type SubCatConstraintJ f j :: Constraint
155+
type SubCatConstraintJ f j = ()
156+
157+
fmap :: (SubCatConstraintI f i, SubCatConstraintJ f j) => (i -> j) -> f i -> f j
158+
159+
-- | Defines a functor for the FuzzySet type that allows to implement the Extension principle
160+
-- prop> fmap (^2) (fromList [(-1, Z 0.5), (0, Z 0.8), (1, Z 1.0), (2, Z 0.4)]) == fromList [(0, Z 0.8), (1, Z 1.0), (4, Z 0.4)]
161+
-- prop> fmap (^2) (fromList [(-1, PA 0.5), (0, PA 0.8), (1, PA 1.0), (2, PA 0.4)]) == fromList [(0, PA 0.8), (1, PA 1.0), (4, PA 0.4)]
162+
instance (L.BoundedLattice m, Eq m) => ExoFunctor (FuzzySet m) i where
163+
type SubCatConstraintI (FuzzySet m) i = Ord i
164+
type SubCatConstraintJ (FuzzySet m) j = Ord j
165+
166+
fmap f fs = fromList [(f x, mu_y (f x)) | x <- support fs]
167+
where mu_y y = L.joins1 [ mu fs a | a <- preimage f y (support fs)]

FST/Membership.hs

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2+
3+
-- | Membership types for the Fuzzy Set definition
4+
module Membership
5+
( ZadehMembership (..)
6+
, PAMembership (..)
7+
) where
8+
9+
import qualified Algebra.Lattice as L
10+
11+
-- | Membership value between 0 and 1 with min and max operators
12+
newtype ZadehMembership = Z Double deriving (Show, Eq, Ord, Num)
13+
14+
-- | Membership value between 0 and 1 with algebraic sum and product operators
15+
newtype PAMembership = PA Double deriving (Show, Eq, Ord, Num)
16+
17+
instance L.JoinSemiLattice ZadehMembership where
18+
Z x \/ Z y = Z (max x y)
19+
20+
instance L.MeetSemiLattice ZadehMembership where
21+
Z x /\ Z y = Z (min x y)
22+
23+
instance L.Lattice ZadehMembership where
24+
25+
instance L.BoundedJoinSemiLattice ZadehMembership where
26+
bottom = Z 0.0
27+
28+
instance L.BoundedMeetSemiLattice ZadehMembership where
29+
top = Z 1.0
30+
31+
instance L.BoundedLattice ZadehMembership where
32+
33+
instance L.JoinSemiLattice PAMembership where
34+
PA x \/ PA y = PA (x + y - x * y)
35+
36+
instance L.MeetSemiLattice PAMembership where
37+
PA x /\ PA y = PA (x * y)
38+
39+
instance L.Lattice PAMembership where
40+
41+
instance L.BoundedJoinSemiLattice PAMembership where
42+
bottom = PA 0.0
43+
44+
instance L.BoundedMeetSemiLattice PAMembership where
45+
top = PA 1.0
46+
47+
instance L.BoundedLattice PAMembership where

Setup.hs

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import Distribution.Simple
2+
main = defaultMain

fst.cabal

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: fst
2+
version: 0.1.0.0
3+
synopsis: Fuzzy Set Theory library
4+
-- description:
5+
-- license:
6+
-- license-file:
7+
homepage:
8+
author: Marco Di Pietro, Claudio Greco, Corrado Mencar, Alessandro Suglia
9+
maintainer: Marco Di Pietro, Claudio Greco, Corrado Mencar, Alessandro Suglia
10+
category: Math
11+
-- copyright:
12+
build-type: Simple
13+
-- extra-source-files:
14+
cabal-version: >=1.10
15+
16+
library
17+
exposed-modules: FuzzySet, Membership
18+
-- other-modules:
19+
-- other-extensions:
20+
build-depends: base >= 4.7 && < 5,
21+
containers >= 0.5,
22+
lattices >= 1.5,
23+
doctest >= 0.10
24+
25+
hs-source-dirs: FST
26+
default-language: Haskell2010
27+
28+
test-suite doctests
29+
type: exitcode-stdio-1.0
30+
ghc-options: -threaded
31+
hs-source-dirs: test
32+
main-is: DocTests.hs
33+
build-depends: base >= 4.7 && < 5,
34+
doctest >= 0.10
35+
default-language: Haskell2010

test/DocTests.hs

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module Main where
2+
3+
import Test.DocTest
4+
5+
main :: IO ()
6+
main = doctest ["-isrc", "FST/Membership.hs", "FST/FuzzySet.hs"]

0 commit comments

Comments
 (0)