fr.boreal.model.kb.api.FactBase Maven / Gradle / Ivy
The newest version!
package fr.boreal.model.kb.api;
import fr.boreal.model.kb.impl.FactBaseDescription;
import fr.boreal.model.logicalElements.api.*;
import fr.boreal.model.logicalElements.impl.SubstitutionImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* A FactBase represents a set of Atom seen as a conjunction
*
* @author Florent Tornil
* @author Federico Ulliana
* @author Guillaume Pérution-Kihli
*
*/
public interface FactBase extends Readable, Writeable {
/**
* @return a stream over all the atoms of the factbase
*/
Stream getAtoms();
/**
* Returns a set of all the atoms in the fact base
* This method can be costly in memory if the fact base is not in memory
*
* @return a set containing all the atoms of the fact base
*/
default Set getAtomsInMemory() {
return getAtoms().collect(Collectors.toSet());
}
/**
* @return a stream over all the variables of the fact base
*/
default Stream getVariables() {
return getAtoms().flatMap(a -> a.getVariables().stream()).distinct();
}
/**
* @return a stream over all the terms of the fact base
*/
default Stream getTerms() {
return getAtoms().flatMap(a -> Arrays.stream(a.getTerms())).distinct();
}
/**
* @return a stream over all the constants of the fact base
*/
default Stream getConstants() {
return getAtoms().flatMap(a -> a.getConstants().stream()).distinct();
}
/**
* @return a stream over all the literals of the fact base
*/
default Stream> getLiterals() {
return getAtoms().flatMap(a -> a.getLiterals().stream()).distinct();
}
/**
* Returns an iterator over all atoms with the specified predicate.
*
* @param predicate to search
* @return an iterator over all atoms with the specified predicate
*/
Iterator getAtomsByPredicate(Predicate predicate);
/**
* Returns an iterator over all atoms with the specified term.
*
* @param term to search
* @return an iterator over all atoms with the specified term
*/
default Iterator getAtomsByTerm(Term term) {
return getAtoms().filter(a -> Arrays.asList(a.getTerms()).contains(term)).iterator();
}
/**
* Returns an Iterator of all predicates in this factbase.
*
* @return an Iterator of all predicates.
*/
Iterator getPredicates();
/**
* Returns an iterator over terms which are in a specific position in at
* least one atom with the given predicate.
*
* @param p predicate
* @param position the position of the term in atoms, positions starts from 0.
* @return an iterator over terms which appear in the specified position of the specified predicate.
*/
Iterator getTermsByPredicatePosition(Predicate p, int position);
/**
* @param t the term that all atoms must contain
* @return a stream over all the atoms of the factbase that contains the given
* term t
*/
default Stream getAtoms(Term t) {
return this.getAtoms().filter(a -> a.contains(t));
}
/**
* @param a the atom to find
* @return true iff this storage contains the given atom
*/
default boolean contains(Atom a) {
return this.getAtoms().anyMatch(atom -> atom.equals(a));
}
/**
* @return the number of atoms represented by this factbase
*/
default long size() {
return this.getAtoms().count();
}
// Tatooine temporary methods
/**
* @param viewPredicate a predicate
* @return the description of the storage
*/
FactBaseDescription getDescription(Predicate viewPredicate);
/**
* @param viewPredicate a predicate
* @return the type of storage used for the given predicate
*/
FactBaseType getType(Predicate viewPredicate);
/**
* @param viewPredicate a predicate
* @return the type of the columns for the given predicate
*/
default List getColumnsType(Predicate viewPredicate) {
int arity = viewPredicate.arity();
List types = new ArrayList<>(arity);
for (int i = 0; i < arity; i++) {
types.add(ColumnType.STRING);
}
return types;
}
/**
* Removes all atoms from the fact base.
*/
@Override
default void clear() {
List batch;
do {
// Collect a batch of atoms to avoid ConcurrentModificationException
batch = this.getAtoms().limit(1000).toList();
this.removeAll(batch);
} while (!batch.isEmpty());
}
/**
* Estimates the upper bound of the number of atoms that match the given atom.
* The estimation is the upper bound, meaning the actual number of matching atoms will not exceed this number.
* Implementations may return an empty Optional if they cannot provide an estimation.
*
* @param atom the atom to match
* @return an Optional containing the estimated upper bound of matching atoms, or an empty Optional if estimation is not possible
*/
default Optional estimateMatchCount(Atom atom) {
return estimateMatchCount(atom, new SubstitutionImpl());
}
/**
* Estimates the upper bound of the number of atoms that match the given atom with a substitution.
* The estimation is the upper bound, meaning the actual number of matching atoms will not exceed this number.
* Implementations may return an empty Optional if they cannot provide an estimation.
*
* @param atom the atom to match
* @param substitution the substitution to apply
* @return an Optional containing the estimated upper bound of matching atoms, or an empty Optional if estimation is not possible
*/
default Optional estimateMatchCount(Atom atom, Substitution substitution) {
return Optional.empty();
}
/**
* Determines if the fact base can perform an indexed match for the given atom.
* This method checks if the fact base can avoid a full scan of all atoms or all atoms with the same predicate.
*
* @param atom the atom to match
* @return true if the fact base can perform an indexed match for the given atom; false otherwise
*/
default boolean canPerformIndexedMatch(Atom atom) {
return estimateMatchCount(atom).isPresent();
}
/**
* Determines if the fact base can perform an indexed match for the given atom with a substitution.
* This method checks if the fact base can avoid a full scan of all atoms or all atoms with the same predicate.
*
* @param atom the atom to match
* @param substitution the substitution to apply
* @return true if the fact base can perform an indexed match for the given atom with the substitution; false otherwise
*/
default boolean canPerformIndexedMatch(Atom atom, Substitution substitution) {
return estimateMatchCount(atom, substitution).isPresent();
}
}