Mentions légales du service

Skip to content
Snippets Groups Projects
Commit d2ac4c5f authored by CHAROENSIT Akira's avatar CHAROENSIT Akira
Browse files

Merge branch '187-add-explanation-module' of gitlab.inria.fr:rules/integraal...

Merge branch '187-add-explanation-module' of gitlab.inria.fr:rules/integraal into 187-add-explanation-module
parents 04de23fe ade77fd9
Branches
No related tags found
1 merge request!64New views
Showing
with 1008 additions and 889 deletions
package fr.boreal.component_builder;
import java.lang.reflect.Field;
import java.time.Duration;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.boreal.component_builder.api.algorithm.IAlgorithmParameters;
import fr.boreal.component_builder.externalHaltingConditions.ExternalAlgorithmHaltingConditions;
import fr.boreal.component_builder.utils.StringUtils;
import fr.boreal.configuration.keywords.InteGraalKeywords;
import fr.boreal.configuration.keywords.InteGraalKeywords.Algorithms;
import fr.boreal.configuration.keywords.InteGraalKeywords.InternalStorageConfiguration;
import fr.boreal.configuration.keywords.InteGraalKeywords.Algorithms.Answers;
import fr.boreal.configuration.keywords.InteGraalKeywords.Algorithms.Images;
import fr.boreal.configuration.keywords.InteGraalKeywords.Algorithms.Parameters.Chase.*;
import fr.boreal.configuration.keywords.InteGraalKeywords.Algorithms.Parameters.Compilation;
import fr.boreal.configuration.keywords.InteGraalKeywords.Algorithms.Parameters.Chase.Applier;
import fr.boreal.configuration.keywords.InteGraalKeywords.Algorithms.Parameters.Chase.Checker;
import fr.boreal.configuration.keywords.InteGraalKeywords.Algorithms.Parameters.Chase.Computer;
import fr.boreal.configuration.keywords.InteGraalKeywords.Algorithms.Parameters.Chase.Evaluator;
import fr.boreal.configuration.keywords.InteGraalKeywords.Algorithms.Parameters.Chase.Scheduler;
import fr.boreal.configuration.keywords.InteGraalKeywords.Algorithms.Parameters.Chase.Namer;
import fr.boreal.configuration.keywords.InteGraalKeywords.Algorithms.Parameters.Chase.Transformer;
import fr.boreal.configuration.keywords.InteGraalKeywords.Algorithms.Parameters.Explanation.ExplainerVerbosity;
import fr.boreal.configuration.keywords.InteGraalKeywords.Algorithms.Parameters.Explanation.ExplainerSolver;
import fr.boreal.configuration.keywords.InteGraalKeywords.Algorithms.Parameters.Explanation.GraphOfRuleInstancesComputation;
import fr.boreal.configuration.keywords.InteGraalKeywords.Algorithms.Parameters.Explanation.ExplanationSupportType;
import fr.boreal.configuration.keywords.InteGraalKeywords.Algorithms.Parameters.Explanation.GraphOfRuleInstancesType;
import fr.boreal.configuration.keywords.InteGraalKeywords.Algorithms.Parameters.Explanation.*;
import fr.boreal.configuration.keywords.InteGraalKeywords.InternalStorageConfiguration;
import fr.boreal.configuration.keywords.InteGraalKeywords.InternalStorageConfiguration.DBMSDriverParameters;
import fr.boreal.configuration.keywords.InteGraalKeywords.InternalStorageConfiguration.DBType;
import fr.boreal.configuration.keywords.InteGraalKeywords.InternalStorageConfiguration.DriverType;
import fr.boreal.configuration.keywords.InteGraalKeywords.InternalStorageConfiguration.StorageLayout;
import fr.boreal.configuration.parameters.IGParameter;
import fr.lirmm.boreal.util.enumerations.EnumUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;
import java.time.Duration;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
/**
* Default implementation for {@link IAlgorithmParameters}.
......@@ -49,850 +38,892 @@ import fr.lirmm.boreal.util.enumerations.EnumUtils;
*/
public class AlgorithmParameters implements IAlgorithmParameters {
/// //////////////////////////////////////
/// / FIELDS
/// //////////////////////////////////////
static final Logger LOG = LoggerFactory.getLogger(AlgorithmParameters.class);
private final boolean parametereSetAtConstruction;
// Core configuration fields
private final Algorithms algorithm;
protected final String name;
// Closed parameters from enumeration
// chase
private Scheduler scheduler;
private Checker checker;
private Computer computer;
private Applier applier;
private Namer skolem;
private Evaluator evaluator; // added by Michel
private Transformer transformer; // added by Michel
// TODO check transfer of IntegralParameters to AlgorithmParameters
// storage
private DBType dbtype;
private DriverType driverType;
private StorageLayout storageLayout;
// query rewriting
private Compilation compilation;
// Open parameters, with names defined from a parent enumeration
// database
private String DBMSDriverParameters_URL;
private String DBMSDriverParameters_PORT;
private String DBMSDriverParameters_DATABASE_NAME;
private String DBMSDriverParameters_USER_NAME;
private String DBMSDriverParameters_USER_PASSWORD;
private String DBMSDriverParameters_CLEAR_DB;
// Open parameters, with names not defined from a parent enumeration
private Integer max;
private Integer rank;
private Duration timeout;
// query answering
private Answers answers;
private Images images;
// Alternative for setting timeout and rank
private ExternalAlgorithmHaltingConditions externalHaltingConditions;
private ExplainerVerbosity explainerVerbosity;
private ExplainerSolver explainerSolver;
private GraphOfRuleInstancesComputation graphOfRuleInstancesComputation;
private ExplanationSupportType explanationSupportType;
private GraphOfRuleInstancesType graphOfRuleInstancesType;
private Algorithms.Parameters.Explanation explanation;
/////////////////////////////////////////
//// CONSTRUCTORS
/////////////////////////////////////////
/**
* Constructs a new {@code AlgorithmParameters} instance.
*
* @param name the name of the configuration
* @param algorithmType the algorithm type (e.g., KB_CHASE, OMQA_CHASE)
*/
public AlgorithmParameters(String name, Algorithms algorithmType) {
this.name = name;
this.algorithm = algorithmType;
this.parametereSetAtConstruction = false;
initDefaultValues();
}
/**
* Constructs a new {@code AlgorithmParameters} instance and immediately sets
* parameters from the specified {@link IGParameter} object.
*
* @param name the name of the configuration
* @param algorithmType the algorithm type
* @param params an {@code IGParameter} containing parameter metadata
*/
public AlgorithmParameters(String name, Algorithms algorithmType, IGParameter<InteGraalKeywords, ?>... params) {
this.name = name;
this.algorithm = algorithmType;
initDefaultValues();
this.parametereSetAtConstruction = setParams(params);
}
/////////////////////////////////////////
//// OVERRIDDEN / PUBLIC METHODS
/////////////////////////////////////////
/**
* Returns the name of the configuration concatenated with the algorithm name.
*
* @return the name of the configuration (e.g., "MyConfig_OMQA_CHASE")
*/
public String getName() {
return this.name + "_" + this.algorithm.toString();
}
/**
* Returns the current algorithm type.
*
* @return the current {@link InteGraalKeywords.Algorithms} enum value
*/
public InteGraalKeywords.Algorithms getAlgorithm() {
return algorithm;
}
@Override
public boolean usesSaturationAlgorithm() {
return algorithm.equals(InteGraalKeywords.Algorithms.KB_CHASE)
|| algorithm.equals(InteGraalKeywords.Algorithms.OMQA_CHASE)
|| algorithm.equals(InteGraalKeywords.Algorithms.QUERY_ANSWERING_VIA_HYBRID_STRATEGY);
}
@Override
public boolean usesQueryRewritingAlgorithm() {
return algorithm.equals(InteGraalKeywords.Algorithms.OMQ_REWRITING)
|| algorithm.equals(InteGraalKeywords.Algorithms.OMQA_REW);
}
@Override
public boolean usesQueryAnsweringAlgorithm() {
return algorithm.equals(InteGraalKeywords.Algorithms.QUERY_ANSWERING);
}
@Override
public boolean usesRuleCompilationAlgorithm() {
return algorithm.equals(InteGraalKeywords.Algorithms.RULE_COMPILATION) || usesQueryRewritingAlgorithm();
}
@Override
public boolean usesOMQASaturationAlgorithm() {
return algorithm.equals(InteGraalKeywords.Algorithms.OMQA_CHASE);
}
@Override
public boolean usesOMQARewritingAlgorithm() {
return algorithm.equals(InteGraalKeywords.Algorithms.OMQA_REW);
}
@Override
public boolean usesOMQAHybridAlgorithm() {
return algorithm.equals(InteGraalKeywords.Algorithms.QUERY_ANSWERING_VIA_HYBRID_STRATEGY);
}
@Override
public boolean usesStorage() {
return usesSaturationAlgorithm() || usesQueryAnsweringAlgorithm() || usesOMQASaturationAlgorithm()
|| usesOMQARewritingAlgorithm() || usesOMQAHybridAlgorithm();
}
@Override
public Optional<Applier> getRuleApplier() {
return Optional.ofNullable(applier);
}
@Override
public Optional<Scheduler> getScheduler() {
return Optional.ofNullable(scheduler);
}
@Override
public Optional<Checker> getCriterion() {
return Optional.ofNullable(checker);
}
@Override
public Optional<Computer> getComputer() {
return Optional.ofNullable(computer);
}
@Override
public Optional<Namer> getSkolemization() {
return Optional.ofNullable(skolem);
}
@Override
public Optional<Evaluator> getEvaluator() {
return Optional.ofNullable(evaluator);
}
@Override
public Optional<Transformer> getTransformer() {
return Optional.ofNullable(transformer);
}
@Override
public Optional<DBType> getStorageType() {
return Optional.ofNullable(dbtype);
}
@Override
public Optional<DriverType> getDBDriver() {
return Optional.ofNullable(driverType);
}
@Override
public Optional<StorageLayout> getDBStrategy() {
return Optional.ofNullable(storageLayout);
}
@Override
public Optional<Compilation> getCompilation() {
return Optional.ofNullable(compilation);
}
@Override
public Optional<Integer> getRank() {
return Optional.ofNullable(this.rank);
}
@Override
public Optional<Integer> getMax() {
return Optional.ofNullable(this.max);
}
@Override
public Optional<Duration> getTimeout() {
return Optional.ofNullable(this.timeout);
}
@Override
public Answers getResultType() {
return this.answers;
}
@Override
public Images getImageType() {
return this.images;
}
@Override
public void setResultType(Answers type) {
this.answers = type;
}
@Override
public void setImageType(Images type) {
this.images = type;
}
@Override
public boolean asksLists() {
return this.answers.equals(Answers.LIST);
}
@Override
public boolean asksSet() {
return this.answers.equals(Answers.SET);
}
@Override
public boolean asksCountOnly() {
return this.answers.equals(Answers.COUNT_ONLY);
}
@Override
public ExternalAlgorithmHaltingConditions getExternalHaltingConditions() {
if (this.externalHaltingConditions == null) {
this.externalHaltingConditions = ExternalAlgorithmHaltingConditions.defaultConditions();
}
return this.externalHaltingConditions;
}
@Override
public Optional<Map<DBMSDriverParameters, String>> getDBMSDriverParameters() {
Map<DBMSDriverParameters, String> result = new LinkedHashMap<>();
if (DBMSDriverParameters_URL != null) {
result.put(DBMSDriverParameters.URL, DBMSDriverParameters_URL);
}
if (DBMSDriverParameters_PORT != null) {
result.put(DBMSDriverParameters.PORT, DBMSDriverParameters_PORT);
}
if (DBMSDriverParameters_DATABASE_NAME != null) {
result.put(DBMSDriverParameters.DATABASE_NAME, DBMSDriverParameters_DATABASE_NAME);
}
if (DBMSDriverParameters_USER_NAME != null) {
result.put(DBMSDriverParameters.USER_NAME, DBMSDriverParameters_USER_NAME);
}
if (DBMSDriverParameters_USER_PASSWORD != null) {
result.put(DBMSDriverParameters.USER_PASSWORD, DBMSDriverParameters_USER_PASSWORD);
}
if (DBMSDriverParameters_CLEAR_DB != null) {
result.put(DBMSDriverParameters.CLEAR_DB, DBMSDriverParameters_CLEAR_DB);
}
if (result.isEmpty()) {
return Optional.empty();
} else {
return Optional.of(result);
}
}
/// //////////////////////////////////////
/// / OVERRIDDEN / PUBLIC SETTER METHODS
/// //////////////////////////////////////
@Override
public IAlgorithmParameters setExternalHaltingConditions(ExternalAlgorithmHaltingConditions hc) {
if (parametereSetAtConstruction) {
LOG.error("parameters have been already set ; wrong usage of the method");
}
this.externalHaltingConditions = hc;
this.rank = externalHaltingConditions.rank();
this.timeout = externalHaltingConditions.timeout();
return this;
}
@Override
public IAlgorithmParameters setMax(Integer max) {
this.max = max;
return this;
}
@Override
public IAlgorithmParameters setRank(Integer rank) {
this.rank = rank;
return this;
}
@Override
public IAlgorithmParameters setTimeout(Duration timeout) {
this.timeout = timeout;
return this;
}
/**
* Sets the DB storage type (e.g., PostgreSQL, H2) by matching the input string
* to an enum constant and then calling {@link #setParameter(Enum)}.
*
* @param storageDBTypeName the name of the storage type (e.g., "H2",
* "POSTGRESQL")
* @return this {@link IAlgorithmParameters} instance for method chaining
*/
public IAlgorithmParameters setStorageType(String storageDBTypeName) {
return setParameter(EnumUtils.findEnumFromString(storageDBTypeName, InternalStorageConfiguration.DBType.class));
}
@Override
public IAlgorithmParameters setStorageType(DBType storage) {
return setParameter(storage);
}
/**
* Sets the database driver type (e.g., "JDBC") by matching the input string to
* an enum constant and then calling {@link #setParameter(Enum)}.
*
* @param storageDriverName the name of the driver type
* @return this {@link IAlgorithmParameters} instance for method chaining
*/
public IAlgorithmParameters setDBDriver(String storageDriverName) {
return setParameter(
EnumUtils.findEnumFromString(storageDriverName, InternalStorageConfiguration.DriverType.class));
}
@Override
public IAlgorithmParameters setDBDriver(DriverType storageDriver) {
return setParameter(storageDriver);
}
/**
* Sets the storage layout strategy (e.g., "DEFAULT") by matching the input
* string to an enum constant and then calling {@link #setParameter(Enum)}.
*
* @param storageStrategyName the name of the storage layout
* @return this {@link IAlgorithmParameters} instance for method chaining
*/
public IAlgorithmParameters setDBStrategy(String storageStrategyName) {
return setParameter(
EnumUtils.findEnumFromString(storageStrategyName, InternalStorageConfiguration.StorageLayout.class));
}
@Override
public IAlgorithmParameters setDBStrategy(StorageLayout storageStrategy) {
return setParameter(storageStrategy);
}
/**
* Sets the chase rule applier by matching the input string to an enum constant
* and then calling {@link #setParameter(Enum)}.
*
* @param applierName the name of the rule applier
* @return this {@link IAlgorithmParameters} instance for method chaining
*/
public IAlgorithmParameters setRuleApplier(String applierName) {
return setParameter(
EnumUtils.findEnumFromString(applierName, InteGraalKeywords.Algorithms.Parameters.Chase.Applier.class));
}
@Override
public IAlgorithmParameters setRuleApplier(Applier applier) {
return setParameter(applier);
}
/**
* Sets the scheduler by matching the input string to an enum constant and then
* calling {@link #setParameter(Enum)}.
*
* @param scheduler the name of the scheduler
* @return this {@link IAlgorithmParameters} instance for method chaining
*/
public IAlgorithmParameters setScheduler(String scheduler) {
return setParameter(
EnumUtils.findEnumFromString(scheduler, InteGraalKeywords.Algorithms.Parameters.Chase.Scheduler.class));
}
@Override
public IAlgorithmParameters setScheduler(Scheduler scheduler) {
return setParameter(scheduler);
}
/**
* Sets the chase criterion (checker) by matching the input string to an enum
* constant and then calling {@link #setParameter(Enum)}.
*
* @param criterionName the name of the chase checker
* @return this {@link IAlgorithmParameters} instance for method chaining
*/
public IAlgorithmParameters setCriterion(String criterionName) {
return setParameter(EnumUtils.findEnumFromString(criterionName,
InteGraalKeywords.Algorithms.Parameters.Chase.Checker.class));
}
@Override
public IAlgorithmParameters setCriterion(Checker criterion) {
return setParameter(criterion);
}
/**
* Sets the chase computer by matching the input string to an enum constant and
* then calling {@link #setParameter(Enum)}.
*
* @param computerName the name of the chase computer
* @return this {@link IAlgorithmParameters} instance for method chaining
*/
public IAlgorithmParameters setComputer(String computerName) {
return setParameter(EnumUtils.findEnumFromString(computerName,
InteGraalKeywords.Algorithms.Parameters.Chase.Computer.class));
}
@Override
public IAlgorithmParameters setComputer(Computer computer) {
return setParameter(computer);
}
/**
* Sets the chase Skolemization approach by matching the input string to an enum
* constant and then calling {@link #setParameter(Enum)}.
*
* @param skolemizationName the name of the Skolemization approach
* @return this {@link IAlgorithmParameters} instance for method chaining
*/
public IAlgorithmParameters setSkolemization(String skolemizationName) {
return setParameter(EnumUtils.findEnumFromString(skolemizationName,
InteGraalKeywords.Algorithms.Parameters.Chase.Namer.class));
}
@Override
public IAlgorithmParameters setSkolemization(Namer skolemization) {
return setParameter(skolemization);
}
/**
* Sets the chase evaluator by matching the input string to an enum
* constant and then calling {@link #setParameter(Enum)}.
*
* @param evaluatorName the name of the evaluator
* @return this {@link IAlgorithmParameters} instance for method chaining
*/
public IAlgorithmParameters setEvaluator(String evaluatorName) {
return setParameter(EnumUtils.findEnumFromString(evaluatorName,
InteGraalKeywords.Algorithms.Parameters.Chase.Evaluator.class));
}
@Override
public IAlgorithmParameters setEvaluator(Evaluator evaluator) {
return setParameter(evaluator);
}
/**
* Sets the chase transformer by matching the input string to an enum
* constant and then calling {@link #setParameter(Enum)}.
*
* @param transformerName the name of the transformer
* @return this {@link IAlgorithmParameters} instance for method chaining
*/
public IAlgorithmParameters setTransformer(String transformerName) {
return setParameter(EnumUtils.findEnumFromString(transformerName,
InteGraalKeywords.Algorithms.Parameters.Chase.Transformer.class));
}
@Override
public IAlgorithmParameters setTransformer(Transformer transformer) {
return setParameter(transformer);
}
/**
* Sets the compilation approach (e.g., "DEFAULT") by matching the input string
* to an enum constant and then calling {@link #setParameter(Enum)}.
*
* @param compilationName the name of the compilation type
* @return this {@link IAlgorithmParameters} instance for method chaining
*/
public IAlgorithmParameters setCompilation(String compilationName) {
return setParameter(EnumUtils.findEnumFromString(compilationName,
InteGraalKeywords.Algorithms.Parameters.Compilation.class));
}
@Override
public IAlgorithmParameters setCompilation(Compilation compilation) {
return setParameter(compilation);
}
/**
* Sets a DBMS driver parameter based on the provided parameter name and value.
* The parameter name is mapped to an enum instance of
* {@link DBMSDriverParameters}, and then the appropriate field in this class is
* updated.
*
* @param paramName the name of the DBMS driver parameter, e.g., "URL" or
* "PORT"
* @param paramValue the value to set for the specified parameter
* @throws IllegalArgumentException if {@code paramName} does not match any
* known {@link DBMSDriverParameters} value
* @see #setDBMSDriverParameters(DBMSDriverParameters, String)
*/
public void setDBMSDriverParameters(String paramName, String paramValue) {
setDBMSDriverParameters(EnumUtils.findEnumFromString(paramName, DBMSDriverParameters.class), paramValue);
}
@Override
public IAlgorithmParameters setDBMSDriverParameters(DBMSDriverParameters paramName, String value) {
switch (paramName) {
case DATABASE_NAME -> this.DBMSDriverParameters_DATABASE_NAME = value;
case PORT -> this.DBMSDriverParameters_PORT = value;
case URL -> this.DBMSDriverParameters_URL = value;
case USER_NAME -> this.DBMSDriverParameters_USER_NAME = value;
case USER_PASSWORD -> this.DBMSDriverParameters_USER_PASSWORD = value;
case CLEAR_DB -> this.DBMSDriverParameters_CLEAR_DB = value;
default -> throw new IllegalArgumentException("Unexpected parameter: " + paramName);
}
return this;
}
/////////////////////////////////////////
//// PRIVATE / HELPER METHODS
/////////////////////////////////////////
/**
* Iterates over the provided {@code params}, handling each based on its
* category (enumeration, open parameter from an enumeration, or open
* parameter).
*
* @param params one or more {@link IGParameter} objects that define parameter
* names and values
* @return {@code true} if all parameters were handled successfully;
* {@code false} if an unrecognized parameter was encountered
*/
@SuppressWarnings("unchecked")
private boolean setParams(IGParameter<InteGraalKeywords, ?>... params) {
for (var param : params) {
switch (param.name()) {
// enumeration with closed set of values
case InteGraalKeywords k when k.isEnumeration() -> setParameter((Enum<?>) param.value());
// open set of values, but defined within an enumeration (e.g.,
// DBConnectionParams)
case InteGraalKeywords k when !k.isEnumeration() && k.getParentEnum().isPresent() ->
setOpenParameterFromEnumeration(k.getParentEnum().get(), param.name().toString(),
param.value().toString());
// open set of values (e.g., Rank, Timeout)
case InteGraalKeywords k when !k.isEnumeration() && !k.getParentEnum().isPresent() ->
setOpenParameter(k, param.value());
default -> {
LOG.error("Cannot handle parameter " + param);
return false;
}
}
}
return true;
}
/**
* Sets the value of a parameter based on the provided enum constant. This
* method uses reflection to dynamically identify and set the field within this
* class that corresponds to the enum type of the given constant. The field name
* is expected to match the simple name of the enum's class, with the first
* letter lowercased (following Java naming conventions)
*
* @param enumValue The enum constant to set as the value of the corresponding
* field. The enum's class simple name (lowercased) should
* match the name of the field in this class.
* @throws RuntimeException If no matching field is found for the enum type, or
* if an error occurs while attempting to set the
* field's value. This includes cases where the field
* is not accessible or if the field name does not
* match the expected naming convention.
* @see Field#setAccessible(boolean)
*/
public IAlgorithmParameters setParameter(Enum<?> enumValue) {
LOG.debug("Setting parameter {} for {}", enumValue, this.name);
validateParameter(enumValue);
String fieldName = enumValue.getClass().getSimpleName();
try {
Field field = null;
for (Field f : this.getClass().getDeclaredFields()) {
if (fieldName.equalsIgnoreCase(f.getName())) {
field = f;
break;
}
}
if (field == null) {
LOG.error("Cannot set parameter {}", enumValue);
throw new RuntimeException(
String.format("[%s::setParameter] Cannot set parameter: %s.", this.getClass(), enumValue));
} else {
field.setAccessible(true);
field.set(this, enumValue);
}
} catch (IllegalAccessException e) {
LOG.error("Failed to set parameter: {}\n{}", fieldName, e.getMessage());
throw new RuntimeException(
String.format("[%s::setParameter] Failed to set parameter: %s.", this.getClass(), fieldName), e);
}
return this;
}
/**
* Sets an open parameter (defined within a known enumeration) by mapping the
* given {@code propertyName} to the appropriate enum constant in
* {@code className}, and assigning the provided {@code value}.
* <p>
* Currently, this is primarily used for {@code DBMSDriverParameters}.
* </p>
*
* @param className the enum's class, e.g.,
* {@code DBMSDriverParameters.class}
* @param propertyName the name of the enum constant, e.g., "URL" or "USER_NAME"
* @param value the string value to assign to this parameter
* @return this {@link IAlgorithmParameters} instance for method chaining
* @throws IllegalArgumentException if {@code propertyName} does not match any
* known constant in {@code className}
*/
public IAlgorithmParameters setOpenParameterFromEnumeration(Class<? extends Enum<?>> className, String propertyName,
String value) {
LOG.debug("Setting parameter {} for {} with value {} for {} ", propertyName, className.getSimpleName(), value,
this.name);
switch (className.getSimpleName().toUpperCase()) {
case "DBMSDRIVERPARAMETERS" -> setDBMSDriverParameters(propertyName, value);
default -> throw new IllegalArgumentException("Unexpected value: " + className);
}
return this;
}
/**
* Similar to {@link #setOpenParameterFromEnumeration(Class, String, String)},
* but takes an {@code enumName} instead of the enum {@code className}. This
* method is used to handle open parameters where the parent enumeration is
* already determined.
*
* @param enumName the enumeration constant representing the parameter
* category
* @param propertyName the name of the specific parameter within that category
* @param value the string value to assign to the parameter
* @return this {@link IAlgorithmParameters} instance for method chaining
* @throws IllegalArgumentException if {@code propertyName} does not match any
* recognized constant for the given
* {@code enumName}
*/
public IAlgorithmParameters setOpenParameterFromEnumeration(Enum<?> enumName, String propertyName, String value) {
LOG.debug("Setting parameter {} for {} with value {} for {} ", propertyName, enumName.name(), value, this.name);
switch (enumName.name().toUpperCase()) {
case "DBMSDRIVERPARAMETERS" -> setDBMSDriverParameters(propertyName, value);
default -> throw new IllegalArgumentException("Unexpected value: " + enumName);
}
return this;
}
/**
* Sets an open parameter (one that is not tied to a closed enumeration of
* values) by matching its name to one of the fields declared in this class. If
* found, the field is updated with the provided {@code value}.
*
* @param k the keyword representing the parameter name
* @param value the value to set (type {@code Object} because parameters can
* vary)
* @return this {@link IAlgorithmParameters} instance for method chaining
* @throws RuntimeException if the parameter field cannot be found or set
* @see Field#setAccessible(boolean)
*/
public IAlgorithmParameters setOpenParameter(InteGraalKeywords k, Object value) {
LOG.debug("Setting parameter {} with value {} for {}", k, value, this.name);
String fieldName = k.name();
try {
Field field = null;
for (Field f : this.getClass().getDeclaredFields()) {
if (fieldName.equalsIgnoreCase(f.getName())) {
field = f;
break;
}
}
if (field == null) {
LOG.error("Cannot set parameter {}", k);
throw new RuntimeException(
String.format("[%s::setParameter] Cannot set parameter: %s.", this.getClass(), value));
} else {
field.setAccessible(true);
field.set(this, value);
}
} catch (IllegalAccessException e) {
LOG.error("Failed to set parameter: {}\n{}", k, e.getMessage());
throw new RuntimeException(
String.format("[%s::setParameter] Failed to set parameter: %s.", this.getClass(), k), e);
}
return this;
}
/**
* Validates whether the specified enum value is allowable based on the current
* algorithm's capabilities. For example, chase parameters cannot be used with
* an algorithm that does not support chase.
*
* @param enumValue the enum constant to validate
* @throws IllegalArgumentException if the enum value is incompatible with the
* current algorithm
*/
private void validateParameter(Enum<?> enumValue) {
if (enumValue.getClass().getEnclosingClass() == InteGraalKeywords.Algorithms.Parameters.Chase.class
&& !usesSaturationAlgorithm()) {
throw new IllegalArgumentException(
"Chase parameter " + enumValue + " cannot be set for " + getAlgorithm() + " algorithms.");
}
if (enumValue.getClass().getEnclosingClass() == InteGraalKeywords.Algorithms.Parameters.Compilation.class
&& !usesRuleCompilationAlgorithm()) {
throw new IllegalArgumentException(
"Compilation parameter " + enumValue + " cannot be set for " + getAlgorithm() + " algorithms.");
}
if (enumValue.getClass().getEnclosingClass() == InteGraalKeywords.InternalStorageConfiguration.class
&& !usesStorage()) {
throw new IllegalArgumentException(
"Storage parameter " + enumValue + " cannot be set for " + getAlgorithm() + " algorithms.");
}
}
private void initDefaultValues() {
this.answers = Answers.SET;
this.max = 1_000_000;
this.rank = 1_00_00;
this.timeout = Duration.ofHours(1);
}
/////////////////////////////////////////
//// toString()
/////////////////////////////////////////
/**
* Returns a string representation of this {@code AlgorithmParameters} object,
* which includes key fields and values.
*
* @return a string describing the fields in this class
*/
public String toString() {
return StringUtils.print(this);
}
@Override
public Optional<Algorithms.Parameters.Explanation> getExplanation() {
return Optional.ofNullable(explanation);
}
@Override
public IAlgorithmParameters setExplanationCategory(Algorithms.Parameters.Explanation explanationCategory) {
this.explanation =explanationCategory;
return this;
}
@Override
public Optional<ExplainerSolver> getExplainerSolver() {
return Optional.ofNullable(explainerSolver);
}
@Override
public IAlgorithmParameters setExplainerSolver(ExplainerSolver solver) {
this.explainerSolver = solver;
return this;
}
@Override
public Optional<ExplanationSupportType> getExplanationSupportType() {
return Optional.ofNullable(explanationSupportType);
}
@Override
public IAlgorithmParameters setExplanationSupportType(ExplanationSupportType explanationSupportType) {
this.explanationSupportType = explanationSupportType;
return this;
}
@Override
public Optional<ExplainerVerbosity> getExplainerVerbosity() {
return Optional.ofNullable(this.explainerVerbosity);
}
@Override
public IAlgorithmParameters setExplainerVerbosity(ExplainerVerbosity verbosity) {
this.explainerVerbosity = verbosity;
return this;
}
@Override
public Optional<GraphOfRuleInstancesType> getGraphOfRuleInstancesType() {
return Optional.ofNullable(this.graphOfRuleInstancesType);
}
@Override
public IAlgorithmParameters setGraphOfRuleInstancesType(GraphOfRuleInstancesType griType) {
this.graphOfRuleInstancesType = griType;
return this;
}
@Override
public Optional<GraphOfRuleInstancesComputation> getGraphOfRuleInstancesComputation() {
return Optional.ofNullable(this.graphOfRuleInstancesComputation);
}
@Override
public IAlgorithmParameters setGraphOfRuleInstancesType(GraphOfRuleInstancesComputation griComputation) {
this.graphOfRuleInstancesComputation = griComputation;
return this;
}
/// //////////////////////////////////////
/// / FIELDS
/// //////////////////////////////////////
static final Logger LOG = LoggerFactory.getLogger(AlgorithmParameters.class);
private final boolean parametereSetAtConstruction;
// Core configuration fields
private final Algorithms algorithm;
protected final String name;
// Closed parameters from enumeration
// chase
private Scheduler scheduler;
private Checker checker;
private Computer computer;
private Applier applier;
private Namer skolem;
private Evaluator evaluator; // added by Michel
private Transformer transformer; // added by Michel
// TODO check transfer of IntegralParameters to AlgorithmParameters
// storage
private DBType dbtype;
private DriverType driverType;
private StorageLayout storageLayout;
// query rewriting
private Compilation compilation;
// Open parameters, with names defined from a parent enumeration
// database
private String DBMSDriverParameters_URL;
private String DBMSDriverParameters_PORT;
private String DBMSDriverParameters_DATABASE_NAME;
private String DBMSDriverParameters_USER_NAME;
private String DBMSDriverParameters_USER_PASSWORD;
private String DBMSDriverParameters_CLEAR_DB;
// Open parameters, with names not defined from a parent enumeration
private Integer max;
private Integer rank;
private Duration timeout;
// query answering
private Answers answers;
private Images images;
// Alternative for setting timeout and rank
private ExternalAlgorithmHaltingConditions externalHaltingConditions;
private ExplainerVerbosity explainerVerbosity;
private ExplainerSolver explainerSolver;
private GraphOfRuleInstancesComputation graphOfRuleInstancesComputation;
private ExplanationSupportType explanationSupportType;
private GraphOfRuleInstancesType graphOfRuleInstancesType;
private Algorithms.Parameters.Explanation explanation;
private Integer GSATSolverParameters_SMART_SOLVER_TRESHOLD;
private String GSATSolverParameters_MARCO_PATH_TO_EXECUTABLE;
/////////////////////////////////////////
//// CONSTRUCTORS
/////////////////////////////////////////
/**
* Constructs a new {@code AlgorithmParameters} instance.
*
* @param name the name of the configuration
* @param algorithmType the algorithm type (e.g., KB_CHASE, OMQA_CHASE)
*/
public AlgorithmParameters(String name, Algorithms algorithmType) {
this.name = name;
this.algorithm = algorithmType;
this.parametereSetAtConstruction = false;
initDefaultValues();
}
/**
* Constructs a new {@code AlgorithmParameters} instance and immediately sets
* parameters from the specified {@link IGParameter} object.
*
* @param name the name of the configuration
* @param algorithmType the algorithm type
* @param params an {@code IGParameter} containing parameter metadata
*/
public AlgorithmParameters(String name, Algorithms algorithmType, IGParameter<InteGraalKeywords, ?>... params) {
this.name = name;
this.algorithm = algorithmType;
initDefaultValues();
this.parametereSetAtConstruction = setParams(params);
}
/////////////////////////////////////////
//// OVERRIDDEN / PUBLIC METHODS
/////////////////////////////////////////
/**
* Returns the name of the configuration concatenated with the algorithm name.
*
* @return the name of the configuration (e.g., "MyConfig_OMQA_CHASE")
*/
public String getName() {
return this.name + "_" + this.algorithm.toString();
}
/**
* Returns the current algorithm type.
*
* @return the current {@link InteGraalKeywords.Algorithms} enum value
*/
public InteGraalKeywords.Algorithms getAlgorithm() {
return algorithm;
}
@Override
public boolean usesSaturationAlgorithm() {
return algorithm.equals(InteGraalKeywords.Algorithms.KB_CHASE)
|| algorithm.equals(InteGraalKeywords.Algorithms.OMQA_CHASE)
|| algorithm.equals(InteGraalKeywords.Algorithms.QUERY_ANSWERING_VIA_HYBRID_STRATEGY);
}
@Override
public boolean usesQueryRewritingAlgorithm() {
return algorithm.equals(InteGraalKeywords.Algorithms.OMQ_REWRITING)
|| algorithm.equals(InteGraalKeywords.Algorithms.OMQA_REW);
}
@Override
public boolean usesQueryAnsweringAlgorithm() {
return algorithm.equals(InteGraalKeywords.Algorithms.QUERY_ANSWERING);
}
@Override
public boolean usesRuleCompilationAlgorithm() {
return algorithm.equals(InteGraalKeywords.Algorithms.RULE_COMPILATION) || usesQueryRewritingAlgorithm();
}
@Override
public boolean usesOMQASaturationAlgorithm() {
return algorithm.equals(InteGraalKeywords.Algorithms.OMQA_CHASE);
}
@Override
public boolean usesOMQARewritingAlgorithm() {
return algorithm.equals(InteGraalKeywords.Algorithms.OMQA_REW);
}
@Override
public boolean usesOMQAHybridAlgorithm() {
return algorithm.equals(InteGraalKeywords.Algorithms.QUERY_ANSWERING_VIA_HYBRID_STRATEGY);
}
@Override
public boolean usesStorage() {
return usesSaturationAlgorithm() || usesQueryAnsweringAlgorithm() || usesOMQASaturationAlgorithm()
|| usesOMQARewritingAlgorithm() || usesOMQAHybridAlgorithm();
}
@Override
public Optional<Applier> getRuleApplier() {
return Optional.ofNullable(applier);
}
@Override
public Optional<Scheduler> getScheduler() {
return Optional.ofNullable(scheduler);
}
@Override
public Optional<Checker> getCriterion() {
return Optional.ofNullable(checker);
}
@Override
public Optional<Computer> getComputer() {
return Optional.ofNullable(computer);
}
@Override
public Optional<Namer> getSkolemization() {
return Optional.ofNullable(skolem);
}
@Override
public Optional<Evaluator> getEvaluator() {
return Optional.ofNullable(evaluator);
}
@Override
public Optional<Transformer> getTransformer() {
return Optional.ofNullable(transformer);
}
@Override
public Optional<DBType> getStorageType() {
return Optional.ofNullable(dbtype);
}
@Override
public Optional<DriverType> getDBDriver() {
return Optional.ofNullable(driverType);
}
@Override
public Optional<StorageLayout> getDBStrategy() {
return Optional.ofNullable(storageLayout);
}
@Override
public Optional<Compilation> getCompilation() {
return Optional.ofNullable(compilation);
}
@Override
public Optional<Integer> getRank() {
return Optional.ofNullable(this.rank);
}
@Override
public Optional<Integer> getMax() {
return Optional.ofNullable(this.max);
}
@Override
public Optional<Duration> getTimeout() {
return Optional.ofNullable(this.timeout);
}
@Override
public Answers getResultType() {
return this.answers;
}
@Override
public Images getImageType() {
return this.images;
}
@Override
public void setResultType(Answers type) {
this.answers = type;
}
@Override
public void setImageType(Images type) {
this.images = type;
}
@Override
public boolean asksLists() {
return this.answers.equals(Answers.LIST);
}
@Override
public boolean asksSet() {
return this.answers.equals(Answers.SET);
}
@Override
public boolean asksCountOnly() {
return this.answers.equals(Answers.COUNT_ONLY);
}
@Override
public ExternalAlgorithmHaltingConditions getExternalHaltingConditions() {
if (this.externalHaltingConditions == null) {
this.externalHaltingConditions = ExternalAlgorithmHaltingConditions.defaultConditions();
}
return this.externalHaltingConditions;
}
@Override
public Optional<Map<DBMSDriverParameters, String>> getDBMSDriverParameters() {
Map<DBMSDriverParameters, String> result = new LinkedHashMap<>();
if (DBMSDriverParameters_URL != null) {
result.put(DBMSDriverParameters.URL, DBMSDriverParameters_URL);
}
if (DBMSDriverParameters_PORT != null) {
result.put(DBMSDriverParameters.PORT, DBMSDriverParameters_PORT);
}
if (DBMSDriverParameters_DATABASE_NAME != null) {
result.put(DBMSDriverParameters.DATABASE_NAME, DBMSDriverParameters_DATABASE_NAME);
}
if (DBMSDriverParameters_USER_NAME != null) {
result.put(DBMSDriverParameters.USER_NAME, DBMSDriverParameters_USER_NAME);
}
if (DBMSDriverParameters_USER_PASSWORD != null) {
result.put(DBMSDriverParameters.USER_PASSWORD, DBMSDriverParameters_USER_PASSWORD);
}
if (DBMSDriverParameters_CLEAR_DB != null) {
result.put(DBMSDriverParameters.CLEAR_DB, DBMSDriverParameters_CLEAR_DB);
}
if (result.isEmpty()) {
return Optional.empty();
} else {
return Optional.of(result);
}
}
/// //////////////////////////////////////
/// / OVERRIDDEN / PUBLIC SETTER METHODS
/// //////////////////////////////////////
@Override
public IAlgorithmParameters setExternalHaltingConditions(ExternalAlgorithmHaltingConditions hc) {
if (parametereSetAtConstruction) {
LOG.error("parameters have been already set ; wrong usage of the method");
}
this.externalHaltingConditions = hc;
this.rank = externalHaltingConditions.rank();
this.timeout = externalHaltingConditions.timeout();
return this;
}
@Override
public IAlgorithmParameters setMax(Integer max) {
this.max = max;
return this;
}
@Override
public IAlgorithmParameters setRank(Integer rank) {
this.rank = rank;
return this;
}
@Override
public IAlgorithmParameters setTimeout(Duration timeout) {
this.timeout = timeout;
return this;
}
/**
* Sets the DB storage type (e.g., PostgreSQL, H2) by matching the input string
* to an enum constant and then calling {@link #setParameter(Enum)}.
*
* @param storageDBTypeName the name of the storage type (e.g., "H2",
* "POSTGRESQL")
* @return this {@link IAlgorithmParameters} instance for method chaining
*/
public IAlgorithmParameters setStorageType(String storageDBTypeName) {
return setParameter(EnumUtils.findEnumFromString(storageDBTypeName, InternalStorageConfiguration.DBType.class));
}
@Override
public IAlgorithmParameters setStorageType(DBType storage) {
return setParameter(storage);
}
/**
* Sets the database driver type (e.g., "JDBC") by matching the input string to
* an enum constant and then calling {@link #setParameter(Enum)}.
*
* @param storageDriverName the name of the driver type
* @return this {@link IAlgorithmParameters} instance for method chaining
*/
public IAlgorithmParameters setDBDriver(String storageDriverName) {
return setParameter(
EnumUtils.findEnumFromString(storageDriverName, InternalStorageConfiguration.DriverType.class));
}
@Override
public IAlgorithmParameters setDBDriver(DriverType storageDriver) {
return setParameter(storageDriver);
}
/**
* Sets the storage layout strategy (e.g., "DEFAULT") by matching the input
* string to an enum constant and then calling {@link #setParameter(Enum)}.
*
* @param storageStrategyName the name of the storage layout
* @return this {@link IAlgorithmParameters} instance for method chaining
*/
public IAlgorithmParameters setDBStrategy(String storageStrategyName) {
return setParameter(
EnumUtils.findEnumFromString(storageStrategyName, InternalStorageConfiguration.StorageLayout.class));
}
@Override
public IAlgorithmParameters setDBStrategy(StorageLayout storageStrategy) {
return setParameter(storageStrategy);
}
/**
* Sets the chase rule applier by matching the input string to an enum constant
* and then calling {@link #setParameter(Enum)}.
*
* @param applierName the name of the rule applier
* @return this {@link IAlgorithmParameters} instance for method chaining
*/
public IAlgorithmParameters setRuleApplier(String applierName) {
return setParameter(
EnumUtils.findEnumFromString(applierName, InteGraalKeywords.Algorithms.Parameters.Chase.Applier.class));
}
@Override
public IAlgorithmParameters setRuleApplier(Applier applier) {
return setParameter(applier);
}
/**
* Sets the scheduler by matching the input string to an enum constant and then
* calling {@link #setParameter(Enum)}.
*
* @param scheduler the name of the scheduler
* @return this {@link IAlgorithmParameters} instance for method chaining
*/
public IAlgorithmParameters setScheduler(String scheduler) {
return setParameter(
EnumUtils.findEnumFromString(scheduler, InteGraalKeywords.Algorithms.Parameters.Chase.Scheduler.class));
}
@Override
public IAlgorithmParameters setScheduler(Scheduler scheduler) {
return setParameter(scheduler);
}
/**
* Sets the chase criterion (checker) by matching the input string to an enum
* constant and then calling {@link #setParameter(Enum)}.
*
* @param criterionName the name of the chase checker
* @return this {@link IAlgorithmParameters} instance for method chaining
*/
public IAlgorithmParameters setCriterion(String criterionName) {
return setParameter(EnumUtils.findEnumFromString(criterionName,
InteGraalKeywords.Algorithms.Parameters.Chase.Checker.class));
}
@Override
public IAlgorithmParameters setCriterion(Checker criterion) {
return setParameter(criterion);
}
/**
* Sets the chase computer by matching the input string to an enum constant and
* then calling {@link #setParameter(Enum)}.
*
* @param computerName the name of the chase computer
* @return this {@link IAlgorithmParameters} instance for method chaining
*/
public IAlgorithmParameters setComputer(String computerName) {
return setParameter(EnumUtils.findEnumFromString(computerName,
InteGraalKeywords.Algorithms.Parameters.Chase.Computer.class));
}
@Override
public IAlgorithmParameters setComputer(Computer computer) {
return setParameter(computer);
}
/**
* Sets the chase Skolemization approach by matching the input string to an enum
* constant and then calling {@link #setParameter(Enum)}.
*
* @param skolemizationName the name of the Skolemization approach
* @return this {@link IAlgorithmParameters} instance for method chaining
*/
public IAlgorithmParameters setSkolemization(String skolemizationName) {
return setParameter(EnumUtils.findEnumFromString(skolemizationName,
InteGraalKeywords.Algorithms.Parameters.Chase.Namer.class));
}
@Override
public IAlgorithmParameters setSkolemization(Namer skolemization) {
return setParameter(skolemization);
}
/**
* Sets the chase evaluator by matching the input string to an enum
* constant and then calling {@link #setParameter(Enum)}.
*
* @param evaluatorName the name of the evaluator
* @return this {@link IAlgorithmParameters} instance for method chaining
*/
public IAlgorithmParameters setEvaluator(String evaluatorName) {
return setParameter(EnumUtils.findEnumFromString(evaluatorName,
InteGraalKeywords.Algorithms.Parameters.Chase.Evaluator.class));
}
@Override
public IAlgorithmParameters setEvaluator(Evaluator evaluator) {
return setParameter(evaluator);
}
/**
* Sets the chase transformer by matching the input string to an enum
* constant and then calling {@link #setParameter(Enum)}.
*
* @param transformerName the name of the transformer
* @return this {@link IAlgorithmParameters} instance for method chaining
*/
public IAlgorithmParameters setTransformer(String transformerName) {
return setParameter(EnumUtils.findEnumFromString(transformerName,
InteGraalKeywords.Algorithms.Parameters.Chase.Transformer.class));
}
@Override
public IAlgorithmParameters setTransformer(Transformer transformer) {
return setParameter(transformer);
}
/**
* Sets the compilation approach (e.g., "DEFAULT") by matching the input string
* to an enum constant and then calling {@link #setParameter(Enum)}.
*
* @param compilationName the name of the compilation type
* @return this {@link IAlgorithmParameters} instance for method chaining
*/
public IAlgorithmParameters setCompilation(String compilationName) {
return setParameter(EnumUtils.findEnumFromString(compilationName,
InteGraalKeywords.Algorithms.Parameters.Compilation.class));
}
@Override
public IAlgorithmParameters setCompilation(Compilation compilation) {
return setParameter(compilation);
}
/**
* Sets a DBMS driver parameter based on the provided parameter name and value.
* The parameter name is mapped to an enum instance of
* {@link DBMSDriverParameters}, and then the appropriate field in this class is
* updated.
*
* @param paramName the name of the DBMS driver parameter, e.g., "URL" or
* "PORT"
* @param paramValue the value to set for the specified parameter
* @throws IllegalArgumentException if {@code paramName} does not match any
* known {@link DBMSDriverParameters} value
* @see #setDBMSDriverParameters(DBMSDriverParameters, String)
*/
public void setDBMSDriverParameters(String paramName, String paramValue) {
setDBMSDriverParameters(EnumUtils.findEnumFromString(paramName, DBMSDriverParameters.class), paramValue);
}
public void setGSATSolverParameters(String paramName, String paramValue) {
setGSATSolverParameters(EnumUtils.findEnumFromString(paramName, GSATSolverParameters.class), paramValue);
}
@Override
public IAlgorithmParameters setDBMSDriverParameters(DBMSDriverParameters paramName, String value) {
switch (paramName) {
case DATABASE_NAME -> this.DBMSDriverParameters_DATABASE_NAME = value;
case PORT -> this.DBMSDriverParameters_PORT = value;
case URL -> this.DBMSDriverParameters_URL = value;
case USER_NAME -> this.DBMSDriverParameters_USER_NAME = value;
case USER_PASSWORD -> this.DBMSDriverParameters_USER_PASSWORD = value;
case CLEAR_DB -> this.DBMSDriverParameters_CLEAR_DB = value;
default -> throw new IllegalArgumentException("Unexpected parameter: " + paramName);
}
return this;
}
@Override
public IAlgorithmParameters setGSATSolverParameters(GSATSolverParameters paramName, String value) {
switch (paramName) {
case SMART_SOLVER_TRESHOLD -> this.GSATSolverParameters_SMART_SOLVER_TRESHOLD = Integer.parseInt(value);
case MARCO_PATH_TO_EXECUTABLE -> this.GSATSolverParameters_MARCO_PATH_TO_EXECUTABLE = value;
default -> throw new IllegalArgumentException("Unexpected parameter: " + paramName);
}
return this;
}
@Override
public Optional<String> getMARCOPathToExecutable() {
return Optional.ofNullable(this.GSATSolverParameters_MARCO_PATH_TO_EXECUTABLE);
}
@Override
public IAlgorithmParameters setMARCOPathToExecutable(String pathtoExecutable) {
this.GSATSolverParameters_MARCO_PATH_TO_EXECUTABLE = pathtoExecutable;
return this;
}
/////////////////////////////////////////
//// PRIVATE / HELPER METHODS
/////////////////////////////////////////
/**
* Iterates over the provided {@code params}, handling each based on its
* category (enumeration, open parameter from an enumeration, or open
* parameter).
*
* @param params one or more {@link IGParameter} objects that define parameter
* names and values
* @return {@code true} if all parameters were handled successfully;
* {@code false} if an unrecognized parameter was encountered
*/
@SuppressWarnings("unchecked")
private boolean setParams(IGParameter<InteGraalKeywords, ?>... params) {
for (var param : params) {
switch (param.name()) {
// enumeration with closed set of values
case InteGraalKeywords k when k.isEnumeration() -> setParameter((Enum<?>) param.value());
// open set of values, but defined within an enumeration (e.g.,
// DBConnectionParams)
case InteGraalKeywords k when !k.isEnumeration() && k.getParentEnum().isPresent() ->
setOpenParameterFromEnumeration(k.getParentEnum().get(), param.name().toString(),
param.value().toString());
// open set of values (e.g., Rank, Timeout)
case InteGraalKeywords k when !k.isEnumeration() && !k.getParentEnum().isPresent() ->
setOpenParameter(k, param.value());
default -> {
LOG.error("Cannot handle parameter " + param);
return false;
}
}
}
return true;
}
/**
* Sets the value of a parameter based on the provided enum constant. This
* method uses reflection to dynamically identify and set the field within this
* class that corresponds to the enum type of the given constant. The field name
* is expected to match the simple name of the enum's class, with the first
* letter lowercased (following Java naming conventions)
*
* @param enumValue The enum constant to set as the value of the corresponding
* field. The enum's class simple name (lowercased) should
* match the name of the field in this class.
* @throws RuntimeException If no matching field is found for the enum type, or
* if an error occurs while attempting to set the
* field's value. This includes cases where the field
* is not accessible or if the field name does not
* match the expected naming convention.
* @see Field#setAccessible(boolean)
*/
public IAlgorithmParameters setParameter(Enum<?> enumValue) {
LOG.debug("Setting parameter {} for {}", enumValue, this.name);
validateParameter(enumValue);
String fieldName = enumValue.getClass().getSimpleName();
try {
Field field = null;
for (Field f : this.getClass().getDeclaredFields()) {
if (fieldName.equalsIgnoreCase(f.getName())) {
field = f;
break;
}
}
if (field == null) {
LOG.error("Cannot set parameter {}", enumValue);
throw new RuntimeException(
String.format("[%s::setParameter] Cannot set parameter: %s.", this.getClass(), enumValue));
} else {
field.setAccessible(true);
field.set(this, enumValue);
}
} catch (IllegalAccessException e) {
LOG.error("Failed to set parameter: {}\n{}", fieldName, e.getMessage());
throw new RuntimeException(
String.format("[%s::setParameter] Failed to set parameter: %s.", this.getClass(), fieldName), e);
}
return this;
}
/**
* Sets an open parameter (defined within a known enumeration) by mapping the
* given {@code propertyName} to the appropriate enum constant in
* {@code className}, and assigning the provided {@code value}.
* <p>
* Currently, this is primarily used for {@code DBMSDriverParameters}.
* </p>
*
* @param className the enum's class, e.g.,
* {@code DBMSDriverParameters.class}
* @param propertyName the name of the enum constant, e.g., "URL" or "USER_NAME"
* @param value the string value to assign to this parameter
* @return this {@link IAlgorithmParameters} instance for method chaining
* @throws IllegalArgumentException if {@code propertyName} does not match any
* known constant in {@code className}
*/
public IAlgorithmParameters setOpenParameterFromEnumeration(Class<? extends Enum<?>> className, String propertyName,
String value) {
LOG.debug("Setting parameter {} for {} with value {} for {} ", propertyName, className.getSimpleName(), value,
this.name);
switch (className.getSimpleName().toUpperCase()) {
case "DBMSDRIVERPARAMETERS" -> setDBMSDriverParameters(propertyName, value);
case "GSATSOLVERPARAMETERS" -> setGSATSolverParameters(propertyName, value);
default -> throw new IllegalArgumentException("Unexpected value: " + className);
}
return this;
}
/**
* Similar to {@link #setOpenParameterFromEnumeration(Class, String, String)},
* but takes an {@code enumName} instead of the enum {@code className}. This
* method is used to handle open parameters where the parent enumeration is
* already determined.
*
* @param enumName the enumeration constant representing the parameter
* category
* @param propertyName the name of the specific parameter within that category
* @param value the string value to assign to the parameter
* @return this {@link IAlgorithmParameters} instance for method chaining
* @throws IllegalArgumentException if {@code propertyName} does not match any
* recognized constant for the given
* {@code enumName}
*/
public IAlgorithmParameters setOpenParameterFromEnumeration(Enum<?> enumName, String propertyName, String value) {
LOG.debug("Setting parameter {} for {} with value {} for {} ", propertyName, enumName.name(), value, this.name);
switch (enumName.name().toUpperCase()) {
case "DBMSDRIVERPARAMETERS" -> setDBMSDriverParameters(propertyName, value);
default -> throw new IllegalArgumentException("Unexpected value: " + enumName);
}
return this;
}
/**
* Sets an open parameter (one that is not tied to a closed enumeration of
* values) by matching its name to one of the fields declared in this class. If
* found, the field is updated with the provided {@code value}.
*
* @param k the keyword representing the parameter name
* @param value the value to set (type {@code Object} because parameters can
* vary)
* @return this {@link IAlgorithmParameters} instance for method chaining
* @throws RuntimeException if the parameter field cannot be found or set
* @see Field#setAccessible(boolean)
*/
public IAlgorithmParameters setOpenParameter(InteGraalKeywords k, Object value) {
LOG.debug("Setting parameter {} with value {} for {}", k, value, this.name);
String fieldName = k.name();
try {
Field field = null;
for (Field f : this.getClass().getDeclaredFields()) {
if (fieldName.equalsIgnoreCase(f.getName())) {
field = f;
break;
}
}
if (field == null) {
LOG.error("Cannot set parameter {}", k);
throw new RuntimeException(
String.format("[%s::setParameter] Cannot set parameter: %s.", this.getClass(), value));
} else {
field.setAccessible(true);
field.set(this, value);
}
} catch (IllegalAccessException e) {
LOG.error("Failed to set parameter: {}\n{}", k, e.getMessage());
throw new RuntimeException(
String.format("[%s::setParameter] Failed to set parameter: %s.", this.getClass(), k), e);
}
return this;
}
/**
* Validates whether the specified enum value is allowable based on the current
* algorithm's capabilities. For example, chase parameters cannot be used with
* an algorithm that does not support chase.
*
* @param enumValue the enum constant to validate
* @throws IllegalArgumentException if the enum value is incompatible with the
* current algorithm
*/
private void validateParameter(Enum<?> enumValue) {
if (enumValue.getClass().getEnclosingClass() == InteGraalKeywords.Algorithms.Parameters.Chase.class
&& !usesSaturationAlgorithm()) {
throw new IllegalArgumentException(
"Chase parameter " + enumValue + " cannot be set for " + getAlgorithm() + " algorithms.");
}
if (enumValue.getClass().getEnclosingClass() == InteGraalKeywords.Algorithms.Parameters.Compilation.class
&& !usesRuleCompilationAlgorithm()) {
throw new IllegalArgumentException(
"Compilation parameter " + enumValue + " cannot be set for " + getAlgorithm() + " algorithms.");
}
if (enumValue.getClass().getEnclosingClass() == InteGraalKeywords.InternalStorageConfiguration.class
&& !usesStorage()) {
throw new IllegalArgumentException(
"Storage parameter " + enumValue + " cannot be set for " + getAlgorithm() + " algorithms.");
}
}
private void initDefaultValues() {
this.answers = Answers.SET;
this.max = 1_000_000;
this.rank = 1_00_00;
this.timeout = Duration.ofHours(1);
}
/////////////////////////////////////////
//// toString()
/////////////////////////////////////////
/**
* Returns a string representation of this {@code AlgorithmParameters} object,
* which includes key fields and values.
*
* @return a string describing the fields in this class
*/
public String toString() {
return StringUtils.print(this);
}
@Override
public Optional<Algorithms.Parameters.Explanation> getExplanation() {
return Optional.ofNullable(explanation);
}
@Override
public IAlgorithmParameters setExplanationCategory(Algorithms.Parameters.Explanation explanationCategory) {
this.explanation = explanationCategory;
return this;
}
@Override
public Optional<ExplainerSolver> getExplainerSolver() {
return Optional.ofNullable(explainerSolver);
}
@Override
public IAlgorithmParameters setExplainerSolver(ExplainerSolver solver) {
this.explainerSolver = solver;
return this;
}
@Override
public Optional<ExplanationSupportType> getExplanationSupportType() {
return Optional.ofNullable(explanationSupportType);
}
@Override
public IAlgorithmParameters setExplanationSupportType(ExplanationSupportType explanationSupportType) {
this.explanationSupportType = explanationSupportType;
return this;
}
@Override
public Optional<ExplainerVerbosity> getExplainerVerbosity() {
return Optional.ofNullable(this.explainerVerbosity);
}
@Override
public IAlgorithmParameters setExplainerVerbosity(ExplainerVerbosity verbosity) {
this.explainerVerbosity = verbosity;
return this;
}
@Override
public Optional<GraphOfRuleInstancesType> getGraphOfRuleInstancesType() {
return Optional.ofNullable(this.graphOfRuleInstancesType);
}
@Override
public IAlgorithmParameters setGraphOfRuleInstancesType(GraphOfRuleInstancesType griType) {
this.graphOfRuleInstancesType = griType;
return this;
}
@Override
public Optional<GraphOfRuleInstancesComputation> getGraphOfRuleInstancesComputation() {
return Optional.ofNullable(this.graphOfRuleInstancesComputation);
}
@Override
public IAlgorithmParameters setGraphOfRuleInstancesType(GraphOfRuleInstancesComputation griComputation) {
this.graphOfRuleInstancesComputation = griComputation;
return this;
}
@Override
public Optional<Integer> getGMUSSolverTreshold() {
return Optional.ofNullable(GSATSolverParameters_SMART_SOLVER_TRESHOLD);
}
@Override
public IAlgorithmParameters setGMUSSolverTreshold(int treshold) {
this.GSATSolverParameters_SMART_SOLVER_TRESHOLD = treshold;
return this;
}
}
......@@ -52,4 +52,20 @@ interface IExplanationParameters {
IAlgorithmParameters setGraphOfRuleInstancesType(InteGraalKeywords.Algorithms.Parameters.Explanation.GraphOfRuleInstancesComputation griComputation);
/*
* GMUS Smart Solver Treshold
*/
Optional<Integer> getGMUSSolverTreshold();
IAlgorithmParameters setGMUSSolverTreshold(int treshold);
/*
* GMUS MARCO Path to Executable
*/
Optional<String> getMARCOPathToExecutable();
IAlgorithmParameters setMARCOPathToExecutable(String pathToExecutable);
public IAlgorithmParameters setGSATSolverParameters(InteGraalKeywords.Algorithms.Parameters.Explanation.GSATSolverParameters paramName, String value) ;
}
\ No newline at end of file
......@@ -94,8 +94,9 @@ public enum InteGraalKeywords {
EXPLAINER_SOLVER(Algorithms.Parameters.Explanation.ExplainerSolver.class),
EXPLAINER_GRI_COMPUTATION(Algorithms.Parameters.Explanation.GraphOfRuleInstancesComputation.class),
EXPLAINER_GRI_TYPE(Algorithms.Parameters.Explanation.GraphOfRuleInstancesType.class),
EXPLANATION_SUPPORT_TYPE(Algorithms.Parameters.Explanation.ExplanationSupportType.class);
EXPLANATION_SUPPORT_TYPE(Algorithms.Parameters.Explanation.ExplanationSupportType.class),
EXPLANATION_GMUS_SOLVER_TREHSOLD(Integer.class),
EXPLANATION_MARCO_PATH_EXECUTBLE(String.class);
// TODO Les paramètres peuvent-ils être partagés par les différents services ?
// Comment indiquer les valeurs autorisés d'un paramètre (cf. code ci-après) ?
......@@ -609,7 +610,19 @@ public enum InteGraalKeywords {
*/
SMART_GSAT_SOLVER
}
public enum GSATSolverParameters {
/**
* Threshold. Above use SAT4J. Below use MARCO
*/
SMART_SOLVER_TRESHOLD,
/**
* Path to marco.py in the sysmte
*/
MARCO_PATH_TO_EXECUTABLE
}
public enum GraphOfRuleInstancesComputation {
/**
* Uses an explainer that will compute the whole GRI first
......
......@@ -94,4 +94,8 @@ public class IGParameterValueExtractor {
return (Algorithms.Parameters.Explanation) search(params, InteGraalKeywords.EXPLANATION);
}
public static Algorithms.Parameters.Explanation getGMUSSolverTreshold(IGParameter<InteGraalKeywords, ?>... params) {
return (Algorithms.Parameters.Explanation) search(params, InteGraalKeywords.EXPLANATION_GMUS_SOLVER_TREHSOLD);
}
}
......@@ -49,12 +49,15 @@ public final class AtomicQueryExplainerBuilder {
private GraphOfRuleInstancesComputation griComputationParam = INCREMENTAL_GRI;
private GraphOfRuleInstancesType griTypeParam = KB_GRI;
private ExplanationSupportType supportTypeParam = KB_SUPPORT;
private Integer solverTreshold;
private String pathToMARCOExecutable;
// instances
private Solver solverInstance;
private KnowledgeBase kbInstance;
private boolean externallySetSolver = false;
/* -------------------------------------------------------------------------------------- */
public AtomicQueryExplainerBuilder apply(KnowledgeBase kb, Collection<IGParameter<InteGraalKeywords, ?>> params) {
......@@ -69,17 +72,20 @@ public final class AtomicQueryExplainerBuilder {
this.griComputationParam = (GraphOfRuleInstancesComputation) p.value();
case EXPLAINER_GRI_TYPE -> this.griTypeParam = (GraphOfRuleInstancesType) p.value();
case EXPLANATION_SUPPORT_TYPE -> this.supportTypeParam = (ExplanationSupportType) p.value();
case EXPLANATION_GMUS_SOLVER_TREHSOLD -> this.solverTreshold = (Integer) p.value();
case EXPLANATION_MARCO_PATH_EXECUTBLE -> this.pathToMARCOExecutable = (String) p.value();
default -> { /* ignored – may belong to another component */}
}
}
return this;
}
public void withSolver(Solver solver){
public void withSolver(Solver solver) {
Objects.requireNonNull(solver, "cannot use this method with a null solver");
this.solverInstance = solver;
this.externallySetSolver=true;
this.externallySetSolver = true;
}
/**
* Convenience one‑shot creation
*/
......@@ -114,14 +120,30 @@ public final class AtomicQueryExplainerBuilder {
private void buildSolver() {
if(externallySetSolver){
return;
if (externallySetSolver) {
return;
}
this.solverInstance = switch (this.solverParam) {
case MARCO -> new MARCOGMUSSolver();
case MARCO -> {
if (this.pathToMARCOExecutable != null) {
yield new MARCOGMUSSolver(this.pathToMARCOExecutable);
} else {
yield new MARCOGMUSSolver();
}
}
case SAT4J -> new Sat4JSolver();
case SMART_GSAT_SOLVER -> new HybridSAT4JMARCOSolver();
case SMART_GSAT_SOLVER -> {
if (this.solverTreshold != null && this.solverTreshold > 0) {
if (this.pathToMARCOExecutable != null) {
yield new HybridSAT4JMARCOSolver(this.solverTreshold, this.pathToMARCOExecutable);
} else {
yield new HybridSAT4JMARCOSolver(this.solverTreshold);
}
} else {
yield new HybridSAT4JMARCOSolver();
}
}
};
}
......
......@@ -15,4 +15,14 @@ public class PathFinder {
}
}
public static String ensureFilePath(String... paths) {
for (String p : paths) {
if (p != null && new File(p).exists()) {
return p;
}
}
throw new IllegalStateException(
"None of the provided paths exists: " + String.join(", ", paths));
}
}
......@@ -13,18 +13,28 @@ import java.util.Set;
public class HybridSAT4JMARCOSolver implements Solver {
private Sat4JSolver sat4JSolver = new Sat4JSolver();
private final Sat4JSolver sat4JSolver;
private MARCOGMUSSolver marcoSolver = new MARCOGMUSSolver();
private final MARCOGMUSSolver marcoSolver;
private final int TRESHOLD;
public HybridSAT4JMARCOSolver() {
this.TRESHOLD = 10;
this.sat4JSolver = new Sat4JSolver();
this.marcoSolver = new MARCOGMUSSolver();
}
public HybridSAT4JMARCOSolver(int treshold) {
this.TRESHOLD = treshold;
this.sat4JSolver = new Sat4JSolver();
this.marcoSolver = new MARCOGMUSSolver();
}
public HybridSAT4JMARCOSolver(int treshold, String marcoPathToExecutable) {
this.TRESHOLD = treshold;
this.sat4JSolver = new Sat4JSolver();
this.marcoSolver = new MARCOGMUSSolver(marcoPathToExecutable);
}
public HybridSolvingResultDecoded solveAndDecode(GSATEncodingResult_GRI encoding) {
......@@ -49,7 +59,7 @@ public class HybridSAT4JMARCOSolver implements Solver {
public HybridSolvingResult solve(GSATEncodingResult_GRI encoding) {
if (encoding.clauses().size() > TRESHOLD) {
if (encoding.clauses().size() < TRESHOLD) {
List<List<List<Integer>>> sat4JGMUSes = sat4JSolver.enumerateGMUSes(encoding.clauses());
return new HybridSolvingResult(sat4JGMUSes, sat4JSolver);
......
......@@ -3,8 +3,6 @@ package fr.boreal.explanation.solving_enumerating.marco;
import com.google.common.collect.BiMap;
import fr.boreal.explanation.api.solver.Solver;
import fr.boreal.model.logicalElements.api.Atom;
import fr.boreal.model.logicalElements.api.Term;
import no.hasmac.jsonld.uri.Path;
import java.io.*;
import java.util.HashSet;
......@@ -16,17 +14,32 @@ import static fr.boreal.explanation.configuration.PathFinder.ensureFilePath;
public class MARCOGMUSSolver implements Solver {
private static final MARCOGMUSSolver INSTANCE = new MARCOGMUSSolver();
public static MARCOGMUSSolver instance() {
return INSTANCE;
}
private final String pathToMARCOExecutable;
String tmpFileName = "gsat.gcnf";
File gcnfFile = new File(tmpFileName);
int timeout = 0;
public MARCOGMUSSolver(String pathToMARCOExecutableSetByUser) {
this.pathToMARCOExecutable =
ensureFilePath(
pathToMARCOExecutableSetByUser,
"integraal-explanation/MARCO-MUS/marco.py",
"MARCO-MUS/marco.py");
}
public MARCOGMUSSolver() {
this.pathToMARCOExecutable =
ensureFilePath(
"integraal-explanation/MARCO-MUS/marco.py",
"MARCO-MUS/marco.py");
}
public String getPathToMARCOExecutable() {
return pathToMARCOExecutable;
}
/**
* This main methods call two methods:
* 1. writeGCNF: Writing the clauses to temporary gsat.gcnf file
......@@ -116,9 +129,9 @@ public class MARCOGMUSSolver implements Solver {
ProcessBuilder build = new ProcessBuilder().redirectErrorStream(true);
String command;
if (timeout == 0)
build.command(ensureFilePath("integraal-explanation/MARCO-MUS/marco.py", "MARCO-MUS/marco.py"), "-s", "-v", "-b", "MUSes", gcnfFile.getAbsolutePath());
build.command(this.pathToMARCOExecutable, "-s", "-v", "-b", "MUSes", gcnfFile.getAbsolutePath());
else
build.command(ensureFilePath("integraal-explanation/MARCO-MUS/marco.py", "MARCO-MUS/marco.py"), "-a", "-v", "-b", "MUSes", "-T", Long.toString(timeout), gcnfFile.getAbsolutePath());
build.command(this.pathToMARCOExecutable, "-a", "-v", "-b", "MUSes", "-T", Long.toString(timeout), gcnfFile.getAbsolutePath());
Process proc;
try {
proc = build.start();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment