From 55bbcb234c9dcc55850eec6d72eb49a2905ce4a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Javier=20Cavero=20L=C3=B3pez?= Date: Mon, 26 Jan 2026 18:02:42 +0100 Subject: [PATCH 1/4] feat: many-obj first implementation --- .vscode/settings.json | 3 + docker-compose.yml | 10 + engines/many-obj/.classpath | 58 ++ engines/many-obj/.gitignore | 1 + engines/many-obj/.project | 40 ++ .../org.eclipse.core.resources.prefs | 3 + .../.settings/org.eclipse.jdt.apt.core.prefs | 2 + .../.settings/org.eclipse.jdt.core.prefs | 12 + .../.settings/org.eclipse.m2e.core.prefs | 4 + ....eclipse.wst.common.project.facet.core.xml | 4 + engines/many-obj/Dockerfile | 13 + engines/many-obj/data/pruebatonta.txt | 111 ++++ engines/many-obj/pom.xml | 49 ++ .../qosawarewsbinding/AbstractWebService.java | 36 ++ .../es/us/isa/qosawarewsbinding/Branch.java | 140 +++++ .../CompositeStructuralComponent.java | 19 + .../qosawarewsbinding/ConcreteWebService.java | 53 ++ .../es/us/isa/qosawarewsbinding/Flow.java | 64 ++ .../es/us/isa/qosawarewsbinding/Loop.java | 98 +++ .../es/us/isa/qosawarewsbinding/Sequence.java | 92 +++ .../StructuralComponent.java | 17 + .../WSCompositionStructure.java | 234 ++++++++ .../isa/qosawarewsbinding/api/Controller.java | 359 +++++++++++ .../us/isa/qosawarewsbinding/api/Server.java | 17 + .../api/dto/SolveRequest.java | 76 +++ .../api/dto/SolveResponse.java | 13 + .../problem/BinaryOperator.java | 12 + .../qosawarewsbinding/problem/Constraint.java | 8 + .../problem/EvaluationCountProblem.java | 38 ++ .../problem/ExecutionPath.java | 76 +++ .../problem/ExecutionPathsBuilder.java | 16 + .../problem/FeasibilityAwareProblem.java | 46 ++ .../GlobalQoSWSCompositionConstraint.java | 113 ++++ .../LoopPeelingExecutionPathBuilder.java | 119 ++++ .../LoopUnfoldingExecutionPathsBuilder.java | 100 ++++ .../qosawarewsbinding/problem/Problem.java | 39 ++ .../problem/ProblemReaderAndWriter.java | 558 ++++++++++++++++++ .../problem/QoSAwareWSCompositionProblem.java | 333 +++++++++++ ...cesDespendenceWSCompositionConstraint.java | 47 ++ .../problem/UnfeasibilityPenalizator.java | 7 + .../problem/WSCompositionConstraint.java | 29 + .../problem/WSCompositionQoSModel.java | 168 ++++++ .../generator/AbstractProblemGenerator.java | 24 + .../problem/generator/ProblemGenerator.java | 7 + ...QoSAwareWSCompositionProblemGenerator.java | 381 ++++++++++++ .../model/GlobalQoSConstraintsModel.java | 45 ++ .../problem/model/ProblemModel.java | 5 + ...eWSCompositionProblemConstraintsModel.java | 39 ++ .../QoSAwareWSCompositionProblemModel.java | 62 ++ .../QoSAwareWSCompositionProblemQoSModel.java | 5 + ...CompositionProblemServicesMarketModel.java | 53 ++ ...reWSCompositionProblemStructuralModel.java | 81 +++ .../ServiceDependencesConstraintsModel.java | 14 + .../qosawarewsbinding/qos/QoSProperty.java | 67 +++ .../qos/QoSPropertyType.java | 12 + .../qos/aggretation/AggregationFunction.java | 19 + .../AverageAggregationFunction.java | 49 ++ .../aggretation/MaxAggregationFunction.java | 47 ++ .../MaxAverageAggregationFunction.java | 49 ++ .../aggretation/MinAggregationFunction.java | 50 ++ .../MinAverageAggregationFunction.java | 52 ++ .../NumericAggregationFunction.java | 42 ++ .../ProductoryAggregationFunction.java | 45 ++ .../ProductoryPowAggregationFunction.java | 44 ++ .../SumatoryAggregationFunction.java | 46 ++ .../SumatoryPowAggregationFunction.java | 44 ++ .../solution/AbstractSolution.java | 63 ++ .../QoSAwareWSCompositionSolution.java | 60 ++ .../qosawarewsbinding/solution/Solution.java | 8 + .../QoSAwareWSCompositionProblemInteger.java | 184 ++++++ .../QoSAwareWSCompositionVectorMovement.java | 99 ++++ .../QoSAwareWSCompositionVectorSolution.java | 96 +++ ...eWSCompositionVectorSolutionNavigable.java | 119 ++++ .../qosawarewsbinding/util/BoundedDomain.java | 72 +++ ...dedDoubleGaussianDistributionFunction.java | 54 ++ .../util/DistributionFunction.java | 14 + .../us/isa/qosawarewsbinding/util/Domain.java | 11 + .../DoubleGaussianDistributionFunction.java | 55 ++ .../DoubleUniformDistributionFunction.java | 51 ++ .../IntegerGausssianDistributionFunction.java | 55 ++ .../IntegerUniformDistributionFunction.java | 50 ++ .../util/IntensionDomain.java | 16 + .../util/MyStringTokenizer.java | 70 +++ engines/minizinc-csp/model/composition.mzn | 2 +- engines/minizinc-csp/src/solver.ts | 2 +- examples/common_valid_instance.json | 205 +++++++ examples/constraints-demo.json | 155 ++++- examples/constraints-global-strict.json | 159 ++++- examples/constraints-infeasible.json | 107 +++- examples/constraints-same-provider.json | 163 ++++- examples/many-obj-example.json | 216 +++++++ examples/many_obj_valid_instance.json | 167 ++++++ examples/minimal-1task.json | 59 +- examples/structured-seq-andpar-xor.json | 65 +- examples/validation-engine-disconnected.json | 131 ++-- examples/validation-gateway-duplicate.json | 131 ++-- .../validation-gateway-specialization.json | 68 ++- examples/variation-objective-cost.json | 351 +++++------ examples/variation-objective-time.json | 351 +++++------ frontend/src/App.tsx | 42 +- frontend/src/schemas/universal.json | 40 +- frontend/test_debug.cjs | 35 ++ openbinding-gateway/.env.example | 4 + openbinding-gateway/API_CHANGES.md | 46 ++ openbinding-gateway/pyproject.toml | 3 +- .../src/openbinding_gateway/jobs.py | 4 +- .../src/openbinding_gateway/main.py | 31 +- .../src/openbinding_gateway/models/api.py | 46 +- .../openbinding_gateway/registry/engine.py | 6 +- .../src/openbinding_gateway/routing/router.py | 114 +++- .../validation/engine_plugins/base.py | 14 +- .../validation/engine_plugins/many_obj.py | 471 +++++++++++++++ .../validation/engine_plugins/minizinc_csp.py | 195 +++++- .../validation/semantic_universal.py | 2 +- schemas/specializations/many-obj.schema.json | 139 +++++ .../specializations/minizinc-csp.schema.json | 4 +- schemas/universal/schema.json | 38 +- schemas/universal/schema.specification.md | 75 +-- tests/test_many_obj_request.py | 37 ++ 119 files changed, 8377 insertions(+), 897 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 engines/many-obj/.classpath create mode 100644 engines/many-obj/.gitignore create mode 100644 engines/many-obj/.project create mode 100644 engines/many-obj/.settings/org.eclipse.core.resources.prefs create mode 100644 engines/many-obj/.settings/org.eclipse.jdt.apt.core.prefs create mode 100644 engines/many-obj/.settings/org.eclipse.jdt.core.prefs create mode 100644 engines/many-obj/.settings/org.eclipse.m2e.core.prefs create mode 100644 engines/many-obj/.settings/org.eclipse.wst.common.project.facet.core.xml create mode 100644 engines/many-obj/Dockerfile create mode 100644 engines/many-obj/data/pruebatonta.txt create mode 100644 engines/many-obj/pom.xml create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/AbstractWebService.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/Branch.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/CompositeStructuralComponent.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/ConcreteWebService.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/Flow.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/Loop.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/Sequence.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/StructuralComponent.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/WSCompositionStructure.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/api/Controller.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/api/Server.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/api/dto/SolveRequest.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/api/dto/SolveResponse.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/BinaryOperator.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/Constraint.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/EvaluationCountProblem.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/ExecutionPath.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/ExecutionPathsBuilder.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/FeasibilityAwareProblem.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/GlobalQoSWSCompositionConstraint.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/LoopPeelingExecutionPathBuilder.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/LoopUnfoldingExecutionPathsBuilder.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/Problem.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/ProblemReaderAndWriter.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/QoSAwareWSCompositionProblem.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/ServicesDespendenceWSCompositionConstraint.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/UnfeasibilityPenalizator.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/WSCompositionConstraint.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/WSCompositionQoSModel.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/generator/AbstractProblemGenerator.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/generator/ProblemGenerator.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/generator/QoSAwareWSCompositionProblemGenerator.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/GlobalQoSConstraintsModel.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/ProblemModel.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/QoSAwareWSCompositionProblemConstraintsModel.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/QoSAwareWSCompositionProblemModel.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/QoSAwareWSCompositionProblemQoSModel.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/QoSAwareWSCompositionProblemServicesMarketModel.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/QoSAwareWSCompositionProblemStructuralModel.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/ServiceDependencesConstraintsModel.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/QoSProperty.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/QoSPropertyType.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/AggregationFunction.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/AverageAggregationFunction.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/MaxAggregationFunction.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/MaxAverageAggregationFunction.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/MinAggregationFunction.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/MinAverageAggregationFunction.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/NumericAggregationFunction.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/ProductoryAggregationFunction.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/ProductoryPowAggregationFunction.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/SumatoryAggregationFunction.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/SumatoryPowAggregationFunction.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/AbstractSolution.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/QoSAwareWSCompositionSolution.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/Solution.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/vector/QoSAwareWSCompositionProblemInteger.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/vector/QoSAwareWSCompositionVectorMovement.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/vector/QoSAwareWSCompositionVectorSolution.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/vector/QoSAwareWSCompositionVectorSolutionNavigable.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/BoundedDomain.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/BoundedDoubleGaussianDistributionFunction.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/DistributionFunction.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/Domain.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/DoubleGaussianDistributionFunction.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/DoubleUniformDistributionFunction.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/IntegerGausssianDistributionFunction.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/IntegerUniformDistributionFunction.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/IntensionDomain.java create mode 100644 engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/MyStringTokenizer.java create mode 100644 examples/common_valid_instance.json create mode 100644 examples/many-obj-example.json create mode 100644 examples/many_obj_valid_instance.json create mode 100644 frontend/test_debug.cjs create mode 100644 openbinding-gateway/.env.example create mode 100644 openbinding-gateway/API_CHANGES.md create mode 100644 openbinding-gateway/src/openbinding_gateway/validation/engine_plugins/many_obj.py create mode 100644 schemas/specializations/many-obj.schema.json create mode 100644 tests/test_many_obj_request.py diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..c5f3f6b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.configuration.updateBuildConfiguration": "interactive" +} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index e019a74..0a45278 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,8 +12,11 @@ services: environment: - UNIVERSAL_SCHEMA_PATH=/app/schemas/universal/schema.json - SCHEMAS_DIR=/app/schemas + - ENGINE_MINIZINC_URL=http://engine-minizinc:3000 + - ENGINE_MANY_OBJ_URL=http://engine-many-obj:8080 depends_on: - engine-minizinc + - engine-many-obj engine-minizinc: build: @@ -22,6 +25,13 @@ services: ports: - "3000:3000" + engine-many-obj: + build: + context: ./engines/many-obj + dockerfile: Dockerfile + ports: + - "8081:8080" + frontend: build: context: ./frontend diff --git a/engines/many-obj/.classpath b/engines/many-obj/.classpath new file mode 100644 index 0000000..18c4786 --- /dev/null +++ b/engines/many-obj/.classpath @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/engines/many-obj/.gitignore b/engines/many-obj/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/engines/many-obj/.gitignore @@ -0,0 +1 @@ +/target diff --git a/engines/many-obj/.project b/engines/many-obj/.project new file mode 100644 index 0000000..92ec78a --- /dev/null +++ b/engines/many-obj/.project @@ -0,0 +1,40 @@ + + + ManyObjectivesQoSawareCWSBinding + + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.wst.common.project.facet.core.nature + + + + 1768938301184 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + + diff --git a/engines/many-obj/.settings/org.eclipse.core.resources.prefs b/engines/many-obj/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..3622a30 --- /dev/null +++ b/engines/many-obj/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +encoding//src/main/java=ISO-8859-1 +encoding/=ISO-8859-1 diff --git a/engines/many-obj/.settings/org.eclipse.jdt.apt.core.prefs b/engines/many-obj/.settings/org.eclipse.jdt.apt.core.prefs new file mode 100644 index 0000000..d4313d4 --- /dev/null +++ b/engines/many-obj/.settings/org.eclipse.jdt.apt.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.apt.aptEnabled=false diff --git a/engines/many-obj/.settings/org.eclipse.jdt.core.prefs b/engines/many-obj/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..6a09005 --- /dev/null +++ b/engines/many-obj/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.processAnnotations=disabled +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.7 diff --git a/engines/many-obj/.settings/org.eclipse.m2e.core.prefs b/engines/many-obj/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/engines/many-obj/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/engines/many-obj/.settings/org.eclipse.wst.common.project.facet.core.xml b/engines/many-obj/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 0000000..bc0009a --- /dev/null +++ b/engines/many-obj/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,4 @@ + + + + diff --git a/engines/many-obj/Dockerfile b/engines/many-obj/Dockerfile new file mode 100644 index 0000000..1f72564 --- /dev/null +++ b/engines/many-obj/Dockerfile @@ -0,0 +1,13 @@ +FROM maven:3.8-openjdk-8 as builder +WORKDIR /app +COPY pom.xml . +COPY src ./src +# COPY lib ./lib # No lib present or empty +RUN mvn package -DskipTests + +FROM eclipse-temurin:8-jre +WORKDIR /app +COPY --from=builder /app/target/ManyObjectivesQoSawareCWSBinding-0.0.1-SNAPSHOT.jar app.jar +COPY --from=builder /app/target/dependency /app/dependency +EXPOSE 8080 +CMD ["java", "-cp", "app.jar:dependency/*", "es.us.isa.qosawarewsbinding.api.Server"] diff --git a/engines/many-obj/data/pruebatonta.txt b/engines/many-obj/data/pruebatonta.txt new file mode 100644 index 0000000..64f9bac --- /dev/null +++ b/engines/many-obj/data/pruebatonta.txt @@ -0,0 +1,111 @@ +%#============================= HEADER ======================================# +% This file contains an instance of the QoS-Aware Web Services Composition Problem +% FILE: pruebatonta.txt +% Created by: José Antonio Parejo Mestre +% Thu Mar 27 12:58:42 CET 2014 +% ---------------------- +% Problem Statistics: +% ---------------------- +% Number of activities: 4 +% Number of Candidate Services: 9 +% Number of Constraints: 0 +%#======================= COMPOSITION STRUCTURE =============================# +% Abstract Services: +%---------------------- +2 +t2 +t1 +% CompositionStructure: +%---------------------- +SEC[ + + BRANCH(0.6;0.4;)[ + SEC[t1, + ] + , + SEC[ + + LOOP(4000)[t2, + ] + , + ] + , + ] +, +] +%#======================= QOS MODEL =============================# +QoSModel{ + Properties{ + Availability:POSITIVE€Double[0.0,1.0] + Security:POSITIVE€Double[0.0,1.0] + ExecTime:NEGATIVE€Double[0.0,1.0] + Cost:NEGATIVE€Double[0.0,1.0] + Reliability:POSITIVE€Double[0.0,1.0] + } + AggregationFunctions( + Availability{ + Loop:PRODUCT + Branch:SUM + Flow:PRODUCT + Sequence:PRODUCT + } + Security{ + Loop:MIN + Branch:SUM + Flow:MIN + Sequence:MIN + } + ExecTime{ + Loop:SUM + Branch:SUM + Flow:MAX + Sequence:SUM + } + Cost{ + Loop:SUM + Branch:SUM + Flow:SUM + Sequence:SUM + } + Reliability{ + Loop:PRODUCT + Branch:SUM + Flow:PRODUCT + Sequence:PRODUCT + } + ) + Weights( + Availability:0.2 + Security:0.1 + ExecTime:0.2 + Cost:0.3 + Reliability:0.2 + ) +} +%#======================= CANDIDATE SERVICES =============================# +------------------------ +t2 +------------------------ +s23(Availability:0.5999999999999999,Security:0.24999999999999994,ExecTime:0.6666666666666666,Cost:0.7499999999999999,Reliability:0.0,) +s22(Availability:0.0,Security:1.0,ExecTime:0.0,Cost:1.0,Reliability:0.0,) +s21(Availability:0.0,Security:1.0,ExecTime:1.0,Cost:0.0,Reliability:1.0,) +------------------------ +t4 +------------------------ +s42(Availability:1.0,Security:0.0,ExecTime:0.33333333333333337,Cost:0.8749999999999999,Reliability:0.0,) +s41(Availability:0.0,Security:1.0,ExecTime:1.0,Cost:0.0,Reliability:1.0,) +------------------------ +t1 +------------------------ +s12(Availability:0.8,Security:1.0,ExecTime:0.8666666666666666,Cost:0.625,Reliability:0.0,) +s11(Availability:0.0,Security:1.0,ExecTime:0.0,Cost:1.0,Reliability:0.0,) +------------------------ +t3 +------------------------ +s32(Availability:1.0,Security:0.0,ExecTime:0.33333333333333337,Cost:0.8749999999999999,Reliability:0.0,) +s31(Availability:0.0,Security:1.0,ExecTime:1.0,Cost:0.0,Reliability:1.0,) +------------------------ +%#======================= CONSTRAINTS =============================# +0 +% ---------------------- +% ---------------------- diff --git a/engines/many-obj/pom.xml b/engines/many-obj/pom.xml new file mode 100644 index 0000000..e8233bc --- /dev/null +++ b/engines/many-obj/pom.xml @@ -0,0 +1,49 @@ + + 4.0.0 + es.us.isa + ManyObjectivesQoSawareCWSBinding + 0.0.1-SNAPSHOT + + ISO-8859-1 + + + + commons-math + commons-math + 1.2 + + + com.google.code.gson + gson + 2.8.9 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.7 + 1.7 + + + + org.apache.maven.plugins + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/dependency + + + + + + + \ No newline at end of file diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/AbstractWebService.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/AbstractWebService.java new file mode 100644 index 0000000..0492e02 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/AbstractWebService.java @@ -0,0 +1,36 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding; + +import java.io.Serializable; + +/** + * + * @author japarejo + */ +public class AbstractWebService implements StructuralComponent, Serializable { + private String name; + public AbstractWebService(String name) + { + this.name=name; + } + + @Override + public String toString() + { + return name; + } + + + public String toStructuralString(String prefix) { + return prefix+name; + } + + public boolean isEmpty() { + return false; + } + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/Branch.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/Branch.java new file mode 100644 index 0000000..be05462 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/Branch.java @@ -0,0 +1,140 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +/** + * + * @author japarejo + */ +public class Branch implements CompositeStructuralComponent { + + protected Map branches; + protected List subComponents; + public Branch() + { + branches=new HashMap(); + subComponents=new LinkedList(); + } + + + public List getSubComponents() { + return subComponents; + } + + public void addBranch(StructuralComponent body, Double probability) + { + /*double scalingFactor=1.0/(1.0+probability.doubleValue()); + Double auxProbability=null; + for(StructuralComponent branch:branches.keySet()) + { + auxProbability=branches.get(branch); + branches.put(branch,auxProbability.doubleValue()*scalingFactor); + } + if(subComponents.size()==0) + branches.put(body,1.0); + else*/ + branches.put(body, probability); + subComponents.add(body); + } + + public void removeBrach(StructuralComponent body) + { + if(hasBranch(body)) + { + Double probability=branches.get(body); + branches.remove(body); + subComponents.remove(body); + if(probability.doubleValue()!=1.0) + { + double scalingFactor=1.0/(1.0-probability.doubleValue()); + for(StructuralComponent branch:branches.keySet()) + { + probability=branches.get(branch); + branches.put(branch,probability.doubleValue()*scalingFactor); + } + } + } + } + + public int numberOfBranches() + { + return subComponents.size(); + } + + private boolean hasBranch(StructuralComponent body) { + return subComponents.contains(body); + } + + + public Double getBranchProbability(StructuralComponent body) + { + Double result=new Double(0); + if(hasBranch(body)) + result=branches.get(body); + return result; + } + + + public Double getPonderation(StructuralComponent subcomponent) { + return getBranchProbability(subcomponent); + } + + + public String toStructuralString(String prefix) { + String newline = System.getProperty("line.separator"); + StringBuffer buffer=new StringBuffer(prefix+"BRANCH("); + for(StructuralComponent subComponent:subComponents) + buffer.append(branches.get(subComponent)+";"); + buffer.append(")["+newline); + String myprefix=prefix+" "; + for(StructuralComponent subComponent:subComponents) + buffer.append(subComponent.toStructuralString(myprefix)+newline+prefix+","+newline); + buffer.append(prefix+"]"); + return buffer.toString(); + } + + @Override + public String toString() + { + return toStructuralString(""); + } + + + public boolean isEmpty() { + boolean result=true; + for(StructuralComponent branch:subComponents){ + if(!branch.isEmpty()){ + result=false; + break; + } + } + return result; + } + + /*@Override + public void buildEvaluationMap(Map, Double> evaluationMap, Double currentValue) { + StructuralComponent component=null; + double probability=0; + for(String branchname:branches.keySet()) + { + component=branches.get(branchname); + probability=probabilities.get(branchname); + if(component instanceof CompositeStructuralComponent) + ((CompositeStructuralComponent)component).buildEvaluationMap(evaluationMap, probability*currentValue.doubleValue()); + else{ + List services=new ArrayList(1); + services.add((AbstractWebService)component); + evaluationMap.put(services,currentValue); + } + } + }*/ + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/CompositeStructuralComponent.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/CompositeStructuralComponent.java new file mode 100644 index 0000000..662d435 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/CompositeStructuralComponent.java @@ -0,0 +1,19 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding; + +import java.util.List; + +/** + * + * @author japarejo + */ +public interface CompositeStructuralComponent extends StructuralComponent { + + public List getSubComponents(); + public Double getPonderation(StructuralComponent subcomponent); + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/ConcreteWebService.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/ConcreteWebService.java new file mode 100644 index 0000000..85403fe --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/ConcreteWebService.java @@ -0,0 +1,53 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import es.us.isa.qosawarewsbinding.qos.QoSProperty; + +/** + * + * @author japarejo + */ +public class ConcreteWebService implements Serializable { + private String name; + private AbstractWebService abstractWebService; + protected Map qosmodel; + + + public ConcreteWebService(String name, AbstractWebService aws) + { + this.name=name; + this.abstractWebService=aws; + qosmodel=new HashMap(); + } + + public Object getQoSValue(QoSProperty property){ + return qosmodel.get(property); + } + + public void setQoSValue(QoSProperty property, Object value){ + qosmodel.put(property, value); + } + + public String getName() { + return name; + } + + public AbstractWebService getAbstractWebService() { + return abstractWebService; + } + + @Override + public String toString() + { + return name; + } + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/Flow.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/Flow.java new file mode 100644 index 0000000..fb136e2 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/Flow.java @@ -0,0 +1,64 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding; + +import java.util.List; + +/** + * + * @author japarejo + */ +public class Flow implements CompositeStructuralComponent { + + private List subcomponents; + + + public List getSubComponents() { + return subcomponents; + } + + + public Double getPonderation(StructuralComponent subcomponent) { + return 1.0; + } + + + public String toStructuralString(String prefix) { + String newline = System.getProperty("line.separator"); + StringBuffer buffer=new StringBuffer(prefix+"FLOW["+newline); + String myprefix=prefix+" ||=>"; + for(StructuralComponent subComponent:subcomponents) + buffer.append(subComponent.toStructuralString(myprefix)+","); + buffer.append("]"); + return buffer.toString(); + } + + public boolean isEmpty() { + boolean result=true; + for(StructuralComponent branch:subcomponents){ + if(!branch.isEmpty()){ + result=false; + break; + } + } + return result; + } + + /*@Override + public void buildEvaluationMap(Map, Double> evaluationMap, Double currentValue) { + List services=new LinkedList(); + for(StructuralComponent component:subcomponents) + { + if(component instanceof AbstractWebService) + { + services.add((AbstractWebService)component); + }else + ((CompositeStructuralComponent)component).buildEvaluationMap(evaluationMap,currentValue); + } + if(services.size()>0) + evaluationMap.put(services, currentValue); + }*/ +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/Loop.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/Loop.java new file mode 100644 index 0000000..04c7b56 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/Loop.java @@ -0,0 +1,98 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding; + +import java.util.LinkedList; +import java.util.List; + +/** + * + * @author japarejo + */ +public class Loop implements CompositeStructuralComponent { + + private int averageNumberOfIterations; + protected List subComponents; + public Loop(int averageNumberOfIterations) + { + this(averageNumberOfIterations,null); + } + public Loop(int averageNumberOfIterations, StructuralComponent component){ + this.averageNumberOfIterations=averageNumberOfIterations; + subComponents=new LinkedList(); + if(component!=null) + subComponents.add(component); + } + + + public List getSubComponents() { + return subComponents; + } + + public int getAverageNumberOfIterations() { + return averageNumberOfIterations; + } + + public void setAverageNumberOfIterations(int averageNumberOfIterations) { + this.averageNumberOfIterations = averageNumberOfIterations; + } + + + public Double getPonderation(StructuralComponent subcomponent) { + return (double)averageNumberOfIterations; + } + + + public String toStructuralString(String prefix) { + String newline = System.getProperty("line.separator"); + StringBuffer buffer=new StringBuffer(prefix+"LOOP("+averageNumberOfIterations+")["); + String myprefix=prefix+" "; + if(subComponents.size()>0) + { + if(!(subComponents.get(0) instanceof AbstractWebService)) + buffer.append(newline); + } + for(StructuralComponent subComponent:subComponents){ + if(subComponent instanceof CompositeStructuralComponent) + buffer.append(newline+subComponent.toStructuralString(myprefix)+newline+prefix+","); + else + buffer.append(subComponent.toStructuralString("")+","); + } + buffer.append(newline+prefix+"]"); + return buffer.toString(); + } + + public boolean isEmpty() { + boolean result=true; + for(StructuralComponent branch:subComponents){ + if(!branch.isEmpty()){ + result=false; + break; + } + } + return result; + } + + /*@Override + public void buildEvaluationMap(Map, Double> evaluationMap, Double currentValue) { + List services=new LinkedList(); + for(StructuralComponent component:subComponents) + { + if(component instanceof AbstractWebService) + { + services.add((AbstractWebService)component); + }else + ((CompositeStructuralComponent)component).buildEvaluationMap(evaluationMap,currentValue*averageNumberOfIterations); + } + if(services.size()>0) + evaluationMap.put(services, currentValue*averageNumberOfIterations); + }*/ + @Override + public String toString() + { + return toStructuralString(""); + } +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/Sequence.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/Sequence.java new file mode 100644 index 0000000..25d4636 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/Sequence.java @@ -0,0 +1,92 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding; + +import java.util.LinkedList; +import java.util.List; + +/** + * + * @author japarejo + */ +public class Sequence implements CompositeStructuralComponent { + protected List subComponents; + public Sequence() + { + subComponents=new LinkedList(); + } + + + public List getSubComponents() { + return subComponents; + } + /* + @Override + public void buildEvaluationMap(Map, Double> evaluationMap, Double currentValue) { + List services=new LinkedList(); + for(StructuralComponent component:subComponents) + { + if(component instanceof AbstractWebService) + { + services.add((AbstractWebService)component); + }else + ((CompositeStructuralComponent)component).buildEvaluationMap(evaluationMap,currentValue); + } + if(services.size()>0) + evaluationMap.put(services, currentValue); + }*/ + + + public Double getPonderation(StructuralComponent subcomponent) { + return 1.0; + } + + @Override + public String toString() + { + StringBuffer buffer=new StringBuffer("Sec["); + for(StructuralComponent subComponent:subComponents) + buffer.append(subComponent.toString()+","); + buffer.append("]"); + return buffer.toString(); + } + + + public String toStructuralString(String prefix) { + StringBuffer buffer=new StringBuffer(prefix+"SEC["); + String newline = System.getProperty("line.separator"); + String myprefix=prefix+" "; + if(subComponents.size()>0) + { + if(!(subComponents.get(0) instanceof AbstractWebService)) + buffer.append(newline); + } + boolean newlinegenerated=false; + for(StructuralComponent subComponent:subComponents) + if(subComponent instanceof CompositeStructuralComponent){ + buffer.append(newline+subComponent.toStructuralString(myprefix)+newline+prefix+","); + newlinegenerated=true; + }else + buffer.append(subComponent.toStructuralString("")+","); + buffer.append(newline+prefix+"]"); + return buffer.toString(); + } + + + public boolean isEmpty() { + boolean result=true; + for(StructuralComponent branch:subComponents){ + if(!branch.isEmpty()){ + result=false; + break; + } + } + return result; + } + + + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/StructuralComponent.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/StructuralComponent.java new file mode 100644 index 0000000..8a66d54 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/StructuralComponent.java @@ -0,0 +1,17 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding; + +import java.io.Serializable; + +/** + * + * @author japarejo + */ +public interface StructuralComponent extends Serializable { + public String toStructuralString(String prefix); + public boolean isEmpty(); +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/WSCompositionStructure.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/WSCompositionStructure.java new file mode 100644 index 0000000..230e21b --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/WSCompositionStructure.java @@ -0,0 +1,234 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding; + +import java.io.Serializable; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +/** + * + * @author japarejo + */ +public class WSCompositionStructure implements Serializable{ + protected Set components; + protected StructuralComponent structure; + protected double numberOfexecutedTasks; + + public WSCompositionStructure(StructuralComponent structure) + { + this.structure=structure; + components=new HashSet(); + createComponents(); + numberOfexecutedTasks=numberOfExecutedTasks(structure); + } + + public Set getComponents() { + return components; + } + + public StructuralComponent getStructure() { + return structure; + } + + public int maxNestingLevel() { + return computeMaxNestingLevel(structure); + } + + private int NBuildingBlocks(Class aClass, StructuralComponent structure) { + int result=0; + if(structure instanceof CompositeStructuralComponent) + { + CompositeStructuralComponent compositeComponent=(CompositeStructuralComponent)structure; + for(StructuralComponent subComponent:compositeComponent.getSubComponents()) + { + result+=NBuildingBlocks(aClass, subComponent); + } + if(structure.getClass().equals(aClass)) + result++; + } + return result; + } + + private void addComponent(StructuralComponent structure) { + if(structure instanceof AbstractWebService) + components.add((AbstractWebService) structure); + else{ + Collection subcomponents=((CompositeStructuralComponent)structure).getSubComponents(); + for(StructuralComponent subcomponent:subcomponents) + addComponent(subcomponent); + } + } + + private int computeMaxNestingLevel(StructuralComponent structure) { + int result=0; + int auxNestingLevel; + if(structure instanceof CompositeStructuralComponent) + { + result=1; + CompositeStructuralComponent compositeComponent=(CompositeStructuralComponent)structure; + for(StructuralComponent subComponent:compositeComponent.getSubComponents()) + { + if(subComponent instanceof Sequence) + auxNestingLevel=computeMaxNestingLevel(subComponent); + else + auxNestingLevel=1+computeMaxNestingLevel(subComponent); + if(auxNestingLevel>result) + result=auxNestingLevel; + } + } + return result; + } + + private void createComponents() { + addComponent(structure); + } + + public int computeCyclomaticComplexity() + { + return computeCyclomaticComplexity(structure)+1; + } + + public int computeMaxNesting() + { + return computeMaxNestingLevel(structure); + } + + public int numberOfActivities() + { + return numberOfActivities(structure); + } + + private int computeCyclomaticComplexity(StructuralComponent component) + { + int result=0; + if(component instanceof CompositeStructuralComponent) + { + CompositeStructuralComponent compositeComponent=(CompositeStructuralComponent)component; + if(compositeComponent instanceof Loop){ + result=1; + for(StructuralComponent subComponent:compositeComponent.getSubComponents()) + { + result+=computeCyclomaticComplexity(subComponent); + } + }else if(compositeComponent instanceof Branch){ + result=compositeComponent.getSubComponents().size()-1; + for(StructuralComponent subComponent:compositeComponent.getSubComponents()) + { + result+=computeCyclomaticComplexity(subComponent); + } + }else if(compositeComponent instanceof Flow){ + result=compositeComponent.getSubComponents().size()-1; + for(StructuralComponent subComponent:compositeComponent.getSubComponents()) + { + result+=computeCyclomaticComplexity(subComponent); + } + }else if(component instanceof Sequence){ + for(StructuralComponent subComponent:compositeComponent.getSubComponents()) + { + result+=computeCyclomaticComplexity(subComponent); + } + } + } + return result; + } + + private int numberOfActivities(StructuralComponent structure) { + int result=1; + if(structure instanceof CompositeStructuralComponent) + { + CompositeStructuralComponent compositeComponent=(CompositeStructuralComponent)structure; + for(StructuralComponent subComponent:compositeComponent.getSubComponents()) + { + result+=numberOfActivities(subComponent); + } + if(structure instanceof Sequence) + result=result-1; + if(structure instanceof Flow) + result=result-1; + } + return result; + } + + private double numberOfExecutedTasks(StructuralComponent structure) { + double result=0; + if(structure instanceof CompositeStructuralComponent) + { + CompositeStructuralComponent compositeComponent=(CompositeStructuralComponent)structure; + for(StructuralComponent subComponent:compositeComponent.getSubComponents()) + { + if(subComponent instanceof AbstractWebService) + result+=compositeComponent.getPonderation(subComponent); + else + result+=numberOfExecutedTasks(subComponent)*compositeComponent.getPonderation(subComponent); + } + }else + result=1; + return result; + } + + private int numberOfTaskActivities(StructuralComponent structure) + { + int result=0; + if(structure instanceof CompositeStructuralComponent) + { + CompositeStructuralComponent compositeComponent=(CompositeStructuralComponent)structure; + for(StructuralComponent subComponent:compositeComponent.getSubComponents()) + { + if(subComponent instanceof CompositeStructuralComponent) + result+=numberOfTaskActivities(subComponent); + else + result++; + } + }else{ + result=1; + } + return result; + } + + public double perecentageOfControlFlowActivities() + { + double percentageOfTaskActivities=((double)(numberOfTaskActivities(structure)))/((double)(numberOfActivities(structure))); + return 1.0 - percentageOfTaskActivities; + } + + public double numberOfExecutedTasks() + { + if(numberOfexecutedTasks==Double.MIN_VALUE) + numberOfexecutedTasks=numberOfExecutedTasks(structure); + return numberOfexecutedTasks; + } + + public double percentageOfLoops() + { + double result=0; + double nloops=(double)NBuildingBlocks(Loop.class, structure); + result=nloops/((double)(numberOfActivities(structure)-numberOfTaskActivities(structure))); + return result; + } + public double averageIterationsPerLoop() + { + double nloops=(double)NBuildingBlocks(Loop.class, structure); + double nTotalIterations=(double)NtotalIterations(structure); + return nTotalIterations/nloops; + } + public double NtotalIterations(StructuralComponent structure) + { + double result=0; + if(structure instanceof CompositeStructuralComponent) + { + CompositeStructuralComponent compositeComponent=(CompositeStructuralComponent)structure; + for(StructuralComponent subComponent:compositeComponent.getSubComponents()) + { + result+=NtotalIterations(subComponent); + } + if(structure instanceof Loop) + result+=((Loop)structure).getAverageNumberOfIterations(); + } + return result; + } +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/api/Controller.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/api/Controller.java new file mode 100644 index 0000000..c101f6f --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/api/Controller.java @@ -0,0 +1,359 @@ +package es.us.isa.qosawarewsbinding.api; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import es.us.isa.qosawarewsbinding.AbstractWebService; +import es.us.isa.qosawarewsbinding.ConcreteWebService; +import es.us.isa.qosawarewsbinding.StructuralComponent; +import es.us.isa.qosawarewsbinding.WSCompositionStructure; +import es.us.isa.qosawarewsbinding.api.dto.SolveRequest; +import es.us.isa.qosawarewsbinding.api.dto.SolveResponse; +import es.us.isa.qosawarewsbinding.problem.QoSAwareWSCompositionProblem; +import es.us.isa.qosawarewsbinding.problem.WSCompositionQoSModel; +import es.us.isa.qosawarewsbinding.problem.GlobalQoSWSCompositionConstraint; +import es.us.isa.qosawarewsbinding.problem.BinaryOperator; +import es.us.isa.qosawarewsbinding.qos.QoSProperty; +import es.us.isa.qosawarewsbinding.qos.QoSPropertyType; +import es.us.isa.qosawarewsbinding.qos.aggretation.*; +import es.us.isa.qosawarewsbinding.solution.QoSAwareWSCompositionSolution; +import es.us.isa.qosawarewsbinding.solution.vector.*; +import es.us.isa.qosawarewsbinding.*; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.util.*; + +public class Controller implements HttpHandler { + private Gson gson = new Gson(); + + @Override + public void handle(HttpExchange exchange) throws IOException { + if (!"POST".equalsIgnoreCase(exchange.getRequestMethod())) { + exchange.sendResponseHeaders(405, -1); + return; + } + + try { + SolveRequest req = gson.fromJson(new InputStreamReader(exchange.getRequestBody()), SolveRequest.class); + SolveResponse resp = process(req); + + String jsonResp = gson.toJson(resp); + exchange.getResponseHeaders().set("Content-Type", "application/json"); + exchange.sendResponseHeaders(200, jsonResp.length()); + OutputStream os = exchange.getResponseBody(); + os.write(jsonResp.getBytes()); + os.close(); + } catch (Exception e) { + e.printStackTrace(); + String error = "{\"error\": \"" + e.getMessage() + "\"}"; + exchange.sendResponseHeaders(500, error.length()); + OutputStream os = exchange.getResponseBody(); + os.write(error.getBytes()); + os.close(); + } + } + + private SolveResponse process(SolveRequest req) { + // 1. Map Structure + Map taskMap = new HashMap(); + StructuralComponent root = mapNode(req.composition.root, taskMap); + WSCompositionStructure structure = new WSCompositionStructure(root); + + // 2. Map QoS Model + Map> propertyMap = new HashMap>(); + Set qosProperties = new HashSet(); + + for (Map.Entry entry : req.features.properties.entrySet()) { + QoSPropertyType type = "maximize".equals(entry.getValue().direction) ? QoSPropertyType.POSITIVE + : QoSPropertyType.NEGATIVE; + // Assuming 0.0-1.0 domain for normalization + QoSProperty prop = new QoSProperty(entry.getKey(), + new es.us.isa.qosawarewsbinding.util.BoundedDomain(0.0, 1.0), type); + qosProperties.add(prop); + propertyMap.put(entry.getKey(), prop); + } + WSCompositionQoSModel qosModel = new WSCompositionQoSModel(qosProperties); + + // Map weights + Map weights = new HashMap(); + for (Map.Entry entry : req.features.weights.entrySet()) { + weights.put(propertyMap.get(entry.getKey()), entry.getValue()); + } + qosModel.setQosPropertiesWeights(weights); + + // Map aggregation functions + for (Map.Entry entry : req.features.aggregation.entrySet()) { + QoSProperty prop = propertyMap.get(entry.getKey()); + SolveRequest.AggregationPolicy policy = entry.getValue(); + + qosModel.setAggregationFunction(prop, Sequence.class, getAggFunc(policy.seq)); + qosModel.setAggregationFunction(prop, Flow.class, getAggFunc(policy.flow)); + qosModel.setAggregationFunction(prop, Branch.class, getAggFunc(policy.branch)); + qosModel.setAggregationFunction(prop, Loop.class, getAggFunc(policy.loop)); + } + + // 3. Map Market + Map> market = new HashMap>(); + // Need to find all AbstractWebServices (Tasks) in structure + + // collectTasks called during mapping + + for (Map.Entry entry : taskMap.entrySet()) { + String taskId = entry.getKey(); + AbstractWebService aws = entry.getValue(); + Set candidates = new HashSet(); + + SolveRequest.ServiceCandidates sc = req.market.get(taskId); + if (sc != null && sc.services != null) { + for (SolveRequest.Service s : sc.services) { + ConcreteWebService cws = new ConcreteWebService(s.id, aws); + + // Iterate over all expected properties to ensure completeness + for (QoSProperty p : propertyMap.values()) { + Double val = s.features.get(p.getName()); + if (val == null) { + // Assign default based on type + if (p.getType() == QoSPropertyType.POSITIVE) { + val = 0.0; + } else { + // For minimization, we'd ideally want a "bad" value. + // But Double.MAX_VALUE might skew normalization too much. + // Let's use a reasonably high value or 0 if that's safer for now, + // but for robustness, 999999.0 is a placeholder "bad" value. + val = 999999.0; + } + System.err.println("Warning: Missing QoS value for " + p.getName() + " in service " + s.id + + " (Task " + taskId + "). Using default: " + val); + } + cws.setQoSValue(p, val); + } + candidates.add(cws); + } + } + market.put(aws, candidates); + } + + // 4. Create Problem (constraints will be attached after instantiation) + QoSAwareWSCompositionProblem problem = new QoSAwareWSCompositionProblem( + structure, + market, + qosModel, + new LinkedList() + ); + + // 4.1 Map Global Attribute Bound Constraints (if any) + if (req.constraints != null) { + for (SolveRequest.Constraint c : req.constraints) { + if (c == null) { + continue; + } + if (c.kind == null || !"attribute_bound".equalsIgnoreCase(c.kind)) { + continue; + } + if (c.scope != null && !"global".equalsIgnoreCase(c.scope)) { + continue; + } + if (c.attribute_id == null || c.op == null || c.value == null) { + continue; + } + + QoSProperty prop = propertyMap.get(c.attribute_id); + if (prop == null) { + continue; + } + + BinaryOperator op; + if ("==".equals(c.op)) { + op = BinaryOperator.EQUAL; + } else if ("!=".equals(c.op)) { + op = BinaryOperator.DISTINCT; + } else if (">".equals(c.op)) { + op = BinaryOperator.GREATER; + } else if (">=".equals(c.op)) { + op = BinaryOperator.GREATEREQUAL; + } else if ("<".equals(c.op)) { + op = BinaryOperator.LOWER; + } else if ("<=".equals(c.op)) { + op = BinaryOperator.LOWEREQUAL; + } else { + continue; + } + + problem.getConstraints().add(new GlobalQoSWSCompositionConstraint(problem, prop, c.value, op)); + } + } + + // 5. Solve (Simple Random Search) + int iterations = 1000; + if (req.config != null && req.config.max_iterations > 0) { + iterations = req.config.max_iterations; + } + + long start = System.currentTimeMillis(); + QoSAwareWSCompositionSolution bestSol = solveSimple(problem, iterations); + long end = System.currentTimeMillis(); + + // 6. Map Response + SolveResponse resp = new SolveResponse(); + resp.execution_time = end - start; + resp.iterations_count = iterations; // Report actual iterations used + resp.status = "optimized"; + resp.selection = new HashMap(); + resp.aggregated_features = new HashMap(); + + // Populate selection + if (bestSol instanceof QoSAwareWSCompositionVectorSolution) { + QoSAwareWSCompositionVectorSolution vecSol = (QoSAwareWSCompositionVectorSolution) bestSol; + // Need to map back AWS -> CWS ID + // The Solution interface doesn't expose map easily, but VectorSolution does + // Actually VectorSolution stores selection in a Map + // But it is protected or invalid access? + // Let's assume we can get it or we need a way. + // VectorSolution has getSelectedService(AbstractWebService) ?? + // Checking source... it extends AbstractSolution. + } + + // Workaround: We need to modify QoSAwareWSCompositionVectorSolution or inspect + // it. + // It has getService(AbstractWebService) ? + // I will check AbstractSolution source code if I can. + // For now, assume a method to extract selection. + + // Evaluate QoS + for (QoSProperty p : propertyMap.values()) { + double val = qosModel.evaluate(bestSol, p, structure); + resp.aggregated_features.put(p.getName(), val); + } + + // Populate selection map + for (Map.Entry entry : taskMap.entrySet()) { + String taskId = entry.getKey(); + AbstractWebService aws = entry.getValue(); + ConcreteWebService cws = bestSol.getSelectedService(aws); + if (cws != null) { + resp.selection.put(taskId, cws.getName()); + } + } + + return resp; + } + + private AggregationFunction getAggFunc(String name) { + if ("sum".equalsIgnoreCase(name)) + return SumatoryAggregationFunction.getInstance(); + if ("product".equalsIgnoreCase(name)) + return ProductoryAggregationFunction.getInstance(); + if ("max".equalsIgnoreCase(name)) + return MaxAggregationFunction.getInstance(); + if ("min".equalsIgnoreCase(name)) + return MinAggregationFunction.getInstance(); + return SumatoryAggregationFunction.getInstance(); // default + } + + private void collectTasks(StructuralComponent node, Map map) { + if (node instanceof AbstractWebService) { + // How do we know the ID? We constructed it with ID. + // AbstractWebService(String id). + // But AbstractWebService constructor takes 'id'. + // I need to store the mapping. + // Actually I should store mapping when creating node. + // AbstractWebService does not expose ID easily? It inherits from + // StructuralComponent ?? + // StructuralComponent doesn't seem to have ID accessor? + // Checking source needed. + // Assuming toString() or similar return ID, or I map objects. + // Best way: Map in context? + } + if (node instanceof CompositeStructuralComponent) { + for (StructuralComponent child : ((CompositeStructuralComponent) node).getSubComponents()) { + collectTasks(child, map); + } + } + } + + private StructuralComponent mapNode(SolveRequest.Node node, Map taskMap) { + if (node == null) { + return null; + } + if ("TASK".equals(node.kind)) { + AbstractWebService aws = new AbstractWebService(node.task_id); + taskMap.put(node.task_id, aws); + return aws; + } else if ("SEQ".equals(node.kind)) { + Sequence seq = new Sequence(); + if (node.children != null) { + for (SolveRequest.Node child : node.children) { + StructuralComponent sc = mapNode(child, taskMap); + if (sc != null) { + seq.getSubComponents().add(sc); + } + } + } + return seq; + } else if ("AND".equals(node.kind)) { + Flow flow = new Flow(); + if (node.children != null) { + for (SolveRequest.Node child : node.children) { + StructuralComponent sc = mapNode(child, taskMap); + if (sc != null) { + flow.getSubComponents().add(sc); + } + } + } + return flow; + } else if ("XOR".equals(node.kind)) { + Branch branch = new Branch(); + if (node.branches != null) { + for (SolveRequest.Branch b : node.branches) { + StructuralComponent child = mapNode(b.child, taskMap); + if (child != null) { + branch.addBranch(child, b.p); + } + } + } + return branch; + } else if ("LOOP".equals(node.kind)) { + int iterations = 1; + if (node.expected_iterations != null) { + iterations = (int) Math.round(node.expected_iterations.doubleValue()); + if (iterations < 0) { + iterations = 0; + } + } + Loop loop = new Loop(iterations); + if (node.body != null) { + StructuralComponent body = mapNode(node.body, taskMap); + if (body != null) { + loop.getSubComponents().add(body); + } + } + return loop; + } + return null; + } + + private QoSAwareWSCompositionSolution solveSimple(QoSAwareWSCompositionProblem problem, int iterations) { + // Simple Random Search + // Initialize with default (all 0 index) or random + QoSAwareWSCompositionSolution best = new QoSAwareWSCompositionVectorSolution(problem); + // best = best.createRandom(); // Maybe start random? + double bestFitness = problem.fitness(best); + + for (int i = 0; i < iterations; i++) { + // Create a new random solution + QoSAwareWSCompositionSolution sol = (QoSAwareWSCompositionSolution) new QoSAwareWSCompositionVectorSolution( + problem).createRandom(); + + double f = problem.fitness(sol); + + if (f < bestFitness) { + best = sol; + bestFitness = f; + } + } + return best; + } +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/api/Server.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/api/Server.java new file mode 100644 index 0000000..9be5032 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/api/Server.java @@ -0,0 +1,17 @@ +package es.us.isa.qosawarewsbinding.api; + +import com.sun.net.httpserver.HttpServer; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.util.concurrent.Executors; + +public class Server { + public static void main(String[] args) throws IOException { + int port = 8080; + HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); + server.createContext("/solve", new Controller()); + server.setExecutor(Executors.newCachedThreadPool()); + System.out.println("Many-OBJ Service started on port " + port); + server.start(); + } +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/api/dto/SolveRequest.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/api/dto/SolveRequest.java new file mode 100644 index 0000000..d6ef63d --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/api/dto/SolveRequest.java @@ -0,0 +1,76 @@ +package es.us.isa.qosawarewsbinding.api.dto; + +import java.util.List; +import java.util.Map; + +public class SolveRequest { + public String id; + public CompositionStructure composition; + public Map market; + public QoSModel features; + public SolvingConfig config; + public List constraints; + + public static class CompositionStructure { + public String type; // "structured" + public Node root; + } + + public static class Node { + public String id; + public String kind; // TASK, SEQ, AND, XOR, LOOP + public String task_id; // if TASK + public List children; // if SEQ, AND + public List branches; // if XOR + public Node body; // if LOOP + public Double expected_iterations; // if LOOP + } + + public static class Branch { + public double p; + public Node child; + } + + public static class ServiceCandidates { + public List services; + } + + public static class Service { + public String id; // service concrete ID (e.g. "s11") + public String name; + public Map features; + } + + public static class QoSModel { + public Map properties; + public Map weights; + public Map aggregation; + } + + public static class QoSPropertyDef { + public String direction; // "minimize", "maximize" + } + + public static class AggregationPolicy { + // Simple map from operator (seq, flow, etc.) to function name (sum, max, etc.) + public String seq; + public String flow; // "and" in request mapped to "flow" in engine + public String branch; // "xor" + public String loop; + } + + public static class SolvingConfig { + public int max_iterations; + public int population_size; + } + + public static class Constraint { + public String id; + public String kind; // "attribute_bound" + public String scope; // "global" + public String attribute_id; + public String op; // <=, <, >=, >, ==, != + public Double value; + public Boolean hard; + } +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/api/dto/SolveResponse.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/api/dto/SolveResponse.java new file mode 100644 index 0000000..d09e047 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/api/dto/SolveResponse.java @@ -0,0 +1,13 @@ +package es.us.isa.qosawarewsbinding.api.dto; + +import java.util.Map; + +public class SolveResponse { + public String status; // optimized, error + public Map selection; // task_id -> service_id + public Map aggregated_features; // aggregated qos + public Object metadata; + public String error; + public Long execution_time; + public Integer iterations_count; +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/BinaryOperator.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/BinaryOperator.java new file mode 100644 index 0000000..4bfdf8a --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/BinaryOperator.java @@ -0,0 +1,12 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.problem; + +/** + * + * @author japarejo + */ +public enum BinaryOperator {EQUAL, DISTINCT(), GREATER,GREATEREQUAL,LOWER,LOWEREQUAL} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/Constraint.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/Constraint.java new file mode 100644 index 0000000..d228d9c --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/Constraint.java @@ -0,0 +1,8 @@ +package es.us.isa.qosawarewsbinding.problem; + +public interface Constraint { + public boolean meets (X solution); + public double meetingDistance (X solution); + +} + diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/EvaluationCountProblem.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/EvaluationCountProblem.java new file mode 100644 index 0000000..d7aa8b9 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/EvaluationCountProblem.java @@ -0,0 +1,38 @@ +package es.us.isa.qosawarewsbinding.problem; + +import es.us.isa.qosawarewsbinding.solution.Solution; + +public abstract class EvaluationCountProblem implements Problem { + private long fitnessEvaluationCount; + private long feasibilityEvaluationCount; + + public EvaluationCountProblem() + { + fitnessEvaluationCount=0; + feasibilityEvaluationCount=0; + } + + + public final double fitness(Solution sol) { + fitnessEvaluationCount++; + return computeFitness(sol); + } + + public final boolean feasible(Solution sol) { + feasibilityEvaluationCount++; + return computeFeasibility(sol); + } + + protected abstract boolean computeFeasibility(Solution sol); + + protected abstract double computeFitness(Solution sol); + + public long getFitnessEvaluationCount() { + return fitnessEvaluationCount; + } + + public long getFeasibilityEvaluationCount() { + return feasibilityEvaluationCount; + } + +} \ No newline at end of file diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/ExecutionPath.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/ExecutionPath.java new file mode 100644 index 0000000..194596b --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/ExecutionPath.java @@ -0,0 +1,76 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.problem; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import es.us.isa.qosawarewsbinding.AbstractWebService; + +/** + * + * @author japarejo + */ +public class ExecutionPath { + private QoSAwareWSCompositionProblem problem; + private List executedTasks; + private double probabilityOfExecution; + + public ExecutionPath(QoSAwareWSCompositionProblem problem, List execTasks,double prob) + { + this.problem=problem; + this.executedTasks=new ArrayList(execTasks.size()); + this.executedTasks.addAll(execTasks); + this.probabilityOfExecution=prob; + } + + public ExecutionPath(QoSAwareWSCompositionProblem problem, double prob) + { + this.problem=problem; + this.executedTasks=new LinkedList(); + this.probabilityOfExecution=prob; + } + + public QoSAwareWSCompositionProblem getProblem() { + return problem; + } + + public List getExecutedTasks() { + return executedTasks; + } + + public double getProbabilityOfExecution() { + return probabilityOfExecution; + } + + public void setProbabilityOfExecution(double pk) { + this.probabilityOfExecution = pk; + } + + @Override + public boolean equals(Object obj) + { + boolean result=false; + if(obj instanceof ExecutionPath) + { + ExecutionPath myobj=(ExecutionPath)obj; + result=(problem==myobj.getProblem()); + result=result && (probabilityOfExecution==myobj.getProbabilityOfExecution()); + result=(result && executedTasks.equals(myobj.getExecutedTasks())); + } + return result; + } + + @Override + public int hashCode() { + int hash = 7; + hash = 29 * hash + (this.problem != null ? this.problem.hashCode() : 0); + hash = 29 * hash + (this.executedTasks != null ? this.executedTasks.hashCode() : 0); + hash = 29 * hash + (int) (Double.doubleToLongBits(this.probabilityOfExecution) ^ (Double.doubleToLongBits(this.probabilityOfExecution) >>> 32)); + return hash; + } +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/ExecutionPathsBuilder.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/ExecutionPathsBuilder.java new file mode 100644 index 0000000..444f2d4 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/ExecutionPathsBuilder.java @@ -0,0 +1,16 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.problem; + +import java.util.Set; + +/** + * + * @author japarejo + */ +public interface ExecutionPathsBuilder{ + public Set buildPaths(QoSAwareWSCompositionProblem aThis); +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/FeasibilityAwareProblem.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/FeasibilityAwareProblem.java new file mode 100644 index 0000000..047b98e --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/FeasibilityAwareProblem.java @@ -0,0 +1,46 @@ +package es.us.isa.qosawarewsbinding.problem; + +import es.us.isa.qosawarewsbinding.solution.Solution; + +public abstract class FeasibilityAwareProblem extends EvaluationCountProblem { + + private UnfeasibilityPenalizator penalizator; + + public FeasibilityAwareProblem() + { + penalizator=null; + } + + public FeasibilityAwareProblem(UnfeasibilityPenalizator penalizator) + { + this.penalizator=penalizator; + } + + + @Override + protected double computeFitness(Solution sol) { + double result=feasibilityFreeFitness(sol); + if(penalizator!=null) + result=getPenalizator().penalize(result,feasibilityDistance(sol)); + return result; + } + + public abstract double feasibilityDistance(Solution sol); + + public abstract double feasibilityFreeFitness(Solution sol); + + @Override + protected boolean computeFeasibility(Solution sol) { + return feasibilityDistance(sol)>0; + } + + /** + * @return the penalizator + */ + public UnfeasibilityPenalizator getPenalizator() { + return penalizator; + } + + +} + diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/GlobalQoSWSCompositionConstraint.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/GlobalQoSWSCompositionConstraint.java new file mode 100644 index 0000000..def3607 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/GlobalQoSWSCompositionConstraint.java @@ -0,0 +1,113 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.problem; + +import java.io.Serializable; + +import es.us.isa.qosawarewsbinding.qos.QoSProperty; +import es.us.isa.qosawarewsbinding.solution.QoSAwareWSCompositionSolution; + +/** + * + * @author japarejo + */ +public class GlobalQoSWSCompositionConstraint extends WSCompositionConstraint implements Serializable { + private QoSProperty property; + private BinaryOperator operator; + private Double value; + + public GlobalQoSWSCompositionConstraint(QoSAwareWSCompositionProblem problem, QoSProperty property, Double value, BinaryOperator operator) + { + super(problem); + if(problem!=null){ + if(problem.getQosmodel().getQosProperties().contains(property)) + { + this.property=property; + this.operator=operator; + this.value=value; + }else + throw new IllegalArgumentException("Property must be part of the QoS model of the problem at hand."); + }else{ + this.property=property; + this.operator=operator; + this.value=value; + } + } + + @Override + public boolean meets(QoSAwareWSCompositionSolution solution) { + return meetingDistance(solution)==0; + } + + @Override + public double meetingDistance(QoSAwareWSCompositionSolution solution) { + Double currentValue=problem.getQosmodel().evaluate(solution,getProperty(),problem.getStructure()); + return meetingDistance(currentValue); + } + + private double meetingDistance(Double currentValue) { + double result=getValue().doubleValue()-currentValue.doubleValue(); + if(getOperator()==BinaryOperator.EQUAL){ + result=Math.abs(result); + }else if(getOperator()==BinaryOperator.DISTINCT){ + if(result==0) + result=1; + else + result=0; + }else if(getOperator()==BinaryOperator.GREATER){ + if(result<0) + result=0; + else if(result==0) + result=Double.MIN_VALUE; + }else if(getOperator()==BinaryOperator.GREATEREQUAL){ + if(result<0) + result=0; + }else if(getOperator()==BinaryOperator.LOWER){ + if(result>0) + result=0; + else if(result<0) + result=Math.abs(result); + else + result=Double.MIN_VALUE; + }else if(getOperator()==BinaryOperator.LOWEREQUAL){ + if(result>0) + result=0; + else if(result<0) + result=Math.abs(result); + } + return result; + } + + public String toString() + { + String result=getOperator()+"("+getProperty().getName()+","+getValue()+")"; + return result; + } + + public QoSProperty getProperty() { + return property; + } + + public void setProperty(QoSProperty property) { + this.property = property; + } + + public BinaryOperator getOperator() { + return operator; + } + + public void setOperator(BinaryOperator operator) { + this.operator = operator; + } + + public Double getValue() { + return value; + } + + public void setValue(Double value) { + this.value = value; + } +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/LoopPeelingExecutionPathBuilder.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/LoopPeelingExecutionPathBuilder.java new file mode 100644 index 0000000..3eb8e33 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/LoopPeelingExecutionPathBuilder.java @@ -0,0 +1,119 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.problem; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +import es.us.isa.qosawarewsbinding.AbstractWebService; +import es.us.isa.qosawarewsbinding.Branch; +import es.us.isa.qosawarewsbinding.Loop; +import es.us.isa.qosawarewsbinding.Sequence; +import es.us.isa.qosawarewsbinding.StructuralComponent; +import es.us.isa.qosawarewsbinding.WSCompositionStructure; + +/** + * + * @author japarejo + */ +public class LoopPeelingExecutionPathBuilder implements ExecutionPathsBuilder { + + public Set buildPaths(QoSAwareWSCompositionProblem aThis) { + Set execPaths=new HashSet(); + buildPaths(aThis.getStructure(),execPaths,aThis); + return execPaths; + } + + private void buildPaths(WSCompositionStructure structure, Set execPaths, QoSAwareWSCompositionProblem aThis) { + List previous=new LinkedList(); + List components=((Sequence)structure.getStructure()).getSubComponents(); + buildPaths(previous,components,0,1.0,execPaths,aThis); + } + + private void buildPaths(List previous, List components, int i, double d, Set execPaths, QoSAwareWSCompositionProblem aThis) { + if(i subComponents=((Sequence)comp).getSubComponents(); + List newComponents=createComponentsSec(subComponents,components,1,i); + buildPaths(previous,newComponents,i,d,execPaths,aThis); + }else if(comp instanceof Loop){ + List subComponents=((Loop)comp).getSubComponents(); + List newComponents=null; + for(int j=0;j<=((Loop)comp).getAverageNumberOfIterations();j++){ + newComponents=createComponentsLoops(subComponents,components,j,i); + buildPaths(previous,newComponents,i,d,execPaths,aThis); + } + }else if(comp instanceof Branch) + { + for(StructuralComponent sc:((Branch)comp).getSubComponents()) + { + components.set(i, sc); + buildPaths(previous,components,i,d*((Branch)comp).getBranchProbability(sc),execPaths,aThis); + } + } + }else{ + execPaths.add(new ExecutionPath(aThis, previous,d)); + } + } + + private List createComponentsLoops(List subComponents, List components, int i, int j) { + List result=new LinkedList(); + for(int k=0;k createComponentsSec(List subComponents, List components, int i, int j) { + List result=new LinkedList(); + for(int k=0;k buildPaths(QoSAwareWSCompositionProblem aThis) { + Set execPaths=new HashSet(); + buildPaths(aThis.getStructure(),execPaths,aThis); + return execPaths; + } + + private void buildPaths(WSCompositionStructure structure, Set execPaths,QoSAwareWSCompositionProblem aThis) { + List previous=new LinkedList(); + List components=((Sequence)structure.getStructure()).getSubComponents(); + buildPaths(previous,components,0,1.0,execPaths,aThis); + } + + private void buildPaths(List previous, List components, int i, double d, Set execPaths,QoSAwareWSCompositionProblem aThis) { + if(i subComponents=((Sequence)comp).getSubComponents(); + List newComponents=createComponents(subComponents,components,1,i); + buildPaths(previous,newComponents,i,d,execPaths,aThis); + }else if(comp instanceof Loop){ + List subComponents=((Loop)comp).getSubComponents(); + List newComponents=null; + for(int j=0;j<=((Loop)comp).getAverageNumberOfIterations();j++){ + newComponents=createComponents(subComponents,components,j,i); + buildPaths(previous,newComponents,i,d,execPaths,aThis); + } + }else if(comp instanceof Branch) + { + for(StructuralComponent sc:((Branch)comp).getSubComponents()) + { + components.set(i, sc); + buildPaths(previous,components,i,d*((Branch)comp).getBranchProbability(sc),execPaths,aThis); + } + } + }else{ + execPaths.add(new ExecutionPath(aThis, previous,d)); + } + } + + private List createComponents(List subComponents, List components, int j, int i) { + List result=new LinkedList(); + for(int k=0;k + * NOTA: se recomienda que la descripcin contenga, los parmetros esenciales que + * determinan el tamao concreto de la instancia del problem que el objeto representa + * y todos los parmetros ms que sean necesarios para describir el problem separados + * por comas. + */ + public String getDescription(); + /** This method provides the name of the problem type e.g.: "TSP","SAT","QAP",etc. + * if you are creating your own problem you should ensure its problem is unique + * in your FOM instance. + * @return name of the problem type as string. + */ + public String getProblemType(); + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/ProblemReaderAndWriter.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/ProblemReaderAndWriter.java new file mode 100644 index 0000000..56d7dbc --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/ProblemReaderAndWriter.java @@ -0,0 +1,558 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.problem; + +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import es.us.isa.qosawarewsbinding.AbstractWebService; +import es.us.isa.qosawarewsbinding.Branch; +import es.us.isa.qosawarewsbinding.ConcreteWebService; +import es.us.isa.qosawarewsbinding.Flow; +import es.us.isa.qosawarewsbinding.Loop; +import es.us.isa.qosawarewsbinding.Sequence; +import es.us.isa.qosawarewsbinding.StructuralComponent; +import es.us.isa.qosawarewsbinding.WSCompositionStructure; +import es.us.isa.qosawarewsbinding.qos.QoSProperty; +import es.us.isa.qosawarewsbinding.qos.QoSPropertyType; +import es.us.isa.qosawarewsbinding.qos.aggretation.AggregationFunction; +import es.us.isa.qosawarewsbinding.qos.aggretation.AverageAggregationFunction; +import es.us.isa.qosawarewsbinding.qos.aggretation.MaxAggregationFunction; +import es.us.isa.qosawarewsbinding.qos.aggretation.MaxAverageAggregationFunction; +import es.us.isa.qosawarewsbinding.qos.aggretation.MinAggregationFunction; +import es.us.isa.qosawarewsbinding.qos.aggretation.MinAverageAggregationFunction; +import es.us.isa.qosawarewsbinding.qos.aggretation.ProductoryAggregationFunction; +import es.us.isa.qosawarewsbinding.qos.aggretation.ProductoryPowAggregationFunction; +import es.us.isa.qosawarewsbinding.qos.aggretation.SumatoryAggregationFunction; +import es.us.isa.qosawarewsbinding.qos.aggretation.SumatoryPowAggregationFunction; +import es.us.isa.qosawarewsbinding.util.MyStringTokenizer; + +/** + * + * @author japarejo + */ +public class ProblemReaderAndWriter { + + public static QoSAwareWSCompositionProblem load(String fileName) + { + File f=new File(fileName); + return load(f); + } + public static void write(String FileName, QoSAwareWSCompositionProblem problem) + { + File f=new File(FileName); + write(f,problem); + } + + private static AbstractWebService getAbstractWebService(String serviceName, QoSAwareWSCompositionProblem result) { + AbstractWebService aws=null; + Set services=result.getStructure().getComponents(); + for(AbstractWebService candidate:services) + if(serviceName.equalsIgnoreCase(candidate.toString())) + aws=candidate; + return aws; + } + + private static AggregationFunction getAggregationFunction(String functionName) { + AggregationFunction result=null; + if(functionName.equalsIgnoreCase("MAX")) + result=MaxAggregationFunction.getInstance(); + else if(functionName.equalsIgnoreCase("MIN")) + result=MinAggregationFunction.getInstance(); + else if(functionName.equalsIgnoreCase("SUM")) + result=SumatoryAggregationFunction.getInstance(); + else if(functionName.equalsIgnoreCase("PRODUCT")) + result=ProductoryAggregationFunction.getInstance(); + else if(functionName.equalsIgnoreCase("POW")) + result=ProductoryPowAggregationFunction.getInstance(); + // New aggregation functions + else if(functionName.equalsIgnoreCase("SUMPOW")) + result=SumatoryPowAggregationFunction.getInstance(); + else if(functionName.equalsIgnoreCase("AVG")) + result=AverageAggregationFunction.getInstance(); + else if(functionName.equalsIgnoreCase("MAXAVG")) + result=MaxAverageAggregationFunction.getInstance(); + else if(functionName.equalsIgnoreCase("MINAVG")) + result=MinAverageAggregationFunction.getInstance(); + return result; + } + + private static Class getStructuralClass(String className) { + Class result=null; + if(className.equalsIgnoreCase("LOOP")) + result=Loop.class; + else if(className.equalsIgnoreCase("BRANCH")) + result=Branch.class; + else if(className.equalsIgnoreCase("SEQUENCE")) + result=Sequence.class; + else if(className.equalsIgnoreCase("FLOW")) + result=Flow.class; + return result; + } + + private static StructuralComponent loadAWS(String line, BufferedReader reader, List awsList) { + StructuralComponent component=null; + line=line.trim(); + if(!line.equals("")) + { + component=searchAWS(line,awsList); + } + return component; + } + + private static StructuralComponent loadBranch(String substring, BufferedReader reader, List awsList) throws IOException { + + StructuralComponent subComponent; + Branch result=new Branch(); + MyStringTokenizer strtok=null; + strtok=new MyStringTokenizer(substring,";",'(',')'); + List probabilities=new LinkedList(); + String value; + while(strtok.hasMoreTokens()) + { + value=strtok.nextToken(); + if(!value.equals(")[")) + probabilities.add(Double.valueOf(value)); + } + int index=0; + do{ + + strtok=new MyStringTokenizer(substring,",",'[',']'); + while(strtok.hasMoreTokens()) + { + subComponent=loadStructureComponent(strtok.nextToken(),reader,awsList); + if(subComponent!=null){ + result.addBranch(subComponent, probabilities.get(index)); + index++; + } + } + if(substring.length()==0 || !(substring.charAt(substring.length()-1)==']')) + substring=reader.readLine(); + }while(substring.length()==0 || !(substring.charAt(substring.length()-1)==']')); + return result; + } + + private static void loadConstraints(QoSAwareWSCompositionProblem result, BufferedReader reader) throws IOException { + String line=reader.readLine(); + while(line.charAt(0)=='%') + line=reader.readLine(); + int nConstraints=Integer.valueOf(line.trim()); + line=reader.readLine(); + if(line.charAt(0)=='%') + line=reader.readLine(); + String stroperator; + BinaryOperator operator; + String propertyName; + QoSProperty property; + String value; + while(line.charAt(0)!='%') + { + line=line.trim(); + MyStringTokenizer strtok=new MyStringTokenizer(line, "(),"); + stroperator=strtok.nextToken("("); + operator=BinaryOperator.valueOf(stroperator); + propertyName=strtok.nextToken(","); + property=result.getQosmodel().getQoSProperty(propertyName); + value=strtok.nextToken(")"); + result.getConstraints().add(new GlobalQoSWSCompositionConstraint(result, property, Double.valueOf(value), operator)); + line=reader.readLine(); + } + } + + private static StructuralComponent loadFlow(String substring, BufferedReader reader, List awsList) { + throw new UnsupportedOperationException("Not yet implemented"); + } + + private static StructuralComponent loadLoop(String substring, BufferedReader reader, List awsList) throws IOException { + String number=substring.substring(0,substring.lastIndexOf(")")); + Integer averageNumberOfIterations=Integer.valueOf(number); + StructuralComponent subComponent; + Loop result=new Loop(averageNumberOfIterations); + substring=substring.substring(substring.lastIndexOf(")")+2); + MyStringTokenizer strtok=null; + do{ + strtok=new MyStringTokenizer(substring,",",'[',']'); + while(strtok.hasMoreTokens()) + { + subComponent=loadStructureComponent(strtok.nextToken(),reader,awsList); + if(subComponent!=null) + result.getSubComponents().add(subComponent); + } + if(substring.length()==0 || !(substring.charAt(substring.length()-1)==']')) + substring=reader.readLine(); + }while(substring.length()==0 || !(substring.charAt(substring.length()-1)==']')); + return result; + } + + private static void loadMarket(QoSAwareWSCompositionProblem result, BufferedReader reader) throws IOException { + Map> market=result.getMarket(); + market.clear(); + String line=reader.readLine(); + while(line.charAt(0)=='%') + line=reader.readLine(); + line=reader.readLine(); + String serviceName=line.trim(); + String cwsName; + String propertyName; + String propertyValue; + AbstractWebService aws=null; + MyStringTokenizer strtok=null; + Set awsSet=null;; + ConcreteWebService cws=null; + while(line.charAt(0)!='%') + { + serviceName=line.trim(); + aws=getAbstractWebService(serviceName,result); + awsSet=new HashSet(); + line=reader.readLine(); + line=reader.readLine(); + while(line.charAt(0)!='-') + { + strtok=new MyStringTokenizer(line, "():,"); + cwsName=strtok.nextToken("("); + cws=new ConcreteWebService(cwsName, aws); + while(strtok.hasMoreTokens()) + { + propertyName=strtok.nextToken(":"); + if(!propertyName.equals(")")){ + propertyValue=strtok.nextToken(","); + try{ + cws.setQoSValue(result.getQosmodel().getQoSProperty(propertyName), Double.valueOf(propertyValue)); + }catch(Exception ex){ + System.out.println(ex); + System.out.println("ON LINE: "+line); + System.out.println("VALUE CAUSING ERROR:"+propertyValue); + } + } + } + awsSet.add(cws); + line=reader.readLine(); + } + market.put(aws, awsSet); + line=reader.readLine(); + } + } + + private static WSCompositionQoSModel loadQoSModel(BufferedReader reader) throws IOException { + WSCompositionQoSModel result=null; + String line=reader.readLine(); + while(line.length()==0 || line.charAt(0)=='%') + line=reader.readLine(); + line=line.trim(); + Set properties; + if(line.equals("QoSModel{")){ + properties=loadQoSModelProperties(reader); + result=new WSCompositionQoSModel(properties); + loadQoSModelAggregationFunctions(reader,result); + loadQoSModelWeights(reader,result); + line=reader.readLine(); + } + return result; + } + + private static void loadQoSModelAggregationFunctions(BufferedReader reader, WSCompositionQoSModel result) throws IOException { + String line=reader.readLine(); + line=line.trim(); + String name; + String function; + QoSProperty property; + String className; + Class myclass; + String functionName; + AggregationFunction aggregationf; + + if(line.equals("AggregationFunctions(")) + { + line=reader.readLine(); + line=line.trim(); + while((!line.equals(")"))) + { + if(line.charAt(line.length()-1)=='{') + { + name=line.substring(0, line.length()-1); + property=result.getQoSProperty(name); + line=reader.readLine(); + line=line.trim(); + while(!line.equals("}")) + { + MyStringTokenizer strtok=new MyStringTokenizer(line,":"); + className=strtok.nextToken(); + functionName=strtok.nextToken(); + myclass=getStructuralClass(className); + aggregationf=getAggregationFunction(functionName); + result.setAggregationFunction(property, myclass, aggregationf); + line=reader.readLine(); + line=line.trim(); + } + } + line=reader.readLine(); + line=line.trim(); + } + } + } + + private static Set loadQoSModelProperties(BufferedReader reader) throws IOException { + Set result=new HashSet(); + QoSProperty property=null; + String line=reader.readLine(); + line=line.trim(); + String name; + String type; + + if(line.equals("Properties{")) + { + line=reader.readLine(); + line=line.trim(); + while((!line.equals("}"))) + { + MyStringTokenizer strtok=new MyStringTokenizer(line, ":-"); // TODO Change the separator € (problems in linux!) + if(strtok.hasMoreTokens()){ + name=strtok.nextToken(":"); + if(strtok.hasMoreTokens()){ + type=strtok.nextToken("-"); // TODO Change the separator € (problems in linux!) + property=new QoSProperty(name,QoSPropertyType.valueOf(type)); + result.add(property); + } + } + line=reader.readLine(); + line=line.trim(); + } + } + return result; + } + + private static void loadQoSModelWeights(BufferedReader reader, WSCompositionQoSModel result) throws IOException { + String line=reader.readLine(); + line=line.trim(); + String name; + String value; + Map qosPropertiesWeights=new HashMap(); + if(line.equals("Weights(")) + { + line=reader.readLine(); + line=line.trim(); + while((!line.equals(")"))) + { + MyStringTokenizer strtok=new MyStringTokenizer(line,":"); + name=strtok.nextToken(); + value=strtok.nextToken(); + qosPropertiesWeights.put(result.getQoSProperty(name),Double.valueOf(value)); + line=reader.readLine(); + line=line.trim(); + } + } + result.setQosPropertiesWeights(qosPropertiesWeights); + } + + + private static StructuralComponent loadSequence(String substring, BufferedReader reader, List awsList) throws IOException { + Sequence result=new Sequence(); + StructuralComponent subComponent; + substring=substring.trim(); + + MyStringTokenizer strtok=null; + do + { + strtok=new MyStringTokenizer(substring,",",'[',']'); + while(strtok.hasMoreTokens()) + { + subComponent=loadStructureComponent(strtok.nextToken(),reader,awsList); + if(subComponent!=null) + result.getSubComponents().add(subComponent); + } + if(substring.length()==0 || !(substring.charAt(substring.length()-1)==']')) + substring=reader.readLine(); + }while(substring.length()==0 || !(substring.charAt(substring.length()-1)==']')); + return result; + } + + private static WSCompositionStructure loadStructure(BufferedReader reader) { + WSCompositionStructure result=null; + String line; + List awsList=new LinkedList(); + try { + line = reader.readLine(); + while(line.charAt(0)=='%') + line=reader.readLine(); + int nAbstractServices=Integer.parseInt(line); + for(int i=0;i awsList) throws IOException + { + StructuralComponent result=null; + line=line.trim(); + if(line.substring(0, Math.min(3, line.length())).equalsIgnoreCase("SEC")) + { + result=loadSequence(line.substring(4),reader,awsList); + }else if(line.substring(0,Math.min(4, line.length())).equalsIgnoreCase("LOOP")){ + result=loadLoop(line.substring(5),reader,awsList); + }else if(line.substring(0,Math.min(6, line.length())).equalsIgnoreCase("BRANCH")){ + result=loadBranch(line.substring(7),reader,awsList); + }else if(line.substring(0,Math.min(3, line.length())).equalsIgnoreCase("FLOW")){ + result=loadFlow(line.substring(5),reader,awsList); + }else{ + result=loadAWS(line,reader,awsList); + } + return result; + } + + private static void printConstraints(PrintWriter writer, List constraints) { + writer.println("%#======================= CONSTRAINTS =============================#"); + writer.println(constraints.size()); + writer.println("% ----------------------"); + for(WSCompositionConstraint constraint:constraints) + { + writer.println(constraint); + } + writer.println("% ----------------------"); + } + + private static void printHeader(PrintWriter writer, String fileName, QoSAwareWSCompositionProblem problem) { + writer.println("%#============================= HEADER ======================================#"); + writer.println("% This file contains an instance of the QoS-Aware Web Services Composition Problem "); + writer.println("% FILE: "+fileName); + writer.println("% Created by: José Antonio Parejo Mestre"); + writer.println("% "+new Date()); + writer.println("% ----------------------"); + writer.println("% Problem Statistics: "); + writer.println("% ----------------------"); + writer.println("% Number of activities: "+problem.getStructure().numberOfActivities()); + int nServices=0; + Collection> values=problem.getMarket().values(); + for(Set services:values) + nServices+=services.size(); + writer.println("% Number of Candidate Services: "+nServices); + writer.println("% Number of Constraints: "+problem.getConstraints().size()); + } + + private static void printMarket(PrintWriter writer, Map> market,WSCompositionQoSModel qosModel) { + writer.println("%#======================= CANDIDATE SERVICES =============================#"); + writer.println("------------------------"); + Set cwservices; + for(AbstractWebService aws:market.keySet()) + { + writer.println(aws); + writer.println("------------------------"); + cwservices=market.get(aws); + for(ConcreteWebService cws:cwservices) + { + writer.print(cws+"("); + for (QoSProperty property : qosModel.getQosProperties()) { + writer.print(property.getName() + ":" + cws.getQoSValue(property) + ","); + } + writer.println(")"); + } + writer.println("------------------------"); + } + } + + private static void printQoSModel(PrintWriter writer, WSCompositionQoSModel qosmodel) { + writer.println("%#======================= QOS MODEL =============================#"); + writer.println(qosmodel); + } + + private static void printStructure(PrintWriter writer, WSCompositionStructure structure) { + writer.println("%#======================= COMPOSITION STRUCTURE =============================#"); + writer.println("% Abstract Services:"); + writer.println("%----------------------"); + writer.println(structure.getComponents().size()); + for(AbstractWebService aws:structure.getComponents()) + writer.println(aws); + writer.println("% CompositionStructure:"); + writer.println("%----------------------"); + writer.println(structure.getStructure().toStructuralString("")); + } + + public static QoSAwareWSCompositionProblem load(File f) { + QoSAwareWSCompositionProblem result=null; + WSCompositionStructure structure=null; + WSCompositionQoSModel qosmodel=null; + Map> market=null; + List constraints; + BufferedReader reader; + String line; + try { + reader = new BufferedReader(new FileReader(f)); + line=reader.readLine(); + line=reader.readLine(); + if(line.equals("% This file contains an instance of the QoS-Aware Web Services Composition Problem ")) + { + // We skip the header: + while(line.charAt(0)=='%' && line.charAt(1)==' ') + line=reader.readLine(); + structure=loadStructure(reader); + qosmodel=loadQoSModel(reader); + result=new QoSAwareWSCompositionProblem(structure, qosmodel); + loadMarket(result,reader); + loadConstraints(result,reader); + } + } catch (FileNotFoundException ex) { + Logger.getLogger(ProblemReaderAndWriter.class.getName()).log(Level.SEVERE, null, ex); + }catch (IOException ex) { + Logger.getLogger(ProblemReaderAndWriter.class.getName()).log(Level.SEVERE, null, ex); + } + if(result!=null) + result.scale(); + return result; + } + + private static StructuralComponent searchAWS(String line, List awsList) { + StructuralComponent result=null; + for(AbstractWebService aws:awsList) + { + if(aws.toString().equals(line)) + result=aws; + } + return result; + } + + private static void write(File f, QoSAwareWSCompositionProblem problem) { + PrintWriter writer; + try { + writer = new PrintWriter(new BufferedOutputStream(new FileOutputStream(f))); + printHeader(writer,f.getName(),problem); + printStructure(writer,problem.getStructure()); + printQoSModel(writer,problem.getQosmodel()); + printMarket(writer,problem.getMarket(),problem.getQosmodel()); + printConstraints(writer,problem.getConstraints()); + writer.close(); + } catch (FileNotFoundException ex) { + Logger.getLogger(ProblemReaderAndWriter.class.getName()).log(Level.SEVERE, null, ex); + } + } + + + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/QoSAwareWSCompositionProblem.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/QoSAwareWSCompositionProblem.java new file mode 100644 index 0000000..87b3bce --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/QoSAwareWSCompositionProblem.java @@ -0,0 +1,333 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package es.us.isa.qosawarewsbinding.problem; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import es.us.isa.qosawarewsbinding.AbstractWebService; +import es.us.isa.qosawarewsbinding.ConcreteWebService; +import es.us.isa.qosawarewsbinding.WSCompositionStructure; +import es.us.isa.qosawarewsbinding.qos.QoSProperty; +import es.us.isa.qosawarewsbinding.qos.QoSPropertyType; +import es.us.isa.qosawarewsbinding.solution.QoSAwareWSCompositionSolution; +import es.us.isa.qosawarewsbinding.solution.Solution; +import es.us.isa.qosawarewsbinding.solution.vector.QoSAwareWSCompositionVectorSolution; + +/** + * + * @author japarejo + */ +public class QoSAwareWSCompositionProblem extends FeasibilityAwareProblem implements Serializable { + + private WSCompositionStructure structure; + private Map> market; + private WSCompositionQoSModel qosmodel; + private List constraints; + private Set expaths; + private static ExecutionPathsBuilder expathBuilder = null; + public boolean scaled; + + public QoSAwareWSCompositionProblem(WSCompositionStructure structure, Map> market, WSCompositionQoSModel qosmodel, List constraints) { + this.structure = structure; + this.market = market; + this.qosmodel = qosmodel; + this.constraints = constraints; + this.expaths = null; + this.scaled = false; + } + + public QoSAwareWSCompositionProblem(WSCompositionStructure structure, WSCompositionQoSModel qosmodel) { + this(structure, new HashMap>(), qosmodel, new LinkedList()); + } + + public int numberOfCandidates(AbstractWebService aws) { + return getMarket().get(aws).size(); + } + + public String getDescription() { + throw new UnsupportedOperationException("Not supported yet."); + } + + public WSCompositionStructure getStructure() { + return structure; + } + + public Map> getMarket() { + return market; + } + + public WSCompositionQoSModel getQosmodel() { + return qosmodel; + } + + public List getConstraints() { + return constraints; + } + + public String toString() { + StringBuffer buffer = new StringBuffer("=== QoS-aware Web Service Composition Problem Instance ===\n"); + buffer.append(getStructure().getStructure().toStructuralString("")); + buffer.append(toStringMarket()); + buffer.append(getQosmodel()); + buffer.append(getConstraints()); + buffer.append("==========================================================\n"); + return buffer.toString(); + + } + + private double scale(double value, double Qmax, double Qmin, QoSProperty property) { + double result = 0; + if (Qmax != Qmin) { + if (property.getType() == QoSPropertyType.POSITIVE) { + result = (value - Qmin) / (Qmax - Qmin); + } else { + result = (Qmax - value) / (Qmax - Qmin); + } + } else { + result = 1.0; + } + return result; + } + + private String toStringMarket() { + + StringBuffer buffer = new StringBuffer("--- MARKET OF SERVICES ---"); + for (AbstractWebService aws : market.keySet()) { + buffer.append("\nAWS" + aws.toString() + ":"); + for (ConcreteWebService cws : market.get(aws)) { + buffer.append(" S" + cws.getName() + "("); + for (QoSProperty property : getQosmodel().getQosProperties()) { + buffer.append(property.getName() + ":" + cws.getQoSValue(property) + ","); + } + buffer.append(")"); + } + } + buffer.append("\n--------------------------\n"); + return buffer.toString(); + } + + public double feasibilityDistance(Solution sol) { + double value = 0; + for (WSCompositionConstraint constraint : getConstraints()) { + value = constraint.meetingDistance((QoSAwareWSCompositionSolution) sol); + } + return value; + } + + protected double computeFitness(Solution sol) { + double feasibilityDistance = Math.min(1, feasibilityDistance(sol)); + double result = feasibilityFreeFitness(sol); + if (getPenalizator() != null) { + result = getPenalizator().penalize(result, (1.0 - feasibilityDistance)); + } + return 1.0 - result; + } + + public double feasibilityFreeFitness(Solution sol) { + double result = 0; + if (!scaled) { + scale(); + } + result = getQosmodel().evaluate((QoSAwareWSCompositionSolution) sol, getStructure()); + result = result / numberOfExecutedTasks(); + return result; + } + + public double candidatesPerService() { + int totalNumberOfCandidates = 0; + for (AbstractWebService aws : getMarket().keySet()) { + totalNumberOfCandidates += getMarket().get(aws).size(); + } + return ((double) (totalNumberOfCandidates)) / ((double) (getMarket().keySet().size())); + } + + public Set getExecutionPaths() { + if (getExpaths() == null) { + if (expathBuilder != null) { + setExpaths(expathBuilder.buildPaths(this)); + } else { + expathBuilder = new LoopUnfoldingExecutionPathsBuilder(); + setExpaths(expathBuilder.buildPaths(this)); + } + } + return getExpaths(); + } + + public boolean isScaled() { + return scaled; + } + + public void scale() { + for (QoSProperty property : getQosmodel().getQosProperties()) { + scale(property); + } + scaled = true; + //System.out.println("Problem Reescaled!! Current State:"); + //System.out.println(this); + } + + private void scale(QoSProperty property) { + double Qmax = max(property); + double Qmin = min(property); + double value = 0; + for (AbstractWebService aws : getMarket().keySet()) { + for (ConcreteWebService cws : getMarket().get(aws)) { + Double objVal = (Double) cws.getQoSValue(property); + if (objVal != null) { + value = objVal; + value = scale(value, Qmax, Qmin, property); + cws.setQoSValue(property, value); + } + } + } + + for (WSCompositionConstraint constraint : constraints) { + if (constraint instanceof GlobalQoSWSCompositionConstraint) { + if (((GlobalQoSWSCompositionConstraint) constraint).getProperty().equals(property)) { + value = ((GlobalQoSWSCompositionConstraint) constraint).getValue(); + value = scale(value, Qmax, Qmin, property); + if (value < 0) { + value = 1 - value; + } + ((GlobalQoSWSCompositionConstraint) constraint).setValue(value); + } + } + } + + } + + private double max(QoSProperty property) { + double result = -Double.MAX_VALUE; + boolean found = false; + for (AbstractWebService aws : getMarket().keySet()) { + for (ConcreteWebService cws : market.get(aws)) { + Double candidate = (Double) cws.getQoSValue(property); + if (candidate != null) { + if (candidate > result) { + result = candidate; + } + found = true; + } + } + } + return found ? result : 1.0; // Default max if no values + } + + private double min(QoSProperty property) { + double result = Double.MAX_VALUE; + boolean found = false; + for (AbstractWebService aws : market.keySet()) { + for (ConcreteWebService cws : market.get(aws)) { + Double candidate = (Double) cws.getQoSValue(property); + if (candidate != null) { + if (candidate < result) { + result = candidate; + } + found = true; + } + } + } + return found ? result : 0.0; // Default min if no values + } + + public void setStructure(WSCompositionStructure structure) { + this.structure = structure; + } + + public void setQosmodel(WSCompositionQoSModel qosmodel) { + this.qosmodel = qosmodel; + } + + public void setConstraints(List constraints) { + this.constraints = constraints; + } + + public Set getExpaths() { + return expaths; + } + + public void setExpaths(Set expaths) { + this.expaths = expaths; + } + + public double numberOfExecutedTasks() { + return structure.numberOfExecutedTasks(); + } + + public String getProblemType() { + return "QoS-awareCWSBinding"; + } + + public Double bestValue(QoSProperty property) { + QoSAwareWSCompositionSolution solution = computeBestSolution(property); + return qosmodel.evaluate(solution, property, structure); + } + + public Double worstValue(QoSProperty property) { + QoSAwareWSCompositionSolution solution = computeWorstSolution(property); + return qosmodel.evaluate(solution, property, structure); + } + + public QoSAwareWSCompositionSolution computeBestSolution(QoSProperty property) { + QoSAwareWSCompositionVectorSolution result = new QoSAwareWSCompositionVectorSolution(this); + ConcreteWebService bestCandidate = null; + + for (AbstractWebService aws : market.keySet()) { + for (ConcreteWebService cws : market.get(aws)) { + if (bestCandidate == null) { + bestCandidate = cws; + } else { + if (property.getType() == QoSPropertyType.POSITIVE) { + if (((Double) cws.getQoSValue(property)) > ((Double) bestCandidate.getQoSValue(property))) { + bestCandidate = cws; + } + } else { + if (((Double) cws.getQoSValue(property)) < ((Double) bestCandidate.getQoSValue(property))) { + bestCandidate = cws; + } + } + } + } + result.setSelectedService(aws, bestCandidate); + bestCandidate = null; + } + return result; + } + + public QoSAwareWSCompositionSolution computeWorstSolution(QoSProperty property) { + QoSAwareWSCompositionVectorSolution result = new QoSAwareWSCompositionVectorSolution(this); + ConcreteWebService worstCandidate = null; + System.out.println("Search worst solution..."); + for (AbstractWebService aws : market.keySet()) { + for (ConcreteWebService cws : market.get(aws)) { + if (worstCandidate == null) { + worstCandidate = cws; + } else { + + System.out.println("type: " + property.getType() + " worst: " + ((Double) worstCandidate.getQoSValue(property)) + " cws: " + ((Double) cws.getQoSValue(property))); + + if (property.getType() == QoSPropertyType.POSITIVE) { + if (((Double) cws.getQoSValue(property)) < ((Double) worstCandidate.getQoSValue(property))) { + worstCandidate = cws; + } + } else { + if (((Double) cws.getQoSValue(property)) > ((Double) worstCandidate.getQoSValue(property))) { + worstCandidate = cws; + } + } + System.out.println("Updated worst: " + ((Double) worstCandidate.getQoSValue(property))); + } + } + result.setSelectedService(aws, worstCandidate); + worstCandidate = null; + } + return result; + } +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/ServicesDespendenceWSCompositionConstraint.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/ServicesDespendenceWSCompositionConstraint.java new file mode 100644 index 0000000..b952034 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/ServicesDespendenceWSCompositionConstraint.java @@ -0,0 +1,47 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.problem; + +import java.io.Serializable; +import java.util.Map; + +import es.us.isa.qosawarewsbinding.AbstractWebService; +import es.us.isa.qosawarewsbinding.ConcreteWebService; +import es.us.isa.qosawarewsbinding.solution.QoSAwareWSCompositionSolution; + +/** + * + * @author japarejo + */ +public class ServicesDespendenceWSCompositionConstraint extends WSCompositionConstraint implements Serializable{ + + public Map dependences; + + public ServicesDespendenceWSCompositionConstraint(QoSAwareWSCompositionProblem problem, Map dependences) + { + super(problem); + this.dependences=dependences; + } + + @Override + public boolean meets(QoSAwareWSCompositionSolution solution) { + return meetingDistance(solution)==0; + } + + @Override + public double meetingDistance(QoSAwareWSCompositionSolution solution) { + double distance=0; + int present=0; + for(AbstractWebService aws:dependences.keySet()) + { + if(solution.isUsing(aws, dependences.get(aws))) + present++; + } + distance=((double)present)/((double)dependences.keySet().size()); + return distance; + } + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/UnfeasibilityPenalizator.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/UnfeasibilityPenalizator.java new file mode 100644 index 0000000..0c8a5d2 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/UnfeasibilityPenalizator.java @@ -0,0 +1,7 @@ +package es.us.isa.qosawarewsbinding.problem; + +public interface UnfeasibilityPenalizator { + + public double penalize(double fitness,double feasibilityDistance); + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/WSCompositionConstraint.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/WSCompositionConstraint.java new file mode 100644 index 0000000..dbf7350 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/WSCompositionConstraint.java @@ -0,0 +1,29 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.problem; + +import es.us.isa.qosawarewsbinding.solution.QoSAwareWSCompositionSolution; + +/** + * + * @author japarejo + */ +public abstract class WSCompositionConstraint implements Constraint { + + protected QoSAwareWSCompositionProblem problem; + + public WSCompositionConstraint(QoSAwareWSCompositionProblem problem) + { + this.problem=problem; + } + + + public abstract boolean meets(QoSAwareWSCompositionSolution solution); + + public abstract double meetingDistance(QoSAwareWSCompositionSolution solution); + + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/WSCompositionQoSModel.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/WSCompositionQoSModel.java new file mode 100644 index 0000000..d226994 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/WSCompositionQoSModel.java @@ -0,0 +1,168 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.problem; + +import java.io.Serializable; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + + + +import es.us.isa.qosawarewsbinding.AbstractWebService; +import es.us.isa.qosawarewsbinding.CompositeStructuralComponent; +import es.us.isa.qosawarewsbinding.StructuralComponent; +import es.us.isa.qosawarewsbinding.WSCompositionStructure; +import es.us.isa.qosawarewsbinding.qos.QoSProperty; +import es.us.isa.qosawarewsbinding.qos.aggretation.AggregationFunction; +import es.us.isa.qosawarewsbinding.solution.QoSAwareWSCompositionSolution; + +/** + * + * @author japarejo + */ +public class WSCompositionQoSModel implements Serializable{ + private Set qosProperties; + Map> aggregationFunctions; + private Map qosPropertiesWeights; + + public WSCompositionQoSModel(Set qosProperties) + { + this.qosProperties=qosProperties; + aggregationFunctions=new HashMap>(); + qosPropertiesWeights=new HashMap(); + Double value=1.0/((double)qosProperties.size()); + for(QoSProperty property:qosProperties) + qosPropertiesWeights.put(property, value); + } + + public WSCompositionQoSModel(Map> aggregationFunctions) + { + this.qosProperties=aggregationFunctions.keySet(); + this.aggregationFunctions=aggregationFunctions; + Double value=1.0/((double)this.qosProperties.size()); + for(QoSProperty property:qosProperties) + qosPropertiesWeights.put(property, value); + } + + public AggregationFunction getAggregationFunction(QoSProperty property,Class pclass) + { + AggregationFunction result=null; + Map functions=aggregationFunctions.get(property); + if(functions!=null) + result=functions.get(pclass); + return result; + } + + public void setAggregationFunction(QoSProperty property,Class pclass, AggregationFunction aggregationFunction) + { + Map functions=aggregationFunctions.get(property); + if(functions==null) + { + functions=new HashMap(); + aggregationFunctions.put(property, functions); + } + functions.put(pclass, aggregationFunction); + } + + public Double getQoSPropertyWeight(QoSProperty property) + { + return qosPropertiesWeights.get(property); + } + + public Set getQosProperties() { + return qosProperties; + } + + public void setQosPropertiesWeights(Map qosPropertiesWeights) { + this.qosPropertiesWeights = qosPropertiesWeights; + } + + public QoSProperty getQoSProperty(String name) + { + QoSProperty result=null; + for(QoSProperty property:qosProperties) + if(property.getName().equals(name)) + result=property; + return result; + } + + public Double evaluate(QoSAwareWSCompositionSolution solution,WSCompositionStructure compositionStructure) + { + double result=0; + double qosPropertyAportation; + for(QoSProperty property:qosProperties){ + qosPropertyAportation=evaluate(solution,property,compositionStructure); + result+=qosPropertiesWeights.get(property).doubleValue()*qosPropertyAportation; + } + return result; + } + + public Double evaluate(QoSAwareWSCompositionSolution solution, QoSProperty property,WSCompositionStructure compositionStructure) + { + return evaluate(solution,property,compositionStructure.getStructure()); + } + + public Double evaluate(QoSAwareWSCompositionSolution solution, QoSProperty property, StructuralComponent component) + { + Double result=null; + if(component instanceof AbstractWebService) + result=(Double)solution.getSelectedService((AbstractWebService)component).getQoSValue(property); + else{ + AggregationFunction aggregationFunction=getAggregationFunction(property,component.getClass()); + List partialResults=new LinkedList(); + List ponderations=new LinkedList(); + CompositeStructuralComponent compositeComponent=(CompositeStructuralComponent)component; + Collection subcomponents=compositeComponent.getSubComponents(); + for(StructuralComponent subcomponent:subcomponents){ + if(subcomponent!=null && !subcomponent.isEmpty()){ + partialResults.add(evaluate(solution,property,subcomponent)); + ponderations.add(compositeComponent.getPonderation(subcomponent)); + } + } + result=aggregationFunction.aggregation(partialResults,ponderations); + } + return result; + } + + @Override + public String toString() + { + StringBuffer buffer=new StringBuffer(); + Map functionsPerProperty; + String newline = System.getProperty("line.separator"); + buffer.append("QoSModel{"+newline); + //buffer.append(" "+qosProperties+newline); + buffer.append(" "+"Properties{"+newline); + for(QoSProperty property:qosProperties) + buffer.append(" "+property.toString()+newline); + buffer.append(" }"+newline); + buffer.append(" AggregationFunctions("+newline); + for(QoSProperty property:aggregationFunctions.keySet()){ + buffer.append(" "+property.getName()+"{"+newline); + functionsPerProperty=aggregationFunctions.get(property); + for(Class structureClass:functionsPerProperty.keySet()) + { + buffer.append(" "+structureClass.getSimpleName()+":"+functionsPerProperty.get(structureClass)+newline); + } + buffer.append(" }"+newline); + } + buffer.append(" )"+newline); + buffer.append(" "+"Weights("+newline); + for(QoSProperty property:qosPropertiesWeights.keySet()) + { + buffer.append(" "+property.getName()+":"+qosPropertiesWeights.get(property).doubleValue()+newline); + } + buffer.append(" )"+newline); + buffer.append("}"); + return buffer.toString(); + + } + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/generator/AbstractProblemGenerator.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/generator/AbstractProblemGenerator.java new file mode 100644 index 0000000..ec8f217 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/generator/AbstractProblemGenerator.java @@ -0,0 +1,24 @@ +package es.us.isa.qosawarewsbinding.problem.generator; + +import es.us.isa.qosawarewsbinding.problem.Problem; +import es.us.isa.qosawarewsbinding.problem.model.ProblemModel; + +public abstract class AbstractProblemGenerator implements ProblemGenerator { + + private ProblemModel problemModel; + + public AbstractProblemGenerator(ProblemModel pmodel) + { + this.problemModel=pmodel; + } + + public ProblemModel getProblemModel() { + return problemModel; + } + + public void setProblemModel(ProblemModel problemModel) { + this.problemModel = problemModel; + } + + +} \ No newline at end of file diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/generator/ProblemGenerator.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/generator/ProblemGenerator.java new file mode 100644 index 0000000..01461bc --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/generator/ProblemGenerator.java @@ -0,0 +1,7 @@ +package es.us.isa.qosawarewsbinding.problem.generator; + +import es.us.isa.qosawarewsbinding.problem.Problem; + +public interface ProblemGenerator { + public X generate(); +} \ No newline at end of file diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/generator/QoSAwareWSCompositionProblemGenerator.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/generator/QoSAwareWSCompositionProblemGenerator.java new file mode 100644 index 0000000..2b37726 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/generator/QoSAwareWSCompositionProblemGenerator.java @@ -0,0 +1,381 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.problem.generator; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import es.us.isa.qosawarewsbinding.AbstractWebService; +import es.us.isa.qosawarewsbinding.Branch; +import es.us.isa.qosawarewsbinding.CompositeStructuralComponent; +import es.us.isa.qosawarewsbinding.ConcreteWebService; +import es.us.isa.qosawarewsbinding.Flow; +import es.us.isa.qosawarewsbinding.Loop; +import es.us.isa.qosawarewsbinding.Sequence; +import es.us.isa.qosawarewsbinding.StructuralComponent; +import es.us.isa.qosawarewsbinding.WSCompositionStructure; +import es.us.isa.qosawarewsbinding.problem.BinaryOperator; +import es.us.isa.qosawarewsbinding.problem.GlobalQoSWSCompositionConstraint; +import es.us.isa.qosawarewsbinding.problem.QoSAwareWSCompositionProblem; +import es.us.isa.qosawarewsbinding.problem.WSCompositionConstraint; +import es.us.isa.qosawarewsbinding.problem.WSCompositionQoSModel; +import es.us.isa.qosawarewsbinding.problem.model.GlobalQoSConstraintsModel; +import es.us.isa.qosawarewsbinding.problem.model.QoSAwareWSCompositionProblemConstraintsModel; +import es.us.isa.qosawarewsbinding.problem.model.QoSAwareWSCompositionProblemModel; +import es.us.isa.qosawarewsbinding.problem.model.QoSAwareWSCompositionProblemServicesMarketModel; +import es.us.isa.qosawarewsbinding.problem.model.QoSAwareWSCompositionProblemStructuralModel; +import es.us.isa.qosawarewsbinding.qos.QoSProperty; +import es.us.isa.qosawarewsbinding.qos.QoSPropertyType; +import es.us.isa.qosawarewsbinding.qos.aggretation.MaxAggregationFunction; +import es.us.isa.qosawarewsbinding.qos.aggretation.MinAggregationFunction; +import es.us.isa.qosawarewsbinding.qos.aggretation.ProductoryAggregationFunction; +import es.us.isa.qosawarewsbinding.qos.aggretation.ProductoryPowAggregationFunction; +import es.us.isa.qosawarewsbinding.qos.aggretation.SumatoryAggregationFunction; +import es.us.isa.qosawarewsbinding.solution.vector.QoSAwareWSCompositionVectorSolution; +import es.us.isa.qosawarewsbinding.util.BoundedDomain; +import es.us.isa.qosawarewsbinding.util.DistributionFunction; + +/** + * + * @author japarejo + */ +public class QoSAwareWSCompositionProblemGenerator extends AbstractProblemGenerator{ + + public QoSAwareWSCompositionProblemGenerator(QoSAwareWSCompositionProblemModel model) + { + super(model); + } + + + public QoSAwareWSCompositionProblem generate() + { + WSCompositionStructure structure=generateStructure(); + WSCompositionQoSModel qosModel=generateQoSModel(); + Map> market=generateMarket(structure,qosModel); + List constraints=generateConstraints(market,qosModel); + QoSAwareWSCompositionProblem problem=new QoSAwareWSCompositionProblem(structure,market,qosModel,constraints); + generateGlobalConstraints(constraints ,market,qosModel,problem); + generateAdditionalConstraints(constraints,market,qosModel,problem); + return problem; + } + + public double computeMax(QoSProperty property, Map> market,QoSAwareWSCompositionProblem problem) { + double result=0; + double localExtremeValue; + Double value; + ConcreteWebService cwsSelected=null; + QoSAwareWSCompositionVectorSolution solution=new QoSAwareWSCompositionVectorSolution(problem); + for(AbstractWebService aws:market.keySet()) + { + localExtremeValue=Double.MIN_VALUE; + cwsSelected=null; + for(ConcreteWebService cws:market.get(aws)) + { + value=(Double)cws.getQoSValue(property); + if(value>localExtremeValue || cwsSelected==null){ + localExtremeValue=value; + cwsSelected=cws; + } + } + solution.setSelectedService(aws, cwsSelected); + } + result=problem.getQosmodel().evaluate(solution, property, problem.getStructure().getStructure()); + return result; + } + + public double computeMin(QoSProperty property, Map> market,QoSAwareWSCompositionProblem problem) { + double result=0; + double localExtremeValue; + Double value; + ConcreteWebService cwsSelected=null; + QoSAwareWSCompositionVectorSolution solution=new QoSAwareWSCompositionVectorSolution(problem); + for(AbstractWebService aws:market.keySet()) + { + localExtremeValue=Double.MAX_VALUE; + cwsSelected=null; + for(ConcreteWebService cws:market.get(aws)) + { + value=(Double)cws.getQoSValue(property); + if(value generateConstraints(Map> market, WSCompositionQoSModel qosModel) { + List result=new LinkedList(); + + return result; + } + + public void generateGlobalConstraints(List result, Map> market, WSCompositionQoSModel qosModel,QoSAwareWSCompositionProblem problem) { + QoSAwareWSCompositionProblemModel problemModel=(QoSAwareWSCompositionProblemModel)getProblemModel(); + QoSAwareWSCompositionProblemConstraintsModel constraintsModel=problemModel.getConstraintsModel(); + GlobalQoSConstraintsModel globalConstraintsModel=constraintsModel.getGlobalConstraintsModel(); + int numberOfConstraints=globalConstraintsModel.getNumberOfConstraints(); + double probability=(double)numberOfConstraints/(double)qosModel.getQosProperties().size(); + double min; + double max; + double value; + double percentage; + BinaryOperator operator; + for(QoSProperty property:qosModel.getQosProperties()) + { + if(Math.random() result, Map> market, WSCompositionQoSModel qosModel,QoSAwareWSCompositionProblem problem) { + // TODO: Implement the generation of additional constraints. + } + private Map> generateMarket(WSCompositionStructure structure, WSCompositionQoSModel qosModel) + { + QoSAwareWSCompositionProblemModel problemModel=(QoSAwareWSCompositionProblemModel)getProblemModel(); + QoSAwareWSCompositionProblemServicesMarketModel marketModel=problemModel.getMarketModel(); + return generateMarket(structure,qosModel,marketModel); + } + public Map> generateMarket(WSCompositionStructure structure, WSCompositionQoSModel qosModel,QoSAwareWSCompositionProblemServicesMarketModel marketModel) { + Map> result=new HashMap>(); + Set setCWS=null; + for(AbstractWebService aws:structure.getComponents()) + { + setCWS=generateSubMarket(aws,qosModel,marketModel); + result.put(aws, setCWS); + } + return result; + } + + + + public WSCompositionQoSModel generateQoSModel() { + Set qosProperties=new HashSet(); + QoSProperty cost=new QoSProperty("Cost",new BoundedDomain(0.0,1.0),QoSPropertyType.NEGATIVE); + QoSProperty execTime=new QoSProperty("ExecTime",new BoundedDomain(0.0,1.0),QoSPropertyType.NEGATIVE); + QoSProperty reliability=new QoSProperty("Reliability",new BoundedDomain(0.0,1.0),QoSPropertyType.POSITIVE); + QoSProperty avaliability=new QoSProperty("Availability",new BoundedDomain(0.0,1.0),QoSPropertyType.POSITIVE); + QoSProperty security=new QoSProperty("Security", new BoundedDomain(0.0,1.0),QoSPropertyType.POSITIVE); + qosProperties.add(cost); + qosProperties.add(execTime); + qosProperties.add(reliability); + qosProperties.add(avaliability); + qosProperties.add(security); + WSCompositionQoSModel qosmodel=new WSCompositionQoSModel(qosProperties); + // Weights: + Map qosWeights=new HashMap(); + qosWeights.put(cost, 0.3); + qosWeights.put(execTime, 0.3); + qosWeights.put(reliability, 0.1); + qosWeights.put(avaliability, 0.1); + qosWeights.put(security, 0.2); + qosmodel.setQosPropertiesWeights(qosWeights); + // Aggregation Functions: + // For Cost: + qosmodel.setAggregationFunction(cost, Sequence.class, SumatoryAggregationFunction.getInstance()); + qosmodel.setAggregationFunction(cost, Loop.class, SumatoryAggregationFunction.getInstance()); + qosmodel.setAggregationFunction(cost, Branch.class, SumatoryAggregationFunction.getInstance()); + qosmodel.setAggregationFunction(cost, Flow.class, SumatoryAggregationFunction.getInstance()); + // For ExecTime: + qosmodel.setAggregationFunction(execTime, Sequence.class, SumatoryAggregationFunction.getInstance()); + qosmodel.setAggregationFunction(execTime, Loop.class, SumatoryAggregationFunction.getInstance()); + qosmodel.setAggregationFunction(execTime, Branch.class, SumatoryAggregationFunction.getInstance()); + qosmodel.setAggregationFunction(execTime, Flow.class, MaxAggregationFunction.getInstance()); + // For Reliability: + qosmodel.setAggregationFunction(reliability, Sequence.class, ProductoryAggregationFunction.getInstance()); + qosmodel.setAggregationFunction(reliability, Loop.class, ProductoryPowAggregationFunction.getInstance()); + qosmodel.setAggregationFunction(reliability, Branch.class, SumatoryAggregationFunction.getInstance()); + qosmodel.setAggregationFunction(reliability, Flow.class, ProductoryAggregationFunction.getInstance()); + // For Availability: + qosmodel.setAggregationFunction(avaliability, Sequence.class, ProductoryAggregationFunction.getInstance()); + qosmodel.setAggregationFunction(avaliability, Loop.class, ProductoryPowAggregationFunction.getInstance()); + qosmodel.setAggregationFunction(avaliability, Branch.class, SumatoryAggregationFunction.getInstance()); + qosmodel.setAggregationFunction(avaliability, Flow.class, ProductoryAggregationFunction.getInstance()); + // For Security: + qosmodel.setAggregationFunction(security, Sequence.class, MinAggregationFunction.getInstance()); + qosmodel.setAggregationFunction(security, Loop.class, MinAggregationFunction.getInstance()); + qosmodel.setAggregationFunction(security, Branch.class, SumatoryAggregationFunction.getInstance()); + qosmodel.setAggregationFunction(security, Flow.class, MinAggregationFunction.getInstance()); + return qosmodel; + } + + public CompositeStructuralComponent generateStructuralComponent(QoSAwareWSCompositionProblemStructuralModel structuralModel) { + CompositeStructuralComponent result=null; + // This method must create the structural components associated with the control flow, + // asigning their ponderation (number of iterations in the case of loops, and execution probability for + // each branch in the case of IF-ELSEs. + // Moreover in the case of IF-ELSEs, this method will create a sequence as the structural componen associated with + // each branch + double random=Math.random(); + if(random<(double)(structuralModel.getPercentageLoops()/100.0)){ + int numberOfIterations=structuralModel.getIterationsPerLoop().getValue(); + result=new Loop(numberOfIterations); + }else{ + random=Math.random(); + Branch branch=new Branch(); + CompositeStructuralComponent branch1=new Sequence(); + CompositeStructuralComponent branch2=new Sequence(); + branch.addBranch(branch1, random); + branch.addBranch(branch2, (1.0-random)); + result=branch; + } + return result; + } + + private WSCompositionStructure generateStructure() + { + QoSAwareWSCompositionProblemModel problemModel=(QoSAwareWSCompositionProblemModel)getProblemModel(); + QoSAwareWSCompositionProblemStructuralModel structuralModel=problemModel.getStructuralModel(); + return generateStructure(structuralModel); + } + + public WSCompositionStructure generateStructure(QoSAwareWSCompositionProblemStructuralModel structuralModel) { + WSCompositionStructure structure=null; + int nAbstractWebServices=(100-structuralModel.getPercentageOfControlFlowActivities())*structuralModel.getNumberOfActivities()/100; + AbstractWebService []services=new AbstractWebService[nAbstractWebServices]; + // We create the abstract web services: + for(int i=0;i structuralComponents=new LinkedList(); + int nControlFlowActivities=structuralModel.getPercentageOfControlFlowActivities()*structuralModel.getNumberOfActivities()/100; + for(int i=0;i candidatesToInsertion=new LinkedList(); + candidatesToInsertion.add(root); + // We create another list to store the candidate composite components to the insertion of others that has no subcomponentes: + List emptyCandidatesToInsertion=new LinkedList(); + // We distribute this structures in a control graph (in this case in a control tree) + // having in to account the constraint on the nesting level: + + // We Create a structure to store the nesting level of each component: + Map nestingLevel=new HashMap(); + nestingLevel.put(root, 0); + // We distribute these components: + StructuralComponent currentComponentToDistribute; + CompositeStructuralComponent componentWhereWeNest; + while(!structuralComponents.isEmpty()) + { + currentComponentToDistribute=(StructuralComponent)getRandomElement(structuralComponents); + componentWhereWeNest=(CompositeStructuralComponent)getRandomElement(candidatesToInsertion); + // We impose the maximum nesting level: + while(nestingLevel.get(componentWhereWeNest)>=structuralModel.getMaxNestingLevel()) + componentWhereWeNest=(CompositeStructuralComponent)getRandomElement(candidatesToInsertion); + // We insert the structural component in a randomly selected position: + insertRandomly(currentComponentToDistribute, componentWhereWeNest); + // We updae the nesting level of each component: + updateNestingLevel(currentComponentToDistribute, componentWhereWeNest,nestingLevel,candidatesToInsertion,emptyCandidatesToInsertion); + structuralComponents.remove(currentComponentToDistribute); + } + // Once the control structure is created, we distribute the AbstractWebService invocations: + for(AbstractWebService service:services) + { + if(emptyCandidatesToInsertion.isEmpty()){ + componentWhereWeNest=(CompositeStructuralComponent)getRandomElement(candidatesToInsertion); + insertRandomly(service,componentWhereWeNest); + }else{ + componentWhereWeNest=(CompositeStructuralComponent)getRandomElement(emptyCandidatesToInsertion); + if(componentWhereWeNest instanceof Branch) + insertRandomly(service,(CompositeStructuralComponent) componentWhereWeNest.getSubComponents().get(0)); + else + insertRandomly(service,componentWhereWeNest); + emptyCandidatesToInsertion.remove(componentWhereWeNest); + } + } + AbstractWebService myservice; + int serviceIndex=0; + for(int i=services.length+nControlFlowActivities;i generateSubMarket(AbstractWebService aws, WSCompositionQoSModel qosModel, QoSAwareWSCompositionProblemServicesMarketModel marketModel) { + Set result=new HashSet(); + int numberOfCandidates=Math.max(marketModel.getNumberOfCandidates().getValue(),2); + ConcreteWebService cws=null; + DistributionFunction qosDistribution=null; + for(int i=0;i listOfSubcomponents=componentWhereWeNest.getSubComponents(); + int index=(int)(Math.floor(Math.random()*((double)listOfSubcomponents.size()))); + listOfSubcomponents.add(index, currentComponentToDistribute); + } + + private void updateNestingLevel(StructuralComponent currentComponentToDistribute, CompositeStructuralComponent componentWhereWeNest, Map nestingLevel, List candidatesToInsertion, List emptyCandidatesToInsertion) { + int parentNestingLevel=nestingLevel.get(componentWhereWeNest); + if(currentComponentToDistribute instanceof Loop){ + nestingLevel.put((Loop)currentComponentToDistribute, parentNestingLevel+1); + candidatesToInsertion.add((Loop)currentComponentToDistribute); + emptyCandidatesToInsertion.add((Loop)currentComponentToDistribute); + emptyCandidatesToInsertion.remove(componentWhereWeNest); + }else if(currentComponentToDistribute instanceof Branch){ + for(StructuralComponent subComponent:((Branch)currentComponentToDistribute).getSubComponents()){ + candidatesToInsertion.add((CompositeStructuralComponent)subComponent); + nestingLevel.put((CompositeStructuralComponent)subComponent, parentNestingLevel+1); + } + emptyCandidatesToInsertion.add((CompositeStructuralComponent)currentComponentToDistribute); + emptyCandidatesToInsertion.remove(componentWhereWeNest); + } + } + + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/GlobalQoSConstraintsModel.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/GlobalQoSConstraintsModel.java new file mode 100644 index 0000000..663808f --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/GlobalQoSConstraintsModel.java @@ -0,0 +1,45 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.problem.model; + +import es.us.isa.qosawarewsbinding.util.DistributionFunction; + + +/** + * + * @author japarejo + */ +public class GlobalQoSConstraintsModel { + private int numberOfConstraints; + private DistributionFunction dfPercentageOfOptimality; + + public GlobalQoSConstraintsModel(int numberOfConstraints, DistributionFunction dfPercentageOfOptimality) + { + this.numberOfConstraints=numberOfConstraints; + this.dfPercentageOfOptimality=dfPercentageOfOptimality; + } + + public int getNumberOfConstraints() { + return numberOfConstraints; + } + + public DistributionFunction getDfPercentageOfOptimality() { + return dfPercentageOfOptimality; + } + + public String toString() + { + StringBuffer buffer=new StringBuffer("GlobalQoSConstraintsModel("); + buffer.append("NumberOfConstraints:"+getNumberOfConstraints()); + buffer.append(",PercentageOfOptimality:"+getDfPercentageOfOptimality()); + buffer.append(")"); + return buffer.toString(); + } + + public void setNumberOfConstraints(int numberOfConstraints) { + this.numberOfConstraints = numberOfConstraints; + } +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/ProblemModel.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/ProblemModel.java new file mode 100644 index 0000000..488f100 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/ProblemModel.java @@ -0,0 +1,5 @@ +package es.us.isa.qosawarewsbinding.problem.model; + +public class ProblemModel { + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/QoSAwareWSCompositionProblemConstraintsModel.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/QoSAwareWSCompositionProblemConstraintsModel.java new file mode 100644 index 0000000..f39ebce --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/QoSAwareWSCompositionProblemConstraintsModel.java @@ -0,0 +1,39 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.problem.model; + +/** + * + * @author japarejo + */ +public class QoSAwareWSCompositionProblemConstraintsModel { + private GlobalQoSConstraintsModel globalConstraintsModel; + private ServiceDependencesConstraintsModel serviceDependencesConstraintsModel; + + public QoSAwareWSCompositionProblemConstraintsModel(GlobalQoSConstraintsModel globalConstraintsModel,ServiceDependencesConstraintsModel serviceDependencesConstraintsModel) + { + this.globalConstraintsModel=globalConstraintsModel; + this.serviceDependencesConstraintsModel=serviceDependencesConstraintsModel; + } + + public GlobalQoSConstraintsModel getGlobalConstraintsModel() { + return globalConstraintsModel; + } + + public ServiceDependencesConstraintsModel getServiceDependencesConstraintsModel() { + return serviceDependencesConstraintsModel; + } + + @Override + public String toString() + { + StringBuffer buffer=new StringBuffer("ConstraintsModel(\n"); + buffer.append(globalConstraintsModel+"\n"); + buffer.append(serviceDependencesConstraintsModel+"\n"); + buffer.append(";"); + return buffer.toString(); + } +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/QoSAwareWSCompositionProblemModel.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/QoSAwareWSCompositionProblemModel.java new file mode 100644 index 0000000..681700d --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/QoSAwareWSCompositionProblemModel.java @@ -0,0 +1,62 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.problem.model; + +import es.us.isa.qosawarewsbinding.problem.QoSAwareWSCompositionProblem; + +/** + * + * @author japarejo + */ +public class QoSAwareWSCompositionProblemModel extends ProblemModel { + private QoSAwareWSCompositionProblemStructuralModel structuralModel; + private QoSAwareWSCompositionProblemQoSModel qosModel; + private QoSAwareWSCompositionProblemServicesMarketModel marketModel; + private QoSAwareWSCompositionProblemConstraintsModel constraintsModel; + + public QoSAwareWSCompositionProblemModel(QoSAwareWSCompositionProblemStructuralModel structuralModel, QoSAwareWSCompositionProblemQoSModel qosModel,QoSAwareWSCompositionProblemServicesMarketModel marketModel,QoSAwareWSCompositionProblemConstraintsModel constraintsModel) + { + this.structuralModel=structuralModel; + this.marketModel=marketModel; + this.qosModel=qosModel; + this.constraintsModel=constraintsModel; + } + + public QoSAwareWSCompositionProblemStructuralModel getStructuralModel() { + return structuralModel; + } + + public QoSAwareWSCompositionProblemQoSModel getQosModel() { + return qosModel; + } + + public QoSAwareWSCompositionProblemServicesMarketModel getMarketModel() { + return marketModel; + } + + public QoSAwareWSCompositionProblemConstraintsModel getConstraintsModel() { + return constraintsModel; + } + + @Override + public String toString() + { + StringBuffer buffer=new StringBuffer("=== QOS-aware Web Service Composition Problem Model ===\n"); + buffer.append("== Structural Model ==\n"); + buffer.append(structuralModel); + buffer.append("== QoS Model ==\n"); + if(qosModel!=null) + buffer.append(qosModel); + buffer.append("== Market Model ==\n"); + buffer.append(marketModel); + buffer.append("== Constraints Model ==\n"); + if(constraintsModel!=null) + buffer.append(constraintsModel); + buffer.append("=======================================================\n"); + return buffer.toString(); + } + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/QoSAwareWSCompositionProblemQoSModel.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/QoSAwareWSCompositionProblemQoSModel.java new file mode 100644 index 0000000..237a603 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/QoSAwareWSCompositionProblemQoSModel.java @@ -0,0 +1,5 @@ +package es.us.isa.qosawarewsbinding.problem.model; + +public class QoSAwareWSCompositionProblemQoSModel { + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/QoSAwareWSCompositionProblemServicesMarketModel.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/QoSAwareWSCompositionProblemServicesMarketModel.java new file mode 100644 index 0000000..59a8d57 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/QoSAwareWSCompositionProblemServicesMarketModel.java @@ -0,0 +1,53 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.problem.model; + +import java.util.HashMap; +import java.util.Map; + +import es.us.isa.qosawarewsbinding.qos.QoSProperty; +import es.us.isa.qosawarewsbinding.util.DistributionFunction; + +/** + * + * @author japarejo + */ +public class QoSAwareWSCompositionProblemServicesMarketModel { + private DistributionFunction numberOfCandidates; + private Map> qosValues; + + public QoSAwareWSCompositionProblemServicesMarketModel(DistributionFunction numberOfCandidates) { + this(numberOfCandidates, new HashMap>()); + } + + public QoSAwareWSCompositionProblemServicesMarketModel(DistributionFunction numberOfCandidates, Map> qosValues) + { + this.numberOfCandidates=numberOfCandidates; + this.qosValues=qosValues; + } + + + public DistributionFunction getNumberOfCandidates() { + return numberOfCandidates; + } + + public Map> getQosValues() { + return qosValues; + } + + @Override + public String toString() + { + StringBuffer buffer=new StringBuffer("ServicesMarquetModel("); + buffer.append("NumberOfCandidates:"+numberOfCandidates+",\n"); + for(QoSProperty property:qosValues.keySet()) + { + buffer.append(" "+property.getName()+":"+qosValues.get(property)+"\n"); + } + buffer.append(")\n"); + return buffer.toString(); + } +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/QoSAwareWSCompositionProblemStructuralModel.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/QoSAwareWSCompositionProblemStructuralModel.java new file mode 100644 index 0000000..df50a81 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/QoSAwareWSCompositionProblemStructuralModel.java @@ -0,0 +1,81 @@ +package es.us.isa.qosawarewsbinding.problem.model; + +import es.us.isa.qosawarewsbinding.util.DistributionFunction; + +public class QoSAwareWSCompositionProblemStructuralModel { + private int numberOfActivities; + private int numberOfAbstractServices; + private int maxNestingLevel; + private int percentageOfControlFlowActivities; + private double percentageLoops; + private DistributionFunction iterationsPerLoop; + private DistributionFunction branchesPerIf; + + public int getNumberOfActivities() { + return numberOfActivities; + } + + public void setNumberOfActivities(int numberOfActivities) { + this.numberOfActivities = numberOfActivities; + } + + public int getNumberOfAbstractServices() { + return (numberOfActivities*(100-percentageOfControlFlowActivities))/100; + } + + public int getMaxNestingLevel() { + return maxNestingLevel; + } + + public void setMaxNestingLevel(int maxNestingLevel) { + this.maxNestingLevel = maxNestingLevel; + } + + public int getPercentageOfControlFlowActivities() { + return percentageOfControlFlowActivities; + } + + public void setPercentageOfControlFlowActivities(int cyclomaticComplexity) { + this.percentageOfControlFlowActivities = cyclomaticComplexity; + } + + public double getPercentageLoops() { + return percentageLoops; + } + + public void setPercentageLoops(double percentageLoops) { + this.percentageLoops = percentageLoops; + } + + public DistributionFunction getIterationsPerLoop() { + return iterationsPerLoop; + } + + public void setIterationsPerLoop(DistributionFunction iterationsPerLoop) { + this.iterationsPerLoop = iterationsPerLoop; + } + + public DistributionFunction getBranchesPerIf() { + return branchesPerIf; + } + + public void setBranchesPerIf(DistributionFunction branchesPerIf) { + this.branchesPerIf = branchesPerIf; + } + + @Override + public String toString() + { + StringBuffer buffer=new StringBuffer("QoSAwareStructuralModel(\n"); + String prefix=" "; + buffer.append(prefix+"NActivities="+numberOfActivities+",\n"); + buffer.append(prefix+"NAbstractServices="+numberOfAbstractServices+",\n"); + buffer.append(prefix+"PercentageOfControlFlowActivities="+percentageOfControlFlowActivities+",\n"); + buffer.append(prefix+"MaxNestingLevel="+maxNestingLevel+",\n"); + buffer.append(prefix+"PercentageOfLoops="+percentageLoops+",\n"); + buffer.append(prefix+"AverageNumberOfIterations(in Loops)="+iterationsPerLoop+",\n"); + buffer.append(prefix+"AverageNumberOfBranches(in Ifs)="+branchesPerIf+",\n"); + buffer.append(prefix+")\n"); + return buffer.toString(); + } +} \ No newline at end of file diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/ServiceDependencesConstraintsModel.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/ServiceDependencesConstraintsModel.java new file mode 100644 index 0000000..751f5af --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/problem/model/ServiceDependencesConstraintsModel.java @@ -0,0 +1,14 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.problem.model; + +/** + * + * @author japarejo + */ +public class ServiceDependencesConstraintsModel { + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/QoSProperty.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/QoSProperty.java new file mode 100644 index 0000000..d7b3bd4 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/QoSProperty.java @@ -0,0 +1,67 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package es.us.isa.qosawarewsbinding.qos; + +import java.io.Serializable; + +import es.us.isa.qosawarewsbinding.util.Domain; + +/** + * + * @author japarejo + */ +public class QoSProperty implements Serializable { + + private String name; + private Domain domain; + private QoSPropertyType type; + + public QoSProperty(String name, Domain domain, QoSPropertyType type) { + this.name = name; + this.domain = domain; + this.type = type; + } + + public QoSProperty(String name, QoSPropertyType type) { + this(name, new Domain(), type); + } + + public String getName() { + return name; + } + + public Domain getDomain() { + return domain; + } + + public QoSPropertyType getType() { + return type; + } + + @Override + public boolean equals(Object value) + { + boolean result=false; + if(value instanceof QoSProperty) + { + QoSProperty vproperty=(QoSProperty)value; + result=(vproperty.name.equalsIgnoreCase(name)) ; + } + return result; + } + + @Override + public int hashCode() { + int hash = 7; + hash = 23 * hash + (this.name != null ? this.name.hashCode() : 0); + return hash; + } + + @Override + public String toString() + { + return name+":"+type+"-"+domain; // TODO Change the separator € (problems in linux!) + } +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/QoSPropertyType.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/QoSPropertyType.java new file mode 100644 index 0000000..b6ad042 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/QoSPropertyType.java @@ -0,0 +1,12 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.qos; + +/** + * + * @author japarejo + */ +public enum QoSPropertyType {POSITIVE,NEGATIVE} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/AggregationFunction.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/AggregationFunction.java new file mode 100644 index 0000000..f1fcafb --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/AggregationFunction.java @@ -0,0 +1,19 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.qos.aggretation; + +import java.util.List; + + + +/** + * + * @author JosĆ© Antonio Parejo Maestre + */ +public interface AggregationFunction { + public Double aggregation(List values, List ponderations); + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/AverageAggregationFunction.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/AverageAggregationFunction.java new file mode 100644 index 0000000..1fccddc --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/AverageAggregationFunction.java @@ -0,0 +1,49 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.qos.aggretation; + +import java.util.List; + +/** + * + * @author JosĆ© Antonio Parejo Maestre + */ +public class AverageAggregationFunction extends NumericAggregationFunction { + + private static AverageAggregationFunction _instance=null; + + private AverageAggregationFunction(){} + + public static AverageAggregationFunction getInstance() + { + if(_instance==null) + _instance=new AverageAggregationFunction(); + return _instance; + } + + @Override + public String toString() + { + return "AVG"; + } + + + public Double aggregation(List values, List ponderations) { + Double result=new Double(0.0); + int i=0; + for(Double value:values) + if(value!=null){ + if(ponderations.get(i)!=null) + result=value*ponderations.get(i)+result; + i++; + } + if(values.size()==0) + result = 0.0; + else + result = result/values.size(); + return result; + } +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/MaxAggregationFunction.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/MaxAggregationFunction.java new file mode 100644 index 0000000..31f5a64 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/MaxAggregationFunction.java @@ -0,0 +1,47 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.qos.aggretation; + +import java.util.List; + +/** + * + * @author JosĆ© Antonio Parejo Maestre + */ +public class MaxAggregationFunction implements AggregationFunction { + + private static MaxAggregationFunction _instance=null; + + private MaxAggregationFunction(){} + + public static MaxAggregationFunction getInstance() + { + if(_instance==null) + _instance=new MaxAggregationFunction(); + return _instance; + } + + @Override + public String toString() + { + return "MAX"; + } + + + public Double aggregation(List values, List ponderations) { + Double result=Double.MIN_VALUE; + double candidate=0; + for(Double value:values) + { + candidate=value; + if(candidate>result) + result=candidate; + } + if(values.size()==0) + result=0.0; + return result; + } +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/MaxAverageAggregationFunction.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/MaxAverageAggregationFunction.java new file mode 100644 index 0000000..a206c78 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/MaxAverageAggregationFunction.java @@ -0,0 +1,49 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.qos.aggretation; + +import java.util.List; + +/** + * + * @author JosĆ© Antonio Parejo Maestre + */ +public class MaxAverageAggregationFunction implements AggregationFunction { + + private static MaxAverageAggregationFunction _instance=null; + + private MaxAverageAggregationFunction(){} + + public static MaxAverageAggregationFunction getInstance() + { + if(_instance==null) + _instance=new MaxAverageAggregationFunction(); + return _instance; + } + + @Override + public String toString() + { + return "MAXAVG"; + } + + + public Double aggregation(List values, List ponderations) { + Double result=Double.MIN_VALUE; + double candidate=0; + for(Double value:values) + { + candidate=value; + if(candidate>result) + result=candidate; + } + if(values.size()==0) + result=0.0; + else + result = result/values.size(); + return result; + } +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/MinAggregationFunction.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/MinAggregationFunction.java new file mode 100644 index 0000000..72fad95 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/MinAggregationFunction.java @@ -0,0 +1,50 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.qos.aggretation; + + +import java.util.List; + +/** + * + * @author JosĆ© Antonio Parejo Maestre + */ +public class MinAggregationFunction implements AggregationFunction{ + + private static MinAggregationFunction _instance=null; + + private MinAggregationFunction(){} + + public static MinAggregationFunction getInstance() + { + if(_instance==null) + _instance=new MinAggregationFunction(); + return _instance; + } + + @Override + public String toString() + { + return "MIN"; + } + + + public Double aggregation(List values, List ponderations) { + Double result=Double.MAX_VALUE; + double candidate=0; + for(Double value:values) + { + candidate=value; + if(candidate values, List ponderations) { + Double result=Double.MAX_VALUE; + double candidate=0; + for(Double value:values) + { + candidate=value; + if(candidate implements AggregationFunction { + + protected X obtainFromDouble(double value) + { + Class myclass=this.getClass(); + TypeVariable[] types=myclass.getTypeParameters(); + TypeVariable type=types[0]; + Class paramTypeClass=(Class)type.getGenericDeclaration(); + X result=null; + Class c; + if(Integer.TYPE.isAssignableFrom(paramTypeClass)) + { + result=(X)(new Integer((int)Math.round(value))); + }else if(Double.TYPE.isAssignableFrom(paramTypeClass)) + { + result=(X)(new Double(value)); + }else if(Long.TYPE.isAssignableFrom(paramTypeClass)) + { + result=(X)(new Long((long)Math.round(value))); + }else if(Float.TYPE.isAssignableFrom(paramTypeClass)) + { + result=(X)(new Float(value)); + } + return result; + } + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/ProductoryAggregationFunction.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/ProductoryAggregationFunction.java new file mode 100644 index 0000000..1a9bcb0 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/ProductoryAggregationFunction.java @@ -0,0 +1,45 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.qos.aggretation; + +import java.util.List; + +/** + * + * @author JosĆ© Antonio Parejo Maestre + */ +public class ProductoryAggregationFunction implements AggregationFunction { + + private static ProductoryAggregationFunction _instance=null; + + private ProductoryAggregationFunction(){} + + public static ProductoryAggregationFunction getInstance() + { + if(_instance==null) + _instance=new ProductoryAggregationFunction(); + return _instance; + } + + @Override + public String toString() + { + return "PRODUCT"; + } + + + public Double aggregation(List values, List ponderations) { + Double result=new Double(1.0); + int i=0; + for(Double value:values){ + result=result*value*ponderations.get(i); + i++; + } + if(values.size()==0) + result=0.0; + return result; + } +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/ProductoryPowAggregationFunction.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/ProductoryPowAggregationFunction.java new file mode 100644 index 0000000..86ac3d8 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/ProductoryPowAggregationFunction.java @@ -0,0 +1,44 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.qos.aggretation; + +import java.util.List; + +/** + * + * @author japarejo + */ +public class ProductoryPowAggregationFunction implements AggregationFunction { + private static ProductoryPowAggregationFunction _instance=null; + + private ProductoryPowAggregationFunction(){} + + public static ProductoryPowAggregationFunction getInstance() + { + if(_instance==null) + _instance=new ProductoryPowAggregationFunction(); + return _instance; + } + + + public Double aggregation(List values, List ponderations) { + double result=1; + for(Double value:values) + if(value!=0) + result*=value; + double ponderation=1; + if(ponderations.size()>0) + ponderation=ponderations.get(0); + result=Math.pow(result, ponderation); + return result; + } + + @Override + public String toString() + { + return "POW"; + } +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/SumatoryAggregationFunction.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/SumatoryAggregationFunction.java new file mode 100644 index 0000000..3df8fb9 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/SumatoryAggregationFunction.java @@ -0,0 +1,46 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.qos.aggretation; + +import java.util.List; + +/** + * + * @author JosĆ© Antonio Parejo Maestre + */ +public class SumatoryAggregationFunction extends NumericAggregationFunction { + + private static SumatoryAggregationFunction _instance=null; + + private SumatoryAggregationFunction(){} + + public static SumatoryAggregationFunction getInstance() + { + if(_instance==null) + _instance=new SumatoryAggregationFunction(); + return _instance; + } + + @Override + public String toString() + { + return "SUM"; + } + + + public Double aggregation(List values, List ponderations) { + Double result=new Double(0.0); + int i=0; + for(Double value:values) + if(value!=null){ + if(ponderations.get(i)!=null) + result=value*ponderations.get(i)+result; + i++; + } + return result; + } + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/SumatoryPowAggregationFunction.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/SumatoryPowAggregationFunction.java new file mode 100644 index 0000000..46ea87b --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/qos/aggretation/SumatoryPowAggregationFunction.java @@ -0,0 +1,44 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.qos.aggretation; + +import java.util.List; + +/** + * + * @author japarejo + */ +public class SumatoryPowAggregationFunction implements AggregationFunction { + + private static SumatoryPowAggregationFunction _instance=null; + + private SumatoryPowAggregationFunction(){} + + public static SumatoryPowAggregationFunction getInstance() + { + if(_instance==null) + _instance=new SumatoryPowAggregationFunction(); + return _instance; + } + + + public Double aggregation(List values, List ponderations) { + double result=0; + for(Double value:values) + result+=value; + double ponderation=1; + if(ponderations.size()>0) + ponderation=ponderations.get(0); + result=Math.pow(result, ponderation); + return result; + } + + public String toString() + { + return "SUMPOW"; + } + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/AbstractSolution.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/AbstractSolution.java new file mode 100644 index 0000000..a69c51f --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/AbstractSolution.java @@ -0,0 +1,63 @@ +package es.us.isa.qosawarewsbinding.solution; + +import es.us.isa.qosawarewsbinding.problem.Problem; + +public abstract class AbstractSolution implements Solution { + + protected double fitness; + protected T problem; + + public AbstractSolution(T problem) { + this.problem = problem; + fitness = Double.MAX_VALUE; + } + + public double getFitness() { + if (fitness == Double.MAX_VALUE && problem != null) + fitness = problem.fitness(this); + return fitness; + } + + public abstract Solution createRandom(); + + /** + * Getter for property problem. + * + * @return Value of property problem. + */ + public T getProblem() { + return problem; + } + + /** + * Setter for property problem. + * + * @param problem + * New value of property problem. + */ + public void setProblem(T problem) { + this.problem = problem; + } + + /** + * Funcin de ordenacin natural en base al ndice de evaluacin. Por defecto, + * si el objeto no es una solucin se consideran iguales. + */ + + public int compareTo(Object obj) { + int result = 0; + if (obj instanceof Solution) { + if (this.fitness > ((Solution) obj).getFitness()) + result = 1; + else if (this.fitness < ((Solution) obj).getFitness()) + result = -1; + } + return result; + } + + @Override + public String toString() { + return "Fitness:" + fitness; + } + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/QoSAwareWSCompositionSolution.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/QoSAwareWSCompositionSolution.java new file mode 100644 index 0000000..28df79c --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/QoSAwareWSCompositionSolution.java @@ -0,0 +1,60 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.solution; + +import java.util.Map; + +import es.us.isa.qosawarewsbinding.AbstractWebService; +import es.us.isa.qosawarewsbinding.ConcreteWebService; +import es.us.isa.qosawarewsbinding.problem.QoSAwareWSCompositionProblem; + +/** + * + * @author japarejo + */ +public abstract class QoSAwareWSCompositionSolution extends + AbstractSolution { + + public QoSAwareWSCompositionSolution(QoSAwareWSCompositionProblem problem) { + super(problem); + } + + public abstract ConcreteWebService getSelectedService(AbstractWebService aws); + + public abstract void setSelectedService(AbstractWebService aws, + ConcreteWebService cws); + + public boolean isUsingServices( + Map cwservices) { + boolean result = true; + int i = 0; + for (AbstractWebService aws : cwservices.keySet()) { + if (!isUsing(aws, cwservices.get(aws))) + return false; + } + return result; + } + + public boolean isUsing(AbstractWebService aws, ConcreteWebService cws) { + return cws == getSelectedService(aws); + } + + @Override + public String toString() { + StringBuffer buffer = new StringBuffer("("); + QoSAwareWSCompositionProblem myproblem = (QoSAwareWSCompositionProblem) problem; + for (AbstractWebService aws : myproblem.getStructure().getComponents()) { + buffer.append("|"); + buffer.append(aws.toString()); + buffer.append("->"); + buffer.append(getSelectedService(aws)); + buffer.append("|"); + } + buffer.append("),"); + buffer.append(super.toString()); + return buffer.toString(); + } +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/Solution.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/Solution.java new file mode 100644 index 0000000..9a0d7f5 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/Solution.java @@ -0,0 +1,8 @@ +package es.us.isa.qosawarewsbinding.solution; + + +public interface Solution extends Comparable,Cloneable { + public double getFitness(); + public Solution createRandom(); + public int compareTo(Object obj); +} \ No newline at end of file diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/vector/QoSAwareWSCompositionProblemInteger.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/vector/QoSAwareWSCompositionProblemInteger.java new file mode 100644 index 0000000..9a2828c --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/vector/QoSAwareWSCompositionProblemInteger.java @@ -0,0 +1,184 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.solution.vector; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import es.us.isa.qosawarewsbinding.AbstractWebService; +import es.us.isa.qosawarewsbinding.ConcreteWebService; +import es.us.isa.qosawarewsbinding.WSCompositionStructure; +import es.us.isa.qosawarewsbinding.problem.ExecutionPath; +import es.us.isa.qosawarewsbinding.problem.QoSAwareWSCompositionProblem; +import es.us.isa.qosawarewsbinding.problem.WSCompositionConstraint; +import es.us.isa.qosawarewsbinding.qos.QoSProperty; +import es.us.isa.qosawarewsbinding.qos.QoSPropertyType; +import es.us.isa.qosawarewsbinding.solution.QoSAwareWSCompositionSolution; +import es.us.isa.qosawarewsbinding.solution.Solution; + +/** + * + * @author japarejo + */ +public class QoSAwareWSCompositionProblemInteger extends QoSAwareWSCompositionProblem { + + private Map abstractWebServicesIndexes; + private QoSAwareWSCompositionProblem problem; + private ConcreteWebService[][] services; + + + public QoSAwareWSCompositionProblemInteger(QoSAwareWSCompositionProblem problem) + { + super(problem.getStructure(),problem.getQosmodel()); + this.problem=problem; + abstractWebServicesIndexes=new HashMap(); + int numberofAbstractServices=problem.getMarket().keySet().size(); + services=new ConcreteWebService[numberofAbstractServices][]; + int i=0; + int j=0; + for(AbstractWebService aws:problem.getMarket().keySet()){ + abstractWebServicesIndexes.put(aws, i); + services[i]=new ConcreteWebService[problem.getMarket().get(aws).size()]; + j=0; + for(ConcreteWebService service:problem.getMarket().get(aws)){ + services[i][j]=service; + j++; + } + i++; + } + } + + @Override + public double feasibilityDistance(Solution sol) { + return problem.feasibilityDistance(sol); + } + + @Override + public double feasibilityFreeFitness(Solution sol) { + return problem.feasibilityFreeFitness(sol); + } + + + @Override + public int numberOfCandidates(AbstractWebService aws) + { + return problem.numberOfCandidates(aws); + } + + @Override + public Map> getMarket() { + return problem.getMarket(); + } + + @Override + public WSCompositionStructure getStructure() + { + return problem.getStructure(); + } + + public int numberOfCandidates(int aws) + { + return services[aws].length; + } + + public ConcreteWebService getService(int aws, int index) + { + return services[aws][index]; + } + + public int getIndex(AbstractWebService aws) + { + return abstractWebServicesIndexes.get(aws); + } + + int getServiceIndex(int aws, ConcreteWebService cws) { + ConcreteWebService []concreteservices=services[aws]; + int result=-1; + for(int i=0;i getExpaths() { + return problem.getExpaths(); + } + + public double numberOfExecutedTasks() + { + return problem.numberOfExecutedTasks(); + } + + @Override + public List getConstraints() { + return problem.getConstraints(); + } + + public Double bestValue(QoSProperty property) { + QoSAwareWSCompositionSolution solution = computeBestSolution(property); + return getQosmodel().evaluate(solution, property, getStructure()); + } + + public Double worstValue(QoSProperty property) { + QoSAwareWSCompositionSolution solution = computeWorstSolution(property); + return getQosmodel().evaluate(solution, property, getStructure()); + } + + public QoSAwareWSCompositionSolution computeBestSolution(QoSProperty property) { + QoSAwareWSCompositionVectorSolution result = new QoSAwareWSCompositionVectorSolution(this); + ConcreteWebService bestCandidate; + ConcreteWebService cws; + Set abstractServices = this.abstractWebServicesIndexes.keySet(); + int i; + for(AbstractWebService aws: abstractServices){ + i = this.abstractWebServicesIndexes.get(aws); + bestCandidate = services[i][0]; + for(int j=0; j ((Double) bestCandidate.getQoSValue(property))) { + bestCandidate = cws; + } + } else { + if (((Double) cws.getQoSValue(property)) < ((Double) bestCandidate.getQoSValue(property))) { + bestCandidate = cws; + } + } + } + result.setSelectedService(aws, bestCandidate); + } + return result; + } + + public QoSAwareWSCompositionSolution computeWorstSolution(QoSProperty property) { + QoSAwareWSCompositionVectorSolution result = new QoSAwareWSCompositionVectorSolution(this); + ConcreteWebService worstCandidate = null; + ConcreteWebService cws; + Set abstractServices = this.abstractWebServicesIndexes.keySet(); + int i; + for(AbstractWebService aws: abstractServices){ + i = this.abstractWebServicesIndexes.get(aws); + worstCandidate = services[i][0]; + for(int j=0; j ((Double) worstCandidate.getQoSValue(property))) { + worstCandidate = cws; + } + } + } + result.setSelectedService(aws, worstCandidate); + } + return result; + } +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/vector/QoSAwareWSCompositionVectorMovement.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/vector/QoSAwareWSCompositionVectorMovement.java new file mode 100644 index 0000000..d510fe5 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/vector/QoSAwareWSCompositionVectorMovement.java @@ -0,0 +1,99 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.solution.vector; + + +/** + * + * @author japarejo + */ +public class QoSAwareWSCompositionVectorMovement { + + private int abstractWebService; + private int previousSelectedService; + private int newSelectedService; + + public QoSAwareWSCompositionVectorMovement(QoSAwareWSCompositionVectorSolutionNavigable solution) + { + + QoSAwareWSCompositionProblemInteger problem=(QoSAwareWSCompositionProblemInteger)solution.getProblem(); + int services=problem.getMarket().keySet().size(); + while(abstractWebService=problem.numberOfCandidates(result.abstractWebService)){ + result.abstractWebService++; + if(result.abstractWebService==services){ + result.abstractWebService=0; + } + while(result.abstractWebService1) + result.newSelectedService=1; + } + result.previousSelectedService=solution.getSelectedService(result.abstractWebService); + return result; + } + + @Override + public String toString() + { + return "["+abstractWebService+","+previousSelectedService+","+newSelectedService+"]"; + } + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/vector/QoSAwareWSCompositionVectorSolution.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/vector/QoSAwareWSCompositionVectorSolution.java new file mode 100644 index 0000000..837594f --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/solution/vector/QoSAwareWSCompositionVectorSolution.java @@ -0,0 +1,96 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.solution.vector; + +import es.us.isa.qosawarewsbinding.AbstractWebService; +import es.us.isa.qosawarewsbinding.ConcreteWebService; +import es.us.isa.qosawarewsbinding.problem.QoSAwareWSCompositionProblem; +import es.us.isa.qosawarewsbinding.solution.QoSAwareWSCompositionSolution; +import es.us.isa.qosawarewsbinding.solution.Solution; + +/** + * + * @author japarejo + */ +public class QoSAwareWSCompositionVectorSolution extends QoSAwareWSCompositionSolution { + + protected int[] selectedServicesIndexes; + + public QoSAwareWSCompositionVectorSolution(QoSAwareWSCompositionProblem problem) + { + super(problem); + if(!(problem instanceof QoSAwareWSCompositionProblemInteger)) + this.problem=new QoSAwareWSCompositionProblemInteger(problem); + selectedServicesIndexes=new int[problem.getMarket().keySet().size()]; + //for(int i=0;i=0 && aws listTasks = new ArrayList(tasks); + for (int i = 0; i < tasks; i++) + if (theproblem.numberOfCandidates(i) > 1) + listTasks.add(new Integer(i)); + int randomAWS = (int) Math.floor(Math.random() + * ((double) listTasks.size())); + int tries = 0; + while (theproblem.numberOfCandidates(randomAWS) < 2 && tries < 5) { + randomAWS = (int) Math.floor(Math.random() + * ((double) listTasks.size())); + tries++; + } + int nCandidates = theproblem.numberOfCandidates(randomAWS); + if (nCandidates > 1) { + List listCandidates = new ArrayList( + nCandidates - 2); + for (int i = 0; i < nCandidates; i++) + if (selectedServicesIndexes[randomAWS] != i) + listCandidates.add(new Integer(i)); + int randomCandidateIndex = (int) Math.floor(Math.random() + * ((double) listCandidates.size())); + result = new QoSAwareWSCompositionVectorSolutionNavigable( + theproblem); + System.arraycopy(selectedServicesIndexes, 0, + result.selectedServicesIndexes, 0, + selectedServicesIndexes.length); + result.selectedServicesIndexes[randomAWS] = listCandidates + .get(randomCandidateIndex); + } + return result; + } + + @Override + public Solution createRandom() { + return new QoSAwareWSCompositionVectorSolutionNavigable( + (QoSAwareWSCompositionProblem) problem); + } + + public void resetNeighbourhood() { + QoSAwareWSCompositionProblemInteger theproblem = (QoSAwareWSCompositionProblemInteger) problem; + int tasks = selectedServicesIndexes.length; + movement = new QoSAwareWSCompositionVectorMovement(this); + neighboursToExplore = 0; + for (int i = 0; i < tasks; i++) { + neighboursToExplore += theproblem.numberOfCandidates(i) - 1; + } + } + + @Override + public String toString() { + return super.toString(); + } + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/BoundedDomain.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/BoundedDomain.java new file mode 100644 index 0000000..9160f9c --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/BoundedDomain.java @@ -0,0 +1,72 @@ +package es.us.isa.qosawarewsbinding.util; + + +public class BoundedDomain extends IntensionDomain { + + + private ComparableType minBound; + + + private ComparableType maxBound; + + + public BoundedDomain () { + super(); + } + + public BoundedDomain(ComparableType valuemin, ComparableType valuemax) + { + minBound=valuemin; + maxBound=valuemax; + } + + + public ComparableType getMaxBound () { + return maxBound; + } + + public void setMaxBound (ComparableType val) { + this.maxBound = val; + } + + public ComparableType getMinBound () { + return minBound; + } + + public void setMinBound (ComparableType val) { + this.minBound = val; + } + + @Override + public boolean predicate (ComparableType value) { + return minBound.doubleValue()<=value.doubleValue() && maxBound.doubleValue()>=value.doubleValue(); + } + + @Override + public boolean equals(Object value) + { + boolean result=false; + if(value instanceof BoundedDomain) + { + BoundedDomain dom=(BoundedDomain)value; + result=minBound.equals(dom.getMinBound()) && maxBound.equals(dom.getMaxBound()); + } + return result; + } + + @Override + public int hashCode() { + int hash = 3; + hash = 17 * hash + (this.minBound != null ? this.minBound.hashCode() : 0); + hash = 17 * hash + (this.maxBound != null ? this.maxBound.hashCode() : 0); + return hash; + } + + @Override + public String toString() + { + return minBound.getClass().getSimpleName()+"["+minBound.toString()+","+maxBound.toString()+"]"; + } +} + + diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/BoundedDoubleGaussianDistributionFunction.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/BoundedDoubleGaussianDistributionFunction.java new file mode 100644 index 0000000..583e73a --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/BoundedDoubleGaussianDistributionFunction.java @@ -0,0 +1,54 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.util; + +/** + * + * @author japarejo + */ +public class BoundedDoubleGaussianDistributionFunction extends DoubleGaussianDistributionFunction { + private double min; + private double max; + public BoundedDoubleGaussianDistributionFunction(double mean, double standardDeviation) + { + this(mean,standardDeviation,Double.MIN_VALUE,Double.MAX_VALUE); + } + + public BoundedDoubleGaussianDistributionFunction(double mean, double standardDeviation, double min, double max) + { + super(mean,standardDeviation); + this.min=min; + this.max=max; + } + + @Override + public Double getValue() { + Double result=super.getValue(); + if(resultgetMax()) + result=getMax(); + return result; + } + + public double getMin() { + return min; + } + + public void setMin(double min) { + this.min = min; + } + + public double getMax() { + return max; + } + + public void setMax(double max) { + this.max = max; + } + + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/DistributionFunction.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/DistributionFunction.java new file mode 100644 index 0000000..620cfff --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/DistributionFunction.java @@ -0,0 +1,14 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.util; + +/** + * + * @author japarejo + */ +public interface DistributionFunction { + public T getValue(); +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/Domain.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/Domain.java new file mode 100644 index 0000000..4191cf0 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/Domain.java @@ -0,0 +1,11 @@ +package es.us.isa.qosawarewsbinding.util; + +public class Domain { + public Domain() { + } + + public boolean belongs(T value) { + return true; + } + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/DoubleGaussianDistributionFunction.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/DoubleGaussianDistributionFunction.java new file mode 100644 index 0000000..df2ae45 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/DoubleGaussianDistributionFunction.java @@ -0,0 +1,55 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package es.us.isa.qosawarewsbinding.util; + +import org.apache.commons.math.random.RandomData; +import org.apache.commons.math.random.RandomDataImpl; + + +/** + * + * @author japarejo + */ +public class DoubleGaussianDistributionFunction implements DistributionFunction { + + protected Double mean; + protected Double standarDeviation; + RandomData dataGenerator; + + public DoubleGaussianDistributionFunction(double mean, double standardDeviation) { + this.mean = mean; + this.standarDeviation = standardDeviation; + dataGenerator = new RandomDataImpl(); + } + + + public Double getValue() { + Double result = mean; + result = dataGenerator.nextGaussian(mean, standarDeviation); + return result; + } + + public double getMean() { + return mean; + } + + public void setMean(double mean) { + this.mean = mean; + } + + public double getStandarDeviation() { + return standarDeviation; + } + + public void setStandarDeviation(double standardDeviation) { + this.standarDeviation = standardDeviation; + } + + @Override + public String toString() + { + return "Gaussian(Mean:"+mean+",StandardDeviation:"+standarDeviation+")"; + } +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/DoubleUniformDistributionFunction.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/DoubleUniformDistributionFunction.java new file mode 100644 index 0000000..94f4aea --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/DoubleUniformDistributionFunction.java @@ -0,0 +1,51 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.util; + +/** + * + * @author japarejo + */ +public class DoubleUniformDistributionFunction implements DistributionFunction { + + private Double min; + private Double max; + + public DoubleUniformDistributionFunction(Double min, Double max) + { + this.min=min; + this.max=max; + } + + + public Double getValue() { + return getMin()+Math.random()*(getMax()-getMin()); + + } + + public Double getMin() { + return min; + } + + public void setMin(Double min) { + this.min = min; + } + + public Double getMax() { + return max; + } + + public void setMax(Double max) { + this.max = max; + } + + @Override + public String toString() + { + return "Uniform(Min:"+min+",Max:"+max+")"; + } + +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/IntegerGausssianDistributionFunction.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/IntegerGausssianDistributionFunction.java new file mode 100644 index 0000000..ae6d4a6 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/IntegerGausssianDistributionFunction.java @@ -0,0 +1,55 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.util; + +import org.apache.commons.math.random.RandomData; +import org.apache.commons.math.random.RandomDataImpl; + +/** + * + * @author japarejo + */ +public class IntegerGausssianDistributionFunction implements DistributionFunction{ + + Integer mean; + Double standarDeviation; + RandomData dataGenerator; + + public IntegerGausssianDistributionFunction(Integer mean, Double standarDeviation) + { + this.mean=mean; + this.standarDeviation=standarDeviation; + dataGenerator=new RandomDataImpl(); + } + + + public Integer getValue() { + Integer result = mean; + result = new Integer((int)Math.round((float)(dataGenerator.nextGaussian(mean, standarDeviation)))); + return result; + } + + public Integer getMean() { + return mean; + } + + public void setMean(Integer mean) { + this.mean = mean; + } + + public double getStandarDeviation() { + return standarDeviation; + } + + public void setStandarDeviation(double standardDeviation) { + this.standarDeviation = standardDeviation; + } + + public String toString() + { + return "Gaussian(Mean:"+mean+",StandardDeviation:"+standarDeviation+")"; + } +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/IntegerUniformDistributionFunction.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/IntegerUniformDistributionFunction.java new file mode 100644 index 0000000..d0f1537 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/IntegerUniformDistributionFunction.java @@ -0,0 +1,50 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package es.us.isa.qosawarewsbinding.util; + +/** + * + * @author japarejo + */ +public class IntegerUniformDistributionFunction implements DistributionFunction { + + private Integer min; + private Integer max; + + public IntegerUniformDistributionFunction(Integer min, Integer max) + { + this.min=min; + this.max=max; + } + + + public Integer getValue() { + double value=getMin().doubleValue()+Math.random()*(getMax().doubleValue()-getMin().doubleValue()); + return (int)Math.round(value); + } + + public Integer getMin() { + return min; + } + + public void setMin(Integer min) { + this.min = min; + } + + public Integer getMax() { + return max; + } + + public void setMax(Integer max) { + this.max = max; + } + + @Override + public String toString() + { + return "Uniform(Min:"+min+",Max:"+max+")"; + } +} diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/IntensionDomain.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/IntensionDomain.java new file mode 100644 index 0000000..0688204 --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/IntensionDomain.java @@ -0,0 +1,16 @@ +package es.us.isa.qosawarewsbinding.util; + + +public abstract class IntensionDomain extends Domain { + + public IntensionDomain () { + } + + public boolean belongs (T value) { + return predicate(value); + } + + public abstract boolean predicate (T value); + +} + diff --git a/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/MyStringTokenizer.java b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/MyStringTokenizer.java new file mode 100644 index 0000000..81d8cea --- /dev/null +++ b/engines/many-obj/src/main/java/es/us/isa/qosawarewsbinding/util/MyStringTokenizer.java @@ -0,0 +1,70 @@ +package es.us.isa.qosawarewsbinding.util; + +public class MyStringTokenizer { + + int nDelimiters; + String input; + String separator; + char startDelimiter; + char endDelimiter; + /** Creates new MyStringTokenizer */ + public MyStringTokenizer(String entrada,String separador,char startDelimiter, char endDelimiter) + { + this.input=entrada; + this.separator=separador; + nDelimiters=0; + this.startDelimiter=startDelimiter; + this.endDelimiter=endDelimiter; + } + public MyStringTokenizer(String entrada,String separador) { + this(entrada,separador,'(',')'); + } + + public String nextToken(String separador) + { + this.separator=separador; + return nextToken(); + } + public String nextToken() + { + String resultado=""; + int indice=input.indexOf(separator); + if(indice<0){ + resultado=input; + input=""; + return resultado; + } + + nDelimiters=countDelimiters(input.substring(0,indice)); + while(nDelimiters!=0) + { + indice=input.indexOf(separator,indice+separator.length()); + nDelimiters=countDelimiters(input.substring(0,indice+separator.length())); + } + if(indice<0){ + resultado=input; + input=""; + }else + { + resultado=input.substring(0,indice); + input=input.substring(indice+separator.length(),input.length()); + } + return resultado; + } + + public int countDelimiters(String s) + { + int parentesis=0; + for(int i=0;i=", "value": 0.9 - }, - { - "id": "dc1", "kind": "dependency", "type": "different_provider", "tasks": ["t1", "t2"] - } + { + "id": "lc1", + "kind": "attribute_bound", + "scope": "local", + "task_id": "t1", + "attribute_id": "reliability", + "op": ">=", + "value": 0.9 + }, + { + "id": "dc1", + "kind": "dependency", + "type": "different_provider", + "tasks": [ + "t1", + "t2" + ] + } ], "objective": { "type": "weighted_sum", - "weights": { "cost": 1.0 }, + "weights": { + "cost": 1.0 + }, "normalized": true } } -} +} \ No newline at end of file diff --git a/examples/constraints-global-strict.json b/examples/constraints-global-strict.json index dfdb1e4..2cbe2af 100644 --- a/examples/constraints-global-strict.json +++ b/examples/constraints-global-strict.json @@ -7,23 +7,128 @@ "version": "1.0", "created_at": "2024-01-01T00:00:00Z" }, - "providers": [{"id": "p1", "name": "Provider 1"}], + "providers": [ + { + "id": "p1", + "name": "Provider 1" + } + ], "tasks": [ - {"id": "t1", "name": "Task 1"}, - {"id": "t2", "name": "Task 2"} + { + "id": "t1", + "name": "Task 1" + }, + { + "id": "t2", + "name": "Task 2" + } ], "candidates": [ - { "id": "t1_cheap", "task_id": "t1", "provider_id": "p1", "qos": { "cost": 1, "time": 100, "reliability": 0.5, "availability": 0.5, "security": 0.5 } }, - { "id": "t1_expensive", "task_id": "t1", "provider_id": "p1", "qos": { "cost": 10, "time": 10, "reliability": 0.9, "availability": 0.9, "security": 0.9 } }, - { "id": "t2_cheap", "task_id": "t2", "provider_id": "p1", "qos": { "cost": 1, "time": 100, "reliability": 0.5, "availability": 0.5, "security": 0.5 } }, - { "id": "t2_expensive", "task_id": "t2", "provider_id": "p1", "qos": { "cost": 10, "time": 10, "reliability": 0.9, "availability": 0.9, "security": 0.9 } } + { + "id": "t1_cheap", + "task_id": "t1", + "provider_id": "p1", + "features": { + "cost": 1, + "time": 100, + "reliability": 0.5, + "availability": 0.5, + "security": 0.5 + } + }, + { + "id": "t1_expensive", + "task_id": "t1", + "provider_id": "p1", + "features": { + "cost": 10, + "time": 10, + "reliability": 0.9, + "availability": 0.9, + "security": 0.9 + } + }, + { + "id": "t2_cheap", + "task_id": "t2", + "provider_id": "p1", + "features": { + "cost": 1, + "time": 100, + "reliability": 0.5, + "availability": 0.5, + "security": 0.5 + } + }, + { + "id": "t2_expensive", + "task_id": "t2", + "provider_id": "p1", + "features": { + "cost": 10, + "time": 10, + "reliability": 0.9, + "availability": 0.9, + "security": 0.9 + } + } ], "features": [ - { "id": "cost", "name": "Cost", "direction": "minimize", "unit": "USD", "scale": "ratio", "valid_range": {"min": 0, "max": 100}, "normalization": { "type": "minmax", "bounds": { "min": 0, "max": 20 } } }, - { "id": "time", "name": "Time", "direction": "minimize", "unit": "ms", "scale": "ratio", "valid_range": {"min": 0, "max": 1000}, "normalization": { "type": "minmax", "bounds": { "min": 0, "max": 100 } } }, - { "id": "reliability", "name": "Rel", "direction": "maximize", "unit": "prob", "scale": "ratio", "valid_range": {"min": 0, "max": 1}, "normalization": { "type": "minmax", "bounds": { "min": 0, "max": 1 } } }, - { "id": "availability", "name": "Avail", "direction": "maximize", "unit": "prob", "scale": "ratio", "valid_range": {"min": 0, "max": 1}, "normalization": { "type": "minmax", "bounds": { "min": 0, "max": 1 } } }, - { "id": "security", "name": "Sec", "direction": "maximize", "unit": "prob", "scale": "ratio", "valid_range": {"min": 0, "max": 1}, "normalization": { "type": "minmax", "bounds": { "min": 0, "max": 1 } } } + { + "id": "cost", + "name": "Cost", + "direction": "minimize", + "unit": "USD", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 100 + } + }, + { + "id": "time", + "name": "Time", + "direction": "minimize", + "unit": "ms", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1000 + } + }, + { + "id": "reliability", + "name": "Rel", + "direction": "maximize", + "unit": "prob", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1 + } + }, + { + "id": "availability", + "name": "Avail", + "direction": "maximize", + "unit": "prob", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1 + } + }, + { + "id": "security", + "name": "Sec", + "direction": "maximize", + "unit": "prob", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1 + } + } ], "composition": { "type": "structured", @@ -31,22 +136,36 @@ "id": "root", "kind": "SEQ", "children": [ - { "id": "n1", "kind": "TASK", "task_id": "t1" }, - { "id": "n2", "kind": "TASK", "task_id": "t2" } + { + "id": "n1", + "kind": "TASK", + "task_id": "t1" + }, + { + "id": "n2", + "kind": "TASK", + "task_id": "t2" + } ] } }, "aggregation_policies": {}, "constraints": [ - { - "id": "gc1", "kind": "attribute_bound", "scope": "global", - "attribute_id": "cost", "op": "<=", "value": 2.0 - } + { + "id": "gc1", + "kind": "attribute_bound", + "scope": "global", + "attribute_id": "cost", + "op": "<=", + "value": 2.0 + } ], "objective": { "type": "weighted_sum", - "weights": { "time": 1.0 }, + "weights": { + "time": 1.0 + }, "normalized": true } } -} +} \ No newline at end of file diff --git a/examples/constraints-infeasible.json b/examples/constraints-infeasible.json index f7134d4..d9aff49 100644 --- a/examples/constraints-infeasible.json +++ b/examples/constraints-infeasible.json @@ -7,38 +7,115 @@ "version": "1.0", "created_at": "2024-01-01T00:00:00Z" }, - "providers": [{"id": "p1", "name": "Provider 1"}], + "providers": [ + { + "id": "p1", + "name": "Provider 1" + } + ], "tasks": [ - {"id": "t1", "name": "Task 1"} + { + "id": "t1", + "name": "Task 1" + } ], "candidates": [ - { "id": "c1", "task_id": "t1", "provider_id": "p1", "qos": { "cost": 1, "time": 10, "reliability": 0.99, "availability": 0.99, "security": 0.99 } } + { + "id": "c1", + "task_id": "t1", + "provider_id": "p1", + "features": { + "cost": 1, + "time": 10, + "reliability": 0.99, + "availability": 0.99, + "security": 0.99 + } + } ], "features": [ - { "id": "cost", "name": "Cost", "direction": "minimize", "unit": "USD", "scale": "ratio", "valid_range": {"min": 0, "max": 100}, "normalization": { "type": "minmax", "bounds": { "min": 0, "max": 20 } } }, - { "id": "time", "name": "Time", "direction": "minimize", "unit": "ms", "scale": "ratio", "valid_range": {"min": 0, "max": 1000}, "normalization": { "type": "minmax", "bounds": { "min": 0, "max": 100 } } }, - { "id": "reliability", "name": "Rel", "direction": "maximize", "unit": "prob", "scale": "ratio", "valid_range": {"min": 0, "max": 1}, "normalization": { "type": "minmax", "bounds": { "min": 0, "max": 1 } } }, - { "id": "availability", "name": "Avail", "direction": "maximize", "unit": "prob", "scale": "ratio", "valid_range": {"min": 0, "max": 1}, "normalization": { "type": "minmax", "bounds": { "min": 0, "max": 1 } } }, - { "id": "security", "name": "Sec", "direction": "maximize", "unit": "prob", "scale": "ratio", "valid_range": {"min": 0, "max": 1}, "normalization": { "type": "minmax", "bounds": { "min": 0, "max": 1 } } } + { + "id": "cost", + "name": "Cost", + "direction": "minimize", + "unit": "USD", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 100 + } + }, + { + "id": "time", + "name": "Time", + "direction": "minimize", + "unit": "ms", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1000 + } + }, + { + "id": "reliability", + "name": "Rel", + "direction": "maximize", + "unit": "prob", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1 + } + }, + { + "id": "availability", + "name": "Avail", + "direction": "maximize", + "unit": "prob", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1 + } + }, + { + "id": "security", + "name": "Sec", + "direction": "maximize", + "unit": "prob", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1 + } + } ], "composition": { "type": "structured", "root": { "id": "root", - "kind": "TASK", "task_id": "t1" + "kind": "TASK", + "task_id": "t1" } }, "aggregation_policies": {}, "constraints": [ - { - "id": "impossible_rel", "kind": "attribute_bound", "scope": "local", "task_id": "t1", - "attribute_id": "reliability", "op": ">=", "value": 1.0 - } + { + "id": "impossible_rel", + "kind": "attribute_bound", + "scope": "local", + "task_id": "t1", + "attribute_id": "reliability", + "op": ">=", + "value": 1.0 + } ], "objective": { "type": "weighted_sum", - "weights": { "cost": 1.0 }, + "weights": { + "cost": 1.0 + }, "normalized": true } } -} +} \ No newline at end of file diff --git a/examples/constraints-same-provider.json b/examples/constraints-same-provider.json index 9db38d6..0586ca0 100644 --- a/examples/constraints-same-provider.json +++ b/examples/constraints-same-provider.json @@ -8,26 +8,131 @@ "created_at": "2024-01-01T00:00:00Z" }, "providers": [ - {"id": "p1", "name": "Provider 1"}, - {"id": "p2", "name": "Provider 2"} + { + "id": "p1", + "name": "Provider 1" + }, + { + "id": "p2", + "name": "Provider 2" + } ], "tasks": [ - {"id": "t1", "name": "Task 1"}, - {"id": "t2", "name": "Task 2"} + { + "id": "t1", + "name": "Task 1" + }, + { + "id": "t2", + "name": "Task 2" + } ], "candidates": [ - { "id": "t1_p1_great", "task_id": "t1", "provider_id": "p1", "qos": { "cost": 10, "time": 10, "reliability": 0.99, "availability": 0.9, "security": 0.9 } }, - { "id": "t1_p2_bad", "task_id": "t1", "provider_id": "p2", "qos": { "cost": 10, "time": 100, "reliability": 0.1, "availability": 0.9, "security": 0.9 } }, - - { "id": "t2_p1_bad", "task_id": "t2", "provider_id": "p1", "qos": { "cost": 10, "time": 100, "reliability": 0.1, "availability": 0.9, "security": 0.9 } }, - { "id": "t2_p2_great", "task_id": "t2", "provider_id": "p2", "qos": { "cost": 10, "time": 10, "reliability": 0.99, "availability": 0.9, "security": 0.9 } } + { + "id": "t1_p1_great", + "task_id": "t1", + "provider_id": "p1", + "features": { + "cost": 10, + "time": 10, + "reliability": 0.99, + "availability": 0.9, + "security": 0.9 + } + }, + { + "id": "t1_p2_bad", + "task_id": "t1", + "provider_id": "p2", + "features": { + "cost": 10, + "time": 100, + "reliability": 0.1, + "availability": 0.9, + "security": 0.9 + } + }, + { + "id": "t2_p1_bad", + "task_id": "t2", + "provider_id": "p1", + "features": { + "cost": 10, + "time": 100, + "reliability": 0.1, + "availability": 0.9, + "security": 0.9 + } + }, + { + "id": "t2_p2_great", + "task_id": "t2", + "provider_id": "p2", + "features": { + "cost": 10, + "time": 10, + "reliability": 0.99, + "availability": 0.9, + "security": 0.9 + } + } ], "features": [ - { "id": "cost", "name": "Cost", "direction": "minimize", "unit": "USD", "scale": "ratio", "valid_range": {"min": 0, "max": 1000}, "normalization": { "type": "minmax", "bounds": { "min": 0, "max": 100 } } }, - { "id": "time", "name": "Time", "direction": "minimize", "unit": "ms", "scale": "ratio", "valid_range": {"min": 0, "max": 1000}, "normalization": { "type": "minmax", "bounds": { "min": 0, "max": 1000 } } }, - { "id": "reliability", "name": "Rel", "direction": "maximize", "unit": "prob", "scale": "ratio", "valid_range": {"min": 0, "max": 1}, "normalization": { "type": "minmax", "bounds": { "min": 0, "max": 1 } } }, - { "id": "availability", "name": "Avail", "direction": "maximize", "unit": "prob", "scale": "ratio", "valid_range": {"min": 0, "max": 1}, "normalization": { "type": "minmax", "bounds": { "min": 0, "max": 1 } } }, - { "id": "security", "name": "Sec", "direction": "maximize", "unit": "prob", "scale": "ratio", "valid_range": {"min": 0, "max": 1}, "normalization": { "type": "minmax", "bounds": { "min": 0, "max": 1 } } } + { + "id": "cost", + "name": "Cost", + "direction": "minimize", + "unit": "USD", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1000 + } + }, + { + "id": "time", + "name": "Time", + "direction": "minimize", + "unit": "ms", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1000 + } + }, + { + "id": "reliability", + "name": "Rel", + "direction": "maximize", + "unit": "prob", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1 + } + }, + { + "id": "availability", + "name": "Avail", + "direction": "maximize", + "unit": "prob", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1 + } + }, + { + "id": "security", + "name": "Sec", + "direction": "maximize", + "unit": "prob", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1 + } + } ], "composition": { "type": "structured", @@ -35,21 +140,37 @@ "id": "root", "kind": "SEQ", "children": [ - { "id": "n1", "kind": "TASK", "task_id": "t1" }, - { "id": "n2", "kind": "TASK", "task_id": "t2" } + { + "id": "n1", + "kind": "TASK", + "task_id": "t1" + }, + { + "id": "n2", + "kind": "TASK", + "task_id": "t2" + } ] } }, "aggregation_policies": {}, "constraints": [ - { - "id": "dep1", "kind": "dependency", "type": "same_provider", "tasks": ["t1", "t2"] - } + { + "id": "dep1", + "kind": "dependency", + "type": "same_provider", + "tasks": [ + "t1", + "t2" + ] + } ], "objective": { "type": "weighted_sum", - "weights": { "reliability": 1.0 }, + "weights": { + "reliability": 1.0 + }, "normalized": true } } -} +} \ No newline at end of file diff --git a/examples/many-obj-example.json b/examples/many-obj-example.json new file mode 100644 index 0000000..6a413da --- /dev/null +++ b/examples/many-obj-example.json @@ -0,0 +1,216 @@ +{ + "metadata": { + "id": "many-obj-complex-example", + "name": "Many-OBJ Complex Workflow", + "version": "1.0", + "created_at": "2024-01-20T12:00:00Z" + }, + "features": [ + { + "id": "cost", + "name": "Cost", + "direction": "minimize", + "unit": "USD", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1000 + } + }, + { + "id": "time", + "name": "Response Time", + "direction": "minimize", + "unit": "ms", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 5000 + } + } + ], + "tasks": [ + { + "id": "payment", + "name": "Payment Processing" + }, + { + "id": "inventory", + "name": "Inventory Check" + }, + { + "id": "shipping", + "name": "Shipping Logistics" + } + ], + "providers": [ + { + "id": "stripe", + "name": "Stripe" + }, + { + "id": "paypal", + "name": "PayPal" + }, + { + "id": "aws", + "name": "AWS Warehouse" + }, + { + "id": "azure", + "name": "Azure Inventory" + }, + { + "id": "fedex", + "name": "FedEx" + }, + { + "id": "ups", + "name": "UPS" + } + ], + "candidates": [ + { + "id": "pay_stripe", + "task_id": "payment", + "provider_id": "stripe", + "features": { + "cost": 0.3, + "time": 200 + } + }, + { + "id": "pay_paypal", + "task_id": "payment", + "provider_id": "paypal", + "features": { + "cost": 0.5, + "time": 150 + } + }, + { + "id": "inv_aws", + "task_id": "inventory", + "provider_id": "aws", + "features": { + "cost": 0.1, + "time": 50 + } + }, + { + "id": "inv_azure", + "task_id": "inventory", + "provider_id": "azure", + "features": { + "cost": 0.05, + "time": 80 + } + }, + { + "id": "ship_fedex", + "task_id": "shipping", + "provider_id": "fedex", + "features": { + "cost": 5.0, + "time": 1000 + } + }, + { + "id": "ship_ups", + "task_id": "shipping", + "provider_id": "ups", + "features": { + "cost": 4.5, + "time": 1200 + } + } + ], + "composition": { + "type": "structured", + "root": { + "id": "root_seq", + "kind": "SEQ", + "children": [ + { + "id": "task_payment", + "kind": "TASK", + "task_id": "payment" + }, + { + "id": "par_flow", + "kind": "AND", + "children": [ + { + "id": "task_inv", + "kind": "TASK", + "task_id": "inventory" + }, + { + "id": "task_ship", + "kind": "TASK", + "task_id": "shipping" + } + ] + } + ] + } + }, + "aggregation_policies": { + "cost": { + "neutral": 0, + "compose": { + "seq": { + "fn": "sum" + }, + "and": { + "fn": "sum" + }, + "xor": { + "fn": "sum" + }, + "loop": { + "fn": "sum" + } + }, + "normalize": { + "type": "minmax", + "bounds": { + "min": 0, + "max": 1000 + } + } + }, + "time": { + "neutral": 0, + "compose": { + "seq": { + "fn": "sum" + }, + "and": { + "fn": "max" + }, + "xor": { + "fn": "sum" + }, + "loop": { + "fn": "sum" + } + }, + "normalize": { + "type": "minmax", + "bounds": { + "min": 0, + "max": 5000 + } + } + } + }, + "objective": { + "type": "weighted_sum", + "weights": { + "cost": 0.5, + "time": 0.5 + }, + "normalized": true + } +} \ No newline at end of file diff --git a/examples/many_obj_valid_instance.json b/examples/many_obj_valid_instance.json new file mode 100644 index 0000000..f3d6271 --- /dev/null +++ b/examples/many_obj_valid_instance.json @@ -0,0 +1,167 @@ +{ + "metadata": { + "id": "test-many-obj-01", + "name": "Many-OBJ Test Instance", + "version": "1.0", + "created_at": "2023-10-27T10:00:00Z" + }, + "providers": [ + { + "id": "p1", + "name": "Provider 1" + }, + { + "id": "p2", + "name": "Provider 2" + } + ], + "tasks": [ + { + "id": "t1", + "name": "Task A" + }, + { + "id": "t2", + "name": "Task B" + } + ], + "composition": { + "type": "structured", + "root": { + "id": "n1", + "kind": "SEQ", + "children": [ + { + "id": "t1", + "kind": "TASK", + "task_id": "t1" + }, + { + "id": "t2", + "kind": "TASK", + "task_id": "t2" + } + ] + } + }, + "candidates": [ + { + "id": "s1", + "task_id": "t1", + "provider_id": "p1", + "features": { + "cost": 10.0, + "time": 50.0 + } + }, + { + "id": "s2", + "task_id": "t1", + "provider_id": "p2", + "features": { + "cost": 12.0, + "time": 45.0 + } + }, + { + "id": "s3", + "task_id": "t2", + "provider_id": "p1", + "features": { + "cost": 5.0, + "time": 20.0 + } + }, + { + "id": "s4", + "task_id": "t2", + "provider_id": "p2", + "features": { + "cost": 8.0, + "time": 15.0 + } + } + ], + "features": [ + { + "id": "cost", + "name": "Cost", + "direction": "minimize", + "unit": "USD", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1000 + } + }, + { + "id": "time", + "name": "Response Time", + "direction": "minimize", + "unit": "ms", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 5000 + } + } + ], + "objective": { + "type": "weighted_sum", + "weights": { + "cost": 0.5, + "time": 0.5 + }, + "normalized": true + }, + "aggregation_policies": { + "cost": { + "neutral": 0, + "normalize": { + "type": "minmax", + "bounds": { + "min": 0, + "max": 100 + } + }, + "compose": { + "seq": { + "fn": "sum" + }, + "and": { + "fn": "max" + }, + "xor": { + "fn": "sum" + }, + "loop": { + "fn": "sum" + } + } + }, + "time": { + "neutral": 0, + "normalize": { + "type": "minmax", + "bounds": { + "min": 0, + "max": 1000 + } + }, + "compose": { + "seq": { + "fn": "sum" + }, + "and": { + "fn": "max" + }, + "xor": { + "fn": "sum" + }, + "loop": { + "fn": "sum" + } + } + } + } +} \ No newline at end of file diff --git a/examples/minimal-1task.json b/examples/minimal-1task.json index 88ba501..78cfa14 100644 --- a/examples/minimal-1task.json +++ b/examples/minimal-1task.json @@ -24,7 +24,7 @@ "id": "c1a", "task_id": "t1", "provider_id": "p1", - "qos": { + "features": { "cost": 10, "time": 100 } @@ -33,7 +33,7 @@ "id": "c1b", "task_id": "t1", "provider_id": "p1", - "qos": { + "features": { "cost": 20, "time": 50 } @@ -48,14 +48,6 @@ "scale": "ratio", "valid_range": { "min": 0 - }, - "normalization": { - "type": "minmax", - "bounds": { - "min": 0, - "max": 100 - }, - "increasing_is_better": false } }, { @@ -67,14 +59,6 @@ "valid_range": { "min": 0, "max": 10000 - }, - "normalization": { - "type": "minmax", - "bounds": { - "min": 0, - "max": 100 - }, - "increasing_is_better": false } }, { @@ -86,14 +70,6 @@ "valid_range": { "min": 0, "max": 1 - }, - "normalization": { - "type": "minmax", - "bounds": { - "min": 0, - "max": 1 - }, - "increasing_is_better": true } }, { @@ -105,14 +81,6 @@ "valid_range": { "min": 0, "max": 1 - }, - "normalization": { - "type": "minmax", - "bounds": { - "min": 0, - "max": 1 - }, - "increasing_is_better": true } }, { @@ -124,14 +92,6 @@ "valid_range": { "min": 0, "max": 1 - }, - "normalization": { - "type": "minmax", - "bounds": { - "min": 0, - "max": 1 - }, - "increasing_is_better": true } } ], @@ -145,9 +105,6 @@ }, "aggregation_policies": { "cost": { - "attribute_id": "cost", - "direction": "minimize", - "scale": "ratio", "neutral": 0, "compose": { "seq": { @@ -171,9 +128,6 @@ } }, "time": { - "attribute_id": "time", - "direction": "minimize", - "scale": "ratio", "neutral": 0, "compose": { "seq": { @@ -197,9 +151,6 @@ } }, "reliability": { - "attribute_id": "reliability", - "direction": "maximize", - "scale": "ratio", "neutral": 1, "compose": { "seq": { @@ -223,9 +174,6 @@ } }, "availability": { - "attribute_id": "availability", - "direction": "maximize", - "scale": "ratio", "neutral": 1, "compose": { "seq": { @@ -249,9 +197,6 @@ } }, "security": { - "attribute_id": "security", - "direction": "maximize", - "scale": "ratio", "neutral": 1, "compose": { "seq": { diff --git a/examples/structured-seq-andpar-xor.json b/examples/structured-seq-andpar-xor.json index 0f788aa..7fcfd51 100644 --- a/examples/structured-seq-andpar-xor.json +++ b/examples/structured-seq-andpar-xor.json @@ -32,7 +32,7 @@ "id": "c1a", "task_id": "t1", "provider_id": "p1", - "qos": { + "features": { "cost": 5, "time": 20 } @@ -41,7 +41,7 @@ "id": "c1b", "task_id": "t1", "provider_id": "p1", - "qos": { + "features": { "cost": 2, "time": 50 } @@ -50,7 +50,7 @@ "id": "c2a", "task_id": "t2", "provider_id": "p1", - "qos": { + "features": { "cost": 10, "time": 100 } @@ -59,7 +59,7 @@ "id": "c2b", "task_id": "t2", "provider_id": "p1", - "qos": { + "features": { "cost": 20, "time": 60 } @@ -68,7 +68,7 @@ "id": "c3a", "task_id": "t3", "provider_id": "p1", - "qos": { + "features": { "cost": 1, "time": 10 } @@ -84,14 +84,6 @@ "valid_range": { "min": 0, "max": 10000 - }, - "normalization": { - "type": "minmax", - "bounds": { - "min": 0, - "max": 100 - }, - "increasing_is_better": false } }, { @@ -103,14 +95,6 @@ "valid_range": { "min": 0, "max": 10000 - }, - "normalization": { - "type": "minmax", - "bounds": { - "min": 0, - "max": 100 - }, - "increasing_is_better": false } }, { @@ -122,14 +106,6 @@ "valid_range": { "min": 0, "max": 1 - }, - "normalization": { - "type": "minmax", - "bounds": { - "min": 0, - "max": 1 - }, - "increasing_is_better": true } }, { @@ -141,14 +117,6 @@ "valid_range": { "min": 0, "max": 1 - }, - "normalization": { - "type": "minmax", - "bounds": { - "min": 0, - "max": 1 - }, - "increasing_is_better": true } }, { @@ -160,14 +128,6 @@ "valid_range": { "min": 0, "max": 1 - }, - "normalization": { - "type": "minmax", - "bounds": { - "min": 0, - "max": 1 - }, - "increasing_is_better": true } } ], @@ -209,9 +169,6 @@ }, "aggregation_policies": { "cost": { - "attribute_id": "cost", - "direction": "minimize", - "scale": "ratio", "neutral": 0, "compose": { "seq": { @@ -235,9 +192,6 @@ } }, "time": { - "attribute_id": "time", - "direction": "minimize", - "scale": "ratio", "neutral": 0, "compose": { "seq": { @@ -261,9 +215,6 @@ } }, "reliability": { - "attribute_id": "reliability", - "direction": "maximize", - "scale": "ratio", "neutral": 1, "compose": { "seq": { @@ -287,9 +238,6 @@ } }, "availability": { - "attribute_id": "availability", - "direction": "maximize", - "scale": "ratio", "neutral": 1, "compose": { "seq": { @@ -313,9 +261,6 @@ } }, "security": { - "attribute_id": "security", - "direction": "maximize", - "scale": "ratio", "neutral": 1, "compose": { "seq": { diff --git a/examples/validation-engine-disconnected.json b/examples/validation-engine-disconnected.json index 8bfb440..4f37ec8 100644 --- a/examples/validation-engine-disconnected.json +++ b/examples/validation-engine-disconnected.json @@ -1,73 +1,66 @@ { - "engine_id": "minizinc-csp", - "instance": { - "metadata": { - "id": "test-disconnected", - "name": "Disconnected Task Test", - "version": "1.0", - "created_at": "2024-01-01T00:00:00Z" - }, - "providers": [ - { - "id": "p1", - "name": "P1" - } - ], - "tasks": [ - { - "id": "t1", - "name": "Task 1" - }, - { - "id": "t2", - "name": "Task 2 Unused" - } - ], - "candidates": [ - { - "id": "c1", - "task_id": "t1", - "provider_id": "p1", - "qos": { - "cost": 1 - } - } - ], - "features": [ - { - "id": "cost", - "name": "Cost", - "direction": "minimize", - "unit": "USD", - "scale": "ratio", - "valid_range": { - "min": 0, - "max": 100 - }, - "normalization": { - "type": "minmax", - "bounds": { - "min": 0, - "max": 20 - } - } - } - ], - "composition": { - "type": "structured", - "root": { - "id": "n1", - "kind": "TASK", - "task_id": "t1" - } - }, - "aggregation_policies": {}, - "objective": { - "type": "weighted_sum", - "weights": { - "cost": 1.0 - }, - "normalized": true + "engine_id": "minizinc-csp", + "instance": { + "metadata": { + "id": "test-disconnected", + "name": "Disconnected Task Test", + "version": "1.0", + "created_at": "2024-01-01T00:00:00Z" + }, + "providers": [ + { + "id": "p1", + "name": "P1" + } + ], + "tasks": [ + { + "id": "t1", + "name": "Task 1" + }, + { + "id": "t2", + "name": "Task 2 Unused" + } + ], + "candidates": [ + { + "id": "c1", + "task_id": "t1", + "provider_id": "p1", + "features": { + "cost": 1 } + } + ], + "features": [ + { + "id": "cost", + "name": "Cost", + "direction": "minimize", + "unit": "USD", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 100 + } + } + ], + "composition": { + "type": "structured", + "root": { + "id": "n1", + "kind": "TASK", + "task_id": "t1" + } + }, + "aggregation_policies": {}, + "objective": { + "type": "weighted_sum", + "weights": { + "cost": 1.0 + }, + "normalized": true } + } } \ No newline at end of file diff --git a/examples/validation-gateway-duplicate.json b/examples/validation-gateway-duplicate.json index 49dc7cc..4b426ff 100644 --- a/examples/validation-gateway-duplicate.json +++ b/examples/validation-gateway-duplicate.json @@ -1,73 +1,66 @@ { - "engine_id": "minizinc-csp", - "instance": { - "metadata": { - "id": "test-dup", - "name": "Duplicate ID Test", - "version": "1.0", - "created_at": "2024-01-01T00:00:00Z" - }, - "providers": [ - { - "id": "p1", - "name": "P1" - } - ], - "tasks": [ - { - "id": "t1", - "name": "Task 1" - }, - { - "id": "t1", - "name": "Task 1 Duplicate" - } - ], - "candidates": [ - { - "id": "c1", - "task_id": "t1", - "provider_id": "p1", - "qos": { - "cost": 1 - } - } - ], - "features": [ - { - "id": "cost", - "name": "Cost", - "direction": "minimize", - "unit": "USD", - "scale": "ratio", - "valid_range": { - "min": 0, - "max": 100 - }, - "normalization": { - "type": "minmax", - "bounds": { - "min": 0, - "max": 20 - } - } - } - ], - "composition": { - "type": "structured", - "root": { - "id": "n1", - "kind": "TASK", - "task_id": "t1" - } - }, - "aggregation_policies": {}, - "objective": { - "type": "weighted_sum", - "weights": { - "cost": 1.0 - }, - "normalized": true + "engine_id": "minizinc-csp", + "instance": { + "metadata": { + "id": "test-dup", + "name": "Duplicate ID Test", + "version": "1.0", + "created_at": "2024-01-01T00:00:00Z" + }, + "providers": [ + { + "id": "p1", + "name": "P1" + } + ], + "tasks": [ + { + "id": "t1", + "name": "Task 1" + }, + { + "id": "t1", + "name": "Task 1 Duplicate" + } + ], + "candidates": [ + { + "id": "c1", + "task_id": "t1", + "provider_id": "p1", + "features": { + "cost": 1 } + } + ], + "features": [ + { + "id": "cost", + "name": "Cost", + "direction": "minimize", + "unit": "USD", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 100 + } + } + ], + "composition": { + "type": "structured", + "root": { + "id": "n1", + "kind": "TASK", + "task_id": "t1" + } + }, + "aggregation_policies": {}, + "objective": { + "type": "weighted_sum", + "weights": { + "cost": 1.0 + }, + "normalized": true } + } } \ No newline at end of file diff --git a/examples/validation-gateway-specialization.json b/examples/validation-gateway-specialization.json index 086ff9e..ac908b0 100644 --- a/examples/validation-gateway-specialization.json +++ b/examples/validation-gateway-specialization.json @@ -1,19 +1,65 @@ { "engine_id": "minizinc-csp", "instance": { - "metadata": { "id": "test-spec-fail", "name": "Spec Fail", "version": "1.0", "created_at": "2024-01-01T00:00:00Z" }, - "providers": [{"id": "p1", "name": "P1"}], - "tasks": [ {"id": "t1", "name": "Task 1"} ], - "candidates": [ { "id": "c1", "task_id": "t1", "provider_id": "p1", "qos": { "cost": 1 } } ], + "metadata": { + "id": "test-spec-fail", + "name": "Spec Fail", + "version": "1.0", + "created_at": "2024-01-01T00:00:00Z" + }, + "providers": [ + { + "id": "p1", + "name": "P1" + } + ], + "tasks": [ + { + "id": "t1", + "name": "Task 1" + } + ], + "candidates": [ + { + "id": "c1", + "task_id": "t1", + "provider_id": "p1", + "features": { + "cost": 1 + } + } + ], "features": [ - { "id": "cost", "name": "Cost", "direction": "minimize", "unit": "USD", "scale": "ratio", "valid_range": {"min": 0, "max": 100}, "normalization": { "type": "minmax", "bounds": { "min": 0, "max": 20 } } } + { + "id": "cost", + "name": "Cost", + "direction": "minimize", + "unit": "USD", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 100 + } + } ], - "composition": { - "type": "dag", - "nodes": [ { "id": "n1", "kind": "TASK", "task_id": "t1" } ], - "edges": [] + "composition": { + "type": "dag", + "nodes": [ + { + "id": "n1", + "kind": "TASK", + "task_id": "t1" + } + ], + "edges": [] }, "aggregation_policies": {}, - "objective": { "type": "weighted_sum", "weights": { "cost": 1.0 }, "normalized": true } + "objective": { + "type": "weighted_sum", + "weights": { + "cost": 1.0 + }, + "normalized": true + } } -} +} \ No newline at end of file diff --git a/examples/variation-objective-cost.json b/examples/variation-objective-cost.json index 1c9ecde..27ef27f 100644 --- a/examples/variation-objective-cost.json +++ b/examples/variation-objective-cost.json @@ -1,197 +1,162 @@ { - "engine_id": "minizinc-csp", - "instance": { - "metadata": { - "id": "var-cost-opt", - "name": "Variation: Cost Optimization", - "version": "1.0", - "created_at": "2024-01-01T00:00:00Z" - }, - "providers": [ - { - "id": "p1", - "name": "Provider 1" - } - ], - "tasks": [ - { - "id": "t1", - "name": "Task 1" - }, - { - "id": "t2", - "name": "Task 2" - } - ], - "candidates": [ - { - "id": "c1_slow_cheap", - "task_id": "t1", - "provider_id": "p1", - "qos": { - "cost": 1, - "time": 100, - "reliability": 0.9, - "availability": 0.9, - "security": 0.9 - } - }, - { - "id": "c1_fast_expensive", - "task_id": "t1", - "provider_id": "p1", - "qos": { - "cost": 100, - "time": 10, - "reliability": 0.9, - "availability": 0.9, - "security": 0.9 - } - }, - { - "id": "c2_slow_cheap", - "task_id": "t2", - "provider_id": "p1", - "qos": { - "cost": 1, - "time": 100, - "reliability": 0.9, - "availability": 0.9, - "security": 0.9 - } - }, - { - "id": "c2_fast_expensive", - "task_id": "t2", - "provider_id": "p1", - "qos": { - "cost": 100, - "time": 10, - "reliability": 0.9, - "availability": 0.9, - "security": 0.9 - } - } - ], - "features": [ - { - "id": "cost", - "name": "Cost", - "direction": "minimize", - "unit": "USD", - "scale": "ratio", - "valid_range": { - "min": 0, - "max": 1000 - }, - "normalization": { - "type": "minmax", - "bounds": { - "min": 0, - "max": 200 - } - } - }, - { - "id": "time", - "name": "Time", - "direction": "minimize", - "unit": "ms", - "scale": "ratio", - "valid_range": { - "min": 0, - "max": 1000 - }, - "normalization": { - "type": "minmax", - "bounds": { - "min": 0, - "max": 200 - } - } - }, - { - "id": "reliability", - "name": "Rel", - "direction": "maximize", - "unit": "prob", - "scale": "ratio", - "valid_range": { - "min": 0, - "max": 1 - }, - "normalization": { - "type": "minmax", - "bounds": { - "min": 0, - "max": 1 - } - } - }, - { - "id": "availability", - "name": "Avail", - "direction": "maximize", - "unit": "prob", - "scale": "ratio", - "valid_range": { - "min": 0, - "max": 1 - }, - "normalization": { - "type": "minmax", - "bounds": { - "min": 0, - "max": 1 - } - } - }, - { - "id": "security", - "name": "Sec", - "direction": "maximize", - "unit": "prob", - "scale": "ratio", - "valid_range": { - "min": 0, - "max": 1 - }, - "normalization": { - "type": "minmax", - "bounds": { - "min": 0, - "max": 1 - } - } - } - ], - "composition": { - "type": "structured", - "root": { - "id": "root", - "kind": "SEQ", - "children": [ - { - "id": "n1", - "kind": "TASK", - "task_id": "t1" - }, - { - "id": "n2", - "kind": "TASK", - "task_id": "t2" - } - ] - } - }, - "aggregation_policies": {}, - "objective": { - "type": "weighted_sum", - "weights": { - "cost": 0.9, - "time": 0.1 - }, - "normalized": true + "engine_id": "minizinc-csp", + "instance": { + "metadata": { + "id": "var-cost-opt", + "name": "Variation: Cost Optimization", + "version": "1.0", + "created_at": "2024-01-01T00:00:00Z" + }, + "providers": [ + { + "id": "p1", + "name": "Provider 1" + } + ], + "tasks": [ + { + "id": "t1", + "name": "Task 1" + }, + { + "id": "t2", + "name": "Task 2" + } + ], + "candidates": [ + { + "id": "c1_slow_cheap", + "task_id": "t1", + "provider_id": "p1", + "features": { + "cost": 1, + "time": 100, + "reliability": 0.9, + "availability": 0.9, + "security": 0.9 } + }, + { + "id": "c1_fast_expensive", + "task_id": "t1", + "provider_id": "p1", + "features": { + "cost": 100, + "time": 10, + "reliability": 0.9, + "availability": 0.9, + "security": 0.9 + } + }, + { + "id": "c2_slow_cheap", + "task_id": "t2", + "provider_id": "p1", + "features": { + "cost": 1, + "time": 100, + "reliability": 0.9, + "availability": 0.9, + "security": 0.9 + } + }, + { + "id": "c2_fast_expensive", + "task_id": "t2", + "provider_id": "p1", + "features": { + "cost": 100, + "time": 10, + "reliability": 0.9, + "availability": 0.9, + "security": 0.9 + } + } + ], + "features": [ + { + "id": "cost", + "name": "Cost", + "direction": "minimize", + "unit": "USD", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1000 + } + }, + { + "id": "time", + "name": "Time", + "direction": "minimize", + "unit": "ms", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1000 + } + }, + { + "id": "reliability", + "name": "Rel", + "direction": "maximize", + "unit": "prob", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1 + } + }, + { + "id": "availability", + "name": "Avail", + "direction": "maximize", + "unit": "prob", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1 + } + }, + { + "id": "security", + "name": "Sec", + "direction": "maximize", + "unit": "prob", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1 + } + } + ], + "composition": { + "type": "structured", + "root": { + "id": "root", + "kind": "SEQ", + "children": [ + { + "id": "n1", + "kind": "TASK", + "task_id": "t1" + }, + { + "id": "n2", + "kind": "TASK", + "task_id": "t2" + } + ] + } + }, + "aggregation_policies": {}, + "objective": { + "type": "weighted_sum", + "weights": { + "cost": 0.9, + "time": 0.1 + }, + "normalized": true } + } } \ No newline at end of file diff --git a/examples/variation-objective-time.json b/examples/variation-objective-time.json index 1c17b26..6fb78ca 100644 --- a/examples/variation-objective-time.json +++ b/examples/variation-objective-time.json @@ -1,197 +1,162 @@ { - "engine_id": "minizinc-csp", - "instance": { - "metadata": { - "id": "var-time-opt", - "name": "Variation: Time Optimization", - "version": "1.0", - "created_at": "2024-01-01T00:00:00Z" - }, - "providers": [ - { - "id": "p1", - "name": "Provider 1" - } - ], - "tasks": [ - { - "id": "t1", - "name": "Task 1" - }, - { - "id": "t2", - "name": "Task 2" - } - ], - "candidates": [ - { - "id": "c1_slow_cheap", - "task_id": "t1", - "provider_id": "p1", - "qos": { - "cost": 1, - "time": 100, - "reliability": 0.9, - "availability": 0.9, - "security": 0.9 - } - }, - { - "id": "c1_fast_expensive", - "task_id": "t1", - "provider_id": "p1", - "qos": { - "cost": 100, - "time": 10, - "reliability": 0.9, - "availability": 0.9, - "security": 0.9 - } - }, - { - "id": "c2_slow_cheap", - "task_id": "t2", - "provider_id": "p1", - "qos": { - "cost": 1, - "time": 100, - "reliability": 0.9, - "availability": 0.9, - "security": 0.9 - } - }, - { - "id": "c2_fast_expensive", - "task_id": "t2", - "provider_id": "p1", - "qos": { - "cost": 100, - "time": 10, - "reliability": 0.9, - "availability": 0.9, - "security": 0.9 - } - } - ], - "features": [ - { - "id": "cost", - "name": "Cost", - "direction": "minimize", - "unit": "USD", - "scale": "ratio", - "valid_range": { - "min": 0, - "max": 1000 - }, - "normalization": { - "type": "minmax", - "bounds": { - "min": 0, - "max": 200 - } - } - }, - { - "id": "time", - "name": "Time", - "direction": "minimize", - "unit": "ms", - "scale": "ratio", - "valid_range": { - "min": 0, - "max": 1000 - }, - "normalization": { - "type": "minmax", - "bounds": { - "min": 0, - "max": 200 - } - } - }, - { - "id": "reliability", - "name": "Rel", - "direction": "maximize", - "unit": "prob", - "scale": "ratio", - "valid_range": { - "min": 0, - "max": 1 - }, - "normalization": { - "type": "minmax", - "bounds": { - "min": 0, - "max": 1 - } - } - }, - { - "id": "availability", - "name": "Avail", - "direction": "maximize", - "unit": "prob", - "scale": "ratio", - "valid_range": { - "min": 0, - "max": 1 - }, - "normalization": { - "type": "minmax", - "bounds": { - "min": 0, - "max": 1 - } - } - }, - { - "id": "security", - "name": "Sec", - "direction": "maximize", - "unit": "prob", - "scale": "ratio", - "valid_range": { - "min": 0, - "max": 1 - }, - "normalization": { - "type": "minmax", - "bounds": { - "min": 0, - "max": 1 - } - } - } - ], - "composition": { - "type": "structured", - "root": { - "id": "root", - "kind": "SEQ", - "children": [ - { - "id": "n1", - "kind": "TASK", - "task_id": "t1" - }, - { - "id": "n2", - "kind": "TASK", - "task_id": "t2" - } - ] - } - }, - "aggregation_policies": {}, - "objective": { - "type": "weighted_sum", - "weights": { - "cost": 0.1, - "time": 0.9 - }, - "normalized": true + "engine_id": "minizinc-csp", + "instance": { + "metadata": { + "id": "var-time-opt", + "name": "Variation: Time Optimization", + "version": "1.0", + "created_at": "2024-01-01T00:00:00Z" + }, + "providers": [ + { + "id": "p1", + "name": "Provider 1" + } + ], + "tasks": [ + { + "id": "t1", + "name": "Task 1" + }, + { + "id": "t2", + "name": "Task 2" + } + ], + "candidates": [ + { + "id": "c1_slow_cheap", + "task_id": "t1", + "provider_id": "p1", + "features": { + "cost": 1, + "time": 100, + "reliability": 0.9, + "availability": 0.9, + "security": 0.9 } + }, + { + "id": "c1_fast_expensive", + "task_id": "t1", + "provider_id": "p1", + "features": { + "cost": 100, + "time": 10, + "reliability": 0.9, + "availability": 0.9, + "security": 0.9 + } + }, + { + "id": "c2_slow_cheap", + "task_id": "t2", + "provider_id": "p1", + "features": { + "cost": 1, + "time": 100, + "reliability": 0.9, + "availability": 0.9, + "security": 0.9 + } + }, + { + "id": "c2_fast_expensive", + "task_id": "t2", + "provider_id": "p1", + "features": { + "cost": 100, + "time": 10, + "reliability": 0.9, + "availability": 0.9, + "security": 0.9 + } + } + ], + "features": [ + { + "id": "cost", + "name": "Cost", + "direction": "minimize", + "unit": "USD", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1000 + } + }, + { + "id": "time", + "name": "Time", + "direction": "minimize", + "unit": "ms", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1000 + } + }, + { + "id": "reliability", + "name": "Rel", + "direction": "maximize", + "unit": "prob", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1 + } + }, + { + "id": "availability", + "name": "Avail", + "direction": "maximize", + "unit": "prob", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1 + } + }, + { + "id": "security", + "name": "Sec", + "direction": "maximize", + "unit": "prob", + "scale": "ratio", + "valid_range": { + "min": 0, + "max": 1 + } + } + ], + "composition": { + "type": "structured", + "root": { + "id": "root", + "kind": "SEQ", + "children": [ + { + "id": "n1", + "kind": "TASK", + "task_id": "t1" + }, + { + "id": "n2", + "kind": "TASK", + "task_id": "t2" + } + ] + } + }, + "aggregation_policies": {}, + "objective": { + "type": "weighted_sum", + "weights": { + "cost": 0.1, + "time": 0.9 + }, + "normalized": true } + } } \ No newline at end of file diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 15008be..753355c 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -20,6 +20,10 @@ function App() { Engine selection is handled by the UI. */ const [inputJson, setInputJson] = useState('{\n "metadata": { "id": "test" },\n "tasks": [],\n "candidates": [],\n "composition": {}\n}'); + const [solverOptions, setSolverOptions] = useState('{\n "iterations_count": 1000\n}'); + const [sendOptions, setSendOptions] = useState(true); + const [verbose, setVerbose] = useState(false); + const [result, setResult] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); @@ -125,7 +129,16 @@ function App() { try { instance = JSON.parse(inputJson); } catch (e) { - throw new Error("Invalid JSON"); + throw new Error("Invalid Instance JSON"); + } + + let options = {}; + if (sendOptions) { + try { + options = JSON.parse(solverOptions); + } catch (e) { + throw new Error("Invalid Options JSON"); + } } // Frontend Validation with Dynamic Schema @@ -149,7 +162,9 @@ function App() { // Construct Payload const payload = { engine_id: selectedEngine, - instance: instance + instance: instance, + options: options, + verbose: verbose }; const res = await fetch('http://localhost:8000/v1/solve', { @@ -262,10 +277,33 @@ function App() {
Input Instance (JSON)