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}