Skip to content

Commit

Permalink
Write NNF
Browse files Browse the repository at this point in the history
  • Loading branch information
emays committed Jan 10, 2025
1 parent e92f3eb commit dd38482
Show file tree
Hide file tree
Showing 5 changed files with 231 additions and 2 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@
<jheaps.version>0.14-r6</jheaps.version>
<roaringbitmap.version>0.9.31-r8</roaringbitmap.version>

<ikm-reasoner.version>0.37.0-SNAPSHOT</ikm-reasoner.version>
<ikm-reasoner.version>0.36.0</ikm-reasoner.version>
<owlapi.version>4.7.6</owlapi.version>
</properties>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public void nnfService() throws Exception {
int nid = ElkSnomedData.getNid(404785009);
LogicalExpression nnf = rs.getNecessaryNormalForm(nid);
LOG.info("NNF: " + nid + " " + nnf);
rs.writeInferredResults();
}

private HashMap<Integer, Long> nid_sctid_map;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
package dev.ikm.tinkar.reasoner.service;

import java.util.Arrays;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;

import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.list.ImmutableList;
import org.eclipse.collections.api.list.primitive.ImmutableIntList;
import org.eclipse.collections.api.set.primitive.ImmutableIntSet;
import org.eclipse.collections.impl.factory.primitive.IntLists;
import org.eclipse.collections.impl.factory.primitive.IntSets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import dev.ikm.tinkar.common.id.IntIdSet;
import dev.ikm.tinkar.common.id.IntIds;
import dev.ikm.tinkar.common.service.PrimitiveData;
import dev.ikm.tinkar.common.sets.ConcurrentHashSet;
import dev.ikm.tinkar.common.util.time.MultipleEndpointTimer;
import dev.ikm.tinkar.common.util.uuid.UuidT5Generator;
import dev.ikm.tinkar.coordinate.stamp.calculator.Latest;
import dev.ikm.tinkar.coordinate.view.ViewCoordinateRecord;
import dev.ikm.tinkar.entity.Entity;
import dev.ikm.tinkar.entity.EntityService;
import dev.ikm.tinkar.entity.EntityVersion;
import dev.ikm.tinkar.entity.RecordListBuilder;
import dev.ikm.tinkar.entity.SemanticEntityVersion;
import dev.ikm.tinkar.entity.SemanticRecord;
import dev.ikm.tinkar.entity.SemanticRecordBuilder;
import dev.ikm.tinkar.entity.SemanticVersionRecord;
import dev.ikm.tinkar.entity.StampEntity;
import dev.ikm.tinkar.entity.graph.DiTreeEntity;
import dev.ikm.tinkar.entity.graph.adaptor.axiom.LogicalExpression;
import dev.ikm.tinkar.entity.graph.isomorphic.IsomorphicResults;
import dev.ikm.tinkar.entity.transaction.Transaction;
import dev.ikm.tinkar.terms.State;
import dev.ikm.tinkar.terms.TinkarTerm;

