All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nl.uu.cs.ape.solver.minisat.EnforceModuleRelatedRules Maven / Gradle / Ivy

Go to download

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.solver.minisat;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import lombok.extern.slf4j.Slf4j;
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.AllModules;
import nl.uu.cs.ape.models.Module;
import nl.uu.cs.ape.models.Pair;
import nl.uu.cs.ape.models.Type;
import nl.uu.cs.ape.models.enums.AtomType;
import nl.uu.cs.ape.models.enums.ConfigEnum;
import nl.uu.cs.ape.models.logic.constructs.PredicateLabel;
import nl.uu.cs.ape.models.logic.constructs.TaxonomyPredicate;
import nl.uu.cs.ape.models.sltlxStruc.SLTLxAtom;
import nl.uu.cs.ape.models.sltlxStruc.SLTLxConjunction;
import nl.uu.cs.ape.models.sltlxStruc.SLTLxDisjunction;
import nl.uu.cs.ape.models.sltlxStruc.SLTLxEquivalence;
import nl.uu.cs.ape.models.sltlxStruc.SLTLxFormula;
import nl.uu.cs.ape.models.sltlxStruc.SLTLxImplication;
import nl.uu.cs.ape.models.sltlxStruc.SLTLxNegatedConjunction;
import nl.uu.cs.ape.models.sltlxStruc.SLTLxNegation;
import nl.uu.cs.ape.models.sltlxStruc.SLTLxXOR;

/**
 * The {@code ModuleUtils} class is used to encode SLTLx constraints based on
 * the module annotations that would encode the workflow structure.
 *
 * @author Vedran Kasalica
 */
@Slf4j
public final class EnforceModuleRelatedRules {

	/**
	 * Private constructor is used to to prevent instantiation.
	 */
	private EnforceModuleRelatedRules() {
		throw new UnsupportedOperationException();
	}

	/**
	 * Return a CNF representation of the INPUT and OUTPUT type constraints.
	 * Depending on the parameter pipeline, the INPUT constraints will be based on a
	 * pipeline or general memory approach.
	 *
	 * @param synthesisInstance A specific synthesis run that contains all the
	 *                          information specific for it.
	 * @return Set of SLTLx formulas that represent the CNF constraints regarding
	 *         the required INPUT
	 *         and OUTPUT types of the modules.
	 */
	public static Set moduleAnnotations(SATSynthesisEngine synthesisInstance) {
		Set fullEncoding = new HashSet<>();
		fullEncoding.addAll(toolInputTypes(synthesisInstance));

		fullEncoding.addAll(toolOutputTypes(synthesisInstance));
		return fullEncoding;
	}

	/**
	 * Return a CNF formula that preserves the memory structure that is being used
	 * (e.g. 'shared memory'), i.e. ensures that the referenced items are available
	 * according to the mem. structure and that the input type and the referenced
	 * type from the memory represent the same data.
	 *
	 * @param synthesisInstance A specific synthesis run that contains all the
	 *                          information specific for it.
	 * @return Set of SLTLx formulas that represent the CNF constraints regarding
	 *         the required
	 *         memory structure implementation.
	 */
	public static Set memoryStructure(SATSynthesisEngine synthesisInstance) {
		Set fullEncoding = new HashSet<>();

		fullEncoding.addAll(allowDataReferencing(synthesisInstance.getTypeAutomaton()));
		fullEncoding.addAll(usageOfGeneratedTypes(synthesisInstance));
		fullEncoding.addAll(dataReference(synthesisInstance.getDomainSetup(),
				synthesisInstance.getTypeAutomaton()));
		return fullEncoding;
	}

