src/main/java/org/thegalactic/context/Context.java
public Lattice subDirectDecomposition() {
        // First, compute 1-generated arrow-closed subcontextes
        ArrayList<Context> parts = new ArrayList<Context>();
        for (Comparable o : this.getObservations()) {
            TreeSet<Comparable> setO = new TreeSet<Comparable>();
            setO.add(o);
            parts.add(this.arrowClosureObject(setO));
        }
        // Second, remove contexts contained in other. They are dispendable.
        // Remove first all contexts that appeared at least twice.
        ArrayList<Context> single = new ArrayList<Context>();
        for (int i = 0; i < parts.size(); i++) {
            boolean containedNext = false;
            for (int j = i + 1; j < parts.size(); j++) {
                containedNext = containedNext || (parts.get(i).containsAllObservations(parts.get(j).getObservations())
                        && parts.get(j).containsAllObservations(parts.get(i).getObservations())
                        && parts.get(i).containsAllAttributes(parts.get(j).getAttributes())
                        && parts.get(j).containsAllAttributes(parts.get(i).getAttributes()));
            }
            if (!containedNext) {
                single.add(parts.get(i));
            }
        }
        parts = single;
        ArrayList<Context> toBeRemoved = new ArrayList<Context>();
        for (Context remove : parts) {
            for (Context test : parts) {
                if ((parts.indexOf(test) != parts.indexOf(remove))
                        && (test.containsAllObservations(remove.getObservations()))
                        && (test.containsAllAttributes(remove.getAttributes()))) {
                    toBeRemoved.add(remove);
                }
            }
        }
        parts.removeAll(toBeRemoved);
        // Third, compute the product but can't use LatticeFactory.product :-(
        /*
         * Content of each node is of the following form :
         * 1. They are Couple
         * 2. Left part is an ArrayList corresponding to the terms of the product
         * 3. Right part is a boolean, true if the node is inside the sub-product.
         * Thus we have : the full product, and nodes of the subproduct marked
         */
        // First compute all nodes of the product
        LinkedList<ConceptLattice> clParts = new LinkedList<ConceptLattice>();
        for (Context ctx : parts) {
            clParts.add(ctx.conceptLattice(true));
        }
        Lattice prod = new Lattice();
        // Computes nodes
        ArrayList<Couple> nodes = new ArrayList<Couple>();
        LinkedList<ConceptLattice> copy = (LinkedList<ConceptLattice>) clParts.clone();
        ConceptLattice firstCL = (ConceptLattice) copy.poll();
        for (Object node : firstCL.getNodes()) {
            Couple couple = new Couple(new ArrayList<Concept>(), false);
            ArrayList<Concept> prodCPT = new ArrayList<Concept>();
            prodCPT.add((Concept) node);
            couple.setLeft(prodCPT);
            nodes.addAll(recursiveGenProd(couple, copy));
        }
        for (Couple c : nodes) {
            prod.addNode(new Node(c));
        }
        // Add edges
        for (Object source : prod.getNodes()) {
            for (Object target : prod.getNodes()) {
                Couple contentSource = (Couple) ((Node) source).getContent();
                Couple contentTarget = (Couple) ((Node) target).getContent();
                boolean haveEdge = true;
                boolean equals = true;
                for (int i = 0; i < clParts.size(); i++) { // clParts.size() is the number of factor
                    Concept cptSource = ((ArrayList<Concept>) contentSource.getLeft()).get(i);
                    Concept cptTarget = ((ArrayList<Concept>) contentTarget.getLeft()).get(i);
                    equals = equals && cptSource.equals(cptTarget);
                    haveEdge = haveEdge && (clParts.get(i).containsEdge(cptSource, cptTarget) || cptSource.equals(cptTarget));
                }
                if (haveEdge && !equals) {
                    prod.addEdge(((Node) source), ((Node) target));
                }
            }
        }
        prod.transitiveReduction();
        // Last, identify the sub-product, e.g. nodes of this component in the product.
        // In the subdirect decomposition, if (A,B) is a concept then (A \cap H,B \cap N) also.
        // Transform nodes of the original lattice into nodes of the subproduct lattice and mark them
        ConceptLattice cl = this.conceptLattice(true);
        for (Object cpt : cl.getNodes()) {
            // Compute cpt representation in prod
            ArrayList<Concept> subCpt = new ArrayList<Concept>();
            for (int i = 0; i < parts.size(); i++) {
                Context ctx = parts.get(i);
                ConceptLattice term = clParts.get(i);
                ComparableSet setA = new ComparableSet();
                setA.addAll(((Concept) cpt).getSetA());
                ComparableSet setB = new ComparableSet();
                setB.addAll(((Concept) cpt).getSetB());
                setA.retainAll(ctx.getAttributes());
                setB.retainAll(ctx.getObservations());
                subCpt.add(term.getConcept((ComparableSet) setA, (ComparableSet) setB));
            }
            // Check if cpt is in prod
            for (Object nodeProd : prod.getNodes()) {
                if (((Couple) ((Node) nodeProd).getContent()).getLeft().equals(subCpt)) {
                    ((Couple) ((Node) nodeProd).getContent()).setRight(true);
                }
            }
        }
        return prod;
    }