public class InferredResultsWriter {

private static final Logger LOG = LoggerFactory.getLogger(InferredResultsWriter.class);

private ReasonerService rs;

private Transaction updateTransaction;

private int updateStampNid;

private int inferredPatternNid;

private int inferredNavigationPatternNid;

private MultipleEndpointTimer<IsomorphicResults.EndPoints> multipleEndpointTimer;

private ConcurrentHashSet<ImmutableIntList> equivalentSets;

private ConcurrentHashSet<Integer> conceptsWithInferredChanges;

private ConcurrentHashSet<Integer> conceptsWithNavigationChanges;

private AtomicInteger axiomDataNotFoundCounter;

public InferredResultsWriter(ReasonerService rs) {
super();
this.rs = rs;
}

private ViewCoordinateRecord getViewCoordinateRecord() {
return rs.getViewCalculator().viewCoordinateRecord();
}

private void processSemantic(Entity<? extends EntityVersion> entity) {
updateTransaction.addComponent(entity);
Entity.provider().putEntity(entity);
}

public ClassifierResults write() {
updateTransaction = Transaction.make("Committing classification");
EntityService.get().beginLoadPhase();
try {
StampEntity<?> updateStamp = updateTransaction.getStamp(State.ACTIVE,
getViewCoordinateRecord().getAuthorNidForChanges(), getViewCoordinateRecord().getDefaultModuleNid(),
getViewCoordinateRecord().getDefaultPathNid());
updateStampNid = updateStamp.nid();
inferredPatternNid = getViewCoordinateRecord().logicCoordinate().inferredAxiomsPatternNid();
inferredNavigationPatternNid = TinkarTerm.INFERRED_NAVIGATION_PATTERN.nid();
multipleEndpointTimer = new MultipleEndpointTimer<>(IsomorphicResults.EndPoints.class);
equivalentSets = new ConcurrentHashSet<>();
conceptsWithInferredChanges = new ConcurrentHashSet<>();
conceptsWithNavigationChanges = new ConcurrentHashSet<>();
axiomDataNotFoundCounter = new AtomicInteger();
rs.getReasonerConceptSet().primitiveParallelStream().forEach(conceptNid -> {
updateEquivalentSets(conceptNid);
writeNNF(conceptNid);
writeNavigation(conceptNid);
});
updateTransaction.commit();
} finally {
EntityService.get().endLoadPhase();
}
LOG.info("Inferred changes: " + conceptsWithInferredChanges.size());
LOG.info("Navigation changes: " + conceptsWithNavigationChanges.size());
LOG.info("NavigationSemantics processed not in AxiomData: " + axiomDataNotFoundCounter.get());
ViewCoordinateRecord commitCoordinate = getViewCoordinateRecord().withStampCoordinate(
getViewCoordinateRecord().stampCoordinate().withStampPositionTime(updateTransaction.commitTime()));
return new ClassifierResults(rs.getReasonerConceptSet(),
IntLists.immutable.ofAll(conceptsWithInferredChanges.stream().sorted().mapToInt(Integer::intValue)),
IntLists.immutable.ofAll(conceptsWithNavigationChanges.stream().sorted().mapToInt(Integer::intValue)),
equivalentSets, commitCoordinate);
}

private void updateEquivalentSets(int conceptNid) {
ImmutableIntSet equivalentNids = rs.getEquivalent(conceptNid);
if (equivalentNids == null) {
LOG.error("Null node for: {} {} {} will be skipped in inferred results", conceptNid,
PrimitiveData.publicId(conceptNid).idString(), PrimitiveData.text(conceptNid));
} else if (equivalentNids.size() > 1) {
equivalentSets.add(equivalentNids.toSortedList().toImmutable());
}
}

private void writeNNF(int conceptNid) {
LogicalExpression nnf = rs.getNecessaryNormalForm(conceptNid);
ImmutableList<Object> fields = Lists.immutable.of(nnf.sourceGraph());
int[] inferredSemanticNids = PrimitiveData.get().semanticNidsForComponentOfPattern(conceptNid,
inferredPatternNid);
if (inferredSemanticNids.length == 0) {
UUID uuidForSemantic = UuidT5Generator.singleSemanticUuid(Entity.getFast(inferredPatternNid),
Entity.getFast(conceptNid));
// Create new semantic...
RecordListBuilder<SemanticVersionRecord> versionRecords = RecordListBuilder.make();
SemanticRecord semanticRecord = SemanticRecordBuilder.builder()
.leastSignificantBits(uuidForSemantic.getLeastSignificantBits())
.mostSignificantBits(uuidForSemantic.getMostSignificantBits())
.nid(PrimitiveData.nid(uuidForSemantic)).referencedComponentNid(conceptNid)
.patternNid(inferredPatternNid).versions(versionRecords).build();
versionRecords.add(new SemanticVersionRecord(semanticRecord, updateStampNid, fields));
processSemantic(semanticRecord);
conceptsWithInferredChanges.add(conceptNid);
} else if (inferredSemanticNids.length == 1) {
Latest<SemanticEntityVersion> latestInferredSemantic = rs.getViewCalculator()
.latest(inferredSemanticNids[0]);
boolean changed = true;
if (latestInferredSemantic.isPresent()) {
ImmutableList<Object> latestInferredFields = latestInferredSemantic.get().fieldValues();
DiTreeEntity latestInferredTree = (DiTreeEntity) latestInferredFields.get(0);
DiTreeEntity correlatedTree = latestInferredTree.makeCorrelatedTree((DiTreeEntity) nnf.sourceGraph(),
conceptNid, multipleEndpointTimer.startNew());
changed = correlatedTree != latestInferredTree;
}
if (changed) {
processSemantic(rs.getViewCalculator().updateFields(inferredSemanticNids[0], fields, updateStampNid));
conceptsWithInferredChanges.add(conceptNid);
}
} else {
throw new IllegalStateException("More than one inferred semantic of pattern "
+ PrimitiveData.text(inferredPatternNid) + "for component: " + PrimitiveData.text(conceptNid));
}
}

private void writeNavigation(int conceptNid) {
ImmutableIntSet parentNids = rs.getParents(conceptNid);
ImmutableIntSet childNids = rs.getChildren(conceptNid);
if (parentNids == null) {
parentNids = IntSets.immutable.of();
childNids = IntSets.immutable.of();
axiomDataNotFoundCounter.incrementAndGet();
}
int[] inferredNavigationNids = PrimitiveData.get().semanticNidsForComponentOfPattern(conceptNid,
inferredNavigationPatternNid);
if (inferredNavigationNids.length == 0) {
if (parentNids.notEmpty() || childNids.notEmpty()) {
UUID uuidForSemantic = UuidT5Generator.singleSemanticUuid(Entity.getFast(inferredNavigationPatternNid),
Entity.getFast(conceptNid));
// Create new semantic...
RecordListBuilder<SemanticVersionRecord> versionRecords = RecordListBuilder.make();
SemanticRecord navigationRecord = SemanticRecordBuilder.builder()
.leastSignificantBits(uuidForSemantic.getLeastSignificantBits())
.mostSignificantBits(uuidForSemantic.getMostSignificantBits())
.nid(PrimitiveData.nid(uuidForSemantic)).referencedComponentNid(conceptNid)
.patternNid(inferredNavigationPatternNid).versions(versionRecords).build();
IntIdSet parentIds = IntIds.set.of(parentNids.toArray());
IntIdSet childrenIds = IntIds.set.of(childNids.toArray());
versionRecords.add(new SemanticVersionRecord(navigationRecord, updateStampNid,
Lists.immutable.of(childrenIds, parentIds)));
processSemantic(navigationRecord);
conceptsWithNavigationChanges.add(conceptNid);
}
} else if (inferredNavigationNids.length == 1) {
Latest<SemanticEntityVersion> latestInferredNavigationSemantic = rs.getViewCalculator()
.latest(inferredNavigationNids[0]);
boolean navigationChanged = true;
if (latestInferredNavigationSemantic.isPresent()) {
ImmutableList<Object> latestInferredNavigationFields = latestInferredNavigationSemantic.get()
.fieldValues();
IntIdSet childIds = (IntIdSet) latestInferredNavigationFields.get(0);
IntIdSet parentIds = (IntIdSet) latestInferredNavigationFields.get(1);
if (parentNids.equals(IntSets.immutable.of(parentIds.toArray()))
&& childNids.equals(IntSets.immutable.of(childIds.toArray()))) {
navigationChanged = false;
}
}
if (navigationChanged) {
IntIdSet newParentIds = IntIds.set.of(parentNids.toArray());
IntIdSet newChildIds = IntIds.set.of(childNids.toArray());
processSemantic(rs.getViewCalculator().updateFields(inferredNavigationNids[0],
Lists.immutable.of(newChildIds, newParentIds), updateStampNid));
conceptsWithNavigationChanges.add(conceptNid);
}
} else {
throw new IllegalStateException(
"More than one semantic of pattern " + PrimitiveData.text(inferredNavigationPatternNid)
+ "for component: " + PrimitiveData.text(conceptNid));
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ public default String getName() {

public void buildNecessaryNormalForm();

public ClassifierResults writeInferredResults();

public int getConceptCount();

public ImmutableIntList getReasonerConceptSet();
Expand All @@ -69,6 +71,7 @@ public default String getName() {

public LogicalExpression getNecessaryNormalForm(int id);

@Deprecated
public ClassifierResults processResults(TrackingCallable<ClassifierResults> trackingCallable,
boolean reinferAllHierarchy) throws Exception;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,14 @@ public void init(ViewCalculator viewCalculator, PatternFacade statedAxiomPattern
}

@Override
public ClassifierResults processResults(TrackingCallable<ClassifierResults> callable, boolean reinferAllHierarchy) throws Exception {
public ClassifierResults writeInferredResults() {
InferredResultsWriter nnfw = new InferredResultsWriter(this);
return nnfw.write();
}

@Override
public ClassifierResults processResults(TrackingCallable<ClassifierResults> callable, boolean reinferAllHierarchy)
throws Exception {
ProcessReasonerResults task = new ProcessReasonerResults(this, reinferAllHierarchy, callable);
return task.compute();
}
Expand Down

0 comments on commit dd38482

Please sign in to comment.