Skip to content

Commit 29adc48

Browse files
authored
Merge pull request #173 from tomhanika/dev
Preparing next release
2 parents f233457 + ddca6a0 commit 29adc48

50 files changed

Lines changed: 20161 additions & 19 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,15 @@ much more.
3333
8. [Computing Traces in Contexts](doc/code/trace-context.clj)
3434
9. [Counting Quasiorders](doc/code/quasiorders.clj)
3535
10. [Rudolph's Algorithm for Computing Bases](doc/code/rudolph_computation.clj)
36-
11. [Discovering Causal Implications](doc/Causal-Implications.org)
36+
11. [Libkin Decompositions](doc/LibkinDecomposition.org)
37+
12. [Direct Product Decompositions](doc/DirectProductDecompositions.org)
3738
5. Advanced Topics
3839
1. [pq-cores](doc/pq-cores-in-Formal-Contexts.md)
3940
2. [REST-API Usage](doc/REST-API-usage.md)
4041
3. [triadic-exploration](doc/Triadic-Exploration.org)
4142
4. [protoconcepts](doc/Protoconcepts.org)
4243
5. [Incomplete Contexts](doc/IncompleteContexts.org)
44+
6. [Factorization of Formal Contexts](doc/MatrixFactorization.org)
4345
6. [API documentation](doc/API.md)
4446
7. [Development](doc/Development.org)
4547

deps-lock.json

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,14 @@
8888
"hash": "sha256-ZIsMIEuk8EDcQ8KfguRHHstmdWCK+wuzGp7BxCYTenQ="
8989
},
9090
{
91-
"mvn-path": "com/clojure-goes-fast/clj-async-profiler/1.2.2/clj-async-profiler-1.2.2.jar",
91+
"mvn-path": "com/clojure-goes-fast/clj-async-profiler/1.6.1/clj-async-profiler-1.6.1.jar",
9292
"mvn-repo": "https://repo.clojars.org/",
93-
"hash": "sha256-qMHpvYHP4c43Kge18EoI7cQeHCMzEcTE7Ua6R7nWWkM="
93+
"hash": "sha256-gXYVy1wAiS21b++Ja4TpU3PS60wuSgMdXK2kTK+5czY="
9494
},
9595
{
96-
"mvn-path": "com/clojure-goes-fast/clj-async-profiler/1.2.2/clj-async-profiler-1.2.2.pom",
96+
"mvn-path": "com/clojure-goes-fast/clj-async-profiler/1.6.1/clj-async-profiler-1.6.1.pom",
9797
"mvn-repo": "https://repo.clojars.org/",
98-
"hash": "sha256-fnjS0rxK05hQ2e4p1bvLA1EVrLrz5YfA4+FpfydAGa8="
98+
"hash": "sha256-yh1bsw48eRDn/RVnNiU9/iywhpxmLmf/V5d7pEcfomA="
9999
},
100100
{
101101
"mvn-path": "com/damnhandy/handy-uri-templates/2.1.8/handy-uri-templates-2.1.8.jar",
@@ -307,6 +307,36 @@
307307
"mvn-repo": "https://repo1.maven.org/maven2/",
308308
"hash": "sha256-VxY5EUJ+1pVuXJId/eH3UKok0b4Z+UBqkwPvGdyAMAU="
309309
},
310+
{
311+
"mvn-path": "com/taoensso/encore/3.142.0/encore-3.142.0.jar",
312+
"mvn-repo": "https://repo.clojars.org/",
313+
"hash": "sha256-la5XSlLY4+zAjr7+RybSwzDQgPDK2/vvaxUMS4Iat9A="
314+
},
315+
{
316+
"mvn-path": "com/taoensso/encore/3.142.0/encore-3.142.0.pom",
317+
"mvn-repo": "https://repo.clojars.org/",
318+
"hash": "sha256-UzH7wyrXUGPdsOwRK3nFJJYAmWvbvWJ8fTH82RSBlxc="
319+
},
320+
{
321+
"mvn-path": "com/taoensso/truss/2.0.5/truss-2.0.5.jar",
322+
"mvn-repo": "https://repo.clojars.org/",
323+
"hash": "sha256-+Fm3m0yhvHBIaoenX/LKBduWAEuUfBW9+9ZqTDdUba4="
324+
},
325+
{
326+
"mvn-path": "com/taoensso/truss/2.0.5/truss-2.0.5.pom",
327+
"mvn-repo": "https://repo.clojars.org/",
328+
"hash": "sha256-b7vRktsuIrZ/vzfbRQFaIaMzNPZhrzBGDFncr1Hyacg="
329+
},
330+
{
331+
"mvn-path": "com/taoensso/tufte/2.7.0/tufte-2.7.0.jar",
332+
"mvn-repo": "https://repo.clojars.org/",
333+
"hash": "sha256-ERCvSiQ8WfQhKP0ethKOHdNYKzvYrij04p2RsD/oMxI="
334+
},
335+
{
336+
"mvn-path": "com/taoensso/tufte/2.7.0/tufte-2.7.0.pom",
337+
"mvn-repo": "https://repo.clojars.org/",
338+
"hash": "sha256-c7hD8o46IHiSwYNnpPMpRtr7EW49xbcKoZ2C7dbzcRQ="
339+
},
310340
{
311341
"mvn-path": "commons-codec/commons-codec/1.10/commons-codec-1.10.pom",
312342
"mvn-repo": "https://repo1.maven.org/maven2/",
@@ -1437,6 +1467,11 @@
14371467
"mvn-repo": "https://repo1.maven.org/maven2/",
14381468
"hash": "sha256-rvXugot8sUocWPRbn4oQ/zQMV2mSXqDvXDXR5J2SC+o="
14391469
},
1470+
{
1471+
"mvn-path": "org/clojure/tools.reader/1.5.2/tools.reader-1.5.2.pom",
1472+
"mvn-repo": "https://repo1.maven.org/maven2/",
1473+
"hash": "sha256-uZlvXJtX4jSGPzlfzmT5fTBQtPWFMKYhWllpsILSFOc="
1474+
},
14401475
{
14411476
"mvn-path": "org/json/json/20240303/json-20240303.jar",
14421477
"mvn-repo": "https://repo1.maven.org/maven2/",

doc/Concept-Lattices.org

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,24 @@ Other interesting functions are ~draw-layout~, which implements the drawing of
175175
layouts, and ~draw-concept-lattice~, which draws the concept-lattice of a given
176176
formal context. With ~draw-poset~ and ~draw-protoconcepts~, Ordered Sets and
177177
Protoconcepts can be drawn as well.
178+
179+
Concept lattices can also be exported to and edited in [[https://app.diagrams.net/][draw.io]]:
180+
181+
#+begin_src clojure :results silent
182+
(use 'conexp.fca.contexts)
183+
(use 'conexp.fca.lattices)
184+
(use 'conexp.layouts.dim-draw)
185+
186+
(def ctx (read-context "testing-data/Forum-Romanum.ctx"))
187+
(def lat (concept-lattice ctx))
188+
(def l (dim-draw-layout lat))
189+
190+
(write-layout :xml l "Forum-Romanum.xml")
191+
#+end_src
192+
193+
The ~write-layout~ method recives the drawing layout of a lattice and a file path as arguments, and saves the layout as a file.
194+
The XML format is compatible with ~draw.io~ and can be dragged and dropped directly into the editor:
195+
196+
[[./images/drawio.png]]
197+
198+
The nodes and labels can now directly be edited on the website.
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#+property: header-args :wrap src text
2+
#+property: header-args:text :eval never
3+
4+
* Direct Product Decompositions
5+
6+
Based on the ~Libkin Decomposition~ formalized by Leonid Libkin, a variety of approaches for decomposing concept lattices were proposed, some of which are implemented in ~conexp-clj~.
7+
8+
For a detailed description of these methods, consult [[https://doi.org/10.17170/kobra-2025021510916][Direct Product Decompositions of Concept Lattices]]:
9+
10+
#+begin_src clojure
11+
(use 'conexp.fca.decompositions)
12+
(def ctx (make-context #{"black" "red" "green" "blue" "yellow" "violet" "cyan" "white"}#{"R" "G" "B"} #{["red" "R"] ["green" "G"] ["blue" "B"] ["yellow" "R"] ["yellow" "G"] ["violet" "R"] ["violet" "B"] ["cyan" "G"] ["cyan" "B"] ["white" "R"] ["white" "G"] ["white" "B"]}))
13+
(def lat (concept-lattice ctx))
14+
(draw-lattice lat)
15+
#+end_src
16+
17+
18+
[[./images/rgb-lattice.png]]
19+
20+
21+
The decomposition pairs of a lattice can be computed using the method ~libkin-decomposition-pairs~:
22+
23+
#+begin_src clojure :exports both
24+
(def pairs (libkin-decomposition-pairs lat))
25+
#+end_src
26+
27+
#+RESULTS:
28+
#+begin_src text
29+
([[#{"cyan" "white"} #{"G" "B"}]
30+
[#{"white" "violet" "yellow" "red"} #{"R"}]]
31+
[[#{"white" "violet" "yellow" "red"} #{"R"}]
32+
[#{"cyan" "white"} #{"G" "B"}]]
33+
[[#{"white" "violet"} #{"R" "B"}]
34+
[#{"cyan" "white" "yellow" "green"} #{"G"}]]
35+
[[#{"blue" "cyan" "white" "violet" "yellow" "green" "red" "black"}
36+
#{}]
37+
[#{"white"} #{"G" "R" "B"}]]
38+
[[#{"white" "yellow"} #{"G" "R"}]
39+
[#{"blue" "cyan" "white" "violet"} #{"B"}]]
40+
[[#{"white"} #{"G" "R" "B"}]
41+
[#{"blue" "cyan" "white" "violet" "yellow" "green" "red" "black"}
42+
#{}]]
43+
[[#{"cyan" "white" "yellow" "green"} #{"G"}]
44+
[#{"white" "violet"} #{"R" "B"}]]
45+
[[#{"blue" "cyan" "white" "violet"} #{"B"}]
46+
[#{"white" "yellow"} #{"G" "R"}]])
47+
#+end_src
48+
49+
These can now be used to compute either a ~downset decomposition~, which is equivalent to the libkin decomposition, or a ~downset decomposition~.
50+
We will compute one each using the decomposition pari ~[[#{"cyan" "white"} #{"G" "B"}] [#{"white" "violet" "yellow" "red"} #{"R"}]]~:
51+
52+
#+begin_src clojure :exports both
53+
(def downsets (downset-decomposition-lattices lat [[#{"cyan" "white"} #{"G" "B"}] [#{"white" "violet" "yellow" "red"} #{"R"}]]))
54+
(draw-lattice (first downsets))
55+
(draw-lattice (second downsets))
56+
#+end_src
57+
58+
[[./images/downset-lattices.png]]
59+
60+
61+
#+begin_src clojure :exports both
62+
(def upsets (upset-decomposition-lattices lat [[#{"cyan" "white"} #{"G" "B"}] [#{"white" "violet" "yellow" "red"} #{"R"}]]))
63+
(draw-lattice (first upsets))
64+
(draw-lattice (second upsets))
65+
#+end_src
66+
67+
[[./images/upset-lattices.png]]
68+
69+
These pairs of lattices can now be reconstructed into their original lattices by applying the ~downset product~ or ~uzpset product~, respectively:
70+
71+
#+begin_src clojure :exports both
72+
(downset-product (first downsets) (second downsets))
73+
(upset-product (first upsets) (second upsets))
74+
#+end_src
75+
76+
Whether a lattice has non-trivial decomposition pairs may be verified using the ~decomposable?~ method.
77+
78+
79+
It may be useful to visualize all possible upset decomposition of a single concept lattice.
80+
To this end, the ~direct decomposition lattice~ of a concept lattice may be computed:
81+
82+
[[./images/decomp-lattice.png]]
83+
84+
#+begin_src clojure :exports both
85+
(def decomp-lat (direct-decomposition-lattice lat))
86+
(draw-lattice decomp-lat)
87+
#+end_src
88+
89+
It is unfortunately not currently possible to directly visualize the concept lattices that form the elements of the ~direct decomposition lattice~:
90+
91+
[[./images/decomp-lattice-drawing.png]]
92+
93+
This lattice can also be computed in terms of the contexts of its constituent lattices using the ~ctx-decomposition-lattice~ method.
94+
95+
This ~direct decomposition lattice~ can slo be used to determine the ~upset prime factorization~ of a concept lattice; a set of indecomposable concept lattices whose upset product is the original concept lattice:
96+
97+
#+begin_src clojure :exports both
98+
(def factors (prime-factorization lat))
99+
(draw-lattice (first factors))
100+
(draw-lattice (second factors))
101+
(draw-lattice (last factors))
102+
#+end_src
103+
104+
[[./images/prime-factors.png]]
105+
106+
107+
In practice, non-trivial direct product decomposition are rare. Therefore it is useful to consider substructures of concept lattices that may be decomposable.
108+
~conexp-clj~ offers two variants of such an algorithm.
109+
110+
The method ~maximally-decomposable-filters~ returns all inclusion-maximal principal filters of a concept lattice, that have non-trivial upset decompostions.
111+
112+
An example using the ~bodies-of-water~ context:
113+
114+
[[./images/max-decomp-filters.png]]
115+
116+
Alternatively, all maximally decomposable intervals may be computed using the ~maximally-decomposable-intervals~ method:
117+
118+
[[./images/max-decomp-intervals.png]]
119+
120+
#+begin_src clojure :exports both
121+
(maximally-decomposable-filters lat)
122+
(maximally-decomposable-intervals lat)
123+
#+end_src

doc/LibkinDecomposition.org

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#+property: header-args :wrap src text
2+
#+property: header-args:text :eval never
3+
4+
* Libkin Decomposition
5+
6+
~conexp-clj~ allows for the computation of Libkin Decompositions of lattices.
7+
For an explanation of the concept consult "Direct product decompositions of lattices, closures and relation schemes" by Leonid Libkin
8+
9+
Some of the following functions require the ~decompositions~ namespace:
10+
11+
12+
#+begin_src clojure
13+
(use 'conexp.fca.decompositions)
14+
#+end_src
15+
16+
(use 'conexp.fca.decompositions)
17+
18+
We will consider the following lattice as an example:
19+
20+
#+begin_src clojure :exports both
21+
(def ctx (read-context "testing-data/drive_concepts_for_motorcars.cxt"))
22+
(def lat (concept-lattice ctx))
23+
#+end_src
24+
25+
[[./images/car-lattice.png]]
26+
27+
A Libkin decomposition of a lattice L is a pair of sublattices of L, whose product is isomorphic to L.
28+
Libkin decompositions are each induced by a decomposition pair, a neutral element in L and its Complement.
29+
30+
All decomposition pairs of the lattice can be computed using the method ~libkin-decomposition-pairs~:
31+
32+
#+begin_src clojure :exports both
33+
(def pairs (libkin-decomposition-pairs lat))
34+
#+end_src
35+
36+
#+RESULTS:
37+
#+begin_src text
38+
([[#{"Conventional" "All-wheel" "Rear-wheel" "Mid-engine"} #{"Dl+"}]
39+
[#{"Front-wheel"}
40+
#{"E+" "C-l" "De+" "C-vl" "E++" "Dl-" "S-u" "R+" "M+" "R++"}]]
41+
[[#{}
42+
#{"E+" "C-l" "E-" "C-h" "De+" "Dl+" "C-vl" "E++" "S-u/n" "Dl++"
43+
"Dl-" "M++" "S-u" "R+" "S-n" "S-o" "De-" "De++" "M+" "M--" "R--"
44+
"C-m" "M-" "R++" "E--"}]
45+
[#{"Conventional" "All-wheel" "Rear-wheel" "Mid-engine"
46+
"Front-wheel"}
47+
#{}]]
48+
[[#{"Conventional" "All-wheel" "Rear-wheel" "Mid-engine"
49+
"Front-wheel"}
50+
#{}]
51+
[#{}
52+
#{"E+" "C-l" "E-" "C-h" "De+" "Dl+" "C-vl" "E++" "S-u/n" "Dl++"
53+
"Dl-" "M++" "S-u" "R+" "S-n" "S-o" "De-" "De++" "M+" "M--" "R--"
54+
"C-m" "M-" "R++" "E--"}]]
55+
[[#{"Front-wheel"}
56+
#{"E+" "C-l" "De+" "C-vl" "E++" "Dl-" "S-u" "R+" "M+" "R++"}]
57+
[#{"Conventional" "All-wheel" "Rear-wheel" "Mid-engine"} #{"Dl+"}]])
58+
#+end_src
59+
60+
Computing the order ideal of both entries of the pair yields the two sublattices forming the decomposition.
61+
62+
The lattices implied by the decomposition through a specific decomposition pair can be exlicitely generated using ~libkin-decomposition-lattices~:
63+
64+
#+begin_src clojure :exports both
65+
(def lattice-pair (libkin-decomposition-lattices lat [[#{"Conventional" "All-wheel" "Rear-wheel" "Mid-engine"} #{"Dl+"}]
66+
[#{"Front-wheel"}
67+
#{"E+" "C-l" "De+" "C-vl" "E++" "Dl-" "S-u" "R+" "M+" "R++"}]]))
68+
#+end_src
69+
70+
These lattices may be visualized as described in Concept-Lattices.org .
71+
72+
#+begin_src text
73+
(draw-lattice (first lattice-pair))
74+
(draw-lattice (last lattice-pair))
75+
#+end_src
76+
77+
[[./images/decomposed-lattice1.png]]
78+
[[./images/decomposed-lattice2.png]]
79+
80+
#+begin_src text
81+
(def prod-lat (lattice-product (first lattice-pair) (last lattice-pair)))
82+
(draw-lattice prod-lat)
83+
#+end_src
84+
85+
The product of these lattices yields a lattice isomorphic to L:
86+
87+
[[./images/prod-lattice.png]]

0 commit comments

Comments
 (0)