/**
     * Returns the concept lattice of this component represented as a subdirect
     * product of its irreductibles components.
     *
     * WARNING : Context MUST BE REDUCED !
     *
     * @return concept Lattice of this component represented as a subdirect
     *         product of its irreductibles components.
     */
Returns the concept lattice of this component represented as a subdirect
product of its irreductibles components.

WARNING : Context MUST BE REDUCED !

@return concept Lattice of this component represented as a subdirect
product of its irreductibles components.
Returns the concept lattice of this component represented as a subdirect product of its irreductibles components . WARNING : Context MUST BE REDUCED ! @return concept Lattice of this component represented as a subdirect product of its irreductibles components .
public Lattice subDirectDecomposition() {
        ArrayList<Context> parts = new ArrayList<Context>();
        for (Comparable o : this.getObservations()) {
            TreeSet<Comparable> setO = new TreeSet<Comparable>();
            setO.add(o);
            parts.add(this.arrowClosureObject(setO));
        }
        ArrayList<Context> single = new ArrayList<Context>();
        for (int i = 0; i < parts.size(); i++) {
            boolean containedNext = false;
            for (int j = i + 1; j < parts.size(); j++) {
                containedNext = containedNext || (parts.get(i).containsAllObservations(parts.get(j).getObservations())
                        && parts.get(j).containsAllObservations(parts.get(i).getObservations())
                        && parts.get(i).containsAllAttributes(parts.get(j).getAttributes())
                        && parts.get(j).containsAllAttributes(parts.get(i).getAttributes()));
            }
            if (!containedNext) {
                single.add(parts.get(i));
            }
        }
        parts = single;
        ArrayList<Context> toBeRemoved = new ArrayList<Context>();
        for (Context remove : parts) {
            for (Context test : parts) {
                if ((parts.indexOf(test) != parts.indexOf(remove))
                        && (test.containsAllObservations(remove.getObservations()))
                        && (test.containsAllAttributes(remove.getAttributes()))) {
                    toBeRemoved.add(remove);
                }
            }
        }
        parts.removeAll(toBeRemoved);
        /*
         * Content of each node is of the following form :
         * 1. They are Couple
         * 2. Left part is an ArrayList corresponding to the terms of the product
         * 3. Right part is a boolean, true if the node is inside the sub-product.
         * Thus we have : the full product, and nodes of the subproduct marked
         */
        LinkedList<ConceptLattice> clParts = new LinkedList<ConceptLattice>();
        for (Context ctx : parts) {
            clParts.add(ctx.conceptLattice(true));
        }
        Lattice prod = new Lattice();
        ArrayList<Couple> nodes = new ArrayList<Couple>();
        LinkedList<ConceptLattice> copy = (LinkedList<ConceptLattice>) clParts.clone();
        ConceptLattice firstCL = (ConceptLattice) copy.poll();
        for (Object node : firstCL.getNodes()) {
            Couple couple = new Couple(new ArrayList<Concept>(), false);
            ArrayList<Concept> prodCPT = new ArrayList<Concept>();
            prodCPT.add((Concept) node);
            couple.setLeft(prodCPT);
            nodes.addAll(recursiveGenProd(couple, copy));
        }
        for (Couple c : nodes) {
            prod.addNode(new Node(c));
        }
        for (Object source : prod.getNodes()) {
            for (Object target : prod.getNodes()) {
                Couple contentSource = (Couple) ((Node) source).getContent();
                Couple contentTarget = (Couple) ((Node) target).getContent();
                boolean haveEdge = true;
                boolean equals = true;
                for (int i = 0; i < clParts.size(); i++) { 
                    Concept cptSource = ((ArrayList<Concept>) contentSource.getLeft()).get(i);
                    Concept cptTarget = ((ArrayList<Concept>) contentTarget.getLeft()).get(i);
                    equals = equals && cptSource.equals(cptTarget);
                    haveEdge = haveEdge && (clParts.get(i).containsEdge(cptSource, cptTarget) || cptSource.equals(cptTarget));
                }
                if (haveEdge && !equals) {
                    prod.addEdge(((Node) source), ((Node) target));
                }
            }
        }
        prod.transitiveReduction();
        ConceptLattice cl = this.conceptLattice(true);
        for (Object cpt : cl.getNodes()) {
            ArrayList<Concept> subCpt = new ArrayList<Concept>();
            for (int i = 0; i < parts.size(); i++) {
                Context ctx = parts.get(i);
                ConceptLattice term = clParts.get(i);
                ComparableSet setA = new ComparableSet();
                setA.addAll(((Concept) cpt).getSetA());
                ComparableSet setB = new ComparableSet();
                setB.addAll(((Concept) cpt).getSetB());
                setA.retainAll(ctx.getAttributes());
                setB.retainAll(ctx.getObservations());
                subCpt.add(term.getConcept((ComparableSet) setA, (ComparableSet) setB));
            }
            for (Object nodeProd : prod.getNodes()) {
                if (((Couple) ((Node) nodeProd).getContent()).getLeft().equals(subCpt)) {
                    ((Couple) ((Node) nodeProd).getContent()).setRight(true);
                }
            }
        }
        return prod;
    }
