001package conexp.fx.core.dl.deprecated;
002
003/*
004 * #%L
005 * Concept Explorer FX
006 * %%
007 * Copyright (C) 2010 - 2019 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.Collection;
026import java.util.HashSet;
027import java.util.Map;
028import java.util.Map.Entry;
029import java.util.Set;
030import java.util.concurrent.ConcurrentHashMap;
031import java.util.concurrent.LinkedBlockingQueue;
032import java.util.concurrent.ThreadPoolExecutor;
033import java.util.concurrent.TimeUnit;
034import java.util.stream.Collectors;
035import java.util.stream.Stream;
036
037import org.semanticweb.owlapi.model.IRI;
038
039import com.google.common.collect.HashMultimap;
040import com.google.common.collect.Multimap;
041
042import conexp.fx.core.algorithm.nextclosures.NextClosures2;
043import conexp.fx.core.collections.Pair;
044import conexp.fx.core.collections.setlist.HashSetArrayList;
045import conexp.fx.core.collections.setlist.SetList;
046import conexp.fx.core.context.Context;
047import conexp.fx.core.context.Implication;
048import conexp.fx.core.context.SparseContext;
049import conexp.fx.core.dl.Signature;
050import conexp.fx.core.math.SetClosureOperator;
051
052@Deprecated
053public abstract class AInterpretation<C, G, T> implements Interpretation<IRI, C, G, T> {
054
055  protected final Set<IRI>                      domain;
056  protected final Signature                     signature;
057
058  protected final Multimap<IRI, IRI>            conceptNameExtensions;
059  protected final Multimap<IRI, Pair<IRI, IRI>> roleNameExtensions;
060
061  public AInterpretation(final IRI baseIRI) {
062    this(new Signature(baseIRI), new HashSet<IRI>());
063  }
064
065  public AInterpretation(final Signature signature) {
066    this(signature, signature.getIndividualNames());
067  }
068
069  public AInterpretation(final Signature signature, final Set<IRI> domain) {
070    super();
071    this.domain = domain;
072    this.signature = signature;
073    this.conceptNameExtensions = HashMultimap.create();
074    this.roleNameExtensions = HashMultimap.create();
075  }
076
077  @Override
078  public Set<IRI> getDomain() {
079    return domain;
080  }
081
082  @Override
083  public Signature getSignature() {
084    return signature;
085  }
086
087  @Override
088  public boolean addConceptNameAssertion(final IRI conceptName, final IRI individual) {
089    return conceptNameExtensions.put(conceptName, individual);
090  }
091
092  public boolean addConceptNameAssertion(final String conceptName, final String individual) {
093    return addConceptNameAssertion(IRI.create(conceptName), IRI.create(individual));
094  }
095
096  @Override
097  public boolean addRoleNameAssertion(final IRI roleName, final IRI individual1, final IRI individual2) {
098    return roleNameExtensions.put(roleName, new Pair<IRI, IRI>(individual1, individual2));
099  }
100
101  public boolean addRoleNameAssertion(final String roleName, final String individual1, final String individual2) {
102    return addRoleNameAssertion(IRI.create(roleName), IRI.create(individual1), IRI.create(individual2));
103  }
104
105  @Override
106  public Collection<IRI> getConceptNameExtension(final IRI conceptName) {
107    return conceptNameExtensions.get(conceptName);
108  }
109
110  @Override
111  public Collection<Pair<IRI, IRI>> getRoleNameExtension(final IRI roleName) {
112    return roleNameExtensions.get(roleName);
113  }
114
115  @Override
116  public Set<IRI> getRoleSuccessors(final IRI roleName, final IRI individual) {
117    return getRoleSuccessorStream(roleName, individual).collect(Collectors.toSet());
118  }
119
120  @Override
121  public Set<IRI> getRolePredecessors(final IRI roleName, final IRI individual) {
122    return getRolePredecessorStream(roleName, individual).collect(Collectors.toSet());
123  }
124
125  private final Map<C, Set<IRI>> cache = new ConcurrentHashMap<>();
126
127  @Override
128  public Set<IRI> getConceptExpressionExtension(C conceptExpression) {
129    if (cache.containsKey(conceptExpression))
130      return cache.get(conceptExpression);
131    final Set<IRI> extent = getDomain()
132        .parallelStream()
133        .filter(individual -> isInstanceOf(individual, conceptExpression))
134        .collect(Collectors.toSet());
135    cache.put(conceptExpression, extent);
136    return extent;
137  }
138
139  @Override
140  public boolean subsumes(final C subsumer, final C subsumee) {
141    return getConceptExpressionExtension(subsumer).containsAll(getConceptExpressionExtension(subsumee));
142  }
143
144  @Override
145  public boolean isSubsumedBy(final C subsumee, final C subsumer) {
146    return getConceptExpressionExtension(subsumer).containsAll(getConceptExpressionExtension(subsumee));
147  }
148
149  @Override
150  public Set<C>
151      getAllMostSpecificConcepts(final int roleDepth, final int maxCardinality, final Constructor... constructors) {
152//    final Set<C> mmscs = new HashSet<C>();
153//    final Iterator<Set<IRI>> it = NextClosure
154//        .enumerate(new HashSetArrayList<IRI>(domain), getClosureOperator(roleDepth, maxCardinality, constructors))
155//        .iterator();
156//    it.forEachRemaining(extension -> {
157//      final C mmsc = getMostSpecificConcept(extension, roleDepth, maxCardinality, constructors);
158//      System.out.println(mmsc);
159//      mmscs.add(mmsc);
160//    });
161//    return mmscs;
162//    final Set<C> singletonMMSCs = domain
163//        .parallelStream()
164//        .map(individuals -> getMostSpecificConcept(individuals, roleDepth, maxCardinality, constructors))
165//        .collect(Collectors.toSet());
166//    System.out.println(singletonMMSCs.size() + " singleton mmscs");
167//    return singletonMMSCs;
168    final Set<Set<IRI>> extents = NextClosures2.compute(
169        domain,
170        getClosureOperator(roleDepth, maxCardinality, constructors),
171        true,
172        new ThreadPoolExecutor(24, 24, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<>()));
173    System.out.println(extents.size() + " mmscs");
174    return extents
175        .parallelStream()
176        .filter(ex -> !ex.isEmpty())
177        .map(extent -> getMostSpecificConcept(extent, roleDepth, maxCardinality, constructors))
178        .collect(Collectors.toSet());
179  }
180
181  protected abstract SetList<C> getAttributeSetForInducedContext(
182      final int roleDepth,
183      final int maxCardinality,
184      final Constructor... constructors);
185
186  @Override
187  public Context<IRI, C> getInducedContext(
188      final Collection<IRI> individuals,
189      final int roleDepth,
190      final int maxCardinality,
191      final Constructor... constructors) {
192    checkRoleDepth(roleDepth);
193    final SetList<IRI> _domain = new HashSetArrayList<IRI>(domain);
194    final SetList<C> _codomain = getAttributeSetForInducedContext(roleDepth, maxCardinality, constructors);
195    final Context<IRI, C> inducedContext = new SparseContext<IRI, C>(_domain, _codomain, false);
196    for (C mmsc : _codomain)
197      for (IRI individual : getConceptExpressionExtension(mmsc))
198        inducedContext.add(individual, mmsc);
199    return inducedContext;
200  }
201
202  protected abstract Set<Implication<IRI, C>>
203      getBackgroundImplications(final Context<IRI, C> inducedContext, final T backgroundTBox);
204
205  @Override
206  public final SetClosureOperator<IRI>
207      getClosureOperator(final int roleDepth, final int maxCardinality, final Constructor... constructors) {
208    return set -> getConceptExpressionExtension(getMostSpecificConcept(set, roleDepth, maxCardinality, constructors));
209  }
210
211  protected final Multimap<IRI, IRI>            conceptNamesPerIndividual = HashMultimap.create();
212  protected final Multimap<IRI, Pair<IRI, IRI>> roleSuccessors            = HashMultimap.create();
213
214  public Multimap<IRI, IRI> getConceptNameExtensions() {
215    return conceptNameExtensions;
216  }
217
218  public Multimap<IRI, Pair<IRI, IRI>> getRoleNameExtensions() {
219    return roleNameExtensions;
220  }
221
222  protected Stream<IRI> getRoleSuccessorStream(final IRI roleName, final IRI individual) {
223    return getRoleNameExtension(roleName).parallelStream().filter(p -> p.x().equals(individual)).map(p -> p.y());
224  }
225
226  protected Stream<IRI> getRolePredecessorStream(final IRI roleName, final IRI individual) {
227    return getRoleNameExtension(roleName).parallelStream().filter(p -> p.y().equals(individual)).map(p -> p.x());
228  }
229
230  /**
231   * This method must be called prior to the computation of most specific concepts.
232   */
233  public final void updateSuccessorSets() {
234    conceptNamesPerIndividual.clear();
235    roleSuccessors.clear();
236    for (Entry<IRI, IRI> entry : conceptNameExtensions.entries())
237      conceptNamesPerIndividual.put(entry.getValue(), entry.getKey());
238    for (Entry<IRI, Pair<IRI, IRI>> entry : roleNameExtensions.entries())
239      roleSuccessors.put(entry.getValue().x(), Pair.of(entry.getKey(), entry.getValue().y()));
240  }
241
242  @Override
243  @SuppressWarnings("unchecked")
244  public boolean equals(final Object obj) {
245    if (!(obj instanceof Interpretation))
246      return false;
247    @SuppressWarnings("rawtypes")
248    final Interpretation other = (Interpretation) obj;
249    return this.getDomain().equals(other.getDomain()) && this.getSignature().equals(other.getSignature())
250        && getSignature().getConceptNames().parallelStream().allMatch(
251            conceptName -> this.getConceptNameExtension(conceptName).equals(other.getConceptNameExtension(conceptName)))
252        && getSignature().getRoleNames().parallelStream().allMatch(
253            roleName -> this.getRoleNameExtension(roleName).equals(other.getRoleNameExtension(roleName)));
254  }
255
256  @Override
257  public int hashCode() {
258    return 7 + 11 * getDomain().hashCode() + 13 * getSignature().hashCode();
259  }
260
261  @Override
262  public String toString() {
263    final StringBuilder sb = new StringBuilder();
264    sb.append("Interpretation\r\n");
265    sb.append("with domain:\r\n" + getDomain().toString() + "\r\n");
266    sb.append("on signature:\r\n" + getSignature().toString() + "\r\n");
267    sb.append("with primitive extensions:\r\n");
268    for (IRI conceptName : signature.getConceptNames())
269      sb.append(conceptName + " :: " + getConceptNameExtension(conceptName).toString() + "\r\n");
270    for (IRI roleName : signature.getRoleNames())
271      sb.append(roleName + " :: " + getRoleNameExtension(roleName).toString() + "\r\n");
272    return sb.toString();
273  }
274
275}