001package conexp.fx.core.algorithm.nextclosures;
002
003/*-
004 * #%L
005 * Concept Explorer FX
006 * %%
007 * Copyright (C) 2010 - 2023 Francesco Kriegel
008 * %%
009 * This program is free software: you can redistribute it and/or modify
010 * it under the terms of the GNU General Public License as
011 * published by the Free Software Foundation, either version 3 of the
012 * License, or (at your option) any later version.
013 * 
014 * This program is distributed in the hope that it will be useful,
015 * but WITHOUT ANY WARRANTY; without even the implied warranty of
016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
017 * GNU General Public License for more details.
018 * 
019 * You should have received a copy of the GNU General Public
020 * License along with this program.  If not, see
021 * <http://www.gnu.org/licenses/gpl-3.0.html>.
022 * #L%
023 */
024
025import java.util.Collections;
026import java.util.ConcurrentModificationException;
027import java.util.HashSet;
028import java.util.Map;
029import java.util.Set;
030import java.util.concurrent.ConcurrentHashMap;
031import java.util.function.Function;
032import java.util.stream.Collectors;
033
034import com.google.common.collect.Sets;
035
036import conexp.fx.core.collections.BitSetFX;
037import conexp.fx.core.collections.Collections3;
038import conexp.fx.core.collections.Pair;
039import conexp.fx.core.context.Concept;
040import conexp.fx.core.context.Implication;
041
042public final class NextClosuresState<G, M, C extends Set<M>> {
043
044  public static final <G, M> NextClosuresState<G, M, Set<M>> withHashSets(final Set<M> domain) {
045    return new NextClosuresState<>(domain, HashSet<M>::new);
046  }
047
048  public static final NextClosuresState<Integer, Integer, BitSetFX> withBitSets(final int max) {
049    return new NextClosuresState<>(Collections3.integers(max), BitSetFX::new);
050  }
051
052  public final Set<Concept<G, M>>     concepts     = Collections3.newConcurrentHashSet();
053  public final Set<Implication<G, M>> implications = Collections3.newConcurrentHashSet();
054  public final Map<C, Integer>        candidates   = new ConcurrentHashMap<>();
055  private final Set<C>                processed    = Collections3.newConcurrentHashSet();
056  public int                          cardinality  = 0;
057
058  private final Set<M>                domain;
059  private final Function<Set<M>, C>   supplier;
060
061  private NextClosuresState(final Set<M> domain, final Function<Set<M>, C> supplier) {
062    this.domain = domain;
063    this.supplier = supplier;
064    candidates.put(supplier.apply(Collections.emptySet()), 0);
065  }
066
067  /*
068   * (non-Javadoc)
069   * 
070   * @see conexp.fx.core.algorithm.nextclosures.INextClosuresState#getActualCandidateStream()
071   */
072
073  public final Set<C> getActualCandidates() {
074//    return new HashSet<>(Sets.filter(candidates.keySet(), c -> c.size() == cardinality));
075    return candidates.keySet().parallelStream().filter(c -> c.size() == cardinality).collect(Collectors.toSet());
076  }
077
078  /*
079   * (non-Javadoc)
080   * 
081   * @see conexp.fx.core.algorithm.nextclosures.INextClosuresState#getFirstPremiseSize(C)
082   */
083
084  public final int getFirstPremiseSize(final C candidate) {
085    return candidates.get(candidate);
086  }
087
088  /*
089   * (non-Javadoc)
090   * 
091   * @see conexp.fx.core.algorithm.nextclosures.INextClosuresState#isNewIntent(C)
092   */
093
094  public final boolean isNewIntent(final C s) {
095    try {
096      return processed.add(s);
097    } catch (ConcurrentModificationException e) {
098      return isNewIntent(s);
099    }
100  }
101
102  /*
103   * (non-Javadoc)
104   * 
105   * @see conexp.fx.core.algorithm.nextclosures.INextClosuresState#addNewCandidates(C)
106   */
107
108  public final void addNewCandidates(final C intent) {
109    for (M m : Sets.difference(domain, intent)) {
110      final C candidateM = supplier.apply(intent);
111      candidateM.add(m);
112      candidates.put(candidateM, 0);
113    }
114  }
115
116  /*
117   * (non-Javadoc)
118   * 
119   * @see conexp.fx.core.algorithm.nextclosures.INextClosuresState#addCandidate(C)
120   */
121
122  public final void addCandidate(final C candidate) {
123    candidates.put(candidate, cardinality);
124
125  }
126
127  /*
128   * (non-Javadoc)
129   * 
130   * @see conexp.fx.core.algorithm.nextclosures.INextClosuresState#getResultAndDispose()
131   */
132
133  public final Pair<Set<Concept<G, M>>, Set<Implication<G, M>>> getResultAndDispose() {
134    candidates.clear();
135    processed.clear();
136    return Pair.of(concepts, implications);
137  }
138
139  public int getActualCardinality() {
140    return cardinality;
141  }
142
143  public void increaseCardinality() {
144    cardinality++;
145  }
146
147}