package uk.ac.manchester.cs.jfact.kernel;
/* This file is part of the JFact DL reasoner
Copyright 2011-2013 by Ignazio Palmisano, Dmitry Tsarkov, University of Manchester
This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA*/
import static uk.ac.manchester.cs.jfact.kernel.InAx.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import uk.ac.manchester.cs.jfact.helpers.DLTree;
import uk.ac.manchester.cs.jfact.helpers.DLTreeFactory;
import uk.ac.manchester.cs.jfact.helpers.LogAdapter;
import conformance.PortedFrom;
/** set of axioms */
@PortedFrom(file = "tAxiomSet.h", name = "TAxiomSet")
public class AxiomSet implements Serializable {
private static final long serialVersionUID = 11000L;
/** host TBox that holds all concepts/etc */
@PortedFrom(file = "tAxiomSet.h", name = "Host")
protected final TBox tboxHost;
/** set of axioms that accumilates incoming (and newly created) axioms */
@PortedFrom(file = "tAxiomSet.h", name = "Accum")
private List<Axiom> accumulator = new ArrayList<Axiom>();
private final LogAdapter absorptionLog;
/** set of absorption action, in order */
@PortedFrom(file = "tAxiomSet.h", name = "ActionVector")
private final List<AbsorptionActions> actions = new ArrayList<AbsorptionActions>();
@PortedFrom(file = "tAxiomSet.h", name = "curAxiom")
private int curAxiom = 0;
/**
* add already built GCI p
*
* @param p
* p
*/
@PortedFrom(file = "tAxiomSet.h", name = "insertGCI")
private void insertGCI(Axiom p) {
tboxHost.getOptions().getAbsorptionLog().print("\n new axiom (")
.print(accumulator.size()).print("):", p);
accumulator.add(p);
}
/**
* @param q
* axiom
* @return true iff axiom q is a copy of an axiom in range [p,p_end)
*/
@PortedFrom(file = "tAxiomSet.h", name = "copyOf")
boolean copyOfExisting(Axiom q) {
int i = accumulator.indexOf(q);
if (i > -1) {
absorptionLog.print(" same as (").print(i).print(")");
return true;
}
return false;
}
/**
* helper that inserts an axiom into Accum;
*
* @param q
* q
* @return bool if success
*/
@PortedFrom(file = "tAxiomSet.h", name = "processNewAxiom")
protected boolean processNewAxiom(Axiom q) {
if (q == null) {
return false;
}
// if an axiom is a copy of already processed one -- fail to add (will
// result in a cycle)
if (q.isCyclic()) {
return false;
}
// if an axiom is a copy of a new one -- succeed but didn't really add
// anything
if (copyOfExisting(q)) {
return true;
}
// fresh axiom -- add it
insertGCI(q);
return true;
}
/**
* @param host
* host
*/
public AxiomSet(TBox host) {
tboxHost = host;
absorptionLog = tboxHost.getOptions().getAbsorptionLog();
Axiom.setLogAdapter(absorptionLog);
}
/**
* add axiom for the GCI C [= D
*
* @param C
* C
* @param D
* D
*/
@PortedFrom(file = "tAxiomSet.h", name = "addAxiom")
public void addAxiom(DLTree C, DLTree D) {
SAbsInput();
Axiom p = new Axiom(null);
p.add(C);
p.add(DLTreeFactory.createSNFNot(D));
insertGCI(p);
}
/**
* get number of (not absorbed) GCIs
*
* @return size
*/
@PortedFrom(file = "tAxiomSet.h", name = "size")
private int size() {
return accumulator.size();
}
/** @return true if non-concept aborption were executed */
@PortedFrom(file = "tAxiomSet.h", name = "wasRoleAbsorptionApplied")
public boolean wasRoleAbsorptionApplied() {
return InAx.containsSAbsRApply();
}
/** @return GCI of all non-absorbed axioms */
@PortedFrom(file = "tAxiomSet.h", name = "getGCI")
public DLTree getGCI() {
List<DLTree> l = new ArrayList<DLTree>();
for (Axiom p : accumulator) {
l.add(p.createAnAxiom(null));
}
return DLTreeFactory.createSNFAnd(l);
}
/**
* split given axiom
*
* @param p
* p
* @return true if any spit happens
*/
@PortedFrom(file = "tAxiomSet.h", name = "split")
protected boolean split(Axiom p) {
List<Axiom> splitted = p.split();
if (splitted.isEmpty()) {
// nothing to split
return false;
}
List<Axiom> kept = new ArrayList<Axiom>();
for (int i = 0; i < splitted.size(); i++) {
Axiom q = splitted.get(i);
if (q.isCyclic()) {
// there is already such an axiom in process; delete it
return false;
}
// axiom is not a copy of a new one: keep it
if (!copyOfExisting(q)) {
kept.add(q);
}
}
// no failure: delete all the unneded axioms, add all kept ones
// do the actual insertion if necessary
for (Axiom q : kept) {
insertGCI(q);
}
return true;
}
/** @return new size */
@PortedFrom(file = "tAxiomSet.h", name = "absorb")
public int absorb() {
// GCIs to process
List<Axiom> GCIs = new ArrayList<Axiom>();
// we will change Accum (via split rule), so indexing and compare with
// size
for (curAxiom = 0; curAxiom < accumulator.size(); curAxiom++) {
Axiom ax = accumulator.get(curAxiom);
tboxHost.getOptions().getAbsorptionLog().print("\nProcessing (")
.print(curAxiom).print("):");
if (!absorbGCI(ax)) {
GCIs.add(ax);
}
}
// clear absorbed and remove them from Accum
accumulator = GCIs;
tboxHost.getOptions().getAbsorptionLog()
.print("\nAbsorption done with ").print(accumulator.size())
.print(" GCIs left\n");
printStatistics();
return size();
}
@PortedFrom(file = "tAxiomSet.h", name = "absorbGCI")
private boolean absorbGCI(Axiom p) {
SAbsAction();
for (AbsorptionActions abs : actions) {
if (abs.execute(p, this)) {
return true;
}
}
tboxHost.getOptions().getAbsorptionLog().print(" keep as GCI");
return false;
}
/**
* @param flags
* flags
* @return false if no absorptions
*/
@PortedFrom(file = "tAxiomSet.h", name = "initAbsorptionFlags")
public boolean initAbsorptionFlags(String flags) {
actions.clear();
for (char c : flags.toCharArray()) {
actions.add(AbsorptionActions.get(c));
}
tboxHost.getOptions().getAbsorptionLog()
.print("Init absorption order as ").print(flags).print("\n");
return false;
}
@PortedFrom(file = "tAxiomSet.h", name = "PrintStatistics")
private void printStatistics() {
if (!containsSAbsAction()) {
return;
}
LogAdapter log = tboxHost.getOptions().getAbsorptionLog();
log.print("\nAbsorption dealt with ").print(getSAbsInput())
.print(" input axioms\nThere were made ")
.print(getSAbsAction()).print(" absorption actions, of which:");
if (containsSAbsRepCN()) {
log.print("\n\t").print(getSAbsRepCN())
.print(" concept name replacements");
}
if (containsSAbsRepForall()) {
log.print("\n\t").print(getSAbsRepForall())
.print(" universals replacements");
}
if (containsSAbsSplit()) {
log.print("\n\t").print(getSAbsSplit())
.print(" conjunction splits");
}
if (containsSAbsBApply()) {
log.print("\n\t").print(getSAbsBApply())
.print(" BOTTOM absorptions");
}
if (containsSAbsTApply()) {
log.print("\n\t").print(getSAbsTApply()).print(" TOP absorptions");
}
if (containsSAbsCApply()) {
log.print("\n\t").print(getSAbsCApply())
.print(" concept absorption with ")
.print(getSAbsCAttempt()).print(" possibilities");
}
if (containsSAbsNApply()) {
log.print("\n\t").print(getSAbsNApply())
.print(" negated concept absorption with ")
.print(getSAbsNAttempt()).print(" possibilities");
}
if (containsSAbsRApply()) {
log.print("\n\t").print(getSAbsRApply())
.print(" role domain absorption with ")
.print(getSAbsRAttempt()).print(" possibilities");
}
if (!accumulator.isEmpty()) {
log.print("\nThere are ").print(accumulator.size())
.print(" GCIs left");
}
}
}