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.ArrayList;
026import java.util.Arrays;
027import java.util.Collections;
028import java.util.HashSet;
029import java.util.Iterator;
030import java.util.List;
031import java.util.Map;
032import java.util.Map.Entry;
033import java.util.Optional;
034import java.util.Set;
035import java.util.concurrent.ConcurrentHashMap;
036import java.util.function.BiPredicate;
037import java.util.stream.Collectors;
038import java.util.stream.Stream;
039
040import org.semanticweb.elk.util.collections.Triple;
041import org.semanticweb.owlapi.apibinding.OWLManager;
042import org.semanticweb.owlapi.model.AddAxiom;
043import org.semanticweb.owlapi.model.IRI;
044import org.semanticweb.owlapi.model.OWLClass;
045import org.semanticweb.owlapi.model.OWLClassExpression;
046import org.semanticweb.owlapi.model.OWLDataFactory;
047import org.semanticweb.owlapi.model.OWLObjectAllValuesFrom;
048import org.semanticweb.owlapi.model.OWLObjectComplementOf;
049import org.semanticweb.owlapi.model.OWLObjectExactCardinality;
050import org.semanticweb.owlapi.model.OWLObjectHasSelf;
051import org.semanticweb.owlapi.model.OWLObjectIntersectionOf;
052import org.semanticweb.owlapi.model.OWLObjectMaxCardinality;
053import org.semanticweb.owlapi.model.OWLObjectMinCardinality;
054import org.semanticweb.owlapi.model.OWLObjectProperty;
055import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
056import org.semanticweb.owlapi.model.OWLObjectSomeValuesFrom;
057import org.semanticweb.owlapi.model.OWLOntology;
058import org.semanticweb.owlapi.model.OWLOntologyCreationException;
059import org.semanticweb.owlapi.model.OWLOntologyManager;
060import org.semanticweb.owlapi.model.OWLSubClassOfAxiom;
061import org.semanticweb.owlapi.model.OWLSubPropertyChainOfAxiom;
062import org.semanticweb.owlapi.model.parameters.Imports;
063
064import com.google.common.collect.Collections2;
065import com.google.common.collect.Sets;
066
067import conexp.fx.core.algorithm.nextclosures.NextClosures1;
068import conexp.fx.core.algorithm.nextclosures.NextClosures1.Result;
069import conexp.fx.core.algorithm.nextclosures.NextClosures1C;
070import conexp.fx.core.algorithm.nextclosures.NextClosures1C.ResultC;
071import conexp.fx.core.collections.Pair;
072import conexp.fx.core.collections.setlist.HashSetArrayList;
073import conexp.fx.core.collections.setlist.SetList;
074import conexp.fx.core.context.Context;
075import conexp.fx.core.context.Implication;
076import conexp.fx.core.context.SparseContext;
077import conexp.fx.core.dl.ELConceptDescription;
078import conexp.fx.core.dl.ELLeastCommonSubsumer;
079import conexp.fx.core.dl.ELReasoner;
080import conexp.fx.core.dl.ELSyntaxException;
081import conexp.fx.core.dl.Signature;
082import conexp.fx.core.math.SetClosureOperator;
083import uk.ac.manchester.cs.owl.owlapi.OWLClassImpl;
084import uk.ac.manchester.cs.owl.owlapi.OWLObjectComplementOfImpl;
085import uk.ac.manchester.cs.owl.owlapi.OWLObjectIntersectionOfImpl;
086
087//import org.semanticweb.owlapi.model.parameters.Imports;
088
089@Deprecated
090public class OWLInterpretation extends AInterpretation<OWLClassExpression, OWLSubClassOfAxiom, OWLOntology> {
091
092  public OWLInterpretation(final IRI baseIRI) {
093    super(baseIRI);
094  }
095
096  public OWLInterpretation(final Signature signature) {
097    super(signature);
098  }
099
100  public OWLInterpretation(final Signature signature, final Set<IRI> domain) {
101    super(signature, domain);
102  }
103
104  public final OWLDataFactory df = OWLManager.getOWLDataFactory();
105
106  @Override
107  public final boolean isInstanceOf(final IRI individual, final OWLClassExpression conceptExpression) {
108    if (conceptExpression.isOWLNothing())
109      return false;
110    if (conceptExpression.isOWLThing())
111      return true;
112    if (conceptExpression instanceof OWLClass)
113      return getConceptNameExtension(((OWLClass) conceptExpression).getIRI()).contains(individual);
114    if (conceptExpression instanceof OWLObjectIntersectionOf)
115      return ((OWLObjectIntersectionOf) conceptExpression)
116          .asConjunctSet()
117          .parallelStream()
118          .allMatch(c -> isInstanceOf(individual, c));
119    if (conceptExpression instanceof OWLObjectSomeValuesFrom) {
120      final OWLObjectSomeValuesFrom existentialRestriction = (OWLObjectSomeValuesFrom) conceptExpression;
121      return getRoleSuccessorStream(((OWLObjectProperty) existentialRestriction.getProperty()).getIRI(), individual)
122          .anyMatch(succ -> isInstanceOf(succ, existentialRestriction.getFiller()));
123    }
124    if (conceptExpression instanceof OWLObjectAllValuesFrom) {
125      final OWLObjectAllValuesFrom valueRestriction = (OWLObjectAllValuesFrom) conceptExpression;
126      return getRoleSuccessorStream(((OWLObjectProperty) valueRestriction.getProperty()).getIRI(), individual)
127          .allMatch(succ -> isInstanceOf(succ, valueRestriction.getFiller()));
128    }
129    if (conceptExpression instanceof OWLObjectHasSelf) {
130      final OWLObjectHasSelf existentialSelfRestriction = (OWLObjectHasSelf) conceptExpression;
131      return getRoleNameExtension(((OWLObjectProperty) existentialSelfRestriction.getProperty()).getIRI())
132          .contains(Pair.of(individual, individual));
133    }
134    if (conceptExpression instanceof OWLObjectMinCardinality) {
135      final OWLObjectMinCardinality qualifiedNumberRestriction = (OWLObjectMinCardinality) conceptExpression;
136      return getRoleSuccessorStream(((OWLObjectProperty) qualifiedNumberRestriction.getProperty()).getIRI(), individual)
137          .filter(succ -> isInstanceOf(succ, qualifiedNumberRestriction.getFiller()))
138          .skip(qualifiedNumberRestriction.getCardinality() - 1)
139          .findAny()
140          .isPresent();
141    }
142    if (conceptExpression instanceof OWLObjectMaxCardinality) {
143      final OWLObjectMaxCardinality qualifiedNumberRestriction = (OWLObjectMaxCardinality) conceptExpression;
144      return !getRoleSuccessorStream(
145          ((OWLObjectProperty) qualifiedNumberRestriction.getProperty()).getIRI(),
146          individual)
147              .filter(succ -> isInstanceOf(succ, qualifiedNumberRestriction.getFiller()))
148              .skip(qualifiedNumberRestriction.getCardinality())
149              .findAny()
150              .isPresent();
151    }
152    if (conceptExpression instanceof OWLObjectExactCardinality) {
153      final OWLObjectExactCardinality qualifiedNumberRestriction = (OWLObjectExactCardinality) conceptExpression;
154      return getRoleSuccessorStream(((OWLObjectProperty) qualifiedNumberRestriction.getProperty()).getIRI(), individual)
155          .filter(succ -> isInstanceOf(succ, qualifiedNumberRestriction.getFiller()))
156          .skip(qualifiedNumberRestriction.getCardinality() - 1)
157          .findAny()
158          .isPresent()
159          && !getRoleSuccessorStream(
160              ((OWLObjectProperty) qualifiedNumberRestriction.getProperty()).getIRI(),
161              individual)
162                  .filter(succ -> isInstanceOf(succ, qualifiedNumberRestriction.getFiller()))
163                  .skip(qualifiedNumberRestriction.getCardinality())
164                  .findAny()
165                  .isPresent();
166    }
167    if (conceptExpression instanceof OWLObjectComplementOf) {
168      final OWLObjectComplementOf primitiveNegation = (OWLObjectComplementOf) conceptExpression;
169      if (primitiveNegation.isClassExpressionLiteral())
170        return !isInstanceOf(individual, (OWLClass) primitiveNegation.getOperand());
171    }
172    throw new ELSyntaxException();
173  }
174
175//  @Override
176//  public Set<IRI> getConceptExpressionExtension(final OWLClassExpression conceptExpression) {
177//    if (conceptExpression.isOWLNothing())
178//      return Collections.emptySet();
179//    if (conceptExpression.isOWLThing())
180//      return getDomain();
181//    if (conceptExpression instanceof OWLClass) {
182//      return Sets.newHashSet(getConceptNameExtension(((OWLClass) conceptExpression).getIRI()));
183//    }
184//    if (conceptExpression instanceof OWLObjectIntersectionOf) {
185//      final OWLObjectIntersectionOf conjunction = (OWLObjectIntersectionOf) conceptExpression;
186//      final Set<IRI> extension = new HashSet<IRI>();
187//      extension.addAll(getDomain());
188//      for (OWLClassExpression conjunct : conjunction.asConjunctSet()) {
189//        extension.retainAll(getConceptExpressionExtension(conjunct));
190//      }
191//      return extension;
192//    }
193//    if (conceptExpression instanceof OWLObjectSomeValuesFrom) {
194//      final OWLObjectSomeValuesFrom existentialRestriction = (OWLObjectSomeValuesFrom) conceptExpression;
195//      final Set<IRI> extension = new HashSet<IRI>();
196//      for (Pair<IRI, IRI> pair : getRoleNameExtension(((OWLObjectProperty) existentialRestriction.getProperty())
197//          .getIRI()))
198//        if (getConceptExpressionExtension(existentialRestriction.getFiller()).contains(pair.y()))
199//          extension.add(pair.x());
200//      return extension;
201//    }
202//    throw new ELSyntaxException();
203//  }
204
205  @Override
206  public final boolean satisfies(final OWLSubClassOfAxiom gci) {
207    return isSubsumedBy(gci.getSubClass(), gci.getSuperClass());
208  }
209
210  @Override
211  public final boolean models(final OWLOntology tBox) {
212    return tBox.getTBoxAxioms(Imports.INCLUDED)
213//        .getTBoxAxioms(true)
214        .parallelStream()
215        .allMatch(gci -> (gci instanceof OWLSubClassOfAxiom) ? satisfies((OWLSubClassOfAxiom) gci) : true);
216  }
217
218  public OWLClassExpression getMostSpecificConceptALQ(
219      final IRI individual,
220      final int roleDepth,
221      final int maxCardinality,
222      final Constructor... constructors) {
223    return getMostSpecificConceptALQ(Collections.singleton(individual), roleDepth, maxCardinality, constructors);
224  }
225
226  public OWLClassExpression getMostSpecificConceptALQ(
227      final Set<IRI> individuals,
228      final int roleDepth,
229      final int maxCardinality,
230      final Constructor... constructors) {
231    checkRoleDepth(roleDepth);
232    if (individuals.isEmpty())
233      return df.getOWLNothing();
234    final Set<OWLClassExpression> conjuncts = new HashSet<OWLClassExpression>();
235    for (IRI conceptName : conceptNameExtensions.keySet())
236      if (getConceptNameExtension(conceptName).containsAll(individuals))
237        conjuncts.add(new OWLClassImpl(conceptName));
238      else if (Arrays.asList(constructors).contains(Constructor.PRIMITIVE_NEGATION) && Collections2
239          .filter(getDomain(), d -> !getConceptNameExtension(conceptName).contains(d))
240          .containsAll(individuals))
241        conjuncts.add(new OWLObjectComplementOfImpl(new OWLClassImpl(conceptName)));
242    if (roleDepth > 0) {
243      for (IRI roleName : signature.getRoleNames()) {
244        final OWLObjectProperty property = df.getOWLObjectProperty(roleName);
245        if (Arrays.asList(constructors).contains(Constructor.EXISTENTIAL_SELF_RESTRICTION)) {
246          if (individuals
247              .parallelStream()
248              .allMatch(individual -> getRoleNameExtension(roleName).contains(Pair.of(individual, individual))))
249            conjuncts.add(df.getOWLObjectHasSelf(property));
250        }
251        if (Arrays.asList(constructors).contains(Constructor.EXISTENTIAL_RESTRICTION)) {
252          for (Set<IRI> successors : getSuccessorSetsER(individuals, roleName))
253            conjuncts
254                .add(
255                    df
256                        .getOWLObjectSomeValuesFrom(
257                            property,
258                            getMostSpecificConceptALQ(successors, roleDepth - 1, maxCardinality, constructors)));
259        }
260        if (Arrays.asList(constructors).contains(Constructor.VALUE_RESTRICTION)) {
261//        for (Set<IRI> successors : getSuccessorSetsVR(individuals, roleName))
262          conjuncts
263              .add(
264                  df
265                      .getOWLObjectAllValuesFrom(
266                          property,
267                          getMostSpecificConceptALQ(
268                              getAllSuccessors(individuals, roleName),
269                              roleDepth - 1,
270                              maxCardinality,
271                              constructors)));
272        }
273        if (Arrays.asList(constructors).contains(Constructor.UNQUALIFIED_AT_MOST_RESTRICTION)) {
274          for (int cardinality = 1; cardinality < maxCardinality; cardinality++)
275            for (Set<IRI> successors : getSuccessorSetsQLR(individuals, roleName, cardinality))
276              conjuncts
277                  .add(
278                      df
279                          .getOWLObjectMaxCardinality(
280                              cardinality,
281                              property,
282                              getMostSpecificConceptALQ(successors, roleDepth - 1, maxCardinality, constructors)));
283        }
284        if (Arrays.asList(constructors).contains(Constructor.QUALIFIED_AT_LEAST_RESTRICTION)) {
285          for (int cardinality = 2; cardinality < maxCardinality; cardinality++)
286            for (Set<IRI> successors : getSuccessorSetsQGR(individuals, roleName, cardinality))
287              conjuncts
288                  .add(
289                      df
290                          .getOWLObjectMinCardinality(
291                              cardinality,
292                              property,
293                              getMostSpecificConceptALQ(successors, roleDepth - 1, maxCardinality, constructors)));
294        }
295        // TODO
296      }
297    }
298    if (conjuncts.isEmpty())
299      return df.getOWLThing();
300    if (conjuncts.size() == 1)
301      return conjuncts.iterator().next();
302    return new OWLObjectIntersectionOfImpl(conjuncts);
303  }
304
305  protected final Set<IRI> getAllSuccessors(final Set<IRI> individuals, final IRI roleName) {
306    if (individuals.isEmpty())
307      return Collections.emptySet();
308    final Optional<Stream<IRI>> optional = individuals
309        .parallelStream()
310        .map(individual -> getRoleSuccessorStream(roleName, individual))
311        .reduce(Stream::concat);
312    if (optional.isPresent())
313      return optional.get().collect(Collectors.toSet());
314    System.out.println("optional is not present");
315    System.out.println(getRoleSuccessors(roleName, individuals.iterator().next()));
316    return Collections.emptySet();
317  }
318
319  protected final Set<Set<IRI>> getSuccessorSetsER(final Set<IRI> individuals, final IRI roleName) {
320    return filterMinimal(
321        Sets
322            .powerSet(getAllSuccessors(individuals, roleName))
323            .parallelStream()
324            .filter(
325                successors -> individuals
326                    .parallelStream()
327                    .allMatch(
328                        individual -> successors
329                            .parallelStream()
330                            .anyMatch(
331                                successor -> getRoleNameExtension(roleName).contains(Pair.of(individual, successor)))))
332            .collect(Collectors.toSet()));
333  }
334
335  protected final Set<Set<IRI>> getSuccessorSetsER2(final Set<IRI> individuals, final IRI roleName) {
336    // this method should not filter the powerset, which is a costly operation, but instead create the minimal
337    // successors directly
338    Set<Set<IRI>> successorSets = Collections.emptySet();
339    final Iterator<IRI> it = individuals.iterator();
340    if (it.hasNext()) {
341      successorSets = firstSuccessorSetsER(it.next(), roleName);
342    }
343    while (it.hasNext()) {
344      successorSets = extendSuccessorSetsER(successorSets, it.next(), roleName);
345    }
346    return filterMinimal(successorSets);
347  }
348
349  private final Set<Set<IRI>> firstSuccessorSetsER(final IRI individual, final IRI roleName) {
350    return getRoleSuccessorStream(roleName, individual)
351        .map(successor -> Sets.newHashSet(successor))
352        .collect(Collectors.toSet());
353  }
354
355  private final Set<Set<IRI>>
356      extendSuccessorSetsER(final Set<Set<IRI>> successorSets, final IRI individual, final IRI roleName) {
357    final Set<Set<IRI>> extendedSets = new HashSet<Set<IRI>>();
358    final Set<Set<IRI>> extendedSetsP = Collections.synchronizedSet(extendedSets);
359    successorSets.parallelStream().forEach(successorSet -> {
360      getRoleSuccessorStream(roleName, individual).forEach(successor -> {
361        final Set<IRI> extendedSet = new HashSet<IRI>();
362        extendedSet.addAll(successorSet);
363        extendedSet.add(successor);
364        extendedSetsP.add(extendedSet);
365      });
366    });
367    return extendedSets;
368  }
369
370  public static final <T> Set<Set<T>> filterMinimal(final Set<Set<T>> sets) {
371    return OWLMinimizer.filterMinimalParallel(sets, (set1, set2) -> set1.containsAll(set2));
372//    return sets.parallelStream().filter(
373//        set1 -> !sets.parallelStream().anyMatch(
374//            set2 -> !set1.equals(set2) && set1.containsAll(set2))).collect(
375//        Collectors.toSet());
376//    final Set<Set<T>> minSets = new HashSet<Set<T>>();
377//    for (Set<T> set1 : sets) {
378//      boolean isMinimal = true;
379//      for (Set<T> set2 : sets)
380//        if (!set1.equals(set2))
381//          if (set1.containsAll(set2)) {
382//            isMinimal = false;
383//            break;
384//          }
385//      if (isMinimal)
386//        minSets.add(set1);
387//    }
388//    return minSets;
389  }
390
391  private final Set<Set<IRI>>
392      getSuccessorSetsQGR(final Set<IRI> individuals, final IRI roleName, final int cardinality) {
393    return filterMinimal(
394        Sets
395            .powerSet(getAllSuccessors(individuals, roleName))
396            .parallelStream()
397            .filter(
398                successors -> individuals
399                    .parallelStream()
400                    .allMatch(
401                        individual -> successors
402                            .parallelStream()
403                            .filter(
404                                successor -> getRoleNameExtension(roleName).contains(Pair.of(individual, successor)))
405                            .skip(cardinality - 1)
406                            .findAny()
407                            .isPresent()))
408            .collect(Collectors.toSet()));
409  }
410
411  private final Set<Set<IRI>>
412      getSuccessorSetsQLR(final Set<IRI> individuals, final IRI roleName, final int cardinality) {
413    return filterMinimal(
414        Sets
415            .powerSet(getAllSuccessors(individuals, roleName))
416            .parallelStream()
417            .filter(
418                successors -> individuals
419                    .parallelStream()
420                    .allMatch(
421                        individual -> !successors
422                            .parallelStream()
423                            .filter(
424                                successor -> getRoleNameExtension(roleName).contains(Pair.of(individual, successor)))
425                            .skip(cardinality)
426                            .findAny()
427                            .isPresent()))
428            .collect(Collectors.toSet()));
429  }
430
431  @Override
432  public OWLClassExpression getMostSpecificConcept(
433      final IRI individual,
434      final int roleDepth,
435      final int maxCardinality,
436      final Constructor... constructors) {
437    return getMostSpecificConcept(Collections.singleton(individual), roleDepth, maxCardinality, constructors);
438  }
439
440  private final Map<Set<IRI>, OWLClassExpression> cache = new ConcurrentHashMap<>();
441
442  @Override
443  public OWLClassExpression getMostSpecificConcept(
444      final Set<IRI> individuals,
445      final int roleDepth,
446      final int maxCardinality,
447      final Constructor... constructors) {
448    if (cache.containsKey(individuals))
449      return cache.get(individuals);
450    final OWLClassExpression mmsc = getMostSpecificConceptALQ(individuals, roleDepth, maxCardinality, constructors);
451    cache.put(individuals, mmsc);
452    return mmsc;
453  }
454
455  public OWLClassExpression _getMostSpecificConcept(final IRI individual, final int roleDepth) {
456    checkRoleDepth(roleDepth);
457    final Set<OWLClassExpression> conjuncts = new HashSet<OWLClassExpression>();
458    for (IRI conceptName : conceptNameExtensions.keySet())
459      if (getConceptNameExtension(conceptName).contains(individual))
460        conjuncts.add(new OWLClassImpl(conceptName));
461    if (roleDepth > 0)
462      for (IRI roleName : roleNameExtensions.keySet())
463        for (Pair<IRI, IRI> pair : getRoleNameExtension(roleName))
464          if (pair.x().equals(individual))
465            conjuncts
466                .add(
467                    df
468                        .getOWLObjectSomeValuesFrom(
469                            df.getOWLObjectProperty(roleName),
470                            getMostSpecificConcept(pair.y(), 0, roleDepth - 1)));
471    if (conjuncts.isEmpty())
472      return df.getOWLThing();
473    if (conjuncts.size() == 1)
474      return conjuncts.iterator().next();
475    return new OWLObjectIntersectionOfImpl(conjuncts);
476  }
477
478  public final OWLClassExpression _getMostSpecificConcept(final Set<IRI> individuals, final int roleDepth) {
479    checkRoleDepth(roleDepth);
480    return ELLeastCommonSubsumer.of(Collections2.transform(individuals, individual -> {
481      return getMostSpecificConcept(individual, 0, roleDepth);
482    }));
483  }
484
485//  private Set<OWLClassExpression> getAllMostSpecificConcepts(final int roleDepth) {
486//    System.out.println("Computing all mmscs...");
487//    final Set<OWLClassExpression> result = new HashSet<OWLClassExpression>();
488//    if (roleDepth > -1) {
489//      final Map<IRI, OWLClassExpression> mmscs = new HashMap<IRI, OWLClassExpression>();
490//      final Map<Integer, Map<Set<IRI>, OWLClassExpression>> _mmscs =
491//          new HashMap<Integer, Map<Set<IRI>, OWLClassExpression>>();
492//      for (IRI individual : getDomain())
493//        mmscs.put(individual, getMostSpecificConcept(individual, roleDepth));
494//      for (int i = 2; i < getDomain().size(); i++) {
495//        System.out.println("cardinality " + i);
496//        final HashMap<Set<IRI>, OWLClassExpression> map = new HashMap<Set<IRI>, OWLClassExpression>();
497//        _mmscs.put(i, map);
498//        if (i == 2) {
499//          for (Entry<IRI, OWLClassExpression> e1 : mmscs.entrySet())
500//            for (Entry<IRI, OWLClassExpression> e2 : mmscs.entrySet())
501//              if (!e1.getKey().equals(e2.getKey())) {
502//                final HashSet<IRI> key = Sets.newHashSet(e1.getKey(), e2.getKey());
503//                if (!map.containsKey(key)) {
504//                  map.put(key, ELLeastCommonSubsumer.of(e1.getValue(), e2.getValue()));
505//                  System.out.print(".");
506//                }
507//              }
508//        } else {
509//          for (Entry<IRI, OWLClassExpression> e1 : mmscs.entrySet())
510//            for (Entry<Set<IRI>, OWLClassExpression> e2 : _mmscs.get(i - 1).entrySet())
511//              if (!e2.getKey().contains(e1.getKey())) {
512//                final HashSet<IRI> key = Sets.newHashSet(Sets.union(e2.getKey(), Collections.singleton(e1.getKey())));
513//                if (!map.containsKey(key)) {
514//                  map.put(key, ELLeastCommonSubsumer.of(e1.getValue(), e2.getValue()));
515//                  System.out.print(".");
516//                }
517//              }
518//        }
519//      }
520//      result.addAll(mmscs.values());
521//      for (Entry<Integer, Map<Set<IRI>, OWLClassExpression>> entry : _mmscs.entrySet())
522//        result.addAll(entry.getValue().values());
523//    }
524//    return result;
525//  }
526
527  @Override
528  protected final SetList<OWLClassExpression> getAttributeSetForInducedContext(
529      final int roleDepth,
530      final int maxCardinality,
531      final Constructor... constructors) {
532    final Set<OWLClassExpression> mmscs = roleDepth > 0
533        ? getAllMostSpecificConcepts(roleDepth - 1, maxCardinality, constructors) : Collections.emptySet();
534    final SetList<OWLClassExpression> _codomain = new HashSetArrayList<OWLClassExpression>();
535    _codomain.add(df.getOWLNothing());
536    _codomain.addAll(Collections2.transform(signature.getConceptNames(), df::getOWLClass));
537    if (Arrays.asList(constructors).contains(Constructor.PRIMITIVE_NEGATION))
538      _codomain
539          .addAll(
540              Collections2
541                  .transform(
542                      signature.getConceptNames(),
543                      conceptName -> df.getOWLObjectComplementOf(df.getOWLClass(conceptName))));
544    for (IRI roleName : signature.getRoleNames())
545      for (Constructor c : constructors)
546        switch (c) {
547        case EXISTENTIAL_RESTRICTION:
548          _codomain.addAll(Collections2.transform(mmscs, mmsc -> {
549            return df.getOWLObjectSomeValuesFrom(df.getOWLObjectProperty(roleName), mmsc);
550          }));
551          break;
552        case VALUE_RESTRICTION:
553          _codomain.addAll(Collections2.transform(mmscs, mmsc -> {
554            return df.getOWLObjectAllValuesFrom(df.getOWLObjectProperty(roleName), mmsc);
555          }));
556          break;
557        case QUALIFIED_AT_LEAST_RESTRICTION:
558          Stream
559              .iterate(0, n -> n + 1)
560              .limit(maxCardinality)
561              .skip(2)
562              .map(
563                  cardinality -> Collections2
564                      .transform(
565                          mmscs,
566                          mmsc -> df.getOWLObjectMinCardinality(cardinality, df.getOWLObjectProperty(roleName), mmsc))
567                      .stream())
568              .reduce(Stream::concat)
569              .ifPresent(stream -> _codomain.addAll(stream.collect(Collectors.toSet())));
570          break;
571        case UNQUALIFIED_AT_MOST_RESTRICTION:
572          Stream
573              .iterate(0, n -> n + 1)
574              .limit(maxCardinality)
575              .map(cardinality -> df.getOWLObjectMaxCardinality(cardinality, df.getOWLObjectProperty(roleName)))
576              .forEach(_codomain::add);
577//          Stream.iterate(
578//              0,
579//              n -> n + 1).limit(
580//              maxCardinality).skip(
581//              1).map(
582//              cardinality -> Collections2.transform(
583//                  mmscs,
584//                  mmsc -> df.getOWLObjectMaxCardinality(
585//                      cardinality,
586//                      df.getOWLObjectProperty(roleName),
587//                      mmsc)).stream()).reduce(
588//              Stream::concat).ifPresent(
589//              stream -> _codomain.addAll(stream.collect(Collectors.toSet())));
590          break;
591        case EXISTENTIAL_SELF_RESTRICTION:
592          _codomain.add(df.getOWLObjectHasSelf(df.getOWLObjectProperty(roleName)));
593          break;
594        }
595    return _codomain;
596  };
597
598  @Override
599  protected final Set<Implication<IRI, OWLClassExpression>> getBackgroundImplications(
600      final Context<IRI, OWLClassExpression> inducedContext,
601      final OWLOntology backgroundOntology) {
602    final BiPredicate<OWLClassExpression, OWLClassExpression> subsumptionTest;
603    if (backgroundOntology == null)
604      subsumptionTest = (concept1, concept2) -> ELReasoner.isSubsumedBy(concept1, concept2);
605    else
606      subsumptionTest = (concept1, concept2) -> ELReasoner.isSubsumedBy(concept1, concept2, backgroundOntology);
607    final Set<Implication<IRI, OWLClassExpression>> backgroundImplications =
608        new HashSet<Implication<IRI, OWLClassExpression>>();
609    for (OWLClassExpression concept1 : inducedContext.colHeads())
610      for (OWLClassExpression concept2 : inducedContext.colHeads())
611        if (!concept1.equals(concept2)) {
612          if (subsumptionTest.test(concept1, concept2))
613            backgroundImplications
614                .add(
615                    new Implication<IRI, OWLClassExpression>(
616                        Collections.singleton(concept1),
617                        Collections.singleton(concept2),
618                        Collections.emptySet()));
619        }
620    return backgroundImplications;
621  }
622
623  @Override
624  public final OWLOntology computeTBoxBase(
625      final int roleDepth,
626      final int maxCardinality,
627      final OWLOntology backgroundOntology,
628      final Constructor... constructors) throws OWLOntologyCreationException {
629    checkRoleDepth(roleDepth);
630    final OWLOntologyManager om = OWLManager.createOWLOntologyManager();
631    final OWLOntology ontology = om.createOntology();
632    final Context<IRI, OWLClassExpression> inducedContext =
633        getInducedContext(domain, roleDepth, maxCardinality, constructors);
634    final Set<Implication<IRI, OWLClassExpression>> backgroundImplications =
635        getBackgroundImplications(inducedContext, backgroundOntology);
636    final ResultC<IRI, OWLClassExpression> result =
637        NextClosures1C.computeWithBackgroundImplications(inducedContext, backgroundImplications, true);
638    for (Entry<Set<OWLClassExpression>, Set<OWLClassExpression>> entry : result.implications.entrySet())
639      om
640          .applyChange(
641              new AddAxiom(
642                  ontology,
643                  df
644                      .getOWLSubClassOfAxiom(
645                          ELConceptDescription
646                              .of(df.getOWLObjectIntersectionOf(entry.getKey()))
647                              .clone()
648                              .reduce()
649                              .toOWLClassExpression(),
650                          ELConceptDescription
651                              .of(df.getOWLObjectIntersectionOf(entry.getValue()))
652                              .clone()
653                              .reduce()
654                              .toOWLClassExpression())));
655    return ontology;
656  }
657
658  public final class Variable {
659
660    final int index;
661
662    public Variable(final int index) {
663      super();
664      this.index = index;
665    }
666  }
667
668  private final SetList<ArrayList<IRI>> getFirstFunctions() {
669    final SetList<ArrayList<IRI>> fs = new HashSetArrayList<ArrayList<IRI>>();
670    for (IRI individual : getDomain()) {
671      final ArrayList<IRI> f = new ArrayList<IRI>();
672      f.add(individual);
673      fs.add(f);
674    }
675    return fs;
676  }
677
678  private final SetList<ArrayList<IRI>> getNextFunctions(final SetList<ArrayList<IRI>> _fs) {
679    final SetList<ArrayList<IRI>> fs = new HashSetArrayList<ArrayList<IRI>>();
680    for (ArrayList<IRI> _f : _fs) {
681      for (IRI individual : getDomain()) {
682        final ArrayList<IRI> f = new ArrayList<IRI>(_f);
683        f.add(individual);
684        fs.add(f);
685      }
686    }
687    return fs;
688  }
689
690  private final SetList<ArrayList<IRI>> getFunctions(final int roleDepth) {
691    SetList<ArrayList<IRI>> fs = new HashSetArrayList<ArrayList<IRI>>();
692    fs.add(new ArrayList<IRI>());
693    for (int i = 0; i <= roleDepth; i++) {
694      fs = getNextFunctions(fs);
695    }
696    return fs;
697  }
698
699  private final boolean applies(final ArrayList<IRI> f, final Triple<Integer, IRI, Integer> t) {
700    final IRI d = f.get(t.getFirst());
701    final IRI r = t.getSecond();
702    final IRI e = f.get(t.getThird());
703    return roleNameExtensions.get(r).contains(Pair.of(d, e));
704  }
705
706  public final SparseContext<ArrayList<IRI>, Triple<Integer, IRI, Integer>> getInducedRoleContext(final int roleDepth) {
707    final SetList<ArrayList<IRI>> _domain = getFunctions(roleDepth + 1);
708
709    final SetList<Triple<Integer, IRI, Integer>> _codomain = new HashSetArrayList<Triple<Integer, IRI, Integer>>();
710    for (IRI roleName : signature.getRoleNames()) {
711      for (int i = 2; i <= roleDepth; i++)
712        for (int j = 1; j <= i; j++) {
713          _codomain.add(new Triple<Integer, IRI, Integer>(j, roleName, j + 1));
714          if (i != 1)
715            _codomain.add(new Triple<Integer, IRI, Integer>(1, roleName, j + 1));
716        }
717
718    }
719    final SparseContext<ArrayList<IRI>, Triple<Integer, IRI, Integer>> inducedRoleContext =
720        new SparseContext<ArrayList<IRI>, Triple<Integer, IRI, Integer>>(_domain, _codomain, false);
721
722    for (ArrayList<IRI> o : _domain)
723      for (Triple<Integer, IRI, Integer> a : _codomain) {
724        if (applies(o, a))
725          inducedRoleContext.add(o, a);
726      }
727
728    return inducedRoleContext;
729  }
730
731  public final Set<OWLSubPropertyChainOfAxiom> getRoleInclusionBase(final int roleDepth) {
732    final Set<OWLSubPropertyChainOfAxiom> base = new HashSet<OWLSubPropertyChainOfAxiom>();
733
734    final SparseContext<ArrayList<IRI>, Triple<Integer, IRI, Integer>> cxt = getInducedRoleContext(roleDepth);
735    final SetClosureOperator<Triple<Integer, IRI, Integer>> clop = new SetClosureOperator<Triple<Integer, IRI, Integer>>() {
736
737      @Override
738      public Set<Triple<Integer, IRI, Integer>> closure(Set<Triple<Integer, IRI, Integer>> set) {
739        return set;
740//        if (set.parallelStream().anyMatch(
741//            t -> t.getFirst().equals(
742//                1) && t.getThird().equals(
743//                2)))
744//          return new HashSet<Triple<Integer, IRI, Integer>>(set);
745//        return new HashSet<Triple<Integer, IRI, Integer>>(cxt.colHeads());
746      }
747
748    };
749    final Result<ArrayList<IRI>, Triple<Integer, IRI, Integer>> result = NextClosures1
750        .compute(
751            cxt,
752            // clop,
753            true);
754    for (Entry<Set<Triple<Integer, IRI, Integer>>, Set<Triple<Integer, IRI, Integer>>> e : result.implications
755        .entrySet()) {
756      final List<Triple<Integer, IRI, Integer>> chain = new ArrayList<Triple<Integer, IRI, Integer>>(roleDepth);
757      final Triple<Integer, IRI, Integer> conclusion;
758      boolean chainEnded = false;
759      int i;
760      for (i = 1; !chainEnded || i <= roleDepth; i++) {
761        final int j = i;
762        final Optional<Triple<Integer, IRI, Integer>> opt =
763            e.getKey().parallelStream().filter(t -> t.getFirst().equals(j) && t.getThird().equals(j + 1)).findFirst();
764        if (opt.isPresent())
765          chain.add(opt.get());
766        else
767          chainEnded = true;
768      }
769      if (!chain.isEmpty())
770        System.out.println("found chain of size " + chain.size() + " " + chain);
771      final int j = chain.size() + 1;// i;
772      final Optional<Triple<Integer, IRI, Integer>> opt =
773          e.getValue().parallelStream().filter(t -> t.getFirst().equals(1) && t.getThird().equals(j)).findFirst();
774      if (opt.isPresent())
775        conclusion = opt.get();
776      else
777        conclusion = null;
778      if (conclusion != null) {
779        final List<OWLObjectPropertyExpression> subProperty =
780            chain.stream().map(t -> df.getOWLObjectProperty(t.getSecond())).collect(Collectors.toList());
781        base.add(df.getOWLSubPropertyChainOfAxiom(subProperty, df.getOWLObjectProperty(conclusion.getSecond())));
782      }
783    }
784    return base;
785  }
786}