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}