Skip to content

Commit

Permalink
Merge branch 'master' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
tomhanika committed Feb 4, 2025
2 parents 43896b7 + 0e45830 commit 64c8b1e
Show file tree
Hide file tree
Showing 5 changed files with 553 additions and 0 deletions.
101 changes: 101 additions & 0 deletions doc/FuzzyFCA.org
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#+property: header-args :wrap src text
#+property: header-args:text :eval never

* Working with Fuzzy Formal Contexts

~conexp-clj~ offers basic functionality for fuzzy formal concept analysis.
A fuzzy formal context consists of a set of objects, a set of attributes and an incidence rerlation that determines the degree to which an object is incident to each attribute.
A fuzzy formal context can be declared as follows:


#+begin_src
(def fctx (make-fuzzy-context [1 2 3 4]
[1 2 3 4 5 6]
[1.0 1.0 0.0 1.0 1.0 0.2,
1.0 0.4 0.3 0.8 0.5 1.0,
0.2 0.9 0.7 0.5 1.0 0.6,
1.0 1.0 0.8 1.0 1.0 0.5]))
#+end_src

#+begin_src
|1 2 3 4 5 6
--+------------------------
1 |1.0 1.0 0 1.0 1.0 0.2
2 |1.0 0.4 0.3 0.8 0.5 1.0
3 |0.2 0.9 0.7 0.5 1.0 0.6
4 |1.0 1.0 0.8 1.0 1.0 0.5
#+end_src

It can also be created from an existing many valued context:

#+begin_src
(def mvctx (make-mv-context [1 2 3 4]
[1 2 3 4 5 6]
#{[1 1 1.0]
[1 2 1.0]
[1 3 0.0]
[1 4 1.0]
[1 5 1.0]
[1 6 0.2]
[2 1 1.0]
[2 2 0.4]
[2 3 0.3]
[2 4 0.8]
[2 5 0.5]
[2 6 1.0]
[3 1 0.2]
[3 2 0.9]
[3 3 0.7]
[3 4 0.5]
[3 5 1.0]
[3 6 0.6]
[4 1 1.0]
[4 2 1.0]
[4 3 0.8]
[4 4 1.0]
[4 5 1.0]
[4 6 0.5]}))

(def fctx (mv->fuzzy-context-nc mvctx))
#+end_src

On the resulting fuzzy formal context, the fuzzy derivation operations can now be computed.
These operations rely on fuzzy sets. A fuzzy set contains each element to a certain membership degree:

#+begin_src
(def fset (make-fuzzy-set {1 0.6 2 0.4}))
#+end_src

This set contains the element ~1~ to a degree of 0.6 and ~2~ to a degree of 0.4 .

A fuzzy derivation can now be computed as follows:

#+begin_src
(fuzzy-object-derivation fctx fset lukasiewicz-norm)
#+end_src

#+begin_src
([1 1]
[4 1]
[6 0.6000000000000001]
[3 0.3999999999999999]
[2 1.0]
[5 1])
#+end_src

The final argument of the ~fuzzy-object-derivation~ function is the norm used to compute the fuzzy set operations.
Available options are the ~lukasiewicz-norm~, the ~goedel-norm~ and the ~product-norm~.

The degree to which an implication holds in a fuzzy context can be computed using the ~validity~ method:


#+begin_src
(def fset1 (make-fuzzy-set {1 1}))
(def fset2 (make-fuzzy-set {2 1}))

(validity fctx fset1 fset2 product-norm)
#+end_src

#+begin_src
0.4
#+end_src
154 changes: 154 additions & 0 deletions src/main/clojure/conexp/fca/fuzzy/fca.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
;; Copyright ⓒ the conexp-clj developers; all rights reserved.
;; The use and distribution terms for this software are covered by the
;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
;; which can be found in the file LICENSE at the root of this distribution.
;; By using this software in any fashion, you are agreeing to be bound by
;; the terms of this license.
;; You must not remove this notice, or any other, from this software.

(ns conexp.fca.fuzzy.fca
"Basic definitions for Fuzzy FCA"
(:use conexp.base
conexp.fca.contexts
conexp.fca.many-valued-contexts
[conexp.fca.fuzzy sets]))


(deftype Fuzzy-Context [objects attributes incidence]
Object
(equals [this other]
(generic-equals [this other] Fuzzy-Context [objects attributes incidence]))
(hashCode [this]
(hash-combine-hash Fuzzy-Context objects attributes incidence))

conexp.fca.contexts/Context
(objects [this] objects)
(attributes [this] attributes)
(incidence [this] incidence))

(defn mv->fuzzy-context-nc
"Converts a many-valued-context to a fuzzy context, without checking."
[mv-ctx]
(Fuzzy-Context. (objects mv-ctx) (attributes mv-ctx) (make-fuzzy-set (incidence mv-ctx)))
)

