From d89053792e8daca158bc9213ffbfaf704a0c0a99 Mon Sep 17 00:00:00 2001 From: Marie Salm Date: Thu, 31 Mar 2022 14:21:07 +0200 Subject: [PATCH] Add support for learning of MCDA weights, sensitivity analysis of MCDA weights, manually choosing weights --- generated/api-nisq/models.ts | 3 + ...ity-model-mcda-sensitivity-analysis-job.ts | 9 + .../api-nisq/models/entity-model-mcda-job.ts | 1 + ...ity-model-mcda-sensitivity-analysis-job.ts | 19 + .../entity-model-mcda-weight-learning-job.ts | 11 + generated/api-nisq/services/root.service.ts | 112 +++--- .../services/xmcda-criteria.service.ts | 335 ++++++++++++++++++ ...analyzer-qpu-selection-dialog.component.ts | 2 +- ...ection-prioritization-dialog.component.css | 23 ++ ...ction-prioritization-dialog.component.html | 190 ++++++++-- ...lection-prioritization-dialog.component.ts | 198 ++++++++++- ...sensitivity-analysis-dialog.component.html | 27 ++ ...sensitivity-analysis-dialog.component.scss | 0 ...n-sensitivity-analysis-dialog.component.ts | 90 +++++ ...nisq-analyzer-qpu-selection.component.html | 24 +- ...nisq-analyzer-qpu-selection.component.scss | 12 + ...n-nisq-analyzer-qpu-selection.component.ts | 135 ++++++- .../implementation-view.module.ts | 5 + 18 files changed, 1085 insertions(+), 111 deletions(-) create mode 100644 generated/api-nisq/models/collection-model-entity-model-mcda-sensitivity-analysis-job.ts create mode 100644 generated/api-nisq/models/entity-model-mcda-sensitivity-analysis-job.ts create mode 100644 generated/api-nisq/models/entity-model-mcda-weight-learning-job.ts create mode 100644 src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-prioritization-dialog/implementation-nisq-analyzer-qpu-selection-prioritization-dialog.component.css create mode 100644 src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog.component.html create mode 100644 src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog.component.scss create mode 100644 src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog.component.ts diff --git a/generated/api-nisq/models.ts b/generated/api-nisq/models.ts index b571c139..b7c5a990 100644 --- a/generated/api-nisq/models.ts +++ b/generated/api-nisq/models.ts @@ -3,6 +3,7 @@ export { AnalysisJobListDto } from './models/analysis-job-list-dto'; export { AnalysisResultDto } from './models/analysis-result-dto'; export { AnalysisResultListDto } from './models/analysis-result-list-dto'; export { CollectionModelEntityModelMcdaJob } from './models/collection-model-entity-model-mcda-job'; +export { CollectionModelEntityModelMcdaSensitivityAnalysisJob } from './models/collection-model-entity-model-mcda-sensitivity-analysis-job'; export { CompilationJobDto } from './models/compilation-job-dto'; export { CompilationJobListDto } from './models/compilation-job-list-dto'; export { CompilerAnalysisResultDto } from './models/compiler-analysis-result-dto'; @@ -14,6 +15,8 @@ export { Description } from './models/description'; export { Element } from './models/element'; export { EntityModelCriterionValue } from './models/entity-model-criterion-value'; export { EntityModelMcdaJob } from './models/entity-model-mcda-job'; +export { EntityModelMcdaSensitivityAnalysisJob } from './models/entity-model-mcda-sensitivity-analysis-job'; +export { EntityModelMcdaWeightLearningJob } from './models/entity-model-mcda-weight-learning-job'; export { ExecuteAnalysisResultRequestDto } from './models/execute-analysis-result-request-dto'; export { ExecutionResultDto } from './models/execution-result-dto'; export { ExecutionResultListDto } from './models/execution-result-list-dto'; diff --git a/generated/api-nisq/models/collection-model-entity-model-mcda-sensitivity-analysis-job.ts b/generated/api-nisq/models/collection-model-entity-model-mcda-sensitivity-analysis-job.ts new file mode 100644 index 00000000..d8291238 --- /dev/null +++ b/generated/api-nisq/models/collection-model-entity-model-mcda-sensitivity-analysis-job.ts @@ -0,0 +1,9 @@ +/* tslint:disable */ +import { EntityModelMcdaSensitivityAnalysisJob } from './entity-model-mcda-sensitivity-analysis-job'; +import { Links } from './links'; +export type CollectionModelEntityModelMcdaSensitivityAnalysisJob = { + _embedded?: { + mcdaSensitivityAnalysisJobs?: Array; + }; + _links?: Links; +}; diff --git a/generated/api-nisq/models/entity-model-mcda-job.ts b/generated/api-nisq/models/entity-model-mcda-job.ts index 67c178c0..d7441595 100644 --- a/generated/api-nisq/models/entity-model-mcda-job.ts +++ b/generated/api-nisq/models/entity-model-mcda-job.ts @@ -7,6 +7,7 @@ export type EntityModelMcdaJob = { ready?: boolean; method?: string; state?: string; + useBordaCount?: boolean; jobId?: string; jobType?: 'ANALYSIS' | 'COMPILATION' | 'QPU_SELECTION' | 'MCDA'; rankedResults?: Array; diff --git a/generated/api-nisq/models/entity-model-mcda-sensitivity-analysis-job.ts b/generated/api-nisq/models/entity-model-mcda-sensitivity-analysis-job.ts new file mode 100644 index 00000000..ff166ce0 --- /dev/null +++ b/generated/api-nisq/models/entity-model-mcda-sensitivity-analysis-job.ts @@ -0,0 +1,19 @@ +/* tslint:disable */ +import { Links } from './links'; +import { McdaResult } from './mcda-result'; +export type EntityModelMcdaSensitivityAnalysisJob = { + id?: string; + time?: string; + ready?: boolean; + method?: string; + state?: string; + useBordaCount?: boolean; + jobId?: string; + jobType?: 'ANALYSIS' | 'COMPILATION' | 'QPU_SELECTION' | 'MCDA'; + stepSize?: number; + upperBound?: number; + lowerBound?: number; + plotFileLocation?: string; + originalRanking?: Array; + _links?: Links; +}; diff --git a/generated/api-nisq/models/entity-model-mcda-weight-learning-job.ts b/generated/api-nisq/models/entity-model-mcda-weight-learning-job.ts new file mode 100644 index 00000000..a351ff4a --- /dev/null +++ b/generated/api-nisq/models/entity-model-mcda-weight-learning-job.ts @@ -0,0 +1,11 @@ +/* tslint:disable */ +import { Links } from './links'; +export type EntityModelMcdaWeightLearningJob = { + id?: string; + time?: string; + ready?: boolean; + mcdaMethod?: string; + weightLearningMethod?: string; + state?: string; + _links?: Links; +}; diff --git a/generated/api-nisq/services/root.service.ts b/generated/api-nisq/services/root.service.ts index 755464a5..6c2e3ff7 100644 --- a/generated/api-nisq/services/root.service.ts +++ b/generated/api-nisq/services/root.service.ts @@ -288,6 +288,59 @@ export class RootService extends BaseService { ); } + /** + * Path part for operation getCompilers + */ + static readonly GetCompilersPath = '/compilers'; + + /** + * Retrieve compilers + * + * This method provides access to the full `HttpResponse`, allowing access to response headers. + * To access only the response body, use `getCompilers()` instead. + * + * This method doesn't expect any request body. + */ + getCompilers$Response(params: { + provider: string; + }): Observable>> { + const rb = new RequestBuilder( + this.rootUrl, + RootService.GetCompilersPath, + 'get' + ); + if (params) { + rb.query('provider', params.provider, {}); + } + return this.http + .request( + rb.build({ + responseType: 'json', + accept: 'application/hal+json', + }) + ) + .pipe( + filter((r: any) => r instanceof HttpResponse), + map((r: HttpResponse) => { + return r as StrictHttpResponse>; + }) + ); + } + + /** + * Retrieve compilers + * + * This method provides access to only to the response body. + * To access the full response (for headers, for example), `getCompilers$Response()` instead. + * + * This method doesn't expect any request body. + */ + getCompilers(params: { provider: string }): Observable> { + return this.getCompilers$Response(params).pipe( + map((r: StrictHttpResponse>) => r.body as Array) + ); + } + /** * Path part for operation selectQpuForCircuitFile1 */ @@ -307,8 +360,8 @@ export class RootService extends BaseService { circuitLanguage: string; tokens: {}; circuitName?: string; + compilers?: Array; body: { circuit?: Blob }; - compilers: string[]; }): Observable> { const rb = new RequestBuilder( this.rootUrl, @@ -321,7 +374,7 @@ export class RootService extends BaseService { rb.query('circuitLanguage', params.circuitLanguage, {}); rb.query('tokens', params.tokens, {}); rb.query('circuitName', params.circuitName, {}); - rb.query('compilers', params) + rb.query('compilers', params.compilers, {}); rb.body(params.body, 'multipart/form-data'); } @@ -354,8 +407,8 @@ export class RootService extends BaseService { circuitLanguage: string; tokens: {}; circuitName?: string; + compilers?: Array; body: { circuit?: Blob }; - compilers: string[]; }): Observable { return this.selectQpuForCircuitFile1$FormData$Response(params).pipe( map( @@ -379,8 +432,8 @@ export class RootService extends BaseService { circuitLanguage: string; tokens: {}; circuitName?: string; + compilers?: Array; body: QpuSelectionDto; - compilers: string[]; }): Observable> { const rb = new RequestBuilder( this.rootUrl, @@ -393,7 +446,7 @@ export class RootService extends BaseService { rb.query('circuitLanguage', params.circuitLanguage, {}); rb.query('tokens', params.tokens, {}); rb.query('circuitName', params.circuitName, {}); - rb.query('compilers', params) + rb.query('compilers', params.compilers, {}); rb.body(params.body, 'application/xml'); } @@ -426,8 +479,8 @@ export class RootService extends BaseService { circuitLanguage: string; tokens: {}; circuitName?: string; + compilers?: Array; body: QpuSelectionDto; - compilers: string[]; }): Observable { return this.selectQpuForCircuitFile1$Xml$Response(params).pipe( map( @@ -451,8 +504,8 @@ export class RootService extends BaseService { circuitLanguage: string; tokens: {}; circuitName?: string; + compilers?: Array; body: QpuSelectionDto; - compilers: string[]; }): Observable> { const rb = new RequestBuilder( this.rootUrl, @@ -465,7 +518,7 @@ export class RootService extends BaseService { rb.query('circuitLanguage', params.circuitLanguage, {}); rb.query('tokens', params.tokens, {}); rb.query('circuitName', params.circuitName, {}); - rb.query('compilers', params) + rb.query('compilers', params.compilers, {}); rb.body(params.body, 'application/json'); } @@ -498,8 +551,8 @@ export class RootService extends BaseService { circuitLanguage: string; tokens: {}; circuitName?: string; + compilers?: Array; body: QpuSelectionDto; - compilers: string[]; }): Observable { return this.selectQpuForCircuitFile1$Json$Response(params).pipe( map( @@ -618,45 +671,4 @@ export class RootService extends BaseService { ) ); } - - /** - * Path part for operation getCompilers - */ - static readonly GetCompilersPath = '/compilers' - - getCompilers$Response(params: { - provider: string; - }): Observable> { - const rb = new RequestBuilder( - this.rootUrl, - RootService.GetCompilersPath, - 'get' - ); - if (params) { - rb.query('provider', params.provider, {}); - } - return this.http - .request( - rb.build({ - responseType: 'json', - accept: 'application/hal+json', - }) - ) - .pipe( - filter((r: any) => r instanceof HttpResponse), - map((r: HttpResponse) => { - return r as StrictHttpResponse; - }) - ); - } - - getCompilers(params: { provider: string; }): Observable { - console.log("line 645"); - return this.getCompilers$Response(params).pipe( - map( - (r: StrictHttpResponse) => r.body as string[] - ) - ); - } - } diff --git a/generated/api-nisq/services/xmcda-criteria.service.ts b/generated/api-nisq/services/xmcda-criteria.service.ts index eb3a4e14..fad4c008 100644 --- a/generated/api-nisq/services/xmcda-criteria.service.ts +++ b/generated/api-nisq/services/xmcda-criteria.service.ts @@ -9,9 +9,12 @@ import { Observable } from 'rxjs'; import { map, filter } from 'rxjs/operators'; import { CollectionModelEntityModelMcdaJob } from '../models/collection-model-entity-model-mcda-job'; +import { CollectionModelEntityModelMcdaSensitivityAnalysisJob } from '../models/collection-model-entity-model-mcda-sensitivity-analysis-job'; import { CriterionValue } from '../models/criterion-value'; import { EntityModelCriterionValue } from '../models/entity-model-criterion-value'; import { EntityModelMcdaJob } from '../models/entity-model-mcda-job'; +import { EntityModelMcdaSensitivityAnalysisJob } from '../models/entity-model-mcda-sensitivity-analysis-job'; +import { EntityModelMcdaWeightLearningJob } from '../models/entity-model-mcda-weight-learning-job'; import { McdaCriterionDto } from '../models/mcda-criterion-dto'; import { McdaCriterionListDto } from '../models/mcda-criterion-list-dto'; import { McdaMethodDto } from '../models/mcda-method-dto'; @@ -522,6 +525,7 @@ export class XmcdaCriteriaService extends BaseService { prioritizeCompiledCircuitsOfJob$Response(params: { methodName: string; jobId: string; + useBordaCount: boolean; }): Observable> { const rb = new RequestBuilder( this.rootUrl, @@ -531,6 +535,7 @@ export class XmcdaCriteriaService extends BaseService { if (params) { rb.path('methodName', params.methodName, {}); rb.query('jobId', params.jobId, {}); + rb.query('useBordaCount', params.useBordaCount, {}); } return this.http .request( @@ -558,6 +563,7 @@ export class XmcdaCriteriaService extends BaseService { prioritizeCompiledCircuitsOfJob(params: { methodName: string; jobId: string; + useBordaCount: boolean; }): Observable { return this.prioritizeCompiledCircuitsOfJob$Response(params).pipe( map( @@ -566,4 +572,333 @@ export class XmcdaCriteriaService extends BaseService { ) ); } + + /** + * Path part for operation analyzeSensitivityOfCompiledCircuitsOfJob + */ + static readonly AnalyzeSensitivityOfCompiledCircuitsOfJobPath = + '/mcda-methods/{methodName}/sensitivity-analyzes/analyze-sensitivity'; + + /** + * Run the MCDA method on the NISQ Analyzer job passed as parameter + * + * This method provides access to the full `HttpResponse`, allowing access to response headers. + * To access only the response body, use `analyzeSensitivityOfCompiledCircuitsOfJob()` instead. + * + * This method doesn't expect any request body. + */ + analyzeSensitivityOfCompiledCircuitsOfJob$Response(params: { + methodName: string; + jobId: string; + stepSize: number; + upperBound: number; + lowerBound: number; + useBordaCount: boolean; + }): Observable> { + const rb = new RequestBuilder( + this.rootUrl, + XmcdaCriteriaService.AnalyzeSensitivityOfCompiledCircuitsOfJobPath, + 'post' + ); + if (params) { + rb.path('methodName', params.methodName, {}); + rb.query('jobId', params.jobId, {}); + rb.query('stepSize', params.stepSize, {}); + rb.query('upperBound', params.upperBound, {}); + rb.query('lowerBound', params.lowerBound, {}); + rb.query('useBordaCount', params.useBordaCount, {}); + } + return this.http + .request( + rb.build({ + responseType: 'json', + accept: 'application/hal+json', + }) + ) + .pipe( + filter((r: any) => r instanceof HttpResponse), + map((r: HttpResponse) => { + return r as StrictHttpResponse; + }) + ); + } + + /** + * Run the MCDA method on the NISQ Analyzer job passed as parameter + * + * This method provides access to only to the response body. + * To access the full response (for headers, for example), `analyzeSensitivityOfCompiledCircuitsOfJob$Response()` instead. + * + * This method doesn't expect any request body. + */ + analyzeSensitivityOfCompiledCircuitsOfJob(params: { + methodName: string; + jobId: string; + stepSize: number; + upperBound: number; + lowerBound: number; + useBordaCount: boolean; + }): Observable { + return this.analyzeSensitivityOfCompiledCircuitsOfJob$Response(params).pipe( + map( + (r: StrictHttpResponse) => + r.body as EntityModelMcdaSensitivityAnalysisJob + ) + ); + } + + /** + * Path part for operation getSensitivityAnalysisJobs + */ + static readonly GetSensitivityAnalysisJobsPath = + '/mcda-methods/{methodName}/sensitivity-analyzes/jobs'; + + /** + * Retrieve all sensitivity analysis jobs for the given method + * + * This method provides access to the full `HttpResponse`, allowing access to response headers. + * To access only the response body, use `getSensitivityAnalysisJobs()` instead. + * + * This method doesn't expect any request body. + */ + getSensitivityAnalysisJobs$Response(params: { + methodName: string; + }): Observable< + StrictHttpResponse + > { + const rb = new RequestBuilder( + this.rootUrl, + XmcdaCriteriaService.GetSensitivityAnalysisJobsPath, + 'get' + ); + if (params) { + rb.path('methodName', params.methodName, {}); + } + return this.http + .request( + rb.build({ + responseType: 'json', + accept: 'application/hal+json', + }) + ) + .pipe( + filter((r: any) => r instanceof HttpResponse), + map((r: HttpResponse) => { + return r as StrictHttpResponse< + CollectionModelEntityModelMcdaSensitivityAnalysisJob + >; + }) + ); + } + + /** + * Retrieve all sensitivity analysis jobs for the given method + * + * This method provides access to only to the response body. + * To access the full response (for headers, for example), `getSensitivityAnalysisJobs$Response()` instead. + * + * This method doesn't expect any request body. + */ + getSensitivityAnalysisJobs(params: { + methodName: string; + }): Observable { + return this.getSensitivityAnalysisJobs$Response(params).pipe( + map( + ( + r: StrictHttpResponse< + CollectionModelEntityModelMcdaSensitivityAnalysisJob + > + ) => r.body as CollectionModelEntityModelMcdaSensitivityAnalysisJob + ) + ); + } + + /** + * Path part for operation getSensitivityAnalysisJob + */ + static readonly GetSensitivityAnalysisJobPath = + '/mcda-methods/{methodName}/sensitivity-analyzes/jobs/{jobId}'; + + /** + * Retrieve the sensitivity analysis job for the given method + * + * This method provides access to the full `HttpResponse`, allowing access to response headers. + * To access only the response body, use `getSensitivityAnalysisJob()` instead. + * + * This method doesn't expect any request body. + */ + getSensitivityAnalysisJob$Response(params: { + methodName: string; + jobId: string; + }): Observable> { + const rb = new RequestBuilder( + this.rootUrl, + XmcdaCriteriaService.GetSensitivityAnalysisJobPath, + 'get' + ); + if (params) { + rb.path('methodName', params.methodName, {}); + rb.path('jobId', params.jobId, {}); + } + return this.http + .request( + rb.build({ + responseType: 'json', + accept: 'application/hal+json', + }) + ) + .pipe( + filter((r: any) => r instanceof HttpResponse), + map((r: HttpResponse) => { + return r as StrictHttpResponse; + }) + ); + } + + /** + * Retrieve the sensitivity analysis job for the given method + * + * This method provides access to only to the response body. + * To access the full response (for headers, for example), `getSensitivityAnalysisJob$Response()` instead. + * + * This method doesn't expect any request body. + */ + getSensitivityAnalysisJob(params: { + methodName: string; + jobId: string; + }): Observable { + return this.getSensitivityAnalysisJob$Response(params).pipe( + map( + (r: StrictHttpResponse) => + r.body as EntityModelMcdaSensitivityAnalysisJob + ) + ); + } + + /** + * Path part for operation getWeightLearningJob + */ + static readonly GetWeightLearningJobPath = + '/mcda-methods/{methodName}/weight-learning-methods/{weightLearningMethod}/jobs/{jobId}'; + + /** + * Retrieve all MCDA-weight-learning jobs for the given method + * + * This method provides access to the full `HttpResponse`, allowing access to response headers. + * To access only the response body, use `getWeightLearningJob()` instead. + * + * This method doesn't expect any request body. + */ + getWeightLearningJob$Response(params: { + methodName: string; + weightLearningMethod: string; + jobId: string; + }): Observable> { + const rb = new RequestBuilder( + this.rootUrl, + XmcdaCriteriaService.GetWeightLearningJobPath, + 'get' + ); + if (params) { + rb.path('methodName', params.methodName, {}); + rb.path('weightLearningMethod', params.weightLearningMethod, {}); + rb.path('jobId', params.jobId, {}); + } + return this.http + .request( + rb.build({ + responseType: 'json', + accept: 'application/hal+json', + }) + ) + .pipe( + filter((r: any) => r instanceof HttpResponse), + map((r: HttpResponse) => { + return r as StrictHttpResponse; + }) + ); + } + + /** + * Retrieve all MCDA-weight-learning jobs for the given method + * + * This method provides access to only to the response body. + * To access the full response (for headers, for example), `getWeightLearningJob$Response()` instead. + * + * This method doesn't expect any request body. + */ + getWeightLearningJob(params: { + methodName: string; + weightLearningMethod: string; + jobId: string; + }): Observable { + return this.getWeightLearningJob$Response(params).pipe( + map( + (r: StrictHttpResponse) => + r.body as EntityModelMcdaWeightLearningJob + ) + ); + } + + /** + * Path part for operation learnWeightsForCompiledCircuitsOfJob + */ + static readonly LearnWeightsForCompiledCircuitsOfJobPath = + '/mcda-methods/{methodName}/weight-learning-methods/{weightLearningMethod}/learning-weights'; + + /** + * Run the MCDA method and weight learning method on the NISQ Analyzer, job passed as parameter + * + * This method provides access to the full `HttpResponse`, allowing access to response headers. + * To access only the response body, use `learnWeightsForCompiledCircuitsOfJob()` instead. + * + * This method doesn't expect any request body. + */ + learnWeightsForCompiledCircuitsOfJob$Response(params: { + methodName: string; + weightLearningMethod: string; + }): Observable> { + const rb = new RequestBuilder( + this.rootUrl, + XmcdaCriteriaService.LearnWeightsForCompiledCircuitsOfJobPath, + 'post' + ); + if (params) { + rb.path('methodName', params.methodName, {}); + rb.path('weightLearningMethod', params.weightLearningMethod, {}); + } + return this.http + .request( + rb.build({ + responseType: 'json', + accept: 'application/hal+json', + }) + ) + .pipe( + filter((r: any) => r instanceof HttpResponse), + map((r: HttpResponse) => { + return r as StrictHttpResponse; + }) + ); + } + + /** + * Run the MCDA method and weight learning method on the NISQ Analyzer, job passed as parameter + * + * This method provides access to only to the response body. + * To access the full response (for headers, for example), `learnWeightsForCompiledCircuitsOfJob$Response()` instead. + * + * This method doesn't expect any request body. + */ + learnWeightsForCompiledCircuitsOfJob(params: { + methodName: string; + weightLearningMethod: string; + }): Observable { + return this.learnWeightsForCompiledCircuitsOfJob$Response(params).pipe( + map( + (r: StrictHttpResponse) => + r.body as EntityModelMcdaWeightLearningJob + ) + ); + } } diff --git a/src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-dialog/implementation-nisq-analyzer-qpu-selection-dialog.component.ts b/src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-dialog/implementation-nisq-analyzer-qpu-selection-dialog.component.ts index 5697219a..eb07894c 100644 --- a/src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-dialog/implementation-nisq-analyzer-qpu-selection-dialog.component.ts +++ b/src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-dialog/implementation-nisq-analyzer-qpu-selection-dialog.component.ts @@ -80,7 +80,7 @@ export class ImplementationNisqAnalyzerQpuSelectionDialogComponent this.vendor.setValue('IBMQ'); this.onVendorChanged(this.vendor.value); - this.simulatorAllowed.setValue(false); + this.simulatorAllowed.setValue(true); this.setCompilerOptions(this.vendor.value); this.dialogRef.beforeClosed().subscribe(() => { diff --git a/src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-prioritization-dialog/implementation-nisq-analyzer-qpu-selection-prioritization-dialog.component.css b/src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-prioritization-dialog/implementation-nisq-analyzer-qpu-selection-prioritization-dialog.component.css new file mode 100644 index 00000000..b9a6d393 --- /dev/null +++ b/src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-prioritization-dialog/implementation-nisq-analyzer-qpu-selection-prioritization-dialog.component.css @@ -0,0 +1,23 @@ +:host ::ng-deep .mat-horizontal-stepper-header-container { + display: none !important; +} + +button.defineOwnPreferencesButton { + background: none; + border: none; + padding: 0; + margin: 0; +} + +mat-expansion-panel.advancedSettings { + background: none; + border: none; + padding: 0; + margin: 0; +} + +.waitingLearning { + justify-content: center; + align-items: center; +} + diff --git a/src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-prioritization-dialog/implementation-nisq-analyzer-qpu-selection-prioritization-dialog.component.html b/src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-prioritization-dialog/implementation-nisq-analyzer-qpu-selection-prioritization-dialog.component.html index c2f79784..1933e4de 100644 --- a/src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-prioritization-dialog/implementation-nisq-analyzer-qpu-selection-prioritization-dialog.component.html +++ b/src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-prioritization-dialog/implementation-nisq-analyzer-qpu-selection-prioritization-dialog.component.html @@ -1,40 +1,162 @@
-

{{data.title}}

-
-
- - MCDA Method - - TOPSIS - PROMETHEE II - ELECTRE III - - -

Assign points between 0 (low importance) and 100 (high importance) in the following to define the weighting of metrics.

-
-
+ + +

Prioritize Analysis Results

+
+ +

Select predefined preferences + Short waiting time + + Stable execution + results + + + + + Advanced settings + + + + MCDA Method + + TOPSIS + PROMETHEE II + + ELECTRE III + + + + + Weight Learning Method + + COBYLA + Evolution Strategy + Genetic Algorithm + + + + +

+ +
+ +
+ +
+ + + +
+ +
+
+ +

{{data.title}}

+
+
- {{ criterion.name }} - - Please enter a value between 0 and 100 + MCDA Method + + TOPSIS + PROMETHEE II + ELECTRE III + +

Assign points between 0 (low importance) and 100 (high importance) in the following to define the + weighting of metrics.

+
+
+ + {{ criterion.name }} + + Please enter a value between 0 and 100 + +
+
+
+
+
+ + + +
+
+ +
+

Learning weights to prioritize based on previous execution results ...

+
+ +
+
+
- -
-
- - -
+ +

Learned Weights

+
+
+

The learned weights are presented

+
+
+
+ + {{ criterion.name }} + + Please use float numbers as weights + +
+
+
+
+
+
+ + +
+
+ +
diff --git a/src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-prioritization-dialog/implementation-nisq-analyzer-qpu-selection-prioritization-dialog.component.ts b/src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-prioritization-dialog/implementation-nisq-analyzer-qpu-selection-prioritization-dialog.component.ts index fb6ab3bd..9ffd26d4 100644 --- a/src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-prioritization-dialog/implementation-nisq-analyzer-qpu-selection-prioritization-dialog.component.ts +++ b/src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-prioritization-dialog/implementation-nisq-analyzer-qpu-selection-prioritization-dialog.component.ts @@ -1,4 +1,4 @@ -import { Component, Inject, OnInit } from '@angular/core'; +import { Component, Inject, OnInit, ViewChild } from '@angular/core'; import { AbstractControl, FormBuilder, @@ -12,18 +12,37 @@ import { MatDialogRef, } from '@angular/material/dialog'; import { XmcdaCriteriaService } from 'api-nisq/services/xmcda-criteria.service'; +import { MatStepper } from '@angular/material/stepper'; +import { EntityModelMcdaWeightLearningJob } from 'api-nisq/models/entity-model-mcda-weight-learning-job'; +import { interval, Subscription } from 'rxjs'; +import { startWith, switchMap } from 'rxjs/operators'; +import { UtilService } from '../../../../../util/util.service'; @Component({ selector: 'app-implementation-nisq-analyzer-qpu-selection-prioritization-dialog', templateUrl: './implementation-nisq-analyzer-qpu-selection-prioritization-dialog.component.html', + styleUrls: [ + './implementation-nisq-analyzer-qpu-selection-prioritization-dialog.component.css', + ], }) export class ImplementationNisqAnalyzerQpuSelectionPrioritizationDialogComponent implements OnInit { + @ViewChild('matHorizontalStepper') matHorizontalStepper: MatStepper; prioritizationFrom: FormGroup; + weightLearningForm: FormGroup; + preferenceForm: FormGroup; criteriaNamesAndValues: Criterion[] = []; inputChanged = false; + shortWaitingTimeEnabled = false; + stableExecutionResultsEnabled = false; + advancedSettingsOpen: boolean; + mcdaMethodPredefinedPreferences = 'topsis'; + weightLearningMethodPredefinedPreferences = 'cobyla'; + weightLearningJob: EntityModelMcdaWeightLearningJob; + jobReady: boolean; + pollingWeightLearningJobData: Subscription; constructor( public dialogRef: MatDialogRef< @@ -32,9 +51,26 @@ export class ImplementationNisqAnalyzerQpuSelectionPrioritizationDialogComponent @Inject(MAT_DIALOG_DATA) public data: DialogData, public dialog: MatDialog, private formBuilder: FormBuilder, - private mcdaService: XmcdaCriteriaService + private mcdaService: XmcdaCriteriaService, + private utilService: UtilService ) {} + get preferenceMcdaMethod(): AbstractControl | null { + return this.preferenceForm.get('preferenceMcdaMethod'); + } + + get weightLearningMethod(): AbstractControl | null { + return this.preferenceForm.get('weightLearningMethod'); + } + + get shortWaitingTime(): AbstractControl | null { + return this.preferenceForm.get('shortWaitingTime'); + } + + get stableExecutionResults(): AbstractControl | null { + return this.preferenceForm.get('stableExecutionResults'); + } + get mcdaMethod(): AbstractControl | null { return this.prioritizationFrom.get('mcdaMethod'); } @@ -43,7 +79,37 @@ export class ImplementationNisqAnalyzerQpuSelectionPrioritizationDialogComponent return this.prioritizationFrom.get('criteriaAndValues'); } + get criteriaAndWeightValues(): AbstractControl | null { + return this.weightLearningForm.get('criteriaAndValues'); + } + ngOnInit(): void { + this.preferenceForm = new FormGroup({ + preferenceMcdaMethod: new FormControl(this.data.mcdaMethod, [ + // eslint-disable-next-line @typescript-eslint/unbound-method + Validators.required, + ]), + weightLearningMethod: new FormControl(this.data.weightLearningMethod, [ + // eslint-disable-next-line @typescript-eslint/unbound-method + Validators.required, + ]), + shortWaitingTime: new FormControl(this.data.shortWaitingTime, [ + // eslint-disable-next-line @typescript-eslint/unbound-method + Validators.required, + ]), + stableExecutionResults: new FormControl( + this.data.stableExecutionResults, + [ + // eslint-disable-next-line @typescript-eslint/unbound-method + Validators.required, + ] + ), + }); + this.preferenceMcdaMethod.setValue('topsis'); + this.weightLearningMethod.setValue('cobyla'); + this.stableExecutionResults.setValue(false); + this.shortWaitingTime.setValue(false); + this.onMcdaMethodChanged('topsis'); } @@ -51,6 +117,32 @@ export class ImplementationNisqAnalyzerQpuSelectionPrioritizationDialogComponent this.dialogRef.close(); } + setWaitingTimeEnabled(enabled: boolean): void { + this.shortWaitingTimeEnabled = enabled; + this.shortWaitingTime.setValue(this.shortWaitingTimeEnabled); + } + + setStableExecutionResultsEnabled(enabled: boolean): void { + this.stableExecutionResultsEnabled = enabled; + this.stableExecutionResults.setValue(this.stableExecutionResultsEnabled); + } + + setMcdaMethodPredefinedPreferences(selectedMcdaMethod: string): void { + this.mcdaMethodPredefinedPreferences = selectedMcdaMethod; + } + + setWeightLearningMethodPredefinedPreferences( + selectedWeightLearningMethod: string + ): void { + this.weightLearningMethodPredefinedPreferences = selectedWeightLearningMethod; + } + + resetPredefinedPreferences(): boolean { + this.setWaitingTimeEnabled(false); + this.setStableExecutionResultsEnabled(false); + return true; + } + onMcdaMethodChanged(mcdaMethod: string): void { this.criteriaNamesAndValues = []; this.mcdaService @@ -89,16 +181,61 @@ export class ImplementationNisqAnalyzerQpuSelectionPrioritizationDialogComponent ) ), }); + this.weightLearningForm = this.formBuilder.group({ + criteriaAndValues: this.formBuilder.array( + this.criteriaNamesAndValues.map((c) => + this.formBuilder.group({ + [c.name]: [c.weight], + }) + ) + ), + }); this.mcdaMethod.setValue(mcdaMethod); this.dialogRef.beforeClosed().subscribe(() => { - this.data.mcdaMethod = this.mcdaMethod.value; + if ( + this.shortWaitingTime.value || + this.stableExecutionResults.value + ) { + this.data.mcdaMethod = this.preferenceMcdaMethod.value; + } else { + this.data.mcdaMethod = this.mcdaMethod.value; + } + this.data.weightLearningMethod = this.weightLearningMethod.value; + this.data.shortWaitingTime = this.shortWaitingTime.value; + this.data.stableExecutionResults = this.stableExecutionResults.value; this.criteriaNamesAndValues.forEach((criterionVal) => { - for (const val of this.criteriaAndValues.value) { - if (criterionVal.name === Object.keys(val)[0]) { - criterionVal.points = Number(Object.values(val)[0]); - break; + if ( + this.shortWaitingTime.value && + !this.stableExecutionResults.value && + criterionVal.name === 'queue-size' + ) { + criterionVal.points = 100; + } else if ( + this.shortWaitingTime.value && + !this.stableExecutionResults.value && + criterionVal.name !== 'queue-size' + ) { + criterionVal.points = 0; + } else if (this.stableExecutionResults.value) { + for (const val of this.criteriaAndWeightValues.value) { + if (criterionVal.name === Object.keys(val)[0]) { + if (criterionVal.name !== 'queue-size') { + criterionVal.weight = Number(Object.values(val)[0]); + } else { + criterionVal.weight = 0.0; + } + break; + } + } + } else { + for (const val of this.criteriaAndValues.value) { + if (criterionVal.name === Object.keys(val)[0]) { + criterionVal.points = Number(Object.values(val)[0]); + break; + } } } + this.data.criteriaAndWeightValues = this.criteriaNamesAndValues; this.data.criteriaAndValues = this.criteriaNamesAndValues; }); }); @@ -107,15 +244,62 @@ export class ImplementationNisqAnalyzerQpuSelectionPrioritizationDialogComponent }); } + onLearnWeights(): boolean { + this.mcdaService + .learnWeightsForCompiledCircuitsOfJob({ + methodName: this.mcdaMethodPredefinedPreferences, + weightLearningMethod: this.weightLearningMethodPredefinedPreferences, + }) + .subscribe((job) => { + this.weightLearningJob = job; + this.jobReady = job.ready; + + this.pollingWeightLearningJobData = interval(2000) + .pipe( + startWith(0), + switchMap(() => + this.mcdaService.getWeightLearningJob({ + methodName: this.mcdaMethodPredefinedPreferences, + weightLearningMethod: this + .weightLearningMethodPredefinedPreferences, + jobId: this.weightLearningJob.id, + }) + ) + ) + .subscribe((jobResult) => { + this.weightLearningJob = jobResult; + this.jobReady = jobResult.ready; + if (jobResult.state === 'FINISHED') { + this.onMcdaMethodChanged(this.mcdaMethodPredefinedPreferences); + this.pollingWeightLearningJobData.unsubscribe(); + } else if (jobResult.state === 'FAILED') { + this.pollingWeightLearningJobData.unsubscribe(); + this.utilService.callSnackBar('Error! Could not learn weights.'); + this.onNoClick(); + } + }); + }); + return true; + } + onChangeEvent(): void { this.inputChanged = true; } + + move(index: number): boolean { + this.matHorizontalStepper.selectedIndex = index; + return true; + } } export interface DialogData { title: string; mcdaMethod: string; + weightLearningMethod: string; + shortWaitingTime: boolean; + stableExecutionResults: boolean; criteriaAndValues: Criterion[]; + criteriaAndWeightValues: Criterion[]; } export interface Criterion { diff --git a/src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog.component.html b/src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog.component.html new file mode 100644 index 00000000..23e8e921 --- /dev/null +++ b/src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog.component.html @@ -0,0 +1,27 @@ +

{{data.title}}

+
+
+

To analyze the sensitivity of the ranking, defined weights are changed to a customizable range.

+

What is the maximum percentage each individual weight should be increased?

+ + Upper bound + + +

What is the maximum percentage each individual weight should be decreased?

+ + Lower bound + + +

How big should the weight steps be until the bounds are reached?

+ + Step size + + +
+
+
+ + +
+ diff --git a/src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog.component.scss b/src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog.component.ts b/src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog.component.ts new file mode 100644 index 00000000..62a1292b --- /dev/null +++ b/src/app/components/algorithms/implementation-view/dialogs/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog.component.ts @@ -0,0 +1,90 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { + MAT_DIALOG_DATA, + MatDialog, + MatDialogRef, +} from '@angular/material/dialog'; +import { + AbstractControl, + FormControl, + FormGroup, + Validators, +} from '@angular/forms'; + +@Component({ + selector: + 'app-implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog', + templateUrl: + './implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog.component.html', + styleUrls: [ + './implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog.component.scss', + ], +}) +export class ImplementationNisqAnalyzerQpuSelectionSensitivityAnalysisDialogComponent + implements OnInit { + sensitivityAnalysisForm: FormGroup; + + constructor( + public dialogRef: MatDialogRef< + ImplementationNisqAnalyzerQpuSelectionSensitivityAnalysisDialogComponent + >, + @Inject(MAT_DIALOG_DATA) public data: DialogData, + public dialog: MatDialog + ) {} + + get stepSize(): AbstractControl | null { + return this.sensitivityAnalysisForm.get('stepSize'); + } + + get upperBound(): AbstractControl | null { + return this.sensitivityAnalysisForm.get('upperBound'); + } + + get lowerBound(): AbstractControl | null { + return this.sensitivityAnalysisForm.get('lowerBound'); + } + + ngOnInit(): void { + this.sensitivityAnalysisForm = new FormGroup({ + stepSize: new FormControl(this.data.stepSize, [ + // eslint-disable-next-line @typescript-eslint/unbound-method + Validators.required, + ]), + upperBound: new FormControl(this.data.upperBound, [ + // eslint-disable-next-line @typescript-eslint/unbound-method + Validators.required, + ]), + lowerBound: new FormControl(this.data.lowerBound, [ + // eslint-disable-next-line @typescript-eslint/unbound-method + Validators.required, + ]), + }); + + this.stepSize.setValue(0.01); + this.upperBound.setValue(500); + this.lowerBound.setValue(0.001); + + this.dialogRef.beforeClosed().subscribe(() => { + this.data.stepSize = this.stepSize.value; + this.data.upperBound = this.upperBound.value; + this.data.lowerBound = this.lowerBound.value; + }); + } + + onNoClick(): void { + this.dialogRef.close(); + } + + isRequiredDataMissing(): boolean { + return this.upperBound.errors?.required; + return this.lowerBound.errors?.required; + return this.stepSize.errors?.required; + } +} + +interface DialogData { + title: string; + stepSize: number; + upperBound: number; + lowerBound: number; +} diff --git a/src/app/components/algorithms/implementation-view/implementation-nisq-analyzer-qpu-selection/implementation-nisq-analyzer-qpu-selection.component.html b/src/app/components/algorithms/implementation-view/implementation-nisq-analyzer-qpu-selection/implementation-nisq-analyzer-qpu-selection.component.html index 2a395d86..9b7a9ac1 100644 --- a/src/app/components/algorithms/implementation-view/implementation-nisq-analyzer-qpu-selection/implementation-nisq-analyzer-qpu-selection.component.html +++ b/src/app/components/algorithms/implementation-view/implementation-nisq-analyzer-qpu-selection/implementation-nisq-analyzer-qpu-selection.component.html @@ -106,6 +106,27 @@

QPU Analysis Jobs

class="mat-spinner-left">
+ +

QPU Analysis Job from {{ analyzerJob.time }}

@@ -121,7 +142,8 @@

QPU Analysis Job from {{ analyzerJob.time }}

No suitable QPUs found!
- +
Rank diff --git a/src/app/components/algorithms/implementation-view/implementation-nisq-analyzer-qpu-selection/implementation-nisq-analyzer-qpu-selection.component.scss b/src/app/components/algorithms/implementation-view/implementation-nisq-analyzer-qpu-selection/implementation-nisq-analyzer-qpu-selection.component.scss index aaeb02a1..11792764 100644 --- a/src/app/components/algorithms/implementation-view/implementation-nisq-analyzer-qpu-selection/implementation-nisq-analyzer-qpu-selection.component.scss +++ b/src/app/components/algorithms/implementation-view/implementation-nisq-analyzer-qpu-selection/implementation-nisq-analyzer-qpu-selection.component.scss @@ -132,3 +132,15 @@ button-column { justify-content: center; align-items: center; } + +.sensAnalysisResultsButton { + background: none; + border: none; + padding: 0; + margin: 0; + align-items: center; +} + +.link-icon { + vertical-align: middle; +} diff --git a/src/app/components/algorithms/implementation-view/implementation-nisq-analyzer-qpu-selection/implementation-nisq-analyzer-qpu-selection.component.ts b/src/app/components/algorithms/implementation-view/implementation-nisq-analyzer-qpu-selection/implementation-nisq-analyzer-qpu-selection.component.ts index c0701f41..4b65ff5c 100644 --- a/src/app/components/algorithms/implementation-view/implementation-nisq-analyzer-qpu-selection/implementation-nisq-analyzer-qpu-selection.component.ts +++ b/src/app/components/algorithms/implementation-view/implementation-nisq-analyzer-qpu-selection/implementation-nisq-analyzer-qpu-selection.component.ts @@ -26,6 +26,7 @@ import { ImplementationDto as NisqImplementationDto } from 'api-nisq/models/impl import { CriterionValue, EntityModelMcdaJob, + EntityModelMcdaSensitivityAnalysisJob, ExecutionResultDto, QpuSelectionDto, QpuSelectionResultDto, @@ -47,6 +48,8 @@ import { DialogData, ImplementationNisqAnalyzerQpuSelectionPrioritizationDialogComponent, } from '../dialogs/implementation-nisq-analyzer-qpu-selection-prioritization-dialog/implementation-nisq-analyzer-qpu-selection-prioritization-dialog.component'; +// eslint-disable-next-line max-len +import { ImplementationNisqAnalyzerQpuSelectionSensitivityAnalysisDialogComponent } from '../dialogs/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog.component'; @Component({ selector: 'app-implementation-nisq-analyzer-qpu-selection', @@ -120,8 +123,17 @@ export class ImplementationNisqAnalyzerQpuSelectionComponent prioritizationJob: EntityModelMcdaJob; prioritizationJobReady = false; loadingMCDAJob = false; + mcdaJobSuccessful = false; rankings: Ranking[] = []; dataSource = new MatTableDataSource(this.analyzerResults); + bordaCountEnabled: boolean; + usedMcdaMethod: string; + sensitivityAnalysisJob: EntityModelMcdaSensitivityAnalysisJob; + sensitivityAnalysisJobReady = false; + pollingSensitivityAnalysisJobReadyData: Subscription; + sensitivityAnalysisJobSuccessful = false; + waitUntilSensitivityAnalysisIsFinished = false; + sensitivityAnalysisPlot: string; constructor( private utilService: UtilService, @@ -356,12 +368,11 @@ export class ImplementationNisqAnalyzerQpuSelectionComponent } prioritize(): void { - this.rankings = []; this.utilService .createDialog( ImplementationNisqAnalyzerQpuSelectionPrioritizationDialogComponent, { - title: 'Prioritize QPU-Selection-Analysis', + title: 'Prioritize Analysis Results', } ) .afterClosed() @@ -371,19 +382,34 @@ export class ImplementationNisqAnalyzerQpuSelectionComponent this.loadingMCDAJob = true; this.prioritizationJob = undefined; this.prioritizationJobReady = false; - // calculate SMART with new assigned points - dialogResult.criteriaAndValues.forEach((obj) => { - totalSum += obj.points; - }); - dialogResult.criteriaAndValues.forEach((obj) => { - if (obj.points !== 0) { - obj.weight = obj.points / totalSum; - } else { - obj.weight = 0; - } - }); + this.usedMcdaMethod = dialogResult.mcdaMethod; + if ( + dialogResult.stableExecutionResults && + dialogResult.shortWaitingTime + ) { + this.bordaCountEnabled = true; + } else { + this.bordaCountEnabled = false; + } + + let criteria = dialogResult.criteriaAndValues; + if (dialogResult.stableExecutionResults) { + criteria = dialogResult.criteriaAndWeightValues; + } else { + // calculate SMART with new assigned points + dialogResult.criteriaAndValues.forEach((obj) => { + totalSum += obj.points; + }); + dialogResult.criteriaAndValues.forEach((obj) => { + if (obj.points !== 0) { + obj.weight = obj.points / totalSum; + } else { + obj.weight = 0; + } + }); + } let numberOfCriterion = 0; - dialogResult.criteriaAndValues.forEach((obj) => { + criteria.forEach((obj) => { const criterionValue: CriterionValue = { description: { title: 'points', subTitle: obj.points.toString() }, criterionID: obj.id, @@ -399,17 +425,18 @@ export class ImplementationNisqAnalyzerQpuSelectionComponent .subscribe( () => { numberOfCriterion++; - if ( - numberOfCriterion === dialogResult.criteriaAndValues.length - ) { + if (numberOfCriterion === criteria.length) { this.mcdaService .prioritizeCompiledCircuitsOfJob({ methodName: dialogResult.mcdaMethod, jobId: this.analyzerJob.id, + useBordaCount: this.bordaCountEnabled, }) .subscribe((job) => { + this.rankings = []; this.prioritizationJob = job; this.prioritizationJobReady = job.ready; + this.mcdaJobSuccessful = false; this.utilService.callSnackBar( 'Successfully created prioritization job "' + @@ -468,6 +495,7 @@ export class ImplementationNisqAnalyzerQpuSelectionComponent } }); this.dataSource = new MatTableDataSource(this.analyzerResults); + this.mcdaJobSuccessful = true; this.pollingAnalysisJobData.unsubscribe(); } }, @@ -491,13 +519,84 @@ export class ImplementationNisqAnalyzerQpuSelectionComponent getScoreOfResult(result: QpuSelectionResultDto): number | string { const rankingResult = this.rankings.find((value) => value.id === result.id); - if (rankingResult && this.prioritizationJob.method !== 'electre-III') { + if ( + rankingResult && + this.prioritizationJob.method !== 'electre-III' && + !this.bordaCountEnabled + ) { return rankingResult.score; } else { return '-'; } } + analyzeSensitivity(): void { + this.utilService + .createDialog( + ImplementationNisqAnalyzerQpuSelectionSensitivityAnalysisDialogComponent, + { + title: 'Analyze Sensitivity of Ranking', + } + ) + .afterClosed() + .subscribe((dialogResult) => { + if (dialogResult) { + this.mcdaService + .analyzeSensitivityOfCompiledCircuitsOfJob({ + methodName: this.usedMcdaMethod, + jobId: this.analyzerJob.id, + stepSize: dialogResult.stepSize, + upperBound: dialogResult.upperBound, + lowerBound: dialogResult.lowerBound, + useBordaCount: this.bordaCountEnabled, + }) + .subscribe( + (job) => { + this.waitUntilSensitivityAnalysisIsFinished = true; + this.sensitivityAnalysisJobSuccessful = false; + this.sensitivityAnalysisJob = job; + this.sensitivityAnalysisJobReady = job.ready; + this.utilService.callSnackBar( + 'Successfully created sensitivity analysis job "' + + job.id + + '".' + ); + + this.pollingSensitivityAnalysisJobReadyData = interval(2000) + .pipe( + startWith(0), + switchMap(() => + this.mcdaService.getSensitivityAnalysisJob({ + methodName: this.usedMcdaMethod, + jobId: job.id, + }) + ) + ) + .subscribe((jobResult) => { + this.sensitivityAnalysisJob = jobResult; + this.sensitivityAnalysisJobReady = jobResult.ready; + if (jobResult.state === 'FINISHED') { + this.sensitivityAnalysisJobSuccessful = true; + this.waitUntilSensitivityAnalysisIsFinished = false; + this.sensitivityAnalysisPlot = jobResult.plotFileLocation; + this.pollingSensitivityAnalysisJobReadyData.unsubscribe(); + } + }); + }, + () => { + this.utilService.callSnackBar( + 'Error! Could not start sensitivity analysis.' + ); + } + ); + } + }); + } + + goToLink(url: string): void { + window.open(url, '_blank'); + } + showBackendQueueSize(analysisResult: QpuSelectionResultDto): void { this.nisqAnalyzerService .getIBMQBackendState(analysisResult.qpu) diff --git a/src/app/components/algorithms/implementation-view/implementation-view.module.ts b/src/app/components/algorithms/implementation-view/implementation-view.module.ts index 42976a8a..15f31280 100644 --- a/src/app/components/algorithms/implementation-view/implementation-view.module.ts +++ b/src/app/components/algorithms/implementation-view/implementation-view.module.ts @@ -22,6 +22,7 @@ import { MatOptionModule } from '@angular/material/core'; import { MatSelectModule } from '@angular/material/select'; import { MatBadgeModule } from '@angular/material/badge'; import { MatStepperModule } from '@angular/material/stepper'; +import { MatExpansionModule } from '@angular/material/expansion'; import { ComputeResourcePropertyModule } from '../../compute-resource-property/compute-resource-property.module'; import { NavigationBreadcrumbModule } from '../../generics/navigation-breadcrumb/navigation-breadcrumb.module'; import { GenericsModule } from '../../generics/generics.module'; @@ -39,6 +40,8 @@ import { ImplementationNisqAnalyzerQpuSelectionComponent } from './implementatio import { ImplementationNisqAnalyzerQpuSelectionDialogComponent } from './dialogs/implementation-nisq-analyzer-qpu-selection-dialog/implementation-nisq-analyzer-qpu-selection-dialog.component'; // eslint-disable-next-line max-len import { ImplementationNisqAnalyzerQpuSelectionPrioritizationDialogComponent } from './dialogs/implementation-nisq-analyzer-qpu-selection-prioritization-dialog/implementation-nisq-analyzer-qpu-selection-prioritization-dialog.component'; +// eslint-disable-next-line max-len +import { ImplementationNisqAnalyzerQpuSelectionSensitivityAnalysisDialogComponent } from './dialogs/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog/implementation-nisq-analyzer-qpu-selection-sensitivity-analysis-dialog.component'; @NgModule({ declarations: [ @@ -51,6 +54,7 @@ import { ImplementationNisqAnalyzerQpuSelectionPrioritizationDialogComponent } f ImplementationNisqAnalyzerQpuSelectionComponent, ImplementationNisqAnalyzerQpuSelectionDialogComponent, ImplementationNisqAnalyzerQpuSelectionPrioritizationDialogComponent, + ImplementationNisqAnalyzerQpuSelectionSensitivityAnalysisDialogComponent, ], imports: [ CommonModule, @@ -82,6 +86,7 @@ import { ImplementationNisqAnalyzerQpuSelectionPrioritizationDialogComponent } f QcAtlasUiFeatureToggleModule, MatBadgeModule, MatStepperModule, + MatExpansionModule, ], }) export class ImplementationViewModule {}