public Lattice subDirectDecomposition ( ) { ArrayList < Context > parts = new ArrayList < Context > ( ) ; for ( Comparable o : this . getObservations ( ) ) { TreeSet < Comparable > setO = new TreeSet < Comparable > ( ) ; setO . add ( o ) ; parts . add ( this . arrowClosureObject ( setO ) ) ; } ArrayList < Context > single = new ArrayList < Context > ( ) ; for ( int i = 0 ; i < parts . size ( ) ; i ++ ) { boolean containedNext = false ; for ( int j = i + 1 ; j < parts . size ( ) ; j ++ ) { containedNext = containedNext || ( parts . get ( i ) . containsAllObservations ( parts . get ( j ) . getObservations ( ) ) && parts . get ( j ) . containsAllObservations ( parts . get ( i ) . getObservations ( ) ) && parts . get ( i ) . containsAllAttributes ( parts . get ( j ) . getAttributes ( ) ) && parts . get ( j ) . containsAllAttributes ( parts . get ( i ) . getAttributes ( ) ) ) ; } if ( ! containedNext ) { single . add ( parts . get ( i ) ) ; } } parts = single ; ArrayList < Context > toBeRemoved = new ArrayList < Context > ( ) ; for ( Context remove : parts ) { for ( Context test : parts ) { if ( ( parts . indexOf ( test ) != parts . indexOf ( remove ) ) && ( test . containsAllObservations ( remove . getObservations ( ) ) ) && ( test . containsAllAttributes ( remove . getAttributes ( ) ) ) ) { toBeRemoved . add ( remove ) ; } } } parts . removeAll ( toBeRemoved ) ; /*
         * Content of each node is of the following form :
         * 1. They are Couple
         * 2. Left part is an ArrayList corresponding to the terms of the product
         * 3. Right part is a boolean, true if the node is inside the sub-product.
         * Thus we have : the full product, and nodes of the subproduct marked
         */ LinkedList < ConceptLattice > clParts = new LinkedList < ConceptLattice > ( ) ; for ( Context ctx : parts ) { clParts . add ( ctx . conceptLattice ( true ) ) ; } Lattice prod = new Lattice ( ) ; ArrayList < Couple > nodes = new ArrayList < Couple > ( ) ; LinkedList < ConceptLattice > copy = ( LinkedList < ConceptLattice > ) clParts . clone ( ) ; ConceptLattice firstCL = ( ConceptLattice ) copy . poll ( ) ; for ( Object node : firstCL . getNodes ( ) ) { Couple couple = new Couple ( new ArrayList < Concept > ( ) , false ) ; ArrayList < Concept > prodCPT = new ArrayList < Concept > ( ) ; prodCPT . add ( ( Concept ) node ) ; couple . setLeft ( prodCPT ) ; nodes . addAll ( recursiveGenProd ( couple , copy ) ) ; } for ( Couple c : nodes ) { prod . addNode ( new Node ( c ) ) ; } for ( Object source : prod . getNodes ( ) ) { for ( Object target : prod . getNodes ( ) ) { Couple contentSource = ( Couple ) ( ( Node ) source ) . getContent ( ) ; Couple contentTarget = ( Couple ) ( ( Node ) target ) . getContent ( ) ; boolean haveEdge = true ; boolean equals = true ; for ( int i = 0 ; i < clParts . size ( ) ; i ++ ) { Concept cptSource = ( ( ArrayList < Concept > ) contentSource . getLeft ( ) ) . get ( i ) ; Concept cptTarget = ( ( ArrayList < Concept > ) contentTarget . getLeft ( ) ) . get ( i ) ; equals = equals && cptSource . equals ( cptTarget ) ; haveEdge = haveEdge && ( clParts . get ( i ) . containsEdge ( cptSource , cptTarget ) || cptSource . equals ( cptTarget ) ) ; } if ( haveEdge && ! equals ) { prod . addEdge ( ( ( Node ) source ) , ( ( Node ) target ) ) ; } } } prod . transitiveReduction ( ) ; ConceptLattice cl = this . conceptLattice ( true ) ; for ( Object cpt : cl . getNodes ( ) ) { ArrayList < Concept > subCpt = new ArrayList < Concept > ( ) ; for ( int i = 0 ; i < parts . size ( ) ; i ++ ) { Context ctx = parts . get ( i ) ; ConceptLattice term = clParts . get ( i ) ; ComparableSet setA = new ComparableSet ( ) ; setA . addAll ( ( ( Concept ) cpt ) . getSetA ( ) ) ; ComparableSet setB = new ComparableSet ( ) ; setB . addAll ( ( ( Concept ) cpt ) . getSetB ( ) ) ; setA . retainAll ( ctx . getAttributes ( ) ) ; setB . retainAll ( ctx . getObservations ( ) ) ; subCpt . add ( term . getConcept ( ( ComparableSet ) setA , ( ComparableSet ) setB ) ) ; } for ( Object nodeProd : prod . getNodes ( ) ) { if ( ( ( Couple ) ( ( Node ) nodeProd ) . getContent ( ) ) . getLeft ( ) . equals ( subCpt ) ) { ( ( Couple ) ( ( Node ) nodeProd ) . getContent ( ) ) . setRight ( true ) ; } } } return prod ; }
Returns the concept lattice of this component represented as a subdirect
 product of its irreductibles components.
Returns the concept lattice of this component represented as a subdirect product of its irreductibles components .
// First, compute 1-generated arrow-closed subcontextes // Second, remove contexts contained in other. They are dispendable. // Remove first all contexts that appeared at least twice. // Third, compute the product but can't use LatticeFactory.product :-( // First compute all nodes of the product // Computes nodes // Add edges // clParts.size() is the number of factor // Last, identify the sub-product, e.g. nodes of this component in the product. // In the subdirect decomposition, if (A,B) is a concept then (A \cap H,B \cap N) also. // Transform nodes of the original lattice into nodes of the subproduct lattice and mark them // Compute cpt representation in prod // Check if cpt is in prod