001package conexp.fx.core.dl.deprecated;
002
003import java.io.BufferedReader;
004
005/*
006 * #%L
007 * Concept Explorer FX
008 * %%
009 * Copyright (C) 2010 - 2019 Francesco Kriegel
010 * %%
011 * This program is free software: you can redistribute it and/or modify
012 * it under the terms of the GNU General Public License as
013 * published by the Free Software Foundation, either version 3 of the
014 * License, or (at your option) any later version.
015 * 
016 * This program is distributed in the hope that it will be useful,
017 * but WITHOUT ANY WARRANTY; without even the implied warranty of
018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
019 * GNU General Public License for more details.
020 * 
021 * You should have received a copy of the GNU General Public
022 * License along with this program.  If not, see
023 * <http://www.gnu.org/licenses/gpl-3.0.html>.
024 * #L%
025 */
026
027import java.io.File;
028import java.io.FileReader;
029import java.io.IOException;
030import java.io.UncheckedIOException;
031import java.util.Collections;
032import java.util.HashSet;
033import java.util.Iterator;
034import java.util.List;
035import java.util.Map.Entry;
036import java.util.Set;
037import java.util.function.BiPredicate;
038import java.util.stream.Collectors;
039
040import org.semanticweb.owlapi.model.IRI;
041
042import com.google.common.collect.Collections2;
043import com.google.common.collect.HashMultimap;
044import com.google.common.collect.Multimap;
045
046import conexp.fx.core.algorithm.nextclosures.NextClosures1C;
047import conexp.fx.core.algorithm.nextclosures.NextClosures1C.ResultC;
048import conexp.fx.core.collections.Pair;
049import conexp.fx.core.collections.setlist.HashSetArrayList;
050import conexp.fx.core.collections.setlist.SetList;
051import conexp.fx.core.context.Context;
052import conexp.fx.core.context.Implication;
053import conexp.fx.core.dl.ELConceptDescription;
054import conexp.fx.core.dl.ELConceptInclusion;
055import conexp.fx.core.dl.ELLeastCommonSubsumer;
056import conexp.fx.core.dl.ELReasoner;
057import conexp.fx.core.dl.ELTBox;
058import conexp.fx.core.dl.Signature;
059
060@Deprecated
061public final class ELInterpretation extends AInterpretation<ELConceptDescription, ELConceptInclusion, ELTBox> {
062
063  public ELInterpretation(final IRI baseIRI) {
064    super(baseIRI);
065  }
066
067  public ELInterpretation(final Signature signature) {
068    super(signature);
069  }
070
071  public ELInterpretation(final Signature signature, final Set<IRI> domain) {
072    super(signature, domain);
073  }
074
075  @Override
076  public final boolean isInstanceOf(IRI individual, ELConceptDescription conceptExpression) {
077    if (conceptExpression.isBot())
078      return false;
079    if (conceptExpression.isTop())
080      return true;
081    return conceptExpression
082        .getConceptNames()
083        .parallelStream()
084        .allMatch(conceptName -> conceptNameExtensions.get(conceptName).contains(individual))
085        && conceptExpression
086            .getExistentialRestrictions()
087            .entries()
088            .parallelStream()
089            .allMatch(
090                existentialRestriction -> getRoleSuccessorStream(existentialRestriction.getKey(), individual)
091                    .anyMatch(successor -> isInstanceOf(successor, existentialRestriction.getValue())));
092  }
093
094//  @Override
095//  public Set<IRI> getConceptExpressionExtension(final ELNormalForm conceptExpression) {
096//    if (conceptExpression.isBot())
097//      return Collections.emptySet();
098//    if (conceptExpression.isTop())
099//      return getDomain();
100//    return getDomain()
101//        .parallelStream()
102//        .filter(individual -> isInstanceOf(individual, conceptExpression))
103//        .collect(Collectors.toSet());
104////    return getDomain()
105////        .parallelStream()
106////        .filter(
107////            individual -> conceptExpression
108////                .getConceptNames()
109////                .parallelStream()
110////                .allMatch(conceptName -> getConceptNameExtension(conceptName).contains(individual))
111////                && conceptExpression
112////                    .getExistentialRestrictions()
113////                    .parallelStream()
114////                    .allMatch(
115////                        existentialRestriction -> getRoleSuccessorStream(existentialRestriction.first(), individual)
116////                            .anyMatch(successor -> isInstanceOf(successor, existentialRestriction.second()))))
117////        .collect(Collectors.toSet());
118////    final Set<IRI> extension = new HashSet<IRI>();
119////    extension.addAll(getDomain());
120////    for (IRI conceptName : concept.getConceptNames())
121////      extension.retainAll(getConceptNameExtension(conceptName));
122////    for (Pair<IRI, ELNormalForm> existentialRestriction : concept.getExistentialRestrictions())
123////      extension.retainAll(getExistentialRestrictionExtension(existentialRestriction));
124////    return extension;
125//  }
126//
127//  private final Set<IRI> getExistentialRestrictionExtension(final Pair<IRI, ELNormalForm> existentialRestriction) {
128//    final Set<IRI> extension = new HashSet<IRI>();
129//    for (Pair<IRI, IRI> pair : getRoleNameExtension(existentialRestriction.x()))
130//      if (getConceptExpressionExtension(existentialRestriction.y()).contains(pair.y()))
131//        extension.add(pair.x());
132//    return extension;
133//  }
134
135  @Override
136  public final boolean satisfies(final ELConceptInclusion gci) {
137    return isSubsumedBy(gci.getSubsumee(), gci.getSubsumer());
138  }
139
140  @Override
141  public final boolean models(ELTBox tBox) {
142    return tBox.getConceptInclusions().parallelStream().allMatch(this::satisfies);
143  }
144
145  @Override
146  public ELConceptDescription getMostSpecificConcept(
147      final IRI individual,
148      final int roleDepth,
149      final int maxCardinality,
150      final Constructor... constructors) {
151    checkRoleDepth(roleDepth);
152    final Set<IRI> conceptNames = new HashSet<IRI>(conceptNamesPerIndividual.get(individual));
153    final Set<Pair<IRI, ELConceptDescription>> existentialRestrictions;
154//    for (IRI conceptName : conceptNameExtensions.keySet())
155//      if (getConceptNameExtension(conceptName).contains(individual))
156//        conceptNames.add(conceptName);
157    if (roleDepth > 0)
158      existentialRestrictions = roleSuccessors.get(individual).parallelStream().map(p -> {
159        return new Pair<IRI, ELConceptDescription>(p.x(), getMostSpecificConcept(p.y(), 0, roleDepth - 1));
160      }).collect(Collectors.toSet());
161//      for (IRI roleName : roleNameExtensions.keySet())
162//        for (Pair<IRI, IRI> pair : getRoleNameExtension(roleName))
163//          if (pair.x().equals(individual))
164//            existentialRestrictions.add(new Pair<IRI, ELNormalForm>(roleName, _getMostSpecificConcept(
165//                pair.y(),
166//                roleDepth - 1)));
167    else
168      existentialRestrictions = new HashSet<Pair<IRI, ELConceptDescription>>();
169    final ELConceptDescription msc = new ELConceptDescription();
170    msc.getConceptNames().addAll(conceptNames);
171    for (Pair<IRI, ELConceptDescription> p : existentialRestrictions)
172      msc.getExistentialRestrictions().put(p.x(), p.y());
173    msc.reduce();
174    return msc;
175  }
176
177  @Override
178  public final ELConceptDescription getMostSpecificConcept(
179      final Set<IRI> individuals,
180      final int roleDepth,
181      final int maxCardinality,
182      final Constructor... constructors) {
183    checkRoleDepth(roleDepth);
184    return ELLeastCommonSubsumer
185        .lcs(
186            new HashSet<>(
187                Collections2.transform(individuals, individual -> getMostSpecificConcept(individual, 0, roleDepth))));
188  }
189
190//  private Set<ELNormalForm> getAllMostSpecificConcepts(final int roleDepth) {
191//    System.out.println("Computing all mmscs...");
192//    final Set<ELNormalForm> result = new HashSet<ELNormalForm>();
193//    if (roleDepth > -1) {
194//      final Map<IRI, ELNormalForm> mmscs = new HashMap<IRI, ELNormalForm>();
195//      final Map<Integer, Map<Set<IRI>, ELNormalForm>> _mmscs = new HashMap<Integer, Map<Set<IRI>, ELNormalForm>>();
196//      for (IRI individual : getDomain())
197//        mmscs.put(individual, getMostSpecificConcept(individual, roleDepth));
198//      int c = 0;
199//      for (int i = 2; i < getDomain().size(); i++) {
200//        System.out.println("cardinality " + i);
201//        final HashMap<Set<IRI>, ELNormalForm> map = new HashMap<Set<IRI>, ELNormalForm>();
202//        _mmscs.put(i, map);
203//        if (i == 2) {
204//          for (Entry<IRI, ELNormalForm> e1 : mmscs.entrySet())
205//            for (Entry<IRI, ELNormalForm> e2 : mmscs.entrySet())
206//              if (!e1.getKey().equals(e2.getKey())) {
207//                final HashSet<IRI> key = Sets.newHashSet(e1.getKey(), e2.getKey());
208//                if (!map.containsKey(key)) {
209//                  map.put(key, ELLeastCommonSubsumer._of(e1.getValue(), e2.getValue()).minimize());
210//                  System.out.println(c++);
211//                }
212//              }
213//        } else {
214//          for (Entry<IRI, ELNormalForm> e1 : mmscs.entrySet())
215//            for (Entry<Set<IRI>, ELNormalForm> e2 : _mmscs.get(i - 1).entrySet())
216//              if (!e2.getKey().contains(e1.getKey())) {
217//                final HashSet<IRI> key = Sets.newHashSet(Sets.union(e2.getKey(), Collections.singleton(e1.getKey())));
218//                if (!map.containsKey(key)) {
219//                  map.put(key, ELLeastCommonSubsumer._of(e1.getValue(), e2.getValue()).minimize());
220//                  System.out.println(c++);
221//                }
222//              }
223//        }
224//      }
225//      result.addAll(mmscs.values());
226//      for (Entry<Integer, Map<Set<IRI>, ELNormalForm>> entry : _mmscs.entrySet())
227//        result.addAll(entry.getValue().values());
228//    }
229//    return result;
230//  }
231
232  @Override
233  protected final SetList<ELConceptDescription> getAttributeSetForInducedContext(
234      final int roleDepth,
235      final int maxCardinality,
236      final Constructor... constructors) {
237    final Set<ELConceptDescription> mmscs = getAllMostSpecificConcepts(roleDepth - 1, 0);
238    final SetList<ELConceptDescription> _codomain = new HashSetArrayList<ELConceptDescription>();
239    _codomain.add(ELConceptDescription.bot());
240    _codomain.addAll(Collections2.transform(signature.getConceptNames(), ELConceptDescription::conceptName));
241    for (IRI roleName : signature.getRoleNames())
242      _codomain.addAll(Collections2.transform(mmscs, mmsc -> {
243        return ELConceptDescription.existentialRestriction(roleName, mmsc);
244      }));
245    return _codomain;
246  };
247
248  @Override
249  protected final Set<Implication<IRI, ELConceptDescription>>
250      getBackgroundImplications(final Context<IRI, ELConceptDescription> inducedContext, final ELTBox backgroundTBox) {
251    final BiPredicate<ELConceptDescription, ELConceptDescription> subsumptionTest;
252    if (backgroundTBox == null)
253      subsumptionTest = (concept1, concept2) -> ELReasoner.isSubsumedBy(concept1, concept2);
254    else
255      subsumptionTest = (concept1, concept2) -> ELReasoner.isSubsumedBy(concept1, concept2, backgroundTBox);
256    final Set<Implication<IRI, ELConceptDescription>> backgroundImplications =
257        new HashSet<Implication<IRI, ELConceptDescription>>();
258    for (ELConceptDescription concept1 : inducedContext.colHeads())
259      for (ELConceptDescription concept2 : inducedContext.colHeads())
260        if (!concept1.equals(concept2))
261          if (subsumptionTest.test(concept1, concept2))
262            backgroundImplications
263                .add(
264                    new Implication<IRI, ELConceptDescription>(
265                        Collections.singleton(concept1),
266                        Collections.singleton(concept2),
267                        Collections.emptySet()));
268    return backgroundImplications;
269  }
270
271  @Override
272  public final ELTBox computeTBoxBase(
273      final int roleDepth,
274      final int maxCardinality,
275      final ELTBox backgroundTBox,
276      final Constructor... constructors) {
277    checkRoleDepth(roleDepth);
278    final ELTBox tbox = new ELTBox();
279    final Context<IRI, ELConceptDescription> inducedContext = getInducedContext(domain, roleDepth, maxCardinality);
280    final Set<Implication<IRI, ELConceptDescription>> backgroundImplications =
281        getBackgroundImplications(inducedContext, backgroundTBox);
282    final ResultC<IRI, ELConceptDescription> result =
283        NextClosures1C.computeWithBackgroundImplications(inducedContext, backgroundImplications, false);
284    for (Entry<Set<ELConceptDescription>, Set<ELConceptDescription>> entry : result.implications.entrySet())
285      tbox
286          .getConceptInclusions()
287          .add(
288              new ELConceptInclusion(
289                  ELConceptDescription.conjunction(entry.getKey()).clone().reduce(),
290                  ELConceptDescription.conjunction(entry.getValue()).clone().reduce()));
291    return tbox;
292  }
293
294  public static final ELInterpretation fromTriples(final File rdfFile, final IRI baseIRI, final String isaRole) {
295    final ELInterpretation i = new ELInterpretation(baseIRI);
296    final Multimap<String, String> concepts = HashMultimap.create();
297    final Multimap<String, Pair<String, String>> roles = HashMultimap.create();
298    try {
299      final BufferedReader reader = new BufferedReader(new FileReader(rdfFile));
300      final Iterator<String> it = reader.lines().iterator();
301      while (it.hasNext()) {
302        String next = it.next();
303        while (next.contains("  "))
304          next = next.replace("  ", " ");
305        next = next.replace("<", "").replace(">", "");
306        final String[] triple = next.split(" ");
307        if (triple.length > 2)
308          if (triple[1].contains(isaRole)) {
309            concepts.put(triple[0], triple[2]);
310          } else {
311            roles.put(triple[1], new Pair<String, String>(triple[0], triple[2]));
312          }
313      }
314      reader.close();
315    } catch (IOException e) {
316      throw new UncheckedIOException(e);
317    }
318    for (Entry<String, String> entry : concepts.entries()) {
319      final IRI c = IRI.create(entry.getKey());
320      final IRI d = IRI.create(entry.getValue());
321      i.getSignature().getConceptNames().add(d);
322      i.getDomain().add(c);
323      i.addConceptNameAssertion(d, c);
324    }
325    for (Entry<String, Pair<String, String>> entry : roles.entries()) {
326      final IRI r = IRI.create(entry.getKey());
327      final IRI d = IRI.create(entry.getValue().x());
328      final IRI e = IRI.create(entry.getValue().y());
329      i.getSignature().getRoleNames().add(r);
330      i.getDomain().add(d);
331      i.getDomain().add(e);
332      i.addRoleNameAssertion(r, d, e);
333    }
334    return i;
335  }
336
337  public static final ELInterpretation fromTriples(final List<IRI[]> triples, final IRI baseIRI, final IRI isaRole) {
338    final ELInterpretation i = new ELInterpretation(baseIRI);
339    for (IRI[] triple : triples) {
340      if (triple[1].equals(isaRole)) {
341        i.getSignature().getConceptNames().add(triple[2]);
342        i.getDomain().add(triple[0]);
343        i.addConceptNameAssertion(triple[2], triple[0]);
344      } else {
345        i.getSignature().getRoleNames().add(triple[1]);
346        i.getDomain().add(triple[0]);
347        i.getDomain().add(triple[2]);
348        i.addRoleNameAssertion(triple[1], triple[0], triple[2]);
349      }
350    }
351    return i;
352  }
353
354}