From 0aae09fd4c1825cdd1a23beed8a6fbbaefcd4af8 Mon Sep 17 00:00:00 2001 From: Vedran Kasalica Date: Mon, 23 Sep 2024 13:32:09 +0200 Subject: [PATCH 01/13] Improve APE documentation, bio.tools API and constraint templates --- pom.xml | 14 +- src/main/java/nl/uu/cs/ape/APE.java | 5 - src/main/java/nl/uu/cs/ape/Main.java | 3 +- .../uu/cs/ape/configuration/APERunConfig.java | 9 - .../cs/ape/constraints/ConstraintFactory.java | 39 ++++ .../nl/uu/cs/ape/domain/APEDomainSetup.java | 29 +++ .../java/nl/uu/cs/ape/domain/BioToolsAPI.java | 176 +++++++++++++++++- .../nl/uu/cs/ape/models/AllPredicates.java | 4 +- .../java/nl/uu/cs/ape/models/AllTypes.java | 8 +- src/main/java/nl/uu/cs/ape/models/Type.java | 7 +- .../nl/uu/cs/ape/models/enums/AtomType.java | 4 +- .../logic/constructs/TaxonomyPredicate.java | 2 +- .../sltlxStruc/SLTLxVarQuantification.java | 4 +- .../ape/models/sltlxStruc/SLTLxVariable.java | 17 +- .../SLTLxTemplateFormula.java | 84 ++++++++- .../minisat/EnforceTypeRelatedRules.java | 16 +- .../solver/minisat/SATSynthesisEngine.java | 12 +- .../java/nl/uu/cs/ape/utils/APEUtils.java | 24 +-- 18 files changed, 377 insertions(+), 80 deletions(-) diff --git a/pom.xml b/pom.xml index 0f6f86b..4eebddb 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 io.github.sanctuuary APE - 2.3.0 + 2.4.0 jar io.github.sanctuuary:APE APE is a command line tool and an API for the automated exploration of possible computational pipelines (workflows) from large collections of computational tools. @@ -31,8 +31,8 @@ UTF-8 - 1.8 - 1.8 + 17 + 17 @@ -41,8 +41,8 @@ maven-compiler-plugin 3.8.1 - 1.8 - 1.8 + 17 + 17 -Xlint:all @@ -67,8 +67,8 @@ implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> nl.uu.cs.ape.Main - 1.8 - 1.8 + 17 + 17 diff --git a/src/main/java/nl/uu/cs/ape/APE.java b/src/main/java/nl/uu/cs/ape/APE.java index e615d32..622e64a 100644 --- a/src/main/java/nl/uu/cs/ape/APE.java +++ b/src/main/java/nl/uu/cs/ape/APE.java @@ -1,22 +1,17 @@ package nl.uu.cs.ape; import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; import java.util.Collection; -import java.util.Map; import java.util.SortedSet; import org.json.JSONException; import org.json.JSONObject; import org.semanticweb.owlapi.model.OWLOntologyCreationException; -import org.yaml.snakeyaml.Yaml; -import guru.nidi.graphviz.attribute.For; import guru.nidi.graphviz.attribute.Rank.RankDir; import guru.nidi.graphviz.engine.Format; import lombok.extern.slf4j.Slf4j; diff --git a/src/main/java/nl/uu/cs/ape/Main.java b/src/main/java/nl/uu/cs/ape/Main.java index e0b07f7..3e645bf 100644 --- a/src/main/java/nl/uu/cs/ape/Main.java +++ b/src/main/java/nl/uu/cs/ape/Main.java @@ -1,6 +1,5 @@ package nl.uu.cs.ape; -import guru.nidi.graphviz.attribute.Rank.RankDir; import lombok.extern.slf4j.Slf4j; import nl.uu.cs.ape.configuration.APEConfigException; import nl.uu.cs.ape.configuration.APERunConfig; @@ -97,7 +96,7 @@ public static void main(String[] args) { } else { try { APE.writeSolutionToFile(solutions); - APE.writeDataFlowGraphs(solutions, RankDir.TOP_TO_BOTTOM); + APE.writeTavernaDesignGraphs(solutions); // APE.writeControlFlowGraphs(solutions, RankDir.LEFT_TO_RIGHT); APE.writeExecutableWorkflows(solutions); APE.writeCWLWorkflows(solutions); diff --git a/src/main/java/nl/uu/cs/ape/configuration/APERunConfig.java b/src/main/java/nl/uu/cs/ape/configuration/APERunConfig.java index bfc2cd5..930b5a3 100644 --- a/src/main/java/nl/uu/cs/ape/configuration/APERunConfig.java +++ b/src/main/java/nl/uu/cs/ape/configuration/APERunConfig.java @@ -646,8 +646,6 @@ public interface IBuildStage { IBuildStage withNoCWL(int noCWL); - IBuildStage withNoExecutableCWL(int noExecutableCWL); - IBuildStage withProgramInputs(List programInputs); IBuildStage withProgramOutputs(List programOutputs); @@ -678,7 +676,6 @@ public static final class Builder implements ISolutionMinLengthStage, ISolutionM private int noExecutions; private int noGraphs; private int noCWL; - private int noExecutableCWL; private List programInputs = Collections.emptyList(); private List programOutputs = Collections.emptyList(); private ConfigEnum useWorkflowInput; @@ -749,12 +746,6 @@ public IBuildStage withNoCWL(int noCWL) { return this; } - @Override - public IBuildStage withNoExecutableCWL(int noExecutableCWL) { - this.noExecutableCWL = noExecutableCWL; - return this; - } - @Override public IBuildStage withProgramInputs(List programInputs) { this.programInputs = programInputs; diff --git a/src/main/java/nl/uu/cs/ape/constraints/ConstraintFactory.java b/src/main/java/nl/uu/cs/ape/constraints/ConstraintFactory.java index c54391a..b2dec0a 100644 --- a/src/main/java/nl/uu/cs/ape/constraints/ConstraintFactory.java +++ b/src/main/java/nl/uu/cs/ape/constraints/ConstraintFactory.java @@ -227,6 +227,13 @@ public boolean initializeConstraints(AllModules allModules, AllTypes allTypes) { "No operation that belongs to the subtree should be repeated over."); addConstraintTemplate(currTemplate); + /* + * ID: unique_inputs + */ + currTemplate = new ConstraintUnique_Inputs("unique_inputs", moduleParam1, + "All inputs per tool must be unique."); + addConstraintTemplate(currTemplate); + /* * ID: gen_t * @@ -944,4 +951,36 @@ public String getConstraint(List parameters, APEDomainSetup d mappings); } } + + /** + * Implements constraints of the form:
+ * All inputs per tool should be unique. + * {@link #getConstraint}. + */ + public class ConstraintUnique_Inputs extends ConstraintTemplate { + /** + * Instantiates a new Constraint use type. + * + * @param id the id + * @param parametersNo the parameters no + * @param description the description + */ + protected ConstraintUnique_Inputs(String id, List parametersNo, + String description) { + super(id, parametersNo, description); + } + + @Override + public String getConstraint(List parameters, APEDomainSetup domainSetup, + ModuleAutomaton moduleAutomaton, TypeAutomaton typeAutomaton, SATAtomMappings mappings) { + if (parameters.size() != this.getNoOfParameters()) { + super.throwParametersError(parameters.size()); + return null; + } + + return SLTLxTemplateFormula.useUniqueInputs(moduleAutomaton, + typeAutomaton, mappings); + } + } + } diff --git a/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java b/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java index 7ed5538..7944b02 100644 --- a/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java +++ b/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java @@ -1,5 +1,7 @@ package nl.uu.cs.ape.domain; +import java.io.File; +import java.io.FileInputStream; import java.io.IOException; import java.util.*; @@ -7,6 +9,8 @@ import org.json.JSONException; import org.json.JSONObject; +import lombok.Getter; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import nl.uu.cs.ape.configuration.APECoreConfig; import nl.uu.cs.ape.configuration.ToolAnnotationTag; @@ -14,6 +18,7 @@ import nl.uu.cs.ape.constraints.ConstraintFormatException; import nl.uu.cs.ape.constraints.ConstraintTemplate; import nl.uu.cs.ape.constraints.ConstraintTemplateParameter; +import nl.uu.cs.ape.utils.APEFiles; import nl.uu.cs.ape.utils.APEUtils; import nl.uu.cs.ape.models.AbstractModule; import nl.uu.cs.ape.models.AllModules; @@ -21,6 +26,7 @@ import nl.uu.cs.ape.models.AuxiliaryPredicate; import nl.uu.cs.ape.models.ConstraintTemplateData; import nl.uu.cs.ape.models.Module; +import nl.uu.cs.ape.models.SATAtomMappings; import nl.uu.cs.ape.models.Type; import nl.uu.cs.ape.models.logic.constructs.TaxonomyPredicate; @@ -52,6 +58,12 @@ public class APEDomainSetup { */ private String ontologyPrefixIRI; + @Setter + /** + * Object used to write locally CNF SAT problem specification (in human readable format). + */ + private String writeLocalCNF = null; + /** * Object used to create temporal constraints. */ @@ -551,4 +563,21 @@ public List getHelperPredicates() { return helperPredicates; } + /** + * Write locally the SAT (CNF) workflow specification in human readable format. + * + * @param satInputFile - File containing the SAT problem specification. + * @param mappings - Mappings between the SAT problem and the domain. + * @throws IOException - Error in writing the file to the local file system. + */ + public void localCNF(File satInputFile, SATAtomMappings mappings) throws IOException { + if (writeLocalCNF != null) { + FileInputStream cnfStream = new FileInputStream(satInputFile); + String encoding = APEUtils.convertCNF2humanReadable(cnfStream, mappings); + cnfStream.close(); + + APEFiles.write2file(encoding, new File(writeLocalCNF), false); + } + } + } diff --git a/src/main/java/nl/uu/cs/ape/domain/BioToolsAPI.java b/src/main/java/nl/uu/cs/ape/domain/BioToolsAPI.java index 6ddbf45..fc45614 100644 --- a/src/main/java/nl/uu/cs/ape/domain/BioToolsAPI.java +++ b/src/main/java/nl/uu/cs/ape/domain/BioToolsAPI.java @@ -2,7 +2,9 @@ import java.io.File; import java.io.IOException; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.apache.commons.io.FileUtils; import org.json.JSONArray; @@ -28,7 +30,7 @@ public class BioToolsAPI { /** Http-Client */ - public final static OkHttpClient client = new OkHttpClient(); + private static final OkHttpClient client = new OkHttpClient(); /** * Send Get request to get tool annotations for each elements in JSONArray from @@ -55,7 +57,7 @@ public static void fetchToolSet(String listFilePath, String destinationFilePath) * @return JSONArray with the tool annotations. * @throws IOException - If the file cannot be read or written. */ - public static JSONArray readListOfTools(String filePath) throws IOException { + private static JSONArray readListOfTools(String filePath) throws IOException { File toolList = new File(filePath); JSONArray toolListJson = new JSONArray(FileUtils.readFileToString(toolList, "UTF-8")); @@ -71,7 +73,7 @@ public static JSONArray readListOfTools(String filePath) throws IOException { * @return JSONArray with the tool annotations. * @throws IOException - If the file cannot be read or written. */ - public static JSONArray getToolsFromDomain(String domainName) throws IOException { + private static JSONArray getToolsFromDomain(String domainName) throws IOException { JSONArray toolAnnotations = null; if (!domainName.equals("")) { toolAnnotations = fetchToolsFromURI("https://bio.tools/api/t?domain=" + domainName + "&format=json"); @@ -87,14 +89,15 @@ public static JSONArray getToolsFromDomain(String domainName) throws IOException * * @throws IOException */ - public static JSONArray getToolsFromEDAMTopic(String topicName) throws IOException { + public static JSONObject getToolsFromEDAMTopic(String topicName) throws IOException { JSONArray toolAnnotations = null; - if (topicName != "") { + if (!topicName.equals("")) { toolAnnotations = fetchToolsFromURI("https://bio.tools/api/t?topicID=\"" + topicName + "\"&format=json"); } else { toolAnnotations = fetchToolsFromURI("https://bio.tools/api/t?format=json"); } - return toolAnnotations; + + return convertBioTools2ApeStrict(toolAnnotations); } /** @@ -178,7 +181,7 @@ private static JSONArray fetchToolsFromURI(String url) throws JSONException, IOE * the APE library. * @throws JSONException the json exception */ - public static JSONObject convertBioTools2Ape(JSONArray bioToolsAnnotation) throws JSONException { + private static JSONObject convertBioTools2Ape(JSONArray bioToolsAnnotation) throws JSONException { JSONArray apeToolsAnnotations = new JSONArray(); for (int i = 0; i < bioToolsAnnotation.length(); i++) { @@ -254,4 +257,163 @@ public static JSONObject convertBioTools2Ape(JSONArray bioToolsAnnotation) throw return new JSONObject().put("functions", apeToolsAnnotations); } + + /** + * Method converts tools annotated using 'bio.tools' standard (see bio.tools + * API), into standard supported by the APE library. It is a strict + * conversion, where only tools that have inputs and outputs types and formats + * are accepted. + *

+ * In practice, the method takes a {@link JSONArray} as an argument, where each + * {@link JSONObject} in the array represents a tool annotated using 'bio.tools' + * standard, and returns a {@link JSONObject} that represents tool annotations + * that can be used by the APE library. + * + * @param bioToolsAnnotation A {@link JSONArray} object, that contains list of + * annotated tools ({@link JSONObject}s) according the + * bio.tools specification (see bio.tools + * API) + * @return {@link JSONObject} that represents the tool annotation supported by + * the APE library. + * @throws JSONException the json exception + */ + public static JSONObject convertBioTools2ApeStrict(JSONArray bioToolsAnnotation) throws JSONException { + + Set notAcceptedTools = new HashSet<>(); + Set noFunctionAnnotation = new HashSet<>(); + Set toolsMissingDimension = new HashSet<>(); + Set annotatedBioTools = new HashSet<>(); + int notAcceptedOperations = 0; + int bioToolFunctions = 0; + + JSONArray apeToolsAnnotations = new JSONArray(); + Set toolsList = new HashSet<>(); + + for (int i = 0; i < bioToolsAnnotation.length(); i++) { + + JSONObject bioJsonTool = bioToolsAnnotation.getJSONObject(i); + List functions = APEUtils.getListFromJson(bioJsonTool, "function", JSONObject.class); + if (functions.isEmpty()) { + noFunctionAnnotation.add(bioJsonTool.getString("biotoolsID")); + notAcceptedTools.add(bioJsonTool.getString("biotoolsID")); + continue; + } + int functionNo = 1; + functionloop: for (JSONObject function : functions) { + bioToolFunctions++; + JSONObject apeJsonTool = new JSONObject(); + apeJsonTool.put("label", bioJsonTool.getString("name")); + if (functions.size() > 1) { + apeJsonTool.put("id", bioJsonTool.getString("biotoolsID") + "_op" + (functionNo++)); + } else { + apeJsonTool.put("id", bioJsonTool.getString("biotoolsID")); + } + + JSONArray apeTaxonomyTerms = new JSONArray(); + + JSONArray operations = function.getJSONArray("operation"); + for (int j = 0; j < operations.length(); j++) { + JSONObject bioOperation = operations.getJSONObject(j); + apeTaxonomyTerms.put(bioOperation.get("uri")); + } + apeJsonTool.put("taxonomyOperations", apeTaxonomyTerms); +// reading inputs + JSONArray apeInputs = new JSONArray(); + JSONArray bioInputs = function.getJSONArray("input"); +// for each input + for (int j = 0; j < bioInputs.length(); j++) { + JSONObject bioInput = bioInputs.getJSONObject(j); + JSONObject apeInput = new JSONObject(); + JSONArray apeInputTypes = new JSONArray(); + JSONArray apeInputFormats = new JSONArray(); +// add all data types + for (JSONObject bioType : APEUtils.getListFromJson(bioInput, "data", JSONObject.class)) { + apeInputTypes.put(bioType.getString("uri")); + } + if (apeInputTypes.length() == 0) { + notAcceptedTools.add(bioJsonTool.getString("biotoolsID")); + toolsMissingDimension.add(bioJsonTool.getString("biotoolsID")); + notAcceptedOperations++; + continue functionloop; + } + apeInput.put("data_0006", apeInputTypes); +// add all data formats (or just the first one) + for (JSONObject bioType : APEUtils.getListFromJson(bioInput, "format", JSONObject.class)) { + apeInputFormats.put(bioType.getString("uri")); + } + if (apeInputFormats.length() == 0) { + notAcceptedTools.add(bioJsonTool.getString("biotoolsID")); + toolsMissingDimension.add(bioJsonTool.getString("biotoolsID")); + notAcceptedOperations++; + continue functionloop; + } + apeInput.put("format_1915", apeInputFormats); + + apeInputs.put(apeInput); + } + apeJsonTool.put("inputs", apeInputs); + +// reading outputs + JSONArray apeOutputs = new JSONArray(); + JSONArray bioOutputs = function.getJSONArray("output"); +// for each output + for (int j = 0; j < bioOutputs.length(); j++) { + + JSONObject bioOutput = bioOutputs.getJSONObject(j); + JSONObject apeOutput = new JSONObject(); + JSONArray apeOutputTypes = new JSONArray(); + JSONArray apeOutputFormats = new JSONArray(); +// add all data types + for (JSONObject bioType : APEUtils.getListFromJson(bioOutput, "data", JSONObject.class)) { + apeOutputTypes.put(bioType.getString("uri")); + } + if (apeOutputTypes.length() == 0) { + notAcceptedTools.add(bioJsonTool.getString("biotoolsID")); + toolsMissingDimension.add(bioJsonTool.getString("biotoolsID")); + notAcceptedOperations++; + continue functionloop; + } + apeOutput.put("data_0006", apeOutputTypes); +// add all data formats + for (JSONObject bioType : APEUtils.getListFromJson(bioOutput, "format", JSONObject.class)) { + apeOutputFormats.put(bioType.getString("uri")); + } + if (apeOutputFormats.length() == 0) { + notAcceptedTools.add(bioJsonTool.getString("biotoolsID")); + toolsMissingDimension.add(bioJsonTool.getString("biotoolsID")); + notAcceptedOperations++; + continue functionloop; + } + apeOutput.put("format_1915", apeOutputFormats); + + apeOutputs.put(apeOutput); + } + apeJsonTool.put("outputs", apeOutputs); + + // if the tool has outputs add it to the tool annotation + if (apeInputs.length() > 0 && apeOutputs.length() > 0) { + toolsList.add(bioJsonTool.getString("biotoolsID")); + apeToolsAnnotations.put(apeJsonTool); + annotatedBioTools.add(bioJsonTool.getString("biotoolsID")); + } else { + notAcceptedTools.add(bioJsonTool.getString("biotoolsID")); + notAcceptedOperations++; + } + } + } + log.info("Provide bio.tools: " + bioToolsAnnotation.length()); + log.info("Total bio.tools functions: " + bioToolFunctions); + log.info("Errored bio.tools functions: " + notAcceptedOperations); + log.info("No functions: " + noFunctionAnnotation.size()); + log.info("Created APE annotations: " + apeToolsAnnotations.length()); + + JSONArray tools = new JSONArray(); + for (String tool : toolsList) { + tools.put(tool); + } + return new JSONObject().put("functions", tools); + } + } \ No newline at end of file diff --git a/src/main/java/nl/uu/cs/ape/models/AllPredicates.java b/src/main/java/nl/uu/cs/ape/models/AllPredicates.java index 0a00e6c..365a02f 100644 --- a/src/main/java/nl/uu/cs/ape/models/AllPredicates.java +++ b/src/main/java/nl/uu/cs/ape/models/AllPredicates.java @@ -83,7 +83,9 @@ public boolean trimTaxonomy() { List toRemove = new ArrayList<>(); for (TaxonomyPredicate subClass : APEUtils.safe(root.getSubPredicates())) { if (subClass == null) { - } else if (subClass.getIsRelevant()) { + continue; + } + if (subClass.getIsRelevant()) { trimSubTaxonomy(subClass); } else { toRemove.add(subClass); diff --git a/src/main/java/nl/uu/cs/ape/models/AllTypes.java b/src/main/java/nl/uu/cs/ape/models/AllTypes.java index e95d212..b2a56a5 100644 --- a/src/main/java/nl/uu/cs/ape/models/AllTypes.java +++ b/src/main/java/nl/uu/cs/ape/models/AllTypes.java @@ -234,17 +234,17 @@ public Class getPredicateClass() { * @return List of pairs of types. */ public List> getTypePairsForEachSubTaxonomy() { - List> pairs = new ArrayList>(); + List> pairs = new ArrayList<>(); /* * Create a list for each subtree of the Data Taxonomy (e.g. TypeSubTaxonomy, * FormatSubTaxonomy). Each of these lists represents a class of mutually * exclusive types. */ - Map> subTreesMap = new HashMap>(); + Map> subTreesMap = new HashMap<>(); // Add each of the dimension roots (type and format taxonomy) to the list for (String subRoot : APEUtils.safe(getAllRootIDs())) { - subTreesMap.put(subRoot, new ArrayList()); + subTreesMap.put(subRoot, new ArrayList<>()); } /* @@ -272,7 +272,7 @@ public List> getTypePairsForEachSubTaxonomy() { for (List iterator : subTreesMap.values()) { for (int i = 0; i < iterator.size() - 1; i++) { for (int j = i + 1; j < iterator.size(); j++) { - pairs.add(new Pair(iterator.get(i), iterator.get(j))); + pairs.add(new Pair<>(iterator.get(i), iterator.get(j))); } } } diff --git a/src/main/java/nl/uu/cs/ape/models/Type.java b/src/main/java/nl/uu/cs/ape/models/Type.java index b9473bd..aec6cac 100644 --- a/src/main/java/nl/uu/cs/ape/models/Type.java +++ b/src/main/java/nl/uu/cs/ape/models/Type.java @@ -120,14 +120,17 @@ public static Type taxonomyInstanceFromJson(JSONObject jsonParam, APEDomainSetup /* for each dimensions a disjoint array of types/tools is given */ for (String currTypeLabel : APEUtils.getListFromJson(jsonParam, currRootLabel, String.class)) { String currTypeIRI = currTypeLabel; - if (allTypes.get(currTypeIRI, curRootIRI) == null) { + + Type currType = allTypes.get(currTypeIRI, curRootIRI); + if (currType == null) { currTypeIRI = APEUtils.createClassIRI(currTypeLabel, domainSetup.getOntologyPrefixIRI()); + currType = allTypes.get(currTypeIRI, curRootIRI); } if (currRootLabel.equals(allTypes.getLabelRootID())) { labelDefined = true; } - Type currType = allTypes.get(currTypeIRI, curRootIRI); + if (currType != null) { if (isOutputData) { currType.setAsRelevantTaxonomyTerm(allTypes); diff --git a/src/main/java/nl/uu/cs/ape/models/enums/AtomType.java b/src/main/java/nl/uu/cs/ape/models/enums/AtomType.java index ead9e70..4e2229b 100644 --- a/src/main/java/nl/uu/cs/ape/models/enums/AtomType.java +++ b/src/main/java/nl/uu/cs/ape/models/enums/AtomType.java @@ -84,9 +84,9 @@ public static String getStringShortcut(AtomType elem, Integer blockNumber, int s if (elem == MODULE) { return "Tool" + stateNumber; } else if (elem == MEMORY_TYPE) { - return "MemT" + blockNumber + "." + stateNumber; + return "Out" + blockNumber + "." + stateNumber; } else if (elem == USED_TYPE) { - return "UsedT" + blockNumber + "." + stateNumber; + return "In" + blockNumber + "." + stateNumber; } else if (elem == null) { return "nullMem"; } diff --git a/src/main/java/nl/uu/cs/ape/models/logic/constructs/TaxonomyPredicate.java b/src/main/java/nl/uu/cs/ape/models/logic/constructs/TaxonomyPredicate.java index a85a633..6c7f6ef 100644 --- a/src/main/java/nl/uu/cs/ape/models/logic/constructs/TaxonomyPredicate.java +++ b/src/main/java/nl/uu/cs/ape/models/logic/constructs/TaxonomyPredicate.java @@ -308,7 +308,7 @@ public String toShortString() { * @param allPredicates Set of all the predicates. */ public void printTree(String str, AllPredicates allPredicates) { - log.debug(str + toShortString() + "[" + getNodeType() + "]"); + log.info(str + toShortString() + "[" + getNodeType() + "]"); for (TaxonomyPredicate predicate : APEUtils.safe(this.subPredicates)) { predicate.printTree(str + ". ", allPredicates); } diff --git a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVarQuantification.java b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVarQuantification.java index aee5382..0fcd677 100644 --- a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVarQuantification.java +++ b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVarQuantification.java @@ -37,7 +37,7 @@ public Set getCNFEncoding(int stateNo, SLTLxVariableSubstitutionCollecti */ clauses.addAll(flatBoundVariable.getVariableSubstitutionToPreserveProperties(stateNo, newVarMapping, synthesisEngine)); - clauses.addAll(flatBoundVariable.getVariableMutualExclusion(stateNo, newVarMapping, synthesisEngine)); + clauses.addAll(flatBoundVariable.getVariableUniqueSubstitution(stateNo, newVarMapping, synthesisEngine)); return clauses; } @@ -56,7 +56,7 @@ public Set getNegatedCNFEncoding(int stateNo, SLTLxVariableSubstitutionC */ clauses.addAll(flatBoundVariable.getVariableSubstitutionToPreserveProperties(stateNo, newVarMapping, synthesisEngine)); - clauses.addAll(flatBoundVariable.getVariableMutualExclusion(stateNo, newVarMapping, synthesisEngine)); + clauses.addAll(flatBoundVariable.getVariableUniqueSubstitution(stateNo, newVarMapping, synthesisEngine)); return clauses; } diff --git a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVariable.java b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVariable.java index e1a78e1..e325545 100644 --- a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVariable.java +++ b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVariable.java @@ -349,7 +349,14 @@ public static Set getVariableDomain(int stateNo, SATSynthesisEngine synth return variableDomain; } - public Set getVariableMutualExclusion(int stateNo, SLTLxVariableSubstitutionCollection variableMapping, + /** + * Get the set of clauses that enforce that the a variable cannot reference two different data instances. + * @param stateNo - current state in the SLTLx model + * @param variableMapping - collection of substitutions for each variable + * @param synthesisEngine - synthesis engine + * @return Set of clauses that encode the possible variable substitution. + */ + public Set getVariableUniqueSubstitution(int stateNo, SLTLxVariableSubstitutionCollection variableMapping, SATSynthesisEngine synthesisEngine) { Set allClauses = new HashSet<>(); /** @@ -357,10 +364,10 @@ public Set getVariableMutualExclusion(int stateNo, SLTLxVariableSubstitu * and thus we use the next state to get the domain of the variable. */ int nextStateNo = stateNo + 1; - Set> statePairs = APEUtils + Set> statePairs = APEUtils .getUniquePairs(synthesisEngine.getTypeAutomaton().getAllMemoryStatesUntilBlockNo(nextStateNo)); - statePairs.forEach(statePair -> { + statePairs.forEach(statePair -> allClauses.addAll( new SLTLxNegatedConjunction( new SLTLxAtomVar( @@ -371,8 +378,8 @@ public Set getVariableMutualExclusion(int stateNo, SLTLxVariableSubstitu AtomVarType.VAR_VALUE, statePair.getSecond(), this)) - .getCNFEncoding(stateNo, variableMapping, synthesisEngine)); - }); + .getCNFEncoding(stateNo, variableMapping, synthesisEngine)) + ); return allClauses; } diff --git a/src/main/java/nl/uu/cs/ape/models/templateFormulas/SLTLxTemplateFormula.java b/src/main/java/nl/uu/cs/ape/models/templateFormulas/SLTLxTemplateFormula.java index 108be1e..135d637 100644 --- a/src/main/java/nl/uu/cs/ape/models/templateFormulas/SLTLxTemplateFormula.java +++ b/src/main/java/nl/uu/cs/ape/models/templateFormulas/SLTLxTemplateFormula.java @@ -615,11 +615,61 @@ public static String notConnectedModules(TaxonomyPredicate firstPredicate, Taxon return constraints.toString(); } + /** + * Creates a CNF representation of the Constraint:
+ * Do not repeat using the same tool. + * + * @param predicate + * @param domainSetup + * @param moduleAutomaton + * @param typeAutomaton + * @param mappings + * @return + */ 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); + + // 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(operation, secondModuleState, AtomType.MODULE) + + " 0\n"); + }); + + } + } + + return constraints.toString(); + } + + /** + * Creates a CNF representation of the Constraint:
+ * The same tools that belong to the sub-taxonomy should not be connected. + * + * @param predicate - Root predicate of the sub-taxonomy. + * @param domainSetup + * @param moduleAutomaton + * @param typeAutomaton + * @param mappings + * @return + */ + public static String notConnectModules(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++) { @@ -657,14 +707,36 @@ public static String notRepeatModules(TaxonomyPredicate predicate, APEDomainSetu } /** - * 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. + * Creates a CNF representation of the Constraint:
+ * Tools (that belong to the sub-taxonomy) should have all inputs unique. + * + * @param moduleAutomaton + * @param typeAutomaton + * @param mappings + * @return */ - private static String combine(int int1, int int2) { - return int1 + "_" + int2; + public static String useUniqueInputs( + ModuleAutomaton moduleAutomaton, TypeAutomaton typeAutomaton, SATAtomMappings mappings) { + + StringBuilder constraints = new StringBuilder(); + for (int blockNo = 0; blockNo < typeAutomaton.getLength(); blockNo++) { + Block inputs = typeAutomaton.getUsedTypesBlock(blockNo); + Set> inputPairs = new HashSet<>(); + inputPairs.addAll(APEUtils.getUniquePairs(inputs.getStates())); + for(State memoryState : typeAutomaton.getAllMemoryStatesUntilBlockNo(blockNo)){ + for (Pair inputPair : inputPairs) { + constraints.append("-").append(mappings.add(memoryState, inputPair.getFirst(), AtomType.MEM_TYPE_REFERENCE)).append(" "); + constraints.append("-").append(mappings.add(memoryState, inputPair.getSecond(), AtomType.MEM_TYPE_REFERENCE)).append(" 0\n"); + } + } + + + } + return constraints.toString(); } } + + +// pairs of inputs X1 X2 not ref(x1, O) or not ref(x2, O) \ No newline at end of file diff --git a/src/main/java/nl/uu/cs/ape/solver/minisat/EnforceTypeRelatedRules.java b/src/main/java/nl/uu/cs/ape/solver/minisat/EnforceTypeRelatedRules.java index 8e10042..ae4c841 100644 --- a/src/main/java/nl/uu/cs/ape/solver/minisat/EnforceTypeRelatedRules.java +++ b/src/main/java/nl/uu/cs/ape/solver/minisat/EnforceTypeRelatedRules.java @@ -235,21 +235,21 @@ private static Set typeEnforceTaxonomyStructureForState(TaxonomyPr * Encodes rules that ensure the initial workflow input. * * @param allTypes Set of all the types in the domain - * @param program_inputs Input types for the program. + * @param programInputs Input types for the program. * @param typeAutomaton Automaton representing the type states in the model * @return The String representation of the initial input encoding. * @throws APEConfigException Exception thrown when one of the output types is * not defined in the taxonomy. */ - public static Set workflowInputs(AllTypes allTypes, List program_inputs, + public static Set workflowInputs(AllTypes allTypes, List programInputs, TypeAutomaton typeAutomaton) throws APEConfigException { Set fullEncoding = new HashSet<>(); List workflowInputStates = typeAutomaton.getWorkflowInputBlock().getStates(); for (int i = 0; i < workflowInputStates.size(); i++) { State currState = workflowInputStates.get(i); - if (i < program_inputs.size()) { - Type currType = program_inputs.get(i); + if (i < programInputs.size()) { + Type currType = programInputs.get(i); if (allTypes.get(currType.getPredicateID()) == null) { throw APEConfigException.workflowIODataTypeNotInDomain(currType.getPredicateID()); } @@ -274,20 +274,20 @@ public static Set workflowInputs(AllTypes allTypes, List pro * Encodes the rules that ensure generation of the workflow output. * * @param allTypes Set of all the types in the domain - * @param program_outputs Output types for the program. + * @param programOutputs Output types for the program. * @param typeAutomaton Automaton representing the type states in the model * @return String representation of the workflow output encoding. * @throws APEConfigException Exception thrown when one of the output types is * not defined in the taxonomy. */ - public static Set workdlowOutputs(AllTypes allTypes, List program_outputs, + public static Set workflowOutputs(AllTypes allTypes, List programOutputs, TypeAutomaton typeAutomaton) throws APEConfigException { Set fullEncoding = new HashSet<>(); List workflowOutputStates = typeAutomaton.getWorkflowOutputBlock().getStates(); for (int i = 0; i < workflowOutputStates.size(); i++) { - if (i < program_outputs.size()) { - TaxonomyPredicate currType = program_outputs.get(i); + if (i < programOutputs.size()) { + TaxonomyPredicate currType = programOutputs.get(i); if (allTypes.get(currType.getPredicateID()) == null) { throw APEConfigException.workflowIODataTypeNotInDomain(currType.getPredicateID()); } diff --git a/src/main/java/nl/uu/cs/ape/solver/minisat/SATSynthesisEngine.java b/src/main/java/nl/uu/cs/ape/solver/minisat/SATSynthesisEngine.java index 5f602be..28a8116 100644 --- a/src/main/java/nl/uu/cs/ape/solver/minisat/SATSynthesisEngine.java +++ b/src/main/java/nl/uu/cs/ape/solver/minisat/SATSynthesisEngine.java @@ -248,7 +248,7 @@ public boolean synthesisEncoding() throws IOException { * Encode the workflow output */ SLTLxFormula.appendCNFToFile(cnfEncoding, this, EnforceTypeRelatedRules - .workdlowOutputs(domainSetup.getAllTypes(), runConfig.getProgramOutputs(), typeAutomaton)); + .workflowOutputs(domainSetup.getAllTypes(), runConfig.getProgramOutputs(), typeAutomaton)); /* * Encode rule that the given inputs should not be used as workflow outputs @@ -287,14 +287,12 @@ public boolean synthesisEncoding() throws IOException { /* add the cnf encoding file to Desktop */ // Files.copy(satInputFile, new File("~/Desktop/tmp"+ problemSetupStartTime)); + /* - * Add human readable version of the cnf encoding file to Desktop. Used when - * needed. + * Add human readable version of the cnf encoding file to Desktop. Used only when + * explicitly specified (used for local testing). */ - // FileInputStream cnfStream = new FileInputStream(satInputFile); - // String encoding = APEUtils.convertCNF2humanReadable(cnfStream, mappings); - // cnfStream.close(); - // APEFiles.write2file(encoding, new File("~/Desktop/tmp.txt"), false); + domainSetup.localCNF(satInputFile, mappings); long problemSetupTimeElapsedMillis = System.currentTimeMillis() - problemSetupStartTime; log.info("Total problem setup time: " + (problemSetupTimeElapsedMillis / 1000F) + " sec (" + clauses diff --git a/src/main/java/nl/uu/cs/ape/utils/APEUtils.java b/src/main/java/nl/uu/cs/ape/utils/APEUtils.java index 447c6ec..6738ece 100644 --- a/src/main/java/nl/uu/cs/ape/utils/APEUtils.java +++ b/src/main/java/nl/uu/cs/ape/utils/APEUtils.java @@ -617,18 +617,18 @@ public static void printMemoryStatus(boolean debugMode) { } /** - * Get all unique pairs of PredicateLabels within the collection. - * - * @param set - Set of PredicateLabel that should be used to create the pairs - * @return Set of unique pairs. - */ - public static Set> getUniquePairs(Collection set) { - Set> pairs = new HashSet<>(); - set.stream().forEach(ele1 -> set.stream().filter(ele2 -> ele1.compareTo(ele2) < 0) - .forEach(ele2 -> pairs.add(new Pair<>(ele1, ele2)))); - return pairs; - - } + * Get all unique pairs of PredicateLabels within the collection. + * + * @param - The type that extends PredicateLabel + * @param set - Set of PredicateLabel that should be used to create the pairs + * @return Set of unique pairs. + */ + public static Set> getUniquePairs(Collection set) { + Set> pairs = new HashSet<>(); + set.stream().forEach(ele1 -> set.stream().filter(ele2 -> ele1.compareTo(ele2) < 0) + .forEach(ele2 -> pairs.add(new Pair<>(ele1, ele2)))); + return pairs; + } /** * Get unique pairs of elements within 2 collections. From cf5bd23df661b4f38ebc4fd9d12890b32a3f4f97 Mon Sep 17 00:00:00 2001 From: Vedran Kasalica Date: Wed, 25 Sep 2024 11:37:06 +0200 Subject: [PATCH 02/13] Refactor bio.tools API and add expose the feature at the CLI level --- src/main/java/nl/uu/cs/ape/Main.java | 70 +++- .../nl/uu/cs/ape/domain/APEDomainSetup.java | 2 +- .../java/nl/uu/cs/ape/domain/BioToolsAPI.java | 316 ++++++------------ .../domain/BioToolsAnnotationException.java | 42 +++ .../java/nl/uu/cs/ape/utils/APEUtils.java | 29 +- 5 files changed, 241 insertions(+), 218 deletions(-) create mode 100644 src/main/java/nl/uu/cs/ape/domain/BioToolsAnnotationException.java diff --git a/src/main/java/nl/uu/cs/ape/Main.java b/src/main/java/nl/uu/cs/ape/Main.java index 3e645bf..25f7300 100644 --- a/src/main/java/nl/uu/cs/ape/Main.java +++ b/src/main/java/nl/uu/cs/ape/Main.java @@ -3,9 +3,11 @@ import lombok.extern.slf4j.Slf4j; import nl.uu.cs.ape.configuration.APEConfigException; import nl.uu.cs.ape.configuration.APERunConfig; +import nl.uu.cs.ape.domain.BioToolsAPI; import nl.uu.cs.ape.utils.APEFiles; import nl.uu.cs.ape.solver.solutionStructure.SolutionsList; +import org.apache.commons.lang3.ArrayUtils; import org.json.JSONException; import org.json.JSONObject; import org.semanticweb.owlapi.model.OWLOntologyCreationException; @@ -26,12 +28,72 @@ public class Main { * The entry point of application when the library is used in a Command Line * Interface (CLI). * - * @param args APE expects at most one (1) argument: The absolute or relative - * path to the configuration file. + * @param args APE expects at most two (2) arguments. */ public static void main(String[] args) { + + String method = args[0]; + switch (method) { + case "synthesis": + executeSynthesis(ArrayUtils.remove(args, 0)); + break; + case "convert-tools": + convertBioToolsAnnotations(ArrayUtils.remove(args, 0)); + break; + case "bio.tools": + try { + BioToolsAPI.fetchBioTools("./tools.json"); + } catch (IOException e) { + log.error("Error in fetching the tools from bio.tools."); + } + break; + default: + if (args.length == 0 || args.length == 1) { + executeSynthesis(args); + } else { + log.error("Invalid method provided."); + } + } + + } + + public static void convertBioToolsAnnotations(String[] args) { + String path; + if (args.length != 1) { + log.error("Error: bio.tools method expects path as the only additional argument."); + return; + } + + path = args[0]; + if (!APEFiles.isValidReadFile(path)) { + log.error("Error: Invalid path provided."); + return; + } + + try { + BioToolsAPI.fetchToolSet(path, "./tools.json"); + } catch (IOException e) { + log.error("Error in fetching the tools from bio.tools."); + return; + } + log.info("File generated successfully in the current directory."); + } + + /** + * The entry point of application when the library is used in a Command Line + * Interface (CLI). + * + * @param args APE expects at most two (2) arguments. + */ + public static void executeSynthesis(String[] args) { String path; int solutionsNo = -1; + + if (args.length > 2) { + log.error("Error: synthesis method expects at most two additional arguments."); + return; + } + if (args.length == 1) { path = args[0]; } else if (args.length == 2) { @@ -96,11 +158,11 @@ public static void main(String[] args) { } else { try { APE.writeSolutionToFile(solutions); + // The following method can be changed to write the solutions in different + // formats (e.g., control flow graph, data flow graph) APE.writeTavernaDesignGraphs(solutions); - // APE.writeControlFlowGraphs(solutions, RankDir.LEFT_TO_RIGHT); APE.writeExecutableWorkflows(solutions); APE.writeCWLWorkflows(solutions); - // APE.writeExecutableCWLWorkflows(solutions, apeFramework.getConfig()); } catch (IOException e) { log.error("Error in writing the solutions. to the file system."); e.printStackTrace(); diff --git a/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java b/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java index 7944b02..8e813d8 100644 --- a/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java +++ b/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java @@ -234,7 +234,7 @@ public void updateConstraints(JSONArray constraintsJSONArray) throws ConstraintF String constraintID = null; int currNode = 0; - List constraints = APEUtils.getListFromJsonList(constraintsJSONArray, JSONObject.class); + List constraints = APEUtils.getJSONListFromJSONArray(constraintsJSONArray); /* Iterate through each constraint in the list */ for (JSONObject jsonConstraint : APEUtils.safe(constraints)) { diff --git a/src/main/java/nl/uu/cs/ape/domain/BioToolsAPI.java b/src/main/java/nl/uu/cs/ape/domain/BioToolsAPI.java index fc45614..b25ce8d 100644 --- a/src/main/java/nl/uu/cs/ape/domain/BioToolsAPI.java +++ b/src/main/java/nl/uu/cs/ape/domain/BioToolsAPI.java @@ -45,10 +45,23 @@ public static void fetchToolSet(String listFilePath, String destinationFilePath) // Fetch the Limited (predefined) set of tool JSONArray bioToolsRAW = readListOfTools(listFilePath); - JSONObject apeToolAnnotation = convertBioTools2Ape(bioToolsRAW); + JSONObject apeToolAnnotation = convertBioTools2Ape(bioToolsRAW, false); APEFiles.write2file(apeToolAnnotation.toString(4), new File(destinationFilePath), false); } + /** + * Fetch the list of all the tools from the bio.tools API and save them to a + * file in a format that can be used by the APE library. + * @param destinationFilePath The path to the file where the tool annotations will be saved. + * @throws IOException If an error occurs while fetching the tools. + */ + public static void fetchBioTools(String destinationFilePath) throws IOException { + + // Fetch the Limited (predefined) set of tool + JSONObject biotools = BioToolsAPI.getToolsFromEDAMTopic(""); + APEFiles.write2file(biotools.toString(4), new File(destinationFilePath), false); + } + /** * Send Get request to get tool annotations for each elements in JSONArray from * bio.tools API. It writes the result to a JSONArray. @@ -73,21 +86,24 @@ private static JSONArray readListOfTools(String filePath) throws IOException { * @return JSONArray with the tool annotations. * @throws IOException - If the file cannot be read or written. */ - private static JSONArray getToolsFromDomain(String domainName) throws IOException { + private static JSONObject getToolsFromDomain(String domainName) throws IOException { JSONArray toolAnnotations = null; if (!domainName.equals("")) { toolAnnotations = fetchToolsFromURI("https://bio.tools/api/t?domain=" + domainName + "&format=json"); } else { toolAnnotations = fetchToolsFromURI("https://bio.tools/api/t?format=json"); } - return toolAnnotations; + return convertBioTools2Ape(toolAnnotations, true); } /** - * Send Get request to get tool annotations Saves JSONArray with all - * bio.tools that belong to a certain EDAM topic. + * Retrieve tools from the bio.tools API for a given topic and convert them to + * the tool annotation format used by the APE library. * - * @throws IOException + * @param topicName The name of the topic. + * @return The JSONObject containing the tool annotations in the APE format. + * + * @throws IOException If an error occurs while fetching the tools. */ public static JSONObject getToolsFromEDAMTopic(String topicName) throws IOException { JSONArray toolAnnotations = null; @@ -97,7 +113,7 @@ public static JSONObject getToolsFromEDAMTopic(String topicName) throws IOExcept toolAnnotations = fetchToolsFromURI("https://bio.tools/api/t?format=json"); } - return convertBioTools2ApeStrict(toolAnnotations); + return convertBioTools2Ape(toolAnnotations, true); } /** @@ -108,14 +124,15 @@ public static JSONObject getToolsFromEDAMTopic(String topicName) throws IOExcept * @throws IOException * @throws JSONException */ - private static JSONArray fetchToolListFromBioTools(JSONArray toolListJson) throws JSONException, IOException { + public static JSONArray fetchToolListFromBioTools(JSONArray toolListJson) throws JSONException, IOException { JSONArray bioToolAnnotations = new JSONArray(); for (int i = 0; i < toolListJson.length(); i++) { String currTool = toolListJson.getString(i); Request request = new Request.Builder().url("https://bio.tools/api/" + currTool + "?format=json").build(); try (Response response = client.newCall(request).execute()) { - if (!response.isSuccessful()) - throw new IOException("Unexpected code when trying to fetch" + response); + if (!response.isSuccessful()) { + log.error("The tool " + currTool + " could not be fetched from bio.tools."); + } // Get response body JSONObject responseJson = new JSONObject(response.body().string()); bioToolAnnotations.put(i, responseJson); @@ -135,6 +152,7 @@ private static JSONArray fetchToolListFromBioTools(JSONArray toolListJson) throw */ private static JSONArray fetchToolsFromURI(String url) throws JSONException, IOException { JSONArray bioToolAnnotations = new JSONArray(); + log.info("Fetching tools from bio.tools: " + url); String next = ""; int i = 1; while (next != null) { @@ -155,109 +173,13 @@ private static JSONArray fetchToolsFromURI(String url) throws JSONException, IOE next = null; } } - log.trace("bio.tools: page " + i + " fetched."); + log.info("bio.tools: page " + i + " fetched."); } - log.debug("All tools fetched from a given URL."); + log.info("All tools fetched from a given URL."); return bioToolAnnotations; } - /** - * Method converts tools annotated using 'bio.tools' standard (see bio.tools - * API), into standard supported by the APE library. - *

- * In practice, the method takes a {@link JSONArray} as an argument, where each - * {@link JSONObject} in the array represents a tool annotated using 'bio.tools' - * standard, and returns a {@link JSONObject} that represents tool annotations - * that can be used by the APE library. - * - * @param bioToolsAnnotation A {@link JSONArray} object, that contains list of - * annotated tools ({@link JSONObject}s) according the - * bio.tools specification (see bio.tools - * API) - * @return {@link JSONObject} that represents the tool annotation supported by - * the APE library. - * @throws JSONException the json exception - */ - private static JSONObject convertBioTools2Ape(JSONArray bioToolsAnnotation) throws JSONException { - JSONArray apeToolsAnnotations = new JSONArray(); - for (int i = 0; i < bioToolsAnnotation.length(); i++) { - - JSONObject bioJsonTool = bioToolsAnnotation.getJSONObject(i); - List functions = APEUtils.getListFromJson(bioJsonTool, "function", JSONObject.class); - int functionNo = 1; - for (JSONObject function : functions) { - JSONObject apeJsonTool = new JSONObject(); - apeJsonTool.put(ToolAnnotationTag.LABEL.toString(), bioJsonTool.getString("name")); - apeJsonTool.put(ToolAnnotationTag.ID.toString(), bioJsonTool.getString("biotoolsID") + functionNo++); - - JSONArray apeTaxonomyTerms = new JSONArray(); - - JSONArray operations = function.getJSONArray("operation"); - for (int j = 0; j < operations.length(); j++) { - JSONObject bioOperation = operations.getJSONObject(j); - apeTaxonomyTerms.put(bioOperation.get("uri")); - } - apeJsonTool.put(ToolAnnotationTag.TAXONOMY_OPERATIONS.toString(), apeTaxonomyTerms); - // reading inputs - JSONArray apeInputs = new JSONArray(); - JSONArray bioInputs = function.getJSONArray("input"); - // for each input - for (int j = 0; j < bioInputs.length(); j++) { - JSONObject bioInput = bioInputs.getJSONObject(j); - JSONObject apeInput = new JSONObject(); - JSONArray apeInputTypes = new JSONArray(); - JSONArray apeInputFormats = new JSONArray(); - // add all data types - for (JSONObject bioType : APEUtils.getListFromJson(bioInput, "data", JSONObject.class)) { - apeInputTypes.put(bioType.getString("uri")); - } - apeInput.put("data_0006", apeInputTypes); - // add all data formats (or just the first one) - for (JSONObject bioType : APEUtils.getListFromJson(bioInput, "format", JSONObject.class)) { - apeInputFormats.put(bioType.getString("uri")); - } - apeInput.put("format_1915", apeInputFormats); - - apeInputs.put(apeInput); - } - apeJsonTool.put(ToolAnnotationTag.INPUTS.toString(), apeInputs); - - // reading outputs - JSONArray apeOutputs = new JSONArray(); - JSONArray bioOutputs = function.getJSONArray("output"); - // for each output - for (int j = 0; j < bioOutputs.length(); j++) { - - JSONObject bioOutput = bioOutputs.getJSONObject(j); - JSONObject apeOutput = new JSONObject(); - JSONArray apeOutputTypes = new JSONArray(); - JSONArray apeOutputFormats = new JSONArray(); - // add all data types - for (JSONObject bioType : APEUtils.getListFromJson(bioOutput, "data", JSONObject.class)) { - apeOutputTypes.put(bioType.getString("uri")); - } - apeOutput.put("data_0006", apeOutputTypes); - // add all data formats - for (JSONObject bioType : APEUtils.getListFromJson(bioOutput, "format", JSONObject.class)) { - apeOutputFormats.put(bioType.getString("uri")); - } - apeOutput.put("format_1915", apeOutputFormats); - - apeOutputs.put(apeOutput); - } - apeJsonTool.put(ToolAnnotationTag.OUTPUTS.toString(), apeOutputs); - - apeToolsAnnotations.put(apeJsonTool); - } - } - - return new JSONObject().put("functions", apeToolsAnnotations); - } - - /** * Method converts tools annotated using 'bio.tools' standard (see bio.tools @@ -273,147 +195,119 @@ private static JSONObject convertBioTools2Ape(JSONArray bioToolsAnnotation) thro * @param bioToolsAnnotation A {@link JSONArray} object, that contains list of * annotated tools ({@link JSONObject}s) according the * bio.tools specification (see bio.tools - * API) + * "https://biotools.readthedocs.io/en/latest/api_usage_guide.html">bio.tools API) + * @param excludeBadAnnotation If set to {@code true}, the method will exclude tools + * that do not have both the input and the output fully specified, i.e., with data and format types and formats specified. If set to {@code false}, the method will return annotations that have at least one of the two fully specified (at least one input or or output). * @return {@link JSONObject} that represents the tool annotation supported by * the APE library. * @throws JSONException the json exception */ - public static JSONObject convertBioTools2ApeStrict(JSONArray bioToolsAnnotation) throws JSONException { - - Set notAcceptedTools = new HashSet<>(); - Set noFunctionAnnotation = new HashSet<>(); - Set toolsMissingDimension = new HashSet<>(); - Set annotatedBioTools = new HashSet<>(); + public static JSONObject convertBioTools2Ape(JSONArray bioToolsAnnotation, boolean excludeBadAnnotation) + throws JSONException { + int notAcceptedOperations = 0; + int bioToolFunctions = 0; JSONArray apeToolsAnnotations = new JSONArray(); - Set toolsList = new HashSet<>(); - for (int i = 0; i < bioToolsAnnotation.length(); i++) { - - JSONObject bioJsonTool = bioToolsAnnotation.getJSONObject(i); - List functions = APEUtils.getListFromJson(bioJsonTool, "function", JSONObject.class); + for (JSONObject bioJsonTool : APEUtils.getJSONListFromJSONArray(bioToolsAnnotation)) { + List functions = APEUtils.getJSONListFromJson(bioJsonTool, "function"); if (functions.isEmpty()) { - noFunctionAnnotation.add(bioJsonTool.getString("biotoolsID")); - notAcceptedTools.add(bioJsonTool.getString("biotoolsID")); continue; } int functionNo = 1; - functionloop: for (JSONObject function : functions) { + + for (JSONObject function : functions) { bioToolFunctions++; JSONObject apeJsonTool = new JSONObject(); apeJsonTool.put("label", bioJsonTool.getString("name")); - if (functions.size() > 1) { - apeJsonTool.put("id", bioJsonTool.getString("biotoolsID") + "_op" + (functionNo++)); - } else { - apeJsonTool.put("id", bioJsonTool.getString("biotoolsID")); - } + + apeJsonTool.put("id", + bioJsonTool.getString("biotoolsID") + + (functions.size() > 1 ? "_op" + (functionNo++) : "")); JSONArray apeTaxonomyTerms = new JSONArray(); JSONArray operations = function.getJSONArray("operation"); - for (int j = 0; j < operations.length(); j++) { - JSONObject bioOperation = operations.getJSONObject(j); + for (JSONObject bioOperation : APEUtils.getJSONListFromJSONArray(operations)) { apeTaxonomyTerms.put(bioOperation.get("uri")); } apeJsonTool.put("taxonomyOperations", apeTaxonomyTerms); -// reading inputs + // reading inputs JSONArray apeInputs = new JSONArray(); - JSONArray bioInputs = function.getJSONArray("input"); -// for each input - for (int j = 0; j < bioInputs.length(); j++) { - JSONObject bioInput = bioInputs.getJSONObject(j); - JSONObject apeInput = new JSONObject(); - JSONArray apeInputTypes = new JSONArray(); - JSONArray apeInputFormats = new JSONArray(); -// add all data types - for (JSONObject bioType : APEUtils.getListFromJson(bioInput, "data", JSONObject.class)) { - apeInputTypes.put(bioType.getString("uri")); - } - if (apeInputTypes.length() == 0) { - notAcceptedTools.add(bioJsonTool.getString("biotoolsID")); - toolsMissingDimension.add(bioJsonTool.getString("biotoolsID")); - notAcceptedOperations++; - continue functionloop; - } - apeInput.put("data_0006", apeInputTypes); -// add all data formats (or just the first one) - for (JSONObject bioType : APEUtils.getListFromJson(bioInput, "format", JSONObject.class)) { - apeInputFormats.put(bioType.getString("uri")); - } - if (apeInputFormats.length() == 0) { - notAcceptedTools.add(bioJsonTool.getString("biotoolsID")); - toolsMissingDimension.add(bioJsonTool.getString("biotoolsID")); + try { + apeInputs = calculateBioToolsInputOutput(function.getJSONArray("input"), + bioJsonTool.getString("biotoolsID")); + apeJsonTool.put("inputs", apeInputs); + } catch (BioToolsAnnotationException e) { + if (excludeBadAnnotation) { notAcceptedOperations++; - continue functionloop; + continue; } - apeInput.put("format_1915", apeInputFormats); - - apeInputs.put(apeInput); } - apeJsonTool.put("inputs", apeInputs); - -// reading outputs JSONArray apeOutputs = new JSONArray(); - JSONArray bioOutputs = function.getJSONArray("output"); -// for each output - for (int j = 0; j < bioOutputs.length(); j++) { - - JSONObject bioOutput = bioOutputs.getJSONObject(j); - JSONObject apeOutput = new JSONObject(); - JSONArray apeOutputTypes = new JSONArray(); - JSONArray apeOutputFormats = new JSONArray(); -// add all data types - for (JSONObject bioType : APEUtils.getListFromJson(bioOutput, "data", JSONObject.class)) { - apeOutputTypes.put(bioType.getString("uri")); - } - if (apeOutputTypes.length() == 0) { - notAcceptedTools.add(bioJsonTool.getString("biotoolsID")); - toolsMissingDimension.add(bioJsonTool.getString("biotoolsID")); - notAcceptedOperations++; - continue functionloop; - } - apeOutput.put("data_0006", apeOutputTypes); -// add all data formats - for (JSONObject bioType : APEUtils.getListFromJson(bioOutput, "format", JSONObject.class)) { - apeOutputFormats.put(bioType.getString("uri")); - } - if (apeOutputFormats.length() == 0) { - notAcceptedTools.add(bioJsonTool.getString("biotoolsID")); - toolsMissingDimension.add(bioJsonTool.getString("biotoolsID")); + try { + apeOutputs = calculateBioToolsInputOutput(function.getJSONArray("output"), + bioJsonTool.getString("biotoolsID")); + apeJsonTool.put("outputs", apeOutputs); + } catch (BioToolsAnnotationException e) { + if (excludeBadAnnotation) { notAcceptedOperations++; - continue functionloop; + continue; } - apeOutput.put("format_1915", apeOutputFormats); - - apeOutputs.put(apeOutput); - } - apeJsonTool.put("outputs", apeOutputs); - - // if the tool has outputs add it to the tool annotation - if (apeInputs.length() > 0 && apeOutputs.length() > 0) { - toolsList.add(bioJsonTool.getString("biotoolsID")); - apeToolsAnnotations.put(apeJsonTool); - annotatedBioTools.add(bioJsonTool.getString("biotoolsID")); - } else { - notAcceptedTools.add(bioJsonTool.getString("biotoolsID")); - notAcceptedOperations++; } + apeJsonTool.put("biotoolsID", bioJsonTool.getString("biotoolsID")); + apeToolsAnnotations.put(apeJsonTool); } } - log.info("Provide bio.tools: " + bioToolsAnnotation.length()); + log.info("Provided bio.tools: " + bioToolsAnnotation.length()); log.info("Total bio.tools functions: " + bioToolFunctions); log.info("Errored bio.tools functions: " + notAcceptedOperations); - log.info("No functions: " + noFunctionAnnotation.size()); log.info("Created APE annotations: " + apeToolsAnnotations.length()); - JSONArray tools = new JSONArray(); - for (String tool : toolsList) { - tools.put(tool); + return new JSONObject().put("functions", apeToolsAnnotations); + } + + + + + + /** + * Method converts input and output tool annotations, following bio.tools schema, + * into the APE library tool annotation format. + * @param bioInputs - JSONArray with the bio.tools input/output annotations. + * @param toolID - ID of the tool that is being converted. + * + * @return JSONArray with the APE library input/output annotations. + */ + private static JSONArray calculateBioToolsInputOutput(JSONArray bioInputs, String toolID) { + JSONArray apeInputs = new JSONArray(); + for (JSONObject bioInput : APEUtils.getJSONListFromJSONArray(bioInputs)) { + JSONObject apeInput = new JSONObject(); + JSONArray apeInputTypes = new JSONArray(); + JSONArray apeInputFormats = new JSONArray(); + // add all data types + for (JSONObject bioType : APEUtils.getJSONListFromJson(bioInput, "data")) { + apeInputTypes.put(bioType.getString("uri")); + } + if (apeInputTypes.length() == 0) { + throw BioToolsAnnotationException.notExistingType(toolID); + } + apeInput.put("data_0006", apeInputTypes); + // add all data formats (or just the first one) + for (JSONObject bioType : APEUtils.getJSONListFromJson(bioInput, "format")) { + apeInputFormats.put(bioType.getString("uri")); + } + if (apeInputFormats.length() == 0) { + throw BioToolsAnnotationException.notExistingFormat(toolID); + } + apeInput.put("format_1915", apeInputFormats); + + apeInputs.put(apeInput); + } - return new JSONObject().put("functions", tools); + return apeInputs; } } \ No newline at end of file diff --git a/src/main/java/nl/uu/cs/ape/domain/BioToolsAnnotationException.java b/src/main/java/nl/uu/cs/ape/domain/BioToolsAnnotationException.java new file mode 100644 index 0000000..7664ed5 --- /dev/null +++ b/src/main/java/nl/uu/cs/ape/domain/BioToolsAnnotationException.java @@ -0,0 +1,42 @@ +/** + * + */ +package nl.uu.cs.ape.domain; + +/** + * The {@code BioToolsAnnotationException} exception will be thrown if the + * a tool in bio.tools is not annotated properly. + * + * @author Vedran Kasalica + * + */ +public class BioToolsAnnotationException extends RuntimeException { + + /** + * Instantiates a new Ape exception. + * + * @param message The message that will be passed to the {@link Exception} super + * class. + */ + private BioToolsAnnotationException(String message) { + super(message); + } + + /** + * Exception is thrown when a tool that does not have a data type of data specified in the bio.tools annotations. + * @param toolID - ID of the tool that does not have the data type specified. + * @return BioToolsAnnotationException with information that may help the user solve the problem. + */ + public static BioToolsAnnotationException notExistingType(String toolID) { + return new BioToolsAnnotationException(String.format("The tool with ID %s does not have data type specified (for input or output).", toolID)); + } + + /** + * Exception is thrown when a tool that does not have a data format of data specified in the bio.tools annotations. + * @param toolID - ID of the tool that does not have the format specified. + * @return BioToolsAnnotationException with information that may help the user solve the problem. + */ + public static BioToolsAnnotationException notExistingFormat(String toolID) { + return new BioToolsAnnotationException(String.format("The tool with ID %s does not have data format specified (for input or output).", toolID)); + } +} diff --git a/src/main/java/nl/uu/cs/ape/utils/APEUtils.java b/src/main/java/nl/uu/cs/ape/utils/APEUtils.java index 6738ece..ca88866 100644 --- a/src/main/java/nl/uu/cs/ape/utils/APEUtils.java +++ b/src/main/java/nl/uu/cs/ape/utils/APEUtils.java @@ -120,7 +120,7 @@ public static List getListFromJson(JSONObject jsonObject, String key, Cla Object tmp = jsonObject.get(key); try { if (tmp instanceof JSONArray) { - jsonList = getListFromJsonList((JSONArray) tmp, clazz); + jsonList = getListFromJSONArray((JSONArray) tmp, clazz); } else { T element = (T) tmp; jsonList.add(element); @@ -138,6 +138,20 @@ public static List getListFromJson(JSONObject jsonObject, String key, Cla } } + /** + * The method return a list of {@link JSONObject} elements that correspond to + * the value of a given key in the given json object. If the key corresponds to + * a {@link JSONArray} all the elements are put in a {@link List}, otherwise if + * the key corresponds to a {@link JSONObject} list will contain only that object. + * @param jsonObject {@link JSONObject} that is being explored. + * @param key Key label that corresponds to the elements. + * + * @return List of elements that corresponds to the key. If the key does not exists returns empty list. + */ + public static List getJSONListFromJson(JSONObject jsonObject, String key) { + return getListFromJson(jsonObject, key, JSONObject.class); + } + /** * The method converts the {@link JSONArray} object to {@link List} of objects * of the given structure. @@ -148,7 +162,7 @@ public static List getListFromJson(JSONObject jsonObject, String key, Cla * @return List of objects of type {@link T}. */ @SuppressWarnings("unchecked") - public static List getListFromJsonList(JSONArray jsonArray, Class clazz) { + public static List getListFromJSONArray(JSONArray jsonArray, Class clazz) { List newList = new ArrayList<>(); for (int i = 0; i < jsonArray.length(); i++) { T element = (T) jsonArray.get(i); @@ -157,6 +171,17 @@ public static List getListFromJsonList(JSONArray jsonArray, Class claz return newList; } + /** + * The method converts the {@link JSONArray} object to {@link List} of + * {@link JSONObject} objects. + * + * @param jsonArray JSON array object. + * @return List of {@link JSONObject} objects. + */ + public static List getJSONListFromJSONArray(JSONArray jsonArray) { + return getListFromJSONArray(jsonArray, JSONObject.class); + } + /** * Debug printout. * From ec70fa8f43276af9bfc8d79542398013054a5bca Mon Sep 17 00:00:00 2001 From: Vedran Kasalica Date: Wed, 25 Sep 2024 11:50:30 +0200 Subject: [PATCH 03/13] Simplify PR and issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 30 +++++------- .github/ISSUE_TEMPLATE/feature_request.md | 27 +---------- .github/pull_request_template.md | 56 ++++------------------- 3 files changed, 24 insertions(+), 89 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index f1e4a73..462725a 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,13 +1,16 @@ --- -name: Bug Report -about: Create a report to help improve the APE library -title: '[BUG] ' -labels: 'bug' -assignees: vedran-kasalica +name: Bug report +about: Create a report to help us improve the APE library +title: '' +labels: bug +assignees: '' --- -**Note:** Not all fields are obligatory, but the more details you provide, the easier it will be for us to address the issue. Feel free to omit sections that you feel are not relevant to your report. +## Checklist before submitting a bug report + +- [ ] I have checked the [existing issues](https://github.com/NLeSC/python-template/issues) and couldn't find an issue about this bug. + ## Description @@ -16,12 +19,10 @@ assignees: vedran-kasalica - [ ] API - [ ] CLI +- [ ] REST API -## APE Version - - -## Java Version - +## APE and Java Version + ## Steps to Reproduce @@ -30,14 +31,7 @@ assignees: vedran-kasalica 3. 4. -## Expected Behavior - - -## Actual Behavior - -## Possible Solution - ## Additional Context diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 66998a7..3a2c469 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,34 +1,11 @@ --- name: Feature Request about: Suggest a new feature or enhancement for the APE library -title: '[FEATURE] ' +title: '' labels: 'enhancement' -assignees: vedran-kasalica +assignees: '' --- -**Note:** Not all fields are obligatory, but the more details you provide, the easier it will be for us to address the issue. Feel free to omit sections that you feel are not relevant to your report. - ## Feature Description - -## Is this feature related to a problem? Please describe. - - -## Describe the solution you'd like - - -## Describe alternatives you've considered - - -## API/CLI Impact - -- [ ] API -- [ ] CLI -- [ ] Both - -## Potential Benefits - - -## Additional Context - diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index f5cf5b3..0056eb6 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,54 +1,18 @@ ---- -name: Pull Request -about: Submit a pull request to contribute to the APE library -title: '' -labels: '' -assignees: vedran-kasalica - ---- - -**Note:** Not all fields are obligatory, but the more details you provide, the easier it will be for us to address the issue. Feel free to omit sections that you feel are not relevant to your report. - ## Pull Request Overview - + -## Related Issue(s) or Pull Request(s) - +## Related Issue + ## Changes Introduced - - -## Motivation and Context - + ## How Has This Been Tested? - - -## API/CLI Changes - - -## Screenshots (if appropriate): - - -## Potential Impacts - - -## Checklist: - -- [ ] I have followed the [style guidelines](https://github.com/sanctuuary/APE/blob/main/CONTRIBUTION.md#good-java-practices) of this project. -- [ ] I have performed a self-review of my own code. -- [ ] I have commented my code, particularly in hard-to-understand areas. -- [ ] I have made corresponding changes to the documentation (if applicable). -- [ ] My changes generate no new warnings. -- [ ] I have added tests that prove my fix is effective or that my feature works. -- [ ] New and existing unit tests pass locally with my changes. + -## Additional Notes - +## Checklist -## Reviewer Checklist: - -- [ ] The code follows the project’s style guide. -- [ ] The changes are well-documented and commented. -- [ ] The tests cover all changes adequately. -- [ ] All checks pass successfully. +- [ ] I have referenced a related issue. +- [ ] I have followed the project’s style guidelines. +- [ ] My changes include tests, if applicable. +- [ ] All tests pass locally. From 54e6c2e70a81d32586e3995c4d23db3b744ca24f Mon Sep 17 00:00:00 2001 From: Vedran Kasalica Date: Wed, 25 Sep 2024 11:58:52 +0200 Subject: [PATCH 04/13] Update build to java 17 --- .github/workflows/mvnbuild.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/mvnbuild.yml b/.github/workflows/mvnbuild.yml index e28d35c..9ade782 100644 --- a/.github/workflows/mvnbuild.yml +++ b/.github/workflows/mvnbuild.yml @@ -20,11 +20,11 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Set up JDK 11 - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - name: Set up JDK 17 + uses: actions/setup-java@v4 with: - java-version: '11' + java-version: '17' distribution: 'temurin' cache: maven - name: Build, test and package with Maven From 7f8b7b934de17099cb382232d946bde1cb86bcb9 Mon Sep 17 00:00:00 2001 From: Vedran Kasalica Date: Wed, 25 Sep 2024 12:45:50 +0200 Subject: [PATCH 05/13] Update the path to the test repo --- .github/workflows/mvnbuild.yml | 6 +++--- src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/mvnbuild.yml b/.github/workflows/mvnbuild.yml index 9ade782..7955092 100644 --- a/.github/workflows/mvnbuild.yml +++ b/.github/workflows/mvnbuild.yml @@ -35,9 +35,9 @@ jobs: pip3 install cwlref-runner - name: Test CWL generation run: | - git clone https://github.com/Workflomics/domain-annotations - cd domain-annotations/WombatP_tools - java -jar ../../target/APE-*-executable.jar ./config.json + git clone https://github.com/Workflomics/containers + cd containers/domains/proteomics + java -jar ../../../target/APE-*-executable.jar ./config.json cd ./CWL cwltool --enable-dev --validate candidate_workflow_1.cwl diff --git a/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java b/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java index 8e813d8..431ea59 100644 --- a/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java +++ b/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java @@ -9,7 +9,6 @@ import org.json.JSONException; import org.json.JSONObject; -import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import nl.uu.cs.ape.configuration.APECoreConfig; @@ -576,7 +575,7 @@ public void localCNF(File satInputFile, SATAtomMappings mappings) throws IOExcep String encoding = APEUtils.convertCNF2humanReadable(cnfStream, mappings); cnfStream.close(); - APEFiles.write2file(encoding, new File(writeLocalCNF), false); + APEFiles.write2file(encoding, new File(writeLocalCNF), false); } } From 783f359c168c10d4de923900873055000a04511b Mon Sep 17 00:00:00 2001 From: Vedran Kasalica Date: Wed, 25 Sep 2024 19:57:06 +0200 Subject: [PATCH 06/13] Update logging, bio.tools API and cwl naming --- .github/workflows/mvnbuild.yml | 2 ++ src/main/java/nl/uu/cs/ape/domain/BioToolsAPI.java | 9 ++++++--- .../solver/solutionStructure/cwl/DefaultCWLCreator.java | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/mvnbuild.yml b/.github/workflows/mvnbuild.yml index 7955092..5e982ca 100644 --- a/.github/workflows/mvnbuild.yml +++ b/.github/workflows/mvnbuild.yml @@ -40,6 +40,8 @@ jobs: java -jar ../../../target/APE-*-executable.jar ./config.json cd ./CWL cwltool --enable-dev --validate candidate_workflow_1.cwl + cwltool --enable-dev --validate candidate_workflow_2.cwl + cwltool --enable-dev --validate candidate_workflow_3.cwl # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive - name: Update dependency graph diff --git a/src/main/java/nl/uu/cs/ape/domain/BioToolsAPI.java b/src/main/java/nl/uu/cs/ape/domain/BioToolsAPI.java index b25ce8d..e47954c 100644 --- a/src/main/java/nl/uu/cs/ape/domain/BioToolsAPI.java +++ b/src/main/java/nl/uu/cs/ape/domain/BioToolsAPI.java @@ -173,7 +173,7 @@ private static JSONArray fetchToolsFromURI(String url) throws JSONException, IOE next = null; } } - log.info("bio.tools: page " + i + " fetched."); + log.info("bio.tools: page " + i++ + " fetched."); } log.info("All tools fetched from a given URL."); @@ -257,8 +257,11 @@ public static JSONObject convertBioTools2Ape(JSONArray bioToolsAnnotation, boole continue; } } - apeJsonTool.put("biotoolsID", bioJsonTool.getString("biotoolsID")); - apeToolsAnnotations.put(apeJsonTool); + if (!excludeBadAnnotation || + (apeInputs.length() > 0 && apeOutputs.length() > 0)) { + apeJsonTool.put("biotoolsID", bioJsonTool.getString("biotoolsID")); + apeToolsAnnotations.put(apeJsonTool); + } } } log.info("Provided bio.tools: " + bioToolsAnnotation.length()); diff --git a/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/DefaultCWLCreator.java b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/DefaultCWLCreator.java index c2f62d2..c898a7d 100644 --- a/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/DefaultCWLCreator.java +++ b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/DefaultCWLCreator.java @@ -254,7 +254,7 @@ private void generateStepOut(ModuleNode moduleNode) { */ private void generateDefaultStepRun(ModuleNode moduleNode) { final int baseInd = 2; - String moduleReference = "add-path-to-the-implementation/" + moduleNode.getUsedModule().getPredicateLabel() + String moduleReference = "add-path-to-the-implementation/" + moduleNode.getUsedModule().getPredicateID() + ".cwl "; if (moduleNode.getUsedModule().getCwlFileReference() != null) { moduleReference = moduleNode.getUsedModule().getCwlFileReference(); From 5aa13801ff7ff36c0c99c36ae1b8fb1dae2bc8be Mon Sep 17 00:00:00 2001 From: Vedran Kasalica Date: Wed, 25 Sep 2024 20:46:06 +0200 Subject: [PATCH 07/13] Add JavaDocs --- src/main/java/nl/uu/cs/ape/Main.java | 16 +++++++++++----- .../solutionStructure/cwl/DefaultCWLCreator.java | 1 - 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/main/java/nl/uu/cs/ape/Main.java b/src/main/java/nl/uu/cs/ape/Main.java index 25f7300..754dd04 100644 --- a/src/main/java/nl/uu/cs/ape/Main.java +++ b/src/main/java/nl/uu/cs/ape/Main.java @@ -28,7 +28,8 @@ public class Main { * The entry point of application when the library is used in a Command Line * Interface (CLI). * - * @param args APE expects at most two (2) arguments. + * @param args APE expects the first argument to specify the method to be executed. + * The rest of the arguments are provided depending on the method. */ public static void main(String[] args) { @@ -57,6 +58,13 @@ public static void main(String[] args) { } + /** + * Retrieve tools from bio.tools using bio.tools API and convert them to + * APE-compatible tool annotation format. + * + * @param args The arguments provided to the method. Only one argument is + * expected, the path to the file where the biotoolsIDs are stored. + */ public static void convertBioToolsAnnotations(String[] args) { String path; if (args.length != 1) { @@ -80,10 +88,8 @@ public static void convertBioToolsAnnotations(String[] args) { } /** - * The entry point of application when the library is used in a Command Line - * Interface (CLI). - * - * @param args APE expects at most two (2) arguments. + * Executes the synthesis based on the provided configuration file. + * @param args The arguments provided to the method. */ public static void executeSynthesis(String[] args) { String path; diff --git a/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/DefaultCWLCreator.java b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/DefaultCWLCreator.java index c898a7d..8731402 100644 --- a/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/DefaultCWLCreator.java +++ b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/DefaultCWLCreator.java @@ -1,7 +1,6 @@ package nl.uu.cs.ape.solver.solutionStructure.cwl; import nl.uu.cs.ape.models.Type; -import nl.uu.cs.ape.models.logic.constructs.TaxonomyPredicate; import nl.uu.cs.ape.solver.solutionStructure.ModuleNode; import nl.uu.cs.ape.solver.solutionStructure.SolutionWorkflow; import nl.uu.cs.ape.solver.solutionStructure.TypeNode; From 06cf21eb9a0454f9221f475e04cfba860bdbe3e7 Mon Sep 17 00:00:00 2001 From: Vedran Kasalica Date: Tue, 1 Oct 2024 14:14:17 +0200 Subject: [PATCH 08/13] Remove the outdated paper submission, intended for JOSS publication that was canceled --- paper/paper.bib | 1264 ----------------------------------------------- paper/paper.md | 47 -- 2 files changed, 1311 deletions(-) delete mode 100644 paper/paper.bib delete mode 100644 paper/paper.md diff --git a/paper/paper.bib b/paper/paper.bib deleted file mode 100644 index 31568be..0000000 --- a/paper/paper.bib +++ /dev/null @@ -1,1264 +0,0 @@ -@article{10.1093/bib/bbz075, - author = {Ison, Jon and Ménager, Hervé and Brancotte, Bryan and Jaaniso, Erik and Salumets, Ahto and Raček, Tomáš and Lamprecht, Anna-Lena and Palmblad, Magnus and Kalaš, Matúš and Chmura, Piotr and Hancock, John M and Schwämmle, Veit and Ienasescu, Hans-Ioan}, - title = "{Community curation of bioinformatics software and data resources}", - journal = {Briefings in Bioinformatics}, - year = {2019}, - month = {10}, - abstract = "{The corpus of bioinformatics resources is huge and expanding rapidly, presenting life scientists with a growing challenge in selecting tools that fit the desired purpose. To address this, the European Infrastructure for Biological Information is supporting a systematic approach towards a comprehensive registry of tools and databases for all domains of bioinformatics, provided under a single portal (https://bio.tools). We describe here the practical means by which scientific communities, including individual developers and projects, through major service providers and research infrastructures, can describe their own bioinformatics resources and share these via bio.tools.}", - issn = {1477-4054}, - doi = {10.1093/bib/bbz075}, - url = {https://doi.org/10.1093/bib/bbz075}, - note = {bbz075}, - eprint = {https://academic.oup.com/bib/article-pdf/doi/10.1093/bib/bbz075/30157114/bbz075.pdf}, -} - - -@book{ghallab_automated_2016, - address = {New York, NY, USA}, - edition = {1st}, - title = {Automated {Planning} and {Acting}}, - isbn = {978-1-107-03727-4}, - abstract = {Autonomous AI systems need complex computational techniques for planning and performing actions. Planning and acting require significant deliberation because an intelligent system must coordinate and integrate these activities in order to act effectively in the real world. This book presents a comprehensive paradigm of planning and acting using the most recent and advanced automated-planning techniques. It explains the computational deliberation capabilities that allow an actor, whether physical or virtual, to reason about its actions, choose them, organize them purposefully, and act deliberately to achieve an objective. Useful for students, practitioners, and researchers, this book covers state-of-the-art planning techniques, acting techniques, and their integration which will allow readers to design intelligent systems that are able to act effectively in the real world.}, - publisher = {Cambridge University Press}, - author = {Ghallab, Malik and Nau, Dana and Traverso, Paolo}, - year = {2016} -} - -@book{gulwani_program_2017, - series = {Foundations and {Trends} in {Programming} {Languages}}, - title = {Program {Synthesis}}, - volume = {4}, - tmp_url = {https://www.nowpublishers.com/article/Details/PGL-010}, - language = {English}, - number = {1-2}, - urldate = {2018-08-02}, - publisher = {now}, - author = {Gulwani, Sumit and Polozov, Oleksandr and Singh, Rishabh}, - month = jul, - year = {2017}, - file = {Full Text PDF:/home/allamprecht/ownCloud/Documents/Zotero/storage/CC5YNY88/Gulwani et al. - 2017 - Program Synthesis.pdf:application/pdf;Snapshot:/home/allamprecht/ownCloud/Documents/Zotero/storage/QCK77RXV/PGL-010.html:text/html} -} - -@article{atkinson_scientific_2017, - title = {Scientific workflows: {Past}, present and future}, - volume = {75}, - issn = {0167-739X}, - shorttitle = {Scientific workflows}, - tmp_url = {http://www.sciencedirect.com/science/article/pii/S0167739X17311202}, - tmp_doi = {10.1016/j.future.2017.05.041}, - urldate = {2018-08-02}, - journal = {Future Generation Computer Systems}, - author = {Atkinson, Malcolm and Gesing, Sandra and Montagnat, Johan and Taylor, Ian}, - month = oct, - year = {2017}, - keywords = {Optimisation, Performance, Scientific methods, Scientific workflows, Usability}, - pages = {216--227}, - file = {ScienceDirect Full Text PDF:/home/allamprecht/ownCloud/Documents/Zotero/storage/EJ6EYKQW/Atkinson et al. - 2017 - Scientific workflows Past, present and future.pdf:application/pdf;ScienceDirect Snapshot:/home/allamprecht/ownCloud/Documents/Zotero/storage/X7ESF7HW/S0167739X17311202.html:text/html} -} - -@misc{ wiki:SciWFSystems, - author = "{Wikipedia contributors}", - title = "Scientific workflow system --- {Wikipedia}{,} The Free Encyclopedia", - year = "2019", - howpublished = "\url{https://en.wikipedia.org/w/index.php?title=Scientific_workflow_system&oldid=928001704}", - note = "[Online; accessed 3-February-2020]" - } - -@misc{apache:existingWFSystems, - title = {Existing {Workflow} systems}, - url = {https://s.apache.org/existing-workflow-systems}, - language = {en}, - urldate = {2020-02-04}, - file = {Snapshot:/home/allamprecht/ownCloud/Documents/Zotero/storage/QJNAM6YG/Existing-Workflow-systems.html:text/html} -} - -@article{scheiderCCD2020, -author={Scheider, Simon and Meerlo, Rogier and Kasalica, Vedran and Lamprecht, Anna-Lena}, -title={Ontology of core concept data types for answering geo-analytical questions}, -journal={JOSIS}, -year=2020, -url={https://www.josis.org/index.php/josis/article/view/555}, -note={In press.} -} - -@article{kruiger2020, -author={Han Kruiger and Vedran Kasalica and Rogier Meerlo and Anna-Lena Lamprecht and Simon Scheider}, -title={{Loose programming of GIS workflows with geo-analytical concepts}}, -journal={Transactions in GIS}, -year=2020, -note={Under review}, -} - -@InProceedings{kasalicaLamprecht2019, -author="Kasalica, Vedran -and Lamprecht, Anna-Lena", -title="Workflow Discovery Through Semantic Constraints: A Geovisualization Case Study", -booktitle="Computational Science and Its Applications -- ICCSA 2019", -year="2019", -publisher="Springer International Publishing", -address="Cham", -pages="473--488", -abstract="The construction of computational pipelines, for example automated cartographic workflows for the construction of thematic maps, typically requires detailed knowledge about the available tools for the individual steps and the technicalities of their composition. It is a time-consuming process and comes with the risk of missing meaningful workflows because many possible pipelines are never taken into account. Automated workflow composition techniques can facilitate comprehensive workflow discovery based on semantic constraints: The users express their intention about the workflows by means of high-level constraints, and receive possible workflows that meet their request. The successful application of such methods essentially depends on the availability and quality of semantic domain models that describe the tools and data types in the domain. In this paper, we present an exemplary domain model for a geovisualization use case, and show how it enables the abstract specification and automated composition of a complex cartographic workflow.", -isbn="978-3-030-24302-9" -} - -@article{kasalica2019, - title = {Workflow {Discovery} with {Semantic} {Constraints}: {The} {SAT}-{Based} {Implementation} of {APE}}, - volume = {78}, - copyright = {Copyright (c) 2020 Electronic Communications of the EASST}, - issn = {1863-2122}, - shorttitle = {Workflow {Discovery} with {Semantic} {Constraints}}, - doi = {10.14279/tuj.eceasst.78.1092}, - abstract = {Science today is increasingly computational, and many researchers regularly face the need of creating purpose-specific computational pipelines for their specific data analysis problems. The manual composition and implementation of such workflows regularly costs valuable research time. Hence, many scientists wish for a system that would only require an abstract description of their intended data analysis process, and from there automatically compose and implement suitable workflows. In this paper we describe APE (the Automated Pipeline Explorer), a new implementation of a synthesis-based workflow discovery framework that aims to accomplish such automated composition. The framework captures the required technical domain knowledge in the form of tool and type taxonomies and functional tool annotations. Based on this semantic domain model, the framework allows users to specify their intents about workflows at an abstract, conceptual level in the form of natural-language templates. Internally, APE maps them to a temporal logic and translates them into a propositional logic instance of the problem that can be solved by an off-the-shelf SAT solver. From the solutions provided by the solver, APE then constructs executable workflow implementations. First applications of APE on realistic scientific workflow scenarios have shown that it is able to efficiently synthesize meaningful workflows. We use an example from the geospatial application domain as a running example in this paper.}, - language = {en}, - number = {0}, - urldate = {2020-05-17}, - journal = {Electronic Communications of the EASST}, - author = {Kasalica, Vedran and Lamprecht, Anna-Lena}, - month = may, - year = {2020}, - note = {Number: 0} -} - - -@inproceedings{simon_automated_2016, - address = {Cham}, - title = {Automated {Spatial} {Data} {Processing} and {Refining}}, - isbn = {978-3-319-51641-7}, - abstract = {This paper focuses on the definition of a method for data processing by means of automated professional map generation. For this, initially services have to be identified that represents cartographic rules and recommendations. In order to link those services with respect to their cartographic content and to control the process within a component, a set of rules has to be designed. This is explained by examples and can be used as a template pattern for other services. Individual services and modules within the process will be arranged hierarchically on the basis of the cartographic visualisation pipeline. Its consequent graphical classification is presented. The aim is to prepare the theoretical cartographic basis in a formal way, which should enable technical implementation without cartographic technical expertise.}, - booktitle = {Leveraging {Applications} of {Formal} {Methods}, {Verification}, and {Validation}}, - publisher = {Springer International Publishing}, - author = {Simon, Marion and Asche, Hartmut}, - editor = {Lamprecht, Anna-Lena}, - year = {2016}, - pages = {38--49} -} - -@inproceedings{asche_process-oriented_2012, - address = {Berlin, Heidelberg}, - title = {Process-{Oriented} {Geoinformation} {Systems} and {Applications}}, - isbn = {978-3-642-34032-1}, - abstract = {It is a well-accepted truism that the vast majority of digital data have a geographical reference. In the past decades geodata have been processed and visualised by dedicated software products of the geoinformation systems (GIS) type for a limited range of scientific and professional applications. However, For more than a deacade, however, both geodata and GIS functionalities are having an increasing, by now almost ubiquitious impact on various fields of everyday life. Against this background space-related, process-orientend software environments will play a decisive role in the development and delivery of a variety of geoinformation and geovisualisation products and services for a wide range of scientific and practical applications alike. This track aims at providing an update on current as well as emerging issues and applications in ubiquitious geoinformation and geovisualisation.}, - booktitle = {Leveraging {Applications} of {Formal} {Methods}, {Verification} and {Validation}. {Applications} and {Case} {Studies}}, - publisher = {Springer Berlin Heidelberg}, - author = {Asche, Hartmut}, - editor = {Margaria, Tiziana and Steffen, Bernhard}, - year = {2012}, - pages = {324--324} -} - -@article{kuhn_core_2012, - title = {Core concepts of spatial information for transdisciplinary research}, - volume = {26}, - tmp_doi_comment = {10.1080/13658816.2012.722637}, - number = {12}, - journal = {International Journal of Geographical Information Science}, - author = {Kuhn, Werner}, - year = {2012}, - pages = {2267--2276} -} - -@article{palmblad_automated_2018, - title = {Automated workflow composition in mass spectrometry-based proteomics}, - abstract = {Numerous software utilities operating on mass spectrometry (MS) data are described in the literature and provide specific operations as building blocks for the assembly of on-purpose workflows. Working out which tools and combinations are applicable or optimal in practice is often hard. Thus researchers face difficulties in selecting practical and effective data analysis pipelines for a specific experimental design.We provide a toolkit to support researchers in identifying, comparing and benchmarking multiple workflows from individual bioinformatics tools. Automated workflow composition is enabled by the tools’ semantic annotation in terms of the EDAM ontology. To demonstrate the practical use of our framework, we created and evaluated a number of logically and semantically equivalent workflows for four use cases representing frequent tasks in MS-based proteomics. Indeed we found that the results computed by the workflows could vary considerably, emphasizing the benefits of a framework that facilitates their systematic exploration.The project files and workflows are available from https://github.com/bio-tools/biotoolsCompose/tree/master/Automatic-Workflow-Composition.Supplementary data are available at Bioinformatics online.}, - author = {Palmblad, Magnus and Lamprecht, Anna-Lena and Ison, Jon and Schwämmle, Veit}, - year = {2018} -} - -@article{ison2013edam, - title={EDAM: an ontology of bioinformatics operations, types of data and identifiers, topics and formats}, - author={Ison, Jon and Kala{\v{s}}, Mat{\'u}{\v{s}} and Jonassen, Inge and Bolser, Dan and Uludag, Mahmut and McWilliam, Hamish and Malone, James and Lopez, Rodrigo and Pettifer, Steve and Rice, Peter}, - journal={Bioinformatics}, - volume={29}, - number={10}, - pages={1325--1332}, - year={2013}, - publisher={Oxford University Press} -} - -@book{gdal/ogr_contributors_gdal/ogr_2018, - title = {{GDAL}/{OGR} {Geospatial} {Data} {Abstraction} software {Library}}, - url = {http://gdal.org}, - publisher = {Open Source Geospatial Foundation}, - author = {{GDAL/OGR contributors}}, - year = {2018}, - annote = {[Online; 14 Feb 2019]} -} - -@book{noauthor_csiss/gmu_nodate, - title = {{CSISS}/{GMU} {Geospatial} {Web} {Services}}, - url = {http://cube.csiss.gmu.edu/grassweb/manuals/index.html}, - annote = {[Online; 14 Feb 2019]} -} - -@book{noauthor_scientific_nodate, - title = {Scientific workflow system}, - copyright = {Creative Commons Attribution-ShareAlike License}, - url = {https://en.wikipedia.org/w/index.php?title=Scientific_workflow_system&oldid=877419140}, - abstract = {A scientific workflow system is a specialized form of a workflow management system designed specifically to compose and execute a series of computational or data manipulation steps, or workflow, in a scientific application.}, - language = {en}, - urldate = {2019-02-15}, - annote = {[Online; 14 Feb 2019]} -} - -@article{filiot_exploiting_2013, - title = {Exploiting structure in {LTL} synthesis}, - volume = {15}, - issn = {1433-2787}, - Url_comment = {https://tmp_doi.org/10.1007/s10009-012-0222-5}, - tmp_doi_comment = {10.1007/s10009-012-0222-5}, - abstract = {In this paper, we show how to exploit the structure of some automata-based construction to efficiently solve the LTL synthesis problem. We focus on a construction proposed in Schewe and Finkbeiner that reduces the synthesis problem to a safety game, which can then be solved by computing the solution of the classical fixpoint equation νX.Safe ∩ CPre(X), where CPre(X) are the controllable predecessors of X. We have shown in previous works that the sets computed during the fixpoint algorithm can be equipped with a partial order that allows one to represent them very compactly, by the antichain of their maximal elements. However the computation of CPre(X) cannot be done in polynomial time when X is represented by an antichain (unless P = NP). This motivates the use of SAT solvers to compute CPre(X). Also, we show that the CPre operator can be replaced by a weaker operator CPre crit where the adversary is restricted to play a subset of critical signals. We show that the fixpoints of the two operators coincide, and so, instead of applying iteratively CPre, we can apply iteratively CPre crit. In practice, this leads to important improvements on previous LTL synthesis methods. The reduction to SAT problems and the weakening of the CPre operator into CPre crit and their performance evaluations are new.}, - number = {5}, - journal = {International Journal on Software Tools for Technology Transfer}, - author = {Filiot, Emmanuel and Jin, Naiyong and Raskin, Jean-François}, - month = oct, - year = {2013}, - pages = {541--561} -} - -@incollection{maoz_two-way_2013, - address = {Berlin, Heidelberg}, - title = {Two-{Way} {Traceability} and {Conflict} {Debugging} for {AspectLTL} -117 - {Programs}}, - isbn = {978-3-642-36964-3}, - Url_comment = {https://tmp_doi.org/10.1007/978-3-642-36964-3_2}, - abstract = {Tracing program actions back to the concerns that have caused them and blaming specific code artifacts for concern interference are known challenges of AOP and related advanced modularity paradigms. In this work, we address these challenges in the context of AspectLTL, a temporal-logic-based language for the specification and implementation of crosscutting concerns, which has a composition and synthesis-based weaving process whose output is a correct-by-construction executable artifact. When a specification is realizable, we provide two-way traceability information that links each allowed or forbidden transition in the generated program with the aspects that have justified its presence or elimination. When a specification is unrealizable, we provide an interactive game proof that demonstrates conflicts that should be fixed. The techniques are implemented and demonstrated using running examples.}, - booktitle = {Transactions on {Aspect}-{Oriented} {Software} {Development} {X}}, - publisher = {Springer Berlin Heidelberg}, - author = {Maoz, Shahar and Sa'ar, Yaniv}, - editor = {Leavens, Gary T. and Chiba, Shigeru and Tanter, Éric}, - year = {2013}, - tmp_doi_comment = {10.1007/978-3-642-36964-3_2}, - pages = {39--72} -} - -@article{sohail_safety_2013, - title = {Safety first: a two-stage algorithm for the synthesis of reactive systems}, - volume = {15}, - issn = {1433-2787}, - Url_comment = {https://tmp_doi.org/10.1007/s10009-012-0224-3}, - tmp_doi_comment = {10.1007/s10009-012-0224-3}, - abstract = {In the game-theoretic approach to the synthesis of reactive systems, specifications are often expressed as \$ømega\$-regular languages. Computing a winning strategy to an infinite game whose winning condition is an \$ømega\$-regular language is then the main step in obtaining an implementation. Conjoining all the properties of a specification to obtain a monolithic game suffers from the doubly exponential determinization that is required. Despite the success of symbolic algorithms, the monolithic approach is not practical. Existing techniques achieve efficiency by imposing restrictions on the \$ømega\$-regular languages they deal with. In contrast, we present an approach that achieves improvement in performance through the decomposition of the problem while still accepting the full set of \$ømega\$-regular languages. Each property is translated into a deterministic \$ømega\$-regular automaton explicitly while the two-player game defined by the collection of automata is played symbolically. Safety and persistence properties usually make up the majority of a specification. We take advantage of this by solving the game incrementally. Each safety and persistence property is used to gradually construct the parity game. Optimizations are applied after each refinement of the graph. This process produces a compact symbolic encoding of the parity game. We then compose the remaining properties and solve one final game after possibly solving smaller games to further optimize the graph. An implementation is finally derived from the winning strategies computed. We compare the results of our tool to those of the synthesis tool Anzu.}, - number = {5}, - journal = {International Journal on Software Tools for Technology Transfer}, - author = {Sohail, Saqib and Somenzi, Fabio}, - month = oct, - year = {2013}, - pages = {433--454} -} - -@article{joshi_denali:_2006, - title = {Denali: {A} {Practical} {Algorithm} for {Generating} {Optimal} {Code}}, - volume = {28}, - issn = {0164-0925}, - Url_comment = {http://tmp_doi.acm.org/10.1145/1186632.1186633}, - tmp_doi_comment = {10.1145/1186632.1186633}, - number = {6}, - journal = {ACM Trans. Program. Lang. Syst.}, - author = {Joshi, Rajeev and Nelson, Greg and Zhou, Yunhong}, - month = nov, - year = {2006}, - keywords = {code generation, Compilation, practical optimal code generation}, - pages = {967--989} -} - -@article{konighofer_debugging_2013, - title = {Debugging formal specifications: a practical approach using model-based diagnosis and counterstrategies}, - volume = {15}, - issn = {1433-2787}, - Url_comment = {https://tmp_doi.org/10.1007/s10009-011-0221-y}, - tmp_doi_comment = {10.1007/s10009-011-0221-y}, - abstract = {Creating a formal specification for a design is an error-prone process. At the same time, debugging incorrect specifications is difficult and time consuming. In this work, we propose a debugging method for formal specifications that does not require an implementation. We handle conflicts between a formal specification and the informal design intent using a simulation-based refinement loop, where we reduce the problem of debugging overconstrained specifications to that of debugging unrealizability. We show how model-based diagnosis can be applied to locate an error in an unrealizable specification. The diagnosis algorithm computes properties and signals that can be modified in such a way that the specification becomes realizable, thus pointing out potential error locations. In order to fix the specification, the user must understand the problem. We use counterstrategies to explain conflicts in the specification. Since counterstrategies may be large, we propose several ways to simplify them. First, we compute the counterstrategy not for the original specification but only for an unrealizable core. Second, we use a heuristic to search for a countertrace, i.e., a single input trace which necessarily leads to a specification violation. Finally, we present the countertrace or the counterstrategy as an interactive game against the user, and as a graph summarizing possible plays of this game. We introduce a user-friendly implementation of our debugging method and present experimental results for GR(1) specifications.}, - number = {5}, - journal = {International Journal on Software Tools for Technology Transfer}, - author = {Könighofer, Robert and Hofferek, Georg and Bloem, Roderick}, - month = oct, - year = {2013}, - pages = {563--583} -} - -@inproceedings{krishnamurthi_alchemy:_2008, - address = {New York, NY, USA}, - series = {{SIGSOFT} '08/{FSE}-16}, - title = {Alchemy: {Transmuting} {Base} {Alloy} {Specifications} into {Implementations}}, - isbn = {978-1-59593-995-1}, - Url_comment = {http://tmp_doi.acm.org/10.1145/1453101.1453123}, - tmp_doi_comment = {10.1145/1453101.1453123}, - booktitle = {Proceedings of the 16th {ACM} {SIGSOFT} {International} {Symposium} on {Foundations} of {Software} {Engineering}}, - publisher = {ACM}, - author = {Krishnamurthi, Shriram and Fisler, Kathi and Dougherty, Daniel J. and Yoo, Daniel}, - year = {2008}, - note = {event-place: Atlanta, Georgia}, - keywords = {alloy, program synthesis, relational specification}, - pages = {158--169} -} - -@article{kuncak_functional_2013, - title = {Functional synthesis for linear arithmetic and sets}, - volume = {15}, - issn = {1433-2787}, - Url_comment = {https://tmp_doi.org/10.1007/s10009-011-0217-7}, - tmp_doi_comment = {10.1007/s10009-011-0217-7}, - abstract = {Synthesis of program fragments from specifications can make programs easier to write and easier to reason about. To integrate synthesis into programming languages, synthesis algorithms should behave in a predictable way—they should succeed for a well-defined class of specifications. To guarantee correctness and applicability to software (and not just hardware), these algorithms should also support unbounded data types, such as numbers and data structures. To obtain appropriate synthesis algorithms, we propose to generalize decision procedures into predictable and complete synthesis procedures. Such procedures are guaranteed to find the code that satisfies the specification if such code exists. Moreover, we identify conditions under which synthesis will statically decide whether the solution is guaranteed to exist and whether it is unique. We demonstrate our approach by starting from a quantifier elimination decision procedure for Boolean algebra of set with Presburger arithmetic and transforming it into a synthesis procedure. Our procedure also works in the presence of parametric coefficients. We establish results on the size and the efficiency of the synthesized code. We show that such procedures are useful as a language extension with implicit value definitions, and we show how to extend a compiler to support such definitions. Our constructs provide the benefits of synthesis to programmers, without requiring them to learn new concepts, give up a deterministic execution model, or provide code skeletons.}, - number = {5}, - journal = {International Journal on Software Tools for Technology Transfer}, - author = {Kuncak, Viktor and Mayer, Mikaël and Piskac, Ruzica and Suter, Philippe}, - month = oct, - year = {2013}, - pages = {455--474} -} - -@inproceedings{massalin_superoptimizer:_1987, - address = {Los Alamitos, CA, USA}, - series = {{ASPLOS} {II}}, - title = {Superoptimizer: {A} {Look} at the {Smallest} {Program}}, - isbn = {0-8186-0805-6}, - Url_comment = {https://tmp_doi.org/10.1145/36206.36194}, - tmp_doi_comment = {10.1145/36206.36194}, - booktitle = {Proceedings of the {Second} {International} {Conference} on {Architectual} {Support} for {Programming} {Languages} and {Operating} {Systems}}, - publisher = {IEEE Computer Society Press}, - author = {Massalin, Henry}, - year = {1987}, - note = {event-place: Palo Alto, California, USA}, - pages = {122--126} -} - -@article{solar-lezama_program_2013, - title = {Program sketching}, - volume = {15}, - issn = {1433-2787}, - Url_comment = {https://tmp_doi.org/10.1007/s10009-012-0249-7}, - tmp_doi_comment = {10.1007/s10009-012-0249-7}, - abstract = {Sketching is a synthesis methodology that aims to bridge the gap between a programmer's high-level insights about a problem and the computer's ability to manage low-level details. In sketching, the programmer uses a partial program, a sketch, to describe the desired implementation strategy, and leaves the low-level details of the implementation to an automated synthesis procedure. In order to generate an implementation from the programmer provided sketch, the synthesizer uses counterexample-guided inductive synthesis (CEGIS). Inductive synthesis refers to the process of generating candidate implementations from concrete examples of correct or incorrect behavior. CEGIS combines a SAT-based inductive synthesizer with an automated validation procedure, a bounded model-checker, that checks whether the candidate implementation produced by inductive synthesis is indeed correct and to produce new counterexamples. The result is a synthesis procedure that is able to handle complex problems from a variety of domains including ciphers, scientific programs, and even concurrent data-structures.}, - number = {5}, - journal = {International Journal on Software Tools for Technology Transfer}, - author = {Solar-Lezama, Armando}, - month = oct, - year = {2013}, - pages = {475--495} -} - -@article{srivastava_template-based_2013, - title = {Template-based program verification and program synthesis}, - volume = {15}, - issn = {1433-2787}, - Url_comment = {https://tmp_doi.org/10.1007/s10009-012-0223-4}, - tmp_doi_comment = {10.1007/s10009-012-0223-4}, - abstract = {Program verification is the task of automatically generating proofs for a program's compliance with a given specification. Program synthesis is the task of automatically generating a program that meets a given specification. Both program verification and program synthesis can be viewed as search problems, for proofs and programs, respectively. For these search problems, we present approaches based on user-provided insights in the form of templates. Templates are hints about the syntactic forms of the invariants and programs, and help guide the search for solutions. We show how to reduce the template-based search problem to satisfiability solving, which permits the use of off-the-shelf solvers to efficiently explore the search space. Template-based approaches have allowed us to verify and synthesize programs outside the abilities of previous verifiers and synthesizers. Our approach can verify and synthesize difficult algorithmic textbook programs (e.g., sorting and dynamic programming-based algorithms) and difficult arithmetic programs.}, - number = {5}, - journal = {International Journal on Software Tools for Technology Transfer}, - author = {Srivastava, Saurabh and Gulwani, Sumit and Foster, Jeffrey S.}, - month = oct, - year = {2013}, - pages = {497--518} -} - -@book{steffen_module_1993, - title = {Module {Configuration} by {Minimal} {Model} {Construction}}, - author = {Steffen, Bernhard and Margaria, Tiziana and Freitag, Burkhard}, - year = {1993} -} - -@inproceedings{pnueli_distributed_1990, - title = {Distributed {Reactive} {Systems} {Are} {Hard} to {Synthesize}}, - booktitle = {{FOCS}}, - author = {Pnueli, Amir and Rosner, Roni}, - year = {1990} -} - -@article{church_logic_1964, - title = {Logic, {Arithmetic}, and {Automata}}, - volume = {29}, - number = {4}, - journal = {Journal of Symbolic Logic}, - author = {Church, Alonzo}, - year = {1964}, - pages = {210--210} -} - -@article{bloem_synthesis_2012, - title = {Synthesis of {Reactive}(1) designs}, - volume = {78}, - issn = {0022-0000}, - Url_comment = {http://www.sciencedirect.com/science/article/pii/S0022000011000869}, - tmp_doi_comment = {https://tmp_doi.org/10.1016/j.jcss.2011.08.007}, - number = {3}, - journal = {Journal of Computer and System Sciences}, - author = {Bloem, Roderick and Jobstmann, Barbara and Piterman, Nir and Pnueli, Amir and Saʼar, Yaniv}, - year = {2012}, - keywords = {Game theory, Property synthesis, Realizability}, - pages = {911 -- 938}, - annote = {In Commemoration of Amir Pnueli} -} - -@article{wessel_generic_2013, - title = {Generic mapping tools: improved version released}, - volume = {94}, - number = {45}, - journal = {EOS Trans. Amer. Geophys. U.}, - author = {Wessel, Paul and Smith, Walter HF and Scharroo, Remko and {others}}, - year = {2013}, - pages = {409--410} -} - -@article{reza_collaborative_nodate, - title = {Collaborative {Ontology} {Development} for the {Geosciences}}, - volume = {18}, - abstract = {Abstract Ontology‐based information publishing, retrieval, reuse, and integration have become popular research topics to address the challenges involved in exchanging data between heterogeneous sources. However, in most cases ontologies are still developed in a centralized top‐down manner by a few knowledge engineers. Consequently, the role that developers play in conceptualizing a domain such as the geosciences is disproportional compared with the role of domain experts and especially potential end‐users. These and other drawbacks have stimulated the creation of new methodologies focusing around collaboration. Based on a review of existing approaches, this article presents a two‐step methodology and implementation to foster collaborative ontology engineering in the geosciences. Our approach consists of the development of a minimalistic core ontology acting as a catalyst and the creation of a virtual collaborative development cycle. Both methodology and prototypical implementation have been tested in the context of the EU‐funded ForeStClim project which addresses environmental protection with respect to forests and climate change.}, - number = {6}, - journal = {Transactions in GIS}, - author = {Reza, Kalbasi and Krzysztof, Janowicz and Femke, Reitsma and Luc, Boerboom and Ali, Alesheikh}, - pages = {834--851} -} - -@article{albrecht_geo-ontology_2008, - title = {Geo-ontology {Tools}: {The} {Missing} {Link}}, - volume = {12}, - journal = {T. GIS}, - author = {Albrecht, Jochen and Derman, Brandon and Ramasubramanian, Laxmi}, - year = {2008}, - pages = {409--424} -} - -@inproceedings{cox_explicit_2013, - address = {Aachen, Germany, Germany}, - series = {{SSN}'13}, - title = {An {Explicit} {OWL} {Representation} of {ISO}/{OGC} {Observations} and {Measurements}}, - booktitle = {Proceedings of {SSN} 13 - {Volume} 1063}, - publisher = {CEUR-WS.org}, - author = {Cox, Simon J. D.}, - year = {2013}, - note = {event-place: Sydney, Australia}, - keywords = {ISO, observation, OGC, ontology alignment, OWL, semantic sensor network, sensor, UML}, - pages = {1--18} -} - -@techreport{lehmann_geoknow_2015, - title = {The {GeoKnow} {Handbook}}, - author = {Lehmann, Jens and Athanasiou, Spiros and Both, Andreas and {others}}, - year = {2015}, - keywords = {2015 MOLE buehmann geoknow group\_aksw hoeffner lehmann ngonga sherif westphal} -} - -@article{dodge_leatherback_2014, - title = {Leatherback {Turtle} {Movements}, {Dive} {Behavior}, and {Habitat} {Characteristics} in {Ecoregions} of the {Northwest} {Atlantic} {Ocean}}, - volume = {9}, - issn = {1932-6203}, - tmp_doi_comment = {10.1371/journal.pone.0091726}, - abstract = {Leatherback sea turtles, Dermochelys coriacea, are highly migratory predators that feed exclusively on gelatinous zooplankton, thus playing a unique role in coastal and pelagic food webs. From 2007 to 2010, we used satellite telemetry to monitor the movements and dive behavior of nine adult and eleven subadult leatherbacks captured on the Northeast USA shelf and tracked throughout the Northwest Atlantic. Leatherback movements and environmental associations varied by oceanographic region, with slow, sinuous, area-restricted search behavior and shorter, shallower dives occurring in cool (median sea surface temperature: 18.4°C), productive (median chlorophyll a: 0.80 mg m−3), shallow (median bathymetry: 57 m) shelf habitat with strong sea surface temperature gradients (median SST gradient: 0.23°C km−1) at temperate latitudes. Leatherbacks were highly aggregated in temperate shelf and slope waters during summer, early fall, and late spring and more widely dispersed in subtropical and tropical oceanic and neritic habitat during late fall, winter and early spring. We investigated the relationship of ecoregion, satellite-derived surface chlorophyll, satellite-derived sea surface temperature, SST gradient, chlorophyll gradient and bathymetry with leatherback search behavior using generalized linear mixed-effects models. The most well supported model showed that differences in leatherback search behavior were best explained by ecoregion and regional differences in bathymetry and SST. Within the Northwest Atlantic Shelves region, leatherbacks increased path sinuosity (i.e., looping movements) with increasing SST, but this relationship reversed within the Gulf Stream region. Leatherbacks increased path sinuosity with decreasing water depth in temperate and tropical shelf habitats. This relationship is consistent with increasing epipelagic gelatinous zooplankton biomass with decreasing water depth, and bathymetry may be a key feature in identifying leatherback foraging habitat in neritic regions. High-use habitat for leatherbacks in our study occurred in coastal waters of the North American eastern seaboard and eastern Caribbean, putting turtles at heightened risk from land- and ocean-based human activity.}, - number = {3}, - urldate = {2019-01-22}, - journal = {PLoS ONE}, - author = {Dodge, Kara L. and Galuardi, Benjamin and Miller, Timothy J. and {others}}, - month = mar, - year = {2014}, - pmid = {24646920}, - pmcid = {PMC3960146}, - keywords = {animal movements}, - file = {PubMed Central Full Text PDF:/home/vedran/Zotero/storage/JPQP2AKF/Dodge et al. - 2014 - Leatherback Turtle Movements, Dive Behavior, and H.pdf:application/pdf} -} - -@book{noauthor_data_2017, - title = {Data from: {Movement} patterns of a keystone waterbird species are highly predictable from landscape configuration}, - copyright = {license\_1}, - shorttitle = {Data from}, - Url_comment = {http://hdl.handle.net/10255/move.644}, - abstract = {Background: Movement behaviour is fundamental to the ecology of animals and their interactions with other organisms, and as such contributes to ecosystem dynamics. Waterfowl are key players in ecological processes in wetlands and surrounding habitats through predator-prey interactions and their transportation of nutrients and other organisms. Understanding the drivers of their movement behaviour is crucial to predict how environmental changes affect their role in ecosystem functioning. Mallards (Anas platyrhynchos) are the most abundant duck species worldwide and important dispersers of aquatic invertebrates, plants and pathogens like avian influenza viruses. By GPS tracking of 97 mallards in four landscape types along a gradient of wetland availability, we identified patterns in their daily movement behaviour and quantified potential effects of weather conditions and water availability on the spatial scale of their movements. Results: We demonstrate that mallard movement patterns were highly predictable, with regular commuting flights at dusk and dawn between a fixed day roost and one or several fixed nocturnal foraging sites, linked strongly to surface water. Wind and precipitation hardly affected movement, but flight distances and home range sizes increased when temperatures dropped towards zero. Flight distances and home range sizes increased exponentially with decreasing availability of freshwater habitat. Total shoreline length and the number of water bodies in the landscape surrounding the roost were the best predictors of the spatial scale of daily mallard movements. Conclusions: Our results show how mallards may flexibly adjust the spatial scale of their movements to wetland availability in the landscape. This implies that mallards moving between discrete habitat patches continue to preserve biotic connectivity in increasingly fragmented landscapes. The high predictability of mallard movement behaviour in relation to landscape features makes them reliable dispersal vectors for organisms to adapt to, and allows prediction of their ecological role in other landscapes.}, - language = {eng}, - year = {2017}, - keywords = {Anas platyrhynchos, animal movement, animal tracking, dispersal, ecological connectivity, habitat fragmentation, home range, land use change, landscape configuration, mallard, movement ecology}, - file = {Data from\: Movement patterns of a keystone waterbird species are highly predictable from landscape configuration:/home/vedran/Zotero/storage/J8T9B4KQ/move.html:text/html} -} - -@article{kleyheeg_movement_2017, - title = {Movement patterns of a keystone waterbird species are highly predictable from landscape configuration}, - volume = {5}, - issn = {2051-3933}, - tmp_doi_comment = {10.1186/s40462-016-0092-7}, - abstract = {Movement behaviour is fundamental to the ecology of animals and their interactions with other organisms, and as such contributes to ecosystem dynamics. Waterfowl are key players in ecological processes in wetlands and surrounding habitats through predator-prey interactions and their transportation of nutrients and other organisms. Understanding the drivers of their movement behaviour is crucial to predict how environmental changes affect their role in ecosystem functioning. Mallards (Anas platyrhynchos) are the most abundant duck species worldwide and important dispersers of aquatic invertebrates, plants and pathogens like avian influenza viruses. By GPS tracking of 97 mallards in four landscape types along a gradient of wetland availability, we identified patterns in their daily movement behaviour and quantified potential effects of weather conditions and water availability on the spatial scale of their movements.}, - number = {1}, - urldate = {2019-02-05}, - journal = {Movement Ecology}, - author = {Kleyheeg, Erik and van Dijk, Jacintha G. B. and Tsopoglou-Gkina, Despina and {others}}, - month = feb, - year = {2017}, - keywords = {Mallard movements in the Netherlands}, - pages = {2} -} - -@article{coyne_satellite_2005, - title = {Satellite {Tracking} and {Analysis} {Tool} ({STAT}): an integrated system for archiving, analyzing and mapping animal tracking data}, - volume = {301}, - issn = {0171-8630, 1616-1599}, - shorttitle = {Satellite {Tracking} and {Analysis} {Tool} ({STAT})}, - tmp_doi_comment = {10.3354/meps301001}, - abstract = {Despite the obvious power and advantages of the Argos system to track animals by satellite, the data generated are difficult for many biologists to exploit. A broad range of skills is required to efficiently download, collate, filter and interpret Argos data. Integration of animal movements with other physical (e.g. remote sensing imagery) and anthropogenic (e.g. fishery distributions) datasets presents additional technical and computing challenges. The Satellite Tracking and Analysis Tool (STAT) is a freely available system designed for biologists who work on animal tracking; it includes a set of standardized tools and techniques for data management, analysis, and integration with environmental data. STAT logs in to the Argos computer network each day and downloads all available locations and associated data for each user. These data are parsed and stored in a relational database and automatically backed up to an offsite location. A number of data filtering options are available, including setting maximum speed, time or distance between consecutive points, Argos location class, and turning angle. A variety of environmental data layers, including bathymetry, sea surface temperature, sea surface height, ocean currents and chlorophyll, can be sampled for all locations in the STAT database and can be downloaded and incorporated into tracking maps and animations. STAT also facilitates collaboration and the sharing of animal tracking information with the wider public and funding organizations. We hope that STAT will act as a catalytic foundation, fostering collaboration among users of satellite telemetry, and ensuring maximum value from these studies.}, - language = {en}, - urldate = {2019-01-22}, - journal = {Marine Ecology Progress Series}, - author = {Coyne, M. S. and Godley, B. J.}, - month = oct, - year = {2005}, - keywords = {Argos, Biologging, Oceanography, Satellite tracking, Wildlife telemetry}, - pages = {1--7} -} - -@article{gil_wings:_2011, - title = {Wings: {Intelligent} {Workflow}-{Based} {Design} of {Computational} {Experiments}}, - volume = {26}, - issn = {1541-1672}, - number = {1}, - journal = {IEEE Intelligent Systems}, - author = {Gil, Y. and Ratnakar, V. and Kim, J. and {others}}, - month = jan, - year = {2011}, - keywords = {Al planning, computational experiments, Computational intelligence, computer-supported discovery, data analysis, data set requirement, Design methodology, experiment design, Information Sciences Institute, intelligent systems, natural sciences computing, planning (artificial intelligence), software architecture, software components, Tracking, University of Southern California, workflow creation, workflow execution, workflow instance generation and specialization, workflow management, workflow management software, Workflow management software, workflow system, workflow validation}, - pages = {62--72} -} - -@book{johnston_using_2001, - title = {Using {ArcGIS} geostatistical analyst}, - volume = {380}, - publisher = {Esri Redlands}, - author = {Johnston, Kevin and Ver Hoef, Jay M and Krivoruchko, Konstantin and Lucas, Neil}, - year = {2001} -} - -@article{kranstauber_movebank_2011, - title = {The {Movebank} data model for animal tracking}, - volume = {26}, - issn = {1364-8152}, - tmp_doi_comment = {10.1016/j.envsoft.2010.12.005}, - abstract = {Studies of animal movement are rapidly increasing as tracking technologies make it possible to collect more data of a larger variety of species. Comparisons of animal movement across sites, times, or species are key to asking questions about animal adaptation, responses to climate and land-use change. Thus, great gains can be made by sharing and exchanging animal tracking data. Here we present an animal movement data model that we use within the Movebank web application to describe tracked animals. The model facilitates data comparisons across a broad range of taxa, study designs, and technologies, and is based on the scientific questions that could be addressed with the data.}, - number = {6}, - urldate = {2019-02-15}, - journal = {Environmental Modelling \& Software}, - author = {Kranstauber, B. and Cameron, A. and Weinzerl, R. and Fountain, T. and Tilak, S. and Wikelski, M. and Kays, R.}, - month = jun, - year = {2011}, - keywords = {Animal movement, Argos, Data model, GPS, Movebank, Tracking, VHF Telemetry}, - pages = {834--835}, - file = {ScienceDirect Full Text PDF:/home/vedran/Zotero/storage/WC2JLNQG/Kranstauber et al. - 2011 - The Movebank data model for animal tracking.pdf:application/pdf;ScienceDirect Snapshot:/home/vedran/Zotero/storage/3ARNIIG8/S1364815210003257.html:text/html} -} - -@inproceedings{lamprechtKasalica2018, - author = {Kasalica, Vedran and Lamprecht, Anna-Lena}, - year = {2018}, - month = {10}, - pages = {362-363}, - title = {Automated Composition of Scientific Workflows: A Case Study on Geographic Data Manipulation}, - tmp_doi_comment = {10.1109/eScience.2018.00099} -} - -@article{Biere2003BoundedMC, - title={Bounded model checking}, - author={Armin Biere and Alessandro Cimatti and Edmund M. Clarke and Ofer Strichman and Yunshan Zhu}, - journal={Advances in Computers}, - year={2003}, - volume={58}, - pages={117-148} -} - -@inproceedings{green_application_1969, - address = {San Francisco, CA, USA}, - series = {{IJCAI}'69}, - title = {Application of {Theorem} {Proving} to {Problem} {Solving}}, - url_comment = {http://dl.acm.org/citation.cfm?id=1624562.1624585}, - abstract = {This paper shows how an extension of the resolution proof procedure can be used to construct problem solutions. The extended proof procedure can solve problems involving state transformations. The paper explores several alternate problem representations and provides a discussion of solutions to sample problems including the "Monkey and Bananas" puzzle and the 'Tower of Hanoi" puzzle. The paper exhibits solutions to these problems obtained by QA3, a computer program bused on these theorem-proving methods. In addition, the paper shows how QA3 can write simple computer programs and can solve practical problems for a simple robot.}, - urldate = {2019-03-25}, - booktitle = {Proceedings of the 1st {International} {Joint} {Conference} on {Artificial} {Intelligence}}, - publisher = {Morgan Kaufmann Publishers Inc.}, - author = {Green, Cordell}, - year = {1969}, - note = {event-place: Washington, DC}, - keywords = {automatic programming, problem solving, program writing, question answering, resolution, robots, state transformations, theorem proving}, - pages = {219--239} -} - -@article{manna_toward_1971, - title = {Toward {Automatic} {Program} {Synthesis}}, - volume = {14}, - issn = {0001-0782}, - url_comment = {http://tmp_doi.acm.org/10.1145/362566.362568}, - tmp_doi_comment = {10.1145/362566.362568}, - abstract = {An elementary outline of the theorem-proving approach to automatic program synthesis is given, without dwelling on technical details. The method is illustrated by the automatic construction of both recursive and iterative programs operating on natural numbers, lists, and trees. -In order to construct a program satisfying certain specifications, a theorem induced by those specifications is proved, and the desired program is extracted from the proof. The same technique is applied to transform recursively defined functions into iterative programs, frequently with a major gain in efficiency. -It is emphasized that in order to construct a program with loops or with recursion, the principle of mathematical induction must be applied. The relation between the version of the induction rule used and the form of the program constructed is explored in some detail.}, - number = {3}, - urldate = {2019-03-25}, - journal = {Commun. ACM}, - author = {Manna, Zohar and Waldinger, Richard J.}, - month = mar, - year = {1971}, - keywords = {answer extraction, artificial intelligence, automatic program synthesis, mathematical induction principle, problem solving, theorem proving}, - pages = {151--165}, - file = {ACM Full Text PDF:/home/vedran/Zotero/storage/MNN77MEY/Manna and Waldinger - 1971 - Toward Automatic Program Synthesis.pdf:application/pdf} -} - -@article{manna_knowledge_1975, - title = {Knowledge and reasoning in program synthesis}, - volume = {6}, - issn = {0004-3702}, - url_comment = {http://www.sciencedirect.com/science/article/pii/0004370275900089}, - tmp_doi_comment = {10.1016/0004-3702(75)90008-9}, - abstract = {Program synthesis is the construction of a computer program from given specifications. An automatic program synthesis system must combine reasoning and programming ability with a good deal of knowledge about the subject matter of the program. This ability and knowledge must be manifested both procedurally (by programs) and structurally (by choice of representation). We describe some of the reasoning and programming capabilities of a projected synthesis system. Special attention is paid to the introduction of conditional tests, loops, and instructions with side effects in the program being constructed. The ability to satisfy several interacting goals simultaneously proves to be important in many contexts. The modification of an already existing program to solve a somewhat different problem has been found to be a powerful approach. We illustrate these concepts with hand simulations of the synthesis of a number of pattern-matching programs. Some of these techniques have already been implemented, some are in the course of implementation, while others seem equivalent to well-known unsolved problems in artificial intelligence.}, - number = {2}, - urldate = {2019-03-25}, - journal = {Artificial Intelligence}, - author = {Manna, Zohar and Waldinger, Richard}, - month = jun, - year = {1975}, - pages = {175--208}, - file = {ScienceDirect Full Text PDF:/home/vedran/Zotero/storage/KIAKYLR4/Manna and Waldinger - 1975 - Knowledge and reasoning in program synthesis.pdf:application/pdf;ScienceDirect Snapshot:/home/vedran/Zotero/storage/48JIW89X/0004370275900089.html:text/html} -} - -@inproceedings{gulwani_dimensions_2010, - address = {New York, NY, USA}, - series = {{PPDP} '10}, - title = {Dimensions in {Program} {Synthesis}}, - isbn = {978-1-4503-0132-9}, - url_comment = {http://tmp_doi.acm.org/10.1145/1836089.1836091}, - tmp_doi_comment = {10.1145/1836089.1836091}, - abstract = {Program Synthesis, which is the task of discovering programs that realize user intent, can be useful in several scenarios: enabling people with no programming background to develop utility programs, helping regular programmers automatically discover tricky/mundane details, program understanding, discovery of new algorithms, and even teaching. This paper describes three key dimensions in program synthesis: expression of user intent, space of programs over which to search, and the search technique. These concepts are illustrated by brief description of various program synthesis projects that target synthesis of a wide variety of programs such as standard undergraduate textbook algorithms e.g., sorting, dynamic programming), program inverses(e.g., decoders, deserializers), bitvector manipulation routines, deobfuscated programs, graph algorithms, text-manipulating routines, mutual exclusion algorithms, etc.}, - urldate = {2019-03-21}, - booktitle = {Proceedings of the 12th {International} {ACM} {SIGPLAN} {Symposium} on {Principles} and {Practice} of {Declarative} {Programming}}, - publisher = {ACM}, - author = {Gulwani, Sumit}, - year = {2010}, - note = {event-place: Hagenberg, Austria}, - keywords = {belief propagation, deductive synthesis, genetic programming, inductive synthesis, machine learning, probabilistic inference, programming by demonstration, programming by examples, sat solving, smt solving}, - pages = {13--24}, - file = {ACM Full Text PDF:/home/vedran/Zotero/storage/HH6YDTEK/Gulwani - 2010 - Dimensions in Program Synthesis.pdf:application/pdf} -} - -@inproceedings{alur_syntax_guided_2013, - title = {Syntax-guided synthesis}, - tmp_doi_comment = {10.1109/FMCAD.2013.6679385}, - abstract = {The classical formulation of the program-synthesis problem is to find a program that meets a correctness specification given as a logical formula. Recent work on program synthesis and program optimization illustrates many potential benefits of allowing the user to supplement the logical specification with a syntactic template that constrains the space of allowed implementations. Our goal is to identify the core computational problem common to these proposals in a logical framework. The input to the syntax-guided synthesis problem (SyGuS) consists of a background theory, a semantic correctness specification for the desired program given by a logical formula, and a syntactic set of candidate implementations given by a grammar. The computational problem then is to find an implementation from the set of candidate expressions so that it satisfies the specification in the given theory. We describe three different instantiations of the counter-example-guided-inductive-synthesis (CEGIS) strategy for solving the synthesis problem, report on prototype implementations, and present experimental results on an initial set of benchmarks.}, - booktitle = {2013 {Formal} {Methods} in {Computer}-{Aided} {Design}}, - author = {Alur, R. and Bodik, R. and Juniwal, G. and Martin, M. M. K. and Raghothaman, M. and Seshia, S. A. and Singh, R. and Solar-Lezama, A. and Torlak, E. and Udupa, A.}, - month = oct, - year = {2013}, - keywords = {automatic programming, CEGIS, computational linguistics, computational problem, Concrete, counter-example-guided-inductive-synthesis strategy, formal specification, Grammar, Heuristic algorithms, Libraries, logical formula, logical specification, Production, program optimization, program verification, program-synthesis problem, Search problems, semantic correctness specification, SyGuS, syntactic template, Syntactics, syntax-guided synthesis problem}, - pages = {1--8}, - file = {IEEE Xplore Abstract Record:/home/vedran/Zotero/storage/JJ2CETS7/6679385.html:text/html;Submitted Version:/home/vedran/Zotero/storage/KPBIBZ9F/Alur et al. - 2013 - Syntax-guided synthesis.pdf:application/pdf} -} - -@phdthesis{solar-lezama_program_2008, - address = {Berkeley, CA, USA}, - type = {{PhD} {Thesis}}, - title = {Program {Synthesis} by {Sketching}}, - abstract = {The goal of software synthesis is to generate programs automatically from high-level specifications. However, efficient implementations for challenging programs require a combination of high-level algorithmic insights and low-level implementation details. Deriving the low-level details is a natural job for a computer, but the synthesizer can not replace the human insight. Therefore, one of the central challenges for software synthesis is to establish a synergy between the programmer and the synthesizer, exploiting the programmer's expertise to reduce the burden on the synthesizer. This thesis introduces sketching, a new style of synthesis that offers a fresh approach to the synergy problem. Previous approaches have relied on meta-programming, or variations of interactive theorem proving to help the synthesizer deduce an efficient implementation. The resulting systems are very powerful, but they require the programmer to master new formalisms far removed from traditional programming models. To make synthesis accessible, programmers must be able to provide their insight effortlessly, using formalisms they already understand. In Sketching, insight is communicated through a partial program, a sketch that expresses the high-level structure of an implementation but leaves holes in place of the low-level details. This form of synthesis is made possible by a new SAT-based inductive synthesis procedure that can efficiently synthesize an implementation from a small number of test cases. This algorithm forms the core of a new counterexample guided inductive synthesis procedure (CEGIS) which combines the inductive synthesizer with a validation procedure to automatically generate test inputs and ensure that the generated program satisfies its specification. With a few extensions, CEGIS can even use its sequential inductive synthesizer to generate concurrent programs; all the concurrency related reasoning is delegated to an off-the-shelf validation procedure. The resulting synthesis system scales to real programming problems from a variety of domains ranging from bit-level ciphers to manipulations of linked datastructures. The system was even used to produce a complete optimized implementation of the AES cipher. The concurrency aware synthesizer was also used to synthesize, in a matter of minutes, the details of a fine-locking scheme for a concurrent set, a sense reversing barrier, and even a solution to the dining philosophers problem. The system was also extended with domain specific knowledge to better handle the problem of implementing stencil computations, an important domain in scientific computing. For this domain, we were able to encode domain specific insight as a problem reduction that converted stencil sketches into simplified sketch problems which CEGIS resolved in a matter of minutes. This specialized synthesizer was used to quickly implement a MultiGrid solver for partial differential equations containing many difficult implementation strategies from the literature. In short, this thesis shows that sketching is a viable approach to making synthesis practical in a general programming context.}, - school = {University of California at Berkeley}, - author = {Solar-Lezama, Armando}, - year = {2008}, - keywords = {CEGIS}, - annote = {AAI3353225} -} - - -@article{phothilimthana_scaling_2016, - title = {Scaling up {Superoptimization}}, - volume = {50}, - issn = {0163-5980, 0362-1340, 0163-5964}, - url_comment = {http://dl.acm.org/citation.cfm?id=2954680.2872387}, - tmp_doi_comment = {10.1145/2954680.2872387}, - number = {2}, - urldate = {2019-03-21}, - journal = {ACM SIGOPS Operating Systems Review}, - author = {Phothilimthana, Phitchaya Mangpo and Thakur, Aditya and Bodik, Rastislav and {others}}, - month = jun, - year = {2016}, - pages = {297--310}, - annote = {LENS algorithm}, - file = {Full Text:/home/vedran/Zotero/storage/VB2T9NX3/Phothilimthana et al. - 2016 - Scaling up Superoptimization.pdf:application/pdf;Snapshot:/home/vedran/Zotero/storage/E4P6JKKX/citation.html:text/html} -} - -@inproceedings{gulwani_synthesis_2011, - address = {New York, NY, USA}, - series = {{PLDI} '11}, - title = {Synthesis of {Loop}-free {Programs}}, - isbn = {978-1-4503-0663-8}, - url_comment = {http://tmp_doi.acm.org/10.1145/1993498.1993506}, - tmp_doi_comment = {10.1145/1993498.1993506}, - abstract = {We consider the problem of synthesizing loop-free programs that implement a desired functionality using components from a given library. Specifications of the desired functionality and the library components are provided as logical relations between their respective input and output variables. The library components can be used at most once, and hence the library is required to contain a reasonable overapproximation of the multiset of the components required. We solve the above component-based synthesis problem using a constraint-based approach that involves first generating a synthesis constraint, and then solving the constraint. The synthesis constraint is a first-order ∃∀ logic formula whose size is quadratic in the number of components. We present a novel algorithm for solving such constraints. Our algorithm is based on counterexample guided iterative synthesis paradigm and uses off-the-shelf SMT solvers. We present experimental results that show that our tool Brahma can efficiently synthesize highly nontrivial 10-20 line loop-free bitvector programs. These programs represent a state space of approximately 2010 programs, and are beyond the reach of the other tools based on sketching and superoptimization.}, - urldate = {2019-03-21}, - booktitle = {Proceedings of the 32Nd {ACM} {SIGPLAN} {Conference} on {Programming} {Language} {Design} and {Implementation}}, - publisher = {ACM}, - author = {Gulwani, Sumit and Jha, Susmit and Tiwari, Ashish and Venkatesan, Ramarathnam}, - year = {2011}, - note = {event-place: San Jose, California, USA}, - keywords = {program synthesis, component-based synthesis, smt}, - pages = {62--73}, - file = {ACM Full Text PDF:/home/vedran/Zotero/storage/MRVXKKAC/Gulwani et al. - 2011 - Synthesis of Loop-free Programs.pdf:application/pdf} -} - -@inproceedings{dijkstra_program_1979, - address = {London, UK, UK}, - title = {Program {Inversion}}, - isbn = {978-3-540-09251-3}, - url_comment = {http://dl.acm.org/citation.cfm?id=647639.733360}, - urldate = {2019-03-25}, - booktitle = {Program {Construction}, {International} {Summer} {School}}, - publisher = {Springer-Verlag}, - author = {Dijkstra, Edsger W.}, - year = {1979}, - pages = {54--57} -} - -@inproceedings{srivastava_program_2010, - address = {Madrid, Spain}, - title = {From program verification to program synthesis}, - booktitle = {Proceedings of the 37th {ACM} {SIGPLAN}-{SIGACT} {Symposium} on {Principles} of {Programming} {Languages} ({POPL} 2010)}, - publisher = {ACM}, - author = {Srivastava, Saurabh and Gulwani, Sumit and Foster, Jeffrey S.}, - year = {2010}, - pages = {313--326} -} - -@incollection{gulwani_programming_2016, - title = {Programming by examples (and its applications in data wrangling)}, - abstract = {Programming by Examples (PBE) has the potential to revolutionize enduser programming by enabling end users, most of whom are non-programmers, to create scripts for automating repetitive tasks. PBE involves synthesizing intended programs in an underlying domain-specific language (DSL) from example based specifications (Ispec).We formalize the notion of Ispec and discuss some principles behind designing useful DSLs for synthesis. A key technical challenge in PBE is to search for programs that are consistent with the Ispec provided by the user. We present a divide-and-conquer based search paradigm that leverages deductive rules and version space algebras for manipulating sets of programs. Another technical challenge in PBE is to resolve the ambiguity that is inherent in the Ispec. We show how machine learning based ranking techniques can be used to predict an intended program within a set of programs that are consistent with the Ispec. We also present some user interaction models including program navigation and active-learning based conversational clarification that communicate actionable information to the user to help resolve ambiguity in the Ispec. The above-mentioned concepts are illustrated using practical PBE systems for data wrangling (including FlashFill, FlashExtract, FlashRelate), several of which have already been deployed in the real world.}, - author = {Gulwani, S}, - month = apr, - year = {2016}, - tmp_doi_comment = {10.3233/978-1-61499-627-9-137}, - pages = {137--158}, - annote = {data wrangling} -} - -@inproceedings{gulwani_automating_2011, - address = {New York, NY, USA}, - series = {{POPL} '11}, - title = {Automating {String} {Processing} in {Spreadsheets} {Using} {Input}-output {Examples}}, - isbn = {978-1-4503-0490-0}, - url_comment = {http://tmp_doi.acm.org/10.1145/1926385.1926423}, - tmp_doi_comment = {10.1145/1926385.1926423}, - abstract = {We describe the design of a string programming/expression language that supports restricted forms of regular expressions, conditionals and loops. The language is expressive enough to represent a wide variety of string manipulation tasks that end-users struggle with. We describe an algorithm based on several novel concepts for synthesizing a desired program in this language from input-output examples. The synthesis algorithm is very efficient taking a fraction of a second for various benchmark examples. The synthesis algorithm is interactive and has several desirable features: it can rank multiple solutions and has fast convergence, it can detect noise in the user input, and it supports an active interaction model wherein the user is prompted to provide outputs on inputs that may have multiple computational interpretations. The algorithm has been implemented as an interactive add-in for Microsoft Excel spreadsheet system. The prototype tool has met the golden test - it has synthesized part of itself, and has been used to solve problems beyond author's imagination.}, - urldate = {2019-03-25}, - booktitle = {Proceedings of the 38th {Annual} {ACM} {SIGPLAN}-{SIGACT} {Symposium} on {Principles} of {Programming} {Languages}}, - publisher = {ACM}, - author = {Gulwani, Sumit}, - year = {2011}, - note = {event-place: Austin, Texas, USA}, - keywords = {program synthesis, programming by example (pbe), spreadsheet programming, string manipulation, user intent, version space algebra}, - pages = {317--330}, - file = {ACM Full Text PDF:/home/vedran/Zotero/storage/BW8XGWV3/Gulwani - 2011 - Automating String Processing in Spreadsheets Using.pdf:application/pdf} -} - -@article{mo_learning_1992, - title = {Learning text editing tasks from examples: a procedural approach}, - volume = {11}, - issn = {0144-929X}, - shorttitle = {Learning text editing tasks from examples}, - url_comment = {https://tmp_doi.org/10.1080/01449299208924317}, - tmp_doi_comment = {10.1080/01449299208924317}, - abstract = {Reformatting blocks of semi-structured information is a common editing task that typically involves highly repetitive action sequences, but ones where exceptional cases arise constantly and must be dealt with as they arise. This paper describes a procedural programming-by-example approach to repetitive text editing which allows users to construct programs within a standard editing interface and extend them incrementally. Following a brief practice period during which they settle on an editing strategy for the task at hand, users commence editing in the normal way. Once the first block of text has been edited, they inform the learning system which constructs a generalized procedure from the actions that have been recorded. The system then attempts to apply the procedure to the next block of text, by predicting editing actions and displaying them for confirmation. If the user accepts a prediction, the action is carried out (and the program may be generalized accordingly); otherwise the user is asked to intervene and supply additional information, in effect debugging the program on the fly. A pilot implementation is described that operates in a simple interactive point-and-click editor (Macintosh MINI-EDIT), along with its performance on three sample tasks. In one case the procedure was learned correctly from the actions on the first text block, while in the others minor debugging was needed on subsequent text blocks. In each case a much smaller number of both keystrokes and mouse-clicks was required than with normal editing, without the system making any prior assumptions about the stucture of the text except for some general knowledge about lexical patterns. Although a smooth interactive interface has not yet been constructed, the results obtained serve to indicate the potential of this approach for semi-structured editing tasks.}, - number = {1}, - urldate = {2019-03-22}, - journal = {Behaviour \& Information Technology}, - author = {MO, DAN H. and WITTEN, IAN H.}, - month = jan, - year = {1992}, - pages = {32--45}, - annote = {A simple approach used for text editing on principle of programming-by-example. Where system suggest solutions based on the provided examples, and user interacts with the system in order to confirm or improves the suggested solutions.}, - file = {Snapshot:/home/vedran/Zotero/storage/CQM4P5AW/01449299208924317.html:text/html;Submitted Version:/home/vedran/Zotero/storage/N5FTLPF8/MO and WITTEN - 1992 - Learning text editing tasks from examples a proce.pdf:application/pdf} -} - -@inproceedings{lau_version_2000, - address = {San Francisco, CA, USA}, - series = {{ICML} '00}, - title = {Version {Space} {Algebra} and {Its} {Application} to {Programming} by {Demonstration}}, - isbn = {978-1-55860-707-1}, - url_comment = {http://dl.acm.org/citation.cfm?id=645529.657973}, - abstract = {An abstract is not available.}, - urldate = {2019-03-22}, - booktitle = {Proceedings of the {Seventeenth} {International} {Conference} on {Machine} {Learning}}, - publisher = {Morgan Kaufmann Publishers Inc.}, - author = {Lau, Tessa A. and Domingos, Pedro and Weld, Daniel S.}, - year = {2000}, - pages = {527--534}, - file = {Lau et al. - 2000 - Version Space Algebra and Its Application to Progr.pdf:/home/vedran/Zotero/storage/L552NB85/Lau et al. - 2000 - Version Space Algebra and Its Application to Progr.pdf:application/pdf} -} - -@inproceedings{mandelin_jungloid_2005, - address = {New York, NY, USA}, - series = {{PLDI} '05}, - title = {Jungloid {Mining}: {Helping} to {Navigate} the {API} {Jungle}}, - isbn = {978-1-59593-056-9}, - shorttitle = {Jungloid {Mining}}, - url_comment = {http://tmp_doi.acm.org/10.1145/1065010.1065018}, - tmp_doi_comment = {10.1145/1065010.1065018}, - abstract = {Reuse of existing code from class libraries and frameworks is often difficult because APIs are complex and the client code required to use the APIs can be hard to write. We observed that a common scenario is that the programmer knows what type of object he needs, but does not know how to write the code to get the object.In order to help programmers write API client code more easily, we developed techniques for synthesizing jungloid code fragments automatically given a simple query that describes that desired code in terms of input and output types. A jungloid is simply a unary expression; jungloids are simple, enabling synthesis, but are also versatile, covering many coding problems, and composable, combining to form more complex code fragments. We synthesize jungloids using both API method signatures and jungloids mined from a corpus of sample client programs.We implemented a tool, prospector, based on these techniques. prospector is integrated with the Eclipse IDE code assistance feature, and it infers queries from context so there is no need for the programmer to write queries. We tested prospector on a set of real programming problems involving APIs; prospector found the desired solution for 18 of 20 problems. We also evaluated prospector in a user study, finding that programmers solved programming problems more quickly and with more reuse when using prospector than without prospector.}, - urldate = {2019-03-22}, - booktitle = {Proceedings of the 2005 {ACM} {SIGPLAN} {Conference} on {Programming} {Language} {Design} and {Implementation}}, - publisher = {ACM}, - author = {Mandelin, David and Xu, Lin and Bodík, Rastislav and Kimelman, Doug}, - year = {2005}, - note = {event-place: Chicago, IL, USA}, - keywords = {program synthesis, mining, reuse}, - pages = {48--61}, - file = {ACM Full Text PDF:/home/vedran/Zotero/storage/4KQR68Z4/Mandelin et al. - 2005 - Jungloid Mining Helping to Navigate the API Jungl.pdf:application/pdf} -} - -@article{kuncak_complete_2010, - title = {Complete functional synthesis}, - volume = {45}, - issn = {0362-1340}, - url_comment = {http://dl.acm.org/citation.cfm?id=1806596.1806632}, - tmp_doi_comment = {10.1145/1806596.1806632}, - number = {6}, - urldate = {2019-03-22}, - journal = {ACM SIGPLAN Notices}, - author = {Kuncak, Viktor and Mayer, Mikaël and Piskac, Ruzica and Suter, Philippe and Kuncak, Viktor and Mayer, Mikaël and Piskac, Ruzica and Suter, Philippe}, - month = jun, - year = {2010}, - pages = {316--329}, - file = {Snapshot:/home/vedran/Zotero/storage/AZANIXI3/citation.html:text/html;Submitted Version:/home/vedran/Zotero/storage/S2EVHMIT/Kuncak et al. - 2010 - Complete functional synthesis.pdf:application/pdf} -} - -@article{bodik_algorithmic_2013, - title = {Algorithmic program synthesis: introduction}, - volume = {15}, - issn = {1433-2787}, - shorttitle = {Algorithmic program synthesis}, - url_comment = {https://tmp_doi.org/10.1007/s10009-013-0287-9}, - tmp_doi_comment = {10.1007/s10009-013-0287-9}, - abstract = {Program synthesis is a process of producing an executable program from a specification. Algorithmic synthesis produces the program automatically, without an intervention from an expert. While classical compilation falls under the definition of algorithmic program synthesis, with the source program being the specification, the synthesis literature is typically concerned with producing programs that cannot be (easily) obtained with the deterministic transformations of a compiler. To this end, synthesis algorithms often perform a search, either in a space of candidate programs or in a space of transformations that might be composed to transform the specification into a desired program. In this introduction to the special journal issue, we survey the history of algorithmic program synthesis and introduce the contributed articles. We divide the field into reactive synthesis, which is concerned with automata-theoretic techniques for controllers that handle an infinite stream of requests, and functional synthesis, which produces programs consuming finite input. Contributed articles are divided analogously. We also provide pointers to synthesis work outside these categories and list many applications of synthesis.}, - language = {en}, - number = {5}, - urldate = {2018-09-12}, - journal = {International Journal on Software Tools for Technology Transfer}, - author = {Bodik, Rastislav and Jobstmann, Barbara}, - month = oct, - year = {2013}, - keywords = {Controller Synthesis, Formal Methods, Program synthesis, Specifications of Program Correctness}, - pages = {397--411}, - file = {Springer Full Text PDF:/home/vedran/Zotero/storage/UJYS9J5Y/Bodik and Jobstmann - 2013 - Algorithmic program synthesis introduction.pdf:application/pdf} -} - -@article{ison_tools_2016, - title = {Tools and data services registry: a community effort to document bioinformatics resources}, - volume = {44}, - issn = {1362-4962}, - shorttitle = {Tools and data services registry}, - tmp_doi_comment = {10.1093/nar/gkv1116}, - abstract = {Life sciences are yielding huge data sets that underpin scientific discoveries fundamental to improvement in human health, agriculture and the environment. In support of these discoveries, a plethora of databases and tools are deployed, in technically complex and diverse implementations, across a spectrum of scientific disciplines. The corpus of documentation of these resources is fragmented across the Web, with much redundancy, and has lacked a common standard of information. The outcome is that scientists must often struggle to find, understand, compare and use the best resources for the task at hand.Here we present a community-driven curation effort, supported by ELIXIR-the European infrastructure for biological information-that aspires to a comprehensive and consistent registry of information about bioinformatics resources. The sustainable upkeep of this Tools and Data Services Registry is assured by a curation effort driven by and tailored to local needs, and shared amongst a network of engaged partners.As of November 2015, the registry includes 1785 resources, with depositions from 126 individual registrations including 52 institutional providers and 74 individuals. With community support, the registry can become a standard for dissemination of information about bioinformatics resources: we welcome everyone to join us in this common endeavour. The registry is freely available at https://bio.tools.}, - language = {eng}, - number = {D1}, - journal = {Nucleic Acids Research}, - author = {Ison, Jon and Rapacki, Kristoffer and Ménager, Hervé and {others}}, - month = jan, - year = {2016}, - pmid = {26538599}, - pmcid = {PMC4702812}, - keywords = {Computational Biology, Software, Data Curation, Registries, bio.tools}, - pages = {D38--47}, - annote = {biotoolsSchema}, - file = {Full Text:/home/vedran/Zotero/storage/JMCZ6HV8/Ison et al. - 2016 - Tools and data services registry a community effo.pdf:application/pdf} -} - -@article{een_minisat_2005, - title = {{MiniSat} : {A} {SAT} solver with conflict-clause minimization}, - shorttitle = {{MiniSat}}, - url_comment = {https://ci.nii.ac.jp/naid/10026031126/}, - urldate = {2018-09-23}, - journal = {Proc. SAT-05: 8th Int. Conf. on Theory and Applications of Satisfiability Testing}, - author = {EEN, N.}, - year = {2005}, - keywords = {miniSAT}, - pages = {502--518}, - file = {MiniSat \: A SAT solver with conflict-clause minimization Snapshot:/home/vedran/Zotero/storage/PASNARIQ/10026031126.html:text/html} -} -@misc{SWS_wiki, - title = {Scientific workflow system}, - copyright = {Creative Commons Attribution-ShareAlike License}, - url = {https://en.wikipedia.org/w/index.php?title=Scientific_workflow_system}, - abstract = {A scientific workflow system is a specialized form of a workflow management system designed specifically to compose and execute a series of computational or data manipulation steps, or workflow, in a scientific application.}, - language = {en}, - urldate = {2019-02-15}, - journal = {Wikipedia}, - note = {[Online; 14 Feb 2019]} -} -@inproceedings{pnueli_synthesis_1989, - address = {New York, NY, USA}, - series = {{POPL} '89}, - title = {On the {Synthesis} of a {Reactive} {Module}}, - isbn = {978-0-89791-294-5}, - url_comment = {http://tmp_doi.acm.org/10.1145/75277.75293}, - tmp_doi_comment = {10.1145/75277.75293}, - abstract = {We consider the synthesis of a reactive module with input x and output y, which is specified by the linear temporal formula @@@@(x, y). We show that there exists a program satisfying @@@@ iff the branching time formula (∀x) (∃y) A@@@@(x, y) is valid over all tree models. For the restricted case that all variables range over finite domains, the validity problem is decidable, and we present an algorithm for constructing the program whenever it exists. The algorithm is based on a new procedure for checking the emptiness of Rabin automata on infinite trees in time exponential in the number of pairs, but only polynomial in the number of states. This leads to a synthesis algorithm whose complexity is double exponential in the length of the given specification.}, - urldate = {2018-09-12}, - booktitle = {Proceedings of the 16th {ACM} {SIGPLAN}-{SIGACT} {Symposium} on {Principles} of {Programming} {Languages}}, - publisher = {ACM}, - author = {Pnueli, A. and Rosner, R.}, - year = {1989}, - pages = {179--190}, - annote = {This is the main paper where Pnueli presented importance of the Program Synthesis.}, - file = {ACM Full Text PDF:/home/vedran/Zotero/storage/EZ9IDBVE/Pnueli and Rosner - 1989 - On the Synthesis of a Reactive Module.pdf:application/pdf} -} - -@incollection{antoniou_web_2004, - address = {Berlin, Heidelberg}, - series = {International {Handbooks} on {Information} {Systems}}, - title = {Web {Ontology} {Language}: {OWL}}, - shorttitle = {Web {Ontology} {Language}}, - abstract = {SummaryIn order to extend the limited expressiveness of RDF Schema, a more expressive Web Ontology Language (OWL) has been defined by the World Wide Web Consortium (W3C). In this chapter we analyse the limitations of RDF Schema and derive requirements for a richer Web Ontology Language. We then describe the three-layered architecture of the OWL language, and we describe all of the language constructs of OWL in some detail. The chapter concludes with two extensive examples of OWL ontologies.}, - language = {en}, - urldate = {2019-02-26}, - booktitle = {Handbook on {Ontologies}}, - publisher = {Springer Berlin Heidelberg}, - author = {Antoniou, Grigoris and van Harmelen, Frank}, - editor = {Staab, Steffen and Studer, Rudi}, - year = {2004}, - keywords = {Description Logic, Datatype Property, Reasoning Support, Resource Description Framework, Resource Description Framework Schema}, - pages = {67--92} -} - -@book{smith_pygmalion_1975, - title = {Pygmalion: {A} {Creative} {Programming} {Environment}}, - shorttitle = {Pygmalion}, - abstract = {PYGMALION is a two-dimensional, visual programming system implemented on an interactive computer with graphics display. Communication between human being and computer is by means of visual entities called icons, subsuming the notions of variable, reference, data stucture, function and picture. The heart of the system is an interactive remembering editor for icons, which executes and (Optionally) saves operations for later reexecution. The display screen is viewed as a document to be edited. Programming consists of recreating a sequence of display frames, the last of which contains the desired information. Display frames are modified by editing operations.}, - language = {en}, - publisher = {Computer Science Department, Stanford University}, - author = {Smith, David Canfield}, - year = {1975}, - note = {Google-Books-ID: mihHAAAAIAAJ} -} - -@incollection{summers_methodology_1986, - title = {A {Methodology} for {LISP} {Program} {Construction} from {Examples}}, - isbn = {978-0-934613-12-5}, - abstract = {An automatic programming system, THESYS, for constructing recursive Lisp programs from examples of what they do is described. The construction methodology is illustrated as a series of transformations from the set of examples to a program satisfying the examples. The transformations consist of (1) deriving the specific computation associated with a specific example, (2) deriving control flow predicates, and (3) deriving an equivalent program specification in the form of recurrence relations. Equivalence between certain recurrence relations and various program schemata is proved. A detailed description of the construction of four programs is presented to illustrate the application of the methodology.}, - language = {en}, - booktitle = {Readings in {Artificial} {Intelligence} and {Software} {Engineering}}, - publisher = {Morgan Kaufmann}, - author = {Summers, PHILLIP D.}, - editor = {Rich, Charles and Waters, Richard C.}, - month = jan, - year = {1986}, - keywords = {inductive inference, program synthesis, programming languages, recursive programs, sample computations}, - pages = {309--316}, - file = {ScienceDirect Snapshot:/home/vedran/Zotero/storage/89HXUH9A/B9780934613125500288.html:text/html} -} - -@techreport{shaw_inferring_1975, - title = {Inferring {LISP} {Programs} from {Examples}}, - institution = {Department of Computer Science, Columbia University}, - number = {CUCS-001-75}, - abstract = {A program is described which infers certain recursive LiSP programs from single example input-output parts. Synthesized programs may recur in more than one argument, and may involve the synthesis of auxilliary functions. An actual user session with the program, called EXAMPLE, is presented, and the operation of the program and its important heuristics are outlined.}, - language = {en}, - author = {Shaw, David Elliot and Swartout, William R. and Green, C. Cordell}, - year = {1975}, - file = {Full Text PDF:/home/vedran/Zotero/storage/FA384CED/Shaw et al. - 1975 - Inferring LISP Programs from Examples.pdf:application/pdf;Snapshot:/home/vedran/Zotero/storage/SJ57PZYJ/D89K4K6X.html:text/html} -} - -@inproceedings{kautz_planning_1992, - address = {Vienna, Austria}, - series = {{ECAI} '92}, - title = {Planning as satisfiability}, - isbn = {978-0-471-93608-4}, - urldate = {2020-02-01}, - booktitle = {Proceedings of the 10th {European} conference on {Artificial} intelligence}, - publisher = {John Wiley \& Sons, Inc.}, - author = {Kautz, Henry and Selman, Bart}, - month = aug, - year = {1992}, - pages = {359--363} -} - - -@inproceedings{kautz_pushing_1996, - address = {Portland, Oregon}, - series = {{AAAI}'96}, - title = {Pushing the envelope: planning, propositional logic, and stochastic search}, - isbn = {978-0-262-51091-2}, - shorttitle = {Pushing the envelope}, - abstract = {Planning is a notoriously hard combinatorial search problem. In many interesting domains, current planning algorithms fail to scale up gracefully. By combining a general, stochastic search algorithm and appropriate problem encodings based on propositional logic, we are able to solve hard planning problems many times faster than the best current planning systems. Although stochastic methods have been shown to be very effective on a wide range of scheduling problems, this is the first demonstration of its power on truly challenging classical planning instances. This work also provides a new perspective on representational issues in planning.}, - urldate = {2020-02-01}, - booktitle = {Proceedings of the thirteenth national conference on {Artificial} intelligence - {Volume} 2}, - publisher = {AAAI Press}, - author = {Kautz, Henry and Selman, Bart}, - month = aug, - year = {1996}, - pages = {1194--1201} -} - - -@article{di_tommaso_nextflow_2017, - title = {Nextflow enables reproducible computational workflows}, - volume = {35}, - tmp_doi = {10.1038/nbt.3820}, - journal = {Nature Biotechnology}, - author = {Di Tommaso, Paolo and Chatzou, Maria and Floden, Evan W. and {others}}, - month = apr, - year = {2017}, - pages = {316--319} -} - -@article{koster_snakemakescalable_2012, - title = {Snakemake—a scalable bioinformatics workflow engine}, - volume = {28}, - issn = {1367-4803}, - tmp_url = {https://academic.oup.com/bioinformatics/article/28/19/2520/290322}, - tmp_doi = {10.1093/bioinformatics/bts480}, - abstract = {Abstract. Summary: Snakemake is a workflow engine that provides a readable Python-based workflow definition language and a powerful execution environment that}, - language = {en}, - number = {19}, - urldate = {2020-02-04}, - journal = {Bioinformatics}, - author = {Köster, Johannes and Rahmann, Sven}, - month = oct, - year = {2012}, - pages = {2520--2522}, - file = {Full Text PDF:/home/vedran/Zotero/storage/N6VLMMIY/Köster and Rahmann - 2012 - Snakemake—a scalable bioinformatics workflow engin.pdf:application/pdf;Snapshot:/home/vedran/Zotero/storage/IJ6QVPEL/290322.html:text/html} -} - -@article{amstutz_common_2016, - title = {Common {Workflow} {Language}, v1.0}, - tmp_url = {https://www.research.manchester.ac.uk/portal/en/publications/common-workflow-language-v10(741919f5-d0ab-4557-9763-b811e911423b)/publications.html}, - tmp_doi = {10.6084/m9.figshare.3115156.v2}, - language = {English}, - urldate = {2020-02-04}, - author = {Amstutz, Peter and Crusoe, Michael R. and Tijanić, Nebojša and others}, - month = jul, - year = {2016}, - file = {Full Text PDF:/home/vedran/Zotero/storage/DHU46ABD/Amstutz et al. - 2016 - Common Workflow Language, v1.0.pdf:application/pdf;Snapshot:/home/vedran/Zotero/storage/4LJAXUGI/publications.html:text/html} -} - -@article{goecks_2010, - title = {Galaxy: a comprehensive approach for supporting accessible, reproducible, and transparent computational research in the life sciences}, - volume = {11}, - issn = {1474-760X}, - shorttitle = {Galaxy}, - tmp_url = {https://tmp_doi.org/10.1186/gb-2010-11-8-r86}, - tmp_doi = {10.1186/gb-2010-11-8-r86}, - abstract = {Increased reliance on computational approaches in the life sciences has revealed grave concerns about how accessible and reproducible computation-reliant results truly are. Galaxy http://usegalaxy.org, an open web-based platform for genomic research, addresses these problems. Galaxy automatically tracks and manages data provenance and provides support for capturing the context and intent of computational methods. Galaxy Pages are interactive, web-based documents that provide users with a medium to communicate a complete computational analysis.}, - language = {en}, - number = {8}, - urldate = {2020-02-04}, - journal = {Genome Biology}, - author = {Goecks, Jeremy and Nekrutenko, Anton and Taylor, James and {others}}, - month = aug, - year = {2010}, - keywords = {Analysis Workspace, Galaxy Server, Phylogenetic Profile, Public Repository, User Metadata}, - pages = {R86}, - file = {Springer Full Text PDF:/home/vedran/Zotero/storage/NC7ES8M6/Goecks et al. - 2010 - Galaxy a comprehensive approach for supporting ac.pdf:application/pdf} -} -@article{berthold2009knime, - title={KNIME-the Konstanz information miner: version 2.0 and beyond}, - author={Berthold, Michael R and Cebron, Nicolas and Dill, Fabian and Gabriel, Thomas R and K{\"o}tter, Tobias and Meinl, Thorsten and Ohl, Peter and Thiel, Kilian and Wiswedel, Bernd}, - journal={AcM SIGKDD explorations Newsletter}, - volume={11}, - number={1}, - pages={26--31}, - year={2009}, - publisher={ACM New York, NY, USA} -} - -@misc{toolsbiotoolsschema_2019, - title = {bio-tools/{biotoolsSchema}}, - copyright = {CC-BY-SA-4.0}, - url = {https://github.com/bio-tools/biotoolsSchema}, - abstract = {biotoolsSchema : Tool description data model for computational tools in life sciences}, - urldate = {2020-02-04}, - publisher = {bio.tools}, - month = dec, - year = {2019}, - note = {original-date: 2015-05-05T15:52:46Z} -} -@inproceedings{lawrence1997workflow, - title={Workflow handbook}, - author={Lawrence, Peter and Bouzeghoub, Mokrane and Fabret, Fran{\c{c}}oise and Matulovic-broqu{\'e}, Maja}, - booktitle={In Proc. Intl. Workshop on Design and Management of Data Warehouses (DMDW’99}, - year={1997}, - organization={Citeseer} -} - -@book{fischer2002workflow, - title={Workflow handbook 2002}, - author={Fischer, Layna}, - year={2002}, - publisher={Future Strategies Inc.} -} - -@article{van2005yawl, - title={YAWL: yet another workflow language}, - author={Van Der Aalst, Wil MP and Ter Hofstede, Arthur HM}, - journal={Information systems}, - volume={30}, - number={4}, - pages={245--275}, - year={2005}, - publisher={Elsevier} -} - -@article{amstutz2016common, - title={Common workflow language, v1. 0}, - author={Amstutz, Peter and Crusoe, Michael R and Tijani{\'c}, Neboj{\v{s}}a and Chapman, Brad and Chilton, John and Heuer, Michael and Kartashov, Andrey and Leehr, Dan and M{\'e}nager, Herv{\'e} and Nedeljkovich, Maya and others}, - year={2016}, - publisher={Figshare} -} - - -@article{vivian_toil_2017, - title = {Toil enables reproducible, open source, big biomedical data analyses}, - volume = {35}, - issn = {1546-1696}, - url = {http://www.nature.com/articles/nbt.3772}, - doi = {10.1038/nbt.3772}, - language = {en}, - number = {4}, - urldate = {2020-04-15}, - journal = {Nature Biotechnology}, - author = {Vivian, John and Rao, Arjun Arkal and Nothaft, Frank Austin and Ketchum, Christopher and Armstrong, Joel and Novak, Adam and Pfeil, Jacob and Narkizian, Jake and Deran, Alden D. and Musselman-Brown, Audrey and Schmidt, Hannes and Amstutz, Peter and Craft, Brian and Goldman, Mary and Rosenbloom, Kate and Cline, Melissa and O'Connor, Brian and Hanna, Megan and Birger, Chet and Kent, W. James and Patterson, David A. and Joseph, Anthony D. and Zhu, Jingchun and Zaranek, Sasha and Getz, Gad and Haussler, David and Paten, Benedict}, - month = apr, - year = {2017}, - pages = {314--316}, - file = {Full Text PDF:/home/vedran/Zotero/storage/QZPUW2D2/Vivian et al. - 2017 - Toil enables reproducible, open source, big biomed.pdf:application/pdf;Snapshot:/home/vedran/Zotero/storage/ZGXSNXYC/nbt.html:text/html} -} -@misc{noauthor_workflow_2020, - title = {Workflow {Description} {Language} ({WDL})}, - copyright = {BSD-3-Clause}, - url = {https://github.com/openwdl/wdl}, - abstract = {Workflow Description Language}, - urldate = {2020-04-15}, - publisher = {openwdl}, - month = apr, - year = {2020}, - note = {original-date: 2012-08-01T03:12:48Z}, - keywords = {bioinformatics, cloud, cromwell, openwdl, reproducibility, reproducible-science, wdl, workflow} -} -@InProceedings{kasalica2020, -author="Kasalica, Vedran -and Lamprecht, Anna-Lena", -editor="Krzhizhanovskaya, Valeria V. -and Z{\'a}vodszky, G{\'a}bor -and Lees, Michael H. -and Dongarra, Jack J. -and Sloot, Peter M. A. -and Brissos, S{\'e}rgio -and Teixeira, Jo{\~a}o", -title="APE: A Command-Line Tool and API for Automated Workflow Composition", -booktitle="Computational Science -- ICCS 2020", -year="2020", -publisher="Springer International Publishing", -address="Cham", -pages="464--476", -abstract="Automated workflow composition is bound to take the work with scientific workflows to the next level. On top of today's comprehensive eScience infrastructure, it enables the automated generation of possible workflows for a given specification. However, functionality for automated workflow composition tends to be integrated with one of the many available workflow management systems, and is thus difficult or impossible to apply in other environments. Therefore we have developed APE (the Automated Pipeline Explorer) as a command-line tool and API for automated composition of scientific workflows. APE is easily configured to a new application domain by providing it with a domain ontology and semantically annotated tools. It can then be used to synthesize purpose-specific workflows based on a specification of the available workflow inputs, desired outputs and possibly additional constraints. The workflows can further be transformed into executable implementations and/or exported into standard workflow formats. In this paper we describe APE v1.0 and discuss lessons learned from applications in bioinformatics and geosciences.", -isbn="978-3-030-50436-6" -} - -@article{georgakopoulos_overview_1995, - title = {An overview of workflow management: {From} process modeling to workflow automation infrastructure}, - volume = {3}, - issn = {1573-7578}, - shorttitle = {An overview of workflow management}, - url = {https://doi.org/10.1007/BF01277643}, - doi = {10.1007/BF01277643}, - abstract = {Today's business enterprises must deal with global competition, reduce the cost of doing business, and rapidly develop new services and products. To address these requirements enterprises must constantly reconsider and optimize the way they do business and change their information systems and applications to support evolving business processes. Workflow technology facilitates these by providing methodologies and software to support (i) business process modeling to capture business processes as workflow specifications, (ii) business process reengineering to optimize specified processes, and (iii) workflow automation to generate workflow implementations from workflow specifications. This paper provides a high-level overview of the current workflow management methodologies and software products. In addition, we discuss the infrastructure technologies that can address the limitations of current commercial workflow technology and extend the scope and mission of workflow management systems to support increased workflow automation in complex real-world environments involving heterogeneous, autonomous, and distributed information systems. In particular, we discuss how distributed object management and customized transaction management can support further advances in the commercial state of the art in this area.}, - language = {en}, - number = {2}, - urldate = {2020-07-07}, - journal = {Distributed and Parallel Databases}, - author = {Georgakopoulos, Diimitrios and Hornick, Mark and Sheth, Amit}, - month = apr, - year = {1995}, - pages = {119--153} -} - -@Book{Lampre2013, - Title = {{U}ser-{L}evel {W}orkflow {D}esign - {A} {B}ioinformatics {P}erspective}, - Author = {Anna-Lena Lamprecht}, - Publisher = {Springer}, - Year = {2013}, - Series = {Lecture Notes in Computer Science}, - Volume = {8311}, - - Doi = {10.1007/978-3-642-45389-2}, - Ee = {http://dx.doi.org/10.1007/978-3-642-45389-2}, - File = {Lampre2012 (User-Level Workflow Design - A Bioinformatics Perspective).pdf:Lampre2012 (User-Level Workflow Design - A Bioinformatics Perspective).pdf:PDF}, - ISBN = {978-3-642-45388-5, 978-3-642-45389-2}, - Keywords = {bio-jeti, prophets, bioinformatics, synthesis, ser-level workflow design}, - Owner = {Lamprecht}, - Pages = {1-202}, - School = {Technische Universität Dortmund}, - Timestamp = {2012.07.04}, - Type = {Dissertation} -} - -@InCollection{KaMaRT2010, - Title = {{W}orkflow {C}omposition and {E}nactment {U}sing j{ORCA}}, - Author = {Karlsson, Johan and Martín-Requena, Victoria and Ríos, Javier and {others}}, - Booktitle = {Leveraging Applications of Formal Methods, Verification, and Validation}, - Publisher = {Springer Berlin / Heidelberg}, - Year = {2010}, - Pages = {328-339}, - Series = {Lecture Notes in Computer Science}, - Volume = {6415}, - - Affiliation = {Computer Architecture Department, University of Malaga, Campus de Teatinos, 29071 Málaga, Spain}, - File = {KaMaRT2010 (Workflow Composition and Enactment Using jORCA).pdf:KaMaRT2010 (Workflow Composition and Enactment Using jORCA).pdf:PDF}, - Keywords = {bioinformatics, workflows, synthesis}, - Owner = {Lamprecht}, - Timestamp = {2011.07.04}, - Tmp_Url = {http://dx.doi.org/10.1007/978-3-642-16558-0_28} -} - -@InProceedings{LaNaMS2010, - Title = {{S}ynthesis-{B}ased {L}oose {P}rogramming}, - Author = {Anna-Lena Lamprecht and Stefan Naujokat and Tiziana Margaria and Bernhard Steffen}, - Booktitle = {QUATIC 2010, Porto, Portugal}, - Year = {2010}, - Month = sep, - Pages = {262-267}, - Publisher = {IEEE}, - - Abstract = {In this paper we present loose programming, an approach designed to enable process developers to design their application-specific processes in an intuitive style. Key to this approach is the concept of loose specification, a graphical formalism that allows developers to express their processes just by sketching them as kinds of flow graphs without caring about types, precise knowledge about the available process components or the availability of resources. They only have to specify the rough process flow graphically in terms of ontologically defined ‘semantic’ entities. These loose specifications are then concretized to fully executable process code automatically by means of a combination of 1) data-flow analysis, ensuring the availability of the required resources, 2) temporal logic-based process synthesis, resolving type conflicts and taking care of correct component instantiation, and 3) model checking, to ensure global intents and invariants expressed in temporal logic.}, - Tmp_Doi = {10.1109/QUATIC.2010.53}, - File = {LaNaMS2010 (Synthesis-Based Loose Programming).pdf:LaNaMS2010 (Synthesis-Based Loose Programming).pdf:PDF}, - Keywords = {synthesis, loose programming, loose specification}, - Owner = {naujokat} -} - -@TechReport{StMaFr1993, - Title = {{M}odule {C}onfiguration by {M}inimal {M}odel {C}onstruction}, - Author = {Bernhard Steffen and Tiziana Margaria and Burkhard Freitag}, - Institution = {Fakultät für Mathematik und Informatik, Universität Passau}, - Year = {1993}, - - File = {StMaFr1993 (Module Configuration by Minimal Model Construction).pdf:StMaFr1993 (Module Configuration by Minimal Model Construction).pdf:PDF}, - Keywords = {synthesis}, - Owner = {naujokat}, - Timestamp = {2009.11.23} -} - - -@article{martin_high-level_2009, - title = {High-{Level} {Synthesis}: {Past}, {Present}, and {Future}}, - volume = {26}, - issn = {0740-7475}, - doi = {10.1109/MDT.2009.83}, - number = {4}, - journal = {IEEE Design Test of Computers}, - author = {Martin, G. and Smith, G.}, - month = jul, - year = {2009}, - keywords = {History, design and test, high level synthesis, High level synthesis, high-level synthesis, history, Algorithm design and analysis, behavioral synthesis, commercial use, Commercialization, Computer industry, Electronic design automation and methodology, Electronics industry, ESL synthesis, Hardware, High-level synthesis, HLS tools, industry adoption, Machinery production industries, Physics computing, system-level design}, - pages = {18--25} -} - - -@misc{cwl_computational_ws, - title = {Computational {Data} {Analysis} {Workflow} {Systems}}, - url = {https://github.com/common-workflow-language/common-workflow-language}, - abstract = {Repository for the CWL standards. Use https://cwl.discourse.group/ for support 😊 - common-workflow-language/common-workflow-language}, - language = {en}, - year = {2020}, - urldate = {2020-07-16}, - journal = {GitHub}, - note = {Library Catalog: github.com}, - file = {Snapshot:/home/vedran/Zotero/storage/SPWL2FE4/Existing-Workflow-systems.html:text/html} -} - diff --git a/paper/paper.md b/paper/paper.md deleted file mode 100644 index 8bba951..0000000 --- a/paper/paper.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: 'APE: A Java Library for Automated Exploration of Computational Pipelines' -tags: - - automated workflow exploration - - automated workflow composition - - scientific workflows - - computational pipelines - - workflow synthesis -authors: - - name: Vedran Kasalica - orcid: 0000-0002-0097-1056 - affiliation: 1 - - name: Maurin Voshol - affiliation: 1 - - name: Anna-Lena Lamprecht - orcid: 0000-0003-1953-5606 - affiliation: 1 -affiliations: - - name: Department of Information and Computing Sciences, Utrecht University, 3584 CC Utrecht, Netherlands - index: 1 -date: 7 July 2020 -bibliography: paper.bib - ---- - -# Summary - -Scientists across all disciplines frequently combine diverse computational tools into computational pipelines (a.k.a. scientific workflows) to solve specific data analysis problems. Software registries provide large collections of computational tools, often with rich metadata that captures their functional and non-functional properties. However, finding the right (combinations of) tools for building a problem-specific workflow remains a challenge. - -Therefore we have developed the Automated Pipeline Explorer (APE)^[https://github.com/sanctuuary/ape] [@kasalica2020] to support workflow developers in systematically exploring the possible pipelines of tools for a given computational problem. Like a route planner, it takes a starting point (input data), destination (desired outputs) and possibly additional constraints (such as kinds of operations to use), and returns a set of possible routes (pipelines) that meet the request. As described in detail in [@kasalica2019], internally the framework uses an extension of the well-known Linear Temporal Logic (LTL) to encode the workflow specification. This specification is translated into a propositional logic formula and handed over to a SAT solver, with the resulting solutions representing possible workflows. - -Working with APE has three main phases: -1) Modeling of the *domain knowledge*, which provides the base on which APE relies for the exploration of workflows. It comprises lightweight ontologies, used to annotate operations and data from the domain in form of semantic hierarchies, and tool annotations, i.e. input and output dependencies of the tools. Ideally, the modelling is performed by a small group of domain experts. -2) *Problem specification*, where the user describes the data analysis problem to solve using the vocabulary provided by the domain model. A problem specification for APE comprises the workflow inputs, the desired outputs, and constraints that the workflow has to fulfill. The constraints are exposed in the form of fill-in-the-blank templates (such as "Use operation X" or "If tool X is used, tool Y cannot be used subsequently", etc.). -3) Performing the actual *workflow exploration*. Finally, the obtained candidate solutions that satisfy the specification are returned. The solutions can be presented as workflow structures, executable implementations (such as shell scripts) and/or exported into standard workflow formats (such as CWL) [@amstutz_common_2016]. - -APE has successfully been used for the automated composition of workflows for data analysis in mass spectrometry-based proteomics [@palmblad_automated_2018] (based on the EDAM ontology [@ison2013edam] and the bio.tools [@ison_tools_2016] registry as domain models), creation of thematic maps depicting bird movement patterns in the Netherlands [@kasalicaLamprecht2019] (based on the GMT collection of mapping tools [@wessel_generic_2013]), and creation of a liveability atlas of Amsterdam [@scheiderCCD2020] (based on standard GIS operations as provided by ArcGIS). Further applications, in particular in bioinformatics and geosciences, are currently being developed. - -APE has been inspired by the ideas behind the PROPHETS framework for synthesis-based loose programming [@Lampre2013; @LaNaMS2010; @StMaFr1993], the automated chaining of scientific web services in jORCA/Magallanes [@KaMaRT2010], and the AI planning-based automated workflow instantiation in WINGS [@gil_wings:_2011]. -However, it sets itself apart from these systems by a clear focus on workflow/pipeline exploration in a stand-alone library that is independent from any concrete workflow system. Thus, workflow management systems [@martin_high-level_2009; @cwl_computational_ws] can integrate APE functionality and make automated workflow exploration available to their users. - -# Acknowledgements - -The development of APE has been supported by the last author's Westerdijk Fellowship (Utrecht University, Faculty of Science) and Open Science Community Utrecht Faculty Ambassadorship (Utrecht University, Open Science Program). -We are grateful to our users and collaborators for their continuous feedback that helps us improving APE. - -# References From 52e3e7ca805f5250c31fdbf3532df303b5fb083a Mon Sep 17 00:00:00 2001 From: Vedran Kasalica Date: Wed, 2 Oct 2024 01:37:38 +0200 Subject: [PATCH 09/13] Refactor BioToolsAPI and include tests + update the build job as the used repo was renamed --- .github/workflows/mvnbuild.yml | 4 +- src/main/java/nl/uu/cs/ape/Main.java | 36 ++- .../java/nl/uu/cs/ape/domain/BioToolsAPI.java | 303 +++++++++++------- .../cs/ape/test/sat/ape/BioToolsAPITest.java | 86 +++++ .../nl/uu/cs/ape/test/sat/ape/CLITest.java | 8 +- 5 files changed, 308 insertions(+), 129 deletions(-) create mode 100644 src/test/java/nl/uu/cs/ape/test/sat/ape/BioToolsAPITest.java diff --git a/.github/workflows/mvnbuild.yml b/.github/workflows/mvnbuild.yml index 5e982ca..ab73c27 100644 --- a/.github/workflows/mvnbuild.yml +++ b/.github/workflows/mvnbuild.yml @@ -35,8 +35,8 @@ jobs: pip3 install cwlref-runner - name: Test CWL generation run: | - git clone https://github.com/Workflomics/containers - cd containers/domains/proteomics + git clone https://github.com/Workflomics/tools-and-domains + cd tools-and-domains/domains/proteomics java -jar ../../../target/APE-*-executable.jar ./config.json cd ./CWL cwltool --enable-dev --validate candidate_workflow_1.cwl diff --git a/src/main/java/nl/uu/cs/ape/Main.java b/src/main/java/nl/uu/cs/ape/Main.java index 754dd04..7e813d1 100644 --- a/src/main/java/nl/uu/cs/ape/Main.java +++ b/src/main/java/nl/uu/cs/ape/Main.java @@ -14,6 +14,7 @@ import java.io.File; import java.io.IOException; +import java.util.List; /** * The entry point of application when the library is used in a Command Line @@ -41,9 +42,12 @@ public static void main(String[] args) { case "convert-tools": convertBioToolsAnnotations(ArrayUtils.remove(args, 0)); break; + case "pull-a-tool": + pullATool(ArrayUtils.remove(args, 0)); + break; case "bio.tools": try { - BioToolsAPI.fetchBioTools("./tools.json"); + BioToolsAPI.getAndSaveFullBioTools("./tools.json"); } catch (IOException e) { log.error("Error in fetching the tools from bio.tools."); } @@ -58,6 +62,28 @@ public static void main(String[] args) { } + private static void pullATool(String[] args) { + if (args.length != 1) { + log.error("Error: pull-a-tool method expects biotoolsID as the only additional argument."); + return; + } + + String biotoolsID = args[0]; + if (biotoolsID.isEmpty()) { + log.error("Error: biotoolsID should be provided as an additional argument."); + return; + } + + try { + JSONObject tool = BioToolsAPI.getAndConvertToolList(List.of(biotoolsID)); + APEFiles.write2file(tool.toString(4), new File("./tool.json"), false); + } catch (IOException e) { + log.error("Error in fetching the tool from bio.tools."); + return; + } + + } + /** * Retrieve tools from bio.tools using bio.tools API and convert them to * APE-compatible tool annotation format. @@ -66,20 +92,20 @@ public static void main(String[] args) { * expected, the path to the file where the biotoolsIDs are stored. */ public static void convertBioToolsAnnotations(String[] args) { - String path; if (args.length != 1) { log.error("Error: bio.tools method expects path as the only additional argument."); return; } - path = args[0]; - if (!APEFiles.isValidReadFile(path)) { + String pathToListIDs = args[0]; + if (!APEFiles.isValidReadFile(pathToListIDs)) { log.error("Error: Invalid path provided."); return; } try { - BioToolsAPI.fetchToolSet(path, "./tools.json"); + JSONObject apeToolAnnotation = BioToolsAPI.getAndConvertToolList(new File(pathToListIDs)); + APEFiles.write2file(apeToolAnnotation.toString(4), new File("./tools.json"), false); } catch (IOException e) { log.error("Error in fetching the tools from bio.tools."); return; diff --git a/src/main/java/nl/uu/cs/ape/domain/BioToolsAPI.java b/src/main/java/nl/uu/cs/ape/domain/BioToolsAPI.java index e47954c..b0d34fd 100644 --- a/src/main/java/nl/uu/cs/ape/domain/BioToolsAPI.java +++ b/src/main/java/nl/uu/cs/ape/domain/BioToolsAPI.java @@ -2,19 +2,19 @@ import java.io.File; import java.io.IOException; -import java.util.HashSet; import java.util.List; -import java.util.Set; +import java.util.Optional; import org.apache.commons.io.FileUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import com.kitfox.svg.A; + import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; -import nl.uu.cs.ape.configuration.ToolAnnotationTag; import nl.uu.cs.ape.utils.APEFiles; import nl.uu.cs.ape.utils.APEUtils; import okhttp3.OkHttpClient; @@ -33,115 +33,142 @@ public class BioToolsAPI { private static final OkHttpClient client = new OkHttpClient(); /** - * Send Get request to get tool annotations for each elements in JSONArray from - * bio.tools API. It writes the result to a file. + * Retrieve the list of tools from the bio.tools API and convert it to the + * format used by the APE. + * The list of tools (biotoolsIDs) is read from a file, the JSON annotations are + * retrieved using bio.tools API + * and the result converted to APE annotation format and returned as a + * JSONObject. * - * @param listFilePath Path to the file with the list of tools. - * @param destinationFilePath Path to the file where the result will be written. - * @throws IOException - If the file cannot be read or written. + * @param listFile The file containing the list of biotoolsIDs as a JSON array. + * @return The JSONObject with the tool annotations in the APE format. + * @throws IOException If the file cannot be read or written. */ - public static void fetchToolSet(String listFilePath, String destinationFilePath) throws IOException { + public static JSONObject getAndConvertToolList(File listFile) throws IOException { - // Fetch the Limited (predefined) set of tool - JSONArray bioToolsRAW = readListOfTools(listFilePath); + JSONArray toolList = APEFiles.readFileToJSONArray(listFile); + List biotoolsIDs = APEUtils.getListFromJSONArray(toolList, String.class); - JSONObject apeToolAnnotation = convertBioTools2Ape(bioToolsRAW, false); - APEFiles.write2file(apeToolAnnotation.toString(4), new File(destinationFilePath), false); + return getAndConvertToolList(biotoolsIDs); } /** - * Fetch the list of all the tools from the bio.tools API and save them to a - * file in a format that can be used by the APE library. - * @param destinationFilePath The path to the file where the tool annotations will be saved. - * @throws IOException If an error occurs while fetching the tools. + * Retrieve (using GET request) the list of tool annotations from the bio.tools + * API and convert it to the + * format used by the APE. + * + * @param biotoolsIDs The list of bio.tools IDs. + * @return The JSONObject with the tool annotations in the APE format. + * @throws IOException If the file cannot be read or written. */ - public static void fetchBioTools(String destinationFilePath) throws IOException { + public static JSONObject getAndConvertToolList(List biotoolsIDs) throws IOException { + + JSONArray bioToolsRAW = getToolListFromBioTools(biotoolsIDs); + return convertBioTools2Ape(bioToolsRAW, false); - // Fetch the Limited (predefined) set of tool - JSONObject biotools = BioToolsAPI.getToolsFromEDAMTopic(""); - APEFiles.write2file(biotools.toString(4), new File(destinationFilePath), false); } /** - * Send Get request to get tool annotations for each elements in JSONArray from - * bio.tools API. It writes the result to a JSONArray. + * Fetch the list of all the tools from the bio.tools API and save them to a + * file in a format that can be used by the APE library. * - * @param filePath Path to the file with the list of tools. - * @return JSONArray with the tool annotations. - * @throws IOException - If the file cannot be read or written. + * @param destinationFilePath The path to the file where the tool annotations + * will be saved. + * @throws IOException If an error occurs while fetching the tools. */ - private static JSONArray readListOfTools(String filePath) throws IOException { + public static void getAndSaveFullBioTools(String destinationFilePath) throws IOException { - File toolList = new File(filePath); - JSONArray toolListJson = new JSONArray(FileUtils.readFileToString(toolList, "UTF-8")); - /* Fetch tool annotations */ - return fetchToolListFromBioTools(toolListJson); + // Fetch the Limited (predefined) set of tool + JSONObject biotools = BioToolsAPI.getAndConvertToolsFromEDAMTopic("", true); + APEFiles.write2file(biotools.toString(4), new File(destinationFilePath), false); } /** * Send Get request to get tool annotations for each elements in JSONArray from * bio.tools API. It writes the result to a JSONArray. * - * @param domainName Path to the file with the list of tools. + * @param domainName Path to the file with the list of tools. + * @param excludeBadAnnotation If set to {@code true}, the method will exclude + * tools that do not have both the input and the + * output fully specified, i.e., with data and + * format types and formats specified. * @return JSONArray with the tool annotations. - * @throws IOException - If the file cannot be read or written. + * @throws IOException If the file cannot be read or written. */ - private static JSONObject getToolsFromDomain(String domainName) throws IOException { + public static JSONObject getToolsFromDomain(String domainName, boolean excludeBadAnnotation) throws IOException { JSONArray toolAnnotations = null; - if (!domainName.equals("")) { - toolAnnotations = fetchToolsFromURI("https://bio.tools/api/t?domain=" + domainName + "&format=json"); - } else { + if (domainName.isEmpty()) { toolAnnotations = fetchToolsFromURI("https://bio.tools/api/t?format=json"); + } else { + toolAnnotations = fetchToolsFromURI("https://bio.tools/api/t?domain=" + domainName + "&format=json"); } - return convertBioTools2Ape(toolAnnotations, true); + return convertBioTools2Ape(toolAnnotations, excludeBadAnnotation); } /** - * Retrieve tools from the bio.tools API for a given topic and convert them to - * the tool annotation format used by the APE library. + * Send GET request to get tool annotations for the given topic from bio.tools. * - * @param topicName The name of the topic. + * @param topicName The name of the topic. + * @param excludeBadAnnotation If set to {@code true}, the method will exclude + * tools that do not have both the input and the + * output fully specified, i.e., with data and + * format types and formats specified. * @return The JSONObject containing the tool annotations in the APE format. - * * @throws IOException If an error occurs while fetching the tools. */ - public static JSONObject getToolsFromEDAMTopic(String topicName) throws IOException { + public static JSONObject getAndConvertToolsFromEDAMTopic(String topicName, boolean excludeBadAnnotation) + throws IOException { JSONArray toolAnnotations = null; - if (!topicName.equals("")) { - toolAnnotations = fetchToolsFromURI("https://bio.tools/api/t?topicID=\"" + topicName + "\"&format=json"); - } else { + if (topicName.isEmpty()) { toolAnnotations = fetchToolsFromURI("https://bio.tools/api/t?format=json"); + } else { + toolAnnotations = fetchToolsFromURI("https://bio.tools/api/t?topicID=\"" + topicName + "\"&format=json"); } - return convertBioTools2Ape(toolAnnotations, true); + return convertBioTools2Ape(toolAnnotations, excludeBadAnnotation); } /** - * Send Get request to get tool annotations Saves JSONArray with all the tool - * annotations (in tool list) + * Send GET request to get tool annotations for the given list of bio.tools IDs. + * The + * result is saved to a JSONArray. * - * @return - * @throws IOException - * @throws JSONException + * @param biotoolsIDList The list of bio.tools IDs. + * @return The JSONArray with the tool annotations as provided by bio.tools API. + * @throws IOException If an error occurs while fetching the tools. */ - public static JSONArray fetchToolListFromBioTools(JSONArray toolListJson) throws JSONException, IOException { + public static JSONArray getToolListFromBioTools(List biotoolsIDList) throws IOException { JSONArray bioToolAnnotations = new JSONArray(); - for (int i = 0; i < toolListJson.length(); i++) { - String currTool = toolListJson.getString(i); - Request request = new Request.Builder().url("https://bio.tools/api/" + currTool + "?format=json").build(); - try (Response response = client.newCall(request).execute()) { - if (!response.isSuccessful()) { - log.error("The tool " + currTool + " could not be fetched from bio.tools."); - } - // Get response body - JSONObject responseJson = new JSONObject(response.body().string()); - bioToolAnnotations.put(i, responseJson); - } + for (String biotoolsID : biotoolsIDList) { + JSONObject toolJson = fetchToolFromBioTools(biotoolsID); + bioToolAnnotations.put(toolJson); } log.debug("The list of tools successfully fetched from bio.tools."); return bioToolAnnotations; } + /** + * Send Get request to get tool annotations for a given tool from bio.tools API. + * + * @param biotoolsID The ID of the tool. + * @return The JSONObject with the tool annotations as provided by bio.tools + * API. + * @throws IOException If an error occurs while fetching the tool. + * @throws JSONException If the JSON returned by the bio.tools API is not well + * formatted. + */ + public static JSONObject fetchToolFromBioTools(String biotoolsID) throws IOException, JSONException { + + Request request = new Request.Builder().url("https://bio.tools/api/" + biotoolsID + "?format=json").build(); + try (Response response = client.newCall(request).execute()) { + if (!response.isSuccessful()) { + log.error("The tool " + biotoolsID + " could not be fetched from bio.tools."); + } + // Get response body + return new JSONObject(response.body().string()); + } + } + /** * Send Get request to get tool annotations Saves JSONArray with all the tool * annotations (in tool list) @@ -192,12 +219,20 @@ private static JSONArray fetchToolsFromURI(String url) throws JSONException, IOE * standard, and returns a {@link JSONObject} that represents tool annotations * that can be used by the APE library. * - * @param bioToolsAnnotation A {@link JSONArray} object, that contains list of - * annotated tools ({@link JSONObject}s) according the - * bio.tools specification (see bio.tools API) - * @param excludeBadAnnotation If set to {@code true}, the method will exclude tools - * that do not have both the input and the output fully specified, i.e., with data and format types and formats specified. If set to {@code false}, the method will return annotations that have at least one of the two fully specified (at least one input or or output). + * @param bioToolsAnnotation A {@link JSONArray} object, that contains list of + * annotated tools ({@link JSONObject}s) according + * the + * bio.tools specification (see bio.tools + * API) + * @param excludeBadAnnotation If set to {@code true}, the method will exclude + * tools + * that do not have both the input and the output + * fully specified, i.e., with data and format types + * and formats specified. If set to {@code false}, + * the method will return annotations that have at + * least one of the two fully specified (at least + * one input or or output). * @return {@link JSONObject} that represents the tool annotation supported by * the APE library. * @throws JSONException the json exception @@ -206,12 +241,16 @@ public static JSONObject convertBioTools2Ape(JSONArray bioToolsAnnotation, boole throws JSONException { int notAcceptedOperations = 0; - + int bioToolFunctions = 0; JSONArray apeToolsAnnotations = new JSONArray(); for (JSONObject bioJsonTool : APEUtils.getJSONListFromJSONArray(bioToolsAnnotation)) { + + String toolName = bioJsonTool.getString("name"); + String biotoolsID = bioJsonTool.getString("biotoolsID"); + List functions = APEUtils.getJSONListFromJson(bioJsonTool, "function"); if (functions.isEmpty()) { continue; @@ -219,48 +258,17 @@ public static JSONObject convertBioTools2Ape(JSONArray bioToolsAnnotation, boole int functionNo = 1; for (JSONObject function : functions) { - bioToolFunctions++; - JSONObject apeJsonTool = new JSONObject(); - apeJsonTool.put("label", bioJsonTool.getString("name")); - - apeJsonTool.put("id", - bioJsonTool.getString("biotoolsID") + - (functions.size() > 1 ? "_op" + (functionNo++) : "")); - - JSONArray apeTaxonomyTerms = new JSONArray(); - - JSONArray operations = function.getJSONArray("operation"); - for (JSONObject bioOperation : APEUtils.getJSONListFromJSONArray(operations)) { - apeTaxonomyTerms.put(bioOperation.get("uri")); - } - apeJsonTool.put("taxonomyOperations", apeTaxonomyTerms); - // reading inputs - JSONArray apeInputs = new JSONArray(); - try { - apeInputs = calculateBioToolsInputOutput(function.getJSONArray("input"), - bioJsonTool.getString("biotoolsID")); - apeJsonTool.put("inputs", apeInputs); - } catch (BioToolsAnnotationException e) { - if (excludeBadAnnotation) { - notAcceptedOperations++; - continue; - } - } - JSONArray apeOutputs = new JSONArray(); - try { - apeOutputs = calculateBioToolsInputOutput(function.getJSONArray("output"), - bioJsonTool.getString("biotoolsID")); - apeJsonTool.put("outputs", apeOutputs); - } catch (BioToolsAnnotationException e) { - if (excludeBadAnnotation) { - notAcceptedOperations++; - continue; - } - } - if (!excludeBadAnnotation || - (apeInputs.length() > 0 && apeOutputs.length() > 0)) { - apeJsonTool.put("biotoolsID", bioJsonTool.getString("biotoolsID")); - apeToolsAnnotations.put(apeJsonTool); + String toolID = biotoolsID + + (functions.size() > 1 ? "_op" + (functionNo) : ""); + + Optional apeToolJson = convertSingleBioTool2Ape(toolName, toolID, biotoolsID, function, + excludeBadAnnotation); + if (apeToolJson.isPresent()) { + apeToolsAnnotations.put(apeToolJson.get()); + bioToolFunctions++; + functionNo++; + } else { + notAcceptedOperations++; } } } @@ -272,19 +280,78 @@ public static JSONObject convertBioTools2Ape(JSONArray bioToolsAnnotation, boole return new JSONObject().put("functions", apeToolsAnnotations); } + /** + * Convert a single function from bio.tools schema to an APE tool. + * + * @param toolName The name of the tool. + * @param biotoolsID The ID of the tool. + * @param function The function (see `function` under bio.tools + * schema) in JSON format. + * @param excludeBadAnnotation If set to {@code true}, the method will exclude + * tools that do not have both the input and the + * output fully specified, i.e., with data and + * format types and formats specified. + * @return The JSONObject with the tool annotations for a single tool according + * to the APE tool annotation format. + * @throws JSONException If the JSON is not well formatted. + */ + public static Optional convertSingleBioTool2Ape(String toolName, String toolID, String biotoolsID, + JSONObject function, boolean excludeBadAnnotation) + throws JSONException { + JSONObject apeJsonTool = new JSONObject(); + apeJsonTool.put("label", toolName); + apeJsonTool.put("id", toolID); + apeJsonTool.put("biotoolsID", biotoolsID); + JSONArray apeTaxonomyTerms = new JSONArray(); + JSONArray operations = function.getJSONArray("operation"); + for (JSONObject bioOperation : APEUtils.getJSONListFromJSONArray(operations)) { + apeTaxonomyTerms.put(bioOperation.get("uri")); + } + apeJsonTool.put("taxonomyOperations", apeTaxonomyTerms); + // reading inputs + JSONArray apeInputs = new JSONArray(); + try { + apeInputs = calculateBioToolsInputOutput(function.getJSONArray("input"), + toolName); + apeJsonTool.put("inputs", apeInputs); + } catch (BioToolsAnnotationException e) { + if (excludeBadAnnotation) { + return Optional.empty(); + } + } + JSONArray apeOutputs = new JSONArray(); + try { + apeOutputs = calculateBioToolsInputOutput(function.getJSONArray("output"), + toolName); + apeJsonTool.put("outputs", apeOutputs); + } catch (BioToolsAnnotationException e) { + if (excludeBadAnnotation) { + return Optional.empty(); + } + } + if (!excludeBadAnnotation || + (apeInputs.length() > 0 && apeOutputs.length() > 0)) { + return Optional.of(apeJsonTool); + } + return Optional.empty(); + } - /** - * Method converts input and output tool annotations, following bio.tools schema, + * Method converts input and output tool annotations, following bio.tools + * schema, * into the APE library tool annotation format. - * @param bioInputs - JSONArray with the bio.tools input/output annotations. - * @param toolID - ID of the tool that is being converted. + * + * @param bioInputs JSONArray with the bio.tools input/output annotations. + * @param toolID ID of the tool that is being converted. * * @return JSONArray with the APE library input/output annotations. + * @throws BioToolsAnnotationException If the input/output annotations are not + * well defined. */ - private static JSONArray calculateBioToolsInputOutput(JSONArray bioInputs, String toolID) { + private static JSONArray calculateBioToolsInputOutput(JSONArray bioInputs, String toolID) + throws BioToolsAnnotationException { JSONArray apeInputs = new JSONArray(); for (JSONObject bioInput : APEUtils.getJSONListFromJSONArray(bioInputs)) { JSONObject apeInput = new JSONObject(); diff --git a/src/test/java/nl/uu/cs/ape/test/sat/ape/BioToolsAPITest.java b/src/test/java/nl/uu/cs/ape/test/sat/ape/BioToolsAPITest.java new file mode 100644 index 0000000..2cdc37b --- /dev/null +++ b/src/test/java/nl/uu/cs/ape/test/sat/ape/BioToolsAPITest.java @@ -0,0 +1,86 @@ +package nl.uu.cs.ape.test.sat.ape; + +import nl.uu.cs.ape.domain.BioToolsAPI; + +import org.json.JSONArray; +import org.json.JSONObject; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +class BioToolsAPITest { + + private static File testFile; + + @BeforeAll + static void setup() throws IOException { + // Create a temporary file with some sample tool IDs for testing. + testFile = File.createTempFile("testToolList", ".json"); + testFile.deleteOnExit(); + JSONArray sampleToolIDs = new JSONArray(); + sampleToolIDs.put("comet"); + sampleToolIDs.put("sage"); + sampleToolIDs.put("proteinprophet"); + + Files.writeString(Path.of(testFile.getAbsolutePath()), sampleToolIDs.toString(4)); + } + + @Test + void testGetAndConvertToolListFromFile() throws IOException { + // Call the method and get the result + JSONObject result = BioToolsAPI.getAndConvertToolList(testFile); + + // Assert the result is not null and check the number of tools + assertNotNull(result, "The result should not be null"); + assertEquals(3, result.getJSONArray("functions").length(), + "The number of functions should match the input size"); + + System.out.println("Response: " + result.toString(4)); + } + + @Test + void testGetAndConvertToolListFromList() throws IOException { + // Create a list of tool IDs + List toolIDs = List.of("comet"); + + // Call the method and get the result + JSONObject result = BioToolsAPI.getAndConvertToolList(toolIDs); + + // Assert the result is not null and check the number of tools + assertNotNull(result, "The result should not be null"); + assertEquals(1, result.getJSONArray("functions").length(), + "The number of functions should match the input size"); + + // Check the content of the retrieved tool annotation + JSONObject comet = result.getJSONArray("functions").getJSONObject(0); + assertEquals("comet", comet.getString("biotoolsID"), "The biotoolsID should match the input"); + assumeTrue(comet.getJSONArray("inputs").length() > 0, "The tool should have at least one input"); + assumeTrue(comet.getJSONArray("outputs").length() > 0, "The tool should have at least one output"); + assumeTrue(comet.getJSONArray("taxonomyOperations").length() > 0, "The tool should have at least one taxonomyOperation"); + + + System.out.println("Response: " + result.toString(4)); + } + + @Test + void testGetToolsFromDomain() throws IOException { + String domainName = "proteomics"; + JSONObject result = BioToolsAPI.getToolsFromDomain(domainName, false); + + // Check that the result is not null and contains some tools + assertNotNull(result, "The result should not be null"); + assertTrue(result.getJSONArray("functions").length() > 700, "There should be some functions in the result"); + } + +} \ No newline at end of file diff --git a/src/test/java/nl/uu/cs/ape/test/sat/ape/CLITest.java b/src/test/java/nl/uu/cs/ape/test/sat/ape/CLITest.java index 5a748a9..f09ca33 100644 --- a/src/test/java/nl/uu/cs/ape/test/sat/ape/CLITest.java +++ b/src/test/java/nl/uu/cs/ape/test/sat/ape/CLITest.java @@ -19,10 +19,10 @@ import java.util.Objects; -public class CLITest { +class CLITest { @Test - public void GMTFromCLITest() throws IOException { + void GMTFromCLITest() throws IOException { run( "cli/gmt/base_config.json", "cli/gmt/GMT_UseCase_taxonomy.owl", @@ -34,7 +34,7 @@ public void GMTFromCLITest() throws IOException { // add files to 'src/test/resources/' folder and add the relative paths here //@Test - public void templateTest() throws IOException { + void templateTest() throws IOException { run( "relative/path/base_config.json", "relative/path/ontology.owl", @@ -44,7 +44,7 @@ public void templateTest() throws IOException { ); } - public void run(String base_config_path, String ontology_path, String tools_path, String constraints_path, String solution_dir_path) throws IOException { + void run(String base_config_path, String ontology_path, String tools_path, String constraints_path, String solution_dir_path) throws IOException { // absolute solution_dir_path final Path solution_path = Paths.get(Objects.requireNonNull(TestResources.getAbsoluteResourcePath(solution_dir_path))); From e43ee05047ae325958243e8d5bd804661de9cdab Mon Sep 17 00:00:00 2001 From: Vedran Kasalica Date: Wed, 2 Oct 2024 02:09:41 +0200 Subject: [PATCH 10/13] Make documentation consistent --- .../uu/cs/ape/automaton/ModuleAutomaton.java | 2 +- .../nl/uu/cs/ape/automaton/TypeAutomaton.java | 4 +- .../ape/configuration/APEConfigException.java | 2 +- .../cs/ape/configuration/APECoreConfig.java | 6 +- .../ConstraintFormatException.java | 12 +- .../ConstraintTemplateParameter.java | 2 +- .../cs/ape/domain/APEDimensionsException.java | 6 +- .../nl/uu/cs/ape/domain/APEDomainSetup.java | 8 +- .../domain/BioToolsAnnotationException.java | 4 +- .../nl/uu/cs/ape/models/AllPredicates.java | 8 +- .../java/nl/uu/cs/ape/models/AllTypes.java | 2 +- .../uu/cs/ape/models/AuxModulePredicate.java | 14 +- .../uu/cs/ape/models/MappingsException.java | 4 +- src/main/java/nl/uu/cs/ape/models/Type.java | 10 +- .../logic/constructs/TaxonomyPredicate.java | 2 +- .../cs/ape/models/sltlxStruc/CNFClause.java | 10 +- .../ape/models/sltlxStruc/SLTLxAtomVar.java | 16 +- .../cs/ape/models/sltlxStruc/SLTLxElem.java | 4 +- .../ape/models/sltlxStruc/SLTLxFormula.java | 10 +- .../ape/models/sltlxStruc/SLTLxOperation.java | 4 +- .../SLTLxParsingAnnotationException.java | 6 +- .../sltlxStruc/SLTLxVarQuantification.java | 6 +- .../ape/models/sltlxStruc/SLTLxVariable.java | 36 ++-- .../SLTLxVariableOccurrenceCollection.java | 22 +- .../SLTLxVariableSubstitutionCollection.java | 12 +- .../SLTLxTemplateFormula.java | 194 +++++++++--------- .../cs/ape/parserSLTLx/SLTLxSATVisitor.java | 8 +- .../java/nl/uu/cs/ape/solver/ModuleUtils.java | 10 +- .../minisat/EnforceModuleRelatedRules.java | 18 +- .../minisat/EnforceTypeRelatedRules.java | 22 +- .../solver/minisat/SATSynthesisEngine.java | 4 +- .../solver/solutionStructure/ModuleNode.java | 4 +- .../solutionStructure/SolutionsList.java | 12 +- .../java/nl/uu/cs/ape/utils/APEFiles.java | 26 +-- .../java/nl/uu/cs/ape/utils/APEUtils.java | 67 ++++-- 35 files changed, 302 insertions(+), 275 deletions(-) diff --git a/src/main/java/nl/uu/cs/ape/automaton/ModuleAutomaton.java b/src/main/java/nl/uu/cs/ape/automaton/ModuleAutomaton.java index 80ef5ea..82ef974 100644 --- a/src/main/java/nl/uu/cs/ape/automaton/ModuleAutomaton.java +++ b/src/main/java/nl/uu/cs/ape/automaton/ModuleAutomaton.java @@ -95,7 +95,7 @@ public List getAllStates() { * Gets state object which corresponds to the type and order number (w.r.t. the * type) of the state. * - * @param typeDependantStateNumber - order number of the state within the type + * @param typeDependantStateNumber order number of the state within the type * @return State no {@code typeDependantStateNumber} of the type * {@code usedTypeState} */ diff --git a/src/main/java/nl/uu/cs/ape/automaton/TypeAutomaton.java b/src/main/java/nl/uu/cs/ape/automaton/TypeAutomaton.java index 75978a1..642badf 100644 --- a/src/main/java/nl/uu/cs/ape/automaton/TypeAutomaton.java +++ b/src/main/java/nl/uu/cs/ape/automaton/TypeAutomaton.java @@ -193,7 +193,7 @@ public Block getLastToolOutputBlock() { * Get from the automaton all the @i-th Type Block that contain types used by * tools. * - * @param i - ordering number of the used type block to be returned. + * @param i Specifies number of the used type block to be returned. * (inputs to the first tool are in the block 0, and n-th block * contains the workflow output of the workflow of length n) * @return Block of Type states that are used by tools. @@ -206,7 +206,7 @@ public Block getUsedTypesBlock(int i) { * Get from the automaton all the {@code i}-th Type Block that contain types * added to the memory. * - * @param i - ordering number of the memory type block to be returned + * @param i Specifies number of the memory type block to be returned * (original workflow inputs are in the block 0, and n-th block * contains the outputs of the last tool in the workflow of length n) * @return lock of Type states that are added to the memory. diff --git a/src/main/java/nl/uu/cs/ape/configuration/APEConfigException.java b/src/main/java/nl/uu/cs/ape/configuration/APEConfigException.java index b79fd24..813b173 100644 --- a/src/main/java/nl/uu/cs/ape/configuration/APEConfigException.java +++ b/src/main/java/nl/uu/cs/ape/configuration/APEConfigException.java @@ -168,7 +168,7 @@ public static APEConfigException ruleViolations(ValidationResults validationResu * The annotated type (workflow input or output) is not defined within the * domain taxonomy. * - * @param typeID - ID of the data type not defined + * @param typeID ID of the data type not defined * @return Run configuration exception with information that may help the user * solve the problem. */ diff --git a/src/main/java/nl/uu/cs/ape/configuration/APECoreConfig.java b/src/main/java/nl/uu/cs/ape/configuration/APECoreConfig.java index d6f4446..3c9f75e 100644 --- a/src/main/java/nl/uu/cs/ape/configuration/APECoreConfig.java +++ b/src/main/java/nl/uu/cs/ape/configuration/APECoreConfig.java @@ -225,7 +225,7 @@ public static ValidationResults validate(JSONObject json) { * and data terms. Validation will simply check the format of the ontology and * the existence of the mentioned classes. * - * @param ontologyFile - ontology file + * @param ontologyFile ontology file * @param ontologyPrefixIRI Prefix used to define OWL class IDs * @param toolTaxonomyRoot Node in the ontology that corresponds to the root * of the module taxonomy. @@ -259,7 +259,7 @@ public File getOntologyFile() { /** * Set ontology annotation. * - * @param ontology - ontology file + * @param ontology ontology file */ public void setOntologyFile(File ontology) { ONTOLOGY.setValue(ontology); @@ -304,7 +304,7 @@ public File getToolAnnotationsFile() { /** * Set tool annotations. * - * @param toolAnnotations - tool annotations file + * @param toolAnnotations tool annotations file * */ public void setToolAnnotationsFile(File toolAnnotations) { diff --git a/src/main/java/nl/uu/cs/ape/constraints/ConstraintFormatException.java b/src/main/java/nl/uu/cs/ape/constraints/ConstraintFormatException.java index efe30aa..bff4f16 100644 --- a/src/main/java/nl/uu/cs/ape/constraints/ConstraintFormatException.java +++ b/src/main/java/nl/uu/cs/ape/constraints/ConstraintFormatException.java @@ -22,7 +22,7 @@ private ConstraintFormatException(String message) { /** * Exception is thrown when a constraint is given wrong number of arguments. * - * @param message - Application specific message that may help the user solve + * @param message Application specific message that may help the user solve * the problem. * @return Constraint exception with information that may help the user solve * the problem. @@ -36,7 +36,7 @@ public static ConstraintFormatException wrongNumberOfParameters(String message) /** * Exception is thrown when a constraint is given wrong number of arguments. * - * @param message - Application specific message that may help the user solve + * @param message Application specific message that may help the user solve * the problem. * @return Constraint exception with information that may help the user solve * the problem. @@ -48,7 +48,7 @@ public static ConstraintFormatException badFormat(String message) { /** * Exception is thrown when a constraint is given wrong number of arguments. * - * @param message - Application specific message that may help the user solve + * @param message Application specific message that may help the user solve * the problem. * @return Constraint exception with information that may help the user solve * the problem. @@ -61,7 +61,7 @@ public static ConstraintFormatException wrongConstraintID(String message) { /** * Exception is thrown when a constraint is given wrong number of arguments. * - * @param message - Application specific message that may help the user solve + * @param message Application specific message that may help the user solve * the problem. * @return Constraint exception with information that may help the user solve * the problem. @@ -74,7 +74,7 @@ public static ConstraintFormatException wrongParameter(String message) { /** * Exception is thrown when a constraint is given wrong number of arguments. * - * @param message - Application specific message that may help the user solve + * @param message Application specific message that may help the user solve * the problem. * @return Constraint exception with information that may help the user solve * the problem. @@ -88,7 +88,7 @@ public static ConstraintFormatException wrongSLTLxOperation(String message) { /** * Exception is thrown when a constraint is given wrong number of arguments. * - * @param message - Application specific message that may help the user solve + * @param message Application specific message that may help the user solve * the problem. * @return Constraint exception with information that may help the user solve * the problem. diff --git a/src/main/java/nl/uu/cs/ape/constraints/ConstraintTemplateParameter.java b/src/main/java/nl/uu/cs/ape/constraints/ConstraintTemplateParameter.java index 604d039..2034ee4 100644 --- a/src/main/java/nl/uu/cs/ape/constraints/ConstraintTemplateParameter.java +++ b/src/main/java/nl/uu/cs/ape/constraints/ConstraintTemplateParameter.java @@ -101,7 +101,7 @@ public JSONObject toJSON() { * generate a Type or Module object. * * @param jsonParam json object - * @param domainSetup - domain model + * @param domainSetup domain model * @return A {@link Type} or {@link AbstractModule} object that represent the * data instance given as the parameter. * @throws JSONException if the given JSON is not well formatted diff --git a/src/main/java/nl/uu/cs/ape/domain/APEDimensionsException.java b/src/main/java/nl/uu/cs/ape/domain/APEDimensionsException.java index 673d6b0..fb23431 100644 --- a/src/main/java/nl/uu/cs/ape/domain/APEDimensionsException.java +++ b/src/main/java/nl/uu/cs/ape/domain/APEDimensionsException.java @@ -26,7 +26,7 @@ private APEDimensionsException(String message) { * Exception is thrown when the dimensions described in the OWL file have * overlaps. * - * @param message - Application specific message that may help the user solve + * @param message Application specific message that may help the user solve * the problem. * @return Dimensions exception with information that may help the user solve * the problem. @@ -38,7 +38,7 @@ public static APEDimensionsException dimensionsOverlap(String message) { /** * Exception is thrown when a dimension expected does not exist. * - * @param message - Application specific message that may help the user solve + * @param message Application specific message that may help the user solve * the problem. * @return Dimensions exception with information that may help the user solve * the problem. @@ -50,7 +50,7 @@ public static APEDimensionsException notExistingDimension(String message) { /** * Exception is thrown when a dimension does not contain the specified subclass. * - * @param message - Application specific message that may help the user solve + * @param message Application specific message that may help the user solve * the problem. * @return Dimensions exception with information that may help the user solve * the problem. diff --git a/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java b/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java index 431ea59..f01b704 100644 --- a/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java +++ b/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java @@ -132,7 +132,7 @@ public void addConstraintData(ConstraintTemplateData constr) { * Add the String that corresponds to an SLTLx formula that should be parsed to * the list of constraints. * - * @param formulaSLTLx - String that corresponds to an SLTLx formula that should + * @param formulaSLTLx String that corresponds to an SLTLx formula that should * be parsed */ public void addSLTLxConstraint(String formulaSLTLx) { @@ -565,9 +565,9 @@ public List getHelperPredicates() { /** * Write locally the SAT (CNF) workflow specification in human readable format. * - * @param satInputFile - File containing the SAT problem specification. - * @param mappings - Mappings between the SAT problem and the domain. - * @throws IOException - Error in writing the file to the local file system. + * @param satInputFile File containing the SAT problem specification. + * @param mappings Mappings between the SAT problem and the domain. + * @throws IOException Error in writing the file to the local file system. */ public void localCNF(File satInputFile, SATAtomMappings mappings) throws IOException { if (writeLocalCNF != null) { diff --git a/src/main/java/nl/uu/cs/ape/domain/BioToolsAnnotationException.java b/src/main/java/nl/uu/cs/ape/domain/BioToolsAnnotationException.java index 7664ed5..d11a0a1 100644 --- a/src/main/java/nl/uu/cs/ape/domain/BioToolsAnnotationException.java +++ b/src/main/java/nl/uu/cs/ape/domain/BioToolsAnnotationException.java @@ -24,7 +24,7 @@ private BioToolsAnnotationException(String message) { /** * Exception is thrown when a tool that does not have a data type of data specified in the bio.tools annotations. - * @param toolID - ID of the tool that does not have the data type specified. + * @param toolID ID of the tool that does not have the data type specified. * @return BioToolsAnnotationException with information that may help the user solve the problem. */ public static BioToolsAnnotationException notExistingType(String toolID) { @@ -33,7 +33,7 @@ public static BioToolsAnnotationException notExistingType(String toolID) { /** * Exception is thrown when a tool that does not have a data format of data specified in the bio.tools annotations. - * @param toolID - ID of the tool that does not have the format specified. + * @param toolID ID of the tool that does not have the format specified. * @return BioToolsAnnotationException with information that may help the user solve the problem. */ public static BioToolsAnnotationException notExistingFormat(String toolID) { diff --git a/src/main/java/nl/uu/cs/ape/models/AllPredicates.java b/src/main/java/nl/uu/cs/ape/models/AllPredicates.java index 365a02f..324789c 100644 --- a/src/main/java/nl/uu/cs/ape/models/AllPredicates.java +++ b/src/main/java/nl/uu/cs/ape/models/AllPredicates.java @@ -171,7 +171,7 @@ public SortedSet getElementsFromSubTaxonomy(TaxonomyPredicate /** * Check whether the string occurs as one of the roots in the taxonomy. * - * @param curRootIRI - curr root IRI + * @param curRootIRI curr root IRI * @return true if the root exists */ public boolean existsRoot(String curRootIRI) { @@ -181,8 +181,8 @@ public boolean existsRoot(String curRootIRI) { /** * Put a new TaxonomyPredicate to the mapping. * - * @param key - ID of the TaxonomyPredicate - * @param value - TaxonomyPredicate to be added + * @param key ID of the TaxonomyPredicate + * @param value TaxonomyPredicate to be added */ public void put(String key, TaxonomyPredicate value) { mappedPredicates.put(key, value); @@ -192,7 +192,7 @@ public void put(String key, TaxonomyPredicate value) { /** * Remove the TaxonomyPredicate from the mapping. * - * @param predicateID - ID of the TaxonomyPredicate to be removed + * @param predicateID ID of the TaxonomyPredicate to be removed */ public void remove(String predicateID) { mappedPredicates.remove(predicateID); diff --git a/src/main/java/nl/uu/cs/ape/models/AllTypes.java b/src/main/java/nl/uu/cs/ape/models/AllTypes.java index b2a56a5..3c05509 100644 --- a/src/main/java/nl/uu/cs/ape/models/AllTypes.java +++ b/src/main/java/nl/uu/cs/ape/models/AllTypes.java @@ -81,7 +81,7 @@ public AllTypes(List typeTaxonomyRoots) { /** * Helper method that sets the type to be relevant in the current domain * - * @param type - Type that should be relevant + * @param type Type that should be relevant */ private void setRelevant(Type type) { type.setAsRelevantTaxonomyTerm(this); diff --git a/src/main/java/nl/uu/cs/ape/models/AuxModulePredicate.java b/src/main/java/nl/uu/cs/ape/models/AuxModulePredicate.java index 29d404a..e4f5e07 100644 --- a/src/main/java/nl/uu/cs/ape/models/AuxModulePredicate.java +++ b/src/main/java/nl/uu/cs/ape/models/AuxModulePredicate.java @@ -37,19 +37,19 @@ public class AuxModulePredicate extends AbstractModule implements AuxiliaryPredi * {@link AuxModulePredicate#generateAuxiliaryPredicate} to generate an * auxiliary object. * - * @param moduleName - name of the auxiliary module predicate - * @param moduleID - ID of the auxiliary module predicate - * @param rootNode - module root node - * @param containingPredicates - collection of module predicates that comprise + * @param moduleName name of the auxiliary module predicate + * @param moduleID ID of the auxiliary module predicate + * @param rootNode module root node + * @param containingPredicates collection of module predicates that comprise * the auxiliary predicate - * @param logicOp - logical operation that binds the comprised + * @param logicOp logical operation that binds the comprised * predicates */ private AuxModulePredicate(String moduleName, String moduleID, String rootNode, Collection containingPredicates, LogicOperation logicOp) { super(moduleName, moduleID, rootNode, NodeType.ABSTRACT); this.logicOp = logicOp; - this.containingPredicates = new TreeSet(); + this.containingPredicates = new TreeSet<>(); this.containingPredicates.addAll(containingPredicates); } @@ -68,7 +68,7 @@ private AuxModulePredicate(String moduleName, String moduleID, String rootNode, * always the same due to its ordering). * @param logicOp Logical operation that describes the relation * between the types. - * @param domainSetup - domain model + * @param domainSetup domain model * * @return An abstract predicate that provides abstraction over a * disjunction/conjunction of the labels. diff --git a/src/main/java/nl/uu/cs/ape/models/MappingsException.java b/src/main/java/nl/uu/cs/ape/models/MappingsException.java index 79687cf..a48a39f 100644 --- a/src/main/java/nl/uu/cs/ape/models/MappingsException.java +++ b/src/main/java/nl/uu/cs/ape/models/MappingsException.java @@ -26,7 +26,7 @@ public MappingsException(String message) { * Exception is thrown when two or more atoms share the same signature (ID + * state) * - * @param message - Application specific message that may help the user solve + * @param message Application specific message that may help the user solve * the problem. * @return Dimensions exception with information that may help the user solve * the problem. @@ -39,7 +39,7 @@ public static MappingsException mappedAtomsSignaturesOverlap(String message) { /** * Exception is thrown when two or more predicates share the same signature. * - * @param message - Application specific message that may help the user solve + * @param message Application specific message that may help the user solve * the problem. * @return Dimensions exception with information that may help the user solve * the problem. diff --git a/src/main/java/nl/uu/cs/ape/models/Type.java b/src/main/java/nl/uu/cs/ape/models/Type.java index aec6cac..5705418 100644 --- a/src/main/java/nl/uu/cs/ape/models/Type.java +++ b/src/main/java/nl/uu/cs/ape/models/Type.java @@ -65,9 +65,9 @@ public String getType() { } /** - * Set plain type type. + * Set plain type. * - * @param plainType - plain type that should be used + * @param plainType The plain type value. */ public void setPlainType(Type plainType) { this.plainType = plainType; @@ -88,9 +88,9 @@ public Type getPlainType() { * Generate a taxonomy data instance that is defined based on one or more * dimensions that describe it. * - * @param jsonParam - JSON representation of the data instance - * @param domainSetup - setup of the domain - * @param isOutputData - {@code true} if the data is used to be module output, + * @param jsonParam JSON representation of the data instance + * @param domainSetup setup of the domain + * @param isOutputData {@code true} if the data is used to be module output, * {@code false} otherwise * @return A type object that represent the data instance given as the * parameter. diff --git a/src/main/java/nl/uu/cs/ape/models/logic/constructs/TaxonomyPredicate.java b/src/main/java/nl/uu/cs/ape/models/logic/constructs/TaxonomyPredicate.java index 6c7f6ef..129f918 100644 --- a/src/main/java/nl/uu/cs/ape/models/logic/constructs/TaxonomyPredicate.java +++ b/src/main/java/nl/uu/cs/ape/models/logic/constructs/TaxonomyPredicate.java @@ -397,7 +397,7 @@ public Set getParentPredicates() { * Returns true if the type is a simple/leaf type, otherwise returns false - the * type is an abstract (non-leaf) type. * - * @param nodeType - node type + * @param nodeType NodeType that is checked against the current node. * * @return true (simple/primitive/leaf type) or false (abstract/non-leaf type). */ diff --git a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/CNFClause.java b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/CNFClause.java index a76aaec..76c14b9 100644 --- a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/CNFClause.java +++ b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/CNFClause.java @@ -32,7 +32,7 @@ public CNFClause(List atoms) { /** * Create a clause that has only one element. * - * @param atom - integer that corresponds to the mapping of the atom + * @param atom integer that corresponds to the mapping of the atom */ public CNFClause(Integer atom) { super(); @@ -45,7 +45,7 @@ public CNFClause(Integer atom) { * collections of {@link CNFClause}s and combine them under the AND logic * operator. * - * @param facts - collections of 'collections of clauses' that are conjunct + * @param facts collections of 'collections of clauses' that are conjunct * @return Set of {@link CNFClause}s that represent conjunction of the given * collections of clauses. */ @@ -61,7 +61,7 @@ public static Set conjunctClausesCollection(Set> facts) { * collections of {@link CNFClause}s and combine them under the OR logic * operator. * - * @param facts - collections of 'collections of clauses' that are disjoint. + * @param facts collections of 'collections of clauses' that are disjoint. * @return Set of {@link CNFClause}s that represent disjunction of the given * collections of clauses. */ @@ -96,8 +96,8 @@ public static Set disjoinClausesCollection(Set> facts) { * Return a new clause that combines the two clauses. The method combines the 2 * strings, each comprising disjoint Atoms. * - * @param clause1 - 1st clause that should be combined - * @param clause2 - 2nd clause that should be combined + * @param clause1 1st clause that should be combined + * @param clause2 2nd clause that should be combined * @return String that represents the disjunction of the two clauses. */ public static String disjoin2Clauses(String clause1, String clause2) { diff --git a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxAtomVar.java b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxAtomVar.java index 0353148..f36a03e 100644 --- a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxAtomVar.java +++ b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxAtomVar.java @@ -45,9 +45,9 @@ public class SLTLxAtomVar extends SLTLxFormula { * or a reference between an input type and the state in which it was * generated.. * - * @param elementType - Element that defines what the atom depicts. - * @param firstArg - Predicate used or a variable that is the referenced. - * @param secondArg - Variable representing state in the automaton it was + * @param elementType Element that defines what the atom depicts. + * @param firstArg Predicate used or a variable that is the referenced. + * @param secondArg Variable representing state in the automaton it was * used/created in. */ public SLTLxAtomVar(AtomVarType elementType, PredicateLabel firstArg, SLTLxVariable secondArg) { @@ -200,23 +200,23 @@ public Set getNegatedCNFEncoding(int stateNo, SLTLxVariableSubstitutionC private void substituteVariables(SLTLxVariableSubstitutionCollection variableMapping, SATSynthesisEngine synthesisEngine) { if (this.elementType.isVarDataType()) { - this.secondArg = variableMapping.getVarSabstitute(this.secondArg); + this.secondArg = variableMapping.getVarSubstitute(this.secondArg); synthesisEngine.getVariableUsage().addDataType(firstArg, secondArg); } else if (this.elementType.isVarMemReference()) { - this.secondArg = variableMapping.getVarSabstitute(this.secondArg); + this.secondArg = variableMapping.getVarSubstitute(this.secondArg); synthesisEngine.getVariableUsage().addMemoryReference((State) firstArg, secondArg); } else if (this.elementType.isBinaryRel() && !(this.elementType.equals(AtomVarType.VAR_VALUE))) { - this.firstArg = variableMapping.getVarSabstitute((SLTLxVariable) this.firstArg); - this.secondArg = variableMapping.getVarSabstitute(this.secondArg); + this.firstArg = variableMapping.getVarSubstitute((SLTLxVariable) this.firstArg); + this.secondArg = variableMapping.getVarSubstitute(this.secondArg); synthesisEngine.getVariableUsage().addBinaryPred( new Pair<>((SLTLxVariable) this.firstArg, this.secondArg), this.elementType); } else if (this.elementType.equals(AtomVarType.VAR_VALUE)) { - this.secondArg = variableMapping.getVarSabstitute(this.secondArg); + this.secondArg = variableMapping.getVarSubstitute(this.secondArg); /* These predicates are not added to the set. */ } } diff --git a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxElem.java b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxElem.java index b219dd9..f4bd4a9 100644 --- a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxElem.java +++ b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxElem.java @@ -16,7 +16,7 @@ public interface SLTLxElem { * Create the CNF encoding of the statement and return the string * representation. * - * @param synthesisEngine - synthesis engine used to encode the problem. + * @param synthesisEngine synthesis engine used to encode the problem. * @return The string that represent cnf clauses. */ public Set getCNFEncoding(int stateNo, SLTLxVariableSubstitutionCollection variableMapping, @@ -26,7 +26,7 @@ public Set getCNFEncoding(int stateNo, SLTLxVariableSubstitutionCollecti * CreatE the CNF encoding of the negation of the statement and return the * string representation. * - * @param synthesisEngine - synthesis engine used to encode the problem. + * @param synthesisEngine synthesis engine used to encode the problem. * @return The string that represent the negated cnf clauses. */ public Set getNegatedCNFEncoding(int stateNo, SLTLxVariableSubstitutionCollection variableMapping, diff --git a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxFormula.java b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxFormula.java index 27532a9..3c9b5d5 100644 --- a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxFormula.java +++ b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxFormula.java @@ -24,16 +24,16 @@ protected SLTLxFormula() { * Encode a collection of SLTLx formulas to CNF and append it to the existing * CNF file. It adds the encoding at the end of the content of the file. * - * @param file - existing cnf file + * @param file existing cnf file * @param synthesisEngine synthesis engine used for encoding - * @param formulas - collection of formulas that should be encoded + * @param formulas collection of formulas that should be encoded * @throws IOException Thrown in case of an I/O error. */ public static void appendCNFToFile(File file, SATSynthesisEngine synthesisEngine, Collection formulas) throws IOException { StringBuilder cnf = new StringBuilder(); createCNFEncoding(formulas, 0, synthesisEngine) - .forEach(clause -> cnf.append(clause)); + .forEach(cnf::append); APEFiles.appendToFile(file, cnf.toString()); } @@ -41,8 +41,8 @@ public static void appendCNFToFile(File file, SATSynthesisEngine synthesisEngine * Create the CNF encoding of the facts and return the set of corresponding * clauses in String format. * - * @param facts - all facts that should be encoded - * @param synthesisEngine - synthesis engine used for encoding + * @param facts all facts that should be encoded + * @param synthesisEngine synthesis engine used for encoding * @return Set of clauses in String format that encode the given collector of * formulas. */ diff --git a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxOperation.java b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxOperation.java index 5c95d93..0ff41a5 100644 --- a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxOperation.java +++ b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxOperation.java @@ -53,8 +53,8 @@ public Set getNegatedCNFEncoding(int stateNo, SLTLxVariableSubstitutionC * Create the SLTLx object that enforces usage of the operation and the * corresponding inputs/outputs. * - * @param stateNo - current state number - * @param synthesisEngine - synthesis engine + * @param stateNo current state number + * @param synthesisEngine synthesis engine * @return Fact representing the existence of the operation. */ private SLTLxFormula enforceOperation(int stateNo, SATSynthesisEngine synthesisEngine) { diff --git a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxParsingAnnotationException.java b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxParsingAnnotationException.java index 527debd..fff7f49 100644 --- a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxParsingAnnotationException.java +++ b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxParsingAnnotationException.java @@ -24,7 +24,7 @@ private SLTLxParsingAnnotationException(String message) { * Exception is thrown when the specified SLTLx formula contains a type not * specified in the type taxonomy. * - * @param message - Application specific message that may help the user solve + * @param message Application specific message that may help the user solve * the problem. * @return SLTLx Parsing exception with information that may help the user solve * the problem. @@ -39,7 +39,7 @@ public static SLTLxParsingAnnotationException typeDoesNoExists(String message) { * Exception is thrown when the specified SLTLx formula contains a module not * specified in the type taxonomy. * - * @param message - Application specific message that may help the user solve + * @param message Application specific message that may help the user solve * the problem. * @return SLTLx Parsing exception with information that may help the user solve * the problem. @@ -54,7 +54,7 @@ public static SLTLxParsingAnnotationException moduleDoesNoExists(String message) * Exception is thrown when the specified SLTLx formula contains a free * variable. * - * @param message - Application specific message that may help the user solve + * @param message Application specific message that may help the user solve * the problem. * @return SLTLx Parsing exception with information that may help the user solve * the problem. diff --git a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVarQuantification.java b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVarQuantification.java index 0fcd677..f20ee6b 100644 --- a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVarQuantification.java +++ b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVarQuantification.java @@ -25,8 +25,8 @@ protected SLTLxVarQuantification(SLTLxVariable boundVariable, SLTLxFormula formu @Override public Set getCNFEncoding(int stateNo, SLTLxVariableSubstitutionCollection newVarMapping, SATSynthesisEngine synthesisEngine) { - Set clauses = new HashSet(); - SLTLxVariable flatBoundVariable = newVarMapping.getVarSabstitute(boundVariable); + Set clauses = new HashSet<>(); + SLTLxVariable flatBoundVariable = newVarMapping.getVarSubstitute(boundVariable); /** Encode the underlying formula. */ clauses.addAll(formula.getCNFEncoding(stateNo, newVarMapping, synthesisEngine)); /** @@ -45,7 +45,7 @@ public Set getCNFEncoding(int stateNo, SLTLxVariableSubstitutionCollecti public Set getNegatedCNFEncoding(int stateNo, SLTLxVariableSubstitutionCollection newVarMapping, SATSynthesisEngine synthesisEngine) { Set clauses = new HashSet<>(); - SLTLxVariable flatBoundVariable = newVarMapping.getVarSabstitute(boundVariable); + SLTLxVariable flatBoundVariable = newVarMapping.getVarSubstitute(boundVariable); /** Encode the underlying formula. */ clauses.addAll(formula.getNegatedCNFEncoding(stateNo, newVarMapping, synthesisEngine)); /** diff --git a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVariable.java b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVariable.java index e325545..acb2fd9 100644 --- a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVariable.java +++ b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVariable.java @@ -31,7 +31,7 @@ public class SLTLxVariable implements StateInterface, PredicateLabel { /** * Create new type state variable. * - * @param variableName - Unique variable name + * @param variableName Unique variable name */ public SLTLxVariable(String variableName) { super(); @@ -94,8 +94,8 @@ public String getPredicateLongLabel() { * existential * quantification for the given set of memory states. * - * @param stateNo - current state in the SLTLx model - * @param synthesisEngine - synthesis engine + * @param stateNo current state in the SLTLx model + * @param synthesisEngine synthesis engine * @return Set of clauses that encode the possible variable substitution. */ public Set getExistentialCNFEncoding(int stateNo, SLTLxVariableSubstitutionCollection variableSubstitutions, @@ -126,8 +126,8 @@ public Set getExistentialCNFEncoding(int stateNo, SLTLxVariableSubstitut * in order to ensure that all occurrences of the variable were taken into * account. * - * @param stateNo - current state in the SLTLx model - * @param synthesisEngine - synthesis engine + * @param stateNo current state in the SLTLx model + * @param synthesisEngine synthesis engine * @return Set of clauses that encode the possible variable substitution. */ public Set getUniversalCNFEncoding(int stateNo, SLTLxVariableSubstitutionCollection variableSubstitutions, @@ -158,8 +158,8 @@ public Set getUniversalCNFEncoding(int stateNo, SLTLxVariableSubstitutio * in order to ensure that all the occurrences of the variable were taken into * account. * - * @param stateNo - current state in the SLTLx model - * @param synthesisEngine - synthesis engine + * @param stateNo current state in the SLTLx model + * @param synthesisEngine synthesis engine * @return Set of clauses that encode the possible variable substitution. */ public Set getVariableSubstitutionToPreserveProperties(int stateNo, @@ -191,9 +191,9 @@ public Set getVariableSubstitutionToPreserveProperties(int stateNo, * Generate the rules that enforce substitution over the data properties.
* e.g., (VAL(?x,a) => (P(?x) <=> P(a)) * - * @param variable - the variable that will be substituted - * @param variableSubstitutions - collection of substitutions for each variable - * @param varOccurrences - collection that tracks occurrences of + * @param variable the variable that will be substituted + * @param variableSubstitutions collection of substitutions for each variable + * @param varOccurrences collection that tracks occurrences of * variables * @return Set of formulas that represent the encoding of the rules */ @@ -251,9 +251,9 @@ private static Set generateDataPropertySubstitutionRules(SLTLxVari * Generate the rules that enforce substitution over binary predicates.
* e.g., VAL(?x,a) & VAL(?y,b) => (R_v(x,y) <=> R(a,b)) * - * @param pair - a pair of variables that will be substituted - * @param variableSubstitutions - collection of substitutions for each variable - * @param varOccurrences - collection that tracks occurrences of + * @param pair a pair of variables that will be substituted + * @param variableSubstitutions collection of substitutions for each variable + * @param varOccurrences collection that tracks occurrences of * variables * @return Set of formulas that represent the encoding of the rules */ @@ -311,7 +311,7 @@ private static Set generateBinarySubstitutionRules(Pair getVariableDomain(int stateNo, SATSynthesisEngine synth /** * Get the set of clauses that enforce that the a variable cannot reference two different data instances. - * @param stateNo - current state in the SLTLx model - * @param variableMapping - collection of substitutions for each variable - * @param synthesisEngine - synthesis engine + * @param stateNo current state in the SLTLx model + * @param variableMapping collection of substitutions for each variable + * @param synthesisEngine synthesis engine * @return Set of clauses that encode the possible variable substitution. */ public Set getVariableUniqueSubstitution(int stateNo, SLTLxVariableSubstitutionCollection variableMapping, diff --git a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVariableOccurrenceCollection.java b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVariableOccurrenceCollection.java index d2fe26e..a99d406 100644 --- a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVariableOccurrenceCollection.java +++ b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVariableOccurrenceCollection.java @@ -45,8 +45,8 @@ public SLTLxVariableOccurrenceCollection() { /** * Associate the data type to the corresponding variable. * - * @param dataType - state property - * @param variableState - variable used + * @param dataType state property + * @param variableState variable used * @return {@code true} if the property was associated with the variable, * {@code false} otherwise. */ @@ -65,8 +65,8 @@ public boolean addDataType(PredicateLabel dataType, SLTLxVariable variableState) /** * Associate the tool input state to the corresponding variable. * - * @param usedState - state that represents data input - * @param variableState - variable used + * @param usedState state that represents data input + * @param variableState variable used * @return {@code true} if the state was associated with the variable, * {@code false} otherwise. */ @@ -86,8 +86,8 @@ public boolean addMemoryReference(State usedState, SLTLxVariable variableState) * Associate the pair of variables (the order of the variables matter) with the * type of atom they are used in. * - * @param varPair - pair of the variables used - * @param relType - Atom type that has the pair of variables as arguments + * @param varPair pair of the variables used + * @param relType Atom type that has the pair of variables as arguments */ public void addBinaryPred(Pair varPair, AtomVarType relType) { if (relType.equals(AtomVarType.VAR_VALUE)) { @@ -109,7 +109,7 @@ public void addBinaryPred(Pair varPair, AtomVarType relType) { if (this.variablePairs.get(varPair.getSecond()) == null) { // create the second element mapping as it did not occur earlier (and add the // first element) - Set> vars = new HashSet>(); + Set> vars = new HashSet<>(); vars.add(varPair); this.variablePairs.put(varPair.getSecond(), vars); } else { @@ -132,7 +132,7 @@ public void addBinaryPred(Pair varPair, AtomVarType relType) { /** * Get all data types that include the given variable. * - * @param satVariable - the given variable + * @param satVariable the given variable * @return Set (possibly empty) of memory references that are mentioned in * combination with the given variable. */ @@ -144,7 +144,7 @@ public Set getDataTypes(SLTLxVariable satVariable) { /** * Get all memory references that include the given variable. * - * @param satVariable - the given variable + * @param satVariable the given variable * @return Set (possibly empty) of memory references that are mentioned in * combination with the given variable. */ @@ -157,7 +157,7 @@ public Set getMemoryReferences(SLTLxVariable satVariable) { * Get all binary relations that include the given variable pair as arguments * (in the given order). * - * @param varPair - the given variable pair + * @param varPair the given variable pair * @return Set (possibly empty) of binary predicates that were used over the * variable pair. */ @@ -170,7 +170,7 @@ public Set getBinaryPredicates(Pair varPair) { * Return the set of pairs that are used in the formulas, where the given * variable is one of the two in pair. * - * @param variable - variable that is in the pairs + * @param variable variable that is in the pairs * @return Set of Pair objects that are used in the formulas that contain the * given variable. */ diff --git a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVariableSubstitutionCollection.java b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVariableSubstitutionCollection.java index 581e09f..b20efc7 100644 --- a/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVariableSubstitutionCollection.java +++ b/src/main/java/nl/uu/cs/ape/models/sltlxStruc/SLTLxVariableSubstitutionCollection.java @@ -34,7 +34,7 @@ public SLTLxVariableSubstitutionCollection() { /** * Create a new variable mapping, based on the existing one. * - * @param existing - existing variable mapping. + * @param existing existing variable mapping. */ public SLTLxVariableSubstitutionCollection(SLTLxVariableSubstitutionCollection existing) { super(); @@ -55,7 +55,7 @@ public SLTLxVariableSubstitutionCollection(SLTLxVariableSubstitutionCollection e * In case that the substitution for a variable with the same name exists, it * will be overwritten. * - * @param existingVar - variable used in the formula + * @param existingVar variable used in the formula * @return Unique variable that corresponds to the current variable binding. */ public SLTLxVariable addNewVariable(SLTLxVariable existingVar, Set varDomain) { @@ -70,12 +70,12 @@ public SLTLxVariable addNewVariable(SLTLxVariable existingVar, Set varDom * Get the unique variable used to substitute the current binding of the * variable. * - * @param existingVar - variable used in the formula + * @param existingVar variable used in the formula * @return Unique variable that corresponds to the current variable binding. - * @throws SLTLxParsingAnnotationException - in case that the variable does not + * @throws SLTLxParsingAnnotationException in case that the variable does not * exist. */ - public SLTLxVariable getVarSabstitute(SLTLxVariable existingVar) throws SLTLxParsingAnnotationException { + public SLTLxVariable getVarSubstitute(SLTLxVariable existingVar) throws SLTLxParsingAnnotationException { SLTLxVariable variable = mappedVariables.get(existingVar); if (variable == null) { throw SLTLxParsingAnnotationException @@ -87,7 +87,7 @@ public SLTLxVariable getVarSabstitute(SLTLxVariable existingVar) throws SLTLxPar /** * Get the domain for the given variable. * - * @param variable - variable in question + * @param variable variable in question * @return Set of states that represent the domain of the variable. */ public Set getVariableDomain(SLTLxVariable variable) { diff --git a/src/main/java/nl/uu/cs/ape/models/templateFormulas/SLTLxTemplateFormula.java b/src/main/java/nl/uu/cs/ape/models/templateFormulas/SLTLxTemplateFormula.java index 135d637..5084389 100644 --- a/src/main/java/nl/uu/cs/ape/models/templateFormulas/SLTLxTemplateFormula.java +++ b/src/main/java/nl/uu/cs/ape/models/templateFormulas/SLTLxTemplateFormula.java @@ -509,11 +509,11 @@ public static String useModuleOutput(TaxonomyPredicate module, TaxonomyPredicate * 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. + * @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, @@ -525,22 +525,21 @@ public static String connectedModules(TaxonomyPredicate firstPredicate, Taxonomy 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); + for (Pair operations : APEUtils.generateDistinctPairs(automatonSize)) { + int op1 = operations.getFirst(); + int op2 = operations.getSecond(); + int currComb = mappings.getNextAuxNum(); + allCombinations.add(currComb); - opOrderStates.put(currComb, new Pair<>(moduleAutomaton.getAllStates().get(op1), - moduleAutomaton.getAllStates().get(op2))); + 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(); + List op1outputs = typeAutomaton.getMemoryTypesBlock(op1 + 1).getStates(); + List op2inputs = typeAutomaton.getUsedTypesBlock(op2).getStates(); - Set> statePairs = APEUtils.getUniquePairs(op1outputs, op2inputs); - opOutInPairs.put(currComb, statePairs); + Set> statePairs = APEUtils.getUniquePairs(op1outputs, op2inputs); + opOutInPairs.put(currComb, statePairs); - } } // at least one of the combinations must be valid for (Integer currComb : allCombinations) { @@ -574,10 +573,10 @@ public static String connectedModules(TaxonomyPredicate firstPredicate, Taxonomy * 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. + * @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, @@ -586,33 +585,34 @@ public static String notConnectedModules(TaxonomyPredicate firstPredicate, Taxon 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); + for (Pair operations : APEUtils.generateDistinctPairs(automatonSize)) { + int op1 = operations.getFirst(); + int op2 = operations.getSecond(); - List op1outputs = typeAutomaton.getMemoryTypesBlock(op1 + 1).getStates(); - List op2inputs = typeAutomaton.getUsedTypesBlock(op2).getStates(); + State firstModuleState = moduleAutomaton.get(op1); + State secondModuleState = moduleAutomaton.get(op2); - // 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"); - } + 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(); + } /** @@ -632,24 +632,24 @@ public static String notRepeatModules(TaxonomyPredicate predicate, APEDomainSetu 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++) { + for (Pair operations : APEUtils.generateDistinctPairs(automatonSize)) { + int op1 = operations.getFirst(); + int op2 = operations.getSecond(); - State firstModuleState = moduleAutomaton.get(op1); - State secondModuleState = moduleAutomaton.get(op2); + State firstModuleState = moduleAutomaton.get(op1); + State secondModuleState = moduleAutomaton.get(op2); - // filter all operations - domainSetup.getAllModules().getElementsFromSubTaxonomy(predicate).stream() - .filter(x -> x.isSimplePredicate()).forEach(operation -> { + // 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(operation, secondModuleState, AtomType.MODULE) - + " 0\n"); - }); + constraints.append("-") + .append(mappings.add(operation, firstModuleState, AtomType.MODULE)).append(" "); + constraints.append("-" + + mappings.add(operation, secondModuleState, AtomType.MODULE) + + " 0\n"); + }); - } } return constraints.toString(); @@ -659,48 +659,50 @@ public static String notRepeatModules(TaxonomyPredicate predicate, APEDomainSetu * Creates a CNF representation of the Constraint:
* The same tools that belong to the sub-taxonomy should not be connected. * - * @param predicate - Root predicate of the sub-taxonomy. - * @param domainSetup - * @param moduleAutomaton - * @param typeAutomaton - * @param mappings - * @return + * @param predicate Root predicate of the sub-taxonomy. + * @param domainSetup Current domain setup. + * @param moduleAutomaton Current module automaton modeling the workflow control + * flow. + * @param typeAutomaton Current type automaton modeling the workflow data + * flow. + * @param mappings Set of the mappings for the literals. + * @return The String CNF representation of the SLTLx formula. */ public static String notConnectModules(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"); - }); - } + for (Pair operations : APEUtils.generateDistinctPairs(automatonSize)) { + int op1 = operations.getFirst(); + int op2 = operations.getSecond(); + + 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(); @@ -724,19 +726,21 @@ public static String useUniqueInputs( Block inputs = typeAutomaton.getUsedTypesBlock(blockNo); Set> inputPairs = new HashSet<>(); inputPairs.addAll(APEUtils.getUniquePairs(inputs.getStates())); - for(State memoryState : typeAutomaton.getAllMemoryStatesUntilBlockNo(blockNo)){ + for (State memoryState : typeAutomaton.getAllMemoryStatesUntilBlockNo(blockNo)) { for (Pair inputPair : inputPairs) { - constraints.append("-").append(mappings.add(memoryState, inputPair.getFirst(), AtomType.MEM_TYPE_REFERENCE)).append(" "); - constraints.append("-").append(mappings.add(memoryState, inputPair.getSecond(), AtomType.MEM_TYPE_REFERENCE)).append(" 0\n"); + constraints.append("-") + .append(mappings.add(memoryState, inputPair.getFirst(), AtomType.MEM_TYPE_REFERENCE)) + .append(" "); + constraints.append("-") + .append(mappings.add(memoryState, inputPair.getSecond(), AtomType.MEM_TYPE_REFERENCE)) + .append(" 0\n"); } } - } return constraints.toString(); } } - -// pairs of inputs X1 X2 not ref(x1, O) or not ref(x2, O) \ No newline at end of file +// pairs of inputs X1 X2 not ref(x1, O) or not ref(x2, O) \ No newline at end of file diff --git a/src/main/java/nl/uu/cs/ape/parserSLTLx/SLTLxSATVisitor.java b/src/main/java/nl/uu/cs/ape/parserSLTLx/SLTLxSATVisitor.java index 8dc0574..9973c8a 100644 --- a/src/main/java/nl/uu/cs/ape/parserSLTLx/SLTLxSATVisitor.java +++ b/src/main/java/nl/uu/cs/ape/parserSLTLx/SLTLxSATVisitor.java @@ -82,15 +82,15 @@ public SLTLxSATVisitor(SATSynthesisEngine synthesisEngine) { * Parse the formulas, where each is separated by a new line, and return the set * of {link SLTLxFormula}a that model it. * - * @param synthesisEngine - SAT synthesis engine - * @param formulasInSLTLx - SLTLx formulas in textual format (separated by new + * @param synthesisEngine SAT synthesis engine + * @param formulasInSLTLx SLTLx formulas in textual format (separated by new * lines) * @return Set of {link SLTLxFormula} objects, where each represents a row * (formula) from the text. - * @throws SLTLxParsingGrammarException - Exception is thrown when a formula + * @throws SLTLxParsingGrammarException Exception is thrown when a formula * does not follow the provided grammar * rules. - * @throws SLTLxParsingAnnotationException - Exception is thrown if the formula + * @throws SLTLxParsingAnnotationException Exception is thrown if the formula * follows the given grammar, but cannot * be interpreted under the current * domain (e.g., used operation does not diff --git a/src/main/java/nl/uu/cs/ape/solver/ModuleUtils.java b/src/main/java/nl/uu/cs/ape/solver/ModuleUtils.java index 514f3cb..6d65b5a 100644 --- a/src/main/java/nl/uu/cs/ape/solver/ModuleUtils.java +++ b/src/main/java/nl/uu/cs/ape/solver/ModuleUtils.java @@ -83,7 +83,7 @@ public String encodeDataInstanceDependencyCons(TypeAutomaton typeAutomaton, SATA * Returns the representation of the input type constraints for all tools * regarding @typeAutomaton, for the synthesis concerning @moduleAutomaton. * - * @param synthesisInstance - synthesis instance + * @param synthesisInstance synthesis instance * * @return String representation of constraints. */ @@ -95,7 +95,7 @@ public String encodeDataInstanceDependencyCons(TypeAutomaton typeAutomaton, SATA * ensure that the {@link AtomType#MEM_TYPE_REFERENCE} are implemented * correctly. * - * @param synthesisInstance - synthesis instance + * @param synthesisInstance synthesis instance * * @return String representing the constraints required to ensure that the * {@link AtomType#MEM_TYPE_REFERENCE} are implemented correctly. @@ -111,7 +111,7 @@ public String encodeDataInstanceDependencyCons(TypeAutomaton typeAutomaton, SATA * regarding @typeAutomaton, for the synthesis concerning @moduleAutomaton and * the Shared Memory Approach. * - * @param synthesisInstance - synthesis instance + * @param synthesisInstance synthesis instance * * @return String representation of constraints. */ @@ -157,7 +157,7 @@ public abstract String enforceDataDependencyOverDataReferencing(TypeAutomaton ty * workflow inputs have to be used, then each of them has to be referenced at * least once. * - * @param synthesisInstance - synthesis instance + * @param synthesisInstance synthesis instance * * @return String representation of constraints. */ @@ -168,7 +168,7 @@ public abstract String enforceDataDependencyOverDataReferencing(TypeAutomaton ty * regarding @typeAutomaton, for the synthesis concerning @moduleAutomaton.
* Generate constraints that preserve tool outputs. * - * @param synthesisInstance - synthesis instance + * @param synthesisInstance synthesis instance * * @return String representation of constraints. */ diff --git a/src/main/java/nl/uu/cs/ape/solver/minisat/EnforceModuleRelatedRules.java b/src/main/java/nl/uu/cs/ape/solver/minisat/EnforceModuleRelatedRules.java index 0a6cf0b..c6c98a9 100644 --- a/src/main/java/nl/uu/cs/ape/solver/minisat/EnforceModuleRelatedRules.java +++ b/src/main/java/nl/uu/cs/ape/solver/minisat/EnforceModuleRelatedRules.java @@ -126,7 +126,7 @@ public static Set ancestorRelationsDependency(SATSynthesisEngine s * 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 + * @param typeAutomaton collection of states representing the data objects in * the workflow * @return Set of SLTLx formulas that represent the constraints. */ @@ -564,7 +564,7 @@ private static Set ancestorRelRestrictOverModules(SATSynthesisEngi * Generate constraints that ensure that the relations (e.g., identity relation * (IS)) are reflexive. * - * @param binRel - binary relation that is reflexive + * @param binRel binary relation that is reflexive * * @return Set of SLTLx formulas that represent the constraints. */ @@ -598,7 +598,7 @@ private static Set relationalReflexivity(AtomType binRel, TypeAuto * (IS)) are an identity. * Forall X,Y IS(X,Y) IFF * - * @param binRel - binary relation that is reflexive + * @param binRel binary relation that is reflexive * * @return Set of SLTLx formulas that represent the constraints. */ @@ -650,8 +650,8 @@ private static Set relationalIdentity(AtomType binRel, TypeAutomat * 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 + * @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) { @@ -688,8 +688,8 @@ private static Set relationalTransitivity(AtomType binRel, TypeAut * 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 + * @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) { @@ -722,7 +722,7 @@ private static Set relationalSymmetry(AtomType binRel, TypeAutomat * workflow inputs have to be used, then each of them has to be referenced at * least once. * - * @param synthesisInstance - instance of the synthesis engine + * @param synthesisInstance instance of the synthesis engine * * @return Set of SLTLx formulas that represent the constraints. */ @@ -838,7 +838,7 @@ private static Set usageOfGeneratedTypes(SATSynthesisEngine synthe * regarding @typeAutomaton, for the synthesis concerning @moduleAutomaton.
* Generate constraints that preserve tool outputs. * - * @param synthesisInstance - instance of the synthesis engine + * @param synthesisInstance instance of the synthesis engine * * @return Set of SLTLx formulas that represent the constraints. */ diff --git a/src/main/java/nl/uu/cs/ape/solver/minisat/EnforceTypeRelatedRules.java b/src/main/java/nl/uu/cs/ape/solver/minisat/EnforceTypeRelatedRules.java index ae4c841..8013da9 100644 --- a/src/main/java/nl/uu/cs/ape/solver/minisat/EnforceTypeRelatedRules.java +++ b/src/main/java/nl/uu/cs/ape/solver/minisat/EnforceTypeRelatedRules.java @@ -47,8 +47,8 @@ private EnforceTypeRelatedRules() { * (excluding abstract modules from the taxonomy) in each memory state * of @moduleAutomaton. * - * @param pair - pair of types from a dimension. - * @param typeAutomaton - System that represents states in the workflow + * @param pair pair of types from a dimension. + * @param typeAutomaton System that represents states in the workflow * @return String representation of constraints. */ public static Set memoryTypesMutualExclusion(Pair pair, TypeAutomaton typeAutomaton) { @@ -77,8 +77,8 @@ public static Set memoryTypesMutualExclusion(Pair * (excluding abstract modules from the taxonomy) in each used state * of @moduleAutomaton. * - * @param pair - pair of types from a dimension. - * @param typeAutomaton - System that represents states in the workflow + * @param pair pair of types from a dimension. + * @param typeAutomaton System that represents states in the workflow * @return String representation of constraints. */ public static Set usedTypeMutualExclusion(Pair pair, TypeAutomaton typeAutomaton) { @@ -109,8 +109,8 @@ public static Set usedTypeMutualExclusion(Pair pai * state of @moduleAutomaton. It enforces that each type instance is either * defined on all the dimensions or is empty. * - * @param domainSetup - Domain model - * @param typeAutomaton - System that represents states in the workflow + * @param domainSetup Domain model + * @param typeAutomaton System that represents states in the workflow * @return String representation of constraints. */ public static Set typeMandatoryUsage(APEDomainSetup domainSetup, TypeAutomaton typeAutomaton) { @@ -158,8 +158,8 @@ public static Set typeMandatoryUsage(APEDomainSetup domainSetup, T * and it's valid in each state of @typeAutomaton. @emptyType denotes the type * that is being used if the state has no type. * - * @param allTypes - Collection of all the types in the domain. - * @param typeAutomaton - System that represents states in the workflow + * @param allTypes Collection of all the types in the domain. + * @param typeAutomaton System that represents states in the workflow * @return The String representation of constraints enforcing taxonomy * classifications. */ @@ -187,9 +187,9 @@ public static Set typeEnforceTaxonomyStructure(AllTypes allTypes, /** * Supporting recursive method for typeEnforceTaxonomyStructure. * - * @param currType - Current type - * @param typeState - Current type state - * @param typeElement - Current type element + * @param currType Current type + * @param typeState Current type state + * @param typeElement Current type element * @return Set of the corresponding SLTLx formulas */ private static Set typeEnforceTaxonomyStructureForState(TaxonomyPredicate currType, diff --git a/src/main/java/nl/uu/cs/ape/solver/minisat/SATSynthesisEngine.java b/src/main/java/nl/uu/cs/ape/solver/minisat/SATSynthesisEngine.java index 28a8116..b34bd12 100644 --- a/src/main/java/nl/uu/cs/ape/solver/minisat/SATSynthesisEngine.java +++ b/src/main/java/nl/uu/cs/ape/solver/minisat/SATSynthesisEngine.java @@ -124,7 +124,7 @@ public class SATSynthesisEngine implements SynthesisEngine { * @param allSolutions Set of {@link SolutionWorkflow}. * @param runConfig Setup configuration for the synthesis. * @param workflowLength Workflow length - * @throws IOException - Error if the temp file cannot be created + * @throws IOException Error if the temp file cannot be created */ public SATSynthesisEngine(APEDomainSetup domainSetup, SolutionsList allSolutions, APERunConfig runConfig, int workflowLength) throws IOException { @@ -444,7 +444,7 @@ public SLTLxVariableOccurrenceCollection getVariableUsage() { /** * Delete all temporary files created. * - * @throws IOException - Failed to delete temp files. + * @throws IOException Failed to delete temp files. */ public void deleteTempFiles() throws IOException { try { diff --git a/src/main/java/nl/uu/cs/ape/solver/solutionStructure/ModuleNode.java b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/ModuleNode.java index a9c541b..691456f 100644 --- a/src/main/java/nl/uu/cs/ape/solver/solutionStructure/ModuleNode.java +++ b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/ModuleNode.java @@ -92,7 +92,7 @@ public ModuleNode(State automatonState) throws ExceptionInInitializerError { /** * Set module/tool that defines this step in the workflow. * - * @param module - tool provided by the tool/module annotations. + * @param module tool provided by the tool/module annotations. */ public void setUsedModule(Module module) { this.usedModule = module; @@ -102,7 +102,7 @@ public void setUsedModule(Module module) { * Add the abstract module to the list of modules that describes the tool * instance. * - * @param abstractModule - abstract type that describes the instance. + * @param abstractModule abstract type that describes the instance. */ public void addAbstractDescriptionOfUsedType(AbstractModule abstractModule) { if (!abstractModule.isSimplePredicate()) { diff --git a/src/main/java/nl/uu/cs/ape/solver/solutionStructure/SolutionsList.java b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/SolutionsList.java index df92831..83a6e90 100644 --- a/src/main/java/nl/uu/cs/ape/solver/solutionStructure/SolutionsList.java +++ b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/SolutionsList.java @@ -61,10 +61,10 @@ public class SolutionsList { /** * Create an object that will contain all the solutions of the synthesis. * - * @param runConfig - setup configuration for the synthesis run. + * @param runConfig setup configuration for the synthesis run. */ public SolutionsList(APERunConfig runConfig) { - this.solutions = new ArrayList(); + this.solutions = new ArrayList<>(); this.runConfig = runConfig; /* * Provides mapping from each atom/predicate to a number/string, and vice versa @@ -175,8 +175,8 @@ public int size() { * Set a specific number to be the number of solutions that are found up to the * specified length. * - * @param length - the length up until which the solutions are evaluated - * @param noSolutions - number of solutions that can be found up until the given + * @param length the length up until which the solutions are evaluated + * @param noSolutions number of solutions that can be found up until the given * length */ public void addNoSolutionsForLength(Integer length, Integer noSolutions) { @@ -185,7 +185,7 @@ public void addNoSolutionsForLength(Integer length, Integer noSolutions) { if (solutionsPerLength == null) { solutionsPerLength = new ArrayList<>(); } - solutionsPerLength.add(new Pair(length, noSolutions)); + solutionsPerLength.add(new Pair<>(length, noSolutions)); } /** @@ -220,7 +220,7 @@ public Stream getParallelStream() { * Set the synthesis result flag, i.e., set the reason why the synthesis * execution was interrupted. * - * @param flag - the {@link SynthesisFlag} that should be set + * @param flag the {@link SynthesisFlag} that should be set */ public void setFlag(SynthesisFlag flag) { this.runFlag = flag; diff --git a/src/main/java/nl/uu/cs/ape/utils/APEFiles.java b/src/main/java/nl/uu/cs/ape/utils/APEFiles.java index cac3a6b..f11bb16 100644 --- a/src/main/java/nl/uu/cs/ape/utils/APEFiles.java +++ b/src/main/java/nl/uu/cs/ape/utils/APEFiles.java @@ -54,8 +54,8 @@ public enum Permission { /** * Verify and get full local path based based on the field. * - * @param tag - tag - * @param path - path + * @param tag tag + * @param path path * @return Return the path to the file */ private static Path getLocalPath(String tag, String path) { @@ -80,7 +80,7 @@ private static Path getLocalPath(String tag, String path) { /** * Verify whether the path is a valid local path. * - * @param path - local path + * @param path local path * @return Return {@code true} if the local path exists, {@code false} * otherwise. */ @@ -193,8 +193,8 @@ public static Path readDirectoryPath(String tag, String inputPath, Permission... /** * Create a directory path if needed. * - * @param tag - tag used - * @param path - directory path + * @param tag tag used + * @param path directory path */ private static void createDirectory(String tag, Path path) throws APEConfigException { @@ -305,7 +305,7 @@ public static boolean isURI(String uri) { * Read file content from the given path (local path or a public URL) and return * the content as a File object. * - * @param filePath - Local path or a public URL with the content. + * @param filePath Local path or a public URL with the content. * @return File containing info provided at the path. * @throws IOException Exception in case of a badly formatted path or file. */ @@ -318,7 +318,7 @@ public static File readPathToFile(String filePath) throws IOException { /** * Read content from a URL and return it as a file. * - * @param fileUrl - URL of the content + * @param fileUrl URL of the content * @return File containing info provided at the URL. * @throws IOException Exception in case of a badly formatted URL or file. */ @@ -336,8 +336,8 @@ private static File readURLToFile(String fileUrl) throws IOException { * Append text to the existing file. It adds the text at the end of the content * of the file. * - * @param file - existing file - * @param content - content that should be appended + * @param file existing file + * @param content content that should be appended * @throws IOException in case of an I/O error * @throws NullPointerException if the file is null */ @@ -352,8 +352,8 @@ public static void appendToFile(File file, String content) throws IOException, N * Append text to the existing file. It adds the text at the end of the content * of the file. * - * @param file - existing file - * @param content - content that should be appended + * @param file existing file + * @param content content that should be appended * @throws IOException in case of an I/O error * @throws NullPointerException if the file is null */ @@ -370,8 +370,8 @@ public static void appendSetToFile(File file, Set content) throws IOExce * Append text to the existing file. It adds the text at the end of the content * of the file. * - * @param file - existing file - * @param cnfEncoding - cnf clauses that should be appended + * @param file existing file + * @param cnfEncoding cnf clauses that should be appended * @throws IOException in case of an I/O error * @throws NullPointerException if the file is null */ diff --git a/src/main/java/nl/uu/cs/ape/utils/APEUtils.java b/src/main/java/nl/uu/cs/ape/utils/APEUtils.java index ca88866..128b978 100644 --- a/src/main/java/nl/uu/cs/ape/utils/APEUtils.java +++ b/src/main/java/nl/uu/cs/ape/utils/APEUtils.java @@ -139,14 +139,17 @@ public static List getListFromJson(JSONObject jsonObject, String key, Cla } /** - * The method return a list of {@link JSONObject} elements that correspond to - * the value of a given key in the given json object. If the key corresponds to + * The method return a list of {@link JSONObject} elements that correspond to + * the value of a given key in the given json object. If the key corresponds to * a {@link JSONArray} all the elements are put in a {@link List}, otherwise if - * the key corresponds to a {@link JSONObject} list will contain only that object. + * the key corresponds to a {@link JSONObject} list will contain only that + * object. + * * @param jsonObject {@link JSONObject} that is being explored. - * @param key Key label that corresponds to the elements. + * @param key Key label that corresponds to the elements. * - * @return List of elements that corresponds to the key. If the key does not exists returns empty list. + * @return List of elements that corresponds to the key. If the key does not + * exists returns empty list. */ public static List getJSONListFromJson(JSONObject jsonObject, String key) { return getListFromJson(jsonObject, key, JSONObject.class); @@ -592,7 +595,7 @@ public static void enableErr() { /** * Clone the given JSON object * - * @param original - original JSON object + * @param original original JSON object * @return copy of the original JSONObject. */ public static JSONObject clone(JSONObject original) { @@ -602,7 +605,7 @@ public static JSONObject clone(JSONObject original) { /** * Count the number of lines in a file. * - * @param cnfEncoding - file to count lines + * @param cnfEncoding file to count lines * @return number of lines */ public static int countLines(File cnfEncoding) { @@ -622,7 +625,7 @@ public static int countLines(File cnfEncoding) { * Visualises in the command line the memory status of the VM at the given step, * if debug mode is on. * - * @param debugMode - true if debug mode is on + * @param debugMode true if debug mode is on */ public static void printMemoryStatus(boolean debugMode) { if (!debugMode) { @@ -642,25 +645,25 @@ public static void printMemoryStatus(boolean debugMode) { } /** - * Get all unique pairs of PredicateLabels within the collection. - * - * @param - The type that extends PredicateLabel - * @param set - Set of PredicateLabel that should be used to create the pairs - * @return Set of unique pairs. - */ - public static Set> getUniquePairs(Collection set) { - Set> pairs = new HashSet<>(); - set.stream().forEach(ele1 -> set.stream().filter(ele2 -> ele1.compareTo(ele2) < 0) - .forEach(ele2 -> pairs.add(new Pair<>(ele1, ele2)))); - return pairs; - } + * Get all unique pairs of PredicateLabels within the collection. + * + * @param The type that extends PredicateLabel + * @param set Set of PredicateLabel that should be used to create the pairs + * @return Set of unique pairs. + */ + public static Set> getUniquePairs(Collection set) { + Set> pairs = new HashSet<>(); + set.stream().forEach(ele1 -> set.stream().filter(ele2 -> ele1.compareTo(ele2) < 0) + .forEach(ele2 -> pairs.add(new Pair<>(ele1, ele2)))); + return pairs; + } /** * Get unique pairs of elements within 2 collections. * - * @param set1 - Set of elements that should be used to create the first + * @param set1 Set of elements that should be used to create the first * elements of the pairs - * @param set2 - Set of elements that should be used to create the second + * @param set2 Set of elements that should be used to create the second * elements of the pairs * @return Set of unique pairs. */ @@ -670,4 +673,24 @@ public static Set> getUniquePairs(Collection set1, Collection return pairs; } + /** + * Generates a list of distinct pairs of integers where the first element is + * smaller than the second. + * Each pair is generated up to the specified maximum number (exclusive). + * + * @param maxNumber The exclusive upper bound for generating pairs. + * @return List of distinct pairs of integers. + */ + public static List> generateDistinctPairs(int maxNumber) { + List> distinctPairs = new ArrayList<>(); + + for (int first = 0; first < maxNumber - 1; first++) { + for (int second = first + 1; second < maxNumber; second++) { + distinctPairs.add(new Pair<>(first, second)); + } + } + + return distinctPairs; + } + } From 3589f22ac4757ebeb9740cc09f924dd7872be452 Mon Sep 17 00:00:00 2001 From: Vedran Kasalica Date: Wed, 2 Oct 2024 10:38:46 +0200 Subject: [PATCH 11/13] Updated CWL creation to support CWL tool description generation --- src/main/java/nl/uu/cs/ape/Main.java | 28 +- .../nl/uu/cs/ape/domain/APEDomainSetup.java | 8 +- src/main/java/nl/uu/cs/ape/models/Module.java | 6 +- .../nl/uu/cs/ape/solver/SynthesisEngine.java | 2 + .../ape/solver/minisat/SatEncodingUtils.java | 6 +- .../solver/solutionStructure/ModuleNode.java | 8 + .../solver/solutionStructure/TypeNode.java | 7 +- .../cwl/AbstractCWLCreator.java | 9 +- .../solutionStructure/cwl/CWLToolBase.java | 248 ++++++++++++++++++ ...LCreatorBase.java => CWLWorkflowBase.java} | 12 +- .../cwl/DefaultCWLCreator.java | 6 +- .../solutionStructure/cwl/ToolCWLCreator.java | 81 ++++++ .../java/nl/uu/cs/ape/utils/APEFiles.java | 122 +++++---- .../ape/test/sat/ape/APEDomainSetupTest.java | 40 +++ 14 files changed, 498 insertions(+), 85 deletions(-) create mode 100644 src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/CWLToolBase.java rename src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/{CWLCreatorBase.java => CWLWorkflowBase.java} (95%) create mode 100644 src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/ToolCWLCreator.java create mode 100644 src/test/java/nl/uu/cs/ape/test/sat/ape/APEDomainSetupTest.java diff --git a/src/main/java/nl/uu/cs/ape/Main.java b/src/main/java/nl/uu/cs/ape/Main.java index 7e813d1..b3b52d5 100644 --- a/src/main/java/nl/uu/cs/ape/Main.java +++ b/src/main/java/nl/uu/cs/ape/Main.java @@ -6,6 +6,8 @@ import nl.uu.cs.ape.domain.BioToolsAPI; import nl.uu.cs.ape.utils.APEFiles; import nl.uu.cs.ape.solver.solutionStructure.SolutionsList; +import nl.uu.cs.ape.solver.solutionStructure.cwl.ToolCWLCreator; +import nl.uu.cs.ape.models.Module; import org.apache.commons.lang3.ArrayUtils; import org.json.JSONException; @@ -29,8 +31,9 @@ public class Main { * The entry point of application when the library is used in a Command Line * Interface (CLI). * - * @param args APE expects the first argument to specify the method to be executed. - * The rest of the arguments are provided depending on the method. + * @param args APE expects the first argument to specify the method to be + * executed. + * The rest of the arguments are provided depending on the method. */ public static void main(String[] args) { @@ -76,10 +79,24 @@ private static void pullATool(String[] args) { try { JSONObject tool = BioToolsAPI.getAndConvertToolList(List.of(biotoolsID)); - APEFiles.write2file(tool.toString(4), new File("./tool.json"), false); + APEFiles.write2file(tool.toString(4), new File("./" + biotoolsID + ".json"), false); + + JSONObject toolAnnotation = tool.getJSONArray("functions").getJSONObject(0); + APE apeFramework = new APE( + "https://raw.githubusercontent.com/Workflomics/tools-and-domains/refs/heads/main/domains/proteomics/config.json"); + + Module cometModule = apeFramework.getDomainSetup() + .updateModuleFromJson(toolAnnotation).get(); + + ToolCWLCreator toolCWLCreator = new ToolCWLCreator(cometModule); + + APEFiles.write2file(toolCWLCreator.generate(), new File("./" + biotoolsID + ".cwl"), false); + } catch (IOException e) { log.error("Error in fetching the tool from bio.tools."); - return; + } catch (OWLOntologyCreationException e) { + log.error( + "Error in setting up the APE framework from the 'https://raw.githubusercontent.com/Workflomics/tools-and-domains/refs/heads/main/domains/proteomics/config.json' configuration."); } } @@ -89,7 +106,7 @@ private static void pullATool(String[] args) { * APE-compatible tool annotation format. * * @param args The arguments provided to the method. Only one argument is - * expected, the path to the file where the biotoolsIDs are stored. + * expected, the path to the file where the biotoolsIDs are stored. */ public static void convertBioToolsAnnotations(String[] args) { if (args.length != 1) { @@ -115,6 +132,7 @@ public static void convertBioToolsAnnotations(String[] args) { /** * Executes the synthesis based on the provided configuration file. + * * @param args The arguments provided to the method. */ public static void executeSynthesis(String[] args) { diff --git a/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java b/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java index f01b704..4c6c107 100644 --- a/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java +++ b/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java @@ -332,7 +332,7 @@ public boolean annotateToolFromJson(JSONObject toolAnnotationsFile) throws IOExc * @return {@code true} if the domain was updated, false otherwise. * @throws JSONException Error if the JSON file was not properly formatted. */ - private boolean updateModuleFromJson(JSONObject jsonModule) + public Optional updateModuleFromJson(JSONObject jsonModule) throws JSONException, APEDimensionsException { String moduleIRI = APEUtils.createClassIRI(jsonModule.getString(ToolAnnotationTag.ID.toString()), ontologyPrefixIRI); @@ -385,13 +385,13 @@ private boolean updateModuleFromJson(JSONObject jsonModule) if (inputs.isEmpty() && outputs.isEmpty()) { emptyTools.add(moduleLabel); log.debug("Operation '" + "' was not included as it has no (valid) inputs and outputs specified."); - return false; + return Optional.empty(); } } catch (APEDimensionsException badDimension) { wrongToolIO.add(moduleLabel); log.warn("Operation '" + "' was not included." + badDimension.getMessage()); - return false; + return Optional.empty(); } /* Set the implementation cwl file reference of the module, if specified. */ @@ -420,7 +420,7 @@ private boolean updateModuleFromJson(JSONObject jsonModule) currModule.setModuleOutput(outputs); currModule.setAsRelevantTaxonomyTerm(allModules); - return currModule != null; + return Optional.of(currModule); } /** diff --git a/src/main/java/nl/uu/cs/ape/models/Module.java b/src/main/java/nl/uu/cs/ape/models/Module.java index 3891689..d5eb55b 100644 --- a/src/main/java/nl/uu/cs/ape/models/Module.java +++ b/src/main/java/nl/uu/cs/ape/models/Module.java @@ -166,8 +166,8 @@ public void addModuleOutput(Type moduleOutput) { /** * Generate a taxonomy tool instance that is referenced in the json. * - * @param jsonParam - * @param domainSetup + * @param jsonParam JSON object that contains the abstract module information. + * @param domainSetup APE domain information. * @return A AbstractModule object that represent the data instance given as the * parameter. * @throws JSONException if the given JSON is not well formatted @@ -176,7 +176,7 @@ public void addModuleOutput(Type moduleOutput) { public static AbstractModule taxonomyInstanceFromJson(JSONObject jsonParam, APEDomainSetup domainSetup) throws JSONException { /* Set of predicates where each describes a type dimension */ - SortedSet parameterDimensions = new TreeSet(); + SortedSet parameterDimensions = new TreeSet<>(); AllModules allModules = domainSetup.getAllModules(); /* Iterate through each of the dimensions */ for (String currRootLabel : jsonParam.keySet()) { diff --git a/src/main/java/nl/uu/cs/ape/solver/SynthesisEngine.java b/src/main/java/nl/uu/cs/ape/solver/SynthesisEngine.java index ffb6283..cb2fd2d 100644 --- a/src/main/java/nl/uu/cs/ape/solver/SynthesisEngine.java +++ b/src/main/java/nl/uu/cs/ape/solver/SynthesisEngine.java @@ -64,6 +64,8 @@ public interface SynthesisEngine { /** * Delete all temp files generated. + * + * @throws IOException the io exception if the files cannot be deleted. */ public void deleteTempFiles() throws IOException; diff --git a/src/main/java/nl/uu/cs/ape/solver/minisat/SatEncodingUtils.java b/src/main/java/nl/uu/cs/ape/solver/minisat/SatEncodingUtils.java index 674e711..3e0b320 100644 --- a/src/main/java/nl/uu/cs/ape/solver/minisat/SatEncodingUtils.java +++ b/src/main/java/nl/uu/cs/ape/solver/minisat/SatEncodingUtils.java @@ -15,6 +15,10 @@ import nl.uu.cs.ape.models.sltlxStruc.SLTLxFormula; import nl.uu.cs.ape.parserSLTLx.SLTLxSATVisitor; +/** + * The {@code SatEncodingUtils} class is used to provide utility functions for + * encoding constraints in SAT. + */ @Slf4j @NoArgsConstructor(access = AccessLevel.PRIVATE) public class SatEncodingUtils { @@ -22,7 +26,7 @@ public class SatEncodingUtils { /** * Encode APE constraints string. * - * @param synthesisEngine + * @param synthesisEngine the synthesis engine used to generate the CNF encoding * * @param domainSetup Domain information, including all the existing tools * and types. diff --git a/src/main/java/nl/uu/cs/ape/solver/solutionStructure/ModuleNode.java b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/ModuleNode.java index 691456f..957ba22 100644 --- a/src/main/java/nl/uu/cs/ape/solver/solutionStructure/ModuleNode.java +++ b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/ModuleNode.java @@ -304,6 +304,8 @@ public Graph addTavernaStyleModuleToGraph(Graph workflowGraph) { /** * Get id of the current workflow node. + * + * @return ID of the current workflow node. */ public String getNodeID() { StringBuilder printString = new StringBuilder(); @@ -315,6 +317,8 @@ public String getNodeID() { /** * Get label of the current workflow node. + * + * @return Label of the current workflow node. */ public String getNodeLabel() { return this.usedModule.getPredicateLabel(); @@ -322,6 +326,8 @@ public String getNodeLabel() { /** * Get label of the current workflow node as an HTML element. + * + * @return HTML label of the current workflow node. */ public String getNodeGraphLabel() { return "" + this.usedModule.getPredicateLabel() + ""; @@ -329,6 +335,8 @@ public String getNodeGraphLabel() { /** * Gets node descriptive label, containing module IDs. + * + * @return The node descriptive label. */ public String getNodeLongLabel() { return this.usedModule.getPredicateLongLabel(); diff --git a/src/main/java/nl/uu/cs/ape/solver/solutionStructure/TypeNode.java b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/TypeNode.java index d359fac..b2bf613 100644 --- a/src/main/java/nl/uu/cs/ape/solver/solutionStructure/TypeNode.java +++ b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/TypeNode.java @@ -4,7 +4,6 @@ import guru.nidi.graphviz.attribute.Label; import guru.nidi.graphviz.attribute.Shape; import guru.nidi.graphviz.attribute.Style; -import guru.nidi.graphviz.attribute.Label.Justification; import guru.nidi.graphviz.model.Graph; import lombok.extern.slf4j.Slf4j; import nl.uu.cs.ape.automaton.State; @@ -68,10 +67,10 @@ public class TypeNode extends SolutionWorkflowNode { */ public TypeNode(State automatonState) throws ExceptionInInitializerError { super(automatonState); - this.usedTypes = new TreeSet(); - this.abstractTypes = new TreeSet(); + this.usedTypes = new TreeSet<>(); + this.abstractTypes = new TreeSet<>(); this.createdByModule = null; - usedByModules = new ArrayList(); + usedByModules = new ArrayList<>(); if (automatonState.getWorkflowStateType() != AtomType.MEMORY_TYPE) { throw new ExceptionInInitializerError( "Class MemTypeNode can only be instantiated using State that is of type AtomType.MEMORY_TYPE, as a parameter."); diff --git a/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/AbstractCWLCreator.java b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/AbstractCWLCreator.java index 4f040e3..6fb30a6 100644 --- a/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/AbstractCWLCreator.java +++ b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/AbstractCWLCreator.java @@ -14,7 +14,7 @@ * Class to generate a CWL workflow structure from a given workflow solution. */ @Slf4j -public class AbstractCWLCreator extends CWLCreatorBase { +public class AbstractCWLCreator extends CWLWorkflowBase { /** * Maintain a list of the CWL parameter names which represent {@link TypeNode}s. * I.e. this hashmap has TypeNode IDs as keys and their names in the CWL file as @@ -31,13 +31,6 @@ public AbstractCWLCreator(SolutionWorkflow solution) { super(solution); } - @Override - public String getCWLVersion() { - // CWL version 1.2.0-dev2 is the minimum version required for the features we - // use here. - return "v1.2.0-dev2"; - } - /** * Generates the CWL representation. */ diff --git a/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/CWLToolBase.java b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/CWLToolBase.java new file mode 100644 index 0000000..4fda32a --- /dev/null +++ b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/CWLToolBase.java @@ -0,0 +1,248 @@ +package nl.uu.cs.ape.solver.solutionStructure.cwl; + +import nl.uu.cs.ape.solver.solutionStructure.ModuleNode; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import nl.uu.cs.ape.models.AuxTypePredicate; +import nl.uu.cs.ape.models.AuxiliaryPredicate; +import nl.uu.cs.ape.models.Module; +import nl.uu.cs.ape.models.Type; +import nl.uu.cs.ape.models.logic.constructs.TaxonomyPredicate; + +/** + * Base class with shared behavior for CWL export classes. + */ +public abstract class CWLToolBase { + /** + * Cwl representation. + */ + protected final StringBuilder cwlRepresentation; + /** + * Tool depicted in the CWL file. + */ + protected Module tool; + /** + * Indent style used. + */ + private IndentStyle indentStyle; + + /** + * Generate the creator base from the workflow solution. + * + * @param tool APE workflow solution + */ + protected CWLToolBase(Module tool) { + this.tool = tool; + this.cwlRepresentation = new StringBuilder(); + this.indentStyle = IndentStyle.SPACES2; + } + + /** + * Override the default indentation style. + * + * @param indentStyle The indentation style to use. + * @return A reference to this CWLCreator. + */ + public CWLToolBase setIndentStyle(IndentStyle indentStyle) { + this.indentStyle = indentStyle; + return this; + } + + /** + * Get the CWL version required for the CWL file. + * + * @return The required CWL version. + */ + public String getCWLVersion() { + return "v1.2"; + } + + /** + * Generates the CWL representation. + * + * @return The CWL representation. + */ + public String generate() { + // Top of file comment + generateTopComment(); + + cwlRepresentation.append(String.format("cwlVersion: %s%n", getCWLVersion())); + cwlRepresentation.append("class: CommandLineTool").append("\n"); + + cwlRepresentation.append("baseCommand: ").append(tool.getPredicateID()).append("\n"); + cwlRepresentation.append("label: ").append(tool.getPredicateLabel()).append("\n"); + + // Add requirements (generic) + cwlRepresentation.append("requirements:\n"); + cwlRepresentation.append(" ShellCommandRequirement: {}\n"); + cwlRepresentation.append(" InitialWorkDirRequirement:\n"); + cwlRepresentation.append(" listing:\n"); + + // Dynamically add inputs to InitialWorkDirRequirement listing + for (String input : this.getInputs().keySet()) { + cwlRepresentation.append(" - $(inputs.").append(input).append(")\n"); + } + + // Add DockerRequirement dynamically + cwlRepresentation.append(" DockerRequirement:\n"); + cwlRepresentation.append(" dockerPull: fix-this-path/").append(tool.getPredicateLabel()).append("\n") + .append("\n"); + + generateCWLRepresentation(); + + return cwlRepresentation.toString(); + } + + /** + * Get the map of input names and their types. + * + * @return The map of input names and their types. + */ + protected Map> getInputs() { + int i = 0; + Map> inputNames = new HashMap<>(); + for (Type inType : tool.getModuleInput()) { + List formatType = new ArrayList<>(); + if (inType instanceof AuxTypePredicate) { + formatType = extractFormat((AuxTypePredicate) inType); + } + + inputNames.put(tool.getPredicateLabel() + "_in_" + i++, formatType); + + } + return inputNames; + } + + private List extractFormat(AuxTypePredicate auxType) { + List formatTypes = new ArrayList<>(); + for (TaxonomyPredicate subtype : auxType.getGeneralizedPredicates()) { + if (subtype instanceof AuxTypePredicate) { + formatTypes.addAll(extractFormat((AuxTypePredicate) subtype)); + } else if (subtype.getRootNodeID().equals("http://edamontology.org/format_1915")) { + formatTypes.add(subtype); + } + } + return formatTypes; + } + + /** + * Get the map of input names and their types. + * + * @return The map of input names and their types. + */ + protected Map> getOutputs() { + int i = 0; + Map> inputNames = new HashMap<>(); + for (Type inType : tool.getModuleOutput()) { + List formatType = new ArrayList<>(); + if (inType instanceof AuxTypePredicate) { + formatType = extractFormat((AuxTypePredicate) inType); + } + + inputNames.put(tool.getPredicateLabel() + "_out_" + i++, formatType); + + } + return inputNames; + } + + /** + * Adds the comment at the top of the file. + */ + protected void generateTopComment() { + cwlRepresentation.append( + "# The template for this tool description is generated by APE (https://github.com/sanctuuary/APE).\n"); + } + + /** + * Generate the name of the input or output of a step's run input or output. + * I.e. "moduleName_indicator_n". + * + * @param moduleNode The {@link ModuleNode} that is the workflow step. + * @param indicator Indicator whether it is an input or an output. + * @param n The n-th input or output this is. + * @return The name of the input or output. + */ + protected String generateInputOrOutputName(ModuleNode moduleNode, String indicator, int n) { + return String.format("%s_%s_%o", + moduleNode.getNodeLabel(), + indicator, + n); + } + + /** + * Generate the name for a step in the workflow. + * + * @param moduleNode The {@link ModuleNode} that is the workflow step. + * @return The name of the workflow step. + */ + protected String stepName(ModuleNode moduleNode) { + int stepNumber = moduleNode.getAutomatonState().getLocalStateNumber(); + if (stepNumber < 10) { + return String.format("%s_0%o", moduleNode.getUsedModule().getPredicateLabel(), stepNumber); + } else { + return String.format("%s_%o", moduleNode.getUsedModule().getPredicateLabel(), stepNumber); + } + } + + /** + * Generate the main part of the CWL representation. + */ + protected abstract void generateCWLRepresentation(); + + /** + * Gets the CWL representation. + * + * @return The CWL representation. + */ + public String getCWL() { + return cwlRepresentation.toString(); + } + + /** + * Delete a number of characters at the end of the CWL file. + * + * @param numberOfCharToDel The number of characters to remove. + */ + protected void deleteLastNCharactersFromCWL(int numberOfCharToDel) { + cwlRepresentation.delete(cwlRepresentation.length() - numberOfCharToDel, cwlRepresentation.length()); + } + + /** + * Generate the indentation at the start of a line. + * + * @param level The level of indentation. + * @return The indentation of the given level. + */ + protected String ind(int level) { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < level; i++) { + builder.append(this.indentStyle); + } + return builder.toString(); + } + + /** + * The available indentation styles. + */ + public enum IndentStyle { + /** Two spaces for indentation. */ + SPACES2(" "), + /** Four spaces for indentation. */ + SPACES4(" "); + + private final String text; + + IndentStyle(String s) { + this.text = s; + } + + @Override + public String toString() { + return this.text; + } + } +} diff --git a/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/CWLCreatorBase.java b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/CWLWorkflowBase.java similarity index 95% rename from src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/CWLCreatorBase.java rename to src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/CWLWorkflowBase.java index 5bd9a07..76dd303 100644 --- a/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/CWLCreatorBase.java +++ b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/CWLWorkflowBase.java @@ -6,7 +6,7 @@ /** * Base class with shared behavior for CWL export classes. */ -public abstract class CWLCreatorBase { +public abstract class CWLWorkflowBase { /** * Cwl representation. */ @@ -23,9 +23,9 @@ public abstract class CWLCreatorBase { /** * Generate the creator base from the workflow solution. * - * @param solution - APE workflow solution + * @param solution APE workflow solution */ - protected CWLCreatorBase(SolutionWorkflow solution) { + protected CWLWorkflowBase(SolutionWorkflow solution) { this.solution = solution; this.cwlRepresentation = new StringBuilder(); this.indentStyle = IndentStyle.SPACES2; @@ -37,7 +37,7 @@ protected CWLCreatorBase(SolutionWorkflow solution) { * @param indentStyle The indentation style to use. * @return A reference to this CWLCreator. */ - public CWLCreatorBase setIndentStyle(IndentStyle indentStyle) { + public CWLWorkflowBase setIndentStyle(IndentStyle indentStyle) { this.indentStyle = indentStyle; return this; } @@ -47,7 +47,9 @@ public CWLCreatorBase setIndentStyle(IndentStyle indentStyle) { * * @return The required CWL version. */ - public abstract String getCWLVersion(); + public String getCWLVersion() { + return "v1.2"; + } /** * Generates the CWL representation. diff --git a/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/DefaultCWLCreator.java b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/DefaultCWLCreator.java index 8731402..4653bcf 100644 --- a/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/DefaultCWLCreator.java +++ b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/DefaultCWLCreator.java @@ -16,7 +16,7 @@ * Class to generate a CWL workflow structure from a given workflow solution. */ @Slf4j -public class DefaultCWLCreator extends CWLCreatorBase { +public class DefaultCWLCreator extends CWLWorkflowBase { /** * Maintain a list of the CWL parameter names which represent {@link TypeNode}s. * I.e. this hashmap has TypeNode IDs as keys and their names in the CWL file as @@ -33,10 +33,6 @@ public DefaultCWLCreator(SolutionWorkflow solution) { super(solution); } - @Override - public String getCWLVersion() { - return "v1.2"; - } /** * Generates the CWL representation. diff --git a/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/ToolCWLCreator.java b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/ToolCWLCreator.java new file mode 100644 index 0000000..355ebf1 --- /dev/null +++ b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/ToolCWLCreator.java @@ -0,0 +1,81 @@ +package nl.uu.cs.ape.solver.solutionStructure.cwl; + +import nl.uu.cs.ape.models.Module; +import nl.uu.cs.ape.models.logic.constructs.TaxonomyPredicate; + +import java.util.List; +import java.util.Map; + +import lombok.extern.slf4j.Slf4j; + +/** + * Class to generate a CWL structure for a tool. + */ +@Slf4j +public class ToolCWLCreator extends CWLToolBase { + /** + * Instantiates a new CWL creator. + * + * @param module The solution to represent in CWL. + */ + public ToolCWLCreator(Module module) { + super(module); + } + + /** + * Generates the CWL representation. + */ + @Override + protected void generateCWLRepresentation() { + // Tool annotations + generateWorkflowInOut("inputs", super.getInputs()); + generateWorkflowInOut("outputs", super.getOutputs()); + } + + /** + * Generate the inputs and outputs of the tool. + * + * @param header The header of the section (inputs/outputs). + * @param map The types of the inputs/outputs. + */ + private void generateWorkflowInOut(String header, Map> map) { + cwlRepresentation.append(header).append(":\n"); + // Inputs + map.entrySet().forEach(input -> + + cwlRepresentation + // Name + .append(ind(1)) + .append(input.getKey()) + .append(":\n") + // Data type + .append(ind(2)) + .append("type: File") + .append("\n") + // Format + .append(ind(2)) + .append("format: ") + .append(formatType(input.getValue())) + .append("\n")); + } + + /** + * Get the format of the current workflow node and a label for the CWL file. + * + * @param list + */ + public String formatType(List list) { + StringBuilder printString = new StringBuilder(); + + if (!list.isEmpty()) { + printString.append("\"").append(list.get(0).getPredicateLongLabel()).append("\" # ").append(list.get(0).getPredicateLabel()).append("\n"); + } + if (list.size() > 1) { + log.warn("Multiple types for the same input/output are not supported."); + printString.append(ind(2)).append("doc: The I/O is annotated with multiple data formats in bio.tools. We specified here the first one, while the rest are part of tool.json file. Please check the instructions on how to handle such cases: https://workflomics.readthedocs.io/en/domain-creation/developer-guide/domain-development.html#id2 "); + } + + return printString.toString(); + } + +} diff --git a/src/main/java/nl/uu/cs/ape/utils/APEFiles.java b/src/main/java/nl/uu/cs/ape/utils/APEFiles.java index f11bb16..703f2af 100644 --- a/src/main/java/nl/uu/cs/ape/utils/APEFiles.java +++ b/src/main/java/nl/uu/cs/ape/utils/APEFiles.java @@ -13,14 +13,14 @@ import nl.uu.cs.ape.models.sltlxStruc.CNFClause; import org.apache.commons.io.LineIterator; -import org.apache.commons.io.output.FileWriterWithEncoding; import java.io.BufferedWriter; import java.io.File; +import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; -import java.io.Writer; +import java.io.OutputStreamWriter; import java.net.URL; import java.nio.file.Files; import java.nio.file.InvalidPathException; @@ -333,33 +333,41 @@ private static File readURLToFile(String fileUrl) throws IOException { } /** - * Append text to the existing file. It adds the text at the end of the content + * Appends text to the existing file. It adds the text at the end of the content * of the file. - * - * @param file existing file - * @param content content that should be appended - * @throws IOException in case of an I/O error - * @throws NullPointerException if the file is null + * + * @param file The existing file. + * @param content The content that should be appended. + * @throws IOException In case of an I/O error. + * @throws NullPointerException If the file or content is null. */ - public static void appendToFile(File file, String content) throws IOException, NullPointerException { - Writer fileWriter = new FileWriterWithEncoding(file, "ASCII", true); - try (BufferedWriter writer = new BufferedWriter(fileWriter, 8192 * 4)) { + public static void appendToFile(File file, String content) throws IOException { + if (file == null || content == null) { + throw new NullPointerException("File or content cannot be null."); + } + + try (BufferedWriter writer = new BufferedWriter( + new OutputStreamWriter(new FileOutputStream(file, true), StandardCharsets.US_ASCII), 8192 * 4)) { writer.write(content); } } /** - * Append text to the existing file. It adds the text at the end of the content - * of the file. - * - * @param file existing file - * @param content content that should be appended - * @throws IOException in case of an I/O error - * @throws NullPointerException if the file is null + * Appends a set of text strings to the existing file. Each element in the set + * is added at the end of the content of the file. + * + * @param file The existing file. + * @param content The set of content strings that should be appended. + * @throws IOException In case of an I/O error. + * @throws NullPointerException If the file or content set is null. */ - public static void appendSetToFile(File file, Set content) throws IOException, NullPointerException { - Writer fileWriter = new FileWriterWithEncoding(file, "ASCII", true); - try (BufferedWriter writer = new BufferedWriter(fileWriter, 8192 * 4)) { + public static void appendSetToFile(File file, Set content) throws IOException { + if (file == null || content == null) { + throw new NullPointerException("File or content set cannot be null."); + } + + try (BufferedWriter writer = new BufferedWriter( + new OutputStreamWriter(new FileOutputStream(file, true), StandardCharsets.US_ASCII), 8192 * 4)) { for (String str : content) { writer.write(str); } @@ -367,48 +375,62 @@ public static void appendSetToFile(File file, Set content) throws IOExce } /** - * Append text to the existing file. It adds the text at the end of the content - * of the file. - * - * @param file existing file - * @param cnfEncoding cnf clauses that should be appended - * @throws IOException in case of an I/O error - * @throws NullPointerException if the file is null + * Appends CNFClause objects' CNF string representations to the existing file. + * Each CNF clause is added at the end of the content of the file. + * + * @param file The existing file. + * @param cnfEncoding The set of CNFClause objects to be appended. + * @throws IOException In case of an I/O error. + * @throws NullPointerException If the file or CNF encoding set is null. */ - public static void appendToFile(File file, Set cnfEncoding) throws IOException, NullPointerException { - StringBuilder string = new StringBuilder(); - cnfEncoding.forEach(clause -> string.append(clause.toCNF())); - Writer fileWriter = new FileWriterWithEncoding(file, "ASCII", true); - try (BufferedWriter writer = new BufferedWriter(fileWriter, 8192 * 4)) { - writer.write(string.toString()); + public static void appendToFile(File file, Set cnfEncoding) throws IOException { + if (file == null || cnfEncoding == null) { + throw new NullPointerException("File or CNF encoding set cannot be null."); } + StringBuilder stringBuilder = new StringBuilder(); + cnfEncoding.forEach(clause -> stringBuilder.append(clause.toCNF())); + + try (BufferedWriter writer = new BufferedWriter( + new OutputStreamWriter(new FileOutputStream(file, true), StandardCharsets.US_ASCII), 8192 * 4)) { + writer.write(stringBuilder.toString()); + } } /** - * Prepend text to the existing file content and create a new file out of it. - * It adds the text at the beginning, before the existing content of the file. - * - * @param file - * @param prefix - * @throws IOException + * Prepends text to the existing file content and creates a new file with the + * modified content. It adds the text at the beginning, before the existing + * content of the file. + * + * @param prefix The text to be prepended. + * @param file The existing file. + * @return A new file with the prepended content. + * @throws IOException In case of an I/O error. + * @throws NullPointerException If the file or prefix is null. */ public static File prependToFile(String prefix, File file) throws IOException { - LineIterator li = FileUtils.lineIterator(file); + if (file == null || prefix == null) { + throw new NullPointerException("File or prefix cannot be null."); + } + File tempFile = File.createTempFile("prependPrefix", ".tmp"); tempFile.deleteOnExit(); - Writer fileWriter = new FileWriterWithEncoding(tempFile, "ASCII", true); - BufferedWriter writer = new BufferedWriter(fileWriter); - try { + + try (LineIterator lineIterator = FileUtils.lineIterator(file, StandardCharsets.US_ASCII.name()); + BufferedWriter writer = new BufferedWriter( + new OutputStreamWriter(new FileOutputStream(tempFile, true), StandardCharsets.US_ASCII))) { + + // Write the prefix first. writer.write(prefix); - while (li.hasNext()) { - writer.write(li.next()); - writer.write("\n"); + writer.newLine(); + + // Append the existing file content. + while (lineIterator.hasNext()) { + writer.write(lineIterator.nextLine()); + writer.newLine(); } - } finally { - writer.close(); - li.close(); } + return tempFile; } diff --git a/src/test/java/nl/uu/cs/ape/test/sat/ape/APEDomainSetupTest.java b/src/test/java/nl/uu/cs/ape/test/sat/ape/APEDomainSetupTest.java new file mode 100644 index 0000000..e97bd19 --- /dev/null +++ b/src/test/java/nl/uu/cs/ape/test/sat/ape/APEDomainSetupTest.java @@ -0,0 +1,40 @@ +package nl.uu.cs.ape.test.sat.ape; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + +import java.io.IOException; +import java.util.List; + +import org.json.JSONObject; +import org.junit.jupiter.api.Test; +import org.semanticweb.owlapi.model.OWLOntologyCreationException; + +import nl.uu.cs.ape.APE; +import nl.uu.cs.ape.domain.BioToolsAPI; +import nl.uu.cs.ape.models.Module; +import nl.uu.cs.ape.solver.solutionStructure.cwl.ToolCWLCreator; + +class APEDomainSetupTest { + + @Test + void updateModuleFromJsonTest() throws IOException, OWLOntologyCreationException { + List toolIDs = List.of("comet"); + JSONObject toolAnnotationJson = BioToolsAPI.getAndConvertToolList(toolIDs); + JSONObject comet = toolAnnotationJson.getJSONArray("functions").getJSONObject(0); + APE apeFramework = new APE( + "https://raw.githubusercontent.com/Workflomics/tools-and-domains/refs/heads/main/domains/proteomics/config.json"); + + + Module cometModule = apeFramework.getDomainSetup() + .updateModuleFromJson(comet).get(); + + assertEquals("Comet", cometModule.getPredicateLabel()); + + ToolCWLCreator toolCWLCreator = new ToolCWLCreator(cometModule); + String cwlRepresentation = toolCWLCreator.generate(); + assertFalse(cwlRepresentation.isEmpty()); + + + } +} From ab275fe2dc24f8217024de631e76d931349b6f8e Mon Sep 17 00:00:00 2001 From: Vedran Kasalica Date: Sat, 19 Oct 2024 14:29:49 +0200 Subject: [PATCH 12/13] Simplify CLI log, add tests and improve pull-a-tool feature --- src/main/java/nl/uu/cs/ape/Main.java | 33 ++++++++++++------- .../nl/uu/cs/ape/domain/APEDomainSetup.java | 8 ++--- .../java/nl/uu/cs/ape/domain/BioToolsAPI.java | 2 ++ .../solutionStructure/cwl/ToolCWLCreator.java | 4 +-- .../ape/test/sat/ape/APEDomainSetupTest.java | 29 +++++++++------- 5 files changed, 47 insertions(+), 29 deletions(-) diff --git a/src/main/java/nl/uu/cs/ape/Main.java b/src/main/java/nl/uu/cs/ape/Main.java index b3b52d5..487841b 100644 --- a/src/main/java/nl/uu/cs/ape/Main.java +++ b/src/main/java/nl/uu/cs/ape/Main.java @@ -5,11 +5,13 @@ import nl.uu.cs.ape.configuration.APERunConfig; import nl.uu.cs.ape.domain.BioToolsAPI; import nl.uu.cs.ape.utils.APEFiles; +import nl.uu.cs.ape.utils.APEUtils; import nl.uu.cs.ape.solver.solutionStructure.SolutionsList; import nl.uu.cs.ape.solver.solutionStructure.cwl.ToolCWLCreator; import nl.uu.cs.ape.models.Module; import org.apache.commons.lang3.ArrayUtils; +import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.semanticweb.owlapi.model.OWLOntologyCreationException; @@ -17,6 +19,7 @@ import java.io.File; import java.io.IOException; import java.util.List; +import java.util.Optional; /** * The entry point of application when the library is used in a Command Line @@ -27,6 +30,8 @@ @Slf4j public class Main { + private static final String biotools_config_URL = "https://raw.githubusercontent.com/Workflomics/tools-and-domains/refs/heads/main/domains/bio.tools/config.json"; + /** * The entry point of application when the library is used in a Command Line * Interface (CLI). @@ -78,25 +83,29 @@ private static void pullATool(String[] args) { } try { - JSONObject tool = BioToolsAPI.getAndConvertToolList(List.of(biotoolsID)); - APEFiles.write2file(tool.toString(4), new File("./" + biotoolsID + ".json"), false); - - JSONObject toolAnnotation = tool.getJSONArray("functions").getJSONObject(0); - APE apeFramework = new APE( - "https://raw.githubusercontent.com/Workflomics/tools-and-domains/refs/heads/main/domains/proteomics/config.json"); + JSONArray tool = BioToolsAPI.getAndConvertToolList(List.of(biotoolsID)).getJSONArray("functions"); + APEFiles.write2file(tool.toString(4), new File("./tool.json"), false); + for (JSONObject toolAnnotation : APEUtils.getJSONListFromJSONArray(tool)) { + APE apeFramework = new APE(biotools_config_URL); - Module cometModule = apeFramework.getDomainSetup() - .updateModuleFromJson(toolAnnotation).get(); + Optional cometModule = apeFramework.getDomainSetup() + .updateModuleFromJson(toolAnnotation); - ToolCWLCreator toolCWLCreator = new ToolCWLCreator(cometModule); + if (cometModule.isEmpty()) { + log.error(String.format("Error in defining '%s' tool using '%s' configuration.", biotoolsID, + biotools_config_URL)); + } + ToolCWLCreator toolCWLCreator = new ToolCWLCreator(cometModule.get()); - APEFiles.write2file(toolCWLCreator.generate(), new File("./" + biotoolsID + ".cwl"), false); + APEFiles.write2file(toolCWLCreator.generate(), new File("./" + toolAnnotation.getString("id") + ".cwl"), false); + } + } catch (IOException e) { log.error("Error in fetching the tool from bio.tools."); } catch (OWLOntologyCreationException e) { - log.error( - "Error in setting up the APE framework from the 'https://raw.githubusercontent.com/Workflomics/tools-and-domains/refs/heads/main/domains/proteomics/config.json' configuration."); + log.error(String.format( + "Error in setting up the APE framework from the %s configuration.", biotools_config_URL)); } } diff --git a/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java b/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java index 4c6c107..435dfd5 100644 --- a/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java +++ b/src/main/java/nl/uu/cs/ape/domain/APEDomainSetup.java @@ -349,7 +349,7 @@ public Optional updateModuleFromJson(JSONObject jsonModule) for (String parentModule : taxonomyParentModules) { String parentModuleIRI = APEUtils.createClassIRI(parentModule, ontologyPrefixIRI); if (allModules.get(parentModuleIRI) == null) { - log.warn("Tool '" + moduleIRI + "' annotation issue. " + log.debug("Tool '" + moduleIRI + "' annotation issue. " + "Referenced '" + ToolAnnotationTag.TAXONOMY_OPERATIONS.toString() + "': '" + parentModuleIRI + "' cannot be found in the Tool Taxonomy."); wrongToolTax.add(moduleLabel); @@ -363,7 +363,7 @@ public Optional updateModuleFromJson(JSONObject jsonModule) * used as a parent class of the tool. */ if (taxonomyParentModules.isEmpty()) { - log.warn("Tool '" + moduleIRI + "' annotation issue. " + log.debug("Tool '" + moduleIRI + "' annotation issue. " + "None of the referenced '" + ToolAnnotationTag.TAXONOMY_OPERATIONS.toString() + "' can be found in the Tool Taxonomy."); taxonomyParentModules.add(allModules.getRootModuleID()); @@ -384,13 +384,13 @@ public Optional updateModuleFromJson(JSONObject jsonModule) if (inputs.isEmpty() && outputs.isEmpty()) { emptyTools.add(moduleLabel); - log.debug("Operation '" + "' was not included as it has no (valid) inputs and outputs specified."); + log.debug("Operation '" + moduleLabel + "' was not included as it has no (valid) inputs and outputs specified."); return Optional.empty(); } } catch (APEDimensionsException badDimension) { wrongToolIO.add(moduleLabel); - log.warn("Operation '" + "' was not included." + badDimension.getMessage()); + log.debug("Operation '" + moduleLabel + "' was not included. " + badDimension.getMessage()); return Optional.empty(); } diff --git a/src/main/java/nl/uu/cs/ape/domain/BioToolsAPI.java b/src/main/java/nl/uu/cs/ape/domain/BioToolsAPI.java index b0d34fd..50e0620 100644 --- a/src/main/java/nl/uu/cs/ape/domain/BioToolsAPI.java +++ b/src/main/java/nl/uu/cs/ape/domain/BioToolsAPI.java @@ -264,6 +264,8 @@ public static JSONObject convertBioTools2Ape(JSONArray bioToolsAnnotation, boole Optional apeToolJson = convertSingleBioTool2Ape(toolName, toolID, biotoolsID, function, excludeBadAnnotation); if (apeToolJson.isPresent()) { + JSONObject implementation = new JSONObject().put("cwl_reference", "PATH_TO_CWL_FILE.cwl"); + apeToolJson.get().put("implementation", implementation); apeToolsAnnotations.put(apeToolJson.get()); bioToolFunctions++; functionNo++; diff --git a/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/ToolCWLCreator.java b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/ToolCWLCreator.java index 355ebf1..7580bcb 100644 --- a/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/ToolCWLCreator.java +++ b/src/main/java/nl/uu/cs/ape/solver/solutionStructure/cwl/ToolCWLCreator.java @@ -71,8 +71,8 @@ public String formatType(List list) { printString.append("\"").append(list.get(0).getPredicateLongLabel()).append("\" # ").append(list.get(0).getPredicateLabel()).append("\n"); } if (list.size() > 1) { - log.warn("Multiple types for the same input/output are not supported."); - printString.append(ind(2)).append("doc: The I/O is annotated with multiple data formats in bio.tools. We specified here the first one, while the rest are part of tool.json file. Please check the instructions on how to handle such cases: https://workflomics.readthedocs.io/en/domain-creation/developer-guide/domain-development.html#id2 "); + log.info("Multiple formats for the same input/output are not supported."); + printString.append(ind(2)).append("doc: The I/O is annotated with multiple data formats in bio.tools. We specified here the first one, while the rest are part of tool.json file. Please check the instructions on how to handle such cases: https://workflomics.readthedocs.io/en/latest/domain-expert-guide/domain-development.html"); } return printString.toString(); diff --git a/src/test/java/nl/uu/cs/ape/test/sat/ape/APEDomainSetupTest.java b/src/test/java/nl/uu/cs/ape/test/sat/ape/APEDomainSetupTest.java index e97bd19..0c7155b 100644 --- a/src/test/java/nl/uu/cs/ape/test/sat/ape/APEDomainSetupTest.java +++ b/src/test/java/nl/uu/cs/ape/test/sat/ape/APEDomainSetupTest.java @@ -1,7 +1,7 @@ package nl.uu.cs.ape.test.sat.ape; -import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.util.List; @@ -19,22 +19,29 @@ class APEDomainSetupTest { @Test void updateModuleFromJsonTest() throws IOException, OWLOntologyCreationException { - List toolIDs = List.of("comet"); + List toolIDs = List.of("Comet", "ape", "shic", "Jalview"); JSONObject toolAnnotationJson = BioToolsAPI.getAndConvertToolList(toolIDs); - JSONObject comet = toolAnnotationJson.getJSONArray("functions").getJSONObject(0); - APE apeFramework = new APE( - "https://raw.githubusercontent.com/Workflomics/tools-and-domains/refs/heads/main/domains/proteomics/config.json"); + for (int i = 0; i < toolIDs.size(); i++) { + String biotoolsID = toolIDs.get(i); + JSONObject toolJson = toolAnnotationJson.getJSONArray("functions").getJSONObject(i); - Module cometModule = apeFramework.getDomainSetup() - .updateModuleFromJson(comet).get(); + assertFalse(toolJson.isEmpty()); + APE apeFramework = new APE( + "https://raw.githubusercontent.com/Workflomics/tools-and-domains/refs/heads/main/domains/bio.tools/config.json"); - assertEquals("Comet", cometModule.getPredicateLabel()); + Module currModule = apeFramework.getDomainSetup() + .updateModuleFromJson(toolJson).get(); - ToolCWLCreator toolCWLCreator = new ToolCWLCreator(cometModule); - String cwlRepresentation = toolCWLCreator.generate(); - assertFalse(cwlRepresentation.isEmpty()); + assertTrue(toolIDs.stream() + .map(String::toLowerCase) + .anyMatch(id -> id.equals(currModule.getPredicateLabel().toLowerCase()))); + ToolCWLCreator toolCWLCreator = new ToolCWLCreator(currModule); + String cwlRepresentation = toolCWLCreator.generate(); + assertFalse(cwlRepresentation.isEmpty()); + + } } } From 6032f42404c6bdf666a229d9b5b4d1042aee0ea3 Mon Sep 17 00:00:00 2001 From: Vedran Kasalica Date: Sat, 19 Oct 2024 14:49:50 +0200 Subject: [PATCH 13/13] Remove quotation from the issue-template label --- .github/ISSUE_TEMPLATE/feature_request.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 3a2c469..9cd4331 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -2,7 +2,8 @@ name: Feature Request about: Suggest a new feature or enhancement for the APE library title: '' -labels: 'enhancement' +labels: enhancement + assignees: '' ---