/* * Licensed under the Apache License, Version 2.0 (the "License"); * * You may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * limitations under the License. * * Contributions from 2013-2017 where performed either by US government * employees, or under US Veterans Health Administration contracts. * * US Veterans Health Administration contributions by government employees * are work of the U.S. Government and are not subject to copyright * protection in the United States. Portions contributed by government * employees are USGovWork (17USC ยง105). Not subject to copyright. * * Contribution by contractors to the US Veterans Health Administration * during this period are contractually contributed under the * Apache License, Version 2.0. * * See: https://www.usa.gov/government-works * * Contributions prior to 2013: * * Copyright (C) International Health Terminology Standards Development Organisation. * Licensed under the Apache License, Version 2.0. * */ package sh.isaac.provider.logic.csiro.classify; //~--- JDK imports ------------------------------------------------------------ import java.util.ArrayList; import java.util.BitSet; import java.util.HashSet; import java.util.Set; import java.util.function.BiConsumer; //~--- non-JDK imports -------------------------------------------------------- import org.apache.mahout.math.map.OpenIntObjectHashMap; import org.apache.mahout.math.set.OpenIntHashSet; import au.csiro.ontology.Factory; import au.csiro.ontology.model.Axiom; import au.csiro.ontology.model.Concept; import au.csiro.ontology.model.ConceptInclusion; import au.csiro.ontology.model.Role; import sh.isaac.api.logic.LogicNode; import sh.isaac.model.logic.LogicalExpressionOchreImpl; import sh.isaac.model.logic.node.AndNode; import sh.isaac.model.logic.node.internal.ConceptNodeWithSequences; import sh.isaac.model.logic.node.internal.RoleNodeSomeWithSequences; //~--- classes ---------------------------------------------------------------- /** * Created by kec on 12/16/14. */ //TODO move to CSIRO specific module public class AxiomAccumulator implements BiConsumer<Set<Axiom>, LogicalExpressionOchreImpl> { /** The concept sequences. */ BitSet conceptSequences; /** The concepts. */ Concept[] concepts; /** The roles. */ OpenIntObjectHashMap<Role> roles; /** The never group role sequences. */ OpenIntHashSet neverGroupRoleSequences; /** The role group concept sequence. */ int roleGroupConceptSequence; //~--- constructors -------------------------------------------------------- /** * Instantiates a new axiom accumulator. * * @param concepts the concepts * @param conceptSequences the concept sequences * @param roles the roles * @param neverGroupRoleSequences the never group role sequences * @param roleGroupConceptSequence the role group concept sequence */ public AxiomAccumulator(Concept[] concepts, BitSet conceptSequences, OpenIntObjectHashMap<Role> roles, OpenIntHashSet neverGroupRoleSequences, int roleGroupConceptSequence) { this.concepts = concepts; this.conceptSequences = conceptSequences; this.roles = roles; this.neverGroupRoleSequences = neverGroupRoleSequences; this.roleGroupConceptSequence = roleGroupConceptSequence; } //~--- methods ------------------------------------------------------------- /** * Accept. * * @param axioms the axioms * @param logicGraphVersion the logic graph version */ @Override public void accept(Set<Axiom> axioms, LogicalExpressionOchreImpl logicGraphVersion) { if (this.conceptSequences.get(logicGraphVersion.getConceptSequence())) { axioms.addAll(generateAxioms(logicGraphVersion)); } } /** * Generate axioms. * * @param logicGraphVersion the logic graph version * @return the set */ public Set<Axiom> generateAxioms(LogicalExpressionOchreImpl logicGraphVersion) { final Concept thisConcept = this.concepts[logicGraphVersion.getConceptSequence()]; final Set<Axiom> axioms = new HashSet<>(); for (final LogicNode setLogicNode: logicGraphVersion.getRoot() .getChildren()) { final AndNode andNode = (AndNode) setLogicNode.getChildren()[0]; final ArrayList<Concept> definition = new ArrayList<>(); for (final LogicNode child: andNode.getChildren()) { switch (child.getNodeSemantic()) { case CONCEPT: final ConceptNodeWithSequences conceptNode = (ConceptNodeWithSequences) child; definition.add(this.concepts[conceptNode.getConceptSequence()]); break; case ROLE_SOME: final RoleNodeSomeWithSequences roleNodeSome = (RoleNodeSomeWithSequences) child; definition.add(processRole(roleNodeSome, this.concepts, this.roles, this.neverGroupRoleSequences, this.roleGroupConceptSequence)); break; default: throw new UnsupportedOperationException("Can't handle " + child + " as child of AND"); } } switch (setLogicNode.getNodeSemantic()) { case SUFFICIENT_SET: // if sufficient set, create a concept inclusion from the axioms to the concept axioms.add( new ConceptInclusion(Factory.createConjunction(definition.toArray(new Concept[definition.size()])), thisConcept)); // No break; here, for sufficient set, need to add the reverse necessary set... case NECESSARY_SET: // if necessary set create a concept inclusion from the concept to the axioms axioms.add(new ConceptInclusion(thisConcept, Factory.createConjunction( definition.toArray(new Concept[definition.size()])))); break; default: throw new UnsupportedOperationException("Can't handle " + setLogicNode + " as child of root"); } } return axioms; } /** * Process role. * * @param roleNodeSome the role node some * @param concepts the concepts * @param roles the roles * @param neverGroupRoleSequences the never group role sequences * @param roleGroupConceptSequence the role group concept sequence * @return the concept */ private Concept processRole(RoleNodeSomeWithSequences roleNodeSome, Concept[] concepts, OpenIntObjectHashMap<Role> roles, OpenIntHashSet neverGroupRoleSequences, int roleGroupConceptSequence) { // need to handle grouped, and never grouped... if (neverGroupRoleSequences.contains(roleNodeSome.getTypeConceptSequence())) { return Factory.createExistential(roles.get(roleNodeSome.getTypeConceptSequence()), getConcept(roleNodeSome.getOnlyChild(), concepts, roles, neverGroupRoleSequences, roleGroupConceptSequence)); } return Factory.createExistential(roles.get(roleGroupConceptSequence), getConcept(roleNodeSome, concepts, roles, neverGroupRoleSequences, roleGroupConceptSequence)); } //~--- get methods --------------------------------------------------------- /** * Gets the concept. * * @param logicNode the logic node * @param concepts the concepts * @param roles the roles * @param neverGroupRoleSequences the never group role sequences * @param roleGroupConceptSequence the role group concept sequence * @return the concept */ private Concept getConcept(LogicNode logicNode, Concept[] concepts, OpenIntObjectHashMap<Role> roles, OpenIntHashSet neverGroupRoleSequences, int roleGroupConceptSequence) { switch (logicNode.getNodeSemantic()) { case ROLE_SOME: final RoleNodeSomeWithSequences roleNodeSome = (RoleNodeSomeWithSequences) logicNode; return Factory.createExistential(roles.get(roleNodeSome.getTypeConceptSequence()), getConcept(roleNodeSome.getOnlyChild(), concepts, roles, neverGroupRoleSequences, roleGroupConceptSequence)); case CONCEPT: final ConceptNodeWithSequences conceptNode = (ConceptNodeWithSequences) logicNode; return concepts[conceptNode.getConceptSequence()]; case AND: return Factory.createConjunction(getConcepts(logicNode.getChildren(), concepts, roles, neverGroupRoleSequences, roleGroupConceptSequence)); } throw new UnsupportedOperationException("Can't handle " + logicNode + " as child of ROLE_SOME."); } /** * Gets the concepts. * * @param logicNodes the logic nodes * @param concepts the concepts * @param roles the roles * @param neverGroupRoleSequences the never group role sequences * @param roleGroupConceptSequence the role group concept sequence * @return the concepts */ private Concept[] getConcepts(LogicNode[] logicNodes, Concept[] concepts, OpenIntObjectHashMap<Role> roles, OpenIntHashSet neverGroupRoleSequences, int roleGroupConceptSequence) { final Concept[] returnValues = new Concept[concepts.length]; for (int i = 0; i < concepts.length; i++) { returnValues[i] = getConcept(logicNodes[i], concepts, roles, neverGroupRoleSequences, roleGroupConceptSequence); } return returnValues; } }