(defmethod print-method Fuzzy-Context
[ctx out]
(.write ^java.io.Writer out
^String (mv-context-to-string (make-mv-context (objects ctx)
(attributes ctx)
(fn [a b] ((incidence ctx) [a b])))))
)

(defmulti make-fuzzy-context
"Creates a fuzzy context from the given attributes. A fuzzy context
is nothing else than a Many-Valued Context with real entries between
0 and 1."
{:arglists '([objects attributes incidence])}
(fn [& args]
(vec (map clojure-type args))))

(defmethod make-fuzzy-context [clojure-coll clojure-coll clojure-fn]
[objects attributes truth-function]
(let [mv-ctx (make-mv-context (set objects)
(set attributes)
truth-function)]
(when-not (forall [v (vals (incidence mv-ctx))] (and (number? v) (<= 0 v 1)))
(illegal-argument "Given function does not return real values between 0 and 1."))
(mv->fuzzy-context-nc mv-ctx)))

(defmethod make-fuzzy-context [clojure-coll clojure-coll clojure-coll]
[objects attributes values]
(let [mv-ctx (make-mv-context-from-matrix objects attributes values)]
(when-not (forall [v (vals (incidence mv-ctx))] (and (number? v) (<= 0 v 1)))
(illegal-argument "Given value table does not contain of real values between 0 and 1."))
(mv->fuzzy-context-nc mv-ctx)))

(defn make-fuzzy-context-from-matrix
"Creates a fuzzy context from the given (number of) objects, (number
of) attributes and the value table, which must contain only real
values between 0 and 1."
[objects attributes values]
(make-fuzzy-context objects attributes values))

(defn- fuzzy-operators [norm]
"Returns fuzzy operations based on the supplied norm, that are required for more complex fuzzy operations."
(let [t-norm (first norm)
residuum (second norm)
f-and #(t-norm %1 (residuum %1 %2))
f-or #(f-and (residuum (residuum %1 %2) %2)
(residuum (residuum %2 %1) %1))
f-neg #(residuum % 0)]
[t-norm residuum f-and f-or f-neg])
)

(defn fuzzy-object-derivation
"Accepts a fuzzy context and a fuzzy set of objects.
Computes the fuzzy object derivation of the supplied objects in the supplied fuzzy context."
([fctx fobjs norm]
(fuzzy-object-derivation fctx fobjs norm identity))

([fctx fobjs norm hedge]
(let [[t-norm residuum f-and f-or f-neg] (fuzzy-operators norm)
inz (incidence fctx)]
(make-fuzzy-set (into {} (for [attr (attributes fctx)]
[attr
(reduce f-and 1 (for [obj (keys fobjs)] (residuum (hedge (fobjs obj)) (inz [obj attr]))))])))))
)

(defn fuzzy-attribute-derivation
"Accepts a fuzzy context and a fuzzy set of attributes.
Computes the fuzzy object derivation of the supplied attributes in the supplied fuzzy context."
([fctx fattrs norm]
(fuzzy-attribute-derivation fctx fattrs norm identity))

([fctx fattrs norm hedge]
(let [[t-norm residuum f-and f-or f-neg] (fuzzy-operators norm)
inz (incidence fctx)]
(make-fuzzy-set (into {} (for [obj (attributes fctx)]
[obj
(reduce f-and 1 (for [attr (keys fattrs)] (residuum (hedge (fattrs attr)) (inz [obj attr]))))])))))
)

(defn globalization-hedge [x]
"Globalization hedge function."
(if (= x 1) 1 0)
)

(defn fuzzy-subset-degree
"Returns the degree to which fset1 is a subset of fset2. Applies hedge to the truth
value of an element being in fset1, if given."
([fset1 fset2 norm]
(fuzzy-subset-degree fset1 fset2 norm identity))

([fset1 fset2 norm hedge]
(let [[t-norm residuum f-and f-or f-neg] (fuzzy-operators norm)]
(reduce #(f-and %1 (residuum (hedge (fset1 %2))
(fset2 %2)))
1
(keys fset1))))
)

(defn validity
"Returns the degree to which the implication *fset1* ==> *fset2* is true in the
supplied fuzzy context. *fset1* and *fset2* are fuzzy subsets of the attributes of
the supplied fuzzy context."
([fctx fset1 fset2 norm]
(validity fctx fset1 fset2 norm identity))
([fctx fset1 fset2 norm hedge]
(fuzzy-subset-degree (make-fuzzy-set fset2)
(fuzzy-object-derivation fctx
(fuzzy-attribute-derivation fctx (make-fuzzy-set fset1) norm)
norm
hedge)
norm)))

;Pairs of t-norms and residuum
(def lukasiewicz-norm [#(max 0 (+ %1 %2 -1))
#(min 1 (+ 1 (- %1) %2))])

(def goedel-norm [#(min %1 %2)
#(if (<= %1 %2) 1 %2)])

(def product-norm [#(* %1 %2)
#(if (<= %1 %2) 1 (/ %2 %1))])
Loading

0 comments on commit 64c8b1e

Please sign in to comment.