	/**
	 * Function returns the encoding that ensures that ancestor relation (R)
	 * among data objects is preserved.
	 * 
	 * @param synthesisInstance A specific synthesis run that contains all the
	 *                          information specific for it.
	 * @return Set of SLTLx formulas that represent the constraints.
	 */
	public static Set ancestorRelationsDependency(SATSynthesisEngine synthesisInstance) {
		Set fullEncoding = new HashSet<>();
		TypeAutomaton typeAutomaton = synthesisInstance.getTypeAutomaton();

		/**
		 * Encode reflexivity and transitivity of the relation.
		 */
		fullEncoding.addAll(relationalReflexivity(AtomType.R_RELATION, typeAutomaton));
		fullEncoding.addAll(relationalTransitivity(AtomType.R_RELATION, typeAutomaton));

		/**
		 * Ancestor relation:
		 * - encode restrictions
		 * - preserve ancestor relation among tool I/O
		 * - preserve ancestor relation when data referencing
		 * - restrict that outputs can ONLY depend on inputs of the tool
		 * ONLY
		 * - restrict that empty types don't depend on anything
		 */
		fullEncoding.addAll(restrictAncestorRelationDomain(typeAutomaton));
		fullEncoding.addAll(ancestorRelRestrictOverModules(synthesisInstance));
		fullEncoding.addAll(ancestorRelDependencyOverModules(synthesisInstance));
		fullEncoding.addAll(ancestorRelOverDataReferencing(typeAutomaton));

		return fullEncoding;
	}

	/**
	 * Function returns the encoding that ensures that identity relation (IS)
	 * among data objects is preserved.
	 * 
	 * @param typeAutomaton - collection of states representing the data objects in
	 *                      the workflow
	 * @return Set of SLTLx formulas that represent the constraints.
	 */
	public static Set identityRelationsDependency(TypeAutomaton typeAutomaton) {
		Set fullEncoding = new HashSet<>();

		/**
		 * Encode that the relation in an identity.
		 */

		fullEncoding.addAll(relationalIdentity(AtomType.IDENTITY_RELATION, typeAutomaton));

		return fullEncoding;
	}

