Skip to content

Releases

0.6.0

Choose a tag to compare

@anuragxorma anuragxorma released this 30 Oct 13:28

ConceptFlow 0.6.0 adds tools for comparing views of a data set and for judging how well a lattice is drawn. Existing code keeps working unchanged.

New

Scale-measures

conceptflow.core now builds and checks scale-measures (Hanika & Hirth, 2022): coarser views of a formal context on the same objects.

  • scale_measure(context, attributes) builds one from original attributes and their conjunctions (("a", "b") becomes "a ∧ b"), in a fixed, reproducible column order.
  • is_scale_measure and scale_measure_problems check any view, attribute by attribute.
  • refines(coarse, fine) tells whether every concept of one view is a concept of the other (a refinement pair).

Order indices

conceptflow.metrics adds lattice_width (largest antichain), lattice_height (longest chain), incomparable_pairs and concept_levels. They work on iceberg lattices too.

Drawing quality metrics

14 scores in [0, 1] for line diagrams, in four families: crossings, layering, slopes and clearance. drawing_quality_scores computes all of them at once, with optional worst cases. They take a laid-out GraphData or a networkx.DiGraph. Layouts such as DimFlux's are scored upright, as they are drawn.

Contributed by marcelnoehre (#2). On all 635 drawings of a study of eight layout algorithms, they reproduce the original implementation's scores to within 1e-9.

Layout positions

conceptflow.visualization.layout_positions(graph_data) returns where each concept is drawn, keyed by its extent. Drawings of two related lattices can then be compared concept by concept.

Documentation

Two new guide pages: Scale-measures and order indices and Drawing quality.

Reliability

  • Built packages tested in CI: the wheel and the source archive are each installed into a clean environment and smoke-tested outside the repository.
  • More CI coverage: CI also runs on Python 3.13. On the oldest supported scikit-learn, everything except the estimator checks now runs.
  • New tests:
    • independent reference implementations for the new functions;
    • workflow tests that run whole chains on contexts too large for exhaustive checks.
  • README: the first example now runs after a plain pip install, without LaTeX.

Install

pip install --upgrade conceptflow

Full list of changes: changelog · compare with v0.5.0

ConceptFlow 0.5.0: now beta

Choose a tag to compare

@anuragxorma anuragxorma released this 30 Oct 09:49

ConceptFlow is now beta. For this release every part of the package was checked against brute force or the definitions in the literature, and the bugs found were fixed. Most of them were in the visualization, which is now also tested in a real browser in CI.

Changes that affect existing code

  • Ord2Factor now uses method="annealing" by default. The previous default, "exact", is exponential: about 20 seconds for a 15 × 15 context and hours a little beyond, without a warning. Annealing gave the same results on small contexts and takes seconds on larger ones. "exact" is still available and now stops after max_time seconds (default 60) with a TimeoutError.
  • Ord2Factor's greedy and annealing results change. They are now inclusion-minimal, as the paper states (no dropped cross could be kept). Greedy drops noticeably fewer crosses: 3 instead of 10 on triangles_en.
  • Some layout coordinates change. Line diagrams no longer draw an edge straight through a concept it does not connect.
  • conceptflow.model_selection was removed. It was an empty, undocumented placeholder.
  • Deprecated: debug_filled_pairs and debug_bottom_outer (removal in 0.6.0); use conceptflow.exploration.realized_pairs.

Visualization

  • Interactive line diagrams use reduced labelling (attributes above, objects below) instead of each concept's full intent.
  • Nodes and nested bubbles no longer overlap on larger lattices, and every node can be clicked.
  • Several interactive figures in one Jupyter notebook all draw; each is shown in its own frame.
  • Nested diagrams show attribute names exactly as given (color!=red was shown as red), and clicking the preview dots inside a bubble opens it.
  • "Save PDF" in nested diagrams writes a vector PDF of a few KB instead of a 6.9 MB image.
  • LaTeX in names is shown as symbols (\sqrt{3} → √3, \alpha → α) and typeset properly in TikZ.
  • Narrow pages work, D3 is pinned to an exact version, and invalid plotting options raise clear errors.
  • The visualization guide has a new Known limitations section.

Other fixes

  • make_random_context accepts NumPy Generators, as documented.
  • write_cxt, write_json and write_csv create missing folders.
  • Clearer errors for misused index arguments and for wrong scales in ExplorationBuilder.
  • A hand-built GraphData of an iceberg lattice no longer labels objects at the wrong concept.

Testing

  • Oracle tests: about 480 tests compare the mathematical core with independent references written from the definitions. This covers concepts, the canonical, proper-premise and Luxenburger bases, stability, incomplete contexts, GreConD and ASSO as in their papers, optimal ordinal factorization, nested diagrams and ordinal scales.
  • Browser tests: the interactive pages are tested in headless Firefox.
  • More CI platforms: CI now also runs on macOS and Windows.

Install

pip install --upgrade conceptflow

Full list of changes: changelog · compare with v0.4.0

0.4.0

Choose a tag to compare

@anuragxorma anuragxorma released this 28 Oct 15:17

New algorithms, a datasets module, large speed-ups and benchmarks against fcapy and concepts. Documentation: https://conceptflow.readthedocs.io

New

  • Boolean matrix factorization: GreConD and ASSO as scikit-learn transformers (like NMF).
  • Ord2Factor: large ordinal two-factorizations of any context (Dürrschnabel & Stumme 2023), with an exact SAT method and greedy/annealing heuristics.
  • conceptflow.datasets: the 20 contexts of the FCA repository bundled, fetch_fca_repository, the UCI Mushroom data and random contexts.
  • ConceptualScaler(handle_unknown="ignore") for values unseen during fit, e.g. in cross-validation.
  • Benchmarks against fcapy and concepts, an API stability and deprecation policy, CITATION.cff, CONTRIBUTING.md and continuous integration.

Faster (same results)

  • Canonical basis with LinCbO: UCI Mushroom 134 s → 17 s; 40–85× faster with many attributes.
  • Concept enumeration with FCbO pruning: Mushroom 26 s → 14 s.
  • Exact stability, now per concept: all of Mushroom in about 40 s; also works on iceberg lattices.
  • Conceptual scaling: Mushroom 49 s → 0.1 s.

Changed

  • Concept ids and feature names are derived from the intent: stable across reordered or resampled data, but different from earlier versions.
  • NominalScale(0) means the first column (as in ColumnTransformer).
  • inf in DataFrames is rejected.
  • Python 3.14 is supported.

Full list in the CHANGELOG.

pip install --upgrade conceptflow

0.3.1

Choose a tag to compare

@anuragxorma anuragxorma released this 27 Oct 13:02

Bug fixes found in an audit of 0.3.0: broken HTML pages with special characters in names, two-concept lattices drawn as one point, wrong labels on iceberg drawings, NominalScale failing when a column's type changes, a hang in ExactOrdinalTwoFactorizer, and contexts that could be modified after creation. Full list in the CHANGELOG

0.3.0

Choose a tag to compare

@anuragxorma anuragxorma released this 27 Oct 10:25

ew features: lattice navigation, concept measures, iceberg lattices, TikZ/Graphviz export, context operations, data-quality tools and an outlier detector. Documentation is now at https://conceptflow.readthedocs.io.

Added

  • Documentation site with a user guide, API reference and changelog; every guide example is run by the test suite.
  • Lattice navigation: join, meet, upset, downset, atoms, coatoms, object_concept, attribute_concept, concept_from_objects, concept_from_attributes.
  • Iceberg lattices: min_support= computes only frequent concepts.
  • Size guard: a LargeLatticeWarning past 50,000 concepts, and an opt-in max_concepts= limit.
  • Concept measures: stability (exact and bounds), Δ-measure, entropy, information gain, linearity and distributivity indices; ConceptLatticeEstimator(select=..., n_concepts=...).
  • Minimal generators and the proper-premise basis.
  • Context handling: transpose, subcontext, rename, add/remove objects and attributes, full reduction, JSON (FCART/fcapy) and CSV files.
  • Context operations: apposition, subposition, direct sum and product, complement, dual; nested diagrams of any two contexts.
  • Layouts and export: layered layout, TikZ/LaTeX and Graphviz export.
  • Data quality: check_implications, redundancy_report, explain_object, explain_rule.
  • ImplicationOutlierDetector: a scikit-learn outlier detector that explains each flag with the rules it breaks.

Changed

  • Cell values follow one rule per cell: numbers > 0 are crosses; strings must be a known spelling ("yes"/"no" now raise instead of being guessed).
  • Out-of-range object/attribute indices raise IndexError.
  • Estimators fitted on named columns refuse different or reordered columns, as scikit-learn's do.

Full details: CHANGELOG

pip install --upgrade conceptflow

v0.2.0

Choose a tag to compare

@anuragxorma anuragxorma released this 23 Oct 12:42

Install with pip install conceptflow==0.2.0 (requires Python 3.12+).

Breaking changes

  • Python 3.12 or newer is required. The layout engine is now the
    dim-flux package from PyPI, which
    needs Python 3.12. The bundled copy of DimFlux, its Java jar and the Java
    requirement are gone; sympy and z3-solver are no longer direct
    dependencies.
  • Missing values are no longer silently converted.
    • FormalContext (constructor, from_dataframe, from_array) reads
      empty cells (None, NaN, pd.NA) as "no cross", like a printed cross
      table. Previously NaN became a cross (bool(NaN) is True) while None
      became a non-cross. The marker "?" (unknown) raises; use
      IncompleteContext for unknown entries.
    • The scikit-learn estimators still reject NaN, as scikit-learn requires;
      convert with FormalContext.from_dataframe for the cross-table reading.
    • ConceptualScaler raises by default (missing="error"). Previously NaN
      became its own category (color=nan) in nominal scales and "below every
      threshold" in threshold scales. To keep going, pass missing="false"
      (none of the scale's attributes) or missing="unknown" (see below), or
      fill missing values yourself before scaling.
    • The string "?" counts as missing (unknown) in ConceptualScaler and
      IncompleteContext.
  • plot_lattice(..., title=...) defaults to None; the d3 backend still
    shows "Concept lattice" when no title is given.
  • Index handling is stricter: Concept accepts only integer indices (NumPy
    integers are converted; floats and NumPy booleans raise), and True/False
    are no longer accepted as attribute or object indices in derivations.
  • FormalContext copies the incidence array it is given, so changing the
    original array afterwards no longer changes the context.
  • compute_luxenburger_basis(concepts=...) rejects concepts with indices
    outside the context and ignores duplicates.

Added

  • compute_luxenburger_basis: near-implications (confidence < 1) with
    support, confidence and exception objects, as AssociationRule objects.
  • conceptflow.metrics.implication_exceptions: the objects violating a rule.
  • IncompleteContext: yes / no / unknown contexts with certain/possible
    derivations, completions, and implication_status ("valid", "possible",
    "refuted" over all completions).
  • ConceptualScaler(missing=...) with "error", "false" and "unknown";
    ExplorationBuilder(missing=...) with "error" and "false".
  • Static figures: plot_lattice(..., backend="matplotlib") and
    plot_nested(..., backend="matplotlib") return matplotlib figures for
    SVG/PDF/PNG export. With layout="none" large lattices render in
    well under a second.
  • nested_combinations(view) and realized_pairs(...): the realized and
    unrealized (outer, inner) concept pairs of a nested diagram as data.
  • timeout_ms for DimFlux layouts in plot_lattice, plot_nested and
    lattice_to_graph_data_dimflux; a warning for lattices above 150 concepts.
  • compute_canonical_basis_bruteforce: the definition-based reference
    implementation, kept for testing.

Fixed

  • compute_canonical_basis uses NextClosure instead of trying every
    attribute subset: a 240 x 30 context went from not finishing to 0.04 s.
  • ConceptLattice.edges, parents() and children() are computed once and
    cached; previously every parents()/children() call recomputed all
    edges. compute_hasse_edges itself is also much faster when given the
    context.
  • Concepts holding NumPy integer indices no longer produce wrong Hasse edges.
  • Nested diagrams compute filled nodes with a direct test per pair, which is
    much faster on large diagrams (same result).

Performance

Measured on a laptop; "before" is 0.1.1 or the first fixed version where
0.1.1 did not finish.

Operation Context Before Now
Canonical basis 357 x 42 (1,376 implications) 3.9 s 0.22 s
Canonical basis random 100 x 24, dense (8,423) ~150 s 0.95 s
Canonical basis random 60 x 80 (3,432) 23 s 2.1 s
Concept enumeration, Close-by-One random 300 x 40 (55,392 concepts) 3.3 s 0.8 s
Concept enumeration, NextClosure random 300 x 40 3.0 s 1.3 s
ConceptLatticeEstimator.fit_transform random 300 x 40 22 s 2.3 s
ImplicationBasisEstimator.transform random 300 x 40 17 s 0.09 s
Luxenburger basis, confidence >= 0.8, support >= 5 random 300 x 40 2.7 s 0.43 s
  • The canonical basis closes candidate sets under the implications found so
    far with vectorised NumPy passes (packed 64-bit words up to 64 attributes,
    a matrix-vector product beyond), and stops a closure as soon as it fails
    NextClosure's canonicity test. Pure-Python LinClosure was benchmarked as
    well and was slower here.
  • NextClosure and Close-by-One run on integer bitsets.
  • The transformers compute concept/premise membership for all objects with
    one matrix product instead of per-pair set tests.
  • The Luxenburger basis only enumerates concepts that reach the support
    threshold and reads their lower neighbours off the attribute extents.

Compatibility notes

  • ConceptualScaler objects pickled with 0.1.x still load and behave like
    missing="error".
  • import conceptflow no longer imports the layout engine; it is loaded on
    first use.