nl.uu.cs.ape.models.templateFormulas.SLTLxTemplateFormula Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of APE Show documentation
Show all versions of APE Show documentation
APE is a command line tool and an API for the automated exploration of possible computational pipelines (workflows) from large collections of computational tools.
The newest version!
package nl.uu.cs.ape.models.templateFormulas;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import nl.uu.cs.ape.automaton.Block;
import nl.uu.cs.ape.automaton.ModuleAutomaton;
import nl.uu.cs.ape.automaton.State;
import nl.uu.cs.ape.automaton.TypeAutomaton;
import nl.uu.cs.ape.domain.APEDomainSetup;
import nl.uu.cs.ape.utils.APEUtils;
import nl.uu.cs.ape.models.AbstractModule;
import nl.uu.cs.ape.models.Module;
import nl.uu.cs.ape.models.Pair;
import nl.uu.cs.ape.models.SATAtomMappings;
import nl.uu.cs.ape.models.Type;
import nl.uu.cs.ape.models.enums.AtomType;
import nl.uu.cs.ape.models.logic.constructs.TaxonomyPredicate;
/**
* The class is used to represent a predefined SLTLx constraints according to a
* template, and to generate the
* corresponding CNF representation. The form supports a limited set of commonly
* used formulas, and unlike arbitrary
* SLTLx formulas, encoding of templates is optimized.
*
* @author Vedran Kasalica
*/
public abstract class SLTLxTemplateFormula {
private TaxonomyPredicate predicate;
/**
* Sign of the predicate, false if the predicate is negated, true otherwise.
*/
private boolean sign;
/**
* Instantiates a new SLTLx formula.
*
* @param predicate the predicate
*/
protected SLTLxTemplateFormula(TaxonomyPredicate predicate) {
this.predicate = predicate;
sign = true;
}
/**
* Modal operators are performed over formulas. In case of value of
* sign being true, formula is positive, otherwise the
* formula is negative (predicate is negated).
*
* @param sign Sign of the predicate, false if the predicate is negated,
* true otherwise.
* @param predicate A {@link TaxonomyPredicate}.
*/
protected SLTLxTemplateFormula(boolean sign, TaxonomyPredicate predicate) {
this.predicate = predicate;
this.sign = sign;
}
/**
* Setting whether the predicate is negated or not.
* If sign is false the predicate will be negated.
*
* @param sign Sign of the predicate, false if the predicate is negated, true
* otherwise.
*/
public void setSign(boolean sign) {
this.sign = sign;
}
/**
* Gets sign.
*
* @return false if the predicate is negated, true otherwise.
*/
public boolean getSign() {
return sign;
}
/**
* Function returns the formula that was specified under the SLTLx operator.
* Currently only predicates.
*
* @return StateInterface ({@link AbstractModule}, {@link Module} or
* {@link Type}).
*/
public TaxonomyPredicate getSubFormula() {
return predicate;
}
/**
* Returns the type of the SLTLx formula [F, G or X].
*
* @return String [F, G or X], depending on the type of
* SLTLx formula.
*/
public abstract String getType();
/**
* Generate String representation of the CNF formula for
* defined @moduleAutomaton and @typeAutomaton.
*
* @param moduleAutomaton Automaton of all the module states.
* @param typeStateBlocks Automaton of all the type states.
* @param workflowElement type of the workflow element ({@link AtomType#MODULE},
* {@link AtomType#MEM_TYPE_REFERENCE} etc.)
* @param mappings Set of the mappings for the literals.
* @return The String CNF representation of the SLTLx formula.
*/
public abstract String getCNF(ModuleAutomaton moduleAutomaton, List typeStateBlocks,
AtomType workflowElement, SATAtomMappings mappings);
/**
* Creates a CNF representation of the Constraint:
* If ifPredicate is used, tool thenPredicate has to be used
* subsequently.
*
* @param ifPredicate Predicate that enforce the usage of
* thenPredicate.
* @param thenPredicate Predicate that is enforced by ifPredicate.
* @param moduleAutomaton Module automaton.
* @param mappings Set of the mappings for the literals.
* @return The String CNF representation of the SLTLx formula.
*/
public static String iteModule(TaxonomyPredicate ifPredicate, TaxonomyPredicate thenPredicate,
ModuleAutomaton moduleAutomaton,
SATAtomMappings mappings) {
StringBuilder constraints = new StringBuilder();
int automatonSize = moduleAutomaton.getAllStates().size();
for (int i = 0; i < automatonSize; i++) {
constraints.append("-"
+ mappings.add(ifPredicate, moduleAutomaton.getAllStates().get(i), AtomType.MODULE)
+ " ");
for (int j = i + 1; j < automatonSize; j++) {
constraints.append(mappings.add(thenPredicate, moduleAutomaton.get(j), AtomType.MODULE)).append(" ");
}
constraints.append("0\n");
}
return constraints.toString();
}
/**
* Creates a CNF representation of the Constraint:
* If type ifPredicate is used/generated (depending on the @typeBlocks),
* then type thenPredicate has to be used/generated subsequently.
*
* @param ifPredicate Predicate that enforce the usage of
* thenPredicate.
* @param thenPredicate Predicate that is enforced by ifPredicate.
* @param typeElement Workflow element type.
* @param typeBlocks Type blocks (corresponding to the memory or used type
* states).
* @param mappings Set of the mappings for the literals.
* @return The String CNF representation of the SLTLx formula.
*/
public static String iteType(TaxonomyPredicate ifPredicate, TaxonomyPredicate thenPredicate,
AtomType typeElement,
List typeBlocks, SATAtomMappings mappings) {
StringBuilder constraints = new StringBuilder();
int numberOfBlocks = typeBlocks.size();
int numberOfStates = typeBlocks.get(0).getBlockSize();
for (int i_block = 0; i_block < numberOfBlocks; i_block++) {
for (int i_state = 0; i_state < numberOfStates; i_state++) {
/* If ifPredicate is used in any state of a certain block */
constraints.append("-").append(mappings.add(ifPredicate,
typeBlocks.get(i_block).getState(i_state), typeElement)).append(" ");
/* then thenPredicate must be used in a state of the subsequent blocks. */
for (int j_block = i_block + 1; j_block < numberOfBlocks; j_block++) {
for (int j_state = i_state + 1; j_state < numberOfBlocks; j_state++) {
constraints.append(mappings.add(thenPredicate,
typeBlocks.get(j_block).getState(j_state), typeElement)).append(" ");
}
}
constraints.append("0\n");
}
}
return constraints.toString();
}
/**
* Creates a CNF representation of the Constraint:
* If ifPredicate is used, tool thenPredicate cannot be used
* subsequently.
*
* @param ifPredicate Predicate that forbids the usage of
* thenNotPredicate.
* @param thenNotPredicate Module that is forbidden by ifPredicate.
* @param moduleAutomaton Module automaton.
* @param mappings Set of the mappings for the literals.
* @return The String CNF representation of the SLTLx formula.
*/
public static String itnModule(TaxonomyPredicate ifPredicate, TaxonomyPredicate thenNotPredicate,
ModuleAutomaton moduleAutomaton, SATAtomMappings mappings) {
StringBuilder constraints = new StringBuilder();
int automatonSize = moduleAutomaton.getAllStates().size();
for (int i = 0; i < automatonSize - 1; i++) {
State currModuleState = moduleAutomaton.getAllStates().get(i);
for (int j = i + 1; j < automatonSize; j++) {
constraints.append("-").append(mappings.add(ifPredicate, currModuleState, AtomType.MODULE))
.append(" ");
constraints.append("-"
+ mappings.add(thenNotPredicate, moduleAutomaton.get(j), AtomType.MODULE)
+ " 0\n");
}
}
return constraints.toString();
}
/**
* Creates a CNF representation of the Constraint:
* If type ifPredicate is used/generated (depending on the @typeBlocks),
* then do not use/generate type thenNotPredicate subsequently.
*
* @param ifPredicate Predicate that forbids the usage of
* thenNotPredicate.
* @param thenNotPredicate Predicate that is forbidden by ifPredicate.
* @param typeElement Workflow element type.
* @param typeBlocks Type blocks (corresponding to the memory or used
* type states).
* @param mappings Set of the mappings for the literals.
* @return The String CNF representation of the SLTLx formula.
*/
public static String itnType(TaxonomyPredicate ifPredicate, TaxonomyPredicate thenNotPredicate,
AtomType typeElement,
List typeBlocks, SATAtomMappings mappings) {
StringBuilder constraints = new StringBuilder();
int numberOfBlocks = typeBlocks.size();
int numberOfStates = typeBlocks.get(0).getBlockSize();
for (int i_block = 0; i_block < numberOfBlocks - 1; i_block++) {
for (int i_state = 0; i_state < numberOfStates; i_state++) {
for (int j_block = i_block + 1; j_block < numberOfBlocks; j_block++) {
for (int j_state = 0; j_state < numberOfStates; j_state++) {
/*
* If ifPredicate is used in any state of a certain block
*/
constraints.append("-").append(mappings.add(ifPredicate,
typeBlocks.get(i_block).getState(i_state), typeElement)).append(" ");
/*
* then thenPredicate cannot be used in a state of the subsequent blocks.
*/
constraints.append("-").append(mappings.add(thenNotPredicate,
typeBlocks.get(j_block).getState(j_state), typeElement)).append(" 0\n");
}
}
}
}
return constraints.toString();
}
/**
* Creates a CNF representation of the Constraint:
* If we use module secondModuleInSequence,
* then we must have used firstModuleInSequence prior to it.
*
* @param secondModuleInSequence Predicate that enforces the usage of
* firstPredicate.
* @param firstModuleInSequence Predicate that is enforced by
* secondPredicate.
* @param moduleAutomaton Module automaton.
* @param mappings Set of the mappings for the literals.
* @return The String CNF representation of the SLTLx formula.
*/
public static String dependModule(TaxonomyPredicate secondModuleInSequence,
TaxonomyPredicate firstModuleInSequence,
ModuleAutomaton moduleAutomaton, SATAtomMappings mappings) {
StringBuilder constraints = new StringBuilder();
int automatonSize = moduleAutomaton.getAllStates().size();
for (int i = 0; i < automatonSize; i++) {
constraints.append("-").append(mappings.add(secondModuleInSequence,
moduleAutomaton.getAllStates().get(i), AtomType.MODULE)).append(" ");
for (int j = 0; j < i; j++) {
constraints.append(mappings.add(firstModuleInSequence,
moduleAutomaton.get(j), AtomType.MODULE)).append(" ");
}
constraints.append("0\n");
}
return constraints.toString();
}
/**
* Creates a CNF representation of the Constraint:
* If we use predicate firstModuleInSequence, then use
* secondModuleInSequence as a next predicate in the sequence.
*
* @param firstModuleInSequence Predicate that enforce the usage of
* secondPredicate.
* @param secondModuleInSequence Predicate that is enforced by
* firstPredicate.
* @param moduleAutomaton Module automaton.
* @param mappings Set of the mappings for the literals.
* @return The String CNF representation of the constraint.
*/
public static String nextModule(TaxonomyPredicate firstModuleInSequence,
TaxonomyPredicate secondModuleInSequence,
ModuleAutomaton moduleAutomaton, SATAtomMappings mappings) {
StringBuilder constraints = new StringBuilder();
int automatonSize = moduleAutomaton.getAllStates().size();
for (int i = 0; i < automatonSize; i++) {
constraints.append("-").append(mappings.add(firstModuleInSequence,
moduleAutomaton.getAllStates().get(i), AtomType.MODULE)).append(" ");
/* Clause that forbids using firstPredicate as the last in the sequence */
if (i < automatonSize - 1) {
constraints.append(mappings.add(secondModuleInSequence,
moduleAutomaton.get(i + 1), AtomType.MODULE)).append(" ");
}
constraints.append("0\n");
}
return constraints.toString();
}
/**
* Creates a CNF representation of the Constraint:
* If we use predicate firstPredicate, then use
* secondPredicate as a next predicate in the sequence.
*
* @param secondModuleInSequence Predicate that is enforced by
* firstPredicate.
* @param firstModuleInSequence Predicate that enforce the usage of
* secondPredicate.
* @param moduleAutomaton Module automaton.
* @param mappings Set of the mappings for the literals.
* @return The String CNF representation of the constraint.
*/
public static String prevModule(TaxonomyPredicate secondModuleInSequence,
TaxonomyPredicate firstModuleInSequence,
ModuleAutomaton moduleAutomaton, SATAtomMappings mappings) {
StringBuilder constraints = new StringBuilder();
int automatonSize = moduleAutomaton.getAllStates().size();
for (int i = 0; i < automatonSize; i++) {
constraints.append("-").append(mappings.add(secondModuleInSequence,
moduleAutomaton.getAllStates().get(i), AtomType.MODULE)).append(" ");
/*
* Clause that forbids using secondModuleInSequence as the first tool in the
* sequence
*/
if (i > 0) {
constraints.append(mappings.add(firstModuleInSequence,
moduleAutomaton.get(i - 1), AtomType.MODULE)).append(" ");
}
constraints.append("0\n");
}
return constraints.toString();
}
/**
* Creates a CNF representation of the Constraint:
* Use lastModule as last module in the solution.
*
* @param lastModule The module.
* @param moduleAutomaton Automaton of all the module states.
* @param mappings Set of the mappings for the literals.
* @return The String CNF representation of the SLTLx formula.
*/
public static String useAsLastModule(TaxonomyPredicate lastModule, ModuleAutomaton moduleAutomaton,
SATAtomMappings mappings) {
StringBuilder constraints = new StringBuilder();
List moduleAutomatonStates = moduleAutomaton.getAllStates();
State lastModuleState = moduleAutomatonStates.get(moduleAutomatonStates.size() - 1);
constraints.append(mappings.add(lastModule, lastModuleState, AtomType.MODULE)).append(" 0\n");
return constraints.toString();
}
/**
* Creates a CNF representation of the Constraint:
* Use module as the n-th module in the solution.
*
* @param module The module.
* @param n The absolute position in the solution.
* @param moduleAutomaton Automaton of all the module states.
* @param mappings Set of the mappings for the literals.
* @return The String CNF representation of the SLTLx formula.
*/
public static String useAsNthModule(TaxonomyPredicate module, int n, ModuleAutomaton moduleAutomaton,
SATAtomMappings mappings) {
StringBuilder constraints = new StringBuilder();
List moduleAutomatonStates = moduleAutomaton.getAllStates();
State nthModuleState = moduleAutomatonStates.get(n - 1);
constraints.append(mappings.add(module, nthModuleState, AtomType.MODULE)).append(" 0\n");
return constraints.toString();
}
/**
* Creates a CNF representation of the Constraint:
* Use module with data inputType as one of the inputs.
*
* @param module Module to be used.
* @param inputType Type of one of the input types.
* @param moduleAutomaton The module automaton
* @param typeAutomaton The type automaton.
* @param mappings Set of the mappings for the literals.
* @return
*/
public static String useModuleInput(TaxonomyPredicate module, TaxonomyPredicate inputType,
ModuleAutomaton moduleAutomaton, TypeAutomaton typeAutomaton, SATAtomMappings mappings) {
StringBuilder constraints = new StringBuilder();
Set allCombinations = new HashSet<>();
Map opOrderStates = new HashMap<>();
Map> opInputs = new HashMap<>();
int automatonSize = moduleAutomaton.getAllStates().size();
for (int opNo = 0; opNo < automatonSize; opNo++) {
int currOp = mappings.getNextAuxNum();
allCombinations.add(currOp);
opOrderStates.put(currOp, moduleAutomaton.getAllStates().get(opNo));
opInputs.put(currOp, typeAutomaton.getUsedTypesBlock(opNo).getStates());
}
// at least one of the states must be valid
for (Integer currComb : allCombinations) {
constraints.append(currComb + " ");
}
constraints.append("0\n");
// each state enforces usage of the corresponding tools and input
for (Integer currComb : allCombinations) {
// enforce tools
constraints.append("-" + currComb + " ")
.append(mappings.add(module, opOrderStates.get(currComb), AtomType.MODULE))
.append(" 0\n");
// enforce output/input dependencies
constraints.append("-" + currComb + " ");
for (State currState : opInputs.get(currComb)) {
constraints.append(mappings.add(inputType, currState, AtomType.USED_TYPE))
.append(" ");
}
constraints.append("0\n");
}
return constraints.toString();
}
/**
* Creates a CNF representation of the Constraint:
* Use module with data outputType as one of the outputs.
*
* @param module Module to be used.
* @param outputType Type of one of the input types.
* @param moduleAutomaton The module automaton
* @param typeAutomaton The type automaton.
* @param mappings Set of the mappings for the literals.
* @return
*/
public static String useModuleOutput(TaxonomyPredicate module, TaxonomyPredicate outputType,
ModuleAutomaton moduleAutomaton, TypeAutomaton typeAutomaton, SATAtomMappings mappings) {
StringBuilder constraints = new StringBuilder();
Set allCombinations = new HashSet<>();
Map opOrderStates = new HashMap<>();
Map> onOutputs = new HashMap<>();
int automatonSize = moduleAutomaton.getAllStates().size();
for (int opNo = 0; opNo < automatonSize; opNo++) {
int currOp = mappings.getNextAuxNum();
allCombinations.add(currOp);
opOrderStates.put(currOp, moduleAutomaton.getAllStates().get(opNo));
onOutputs.put(currOp, typeAutomaton.getMemoryTypesBlock(opNo + 1).getStates());
}
// at least one of the states must be valid
for (Integer currComb : allCombinations) {
constraints.append(currComb + " ");
}
constraints.append("0\n");
// each state enforces usage of the corresponding tools and input
for (Integer currComb : allCombinations) {
// enforce tools
constraints.append("-" + currComb + " ")
.append(mappings.add(module, opOrderStates.get(currComb), AtomType.MODULE))
.append(" 0\n");
// enforce output/input dependencies
constraints.append("-" + currComb + " ");
for (State currState : onOutputs.get(currComb)) {
constraints.append(mappings.add(outputType, currState, AtomType.MEM_TYPE_REFERENCE))
.append(" ");
}
constraints.append("0\n");
}
return constraints.toString();
}
/**
* Creates a CNF representation of the Constraint:
* 1st operation should generate an output used by the 2nd operation.
*
* @param firstPredicate - Module type that generates the data as output
* @param secondPredicate - Module type that uses the generated data as input
* @param moduleAutomaton - module automaton.
* @param typeAutomaton - type automaton
* @param mappings - Set of the mappings for the literals.
* @return The String CNF representation of the SLTLx formula.
*/
public static String connectedModules(TaxonomyPredicate firstPredicate, TaxonomyPredicate secondPredicate,
ModuleAutomaton moduleAutomaton,
TypeAutomaton typeAutomaton, SATAtomMappings mappings) {
StringBuilder constraints = new StringBuilder();
Set allCombinations = new HashSet<>();
Map> opOrderStates = new HashMap<>();
Map>> opOutInPairs = new HashMap<>();
int automatonSize = moduleAutomaton.getAllStates().size();
for (int op1 = 0; op1 < automatonSize - 1; op1++) {
for (int op2 = op1 + 1; op2 < automatonSize; op2++) {
int currComb = mappings.getNextAuxNum();
allCombinations.add(currComb);
opOrderStates.put(currComb, new Pair<>(moduleAutomaton.getAllStates().get(op1),
moduleAutomaton.getAllStates().get(op2)));
List op1outputs = typeAutomaton.getMemoryTypesBlock(op1 + 1).getStates();
List op2inputs = typeAutomaton.getUsedTypesBlock(op2).getStates();
Set> statePairs = APEUtils.getUniquePairs(op1outputs, op2inputs);
opOutInPairs.put(currComb, statePairs);
}
}
// at least one of the combinations must be valid
for (Integer currComb : allCombinations) {
constraints.append(currComb + " ");
}
constraints.append("0\n");
// each combination enforces usage of the corresponding tools and output/inputs
for (Integer currComb : allCombinations) {
// enforce tools
constraints.append("-" + currComb + " ")
.append(mappings.add(firstPredicate, opOrderStates.get(currComb).getFirst(), AtomType.MODULE))
.append(" 0\n");
constraints.append("-" + currComb + " ")
.append(mappings.add(secondPredicate, opOrderStates.get(currComb).getSecond(), AtomType.MODULE))
.append(" 0\n");
// enforce output/input dependencies
constraints.append("-" + currComb + " ");
for (Pair currPair : opOutInPairs.get(currComb)) {
constraints.append(mappings.add(currPair.getFirst(), currPair.getSecond(), AtomType.MEM_TYPE_REFERENCE))
.append(" ");
}
constraints.append("0\n");
}
return constraints.toString();
}
/**
* Creates a CNF representation of the Constraint:
* 1st operation should not generate an output used by the 2nd operation.
*
* @param firstPredicate - Module type that generates the data as output
* @param secondPredicate - Module type that uses the generated data as input
* @param typeAutomaton - type automaton
* @param mappings - Set of the mappings for the literals.
* @return The String CNF representation of the SLTLx formula.
*/
public static String notConnectedModules(TaxonomyPredicate firstPredicate, TaxonomyPredicate secondPredicate,
ModuleAutomaton moduleAutomaton,
TypeAutomaton typeAutomaton, SATAtomMappings mappings) {
StringBuilder constraints = new StringBuilder();
int automatonSize = moduleAutomaton.getAllStates().size();
for (int op1 = 0; op1 < automatonSize - 1; op1++) {
for (int op2 = op1 + 1; op2 < automatonSize; op2++) {
State firstModuleState = moduleAutomaton.get(op1);
State secondModuleState = moduleAutomaton.get(op2);
List op1outputs = typeAutomaton.getMemoryTypesBlock(op1 + 1).getStates();
List op2inputs = typeAutomaton.getUsedTypesBlock(op2).getStates();
// Ensure that either the 2 operations are not used consequently, or that they
// are not connected
Set> statePairs = APEUtils.getUniquePairs(op1outputs, op2inputs);
for (Pair currIOpair : statePairs) {
constraints.append("-").append(mappings.add(firstPredicate, firstModuleState, AtomType.MODULE))
.append(" ");
constraints.append("-"
+ mappings.add(currIOpair.getFirst(), currIOpair.getSecond(), AtomType.MEM_TYPE_REFERENCE)
+ " ");
constraints.append("-"
+ mappings.add(secondPredicate, secondModuleState, AtomType.MODULE)
+ " 0\n");
}
}
}
return constraints.toString();
}
public static String notRepeatModules(TaxonomyPredicate predicate, APEDomainSetup domainSetup,
ModuleAutomaton moduleAutomaton,
TypeAutomaton typeAutomaton, SATAtomMappings mappings) {
StringBuilder constraints = new StringBuilder();
int automatonSize = moduleAutomaton.getAllStates().size();
for (int op1 = 0; op1 < automatonSize - 1; op1++) {
for (int op2 = op1 + 1; op2 < automatonSize; op2++) {
State firstModuleState = moduleAutomaton.get(op1);
State secondModuleState = moduleAutomaton.get(op2);
List op1outputs = typeAutomaton.getMemoryTypesBlock(op1 + 1).getStates();
List op2inputs = typeAutomaton.getUsedTypesBlock(op2).getStates();
// Ensure that either each operation is not used consequently, or that they are
// not connected
Set> statePairs = APEUtils.getUniquePairs(op1outputs, op2inputs);
for (Pair currIOpair : statePairs) {
// filter all operations
domainSetup.getAllModules().getElementsFromSubTaxonomy(predicate).stream()
.filter(x -> x.isSimplePredicate()).forEach(operation -> {
constraints.append("-")
.append(mappings.add(operation, firstModuleState, AtomType.MODULE)).append(" ");
constraints.append("-"
+ mappings.add(currIOpair.getFirst(), currIOpair.getSecond(),
AtomType.MEM_TYPE_REFERENCE)
+ " ");
constraints.append("-"
+ mappings.add(operation, secondModuleState, AtomType.MODULE)
+ " 0\n");
});
}
}
}
return constraints.toString();
}
/**
* Simple method that combines a pair of integers into a unique String.
*
* @param int1 - first integer
* @param int2 - second integer
* @return Unique combination of the pair, as String.
*/
private static String combine(int int1, int int2) {
return int1 + "_" + int2;
}
}