Skip to content

Latest commit

 

History

History
147 lines (116 loc) · 3.3 KB

How-to-compute-the-Canonical-Base-from-a-Context-given-in-CSV-Format.org

File metadata and controls

147 lines (116 loc) · 3.3 KB

Computing the Canonical Base from a Formal Context in CSV Format

Suppose that you have given a formal context in a file called test.csv that is specified in CSV like so:

cat test.csv

(the space before the A is not important). The task you want to solve is to compute the canonical base of this formal context in conexp-clj.

Now, conexp-clj does not support this input format for formal contexts directly (maybe it should?), but it is very easy to get the job done using many-valued contexts as an intermediate step. For this we first read the context as many-value context and define mv-ctx to be the result, like so

(def mv-ctx (read-mv-context "doc/tutorials/test.csv"))

Then mv-ctx looks like this

mv-ctx
  |A B C D 
--+--------
1 |1 0 0 1 
2 |1 0 1 1 
3 |1 0 1 1 
4 |1 0 0 0 

Looks almost like a formal context, doesn’t it? The only thing that has to be done now is to turn the 1s into crosses, and the 0s into non-crosses. For this recall that the incidence relation of mv-ctx is a hash-map that maps pairs of objects and attributes from mv-ctx to their corresponding values. In other words,

(incidence mv-ctx)
{[2 D] 1,
 [4 A] 1,
 [3 B] 0,
 [3 A] 1,
 [4 D] 0,
 [1 D] 1,
 [4 C] 0,
 [2 C] 1,
 [3 C] 1,
 [2 A] 1,
 [1 A] 1,
 [3 D] 1,
 [4 B] 0,
 [1 C] 0,
 [2 B] 0,
 [1 B] 0}

Thus, to convert mv-ctx into a formal context we make a cross at [g m] (where g is an object, and m an attribute from mv-ctx) whenever the value of this pair in (incidence mv-ctx) is one. This can be done like so

(def ctx (make-context (objects mv-ctx)
                       (attributes mv-ctx)
                       (fn [g m]
                         (= 1 ((incidence mv-ctx) [g m])))))

Let’s check whether this worked as expected

ctx
  |A B C D 
--+--------
1 |x . . x 
2 |x . x x 
3 |x . x x 
4 |x . . . 

Great! So to get the canonical base of ctx you just call canonical-base on ctx and you are done.

(canonical-base ctx)
((#{} ⟶ #{A}) (#{A C} ⟶ #{D}) (#{A B} ⟶ #{D C}))

In case you only want to compute the implications of the canonical base which have positive support, you can either filter out those implications which have support 0

(filter #(pos? (support % ctx))
        (canonical-base ctx))
((#{} ⟶ #{A}) (#{A C} ⟶ #{D}))

or you can instruct canonical-base to not even compute implications with support 0, by using the optional third argument of canonical-base, which is a predicate on the premises of the implications which should be computed:

(canonical-base ctx #{} #(pos? (support % ctx)))
((#{} ⟶ #{A}) (#{A C} ⟶ #{D}))