	/**
	 * Generate constraints that ensure that the set of inputs correspond to the
	 * tool specifications.
* Returns the CNF representation of the input type constraints for all tools * regarding @typeAutomaton, for the synthesis concerning @moduleAutomaton. * * @return Set of SLTLx formulas that represent the constraints. */ private static Set toolInputTypes(SATSynthesisEngine synthesisInstance) { Set fullEncoding = new HashSet<>(); /* For each module.. */ for (TaxonomyPredicate potentialModule : synthesisInstance.getDomainSetup().getAllModules().getModules()) { /* ..which is a Tool.. */ if ((potentialModule instanceof Module)) { Module module = (Module) potentialModule; /* ..iterate through all the states.. */ for (State moduleState : synthesisInstance.getModuleAutomaton().getAllStates()) { int moduleNo = moduleState.getLocalStateNumber(); /* ..and for each state and input state of that module state.. */ List currInputStates = synthesisInstance.getTypeAutomaton().getUsedTypesBlock(moduleNo - 1) .getStates(); List moduleInputs = module.getModuleInput(); for (State currInputState : currInputStates) { int currInputStateNo = currInputState.getLocalStateNumber(); /* * ..require data type and/or format to be used in one of the directly preceding * input states, if the data type/format it exists, otherwise use empty type. */ if (currInputStateNo < moduleInputs.size()) { /* Get input type and/or format that are/is required by the tool */ TaxonomyPredicate currInputType = moduleInputs.get(currInputStateNo); /* * Encode: if module was used in the module state * the corresponding data and format types need to be provided in input * states */ fullEncoding.add( new SLTLxImplication( new SLTLxAtom( AtomType.MODULE, module, moduleState), new SLTLxAtom( AtomType.USED_TYPE, currInputType, currInputState))); } else { fullEncoding.add( new SLTLxImplication( new SLTLxAtom( AtomType.MODULE, module, moduleState), new SLTLxAtom( AtomType.USED_TYPE, synthesisInstance.getEmptyType(), currInputState))); } } } } } return fullEncoding; } /** * Constraints that ensure that the referenced memory states contain the same * data type as the one that is used as the input for the tool. Constraints * ensure that the {@link AtomType#MEM_TYPE_REFERENCE} are implemented * correctly. * * @return String representing the constraints required to ensure that the * {@link AtomType#MEM_TYPE_REFERENCE} are implemented correctly. */ private static Set dataReference(APEDomainSetup domainSetup, TypeAutomaton typeAutomaton) { Set fullEncoding = new HashSet<>(); /* For each type instance */ for (TaxonomyPredicate currType : domainSetup.getAllTypes().getTypes()) { if (currType.isSimplePredicate() || currType.isEmptyPredicate()) { /* ..for each state in which type can be used .. */ for (State currUsedTypeState : typeAutomaton.getAllUsedTypesStates()) { if (!currType.isEmptyPredicate()) { /* * If the predicate is not empty * the referenced memory state cannot be null.. */ fullEncoding.add( new SLTLxNegatedConjunction( new SLTLxAtom( AtomType.USED_TYPE, currType, currUsedTypeState), new SLTLxAtom( AtomType.MEM_TYPE_REFERENCE, typeAutomaton.getNullState(), currUsedTypeState))); /* ..and for each state in which type can be created in memory .. */ for (State refMemoryTypeState : typeAutomaton.getAllMemoryTypesStates()) { /* * Pairs of referenced states have to be of the same types. */ fullEncoding.add( new SLTLxImplication( new SLTLxAtom( AtomType.MEM_TYPE_REFERENCE, refMemoryTypeState, currUsedTypeState), new SLTLxEquivalence( new SLTLxAtom( AtomType.USED_TYPE, currType, currUsedTypeState), new SLTLxAtom( AtomType.MEMORY_TYPE, currType, refMemoryTypeState)))); } /* If the type is empty the referenced state has to be null. */ } else { fullEncoding.add( new SLTLxImplication( new SLTLxAtom( AtomType.USED_TYPE, currType, currUsedTypeState), new SLTLxAtom( AtomType.MEM_TYPE_REFERENCE, typeAutomaton.getNullState(), currUsedTypeState))); } } } } return fullEncoding; } /** * Generate constraints that ensure that the all tool inputs can reference data * that is available in memory at the time. * *
* Return the CNF representation of the input type constraints for all modules, * regarding @typeAutomaton, for the synthesis concerning @moduleAutomaton and * the Shared Memory Approach. * * @return Set of SLTLx formulas that represent the constraints. */ private static Set allowDataReferencing(TypeAutomaton typeAutomaton) { // setting up input constraints (Shared Memory Approach) Set fullEncoding = new HashSet<>(); /** For each input state... */ for (Block currBlock : typeAutomaton.getUsedTypesBlocks()) { int blockNumber = currBlock.getBlockNumber(); for (State currInputState : currBlock.getStates()) { /* * Used state can reference states that are currently in the shared memory, i.e. * already created. */ List possibleMemStates = typeAutomaton.getMemoryStatesUntilBlockNo(blockNumber); possibleMemStates.add(typeAutomaton.getNullState()); Set allPossibilities = new HashSet<>(); for (State existingMemState : possibleMemStates) { allPossibilities.add(new SLTLxAtom(AtomType.MEM_TYPE_REFERENCE, existingMemState, currInputState)); } fullEncoding.add(new SLTLxDisjunction(allPossibilities)); /* Defining that each input can reference only one state in the shared memory */ for (Pair pair : getPredicatePairs(possibleMemStates)) { fullEncoding.add( new SLTLxNegatedConjunction( new SLTLxAtom( AtomType.MEM_TYPE_REFERENCE, pair.getFirst(), currInputState), new SLTLxAtom( AtomType.MEM_TYPE_REFERENCE, pair.getSecond(), currInputState))); } /* * Used state cannot reference states that are yet to be created, i.e. not yet * in the shared memory. */ for (State nonExistingMemState : typeAutomaton.getMemoryStatesAfterBlockNo(blockNumber)) { fullEncoding.add( new SLTLxNegation( new SLTLxAtom( AtomType.MEM_TYPE_REFERENCE, nonExistingMemState, currInputState))); } } } return fullEncoding; } /** * Generate constraints that ensure the data objects cannot depend (have * ancestors) on * data objects that are not available in memory. * * @return Set of SLTLx formulas that represent the constraints. */ private static Set restrictAncestorRelationDomain(TypeAutomaton typeAutomaton) { Set fullEncoding = new HashSet<>(); /** For each used state... */ for (Block currBlock : typeAutomaton.getUsedTypesBlocks()) { int blockNumber = currBlock.getBlockNumber(); for (State currInputState : currBlock.getStates()) { /* * Used state cannot depend on states that are yet to be created, i.e. not yet * in the shared memory. */ for (State nonExistingMemState : typeAutomaton.getMemoryStatesAfterBlockNo(blockNumber)) { fullEncoding.add( new SLTLxNegation( new SLTLxAtom( AtomType.R_RELATION, nonExistingMemState, currInputState))); } // Empty inputs have no data dependencies for (State existingMemState : typeAutomaton.getMemoryStatesUntilBlockNo(blockNumber)) { /* !(input -> empty) || !R(mem,input) */ fullEncoding.add( new SLTLxNegatedConjunction( new SLTLxAtom( AtomType.MEM_TYPE_REFERENCE, typeAutomaton.getNullState(), currInputState), new SLTLxAtom( AtomType.R_RELATION, existingMemState, currInputState))); } } } /** For each memory state... */ for (Block currBlock : typeAutomaton.getMemoryTypesBlocks()) { int blockNumber = currBlock.getBlockNumber(); for (State currMemState : currBlock.getStates()) { /* * Memory state cannot depend on states that are yet to be created or that were * just, i.e. not yet in the shared memory. */ for (State nonExistingMemState : typeAutomaton.getMemoryStatesAfterBlockNo(blockNumber - 1)) { if (!nonExistingMemState.equals(currMemState)) { fullEncoding.add( new SLTLxNegation( new SLTLxAtom( AtomType.R_RELATION, nonExistingMemState, currMemState))); } } } } return fullEncoding; } /** * Generate constraints that ensure that tool inputs that reference data in * memory are in ancestor relation (R) with the referenced data. * * @return Set of SLTLx formulas that represent the constraints. */ private static Set ancestorRelOverDataReferencing(TypeAutomaton typeAutomaton) { // setting up dependency constraints Set fullEncoding = new HashSet<>(); /** For each input state... */ for (Block currInputBlock : typeAutomaton.getUsedTypesBlocks()) { int blockNumber = currInputBlock.getBlockNumber(); for (State currInputState : currInputBlock.getStates()) { /* * and for each available memory state.. */ for (State availableMemState : typeAutomaton.getMemoryStatesUntilBlockNo(blockNumber)) { /* * If input references a memory, they are in ancestor relation * (used -> mem) => R(mem, used) */ fullEncoding.add( new SLTLxImplication( new SLTLxAtom( AtomType.MEM_TYPE_REFERENCE, availableMemState, currInputState), new SLTLxAtom( AtomType.R_RELATION, availableMemState, currInputState))); } } } return fullEncoding; } /** * Function returns the encoding that ensures that tool inputs and outputs are * preserving the ancestor relation (R). Outputs have to depend on inputs. * * @param synthesisInstance A specific synthesis run that contains all the * information specific for it. * * @return Set of SLTLx formulas that represent the constraints. */ private static Set ancestorRelDependencyOverModules(SATSynthesisEngine synthesisInstance) { TypeAutomaton typeAutomaton = synthesisInstance.getTypeAutomaton(); Set fullEncoding = new HashSet<>(); /** For tool inputs and outputs */ for (int i = 0; i < typeAutomaton.getUsedTypesBlocks().size() - 1; i++) { Block currInputBlock = typeAutomaton.getUsedTypesBlock(i); Block currMemBlock = typeAutomaton.getMemoryTypesBlock(i + 1); Type emptyType = synthesisInstance.getEmptyType(); // For each output state.. for (State currMemState : currMemBlock.getStates()) { // .. the memory (output) state has all tool inputs as ancestors, as long as // none of them is empty for (State currInputState : currInputBlock.getStates()) { fullEncoding.add( new SLTLxXOR( new SLTLxAtom( AtomType.R_RELATION, currInputState, currMemState), new SLTLxDisjunction( new SLTLxAtom( AtomType.MEMORY_TYPE, emptyType, currMemState), new SLTLxAtom( AtomType.USED_TYPE, emptyType, currInputState)))); } } } return fullEncoding; } /** * Function returns the encoding that ensures that tool outputs are only in the * ancestor relation (R) * with the tool inputs (and their ancestors), and not any other data objects. * Outputs can depend only on inputs. * * @param synthesisInstance A specific synthesis run that contains all the * information specific for it. * * @return Set of SLTLx formulas that represent the constraints. */ private static Set ancestorRelRestrictOverModules(SATSynthesisEngine synthesisInstance) { TypeAutomaton typeAutomaton = synthesisInstance.getTypeAutomaton(); Set fullEncoding = new HashSet<>(); Type emptyType = synthesisInstance.getEmptyType(); for (int i = 0; i < typeAutomaton.getUsedTypesBlocks().size() - 1; i++) { Block currInputBlock = typeAutomaton.getUsedTypesBlock(i); Block currMemBlock = typeAutomaton.getMemoryTypesBlock(i + 1); /** For each tool output.. */ for (State currMemState : currMemBlock.getStates()) { /* ..(unless it is empty).. */ SLTLxAtom outputEmpty = new SLTLxAtom( AtomType.MEMORY_TYPE, emptyType, currMemState); /* ..and an arbitrary element in the memory.. */ for (State existingType : typeAutomaton.getAllMemoryStatesUntilBlockNo(i)) { /* ..if the element from the memory is not ancestor of any of the inputs.. */ Set notInputAncestors = new HashSet<>(); for (State currInputState : currInputBlock.getStates()) { notInputAncestors.add( new SLTLxNegation( new SLTLxAtom( AtomType.R_RELATION, existingType, currInputState))); } /* .., it cannot be an ancestor of the output either (unless it is empty). */ fullEncoding.add( new SLTLxDisjunction( outputEmpty, new SLTLxImplication( new SLTLxConjunction(notInputAncestors), new SLTLxNegation( new SLTLxAtom( AtomType.R_RELATION, existingType, currMemState))))); } } } return fullEncoding; } /** * Generate constraints that ensure that the relations (e.g., identity relation * (IS)) are reflexive. * * @param binRel - binary relation that is reflexive * * @return Set of SLTLx formulas that represent the constraints. */ private static Set relationalReflexivity(AtomType binRel, TypeAutomaton typeAutomaton) { Set fullEncoding = new HashSet<>(); /* Relation is reflexive for any state in the system. */ typeAutomaton.getAllStates() .forEach(state -> { /* Rel(state,state) */ fullEncoding.add( new SLTLxAtom( binRel, state, state)); /* ..no state is related to null state */ fullEncoding.add( new SLTLxNegation( new SLTLxAtom( binRel, state, typeAutomaton.getNullState()))); }); return fullEncoding; } /** * Generate constraints that ensure that the relations (e.g., identity relation * (IS)) are an identity. * Forall X,Y IS(X,Y) IFF * * @param binRel - binary relation that is reflexive * * @return Set of SLTLx formulas that represent the constraints. */ private static Set relationalIdentity(AtomType binRel, TypeAutomaton typeAutomaton) { Set fullEncoding = new HashSet<>(); /* Relation is reflexive for any state in the system. */ typeAutomaton.getAllStates() .forEach(state1 -> { /* ..no state is identical to null state */ fullEncoding.add( new SLTLxNegation( new SLTLxAtom( binRel, state1, typeAutomaton.getNullState()))); fullEncoding.add( new SLTLxNegation( new SLTLxAtom( binRel, typeAutomaton.getNullState(), state1))); typeAutomaton.getAllStates() .forEach(state2 -> { if (state1.equals(state2)) { /* state=state -> IS(state,state) */ fullEncoding.add( new SLTLxAtom( binRel, state1, state2)); } else { /* state1<>state2 then !IS(state1,state2) */ fullEncoding.add( new SLTLxNegation( new SLTLxAtom( binRel, state1, state2))); } }); }); return fullEncoding; } /** * Function returns the encoding that ensures that the relation (e.g., ancestor * relation (R)) is transitive. * * @param binRel - relation that is transitive * @param typeAutomaton - system that represents states in the workflow * @return Set of SLTLx formulas that represent the constraints. */ private static Set relationalTransitivity(AtomType binRel, TypeAutomaton typeAutomaton) { Set fullEncoding = new HashSet<>(); /* Relation is transitive for any 3 states in the system. */ typeAutomaton.getAllStates() .forEach(state1 -> typeAutomaton.getAllStates() .forEach(state2 -> typeAutomaton.getAllStates() .forEach(state3 -> /* * Encode the transitivity. * E.g., R(s1,s2) & R(s2,s3) => R(s1,s3) */ fullEncoding.add( new SLTLxImplication( new SLTLxConjunction( new SLTLxAtom( binRel, state1, state2), new SLTLxAtom( binRel, state2, state3)), new SLTLxAtom( binRel, state1, state3)))))); return fullEncoding; } /** * Function returns the encoding that ensures that * the relation (e.g., identity relations (IS)) is symmetrical. * * @param binRel - binary relation that is symmetrical * @param typeAutomaton - system that represents states in the workflow * @return Set of SLTLx formulas that represent the constraints. */ private static Set relationalSymmetry(AtomType binRel, TypeAutomaton typeAutomaton) { Set fullEncoding = new HashSet<>(); /* Relation is symmetric for any 2 states in the system. */ typeAutomaton.getAllMemoryTypesStates() .forEach(state1 -> typeAutomaton.getAllMemoryTypesStates() .forEach(state2 -> /* * Encode the symmetry. * E.g., IS(s1,s2) => IS(s2,s1) */ fullEncoding.add( new SLTLxImplication( new SLTLxAtom( binRel, state1, state2), new SLTLxAtom( binRel, state2, state1))))); return fullEncoding; } /** * Function returns the encoding that ensures that tool outputs are used * according to the configuration, e.g. if the config specifies that all * workflow inputs have to be used, then each of them has to be referenced at * least once. * * @param synthesisInstance - instance of the synthesis engine * * @return Set of SLTLx formulas that represent the constraints. */ private static Set usageOfGeneratedTypes(SATSynthesisEngine synthesisInstance) { Type emptyType = synthesisInstance.getEmptyType(); TypeAutomaton typeAutomaton = synthesisInstance.getTypeAutomaton(); Set fullEncoding = new HashSet<>(); /* * Setting up the constraints that ensure usage of the generated types in the * memory, (e.g. all workflow inputs and at least one of each of the tool * outputs needs to be used in the program, unless they are empty.) */ for (Block currBlock : typeAutomaton.getMemoryTypesBlocks()) { int blockNumber = currBlock.getBlockNumber(); /* If the memory is provided as input */ if (blockNumber == 0) { /* In case that all workflow inputs need to be used */ if (synthesisInstance.getRunConfig().getUseWorkflowInput() == ConfigEnum.ALL) { for (State currMemoryState : currBlock.getStates()) { Set allPossibilities = new HashSet<>(); allPossibilities.add( new SLTLxAtom( AtomType.MEMORY_TYPE, emptyType, currMemoryState)); for (State inputState : typeAutomaton.getUsedStatesAfterBlockNo(blockNumber - 1)) { allPossibilities.add( new SLTLxAtom( AtomType.MEM_TYPE_REFERENCE, currMemoryState, inputState)); } fullEncoding.add(new SLTLxDisjunction(allPossibilities)); } /* In case that at least one workflow input need to be used */ } else if (synthesisInstance.getRunConfig().getUseWorkflowInput() == ConfigEnum.ONE) { Set allPossibilities = new HashSet<>(); for (State currMemoryState : currBlock.getStates()) { if (currMemoryState.getLocalStateNumber() == 0) { allPossibilities.add( new SLTLxAtom( AtomType.MEMORY_TYPE, emptyType, currMemoryState)); } for (State inputState : typeAutomaton.getUsedStatesAfterBlockNo(blockNumber - 1)) { allPossibilities.add( new SLTLxAtom( AtomType.MEM_TYPE_REFERENCE, currMemoryState, inputState)); } } fullEncoding.add(new SLTLxDisjunction(allPossibilities)); } /* In case that none of the workflow input has to be used, do nothing. */ } else { /* In case that all generated data need to be used. */ if (synthesisInstance.getRunConfig().getUseAllGeneratedData() == ConfigEnum.ALL) { for (State currMemoryState : currBlock.getStates()) { Set allPossibilities = new HashSet<>(); allPossibilities.add( new SLTLxAtom( AtomType.MEMORY_TYPE, emptyType, currMemoryState)); for (State inputState : typeAutomaton.getUsedStatesAfterBlockNo(blockNumber - 1)) { allPossibilities.add( new SLTLxAtom( AtomType.MEM_TYPE_REFERENCE, currMemoryState, inputState)); } fullEncoding.add(new SLTLxDisjunction(allPossibilities)); } /* * In case that at least one of the generated data instances per tool need to be * used. */ } else if (synthesisInstance.getRunConfig().getUseAllGeneratedData() == ConfigEnum.ONE) { Set allPossibilities = new HashSet<>(); for (State currMemoryState : currBlock.getStates()) { if (currMemoryState.getLocalStateNumber() == 0) { allPossibilities.add( new SLTLxAtom( AtomType.MEMORY_TYPE, emptyType, currMemoryState)); } for (State inputState : typeAutomaton.getUsedStatesAfterBlockNo(blockNumber - 1)) { allPossibilities.add( new SLTLxAtom( AtomType.MEM_TYPE_REFERENCE, currMemoryState, inputState)); } } fullEncoding.add(new SLTLxDisjunction(allPossibilities)); } /* In case that none generated data has to be used do nothing. */ } } return fullEncoding; } /** * Return the CNF representation of the output type constraints for all tools * regarding @typeAutomaton, for the synthesis concerning @moduleAutomaton.
* Generate constraints that preserve tool outputs. * * @param synthesisInstance - instance of the synthesis engine * * @return Set of SLTLx formulas that represent the constraints. */ private static Set toolOutputTypes(SATSynthesisEngine synthesisInstance) { Set fullEncoding = new HashSet<>(); // for each module for (TaxonomyPredicate potentialModule : synthesisInstance.getDomainSetup().getAllModules().getModules()) { // that is a Tool if ((potentialModule instanceof Module)) { Module module = (Module) potentialModule; // iterate through all the states for (State moduleState : synthesisInstance.getModuleAutomaton().getAllStates()) { int moduleNo = moduleState.getLocalStateNumber(); // and for each state and output state of that module state List currOutputStates = synthesisInstance.getTypeAutomaton().getMemoryTypesBlock(moduleNo) .getStates(); List moduleOutputs = module.getModuleOutput(); for (int i = 0; i < currOutputStates.size(); i++) { if (i < moduleOutputs.size()) { TaxonomyPredicate outputType = moduleOutputs.get(i); // single output // if module was used in the module state // require type and/or format to be used in one of the directly // proceeding output states if it exists, otherwise use empty type fullEncoding.add( new SLTLxImplication( new SLTLxAtom( AtomType.MODULE, module, moduleState), new SLTLxAtom( AtomType.MEMORY_TYPE, outputType, currOutputStates.get(i)))); } else { fullEncoding.add( new SLTLxImplication( new SLTLxAtom( AtomType.MODULE, module, moduleState), new SLTLxAtom( AtomType.MEMORY_TYPE, synthesisInstance.getEmptyType(), currOutputStates.get(i)))); } } } } } return fullEncoding; } /** * Generating the mutual exclusion constraints for the pair of tools from * modules (excluding abstract modules from the taxonomy) in each state of * moduleAutomaton. * * @param pair pair of modules. * @param moduleAutomaton Module automaton. * @return The Set of SLTLx formulas that represent the constraints. */ public static Set moduleMutualExclusion(Pair pair, ModuleAutomaton moduleAutomaton) { Set fullEncoding = new HashSet<>(); for (State moduleState : moduleAutomaton.getAllStates()) { fullEncoding.add( new SLTLxDisjunction( new SLTLxNegation( new SLTLxAtom( AtomType.MODULE, pair.getFirst(), moduleState)), new SLTLxNegation( new SLTLxAtom( AtomType.MODULE, pair.getSecond(), moduleState)))); } return fullEncoding; } /** * Generating the mandatory usage constraints of root module @rootModule in each * state of @moduleAutomaton. * * @param allModules All the modules. * @param moduleAutomaton Module automaton. * @return Set of SLTLx formulas that represent the constraints. */ public static Set moduleMandatoryUsage(AllModules allModules, ModuleAutomaton moduleAutomaton) { Set fullEncoding = new HashSet<>(); if (allModules.getModules().isEmpty()) { log.warn("No tools were I/O annotated."); return fullEncoding; } for (State moduleState : moduleAutomaton.getAllStates()) { Set allPossibilities = new HashSet<>(); for (TaxonomyPredicate tool : allModules.getModules()) { if (tool instanceof Module) { allPossibilities.add( new SLTLxAtom( AtomType.MODULE, tool, moduleState)); } } fullEncoding.add(new SLTLxDisjunction(allPossibilities)); } return fullEncoding; } /** * Generating the mandatory usage of a submodules in case of the parent module * being used, with respect to the Module Taxonomy. The rule starts from * the @rootModule and it's valid in each state of @moduleAutomaton. * * @param allModules All the modules. * @param currModule Module that should be used. * @param moduleAutomaton Module automaton. * @return Set of SLTLx formulas that represent the constraints enforcing * taxonomy * classifications. */ public static Set moduleTaxonomyStructure(AllModules allModules, TaxonomyPredicate currModule, ModuleAutomaton moduleAutomaton) { Set fullEncoding = new HashSet<>(); for (State moduleState : moduleAutomaton.getAllStates()) { fullEncoding.addAll(moduleTaxonomyStructureForState(allModules, currModule, moduleState)); } return fullEncoding; } /** * The recursive method used in * {@link #moduleEnforceTaxonomyStructure}, to enforce the taxonomy structure in * the solution. * * @param allModules All the modules. * @param currModule Module that should be used. * @param moduleState State in which the module should be used. */ private static Set moduleTaxonomyStructureForState(AllModules allModules, TaxonomyPredicate currModule, State moduleState) { SLTLxAtom superModuleState = new SLTLxAtom(AtomType.MODULE, currModule, moduleState); Set fullEncoding = new HashSet<>(); List subModulesStates = new ArrayList<>(); if (!(currModule.getSubPredicates() == null || currModule.getSubPredicates().isEmpty())) { /* * Ensuring the TOP-DOWN taxonomy tree dependency */ for (TaxonomyPredicate subModule : APEUtils.safe(currModule.getSubPredicates())) { if (subModule == null) { log.error("Submodule is 'null': " + currModule.getPredicateID() + " ->" + currModule.getSubPredicates().toString()); } SLTLxAtom subModuleState = new SLTLxAtom(AtomType.MODULE, subModule, moduleState); subModulesStates.add(subModuleState); fullEncoding.addAll(moduleTaxonomyStructureForState(allModules, subModule, moduleState)); } /* * Ensuring the TOP-DOWN taxonomy tree dependency */ fullEncoding.add( new SLTLxImplication( superModuleState, new SLTLxDisjunction(subModulesStates))); /* * Ensuring the BOTTOM-UP taxonomy tree dependency */ for (SLTLxAtom subModuleState : subModulesStates) { fullEncoding.add( new SLTLxImplication( subModuleState, superModuleState)); } } return fullEncoding; } /** * Gets predicate pairs. * * @param predicateList List of predicates. * @return A list of pairs of tools from modules. Note that the abstract * modules are not returned, only the unique pairs of modules that are * representing actual tools. */ public static List> getPredicatePairs(List predicateList) { List> pairs = new ArrayList<>(); for (int i = 0; i < predicateList.size() - 1; i++) { for (int j = i + 1; j < predicateList.size(); j++) { pairs.add(new Pair<>(predicateList.get(i), predicateList.get(j))); } } return pairs; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy