diff --git a/backend/db/init/01.schema.sql b/backend/db/init/01.schema.sql index 1b9270c..1820d9c 100644 --- a/backend/db/init/01.schema.sql +++ b/backend/db/init/01.schema.sql @@ -1,75 +1,34 @@ +drop table main.devices; CREATE TABLE IF NOT EXISTS main.devices ( id VARCHAR(64) PRIMARY KEY, - device_type ENUM ('QPU', 'simulator') NOT NULL, - status ENUM ('AVAILABLE', 'NOT_AVAILABLE') DEFAULT 'NOT_AVAILABLE' NOT NULL, - restart_at DATETIME, - pending_tasks INT DEFAULT 0 NOT NULL, - n_qubits INT NOT NULL, - n_nodes INT, + device_type VARCHAR(32) DEFAULT 'QPU' NOT NULL, + status VARCHAR(64) DEFAULT 'available' NOT NULL, + available_at DATETIME, + pending_jobs INT DEFAULT 0 NOT NULL, + n_qubits INT DEFAULT 1 NOT NULL, basis_gates VARCHAR(256) NOT NULL, instructions VARCHAR(64) NOT NULL, - calibration_data TEXT, + device_info TEXT, calibrated_at DATETIME, - description VARCHAR(128) NOT NULL + description VARCHAR(128) NOT NULL, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ); --- INSERT INTO main.devices (id, device_type, n_qubits, n_nodes, basis_gates, instructions, description) --- SELECT 'SC', 'QPU', 64, NULL, '["sx", "rz", "rzx90", "id"]', '["measure", "barrier"]', 'Superconducting quantum computer' --- WHERE NOT EXISTS (SELECT * FROM main.devices WHERE id = 'SC'); - --- INSERT INTO main.devices (id, device_type, n_qubits, n_nodes, basis_gates, instructions, description) --- SELECT 'SVSim', 'simulator', 39, 512, '["x", "y", "z", "h", "s", "sdg", "t", "tdg", "rx", "ry", "rz", "cx", "cz", "swap", "u1", "u2", "u3", "u", "p", "id", "sx", "sxdg"]', '["measure", "barrier", "reset"]', 'State vector-based quantum circuit simulator' --- WHERE NOT EXISTS (SELECT * FROM main.devices WHERE id = 'SVSim'); - - -CREATE TABLE IF NOT EXISTS main.tasks ( - id VARBINARY(16) PRIMARY KEY, +drop table main.jobs; +CREATE TABLE IF NOT EXISTS main.jobs ( + id VARCHAR(64) PRIMARY KEY, owner VARCHAR(64) NOT NULL, - name varchar(256), - device VARCHAR(64) NOT NULL, - n_qubits INT, - n_nodes INT, - code TEXT NOT NULL, - action ENUM ('sampling', 'estimation') NOT NULL, - method ENUM ('state_vector', 'sampling'), - shots INT, - operator VARCHAR(1024), - qubit_allocation TEXT, - skip_transpilation BOOLEAN DEFAULT false NOT NULL, - seed_transpilation INT, - seed_simulation INT, - n_per_node INT UNSIGNED, - simulation_opt text, - ro_error_mitigation enum('none', 'pseudo_inverse', 'least_square'), - note VARCHAR(1024), - status ENUM ('QUEUED', 'QUEUED_FETCHED', 'RUNNING', 'COMPLETED', 'FAILED', 'CANCELLING', 'CANCELLING_FETCHED', 'CANCELLED') NOT NULL DEFAULT 'QUEUED', - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (device) REFERENCES devices(id) + name varchar(256) DEFAULT '' NOT NULL, + description VARCHAR(1024), + device_id VARCHAR(64) NOT NULL, + job_info TEXT, + transpiler_info TEXT, + simulator_info TEXT, + mitigation_info TEXT, + job_type VARCHAR(32) DEFAULT 'sampling' NOT NULL, + shots INT DEFAULT 1000 NOT NULL, + status VARCHAR(32) DEFAULT 'submitted' NOT NULL, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ); - -CREATE TABLE IF NOT EXISTS main.results ( - task_id VARBINARY(16) PRIMARY KEY, - status ENUM('SUCCESS', 'FAILURE', 'CANCELLED') NOT NULL, - result TEXT, - reason TEXT, - transpiled_code TEXT, - qubit_allocation TEXT, - FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE -); - -delimiter $$ - -CREATE TRIGGER main.update_tasks_status_trigger -AFTER INSERT ON main.results -FOR EACH ROW -BEGIN - IF NEW.status = 'SUCCESS' THEN - UPDATE main.tasks SET status = 'COMPLETED' WHERE id = NEW.task_id; - ELSEIF NEW.status = 'FAILURE' THEN - UPDATE main.tasks SET status = 'FAILED' WHERE id = NEW.task_id; - ELSEIF NEW.status = 'CANCELLED' THEN - UPDATE main.tasks SET status = 'CANCELLED' WHERE id = NEW.task_id; - END IF; -END$$ - -delimiter ; diff --git a/backend/db/init/02.insert_device.sql b/backend/db/init/02.insert_device.sql index 7470d0e..b6beb41 100644 --- a/backend/db/init/02.insert_device.sql +++ b/backend/db/init/02.insert_device.sql @@ -1,15 +1,15 @@ -INSERT INTO main.devices (id, device_type,status, n_qubits, n_nodes, basis_gates, instructions, description) -SELECT 'SC', 'QPU','AVAILABLE', 64, NULL, '["sx", "rz", "rzx90", "id"]', '["measure", "barrier"]', 'Superconducting quantum computer' +INSERT INTO main.devices (id, device_type, status, available_at, pending_jobs, n_qubits, basis_gates, instructions, device_info, calibrated_at, description) +SELECT 'SC', 'QPU','available', CURRENT_TIMESTAMP, 9, 64, '["sx", "rz", "rzx90", "id"]', '["measure", "barrier"]', '', CURRENT_TIMESTAMP, 'Superconducting quantum computer' WHERE NOT EXISTS (SELECT * FROM main.devices WHERE id = 'SC'); -INSERT INTO main.devices (id, device_type, status, n_qubits, n_nodes, basis_gates, instructions, description) -SELECT 'SVSim', 'simulator','AVAILABLE', 39, 512, '["x", "y", "z", "h", "s", "sdg", "t", "tdg", "rx", "ry", "rz", "cx", "cz", "swap", "u1", "u2", "u3", "u", "p", "id", "sx", "sxdg"]', '["measure", "barrier", "reset"]', 'State vector-based quantum circuit simulator' +INSERT INTO main.devices (id, device_type, status, available_at, pending_jobs, n_qubits, basis_gates, instructions, device_info, calibrated_at, description) +SELECT 'SVSim', 'simulator','available', CURRENT_TIMESTAMP, 0, 39, '["x", "y", "z", "h", "s", "sdg", "t", "tdg", "rx", "ry", "rz", "cx", "cz", "swap", "u1", "u2", "u3", "u", "p", "id", "sx", "sxdg"]', '["measure", "barrier", "reset"]', '', CURRENT_TIMESTAMP, 'State vector-based quantum circuit simulator' WHERE NOT EXISTS (SELECT * FROM main.devices WHERE id = 'SVSim'); -INSERT INTO main.devices (id, device_type, status, n_qubits, n_nodes, basis_gates, instructions, description) -SELECT 'Kawasaki', 'QPU','AVAILABLE', 64, NULL, '["sx", "rz", "rzx90", "id"]', '["measure", "barrier"]', 'Superconducting quantum computer' +INSERT INTO main.devices (id, device_type, status, available_at, pending_jobs, n_qubits, basis_gates, instructions, device_info, calibrated_at, description) +SELECT 'Kawasaki', 'QPU','available', CURRENT_TIMESTAMP, 2, 64, '["sx", "rz", "rzx90", "id"]', '["measure", "barrier"]', '', CURRENT_TIMESTAMP, 'Superconducting quantum computer' WHERE NOT EXISTS (SELECT * FROM main.devices WHERE id = 'Kawasaki'); -INSERT INTO main.devices (id, device_type, n_qubits, n_nodes, basis_gates, instructions, description) -SELECT 'test1', 'QPU', 64, NULL, '["sx", "rz", "rzx90", "id"]', '["measure", "barrier"]', 'Superconducting quantum computer' -WHERE NOT EXISTS (SELECT * FROM main.devices WHERE id = 'test'); +INSERT INTO main.devices (id, device_type, status, available_at, pending_jobs, n_qubits, basis_gates, instructions, device_info, calibrated_at, description) +SELECT '01927422-86d4-7597-b724-b08a5e7781fc', 'QPU','unavailable', CURRENT_TIMESTAMP, 0, 64, '["sx", "rz", "rzx90", "id"]', '["measure", "barrier"]', '', CURRENT_TIMESTAMP, 'Superconducting quantum computer' +WHERE NOT EXISTS (SELECT * FROM main.devices WHERE id = '01927422-86d4-7597-b724-b08a5e7781fc'); diff --git a/backend/db/init/03.insert_job.sql b/backend/db/init/03.insert_job.sql new file mode 100644 index 0000000..4109132 --- /dev/null +++ b/backend/db/init/03.insert_job.sql @@ -0,0 +1,8 @@ +INSERT INTO main.jobs (id, owner, name, description, device_id, job_info, transpiler_info, simulator_info, mitigation_info, job_type, shots, status) +SELECT '01927422-86d4-73d6-abb4-f2de6a4f5910', 'admin', 'Test job 1', 'Test job 1 description', 'Kawasaki', '{\'code\': \'todo\'}', '', '', '', 'sampling', 1000, 'submitted' +WHERE NOT EXISTS (SELECT * FROM main.jobs WHERE owner = 'admin' AND name = 'Test job 1'); + +INSERT INTO main.jobs (id, owner, name, description, device_id, job_info, transpiler_info, simulator_info, mitigation_info, job_type, shots, status) +SELECT '01927422-86d4-7cbf-98d3-32f5f1263cd9', 'admin', 'Test job 2', 'Test job 2 description', 'Kawasaki', '{\'code\': \'todo\'}', '', '', '', 'sampling', 1000, 'submitted' +WHERE NOT EXISTS (SELECT * FROM main.jobs WHERE owner = 'admin' AND name = 'Test job 2'); + diff --git a/backend/db/init/03.insert_task.sql b/backend/db/init/03.insert_task.sql deleted file mode 100644 index fe46168..0000000 --- a/backend/db/init/03.insert_task.sql +++ /dev/null @@ -1,7 +0,0 @@ -INSERT INTO main.tasks (id, owner, name, device, n_qubits, n_nodes, code, action, method, shots, operator, qubit_allocation, skip_transpilation, seed_transpilation, seed_simulation, n_per_node, simulation_opt, ro_error_mitigation, note, status, created_at) -SELECT UNHEX(REPLACE('7af020f6-2e38-4d70-8cf0-4349650ea08c', '-', '')), 'admin', 'Test task 1', 'Kawasaki', 2, 12, 'OPENQASM 2.0;\ninclude "qelib1.inc";\nqreg q[2];\nh q[0];\ncx q[0], q[1];\nmeasure q[0] -> c[0];\nmeasure q[1] -> c[1];', 'sampling', 'state_vector', 1024, 'Z0*Z1', NULL, false, NULL, NULL, 1, NULL, 'none', NULL, 'QUEUED', CURRENT_TIMESTAMP -WHERE NOT EXISTS (SELECT * FROM main.tasks WHERE owner = 'admin' AND name = 'Test task 1'); - -INSERT INTO main.tasks (id, owner, name, device, n_qubits, n_nodes, code, action, method, shots, operator, qubit_allocation, skip_transpilation, seed_transpilation, seed_simulation, n_per_node, simulation_opt, ro_error_mitigation, note, status, created_at) -SELECT UNHEX(REPLACE('7af020f6-2e38-4d70-8cf0-4349650ea08d', '-', '')), 'admin', 'Test task 2', 'Kawasaki', 2, 12, 'OPENQASM 2.0;\ninclude "qelib1.inc";\nqreg q[2];\nh q[0];\ncx q[0], q[1];\nmeasure q[0] -> c[0];\nmeasure q[1] -> c[1];', 'sampling', 'state_vector', 1024, 'Z0*Z1', NULL, false, NULL, NULL, 1, NULL, 'none', NULL, 'QUEUED_FETCHED', CURRENT_TIMESTAMP -WHERE NOT EXISTS (SELECT * FROM main.tasks WHERE owner = 'admin' AND name = 'Test task 2'); diff --git a/backend/oas/README.md b/backend/oas/README.md index 0423ee3..16e972f 100644 --- a/backend/oas/README.md +++ b/backend/oas/README.md @@ -6,7 +6,7 @@ - ファイル名は、原則`{tag}.{FooBar}.yaml`の形式とし、FooBarはキャメルケースとする - ファイル名の`tag`は、APIのリソース名とする -- ファイル名の`FooBar`は、後続するAPIのメソッド名とする(例: `task/{task_id}`→`task.TaskId.yaml`) +- ファイル名の`FooBar`は、後続するAPIのメソッド名とする(例: `job/{job_id}`→`job.JobId.yaml`) - `datamodel-code-generator`は、`{tag}.{FooBar}.yaml`の形式のファイルを読み込むため、`tag`は、APIのリソース名とし、`FooBar`は、自動生成されるコードのクラス名とする #### 例1.1 @@ -16,21 +16,21 @@ tree . ├── openapi.yaml ├── parameters -│ └── task.TaskId.yaml +│ └── job.JobId.yaml ├── paths │ ├── hello.yaml -│ ├── task.TaskId.yaml -│ └── task.yaml +│ ├── job.JobId.yaml +│ └── job.yaml ├── root.yaml └── schemas ├── error.BadRequest.yaml ├── error.InternalServerError.yaml ├── error.NotFoundError.yaml ├── hello.HelloWorldResponse.yaml - ├── task.GetTaskResponse.yaml - ├── task.PostTaskRequest.yaml - ├── task.PostTaskResponse.yaml - └── task.TaskId.yaml + ├── job.GetJobResponse.yaml + ├── job.PostJobRequest.yaml + ├── job.PostJobResponse.yaml + └── job.JobId.yaml ``` ### 1.2 スキーマの命名規則 @@ -41,12 +41,12 @@ tree #### 例1.2 ```yaml -# schemas/task.GetTaskResponse.yaml -description: detail of task response +# schemas/job.GetJobResponse.yaml +description: detail of job response type: object properties: - task_id: - $ref: "task.TaskId.yaml" + job_id: + $ref: "job.JobId.yaml" code: {type: string, example: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;"} device: {type: string, example: "Kawasaki"} n_qubits: @@ -94,7 +94,7 @@ properties: optimization_swap_level: 1 } required: [ - taskId, code, device, skip_transpilation + jobId, code, device, skip_transpilation ] ``` diff --git a/backend/oas/provider/openapi.yaml b/backend/oas/provider/openapi.yaml index 77dce40..d2a0a99 100644 --- a/backend/oas/provider/openapi.yaml +++ b/backend/oas/provider/openapi.yaml @@ -5,7 +5,7 @@ info: contact: name: oqtopus-team email: oqtopus-team[at]googlegroups.com - description: OQTOPUS Cloud Provider API. This API is used to interact with the OQTOPUS Cloud service. The API provides endpoints to manage devices, tasks, and results. + description: OQTOPUS Cloud Provider API. This API is used to interact with the OQTOPUS Cloud service. The API provides endpoints to manage devices, jobs, and results. license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html @@ -13,17 +13,17 @@ servers: - url: http://localhost:8888 description: Local server url paths: - /internal/devices/{deviceId}: + /devices/{device_id}: patch: tags: - devices summary: Update data of selected device - description: Update data of selected device.
Modifiable device propeties are:

- status (all device types)
- number of pending tasks (all device types)
- calibrationData (QPU devices only) + description: Update data of selected device.
Modifiable device propeties are:

- status (all device types)
- number of pending jobs (all device types)
- calibrationData (QPU devices only) operationId: patchDeviceData security: [] parameters: - in: path - name: deviceId + name: device_id description: Device ID required: true schema: @@ -36,58 +36,24 @@ paths: schema: $ref: '#/components/schemas/devices.DeviceDataUpdate' examples: - status update (NOT_AVAILABLE): + status update (unavailable): value: command: DeviceStatusUpdate - status: NOT_AVAILABLE - restartAt: '2023-09-10T14:00:00Z' - status update (AVAILABLE): + status: unavailable + available_at: '2023-09-10T14:00:00Z' + status update (available): value: command: DeviceStatusUpdate - status: AVAILABLE - pending tasks update: + status: available + pending jobs update: value: - command: DevicePendingTasksUpdate - nPendingTasks: 6 + command: DevicePendingJobsUpdate + n_pending_jobs: 6 calibrationData update: value: command: DeviceCalibrationUpdate - calibrationData: - qubitConnectivity: - - (1,4) - - (4,5) - - (5,8) - t1: - '0': 55.51 - '1': 37.03 - '2': 57.13 - t2: - '0': 99.31 - '1': 111.03 - '2': 30.12 - roError: - '0': 0.0467 - '1': 0.18 - '2': 0.355 - gateError: - sx: - '0': 0.00692 - '1': 0.00296 - '2': 0.072 - measProb0As1: - '0': 0.00608 - '1': 0.012 - '2': 0.248 - measProb1As0: - '0': 0.0281 - '1': 0.386 - '2': 0.0811 - gateDuration: - sx: - '0': 29.3 - '1': 50.9 - '2': 45.4 - calibratedAt: '2023-09-10T14:00:00Z' + device_info: '{ ''calibration_data'': { ''qubit_connectivity'': [''(1,4)'', ''(4,5)'', ''(5,8)''], ''t1'': {''0'': 55.51, ''1'': 37.03, ''2'': 57.13}, ''t2'': {''0'': 99.31, ''1'': 111.03, ''2'': 30.12}, ''ro_error'': {''0'': 4.67e-2, ''1'': 1.8e-1, ''2'': 3.55e-1}, ''gate_error'': {''sx'': {''0'': 6.92e-3, ''1'': 2.96e-3, ''2'': 7.2e-2}}, ''meas_prob0_as1'': {''0'': 6.08e-3, ''1'': 1.2e-2, ''2'': 2.48e-1}, ''meas_prob1_as0'': {''0'': 2.81e-2, ''1'': 3.86e-1, ''2'': 8.11e-2}, ''gate_duration'': {''sx'': {''0'': 29.3, ''1'': 50.9, ''2'': 45.4}} }, }' + calibrated_at: '2023-09-10T14:00:00Z' responses: '200': description: Device's data updated @@ -121,17 +87,17 @@ paths: $ref: '#/components/schemas/error.InternalServerError' example: detail: Internal server error - /internal/tasks: + /jobs: get: tags: - - tasks - summary: Search tasks for a device - description: Search tasks for a device - operationId: gettasks + - jobs + summary: Search jobs for a device + description: Search jobs for a device + operationId: getjobs security: [] parameters: - in: query - name: deviceId + name: device_id required: true description: Device identifier schema: @@ -139,30 +105,30 @@ paths: example: Kawasaki - in: query name: status - description: Additional search parameter:
Search tasks with specified status only + description: Additional search parameter:
Search jobs with specified status only schema: - $ref: '#/components/schemas/tasks.InternalTaskStatus' + $ref: '#/components/schemas/jobs.InternalJobStatus' - in: query - name: maxResults - description: Additional search parameter:
Set max number of quantum tasks to return in single request + name: max_results + description: Additional search parameter:
Set max number of quantum jobs to return in single request schema: type: integer example: 1 - in: query name: timestamp - description: Additional search parameter:
Fetch tasks created after the specified timetsamp + description: Additional search parameter:
Fetch jobs created after the specified timetsamp schema: type: string example: '2022-12-15 15:54:46' responses: '200': - description: List of tasks for a device + description: List of jobs for a device content: application/json: schema: type: array items: - $ref: '#/components/schemas/tasks.TaskInfo' + $ref: '#/components/schemas/jobs.JobDef' '400': description: Bad Request content: @@ -179,28 +145,28 @@ paths: $ref: '#/components/schemas/error.InternalServerError' example: detail: Internal server error - /internal/tasks/{taskId}: + /jobs/{job_id}: get: - summary: Get a task by ID - description: Get a task by ID - operationId: getTask + summary: Get a job by ID + description: Get a job by ID + operationId: getJob security: [] tags: - - tasks + - jobs parameters: - in: path - name: taskId + name: job_id required: true - description: Task identifier + description: Job identifier schema: type: string responses: '200': - description: Return quantum task + description: Return quantum job content: application/json: schema: - $ref: '#/components/schemas/tasks.TaskInfo' + $ref: '#/components/schemas/jobs.JobDef' '400': description: Bad Request content: @@ -216,36 +182,36 @@ paths: schema: $ref: '#/components/schemas/error.NotFoundError' example: - detail: task not found + detail: job not found patch: - summary: Modify selected quantum task (update status). - description: Used by device to set task status to "RUNNING".
Other statuses are set by CloudAPI automatically when result is created - operationId: patchTask + summary: Modify selected quantum job (update status). + description: Used by device to set job status to "RUNNING".
Other statuses are set by CloudAPI automatically when result is created + operationId: patchJob security: [] tags: - - tasks + - jobs parameters: - in: path - name: taskId + name: job_id required: true - description: Task identifier + description: Job identifier schema: type: string requestBody: - description: 'New task status. ' + description: 'New job status. ' content: application/json: schema: - $ref: '#/components/schemas/tasks.TaskStatusUpdate' + $ref: '#/components/schemas/jobs.JobStatusUpdate' responses: '200': - description: task data updated + description: job data updated content: application/json: schema: - $ref: '#/components/schemas/tasks.TaskStatusUpdateResponse' + $ref: '#/components/schemas/jobs.JobStatusUpdateResponse' example: - message: task data updated + message: job data updated '400': description: Bad Request content: @@ -261,18 +227,18 @@ paths: schema: $ref: '#/components/schemas/error.NotFoundError' example: - detail: task not found - /internal/tasks/unfetched: + detail: job not found + /jobs/unfetched: get: - summary: Fetch tasks for device - description: 'Fetches tasks for execution/cancel

Operation is valid only for task with status: QUEUED or CANCELLING. After the operation task status is changed to appropriate FETCHED state (QUEUED_FETCHED or CANCELLING_FETCHED)' - operationId: getUnfetchedTasks + summary: Fetch jobs for device + description: 'Fetches jobs for execution/cancel

Operation is valid only for job with status: submitted or cancelling. After the operation job status is changed to appropriate ready state (submitted or cancelled)' + operationId: getUnfetchedJobs security: [] tags: - - tasks + - jobs parameters: - in: query - name: deviceId + name: device_id required: true description: Device identifier schema: @@ -281,22 +247,22 @@ paths: - in: query name: status required: true - description: Fetch tasks with specified status + description: Fetch jobs with specified status schema: - $ref: '#/components/schemas/tasks.InternalFetchableTaskStatus' + $ref: '#/components/schemas/jobs.InternalFetchableJobStatus' - in: query - name: maxResults - description: Additional search parameter:
Set max number of quantum tasks to return in single request + name: max_results + description: Additional search parameter:
Set max number of quantum jobs to return in single request schema: type: integer example: 1 responses: '200': - description: List of tasks for execution (all task data) / cancel (taskIds only) + description: List of jobs for execution (all job data) / cancel (jobIds only) content: application/json: schema: - $ref: '#/components/schemas/tasks.UnfetchedTasksResponse' + $ref: '#/components/schemas/jobs.UnfetchedJobsResponse' '400': description: Bad Request content: @@ -305,94 +271,6 @@ paths: $ref: '#/components/schemas/error.BadRequest' example: detail: Bad request malformed input data - /internal/results: - post: - summary: Submit a quantum task result - tags: - - results - description: Submit a quantum task result - operationId: postResult - security: [] - requestBody: - description: Result to be submitted - content: - application/json: - schema: - $ref: '#/components/schemas/results.ResultDef' - examples: - success sampling: - value: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - status: SUCCESS - result: - '11': 4980 - '00': 5020 - reason: null - transpiledCode: OPENQASM 3;include "stdgates.inc";qubit[2] _all_qubits;let q = _all_qubits[0:1];h q[0];cx q[0], q[1]; - success estimation: - value: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - status: SUCCESS - result: - - 1.5 - - 2.8 - reason: null - transpiledCode: OPENQASM 3;include "stdgates.inc";qubit[2] _all_qubits;let q = _all_qubits[0:1];h q[0];cx q[0], q[1]; - failure: - value: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - status: FAILURE - result: null - reason: Invalid device parameter in request - transpiledCode: null - cancel: - value: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - status: CANCELLED - result: null - reason: User cancelled - transpiledCode: null - responses: - '200': - description: Results submitted - content: - application/json: - schema: - $ref: '#/components/schemas/results.CreateResultResponse' - example: - message: Results submitted - '400': - description: Bad Request - content: - application/json: - schema: - $ref: '#/components/schemas/error.BadRequest' - example: - detail: Bad request malformed input data - '404': - description: Not Found - content: - application/json: - schema: - $ref: '#/components/schemas/error.NotFoundError' - example: - detail: TaskID not found - '409': - description: Result for taskId already exists - content: - application/json: - schema: - $ref: '#/components/schemas/error.ConflictError' - example: - detail: Result for taskId already exists - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/error.InternalServerError' - example: - detail: Internal server error components: schemas: devices.DeviceStatusUpdate: @@ -404,112 +282,32 @@ components: status: type: string enum: - - AVAILABLE - - NOT_AVAILABLE - restartAt: - description: Parameter mandatory and valid for status 'NOT_AVAILABLE' + - available + - unavailable + available_at: + description: Parameter mandatory and valid for status 'unavailable' type: string format: date-time example: '2023-09-10T14:00:00+09:00' - devices.DevicePendingTasksUpdate: + devices.DevicePendingJobsUpdate: type: object properties: command: type: string - example: DevicePendingTasksUpdate - nPendingTasks: + example: DevicePendingJobsUpdate + n_pending_jobs: type: integer - CalibrationData: - description: Calibration data available only for 'QPU' devices - type: object - properties: - qubitConnectivity: - type: array - items: - type: string - format: (number, number) - example: - - (1,4) - - (4,5) - - (5,8) - t1: - type: object - additionalProperties: - type: number - format: float - example: - '0': 55.51 - '1': 37.03 - '2': 57.13 - t2: - type: object - additionalProperties: - type: number - format: float - example: - '0': 99.31 - '1': 111.03 - '2': 30.12 - roError: - type: object - additionalProperties: - type: number - format: float - example: - '0': 0.0467 - '1': 0.18 - '2': 0.355 - gateError: - type: object - additionalProperties: - type: object - additionalProperties: - type: number - format: float - example: - sx: - '0': 0.00692 - '1': 0.00296 - '2': 0.072 - measProb0As1: - type: object - additionalProperties: - type: number - format: float - example: - '0': 0.00608 - '1': 0.012 - '2': 0.248 - measProb1As0: - type: object - additionalProperties: - type: number - format: float - example: - '0': 0.0281 - '1': 0.386 - '2': 0.0811 - gateDuration: - type: object - additionalProperties: - type: object - additionalProperties: - type: number - format: float - example: - sx: - '0': 29.3 - '1': 50.9 - '2': 45.4 devices.DeviceCalibrationUpdate: type: object properties: command: type: string example: DeviceCalibrationUpdate - calibrationData: - $ref: '#/components/schemas/CalibrationData' - calibratedAt: + device_info: + description: json format calibration_data and n_nodes etc + type: string + example: '{''n_nodes'': 512, ''calibration_data'': {''qubit_connectivity'': [''(1,4)'', ''(4,5)'', ''(5,8)''], ''t1'': {''0'': 55.51, ''1'': 37.03, ''2'': 57.13}}' + calibrated_at: description: Parameter mandatory and valid if calibrationData not null type: string format: date-time @@ -519,11 +317,11 @@ components: propertyName: command mapping: DeviceStatusUpdate: '#/components/schemas/devices.DeviceStatusUpdate' - DevicePendingTasksUpdate: '#/components/schemas/devices.DevicePendingTasksUpdate' + DevicePendingJobsUpdate: '#/components/schemas/devices.DevicePendingJobsUpdate' DeviceCalibrationUpdate: '#/components/schemas/devices.DeviceCalibrationUpdate' oneOf: - $ref: '#/components/schemas/devices.DeviceStatusUpdate' - - $ref: '#/components/schemas/devices.DevicePendingTasksUpdate' + - $ref: '#/components/schemas/devices.DevicePendingJobsUpdate' - $ref: '#/components/schemas/devices.DeviceCalibrationUpdate' devices.DeviceDataUpdateResponse: type: object @@ -555,293 +353,117 @@ components: type: string required: - detail - tasks.InternalTaskStatus: + jobs.InternalJobStatus: type: string enum: - - QUEUED - - QUEUED_FETCHED - - RUNNING - - COMPLETED - - FAILED - - CANCELLING - - CANCELLING_FETCHED - - CANCELLED - example: QUEUED - tasks.TaskId: + - submitted + - ready + - running + - success + - failed + - cancelled + example: submitted + jobs.JobId: type: string format: uuid example: 7af020f6-2e38-4d70-8cf0-4349650ea08c - tasks.SamplingAction: + jobs.JobInfo: + type: string + example: '{''code'': ''{type: string, example: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;"}'', ''Operator'': ''X 0 Y 1 Z 5 I 2'', ''result'': {''00'': 5020, ''11'': 4980}, ''transpiled_code'': '''', ''reason'': ''''}' + jobs.TranspilerInfo: + type: string + example: '{''qubit_allocation'': {''0'': 12, ''1'': 16}, ''skip_transpilation'': false, ''seed_transpilation'': 873}' + jobs.SimulatorInfo: + type: string + example: '{''n_qubits'': 5, ''n_nodes'': 12, ''n_per_node'': 2, ''seed_simulation'': 39058567, ''simulation_opt'': {''optimization_method'': ''light'', ''optimization_block_size'': 1, ''optimization_swap_level'': 1}}' + jobs.MitigationInfo: + type: string + example: '{''ro_error_mitigation'': ''pseudo_inverse''}' + jobs.JobDef: type: object properties: + job_id: + $ref: '#/components/schemas/jobs.JobId' name: type: string - pattern: sampling - example: sampling - nShots: - type: integer - minimum: 1 - maximum: 10000000 - example: '1000' - required: - - name - - nShots - tasks.SingleOperator: - type: array - items: - anyOf: - - type: string - description: Pauli string - example: X 0 Y 1 Z 5 I 2 - - type: array - description: Real and imaginary components of complex coef value - items: - type: number - minItems: 2 - maxItems: 2 - example: - - 1.5 - - 2.8 - minItems: 2 - maxItems: 2 - tasks.Operator: - type: array - items: - $ref: '#/components/schemas/tasks.SingleOperator' - example: - - - X 0 X 1 - - - 1.5 - - 2.8 - - - Y 0 Z 1 - - - 1.2 - - -2.e-8 - tasks.EstimationAction: - type: object - properties: - name: + example: Bell State Sampling + description: type: string - pattern: estimation - example: estimation - method: + example: Bell State Sampling Example + device_id: type: string - enum: - - state_vector - - sampling - example: sampling - description: state_vector method valid only for 'simulator' devices - nShots: + example: Kawasaki + shots: type: integer minimum: 1 maximum: 10000000 example: '1000' - description: Parameter valid only for sampling method - operator: - $ref: '#/components/schemas/tasks.Operator' - required: - - name - - method - - operator - tasks.Action: - type: object - oneOf: - - $ref: '#/components/schemas/tasks.SamplingAction' - - $ref: '#/components/schemas/tasks.EstimationAction' - tasks.TaskInfo: - type: object - properties: - taskId: - $ref: '#/components/schemas/tasks.TaskId' - code: - type: string - example: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; - device: + job_type: type: string - example: Kawasaki - nQubits: - type: integer - example: null - nNodes: - description: Parameter valid only for 'simulator' devices - type: integer - example: 12 - action: - $ref: '#/components/schemas/tasks.Action' - qubitAllocation: - description: Parameter valid only for QPU devices - type: object - additionalProperties: - type: integer - example: - '0': 12 - '1': 16 - skipTranspilation: - type: boolean - example: false - seedTranspilation: - description: Parameter valid only if skipTranspilation is false - type: integer - example: 873 - seedSimulation: - description: Parameter valid only for 'simulator' devices - type: integer - example: 39058567 - roErrorMitigation: - description: Parameter valid only for QPU devices - type: string - enum: - - none - - pseudo_inverse - - least_square - example: pseudo_inverse - nPerNode: - description: Parameter valid only for simulator devices - type: integer - minimum: 1 - example: 5 - simulationOpt: - description: Parameter valid only for simulator devices - type: object - example: - optimizationMethod: light - optimizationBlockSize: 1 - optimizationSwapLevel: 1 + example: '''sampling'' or ''estimation'', ''sse''' + job_info: + $ref: '#/components/schemas/jobs.JobInfo' + transpiler_info: + $ref: '#/components/schemas/jobs.TranspilerInfo' + simulator_info: + $ref: '#/components/schemas/jobs.SimulatorInfo' + mitigation_info: + $ref: '#/components/schemas/jobs.MitigationInfo' status: - $ref: '#/components/schemas/tasks.InternalTaskStatus' - createdAt: + $ref: '#/components/schemas/jobs.InternalJobStatus' + created_at: + type: string + format: date-time + example: '2022-10-19T11:45:34+09:00' + updated_at: type: string format: date-time example: '2022-10-19T11:45:34+09:00' required: - - taskId - - code - - device - - action - - skipTranspilation + - device_id + - shots - status - - createdAt + - created_at example: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - code: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; - device: Kawasaki - nQubits: null - nNodes: 12 - action: - name: sampling - nShots: 1000 - qubitAllocation: null - skipTranspilation: false - seedTranspilation: 873 - seedSimulation: 39058567 - roErrorMitigation: null - nPerNode: 2 - simulationOpt: - optimizationMethod: light - optimizationBlockSize: 1 - optimizationSwapLevel: 1 - status: QUEUED_FETCHED - createdAt: '2022-10-19T11:45:34+09:00' - tasks.TaskStatusUpdate: + job_id: 7af020f6-2e38-4d70-8cf0-4349650ea08c + name: Bell State Sampling + description: Bell State Sampling Example + device_id: Kawasaki + job_info: '{''code'': ''{type: string, example: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;"}'', ''operator'': ''X 0 Y 1 Z 5 I 2''}' + transpiler_info: '{''qubit_allocation'': {''0'': 12, ''1'': 16}, ''skip_transpilation'': false, ''seed_transpilation'': 873}' + simulator_info: '{''n_qubits'': 5, ''n_nodes'': 12, ''n_per_node'': 2, ''seed_simulation'': 39058567, ''simulation_opt'': {''optimization_method'': ''light'', ''optimization_block_size'': 1, ''optimization_swap_level'': 1}}' + mitigation_info: '{''ro_error_mitigation'': ''pseudo_inverse''}' + job_type: sampling + shots: 1000 + status: submitted + created_at: '2022-10-19T11:45:34+09:00' + updated_at: '2022-10-19T11:45:34+09:00' + jobs.JobStatusUpdate: type: object properties: status: type: string enum: - - RUNNING - example: RUNNING + - running + example: running required: - status - tasks.TaskStatusUpdateResponse: + jobs.JobStatusUpdateResponse: type: object properties: message: type: string required: - message - tasks.InternalFetchableTaskStatus: + jobs.InternalFetchableJobStatus: type: string enum: - - QUEUED - - CANCELLING - example: QUEUED - tasks.UnfetchedTasksResponse: + - submitted + - cancelling + example: submitted + jobs.UnfetchedJobsResponse: type: array items: oneOf: - - $ref: '#/components/schemas/tasks.TaskInfo' - - $ref: '#/components/schemas/tasks.TaskId' - results.ResultStatus: - type: string - enum: - - SUCCESS - - FAILURE - - CANCELLED - default: SUCCESS - example: SUCCESS - results.SamplingResult: - type: object - additionalProperties: - type: integer - minProperties: 2 - example: - '11': 4980 - '00': 5020 - results.EstimationResult: - type: array - items: - type: number - minItems: 2 - maxItems: 2 - example: - - 1.5 - - 2.8 - results.Result: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/results.SamplingResult' - - $ref: '#/components/schemas/results.EstimationResult' - results.ResultDef: - type: object - properties: - taskId: - $ref: '#/components/schemas/tasks.TaskId' - status: - $ref: '#/components/schemas/results.ResultStatus' - result: - $ref: '#/components/schemas/results.Result' - reason: - type: string - nullable: true - transpiledCode: - type: string - nullable: true - qubitAllocation: - description: Parameter valid only for QPU devices - type: object - additionalProperties: - type: integer - nullable: true - example: - '0': 0 - '1': 4 - required: - - taskId - - status - - result - - reason - - transpiledCode - results.CreateResultResponse: - type: object - properties: - message: - type: string - required: - - message - example: - message: Results submitted - error.ConflictError: - type: object - properties: - detail: - type: string - required: - - detail + - $ref: '#/components/schemas/jobs.JobDef' + - $ref: '#/components/schemas/jobs.JobId' diff --git a/backend/oas/provider/paths/devices.yaml b/backend/oas/provider/paths/devices.yaml index b532cde..8d0e509 100644 --- a/backend/oas/provider/paths/devices.yaml +++ b/backend/oas/provider/paths/devices.yaml @@ -3,12 +3,12 @@ devices.deviceId: tags: - devices summary: "Update data of selected device" - description: "Update data of selected device.
Modifiable device propeties are:

- status (all device types)
- number of pending tasks (all device types)
- calibrationData (QPU devices only)" + description: "Update data of selected device.
Modifiable device propeties are:

- status (all device types)
- number of pending jobs (all device types)
- calibrationData (QPU devices only)" operationId: patchDeviceData security: [] parameters: - in: path - name: deviceId + name: device_id description: "Device ID" required: true schema: @@ -21,36 +21,38 @@ devices.deviceId: schema: $ref: "../schemas/devices.yaml#/devices.DeviceDataUpdate" examples: - status update (NOT_AVAILABLE): + status update (unavailable): value: { "command": "DeviceStatusUpdate", - "status": "NOT_AVAILABLE", - "restartAt": "2023-09-10T14:00:00Z" + "status": "unavailable", + "available_at": "2023-09-10T14:00:00Z" } - status update (AVAILABLE): + status update (available): value: { "command": "DeviceStatusUpdate", - "status": "AVAILABLE" + "status": "available" } - pending tasks update: + pending jobs update: value: { - "command": "DevicePendingTasksUpdate", - "nPendingTasks": 6 + "command": "DevicePendingJobsUpdate", + "n_pending_jobs": 6 } calibrationData update: value: { "command": "DeviceCalibrationUpdate", - "calibrationData": { - "qubitConnectivity": ["(1,4)", "(4,5)", "(5,8)"], - "t1": {"0": 55.51, "1": 37.03, "2": 57.13}, - "t2": {"0": 99.31, "1": 111.03, "2": 30.12}, - "roError": {"0": 4.67e-2, "1": 1.8e-1, "2": 3.55e-1}, - "gateError": {"sx": {"0": 6.92e-3, "1": 2.96e-3, "2": 7.2e-2}}, - "measProb0As1": {"0": 6.08e-3, "1": 1.2e-2, "2": 2.48e-1}, - "measProb1As0": {"0": 2.81e-2, "1": 3.86e-1, "2": 8.11e-2}, - "gateDuration": {"sx": {"0": 29.3, "1": 50.9, "2": 45.4}} - }, - calibratedAt: "2023-09-10T14:00:00Z" + "device_info": "{ + 'calibration_data': { + 'qubit_connectivity': ['(1,4)', '(4,5)', '(5,8)'], + 't1': {'0': 55.51, '1': 37.03, '2': 57.13}, + 't2': {'0': 99.31, '1': 111.03, '2': 30.12}, + 'ro_error': {'0': 4.67e-2, '1': 1.8e-1, '2': 3.55e-1}, + 'gate_error': {'sx': {'0': 6.92e-3, '1': 2.96e-3, '2': 7.2e-2}}, + 'meas_prob0_as1': {'0': 6.08e-3, '1': 1.2e-2, '2': 2.48e-1}, + 'meas_prob1_as0': {'0': 2.81e-2, '1': 3.86e-1, '2': 8.11e-2}, + 'gate_duration': {'sx': {'0': 29.3, '1': 50.9, '2': 45.4}} + }, + }", + calibrated_at: "2023-09-10T14:00:00Z" } responses: '200': diff --git a/backend/oas/provider/paths/tasks.yaml b/backend/oas/provider/paths/jobs.yaml similarity index 61% rename from backend/oas/provider/paths/tasks.yaml rename to backend/oas/provider/paths/jobs.yaml index d21d47e..a51603d 100644 --- a/backend/oas/provider/paths/tasks.yaml +++ b/backend/oas/provider/paths/jobs.yaml @@ -1,39 +1,39 @@ -tasks: +jobs: get: tags: - - tasks - summary: Search tasks for a device - description: Search tasks for a device - operationId: gettasks + - jobs + summary: Search jobs for a device + description: Search jobs for a device + operationId: getjobs security: [] parameters: - in: query - name: deviceId + name: device_id required: true description: "Device identifier" schema: {type: string, example: "Kawasaki"} - in: query name: status - description: "Additional search parameter:
Search tasks with specified status only" + description: "Additional search parameter:
Search jobs with specified status only" schema: - $ref: "../schemas/tasks.yaml#/tasks.InternalTaskStatus" + $ref: "../schemas/jobs.yaml#/jobs.InternalJobStatus" - in: query - name: maxResults - description: "Additional search parameter:
Set max number of quantum tasks to return in single request" + name: max_results + description: "Additional search parameter:
Set max number of quantum jobs to return in single request" schema: {type: integer, example: 1} - in: query name: timestamp - description: "Additional search parameter:
Fetch tasks created after the specified timetsamp" + description: "Additional search parameter:
Fetch jobs created after the specified timetsamp" schema: {type: string, example: '2022-12-15 15:54:46'} responses: "200": - description: "List of tasks for a device" + description: "List of jobs for a device" content: application/json: schema: type: array items: - $ref: "../schemas/tasks.yaml#/tasks.TaskInfo" + $ref: "../schemas/jobs.yaml#/jobs.JobDef" '400': description: Bad Request content: @@ -51,27 +51,27 @@ tasks: example: detail: Internal server error -tasks.taskId: +jobs.jobId: get: - summary: Get a task by ID - description: Get a task by ID - operationId: getTask + summary: Get a job by ID + description: Get a job by ID + operationId: getJob security: [] tags: - - tasks + - jobs parameters: - in: path - name: taskId + name: job_id required: true - description: "Task identifier" + description: "Job identifier" schema: {type: string} responses: "200": - description: "Return quantum task" + description: "Return quantum job" content: application/json: schema: - $ref: "../schemas/tasks.yaml#/tasks.TaskInfo" + $ref: "../schemas/jobs.yaml#/jobs.JobDef" '400': description: Bad Request content: @@ -87,35 +87,35 @@ tasks.taskId: schema: $ref: '../schemas/error.yaml#/error.NotFoundError' example: - detail: task not found + detail: job not found patch: - summary: "Modify selected quantum task (update status)." - description: "Used by device to set task status to \"RUNNING\".
Other statuses are set by CloudAPI automatically when result is created" - operationId: patchTask + summary: "Modify selected quantum job (update status)." + description: "Used by device to set job status to \"RUNNING\".
Other statuses are set by CloudAPI automatically when result is created" + operationId: patchJob security: [] tags: - - tasks + - jobs parameters: - in: path - name: taskId + name: job_id required: true - description: "Task identifier" + description: "Job identifier" schema: {type: string} requestBody: - description: "New task status. " + description: "New job status. " content: application/json: schema: - $ref: "../schemas/tasks.yaml#/tasks.TaskStatusUpdate" + $ref: "../schemas/jobs.yaml#/jobs.JobStatusUpdate" responses: '200': - description: task data updated + description: job data updated content: application/json: schema: - $ref: '../schemas/tasks.yaml#/tasks.TaskStatusUpdateResponse' + $ref: '../schemas/jobs.yaml#/jobs.JobStatusUpdateResponse' example: - message: task data updated + message: job data updated "400": description: Bad Request content: @@ -131,40 +131,40 @@ tasks.taskId: schema: $ref: '../schemas/error.yaml#/error.NotFoundError' example: - detail: task not found + detail: job not found -tasks.unfetched: +jobs.unfetched: get: - summary: "Fetch tasks for device" - description: "Fetches tasks for execution/cancel

Operation is valid only for task with status: QUEUED or CANCELLING. After the operation task status is changed to appropriate FETCHED state (QUEUED_FETCHED or CANCELLING_FETCHED)" - operationId: getUnfetchedTasks + summary: "Fetch jobs for device" + description: "Fetches jobs for execution/cancel

Operation is valid only for job with status: submitted or cancelling. After the operation job status is changed to appropriate ready state (submitted or cancelled)" + operationId: getUnfetchedJobs security: [] tags: - - tasks + - jobs parameters: - in: query - name: deviceId + name: device_id required: true description: "Device identifier" schema: {type: string, example: "Kawasaki"} - in: query name: status required: true - description: "Fetch tasks with specified status" + description: "Fetch jobs with specified status" schema: - $ref: "../schemas/tasks.yaml#/tasks.InternalFetchableTaskStatus" + $ref: "../schemas/jobs.yaml#/jobs.InternalFetchableJobStatus" - in: query - name: maxResults - description: "Additional search parameter:
Set max number of quantum tasks to return in single request" + name: max_results + description: "Additional search parameter:
Set max number of quantum jobs to return in single request" schema: {type: integer, example: 1} responses: "200": - description: "List of tasks for execution (all task data) / cancel (taskIds only)" + description: "List of jobs for execution (all job data) / cancel (jobIds only)" content: application/json: schema: - $ref: "../schemas/tasks.yaml#/tasks.UnfetchedTasksResponse" + $ref: "../schemas/jobs.yaml#/jobs.UnfetchedJobsResponse" "400": description: Bad Request content: diff --git a/backend/oas/provider/paths/results.yaml b/backend/oas/provider/paths/results.yaml deleted file mode 100644 index cc50170..0000000 --- a/backend/oas/provider/paths/results.yaml +++ /dev/null @@ -1,97 +0,0 @@ -results: - post: - summary: Submit a quantum task result - tags: - - results - description: Submit a quantum task result - operationId: postResult - security: [] - requestBody: - description: "Result to be submitted" - content: - application/json: - schema: - $ref: "../schemas/results.yaml#/results.ResultDef" - examples: - success sampling: - value: - { - "taskId": "7af020f6-2e38-4d70-8cf0-4349650ea08c", - "status": "SUCCESS", - "result": - { - "00": 5020, - "11": 4980 - }, - "reason": null, - "transpiledCode": "OPENQASM 3;include \"stdgates.inc\";qubit[2] _all_qubits;let q = _all_qubits[0:1];h q[0];cx q[0], q[1];" - } - success estimation: - value: - { - "taskId": "7af020f6-2e38-4d70-8cf0-4349650ea08c", - "status": "SUCCESS", - "result": [1.5, 2.8], - "reason": null, - "transpiledCode": "OPENQASM 3;include \"stdgates.inc\";qubit[2] _all_qubits;let q = _all_qubits[0:1];h q[0];cx q[0], q[1];" - } - failure: - value: - { - "taskId": "7af020f6-2e38-4d70-8cf0-4349650ea08c", - "status": "FAILURE", - "result": null, - "reason": "Invalid device parameter in request", - "transpiledCode": null - } - cancel: - value: - { - "taskId": "7af020f6-2e38-4d70-8cf0-4349650ea08c", - "status": "CANCELLED", - "result": null, - "reason": "User cancelled", - "transpiledCode": null - } - - responses: - '200': - description: Results submitted - content: - application/json: - schema: - $ref: '../schemas/results.yaml#/results.CreateResultResponse' - example: - message: Results submitted - '400': - description: Bad Request - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.BadRequest' - example: - detail: Bad request malformed input data - '404': - description: Not Found - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.NotFoundError' - example: - detail: TaskID not found - "409": - description: "Result for taskId already exists" - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.ConflictError' - example: - detail: Result for taskId already exists - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.InternalServerError' - example: - detail: Internal server error diff --git a/backend/oas/provider/root.yaml b/backend/oas/provider/root.yaml index 6c0c604..3c5c117 100644 --- a/backend/oas/provider/root.yaml +++ b/backend/oas/provider/root.yaml @@ -5,7 +5,7 @@ info: contact: name: oqtopus-team email: oqtopus-team[at]googlegroups.com - description: OQTOPUS Cloud Provider API. This API is used to interact with the OQTOPUS Cloud service. The API provides endpoints to manage devices, tasks, and results. + description: OQTOPUS Cloud Provider API. This API is used to interact with the OQTOPUS Cloud service. The API provides endpoints to manage devices, jobs, and results. license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html @@ -13,13 +13,11 @@ servers: - url: http://localhost:8888 description: Local server url paths: - /internal/devices/{deviceId}: + /devices/{device_id}: $ref: ./paths/devices.yaml#/devices.deviceId - /internal/tasks: - $ref: ./paths/tasks.yaml#/tasks - /internal/tasks/{taskId}: - $ref: ./paths/tasks.yaml#/tasks.taskId - /internal/tasks/unfetched: - $ref: ./paths/tasks.yaml#/tasks.unfetched - /internal/results: - $ref: ./paths/results.yaml#/results + /jobs: + $ref: ./paths/jobs.yaml#/jobs + /jobs/{job_id}: + $ref: ./paths/jobs.yaml#/jobs.jobId + /jobs/unfetched: + $ref: ./paths/jobs.yaml#/jobs.unfetched diff --git a/backend/oas/provider/schemas/devices.yaml b/backend/oas/provider/schemas/devices.yaml index 2e97a85..1bf70f5 100644 --- a/backend/oas/provider/schemas/devices.yaml +++ b/backend/oas/provider/schemas/devices.yaml @@ -3,11 +3,11 @@ devices.DeviceDataUpdate: propertyName: command mapping: DeviceStatusUpdate: '#/devices.DeviceStatusUpdate' - DevicePendingTasksUpdate: '#/devices.DevicePendingTasksUpdate' + DevicePendingJobsUpdate: '#/devices.DevicePendingJobsUpdate' DeviceCalibrationUpdate: '#/devices.DeviceCalibrationUpdate' oneOf: - $ref: '#/devices.DeviceStatusUpdate' - - $ref: '#/devices.DevicePendingTasksUpdate' + - $ref: '#/devices.DevicePendingJobsUpdate' - $ref: '#/devices.DeviceCalibrationUpdate' @@ -29,20 +29,20 @@ devices.DeviceStatusUpdate: example: DeviceStatusUpdate status: type: string - enum: ["AVAILABLE", "NOT_AVAILABLE"] - restartAt: - description: "Parameter mandatory and valid for status 'NOT_AVAILABLE'" + enum: ["available", "unavailable"] + available_at: + description: "Parameter mandatory and valid for status 'unavailable'" type: string format: date-time example: "2023-09-10T14:00:00+09:00" -devices.DevicePendingTasksUpdate: +devices.DevicePendingJobsUpdate: type: object properties: command: type: string - example: DevicePendingTasksUpdate - nPendingTasks: + example: DevicePendingJobsUpdate + n_pending_jobs: type: integer devices.DeviceCalibrationUpdate: @@ -51,77 +51,12 @@ devices.DeviceCalibrationUpdate: command: type: string example: DeviceCalibrationUpdate - calibrationData: - $ref: "#/components/schemas/CalibrationData" - calibratedAt: + device_info: + description: "json format calibration_data and n_nodes etc" + type: string + example: "{'n_nodes': 512, 'calibration_data': {'qubit_connectivity': ['(1,4)', '(4,5)', '(5,8)'], 't1': {'0': 55.51, '1': 37.03, '2': 57.13}}" + calibrated_at: description: "Parameter mandatory and valid if calibrationData not null" type: string format: date-time example: "2023-09-10T14:00:00+09:00" - -components: - schemas: - CalibrationData: - description: "Calibration data available only for 'QPU' devices" - type: object - properties: - qubitConnectivity: - type: array - items: - type: string - format: "(number, number)" - example: - ["(1,4)", "(4,5)", "(5,8)"] - t1: - type: object - additionalProperties: - type: number - format: float - example: - {"0": 55.51, "1": 37.03, "2": 57.13} - t2: - type: object - additionalProperties: - type: number - format: float - example: - {"0": 99.31, "1": 111.03, "2": 30.12} - roError: - type: object - additionalProperties: - type: number - format: float - example: - {"0": 4.67e-2, "1": 1.8e-1, "2": 3.55e-1} - gateError: - type: object - additionalProperties: - type: object - additionalProperties: - type: number - format: float - example: - {"sx": {"0": 6.92e-3, "1": 2.96e-3, "2": 7.2e-2}} - measProb0As1: - type: object - additionalProperties: - type: number - format: float - example: - {"0": 6.08e-3, "1": 1.2e-2, "2": 2.48e-1} - measProb1As0: - type: object - additionalProperties: - type: number - format: float - example: - {"0": 2.81e-2, "1": 3.86e-1, "2": 8.11e-2} - gateDuration: - type: object - additionalProperties: - type: object - additionalProperties: - type: number - format: float - example: - {"sx": {"0": 29.3, "1": 50.9, "2": 45.4}} diff --git a/backend/oas/provider/schemas/jobs.yaml b/backend/oas/provider/schemas/jobs.yaml new file mode 100644 index 0000000..12be5d6 --- /dev/null +++ b/backend/oas/provider/schemas/jobs.yaml @@ -0,0 +1,117 @@ +jobs.JobId: + type: string + format: uuid + example: "7af020f6-2e38-4d70-8cf0-4349650ea08c" + +jobs.InternalJobStatus: + type: string + enum: ["submitted", "ready", "running", "success", "failed", "cancelled"] + example: "submitted" + +jobs.JobInfo: + type: string + example: "{'code': '{type: string, example: \"OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;\"}', 'Operator': 'X 0 Y 1 Z 5 I 2', 'result': {'00': 5020, '11': 4980}, 'transpiled_code': '', 'reason': ''}" + +jobs.TranspilerInfo: + type: string + example: "{'qubit_allocation': {'0': 12, '1': 16}, 'skip_transpilation': false, 'seed_transpilation': 873}" + +jobs.SimulatorInfo: + type: string + example: "{'n_qubits': 5, 'n_nodes': 12, 'n_per_node': 2, 'seed_simulation': 39058567, 'simulation_opt': {'optimization_method': 'light', 'optimization_block_size': 1, 'optimization_swap_level': 1}}" + +jobs.MitigationInfo: + type: string + example: "{'ro_error_mitigation': 'pseudo_inverse'}" + +jobs.JobDef: + type: object + properties: + job_id: + $ref: "#/jobs.JobId" + name: + type: string + example: "Bell State Sampling" + description: + type: string + example: "Bell State Sampling Example" + device_id: + type: string + example: "Kawasaki" + shots: + type: integer + minimum: 1 + maximum: 1e7 + example: "1000" + job_type: + type: string + example: "'sampling' or 'estimation', 'sse'" + job_info: + $ref: "#/jobs.JobInfo" + transpiler_info: + $ref: "#/jobs.TranspilerInfo" + simulator_info: + $ref: "#/jobs.SimulatorInfo" + mitigation_info: + $ref: "#/jobs.MitigationInfo" + status: + $ref: "#/jobs.InternalJobStatus" + created_at: + type: string + format: date-time + example: "2022-10-19T11:45:34+09:00" + updated_at: + type: string + format: date-time + example: "2022-10-19T11:45:34+09:00" + required: [ + device_id, shots, status, created_at + ] + example: + { + job_id: "7af020f6-2e38-4d70-8cf0-4349650ea08c", + name: "Bell State Sampling", + description: "Bell State Sampling Example", + device_id: "Kawasaki", + job_info: "{'code': '{type: string, example: \"OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;\"}', 'operator': 'X 0 Y 1 Z 5 I 2'}", + transpiler_info: "{'qubit_allocation': {'0': 12, '1': 16}, 'skip_transpilation': false, 'seed_transpilation': 873}", + simulator_info: "{'n_qubits': 5, 'n_nodes': 12, 'n_per_node': 2, 'seed_simulation': 39058567, 'simulation_opt': {'optimization_method': 'light', 'optimization_block_size': 1, 'optimization_swap_level': 1}}", + mitigation_info: "{'ro_error_mitigation': 'pseudo_inverse'}", + job_type: "sampling", + shots: 1000, + status: "submitted", + created_at: "2022-10-19T11:45:34+09:00", + updated_at: "2022-10-19T11:45:34+09:00" + } + +jobs.JobStatusUpdate: + type: object + properties: + status: + type: string + enum: ["running"] + example: "running" + required: [ + status + ] + +jobs.JobStatusUpdateResponse: + type: object + properties: + message: + type: string + required: + - message + +jobs.UnfetchedJobsResponse: + type: array + items: + oneOf: + - $ref: '#/jobs.JobDef' + - $ref: '#/jobs.JobId' + +jobs.InternalFetchableJobStatus: + type: string + enum: ["submitted", "cancelling"] + example: "submitted" + diff --git a/backend/oas/provider/schemas/results.yaml b/backend/oas/provider/schemas/results.yaml deleted file mode 100644 index 1fdf33c..0000000 --- a/backend/oas/provider/schemas/results.yaml +++ /dev/null @@ -1,66 +0,0 @@ -results.ResultDef: - type: object - properties: - taskId: - $ref: "tasks.yaml#/tasks.TaskId" - status: - $ref: "#/results.ResultStatus" - result: - $ref: "#/results.Result" - reason: - type: string - nullable: true - transpiledCode: - type: string - nullable: true - qubitAllocation: - description: "Parameter valid only for QPU devices" - type: object - additionalProperties: - type: integer - nullable: true - example: - "0": 0 - "1": 4 - required: [ - taskId, status, result, reason, transpiledCode - ] - -results.ResultStatus: - type: string - enum: ["SUCCESS", "FAILURE", "CANCELLED"] - default: "SUCCESS" - example: "SUCCESS" - -results.Result: - oneOf: - - type: "null" - - $ref: "#/results.SamplingResult" - - $ref: "#/results.EstimationResult" - -results.SamplingResult: - type: object - additionalProperties: - type: integer - minProperties: 2 - example: - "11": 4980 - "00": 5020 - -results.EstimationResult: - type: array - items: - type: number - minItems: 2 - maxItems: 2 - example: [1.5, 2.8] - - -results.CreateResultResponse: - type: object - properties: - message: - type: string - required: [message] - example: - message: Results submitted diff --git a/backend/oas/provider/schemas/tasks.yaml b/backend/oas/provider/schemas/tasks.yaml deleted file mode 100644 index 35b2784..0000000 --- a/backend/oas/provider/schemas/tasks.yaml +++ /dev/null @@ -1,199 +0,0 @@ -tasks.TaskId: - type: string - format: uuid - example: "7af020f6-2e38-4d70-8cf0-4349650ea08c" - -tasks.InternalTaskStatus: - type: string - enum: ["QUEUED", "QUEUED_FETCHED", "RUNNING", "COMPLETED", "FAILED", "CANCELLING", "CANCELLING_FETCHED", "CANCELLED"] - example: "QUEUED" - -tasks.Action: - type: object - oneOf: - - $ref: "#/tasks.SamplingAction" - - $ref: "#/tasks.EstimationAction" - -tasks.SamplingAction: - type: object - properties: - name: - type: string - pattern: "sampling" - example: "sampling" - nShots: - type: integer - minimum: 1 - maximum: 1e7 - example: "1000" - required: [ - name, nShots - ] - -tasks.EstimationAction: - type: object - properties: - name: - type: string - pattern: "estimation" - example: "estimation" - method: - type: string - enum: ["state_vector", "sampling"] - example: "sampling" - description: "state_vector method valid only for 'simulator' devices" - nShots: - type: integer - minimum: 1 - maximum: 1e7 - example: "1000" - description: "Parameter valid only for sampling method" - operator: - $ref: "#/tasks.Operator" - required: [ - name, method, operator - ] - -tasks.Operator: - type: array - items: - $ref: "#/tasks.SingleOperator" - example: - [ - ["X 0 X 1", [1.5, 2.8]], - ["Y 0 Z 1", [1.2, -2e-8]], - ] - -tasks.SingleOperator: - type: array - items: - anyOf: - - type: string - description: "Pauli string" - example: "X 0 Y 1 Z 5 I 2" - - type: array - description: "Real and imaginary components of complex coef value" - items: - type: number - minItems: 2 - maxItems: 2 - example: [1.5, 2.8] - minItems: 2 - maxItems: 2 - -tasks.TaskInfo: - type: object - properties: - taskId: - $ref: "#/tasks.TaskId" - code: {type: string, example: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;"} - device: {type: string, example: "Kawasaki"} - nQubits: - type: integer - example: null - nNodes: - description: "Parameter valid only for 'simulator' devices" - type: integer - example: 12 - action: - $ref: "#/tasks.Action" - qubitAllocation: - description: "Parameter valid only for QPU devices" - type: object - additionalProperties: - type: integer - example: - "0": 12 - "1": 16 - skipTranspilation: - type: boolean - example: false - seedTranspilation: - description: "Parameter valid only if skipTranspilation is false" - type: integer - example: 873 - seedSimulation: - description: "Parameter valid only for 'simulator' devices" - type: integer - example: 39058567 - roErrorMitigation: - description: "Parameter valid only for QPU devices" - type: string - enum: ["none", "pseudo_inverse", "least_square"] - example: "pseudo_inverse" - nPerNode: - description: "Parameter valid only for simulator devices" - type: integer - minimum: 1 - example: 5 - simulationOpt: - description: "Parameter valid only for simulator devices" - type: object - example: { - optimizationMethod: "light", - optimizationBlockSize: 1, - optimizationSwapLevel: 1 - } - status: - $ref: "#/tasks.InternalTaskStatus" - createdAt: - type: string - format: date-time - example: "2022-10-19T11:45:34+09:00" - required: [ - taskId, code, device, action, skipTranspilation, status, createdAt - ] - example: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - code: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; - device: Kawasaki - nQubits: null - nNodes: 12 - action: - name: sampling - nShots: 1000 - qubitAllocation: null - skipTranspilation: false - seedTranspilation: 873 - seedSimulation: 39058567 - roErrorMitigation: null - nPerNode: 2 - simulationOpt: { - optimizationMethod: "light", - optimizationBlockSize: 1, - optimizationSwapLevel: 1 - } - status: QUEUED_FETCHED - createdAt: "2022-10-19T11:45:34+09:00" - -tasks.TaskStatusUpdate: - type: object - properties: - status: - type: string - enum: ["RUNNING"] - example: "RUNNING" - required: [ - status - ] - -tasks.TaskStatusUpdateResponse: - type: object - properties: - message: - type: string - required: - - message - -tasks.UnfetchedTasksResponse: - type: array - items: - oneOf: - - $ref: '#/tasks.TaskInfo' - - $ref: '#/tasks.TaskId' - -tasks.InternalFetchableTaskStatus: - type: string - enum: ["QUEUED", "CANCELLING"] - example: "QUEUED" - diff --git a/backend/oas/user/openapi.yaml b/backend/oas/user/openapi.yaml index 062ea79..0b8c5dd 100644 --- a/backend/oas/user/openapi.yaml +++ b/backend/oas/user/openapi.yaml @@ -5,7 +5,7 @@ info: contact: name: oqtopus-team email: oqtopus-team[at]googlegroups.com - description: OQTOPUS Cloud User API. This API is used to interact with the OQTOPUS Cloud service. The API provides endpoints to manage devices, tasks, and results. + description: OQTOPUS Cloud User API. This API is used to interact with the OQTOPUS Cloud service. The API provides endpoints to manage devices, jobs, and results. license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html @@ -45,7 +45,7 @@ paths: application/json: schema: $ref: '#/components/schemas/error.InternalServerError' - /devices/{deviceId}: + /devices/{device_id}: get: tags: - device @@ -55,7 +55,7 @@ paths: security: - BearerAuth: [] parameters: - - name: deviceId + - name: device_id in: path description: Device identifier required: true @@ -64,7 +64,7 @@ paths: example: Kawasaki responses: '200': - description: task response + description: job response content: application/json: schema: @@ -81,24 +81,24 @@ paths: application/json: schema: $ref: '#/components/schemas/error.InternalServerError' - /tasks/sampling: + /jobs: get: tags: - - task - summary: List all sampling quantum tasks - description: List all sampling quantum tasks - operationId: listSamplingTasks + - job + summary: List all quantum jobs + description: List all quantum jobs + operationId: listJobs security: - BearerAuth: [] responses: '200': - description: Return a list of submitted quantum tasks + description: Return a list of submitted quantum jobs content: application/json: schema: type: array items: - $ref: '#/components/schemas/tasks.SamplingTaskInfo' + $ref: '#/components/schemas/jobs.JobDef' '401': description: Unauthorized content: @@ -109,53 +109,58 @@ paths: detail: Unauthorized post: tags: - - task - summary: Submit a sampling quantum task - description: Submit a sampling quantum task - operationId: submitSamplingTask + - job + summary: Submit a quantum job + description: Submit a quantum job + operationId: submitJob security: - BearerAuth: [] requestBody: - description: Quantum task to be submitted + description: Quantum job to be submitted content: application/json: schema: - $ref: '#/components/schemas/tasks.SamplingTaskDef' + $ref: '#/components/schemas/jobs.JobDef' examples: simulator: description: Simulator example value: - code: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; name: Bell State Sampling - device: SVsim - nNodes: 12 - nShots: 1000 - skipTranspilation: false - seedTranspilation: 873 - seedSimulation: 39058567 - nPerNode: 2 - simulationOpt: - optimizationMethod: light - optimizationBlockSize: 1 - optimizationSwapLevel: 1 - note: Bell State Sampling Example + description: Bell State Sampling Example + device_id: Kawasaki + job_info: '{''code'': ''{type: string, example: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;"}'', ''operator'': ''X 0 Y 1 Z 5 I 2'', ''result'': {''00'': 5020, ''11'': 4980}, ''transpiled_code'': '''', ''reason'': ''''}' + transpiler_info: '' + simulator_info: '{''n_qubits'': 5, ''n_nodes'': 12, ''n_per_node'': 2, ''seed_simulation'': 39058567, ''simulation_opt'': {''optimization_method'': ''light'', ''optimization_block_size'': 1, ''optimization_swap_level'': 1}}' + mitigation_info: '' + job_type: sampling + shots: 1000 + status: submitted + created_at: '2022-10-19T11:45:34+09:00' + updated_at: '2022-10-19T11:45:34+09:00' qpu: description: QPU example value: - code: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; name: Bell State Sampling - device: Kawasaki - nShots: 1000 - note: Bell State Sampling Example + description: Bell State Sampling Example + device_id: Kawasaki + job_info: '{''code'': ''{type: string, example: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;"}'', ''operator'': ''X 0 Y 1 Z 5 I 2'', ''result'': {''00'': 5020, ''11'': 4980}, ''transpiled_code'': '''', ''reason'': ''''}' + transpiler_info: '{''qubit_allocation'': {''0'': 12, ''1'': 16}, ''skip_transpilation'': false, ''seed_transpilation'': 873}' + simulator_info: '' + mitigation_info: '{''ro_error_mitigation'': ''pseudo_inverse''}' + job_type: sampling + shots: 1000 + status: submitted + created_at: '2022-10-19T11:45:34+09:00' + updated_at: '2022-10-19T11:45:34+09:00' responses: '200': - description: Task submitted + description: Job submitted content: application/json: schema: - $ref: '#/components/schemas/tasks.SubmitTaskResponse' + $ref: '#/components/schemas/jobs.SubmitJobResponse' example: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c + job_id: 7af020f6-2e38-4d70-8cf0-4349650ea08c '400': description: Bad Request content: @@ -172,29 +177,29 @@ paths: $ref: '#/components/schemas/error.UnauthorizedError' example: detail: Unauthorized - /tasks/sampling/{taskId}: + /jobs/{job_id}: get: tags: - - task - summary: Get selected sampling task - description: Get selected sampling task - operationId: getSamplingTask + - job + summary: Get selected job + description: Get selected job + operationId: getSamplingJob security: - BearerAuth: [] parameters: - in: path - name: taskId + name: job_id required: true - description: Task identifier + description: Job identifier schema: type: string responses: '200': - description: Return quantum task + description: Return quantum job content: application/json: schema: - $ref: '#/components/schemas/tasks.SamplingTaskInfo' + $ref: '#/components/schemas/jobs.JobDef' '400': description: Bad Request content: @@ -218,31 +223,31 @@ paths: schema: $ref: '#/components/schemas/error.NotFoundError' example: - detail: task not found + detail: job not found delete: tags: - - task - summary: Delete sampling task - description: 'Deletes quantum task and related result

Operation is valid only for task with status: COMPLETED, FAILED and CANCELLED. QUEUED and RUNNING tasks must be cancelled before deletion.' - operationId: deleteSamplingTask + - job + summary: Delete job + description: 'Deletes quantum job and related result

Operation is valid only for job with status: COMPLETED, FAILED and CANCELLED. submitted and RUNNING jobs must be cancelled before deletion.' + operationId: deleteSamplingJob security: - BearerAuth: [] parameters: - in: path - name: taskId + name: job_id required: true - description: Task identifier + description: Job identifier schema: type: string responses: '200': - description: Quantum task deleted + description: Quantum job deleted content: application/json: schema: $ref: '#/components/schemas/success.SuccessResponse' example: - message: Quantum task deleted + message: Quantum job deleted '400': description: Bad Request content: @@ -266,30 +271,30 @@ paths: schema: $ref: '#/components/schemas/error.NotFoundError' example: - detail: task not found - /tasks/sampling/{taskId}/status: + detail: job not found + /jobs/{job_id}/status: get: tags: - - task - summary: Get selected sampling task's status - description: Get selected sampling task's status - operationId: getSamplingTaskStatus + - job + summary: Get selected job's status + description: Get selected job's status + operationId: getSamplingJobStatus security: - BearerAuth: [] parameters: - in: path - name: taskId + name: job_id required: true - description: Task identifier + description: Job identifier schema: type: string responses: '200': - description: Return quantum task status + description: Return quantum job status content: application/json: schema: - $ref: '#/components/schemas/tasks.GetSamplingTaskStatusResponse' + $ref: '#/components/schemas/jobs.GetJobStatusResponse' '400': description: Bad Request content: @@ -313,26 +318,26 @@ paths: schema: $ref: '#/components/schemas/error.NotFoundError' example: - detail: task not found - /tasks/sampling/{taskId}/cancel: + detail: job not found + /jobs/{job_id}/cancel: post: tags: - - task - summary: Cancel sampling task - description: 'Start a procedure to cancel quantum task.

Operation is valid only for task with status: QUEUED or RUNNING.' - operationId: cancelSamplingTask + - job + summary: Cancel job + description: 'Start a procedure to cancel quantum job.

Operation is valid only for job with status: submitted or RUNNING.' + operationId: cancelSamplingJob security: - BearerAuth: [] parameters: - in: path - name: taskId + name: job_id required: true - description: Task identifier + description: Job identifier schema: type: string responses: '200': - description: Task cancelled + description: Job cancelled content: application/json: schema: @@ -362,461 +367,7 @@ paths: schema: $ref: '#/components/schemas/error.NotFoundError' example: - detail: task not found - /tasks/estimation: - post: - tags: - - task - summary: Submit estimation quantum task - description: Submit estimation quantum task - operationId: submitEstimationTask - security: - - BearerAuth: [] - requestBody: - description: Quantum task to be submitted - content: - application/json: - schema: - $ref: '#/components/schemas/tasks.EstimationTaskDef' - examples: - simulator: - description: Simulator example - value: - code: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; - name: Bell State Estimation - device: SVsim - nNodes: 12 - method: sampling - nShots: 1000 - operator: - - - X 0 X 1 - - - 1.5 - - 2.8 - - - Y 0 Z 1 - - - 1.2 - - -2.e-8 - skipTranspilation: false - seedTranspilation: 873 - seedSimulation: 39058567 - nPerNode: 2 - simulationOpt: - optimizationMethod: light - optimizationBlockSize: 1 - optimizationSwapLevel: 1 - note: Bell State Estimation Example - simulator2: - description: Simulator example with statevector - value: - code: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; - name: Bell State Estimation - device: SVsim - nNodes: 12 - method: state_vector - operator: - - - X 0 X 1 - - - 1.5 - - 2.8 - - - Y 0 Z 1 - - - 1.2 - - -2.e-8 - skipTranspilation: false - seedTranspilation: 873 - seedSimulation: 39058567 - nPerNode: 2 - simulationOpt: - optimizationMethod: light - optimizationBlockSize: 1 - optimizationSwapLevel: 1 - note: Bell State Estimation Example - qpu: - description: QPU example - value: - code: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; - name: Bell State Estimation - device: Kawasaki - method: sampling - nShots: 1000 - operator: - - - X 0 X 1 - - - 1.5 - - 2.8 - - - Y 0 Z 1 - - - 1.2 - - -2.e-8 - note: Bell State Estimation Example - responses: - '200': - description: Task submitted - content: - application/json: - schema: - $ref: '#/components/schemas/tasks.SubmitTaskResponse' - example: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - '400': - description: Bad Request - content: - application/json: - schema: - $ref: '#/components/schemas/error.BadRequest' - example: - detail: Bad request malformed input data - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/error.UnauthorizedError' - example: - detail: Unauthorized - get: - tags: - - task - summary: List all estimation quantum tasks - description: List all estimation quantum tasks - operationId: listEstimationTasks - security: - - BearerAuth: [] - responses: - '200': - description: Return a list of submitted quantum tasks - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/tasks.EstimationTaskInfo' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/error.UnauthorizedError' - example: - detail: Unauthorized - /tasks/estimation/{taskId}: - get: - tags: - - task - summary: Get selected estimation task - description: Get selected estimation task - operationId: getEstimationTask - security: - - BearerAuth: [] - parameters: - - in: path - name: taskId - required: true - description: Task identifier - schema: - type: string - responses: - '200': - description: Return quantum task - content: - application/json: - schema: - $ref: '#/components/schemas/tasks.EstimationTaskInfo' - '400': - description: Bad Request - content: - application/json: - schema: - $ref: '#/components/schemas/error.BadRequest' - example: - detail: Bad request malformed input data - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/error.UnauthorizedError' - example: - detail: Unauthorized - '404': - description: Not Found - content: - application/json: - schema: - $ref: '#/components/schemas/error.NotFoundError' - example: - detail: task not found - delete: - tags: - - task - summary: Deletes estimation task - description: 'Deletes quantum task and related result

Operation is valid only for task with status: COMPLETED, FAILED and CANCELLED. QUEUED and RUNNING tasks must be cancelled before deletion.' - operationId: deleteEstimationTask - security: - - BearerAuth: [] - parameters: - - in: path - name: taskId - required: true - description: Task identifier - schema: - type: string - responses: - '200': - description: Quantum task deleted - content: - application/json: - schema: - $ref: '#/components/schemas/success.SuccessResponse' - example: - message: Quantum task deleted - '400': - description: Bad Request - content: - application/json: - schema: - $ref: '#/components/schemas/error.BadRequest' - example: - detail: Bad request malformed input data - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/error.UnauthorizedError' - example: - detail: Unauthorized - '404': - description: Not Found - content: - application/json: - schema: - $ref: '#/components/schemas/error.NotFoundError' - example: - detail: task not found - /tasks/estimation/{taskId}/status: - get: - tags: - - task - summary: Get selected estimation task's status - description: Get selected estimation task's status - operationId: getEstimationTaskStatus - security: - - BearerAuth: [] - parameters: - - in: path - name: taskId - required: true - description: Task identifier - schema: - type: string - responses: - '200': - description: Return quantum task status - content: - application/json: - schema: - $ref: '#/components/schemas/tasks.GetEstimationTaskStatusResponse' - '400': - description: Bad Request - content: - application/json: - schema: - $ref: '#/components/schemas/error.BadRequest' - example: - detail: Bad request malformed input data - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/error.UnauthorizedError' - example: - detail: Unauthorized - '404': - description: Not Found - content: - application/json: - schema: - $ref: '#/components/schemas/error.NotFoundError' - example: - detail: task not found - /tasks/estimation/{taskId}/cancel: - post: - tags: - - task - summary: Cancel estimation task - description: 'Start a procedure to cancel quantum task.

Operation is valid only for task with status: QUEUED or RUNNING.' - operationId: cancelEstimationTask - security: - - BearerAuth: [] - parameters: - - in: path - name: taskId - required: true - description: Task identifier - schema: - type: string - responses: - '200': - description: cancel request accepted - content: - application/json: - schema: - $ref: '#/components/schemas/success.SuccessResponse' - example: - message: Task cancelled - '400': - description: Bad Request - content: - application/json: - schema: - $ref: '#/components/schemas/error.BadRequest' - example: - detail: Bad request malformed input data - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/error.UnauthorizedError' - example: - detail: Unauthorized - '404': - description: Not Found - content: - application/json: - schema: - $ref: '#/components/schemas/error.NotFoundError' - example: - detail: task not found - /results/sampling/{taskId}: - get: - tags: - - result - summary: Get result of a sampling task - description: Gets a result of quantum task.

Any finished quantum task must generate a result. The result contains either simulation result (for successfully completed tasks) or reason why simulation outcome is not provided (for unsuccessful and cancelled tasks)

Operation is valid only for COMPLETED, FAILED and CANCELLED tasks - operationId: getSamplingResult - security: - - BearerAuth: [] - parameters: - - in: path - name: taskId - required: true - description: Task identifier - schema: - type: string - responses: - '200': - description: Return quantum task result - content: - application/json: - schema: - $ref: '#/components/schemas/results.SamplingResultDef' - examples: - success sampling: - value: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - status: SUCCESS - result: - '11': 4980 - '00': 5020 - transpiledCode: OPENQASM 3;include "stdgates.inc";qubit[2] _all_qubits;let q = _all_qubits[0:1];h q[0];cx q[0], q[1]; - failure: - value: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - status: FAILURE - reason: Invalid device parameter in request - cancel: - value: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - status: CANCELLED - reason: User cancelled - '400': - description: Bad Request - content: - application/json: - schema: - $ref: '#/components/schemas/error.BadRequest' - example: - detail: Bad request malformed input data - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/error.UnauthorizedError' - example: - detail: Unauthorized - '404': - description: Not Found - content: - application/json: - schema: - $ref: '#/components/schemas/error.NotFoundError' - example: - detail: task not found - /results/estimation/{taskId}: - get: - tags: - - result - summary: Get result of estimation task - description: Gets a result of quantum task.

Any finished quantum task must generate a result. The result contains either simulation result (for successfully completed tasks) or reason why simulation outcome is not provided (for unsuccessful and cancelled tasks)

Operation is valid only for COMPLETED, FAILED and CANCELLED tasks - operationId: getEstimationResult - security: - - BearerAuth: [] - parameters: - - in: path - name: taskId - required: true - description: Task identifier - schema: - type: string - responses: - '200': - description: Return quantum task result - content: - application/json: - schema: - $ref: '#/components/schemas/results.EstimationResultDef' - examples: - success estimation: - value: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - status: SUCCESS - result: - - 1.5 - - 2.8 - transpiledCode: OPENQASM 3;include "stdgates.inc";qubit[2] _all_qubits;let q = _all_qubits[0:1];h q[0];cx q[0], q[1]; - failure: - value: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - status: FAILURE - reason: Invalid device parameter in request - cancel: - value: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - status: CANCELLED - reason: User cancelled - '400': - description: Bad Request - content: - application/json: - schema: - $ref: '#/components/schemas/error.BadRequest' - example: - detail: Bad request malformed input data - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/error.UnauthorizedError' - example: - detail: Unauthorized - '404': - description: Not Found - content: - application/json: - schema: - $ref: '#/components/schemas/error.NotFoundError' - example: - detail: task not found + detail: job not found components: securitySchemes: BearerAuth: @@ -824,95 +375,13 @@ components: scheme: bearer bearerFormat: JWT schemas: - devices.CalibrationData: - description: Calibration data available only for 'QPU' devices - type: object - properties: - qubitConnectivity: - type: array - items: - type: string - format: (number, number) - example: - - (1,4) - - (4,5) - - (5,8) - t1: - type: object - additionalProperties: - type: number - format: float - example: - '0': 55.51 - '1': 37.03 - '2': 57.13 - t2: - type: object - additionalProperties: - type: number - format: float - example: - '0': 99.31 - '1': 111.03 - '2': 30.12 - roError: - type: object - additionalProperties: - type: number - format: float - example: - '0': 0.0467 - '1': 0.18 - '2': 0.355 - gateError: - type: object - additionalProperties: - type: object - additionalProperties: - type: number - format: float - example: - sx: - '0': 0.00692 - '1': 0.00296 - '2': 0.072 - measProb0As1: - type: object - additionalProperties: - type: number - format: float - example: - '0': 0.00608 - '1': 0.012 - '2': 0.248 - measProb1As0: - type: object - additionalProperties: - type: number - format: float - example: - '0': 0.0281 - '1': 0.386 - '2': 0.0811 - gateDuration: - type: object - additionalProperties: - type: object - additionalProperties: - type: number - format: float - example: - sx: - '0': 29.3 - '1': 50.9 - '2': 45.4 devices.DeviceInfo: type: object properties: - deviceId: + device_id: type: string example: SVSim - deviceType: + device_type: type: string enum: - QPU @@ -921,25 +390,21 @@ components: status: type: string enum: - - AVAILABLE - - NOT_AVAILABLE - example: AVAILABLE - restartAt: - description: Parameter mandatory and valid for 'NOT_AVAILABLE' devices + - available + - unavailable + example: available + available_at: + description: Parameter mandatory and valid for 'unavailable' devices type: string format: date-time example: '2022-10-19T11:45:34+09:00' - nPendingTasks: + n_pending_jobs: type: integer example: 8 - nQubits: + n_qubits: type: integer example: 39 - nNodes: - description: Parameter valid only for 'simulator' devices - type: integer - example: 512 - basisGates: + basis_gates: type: array items: type: string @@ -966,7 +431,7 @@ components: - id - sx - sxdg - supportedInstructions: + supported_instructions: type: array items: type: string @@ -974,9 +439,11 @@ components: - measure - barrier - reset - calibrationData: - $ref: '#/components/schemas/devices.CalibrationData' - calibratedAt: + device_info: + description: json format calibration_data and n_nodes etc + type: string + example: '{''n_nodes'': 512, ''calibration_data'': {''qubit_connectivity'': [''(1,4)'', ''(4,5)'', ''(5,8)''], ''t1'': {''0'': 55.51, ''1'': 37.03, ''2'': 57.13}}' + calibrated_at: description: Parameter available only for 'QPU' devices with available calibration data type: string format: date-time @@ -988,18 +455,18 @@ components: - deviceId - deviceType - status - - nPendingTasks + - nPendingJobs - basisGates - supportedInstructions - description example: - - deviceId: SVSim - deviceType: simulator + - device_id: SVSim + device_type: simulator status: AVAILABLE - nPendingTasks: 8 - nQubits: 39 - nNodes: 512 - basisGates: + n_pending_jobs: 8 + n_qubits: 39 + n_nodes: 512 + basis_gates: - x - 'y' - z @@ -1022,10 +489,12 @@ components: - id - sx - sxdg - supportedInstructions: + supported_instructions: - measure - barrier - reset + device_info: '{''n_nodes'': 512, ''calibration_data'': {''qubit_connectivity'': [''(1,4)'', ''(4,5)'', ''(5,8)''], ''t1'': {''0'': 55.51, ''1'': 37.03, ''2'': 57.13}}' + calibrated_at: '2022-10-19T11:45:34+09:00' description: State vector-based quantum circuit simulator error.UnauthorizedError: type: object @@ -1048,200 +517,98 @@ components: type: string required: - detail - tasks.TaskId: + jobs.JobId: type: string - format: uuid example: 7af020f6-2e38-4d70-8cf0-4349650ea08c - tasks.TaskStatus: + jobs.JobInfo: + type: string + example: '{''code'': ''{type: string, example: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;"}'', ''Operator'': ''X 0 Y 1 Z 5 I 2'', ''result'': {''00'': 5020, ''11'': 4980}, ''transpiledCode'': '''', ''reason'': ''''}' + jobs.TranspilerInfo: + type: string + example: '{''qubitAllocation'': {''0'': 12, ''1'': 16}, ''skipTranspilation'': false, ''seedTranspilation'': 873}' + jobs.SimulatorInfo: + type: string + example: '{''nQubits'': 5, ''nNodes'': 12, ''nPerNode'': 2, ''seedSimulation'': 39058567, ''simulationOpt'': {''optimizationMethod'': ''light'', ''optimizationBlockSize'': 1, ''optimizationSwapLevel'': 1}}' + jobs.MitigationInfo: + type: string + example: '{''roErrorMitigation'': ''pseudo_inverse''}' + jobs.JobStatus: type: string enum: - - QUEUED - - RUNNING - - COMPLETED - - FAILED - - CANCELLING - - CANCELLED - example: QUEUED - tasks.SamplingTaskInfo: + - submitted + - ready + - running + - success + - failed + - cancelled + example: submitted + jobs.JobDef: type: object properties: - taskId: - $ref: '#/components/schemas/tasks.TaskId' - code: - type: string - example: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; + job_id: + $ref: '#/components/schemas/jobs.JobId' name: type: string example: Bell State Sampling - device: + description: + type: string + example: Bell State Sampling Example + device_id: type: string example: Kawasaki - nQubits: - description: Parameter exclusive with nNodes - type: integer - nNodes: - description: Parameter exclusive with nQubits
Parameter valid only for 'simulator' devices - type: integer - example: 12 - nShots: + shots: type: integer minimum: 1 maximum: 10000000 example: '1000' - qubitAllocation: - description: Parameter valid only for QPU devices - type: object - additionalProperties: - type: integer - example: - '0': 12 - '1': 16 - skipTranspilation: - type: boolean - example: false - seedTranspilation: - description: Parameter valid only if skipTranspilation is false - type: integer - example: 873 - seedSimulation: - description: Parameter valid only for 'simulator' devices - type: integer - example: 39058567 - roErrorMitigation: - description: Parameter valid only for QPU devices - type: string - enum: - - none - - pseudo_inverse - - least_square - example: pseudo_inverse - nPerNode: - description: Parameter valid only for simulator devices - type: integer - minimum: 1 - example: 5 - simulationOpt: - description: Parameter valid only for simulator devices - type: object - example: - optimizationMethod: light - optimizationBlockSize: 1 - optimizationSwapLevel: 1 - note: - type: string - example: Bell State Sampling Example + job_type: + type: string + example: '''sampling'' or ''estimation'', ''sse''' + job_info: + $ref: '#/components/schemas/jobs.JobInfo' + transpiler_info: + $ref: '#/components/schemas/jobs.TranspilerInfo' + simulator_info: + $ref: '#/components/schemas/jobs.SimulatorInfo' + mitigation_info: + $ref: '#/components/schemas/jobs.MitigationInfo' status: - $ref: '#/components/schemas/tasks.TaskStatus' - createdAt: + $ref: '#/components/schemas/jobs.JobStatus' + created_at: + type: string + format: date-time + example: '2022-10-19T11:45:34+09:00' + updated_at: type: string format: date-time example: '2022-10-19T11:45:34+09:00' required: - - taskId - - code - - device - - nShots - - skipTranspilation + - device_id + - shots - status - - createdAt + - created_at example: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - code: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; + job_id: 7af020f6-2e38-4d70-8cf0-4349650ea08c name: Bell State Sampling - device: Kawasaki - nNodes: 12 - nShots: 1000 - skipTranspilation: false - seedTranspilation: 387 - seedSimulation: 39058567 - nPerNode: 2 - simulationOpt: - optimizationMethod: light - optimizationBlockSize: 1 - optimizationSwapLevel: 1 - note: Bell State Sampling Example - status: QUEUED - createdAt: '2022-10-19T11:45:34+09:00' - tasks.SamplingTaskDef: + description: Bell State Sampling Example + device_id: Kawasaki + job_info: '{''code'': ''{type: string, example: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;"}'', ''Operator'': ''X 0 Y 1 Z 5 I 2'', ''result'': {''00'': 5020, ''11'': 4980}, ''transpiled_code'': '''', ''reason'': ''''}' + transpiler_info: '{''qubit_allocation'': {''0'': 12, ''1'': 16}, ''skip_transpilation'': false, ''seed_transpilation'': 873}' + simulator_info: '{''n_qubits'': 5, ''n_nodes'': 12, ''n_per_node'': 2, ''seed_simulation'': 39058567, ''simulation_opt'': {''optimization_method'': ''light'', ''optimization_block_size'': 1, ''optimization_swap_level'': 1}}' + mitigation_info: '{''ro_error_mitigation'': ''pseudo_inverse''}' + job_type: sampling + shots: 1000 + status: submitted + created_at: '2022-10-19T11:45:34+09:00' + updated_at: '2022-10-19T11:45:34+09:00' + jobs.SubmitJobResponse: + description: submit a job type: object properties: - code: - type: string - example: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; - name: - type: string - example: Bell State Sampling - device: - type: string - example: Kawasaki - nQubits: - description: Parameter exclusive with nNodes - type: integer - nNodes: - description: Parameter exclusive with nQubits
Parameter valid only for 'simulator' devices - type: integer - example: 12 - nShots: - type: integer - minimum: 1 - maximum: 10000000 - example: '1000' - qubitAllocation: - description: Parameter valid only for QPU devices - type: object - additionalProperties: - type: integer - example: - '0': 12 - '1': 16 - skipTranspilation: - type: boolean - default: false - example: false - seedTranspilation: - description: Parameter valid only if skipTranspilation is false - type: integer - example: 873 - seedSimulation: - description: Parameter valid only for 'simulator' devices - type: integer - example: 39058567 - roErrorMitigation: - description: Parameter valid only for QPU devices - type: string - enum: - - none - - pseudo_inverse - - least_square - default: none - example: pseudo_inverse - nPerNode: - description: Parameter valid only for simulator devices - type: integer - minimum: 1 - example: 5 - simulationOpt: - description: Parameter valid only for simulator devices - type: object - example: - optimizationMethod: light - optimizationBlockSize: 1 - optimizationSwapLevel: 1 - note: - type: string - example: Bell State Sampling Example + job_id: + $ref: '#/components/schemas/jobs.JobId' required: - - code - - device - - nShots - tasks.SubmitTaskResponse: - description: submit a task - type: object - properties: - taskId: - $ref: '#/components/schemas/tasks.TaskId' - required: - - taskId + - job_id error.BadRequest: type: object properties: @@ -1256,331 +623,14 @@ components: type: string required: - message - tasks.GetSamplingTaskStatusResponse: - description: task status - type: object - properties: - taskId: - $ref: '#/components/schemas/tasks.TaskId' - status: - $ref: '#/components/schemas/tasks.TaskStatus' - required: - - taskId - - status - tasks.SingleOperator: - type: array - items: - anyOf: - - type: string - description: Pauli string - example: X 0 Y 1 Z 5 I 2 - - type: array - description: Real and imaginary components of complex coef value - items: - type: number - minItems: 2 - maxItems: 2 - example: - - 1.5 - - 2.8 - minItems: 2 - maxItems: 2 - tasks.Operator: - type: array - items: - $ref: '#/components/schemas/tasks.SingleOperator' - example: - - - X 0 X 1 - - - 1.5 - - 2.8 - - - Y 0 Z 1 - - - 1.2 - - -2.e-8 - tasks.EstimationTaskInfo: - type: object - properties: - taskId: - $ref: '#/components/schemas/tasks.TaskId' - code: - type: string - example: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; - name: - type: string - example: Bell State Estimation - device: - type: string - example: Kawasaki - nQubits: - description: Parameter exclusive with nNodes - type: integer - nNodes: - description: Parameter exclusive with nQubits
Parameter valid only for 'simulator' devices - type: integer - example: 12 - method: - type: string - enum: - - state_vector - - sampling - example: sampling - description: state_vector method valid only for 'simulator' devices - nShots: - type: integer - minimum: 1 - maximum: 10000000 - example: '1000' - description: Parameter valid only for sampling method - operator: - $ref: '#/components/schemas/tasks.Operator' - qubitAllocation: - description: Parameter valid only for QPU devices - type: object - additionalProperties: - type: integer - example: - '0': 12 - '1': 16 - skipTranspilation: - type: boolean - example: false - seedTranspilation: - description: Parameter valid only if skipTranspilation is false - type: integer - example: 873 - seedSimulation: - description: Parameter valid only for 'simulator' devices - type: integer - example: 39058567 - roErrorMitigation: - description: Parameter valid only for QPU devices - type: string - enum: - - none - - pseudo_inverse - - least_square - example: pseudo_inverse - nPerNode: - description: Parameter valid only for simulator devices - type: integer - minimum: 1 - example: 5 - simulationOpt: - description: Parameter valid only for simulator devices - type: object - example: - optimizationMethod: light - optimizationBlockSize: 1 - optimizationSwapLevel: 1 - note: - type: string - example: Bell State Estimation Example - status: - $ref: '#/components/schemas/tasks.TaskStatus' - createdAt: - type: string - format: date-time - example: '2022-10-19T11:45:34+09:00' - required: - - taskId - - code - - device - - method - - operator - - skipTranspilation - - status - - createdAt - example: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - code: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; - name: Bell State Estimation - device: Kawasaki - nNodes: 12 - method: sampling - nShots: 1000 - operator: - - - X 0 X 1 - - - 1.5 - - 2.8 - - - Y 0 Z 1 - - - 1.2 - - -2.e-8 - skipTranspilation: false - seedTranspilation: 387 - seedSimulation: 39058567 - nPerNode: 2 - simulationOpt: - optimizationMethod: light - optimizationBlockSize: 1 - optimizationSwapLevel: 1 - note: Bell State Estimation Example - status: QUEUED - createdAt: '2022-10-19T11:45:34+09:00' - tasks.EstimationTaskDef: - type: object - properties: - code: - type: string - example: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; - name: - type: string - example: Bell State Estimation - device: - type: string - example: Kawasaki - nQubits: - description: Parameter exclusive with nNodes - type: integer - nNodes: - description: Parameter exclusive with nQubits
Parameter valid only for 'simulator' devices - type: integer - example: 12 - method: - type: string - enum: - - state_vector - - sampling - example: sampling - description: state_vector method valid only for 'simulator' devices - nShots: - type: integer - minimum: 1 - maximum: 10000000 - example: '1000' - description: Parameter valid only for sampling method - operator: - $ref: '#/components/schemas/tasks.Operator' - qubitAllocation: - description: Parameter valid only for QPU devices - type: object - additionalProperties: - type: integer - example: - '0': 12 - '1': 16 - skipTranspilation: - type: boolean - default: false - example: false - seedTranspilation: - description: Parameter valid only if skipTranspilation is false - type: integer - example: 873 - seedSimulation: - description: Parameter valid only for 'simulator' devices - type: integer - example: 39058567 - roErrorMitigation: - description: Parameter valid only for QPU devices - type: string - enum: - - none - - pseudo_inverse - - least_square - default: none - example: pseudo_inverse - nPerNode: - description: Parameter valid only for simulator devices - type: integer - minimum: 1 - example: 5 - simulationOpt: - description: Parameter valid only for simulator devices - type: object - example: - optimizationMethod: light - optimizationBlockSize: 1 - optimizationSwapLevel: 1 - note: - type: string - example: Bell State Estimation Example - required: - - code - - device - - method - - operator - tasks.GetEstimationTaskStatusResponse: - description: task status - type: object - properties: - taskId: - $ref: '#/components/schemas/tasks.TaskId' - status: - $ref: '#/components/schemas/tasks.TaskStatus' - required: - - taskId - - status - results.ResultStatus: - type: string - enum: - - SUCCESS - - FAILURE - - CANCELLED - default: SUCCESS - example: SUCCESS - results.SamplingResultDef: + jobs.GetJobStatusResponse: + description: job status type: object properties: - taskId: - $ref: '#/components/schemas/tasks.TaskId' + job_id: + $ref: '#/components/schemas/jobs.JobId' status: - $ref: '#/components/schemas/results.ResultStatus' - result: - description: Provided only for successful results - type: object - additionalProperties: - type: integer - minProperties: 2 - example: - '11': 4980 - '00': 5020 - reason: - description: Provided only for unsuccessful (failed, cancelled) results - type: string - transpiledCode: - description: Provided only for tasks with transpilation (tasks created with skipTranspilation=False), if traspilation was successfull - type: string - qubitAllocation: - description: Parameter valid only for QPU devices - type: object - additionalProperties: - type: integer - example: - '0': 0 - '1': 4 - required: - - taskId - - status - results.EstimationResultDef: - type: object - properties: - taskId: - $ref: '#/components/schemas/tasks.TaskId' - status: - $ref: '#/components/schemas/results.ResultStatus' - result: - description: Real and imaginary components of complex estimation result value
Provided only for successful results - type: array - items: - type: number - minItems: 1 - maxItems: 2 - example: - - 1.5 - - 2.8 - reason: - description: Provided only for unsuccessful (failed, cancelled) results - type: string - transpiledCode: - description: Provided only for tasks with transpilation (tasks created with skipTranspilation=False), if traspilation was successfull - type: string - qubitAllocation: - description: Parameter valid only for QPU devices - type: object - additionalProperties: - type: integer - example: - '0': 0 - '1': 4 + $ref: '#/components/schemas/jobs.JobStatus' required: - - taskId + - job_id - status diff --git a/backend/oas/user/paths/devices.yaml b/backend/oas/user/paths/devices.yaml index 99e446e..cd10fba 100644 --- a/backend/oas/user/paths/devices.yaml +++ b/backend/oas/user/paths/devices.yaml @@ -46,7 +46,7 @@ devices.deviceId: security: - BearerAuth: [] parameters: - - name: deviceId + - name: device_id in: path description: "Device identifier" required: true @@ -55,7 +55,7 @@ devices.deviceId: example: "Kawasaki" responses: '200': - description: task response + description: job response content: application/json: schema: diff --git a/backend/oas/user/paths/jobs.yaml b/backend/oas/user/paths/jobs.yaml new file mode 100644 index 0000000..025bd43 --- /dev/null +++ b/backend/oas/user/paths/jobs.yaml @@ -0,0 +1,291 @@ +jobs: + get: + tags: + - job + summary: "List all quantum jobs" + description: "List all quantum jobs" + operationId: listJobs + security: + - BearerAuth: [] + responses: + "200": + description: "Return a list of submitted quantum jobs" + content: + application/json: + schema: + type: array + items: + $ref: "../schemas/jobs.yaml#/jobs.JobDef" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '../schemas/error.yaml#/error.UnauthorizedError' + example: + detail: Unauthorized + post: + tags: + - job + summary: "Submit a quantum job" + description: "Submit a quantum job" + operationId: submitJob + security: + - BearerAuth: [] + requestBody: + description: "Quantum job to be submitted" + content: + application/json: + schema: + $ref: "../schemas/jobs.yaml#/jobs.JobDef" + examples: + simulator: + description: Simulator example + value: + { + name: "Bell State Sampling", + description: "Bell State Sampling Example", + device_id: "Kawasaki", + job_info: "{'code': '{type: string, example: \"OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;\"}', 'operator': 'X 0 Y 1 Z 5 I 2', 'result': {'00': 5020, '11': 4980}, 'transpiled_code': '', 'reason': ''}", + transpiler_info: "", + simulator_info: "{'n_qubits': 5, 'n_nodes': 12, 'n_per_node': 2, 'seed_simulation': 39058567, 'simulation_opt': {'optimization_method': 'light', 'optimization_block_size': 1, 'optimization_swap_level': 1}}", + mitigation_info: "", + job_type: "sampling", + shots: 1000, + status: "submitted", + created_at: "2022-10-19T11:45:34+09:00", + updated_at: "2022-10-19T11:45:34+09:00" + } + qpu: + description: QPU example + value: + { + name: "Bell State Sampling", + description: "Bell State Sampling Example", + device_id: "Kawasaki", + job_info: "{'code': '{type: string, example: \"OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;\"}', 'operator': 'X 0 Y 1 Z 5 I 2', 'result': {'00': 5020, '11': 4980}, 'transpiled_code': '', 'reason': ''}", + transpiler_info: "{'qubit_allocation': {'0': 12, '1': 16}, 'skip_transpilation': false, 'seed_transpilation': 873}", + simulator_info: "", + mitigation_info: "{'ro_error_mitigation': 'pseudo_inverse'}", + job_type: "sampling", + shots: 1000, + status: "submitted", + created_at: "2022-10-19T11:45:34+09:00", + updated_at: "2022-10-19T11:45:34+09:00" + } + + responses: + "200": + description: "Job submitted" + content: + application/json: + schema: + $ref: "../schemas/jobs.yaml#/jobs.SubmitJobResponse" + example: + job_id: 7af020f6-2e38-4d70-8cf0-4349650ea08c + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '../schemas/error.yaml#/error.BadRequest' + example: + detail: Bad request malformed input data + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '../schemas/error.yaml#/error.UnauthorizedError' + example: + detail: Unauthorized + +jobs.jobId: + get: + tags: + - job + summary: "Get selected job" + description: "Get selected job" + operationId: getSamplingJob + security: + - BearerAuth: [] + parameters: + - in: path + name: job_id + required: true + description: "Job identifier" + schema: {type: string} + responses: + "200": + description: "Return quantum job" + content: + application/json: + schema: + $ref: "../schemas/jobs.yaml#/jobs.JobDef" + "400": + description: Bad Request + content: + application/json: + schema: + $ref: '../schemas/error.yaml#/error.BadRequest' + example: + detail: Bad request malformed input data + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '../schemas/error.yaml#/error.UnauthorizedError' + example: + detail: Unauthorized + '404': + description: Not Found + content: + application/json: + schema: + $ref: '../schemas/error.yaml#/error.NotFoundError' + example: + detail: job not found + delete: + tags: + - job + summary: "Delete job" + description: "Deletes quantum job and related result

Operation is valid only for job with status: COMPLETED, FAILED and CANCELLED. submitted and RUNNING jobs must be cancelled before deletion." + operationId: deleteSamplingJob + security: + - BearerAuth: [] + parameters: + - in: path + name: job_id + required: true + description: "Job identifier" + schema: {type: string} + responses: + "200": + description: "Quantum job deleted" + content: + application/json: + schema: + $ref: "../schemas/success.yaml#/success.SuccessResponse" + example: + message: Quantum job deleted + "400": + description: Bad Request + content: + application/json: + schema: + $ref: '../schemas/error.yaml#/error.BadRequest' + example: + detail: Bad request malformed input data + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '../schemas/error.yaml#/error.UnauthorizedError' + example: + detail: Unauthorized + '404': + description: Not Found + content: + application/json: + schema: + $ref: '../schemas/error.yaml#/error.NotFoundError' + example: + detail: job not found + +jobs.jobId.status: + get: + tags: + - job + summary: "Get selected job's status" + description: "Get selected job's status" + operationId: getSamplingJobStatus + security: + - BearerAuth: [] + parameters: + - in: path + name: job_id + required: true + description: "Job identifier" + schema: {type: string} + responses: + "200": + description: "Return quantum job status" + content: + application/json: + schema: + $ref: '../schemas/jobs.yaml#/jobs.GetJobStatusResponse' + "400": + description: Bad Request + content: + application/json: + schema: + $ref: '../schemas/error.yaml#/error.BadRequest' + example: + detail: Bad request malformed input data + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '../schemas/error.yaml#/error.UnauthorizedError' + example: + detail: Unauthorized + '404': + description: Not Found + content: + application/json: + schema: + $ref: '../schemas/error.yaml#/error.NotFoundError' + example: + detail: job not found + +jobs.jobId.cancel: + post: + tags: + - job + summary: "Cancel job" + description: "Start a procedure to cancel quantum job.

Operation is valid only for job with status: submitted or RUNNING." + operationId: cancelSamplingJob + security: + - BearerAuth: [] + parameters: + - in: path + name: job_id + required: true + description: "Job identifier" + schema: {type: string} + responses: + "200": + description: "Job cancelled" + content: + application/json: + schema: + $ref: "../schemas/success.yaml#/success.SuccessResponse" + example: + message: cancel request accepted + "400": + description: Bad Request + content: + application/json: + schema: + $ref: '../schemas/error.yaml#/error.BadRequest' + example: + detail: Bad request malformed input data + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '../schemas/error.yaml#/error.UnauthorizedError' + example: + detail: Unauthorized + '404': + description: Not Found + content: + application/json: + schema: + $ref: '../schemas/error.yaml#/error.NotFoundError' + example: + detail: job not found diff --git a/backend/oas/user/paths/results.yaml b/backend/oas/user/paths/results.yaml deleted file mode 100644 index 103cae5..0000000 --- a/backend/oas/user/paths/results.yaml +++ /dev/null @@ -1,143 +0,0 @@ -results.sampling.taskId: - get: - tags: - - result - summary: "Get result of a sampling task" - description: "Gets a result of quantum task.

Any finished quantum task must generate a result. The result contains either simulation result (for successfully completed tasks) or reason why simulation outcome is not provided (for unsuccessful and cancelled tasks)

Operation is valid only for COMPLETED, FAILED and CANCELLED tasks" - operationId: getSamplingResult - security: - - BearerAuth: [] - parameters: - - in: path - name: taskId - required: true - description: "Task identifier" - schema: {type: string} - responses: - "200": - description: "Return quantum task result" - content: - application/json: - schema: - $ref: "../schemas/results.yaml#/results.SamplingResultDef" - examples: - success sampling: - value: - { - "taskId": "7af020f6-2e38-4d70-8cf0-4349650ea08c", - "status": "SUCCESS", - "result": - { - "00": 5020, - "11": 4980 - }, - "transpiledCode": "OPENQASM 3;include \"stdgates.inc\";qubit[2] _all_qubits;let q = _all_qubits[0:1];h q[0];cx q[0], q[1];" - } - failure: - value: - { - "taskId": "7af020f6-2e38-4d70-8cf0-4349650ea08c", - "status": "FAILURE", - "reason": "Invalid device parameter in request" - } - cancel: - value: - { - "taskId": "7af020f6-2e38-4d70-8cf0-4349650ea08c", - "status": "CANCELLED", - "reason": "User cancelled" - } - "400": - description: Bad Request - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.BadRequest' - example: - detail: Bad request malformed input data - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.UnauthorizedError' - example: - detail: Unauthorized - '404': - description: Not Found - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.NotFoundError' - example: - detail: task not found - -results.estimation.taskId: - get: - tags: - - result - summary: "Get result of estimation task" - description: "Gets a result of quantum task.

Any finished quantum task must generate a result. The result contains either simulation result (for successfully completed tasks) or reason why simulation outcome is not provided (for unsuccessful and cancelled tasks)

Operation is valid only for COMPLETED, FAILED and CANCELLED tasks" - operationId: getEstimationResult - security: - - BearerAuth: [] - parameters: - - in: path - name: taskId - required: true - description: "Task identifier" - schema: {type: string} - responses: - "200": - description: "Return quantum task result" - content: - application/json: - schema: - $ref: "../schemas/results.yaml#/results.EstimationResultDef" - examples: - success estimation: - value: - { - "taskId": "7af020f6-2e38-4d70-8cf0-4349650ea08c", - "status": "SUCCESS", - "result": [1.5, 2.8], - "transpiledCode": "OPENQASM 3;include \"stdgates.inc\";qubit[2] _all_qubits;let q = _all_qubits[0:1];h q[0];cx q[0], q[1];" - } - failure: - value: - { - "taskId": "7af020f6-2e38-4d70-8cf0-4349650ea08c", - "status": "FAILURE", - "reason": "Invalid device parameter in request" - } - cancel: - value: - { - "taskId": "7af020f6-2e38-4d70-8cf0-4349650ea08c", - "status": "CANCELLED", - "reason": "User cancelled" - } - "400": - description: Bad Request - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.BadRequest' - example: - detail: Bad request malformed input data - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.UnauthorizedError' - example: - detail: Unauthorized - '404': - description: Not Found - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.NotFoundError' - example: - detail: task not found diff --git a/backend/oas/user/paths/tasks.yaml b/backend/oas/user/paths/tasks.yaml deleted file mode 100644 index c90963b..0000000 --- a/backend/oas/user/paths/tasks.yaml +++ /dev/null @@ -1,613 +0,0 @@ -tasks.sampling: - get: - tags: - - task - summary: "List all sampling quantum tasks" - description: "List all sampling quantum tasks" - operationId: listSamplingTasks - security: - - BearerAuth: [] - responses: - "200": - description: "Return a list of submitted quantum tasks" - content: - application/json: - schema: - type: array - items: - $ref: "../schemas/tasks.yaml#/tasks.SamplingTaskInfo" - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.UnauthorizedError' - example: - detail: Unauthorized - post: - tags: - - task - summary: "Submit a sampling quantum task" - description: "Submit a sampling quantum task" - operationId: submitSamplingTask - security: - - BearerAuth: [] - requestBody: - description: "Quantum task to be submitted" - content: - application/json: - schema: - $ref: "../schemas/tasks.yaml#/tasks.SamplingTaskDef" - examples: - simulator: - description: Simulator example - value: - { - code: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;", - name: "Bell State Sampling", - device: "SVsim", - nNodes: 12, - nShots: 1000, - skipTranspilation: false, - seedTranspilation: 873, - seedSimulation: 39058567, - nPerNode: 2, - simulationOpt: { - optimizationMethod: "light", - optimizationBlockSize: 1, - optimizationSwapLevel: 1 - }, - note: "Bell State Sampling Example" - } - qpu: - description: QPU example - value: - { - code: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;", - name: "Bell State Sampling", - device: "Kawasaki", - nShots: 1000, - note: "Bell State Sampling Example" - } - - responses: - "200": - description: "Task submitted" - content: - application/json: - schema: - $ref: "../schemas/tasks.yaml#/tasks.SubmitTaskResponse" - example: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - '400': - description: Bad Request - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.BadRequest' - example: - detail: Bad request malformed input data - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.UnauthorizedError' - example: - detail: Unauthorized - -tasks.sampling.taskId: - get: - tags: - - task - summary: "Get selected sampling task" - description: "Get selected sampling task" - operationId: getSamplingTask - security: - - BearerAuth: [] - parameters: - - in: path - name: taskId - required: true - description: "Task identifier" - schema: {type: string} - responses: - "200": - description: "Return quantum task" - content: - application/json: - schema: - $ref: "../schemas/tasks.yaml#/tasks.SamplingTaskInfo" - "400": - description: Bad Request - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.BadRequest' - example: - detail: Bad request malformed input data - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.UnauthorizedError' - example: - detail: Unauthorized - '404': - description: Not Found - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.NotFoundError' - example: - detail: task not found - delete: - tags: - - task - summary: "Delete sampling task" - description: "Deletes quantum task and related result

Operation is valid only for task with status: COMPLETED, FAILED and CANCELLED. QUEUED and RUNNING tasks must be cancelled before deletion." - operationId: deleteSamplingTask - security: - - BearerAuth: [] - parameters: - - in: path - name: taskId - required: true - description: "Task identifier" - schema: {type: string} - responses: - "200": - description: "Quantum task deleted" - content: - application/json: - schema: - $ref: "../schemas/success.yaml#/success.SuccessResponse" - example: - message: Quantum task deleted - "400": - description: Bad Request - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.BadRequest' - example: - detail: Bad request malformed input data - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.UnauthorizedError' - example: - detail: Unauthorized - '404': - description: Not Found - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.NotFoundError' - example: - detail: task not found - -tasks.sampling.taskId.status: - get: - tags: - - task - summary: "Get selected sampling task's status" - description: "Get selected sampling task's status" - operationId: getSamplingTaskStatus - security: - - BearerAuth: [] - parameters: - - in: path - name: taskId - required: true - description: "Task identifier" - schema: {type: string} - responses: - "200": - description: "Return quantum task status" - content: - application/json: - schema: - $ref: '../schemas/tasks.yaml#/tasks.GetSamplingTaskStatusResponse' - "400": - description: Bad Request - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.BadRequest' - example: - detail: Bad request malformed input data - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.UnauthorizedError' - example: - detail: Unauthorized - '404': - description: Not Found - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.NotFoundError' - example: - detail: task not found - -tasks.sampling.taskId.cancel: - post: - tags: - - task - summary: "Cancel sampling task" - description: "Start a procedure to cancel quantum task.

Operation is valid only for task with status: QUEUED or RUNNING." - operationId: cancelSamplingTask - security: - - BearerAuth: [] - parameters: - - in: path - name: taskId - required: true - description: "Task identifier" - schema: {type: string} - responses: - "200": - description: "Task cancelled" - content: - application/json: - schema: - $ref: "../schemas/success.yaml#/success.SuccessResponse" - example: - message: cancel request accepted - "400": - description: Bad Request - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.BadRequest' - example: - detail: Bad request malformed input data - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.UnauthorizedError' - example: - detail: Unauthorized - '404': - description: Not Found - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.NotFoundError' - example: - detail: task not found - -tasks.estimation: - post: - tags: - - task - summary: "Submit estimation quantum task" - description: "Submit estimation quantum task" - operationId: submitEstimationTask - security: - - BearerAuth: [] - requestBody: - description: "Quantum task to be submitted" - content: - application/json: - schema: - $ref: "../schemas/tasks.yaml#/tasks.EstimationTaskDef" - examples: - simulator: - description: Simulator example - value: - { - code: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;", - name: "Bell State Estimation", - device: "SVsim", - nNodes: 12, - method: "sampling", - nShots: 1000, - operator: - [ - ["X 0 X 1", [1.5, 2.8]], - ["Y 0 Z 1", [1.2, -2e-8]], - ], - skipTranspilation: false, - seedTranspilation: 873, - seedSimulation: 39058567, - nPerNode: 2, - simulationOpt: { - optimizationMethod: "light", - optimizationBlockSize: 1, - optimizationSwapLevel: 1 - }, - note: "Bell State Estimation Example" - } - simulator2: - description: Simulator example with statevector - value: - { - code: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;", - name: "Bell State Estimation", - device: "SVsim", - nNodes: 12, - method: "state_vector", - operator: - [ - ["X 0 X 1", [1.5, 2.8]], - ["Y 0 Z 1", [1.2, -2e-8]], - ], - skipTranspilation: false, - seedTranspilation: 873, - seedSimulation: 39058567, - nPerNode: 2, - simulationOpt: { - optimizationMethod: "light", - optimizationBlockSize: 1, - optimizationSwapLevel: 1 - }, - note: "Bell State Estimation Example" - } - qpu: - description: QPU example - value: - { - code: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;", - name: "Bell State Estimation", - device: "Kawasaki", - method: "sampling", - nShots: 1000, - operator: - [ - ["X 0 X 1", [1.5, 2.8]], - ["Y 0 Z 1", [1.2, -2e-8]], - ], - note: "Bell State Estimation Example" - } - - responses: - "200": - description: "Task submitted" - content: - application/json: - schema: - $ref: "../schemas/tasks.yaml#/tasks.SubmitTaskResponse" - example: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - "400": - description: Bad Request - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.BadRequest' - example: - detail: Bad request malformed input data - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.UnauthorizedError' - example: - detail: Unauthorized - get: - tags: - - task - summary: "List all estimation quantum tasks" - description: "List all estimation quantum tasks" - operationId: listEstimationTasks - security: - - BearerAuth: [] - responses: - "200": - description: "Return a list of submitted quantum tasks" - content: - application/json: - schema: - type: array - items: - $ref: "../schemas/tasks.yaml#/tasks.EstimationTaskInfo" - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.UnauthorizedError' - example: - detail: Unauthorized - -tasks.estimation.taskId: - get: - tags: - - task - summary: "Get selected estimation task" - description: "Get selected estimation task" - operationId: getEstimationTask - security: - - BearerAuth: [] - parameters: - - in: path - name: taskId - required: true - description: "Task identifier" - schema: {type: string} - responses: - "200": - description: "Return quantum task" - content: - application/json: - schema: - $ref: "../schemas/tasks.yaml#/tasks.EstimationTaskInfo" - "400": - description: Bad Request - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.BadRequest' - example: - detail: Bad request malformed input data - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.UnauthorizedError' - example: - detail: Unauthorized - '404': - description: Not Found - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.NotFoundError' - example: - detail: task not found - - delete: - tags: - - task - summary: "Deletes estimation task" - description: "Deletes quantum task and related result

Operation is valid only for task with status: COMPLETED, FAILED and CANCELLED. QUEUED and RUNNING tasks must be cancelled before deletion." - operationId: deleteEstimationTask - security: - - BearerAuth: [] - parameters: - - in: path - name: taskId - required: true - description: "Task identifier" - schema: {type: string} - responses: - "200": - description: "Quantum task deleted" - content: - application/json: - schema: - $ref: "../schemas/success.yaml#/success.SuccessResponse" - example: - message: Quantum task deleted - "400": - description: Bad Request - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.BadRequest' - example: - detail: Bad request malformed input data - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.UnauthorizedError' - example: - detail: Unauthorized - '404': - description: Not Found - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.NotFoundError' - example: - detail: task not found - -tasks.estimation.taskId.status: - get: - tags: - - task - summary: "Get selected estimation task's status" - description: "Get selected estimation task's status" - operationId: getEstimationTaskStatus - security: - - BearerAuth: [] - parameters: - - in: path - name: taskId - required: true - description: "Task identifier" - schema: {type: string} - responses: - "200": - description: "Return quantum task status" - content: - application/json: - schema: - $ref: '../schemas/tasks.yaml#/tasks.GetEstimationTaskStatusResponse' - "400": - description: Bad Request - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.BadRequest' - example: - detail: Bad request malformed input data - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.UnauthorizedError' - example: - detail: Unauthorized - '404': - description: Not Found - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.NotFoundError' - example: - detail: task not found - -tasks.estimation.taskId.cancel: - post: - tags: - - task - summary: "Cancel estimation task" - description: "Start a procedure to cancel quantum task.

Operation is valid only for task with status: QUEUED or RUNNING." - operationId: cancelEstimationTask - security: - - BearerAuth: [] - parameters: - - in: path - name: taskId - required: true - description: "Task identifier" - schema: {type: string} - responses: - "200": - description: "cancel request accepted" - content: - application/json: - schema: - $ref: "../schemas/success.yaml#/success.SuccessResponse" - example: - message: Task cancelled - "400": - description: Bad Request - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.BadRequest' - example: - detail: Bad request malformed input data - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.UnauthorizedError' - example: - detail: Unauthorized - '404': - description: Not Found - content: - application/json: - schema: - $ref: '../schemas/error.yaml#/error.NotFoundError' - example: - detail: task not found diff --git a/backend/oas/user/root.yaml b/backend/oas/user/root.yaml index cc66471..18de7dd 100644 --- a/backend/oas/user/root.yaml +++ b/backend/oas/user/root.yaml @@ -5,7 +5,7 @@ info: contact: name: oqtopus-team email: oqtopus-team[at]googlegroups.com - description: OQTOPUS Cloud User API. This API is used to interact with the OQTOPUS Cloud service. The API provides endpoints to manage devices, tasks, and results. + description: OQTOPUS Cloud User API. This API is used to interact with the OQTOPUS Cloud service. The API provides endpoints to manage devices, jobs, and results. license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html @@ -15,29 +15,16 @@ servers: paths: /devices: $ref: ./paths/devices.yaml#/devices - /devices/{deviceId}: + /devices/{device_id}: $ref: ./paths/devices.yaml#/devices.deviceId - /tasks/sampling: - $ref: ./paths/tasks.yaml#/tasks.sampling - /tasks/sampling/{taskId}: - $ref: ./paths/tasks.yaml#/tasks.sampling.taskId - /tasks/sampling/{taskId}/status: - $ref: ./paths/tasks.yaml#/tasks.sampling.taskId.status - /tasks/sampling/{taskId}/cancel: - $ref: ./paths/tasks.yaml#/tasks.sampling.taskId.cancel - /tasks/estimation: - $ref: ./paths/tasks.yaml#/tasks.estimation - /tasks/estimation/{taskId}: - $ref: ./paths/tasks.yaml#/tasks.estimation.taskId - /tasks/estimation/{taskId}/status: - $ref: ./paths/tasks.yaml#/tasks.estimation.taskId.status - /tasks/estimation/{taskId}/cancel: - $ref: ./paths/tasks.yaml#/tasks.estimation.taskId.cancel - /results/sampling/{taskId}: - $ref: ./paths/results.yaml#/results.sampling.taskId - /results/estimation/{taskId}: - $ref: ./paths/results.yaml#/results.estimation.taskId - + /jobs: + $ref: ./paths/jobs.yaml#/jobs + /jobs/{job_id}: + $ref: ./paths/jobs.yaml#/jobs.jobId + /jobs/{job_id}/status: + $ref: ./paths/jobs.yaml#/jobs.jobId.status + /jobs/{job_id}/cancel: + $ref: ./paths/jobs.yaml#/jobs.jobId.cancel components: securitySchemes: diff --git a/backend/oas/user/schemas/devices.yaml b/backend/oas/user/schemas/devices.yaml index d7159f3..8556b49 100644 --- a/backend/oas/user/schemas/devices.yaml +++ b/backend/oas/user/schemas/devices.yaml @@ -1,10 +1,10 @@ devices.DeviceInfo: type: object properties: - deviceId: + device_id: type: string example: "SVSim" - deviceType: + device_type: type: string enum: ["QPU", "simulator"] example: "simulator" @@ -12,36 +12,34 @@ devices.DeviceInfo: type: string enum: - ["AVAILABLE", "NOT_AVAILABLE"] - example: "AVAILABLE" - restartAt: - description: "Parameter mandatory and valid for 'NOT_AVAILABLE' devices" + ["available", "unavailable"] + example: "available" + available_at: + description: "Parameter mandatory and valid for 'unavailable' devices" type: string format: date-time example: "2022-10-19T11:45:34+09:00" - nPendingTasks: + n_pending_jobs: type: integer example: 8 - nQubits: + n_qubits: type: integer example: 39 - nNodes: - description: "Parameter valid only for 'simulator' devices" - type: integer - example: 512 - basisGates: + basis_gates: type: array items: type: string example: ["x", "y", "z", "h", "s", "sdg", "t", "tdg", "rx", "ry", "rz", "cx", "cz", "swap", "u1", "u2", "u3", "u", "p", "id", "sx", "sxdg"] - supportedInstructions: + supported_instructions: type: array items: type: string example: ["measure", "barrier", "reset"] - calibrationData: - $ref: "#/devices.CalibrationData" - calibratedAt: + device_info: + description: "json format calibration_data and n_nodes etc" + type: string + example: "{'n_nodes': 512, 'calibration_data': {'qubit_connectivity': ['(1,4)', '(4,5)', '(5,8)'], 't1': {'0': 55.51, '1': 37.03, '2': 57.13}}" + calibrated_at: description: "Parameter available only for 'QPU' devices with available calibration data" type: string format: date-time @@ -50,80 +48,17 @@ devices.DeviceInfo: type: string example: "State vector-based quantum circuit simulator" required: [ - deviceId, deviceType, status, nPendingTasks, basisGates, supportedInstructions, description + deviceId, deviceType, status, nPendingJobs, basisGates, supportedInstructions, description ] example: - - deviceId: "SVSim" - deviceType: "simulator" + - device_id: "SVSim" + device_type: "simulator" status: "AVAILABLE" - nPendingTasks: 8 - nQubits: 39 - nNodes: 512 - basisGates: ["x", "y", "z", "h", "s", "sdg", "t", "tdg", "rx", "ry", "rz", "cx", "cz", "swap", "u1", "u2", "u3", "u", "p", "id", "sx", "sxdg"] - supportedInstructions: ["measure", "barrier", "reset"] + n_pending_jobs: 8 + n_qubits: 39 + n_nodes: 512 + basis_gates: ["x", "y", "z", "h", "s", "sdg", "t", "tdg", "rx", "ry", "rz", "cx", "cz", "swap", "u1", "u2", "u3", "u", "p", "id", "sx", "sxdg"] + supported_instructions: ["measure", "barrier", "reset"] + device_info: "{'n_nodes': 512, 'calibration_data': {'qubit_connectivity': ['(1,4)', '(4,5)', '(5,8)'], 't1': {'0': 55.51, '1': 37.03, '2': 57.13}}" + calibrated_at: "2022-10-19T11:45:34+09:00" description: "State vector-based quantum circuit simulator" - -devices.CalibrationData: - description: "Calibration data available only for 'QPU' devices" - type: object - properties: - qubitConnectivity: - type: array - items: - type: string - format: "(number, number)" - example: - ["(1,4)", "(4,5)", "(5,8)"] - t1: - type: object - additionalProperties: - type: number - format: float - example: - {"0": 55.51, "1": 37.03, "2": 57.13} - t2: - type: object - additionalProperties: - type: number - format: float - example: - {"0": 99.31, "1": 111.03, "2": 30.12} - roError: - type: object - additionalProperties: - type: number - format: float - example: - {"0": 4.67e-2, "1": 1.8e-1, "2": 3.55e-1} - gateError: - type: object - additionalProperties: - type: object - additionalProperties: - type: number - format: float - example: - {"sx": {"0": 6.92e-3, "1": 2.96e-3, "2": 7.2e-2}} - measProb0As1: - type: object - additionalProperties: - type: number - format: float - example: - {"0": 6.08e-3, "1": 1.2e-2, "2": 2.48e-1} - measProb1As0: - type: object - additionalProperties: - type: number - format: float - example: - {"0": 2.81e-2, "1": 3.86e-1, "2": 8.11e-2} - gateDuration: - type: object - additionalProperties: - type: object - additionalProperties: - type: number - format: float - example: - {"sx": {"0": 29.3, "1": 50.9, "2": 45.4}} diff --git a/backend/oas/user/schemas/jobs.yaml b/backend/oas/user/schemas/jobs.yaml new file mode 100644 index 0000000..10e3c0f --- /dev/null +++ b/backend/oas/user/schemas/jobs.yaml @@ -0,0 +1,105 @@ +jobs.JobId: + type: string + example: "7af020f6-2e38-4d70-8cf0-4349650ea08c" + +jobs.GetJobStatusResponse: + description: job status + type: object + properties: + job_id: + $ref: "#/jobs.JobId" + status: + $ref: "#/jobs.JobStatus" + required: [ + job_id,status + ] + +jobs.SubmitJobResponse: + description: submit a job + type: object + properties: + job_id: + $ref: '#/jobs.JobId' + required: + - job_id + +jobs.JobStatus: + type: string + enum: ["submitted", "ready", "running", "success", "failed", "cancelled"] + example: "submitted" + +jobs.JobInfo: + type: string + example: "{'code': '{type: string, example: \"OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;\"}', 'Operator': 'X 0 Y 1 Z 5 I 2', 'result': {'00': 5020, '11': 4980}, 'transpiledCode': '', 'reason': ''}" + +jobs.TranspilerInfo: + type: string + example: "{'qubitAllocation': {'0': 12, '1': 16}, 'skipTranspilation': false, 'seedTranspilation': 873}" + +jobs.SimulatorInfo: + type: string + example: "{'nQubits': 5, 'nNodes': 12, 'nPerNode': 2, 'seedSimulation': 39058567, 'simulationOpt': {'optimizationMethod': 'light', 'optimizationBlockSize': 1, 'optimizationSwapLevel': 1}}" + +jobs.MitigationInfo: + type: string + example: "{'roErrorMitigation': 'pseudo_inverse'}" + +jobs.JobDef: + type: object + properties: + job_id: + $ref: "#/jobs.JobId" + name: + type: string + example: "Bell State Sampling" + description: + type: string + example: "Bell State Sampling Example" + device_id: + type: string + example: "Kawasaki" + shots: + type: integer + minimum: 1 + maximum: 1e7 + example: "1000" + job_type: + type: string + example: "'sampling' or 'estimation', 'sse'" + job_info: + $ref: "#/jobs.JobInfo" + transpiler_info: + $ref: "#/jobs.TranspilerInfo" + simulator_info: + $ref: "#/jobs.SimulatorInfo" + mitigation_info: + $ref: "#/jobs.MitigationInfo" + status: + $ref: "#/jobs.JobStatus" + created_at: + type: string + format: date-time + example: "2022-10-19T11:45:34+09:00" + updated_at: + type: string + format: date-time + example: "2022-10-19T11:45:34+09:00" + required: [ + device_id, shots, status, created_at + ] + example: + { + job_id: "7af020f6-2e38-4d70-8cf0-4349650ea08c", + name: "Bell State Sampling", + description: "Bell State Sampling Example", + device_id: "Kawasaki", + job_info: "{'code': '{type: string, example: \"OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;\"}', 'Operator': 'X 0 Y 1 Z 5 I 2', 'result': {'00': 5020, '11': 4980}, 'transpiled_code': '', 'reason': ''}", + transpiler_info: "{'qubit_allocation': {'0': 12, '1': 16}, 'skip_transpilation': false, 'seed_transpilation': 873}", + simulator_info: "{'n_qubits': 5, 'n_nodes': 12, 'n_per_node': 2, 'seed_simulation': 39058567, 'simulation_opt': {'optimization_method': 'light', 'optimization_block_size': 1, 'optimization_swap_level': 1}}", + mitigation_info: "{'ro_error_mitigation': 'pseudo_inverse'}", + job_type: "sampling", + shots: 1000, + status: "submitted", + created_at: "2022-10-19T11:45:34+09:00", + updated_at: "2022-10-19T11:45:34+09:00" + } diff --git a/backend/oas/user/schemas/results.yaml b/backend/oas/user/schemas/results.yaml deleted file mode 100644 index 26a5d4a..0000000 --- a/backend/oas/user/schemas/results.yaml +++ /dev/null @@ -1,73 +0,0 @@ -results.SamplingResultDef: - type: object - properties: - taskId: - $ref: "tasks.yaml#/tasks.TaskId" - status: - $ref: "#/results.ResultStatus" - result: - description: "Provided only for successful results" - type: object - additionalProperties: - type: integer - minProperties: 2 - example: - "11": 4980 - "00": 5020 - reason: - description: "Provided only for unsuccessful (failed, cancelled) results" - type: string - transpiledCode: - description: "Provided only for tasks with transpilation (tasks created with skipTranspilation=False), if traspilation was successfull" - type: string - qubitAllocation: - description: "Parameter valid only for QPU devices" - type: object - additionalProperties: - type: integer - example: - "0": 0 - "1": 4 - required: [ - taskId, status - ] - -results.ResultStatus: - type: string - enum: ["SUCCESS", "FAILURE", "CANCELLED"] - default: "SUCCESS" - example: "SUCCESS" - - -results.EstimationResultDef: - type: object - properties: - taskId: - $ref: "tasks.yaml#/tasks.TaskId" - status: - $ref: "#/results.ResultStatus" - result: - description: "Real and imaginary components of complex estimation result value
Provided only for successful results" - type: array - items: - type: number - minItems: 1 - maxItems: 2 - example: [1.5, 2.8] - reason: - description: "Provided only for unsuccessful (failed, cancelled) results" - type: string - transpiledCode: - description: "Provided only for tasks with transpilation (tasks created with skipTranspilation=False), if traspilation was successfull" - type: string - qubitAllocation: - description: "Parameter valid only for QPU devices" - type: object - additionalProperties: - type: integer - example: - "0": 0 - "1": 4 - required: [ - taskId, status - ] diff --git a/backend/oas/user/schemas/tasks.yaml b/backend/oas/user/schemas/tasks.yaml deleted file mode 100644 index f9b9b4c..0000000 --- a/backend/oas/user/schemas/tasks.yaml +++ /dev/null @@ -1,417 +0,0 @@ -tasks.TaskId: - type: string - format: uuid - example: "7af020f6-2e38-4d70-8cf0-4349650ea08c" - -tasks.GetSamplingTaskStatusResponse: - description: task status - type: object - properties: - taskId: - $ref: "#/tasks.TaskId" - status: - $ref: "#/tasks.TaskStatus" - required: [ - taskId,status - ] - -tasks.GetEstimationTaskStatusResponse: - description: task status - type: object - properties: - taskId: - $ref: "#/tasks.TaskId" - status: - $ref: "#/tasks.TaskStatus" - required: [ - taskId,status - ] - -tasks.SubmitTaskResponse: - description: submit a task - type: object - properties: - taskId: - $ref: '#/components/schemas/tasks.TaskId' - required: - - taskId - -tasks.TaskStatus: - type: string - enum: ["QUEUED", "RUNNING", "COMPLETED", "FAILED", "CANCELLING", "CANCELLED"] - example: "QUEUED" - -tasks.SamplingTaskInfo: - type: object - properties: - taskId: - $ref: "#/tasks.TaskId" - code: {type: string, example: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;"} - name: - type: string - example: "Bell State Sampling" - device: - type: string - example: "Kawasaki" - nQubits: - description: "Parameter exclusive with nNodes" - type: integer - nNodes: - description: "Parameter exclusive with nQubits
Parameter valid only for 'simulator' devices" - type: integer - example: 12 - nShots: - type: integer - minimum: 1 - maximum: 1e7 - example: "1000" - qubitAllocation: - description: "Parameter valid only for QPU devices" - type: object - additionalProperties: - type: integer - example: - "0": 12 - "1": 16 - skipTranspilation: - type: boolean - example: false - seedTranspilation: - description: "Parameter valid only if skipTranspilation is false" - type: integer - example: 873 - seedSimulation: - description: "Parameter valid only for 'simulator' devices" - type: integer - example: 39058567 - roErrorMitigation: - description: "Parameter valid only for QPU devices" - type: string - enum: ["none", "pseudo_inverse", "least_square"] - example: "pseudo_inverse" - nPerNode: - description: "Parameter valid only for simulator devices" - type: integer - minimum: 1 - example: 5 - simulationOpt: - description: "Parameter valid only for simulator devices" - type: object - example: { - optimizationMethod: "light", - optimizationBlockSize: 1, - optimizationSwapLevel: 1 - } - note: - type: string - example: "Bell State Sampling Example" - status: - $ref: "#/tasks.TaskStatus" - createdAt: - type: string - format: date-time - example: "2022-10-19T11:45:34+09:00" - required: [ - taskId, code, device, nShots, skipTranspilation, status, createdAt - ] - example: - { - taskId: "7af020f6-2e38-4d70-8cf0-4349650ea08c", - code: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;", - name: "Bell State Sampling", - device: "Kawasaki", - nNodes: 12, - nShots: 1000, - skipTranspilation: false, - seedTranspilation: 387, - seedSimulation: 39058567, - nPerNode: 2, - simulationOpt: { - optimizationMethod: "light", - optimizationBlockSize: 1, - optimizationSwapLevel: 1 - }, - note: "Bell State Sampling Example", - status: "QUEUED", - createdAt: "2022-10-19T11:45:34+09:00" - } - -tasks.SamplingTaskDef: - type: object - properties: - code: {type: string, example: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;"} - name: - type: string - example: "Bell State Sampling" - device: - type: string - example: "Kawasaki" - nQubits: - description: "Parameter exclusive with nNodes" - type: integer - nNodes: - description: "Parameter exclusive with nQubits
Parameter valid only for 'simulator' devices" - type: integer - example: 12 - nShots: - type: integer - minimum: 1 - maximum: 1e7 - example: "1000" - qubitAllocation: - description: "Parameter valid only for QPU devices" - type: object - additionalProperties: - type: integer - example: - "0": 12 - "1": 16 - skipTranspilation: - type: boolean - default: false - example: false - seedTranspilation: - description: "Parameter valid only if skipTranspilation is false" - type: integer - example: 873 - seedSimulation: - description: "Parameter valid only for 'simulator' devices" - type: integer - example: 39058567 - roErrorMitigation: - description: "Parameter valid only for QPU devices" - type: string - enum: ["none", "pseudo_inverse", "least_square"] - default: "none" - example: "pseudo_inverse" - nPerNode: - description: "Parameter valid only for simulator devices" - type: integer - minimum: 1 - example: 5 - simulationOpt: - description: "Parameter valid only for simulator devices" - type: object - example: { - optimizationMethod: "light", - optimizationBlockSize: 1, - optimizationSwapLevel: 1 - } - note: - type: string - example: "Bell State Sampling Example" - required: [ - code, device, nShots - ] - -tasks.Operator: - type: array - items: - $ref: "#/tasks.SingleOperator" - example: - [ - ["X 0 X 1", [1.5, 2.8]], - ["Y 0 Z 1", [1.2, -2e-8]], - ] - -tasks.SingleOperator: - type: array - items: - anyOf: - - type: string - description: "Pauli string" - example: "X 0 Y 1 Z 5 I 2" - - type: array - description: "Real and imaginary components of complex coef value" - items: - type: number - minItems: 2 - maxItems: 2 - example: [1.5, 2.8] - minItems: 2 - maxItems: 2 - -tasks.EstimationTaskDef: - type: object - properties: - code: {type: string, example: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;"} - name: - type: string - example: "Bell State Estimation" - device: - type: string - example: "Kawasaki" - nQubits: - description: "Parameter exclusive with nNodes" - type: integer - nNodes: - description: "Parameter exclusive with nQubits
Parameter valid only for 'simulator' devices" - type: integer - example: 12 - method: - type: string - enum: ["state_vector", "sampling"] - example: "sampling" - description: "state_vector method valid only for 'simulator' devices" - nShots: - type: integer - minimum: 1 - maximum: 1e7 - example: "1000" - description: "Parameter valid only for sampling method" - operator: - $ref: "#/tasks.Operator" - qubitAllocation: - description: "Parameter valid only for QPU devices" - type: object - additionalProperties: - type: integer - example: - "0": 12 - "1": 16 - skipTranspilation: - type: boolean - default: false - example: false - seedTranspilation: - description: "Parameter valid only if skipTranspilation is false" - type: integer - example: 873 - seedSimulation: - description: "Parameter valid only for 'simulator' devices" - type: integer - example: 39058567 - roErrorMitigation: - description: "Parameter valid only for QPU devices" - type: string - enum: ["none", "pseudo_inverse", "least_square"] - default: "none" - example: "pseudo_inverse" - nPerNode: - description: "Parameter valid only for simulator devices" - type: integer - minimum: 1 - example: 5 - simulationOpt: - description: "Parameter valid only for simulator devices" - type: object - example: { - optimizationMethod: "light", - optimizationBlockSize: 1, - optimizationSwapLevel: 1 - } - note: - type: string - example: "Bell State Estimation Example" - required: [ - code, device, method, operator - ] - -tasks.EstimationTaskInfo: - type: object - properties: - taskId: - $ref: "#/tasks.TaskId" - code: {type: string, example: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;"} - name: - type: string - example: "Bell State Estimation" - device: - type: string - example: "Kawasaki" - nQubits: - description: "Parameter exclusive with nNodes" - type: integer - nNodes: - description: "Parameter exclusive with nQubits
Parameter valid only for 'simulator' devices" - type: integer - example: 12 - method: - type: string - enum: ["state_vector", "sampling"] - example: "sampling" - description: "state_vector method valid only for 'simulator' devices" - nShots: - type: integer - minimum: 1 - maximum: 1e7 - example: "1000" - description: "Parameter valid only for sampling method" - operator: - $ref: "#/tasks.Operator" - qubitAllocation: - description: "Parameter valid only for QPU devices" - type: object - additionalProperties: - type: integer - example: - "0": 12 - "1": 16 - skipTranspilation: - type: boolean - example: false - seedTranspilation: - description: "Parameter valid only if skipTranspilation is false" - type: integer - example: 873 - seedSimulation: - description: "Parameter valid only for 'simulator' devices" - type: integer - example: 39058567 - roErrorMitigation: - description: "Parameter valid only for QPU devices" - type: string - enum: ["none", "pseudo_inverse", "least_square"] - example: "pseudo_inverse" - nPerNode: - description: "Parameter valid only for simulator devices" - type: integer - minimum: 1 - example: 5 - simulationOpt: - description: "Parameter valid only for simulator devices" - type: object - example: { - optimizationMethod: "light", - optimizationBlockSize: 1, - optimizationSwapLevel: 1 - } - note: - type: string - example: "Bell State Estimation Example" - status: - $ref: "#/tasks.TaskStatus" - createdAt: - type: string - format: date-time - example: "2022-10-19T11:45:34+09:00" - required: [ - taskId, code, device, method, operator, skipTranspilation, status, createdAt - ] - example: - { - taskId: "7af020f6-2e38-4d70-8cf0-4349650ea08c", - code: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;", - name: "Bell State Estimation", - device: "Kawasaki", - nNodes: 12, - method: "sampling", - nShots: 1000, - operator: - [ - ["X 0 X 1", [1.5, 2.8]], - ["Y 0 Z 1", [1.2, -2e-8]], - ], - skipTranspilation: false, - seedTranspilation: 387, - seedSimulation: 39058567, - nPerNode: 2, - simulationOpt: { - optimizationMethod: "light", - optimizationBlockSize: 1, - optimizationSwapLevel: 1 - }, - note: "Bell State Estimation Example", - status: "QUEUED", - createdAt: "2022-10-19T11:45:34+09:00" - } diff --git a/backend/oqtopus_cloud/common/models/__init__.py b/backend/oqtopus_cloud/common/models/__init__.py index fe533f4..99ff668 100644 --- a/backend/oqtopus_cloud/common/models/__init__.py +++ b/backend/oqtopus_cloud/common/models/__init__.py @@ -1,8 +1,7 @@ # Don't erase this definition, it is used to import all models in the api.models package # https://stackoverflow.com/questions/7478403/sqlalchemy-classes-across-files # if table has foreign key, it should be imported in the same file -__all__ = ["Device", "Task", "Base", "Result"] +__all__ = ["Device", "Job", "Base"] from oqtopus_cloud.common.models.base import Base from oqtopus_cloud.common.models.device import Device -from oqtopus_cloud.common.models.result import Result -from oqtopus_cloud.common.models.task import Task +from oqtopus_cloud.common.models.job import Job diff --git a/backend/oqtopus_cloud/common/models/device.py b/backend/oqtopus_cloud/common/models/device.py index 1641615..e40e418 100644 --- a/backend/oqtopus_cloud/common/models/device.py +++ b/backend/oqtopus_cloud/common/models/device.py @@ -4,6 +4,7 @@ from sqlalchemy import ( Enum, String, + TIMESTAMP ) from sqlalchemy.orm import Mapped, mapped_column @@ -22,13 +23,12 @@ class Device(Base): id (str): The unique identifier of the device. device_type (str): The type of the device (QPU or simulator). status (str): The status of the device (AVAILABLE or NOT_AVAILABLE). - restart_at (datetime): The date and time when the device is scheduled to restart. - pending_tasks (int): The number of pending tasks for the device. + available_at (datetime): The date and time when the device is scheduled to restart. + pending_jobs (int): The number of pending jobs for the device. n_qubits (int): The number of qubits of the device. - n_nodes (int): The number of nodes of the device. basis_gates (str): The basis gates supported by the device. instructions (str): The supported instructions of the device. - calibration_data (str): The calibration data of the device. + device_info (str): The infomation of the device. calibrated_at (datetime): The date and time when the device was last calibrated. description (str): The description of the device. """ @@ -48,25 +48,22 @@ class Device(Base): ) status: Mapped[enum.Enum] = mapped_column( Enum( - "AVAILABLE", - "NOT_AVAILABLE", + "available", + "unavailable", ), nullable=False, - default="NOT_AVAILABLE", + default="unavailable", ) - restart_at: Mapped[datetime.datetime] = mapped_column( + available_at: Mapped[datetime.datetime] = mapped_column( nullable=True, ) - pending_tasks: Mapped[int] = mapped_column( + pending_jobs: Mapped[int] = mapped_column( nullable=False, default=0, ) n_qubits: Mapped[int] = mapped_column( nullable=False, ) - n_nodes: Mapped[int] = mapped_column( - nullable=True, - ) basis_gates: Mapped[str] = mapped_column( String(256), nullable=False, @@ -75,9 +72,15 @@ class Device(Base): String(64), nullable=False, ) - calibration_data: Mapped[str] + device_info: Mapped[str] calibrated_at: Mapped[datetime.datetime] description: Mapped[str] = mapped_column( String(128), nullable=False, ) + created_at: Mapped[datetime.datetime] = mapped_column( + TIMESTAMP, + ) + updated_at: Mapped[datetime.datetime] = mapped_column( + TIMESTAMP, + ) diff --git a/backend/oqtopus_cloud/common/models/job.py b/backend/oqtopus_cloud/common/models/job.py new file mode 100644 index 0000000..86a56a5 --- /dev/null +++ b/backend/oqtopus_cloud/common/models/job.py @@ -0,0 +1,103 @@ +import datetime +import enum + +from sqlalchemy import ( + Enum, + String, + TIMESTAMP +) +from sqlalchemy.orm import Mapped, mapped_column + +from oqtopus_cloud.common.models.base import ( + Base, +) + + +class Job(Base): + """ + Represents a job in the system. + + See https://github.com/sqlalchemy/sqlalchemy/issues/5613 for the reason why we need to use nullable=True for some columns. + + Attributes: + id (str): The unique identifier of the job. + owner (str): The owner of the job. + name (str): The name of the job. + description (str): Additional notes for the job. + device_id (str): The device used for the job. + n_qubits (int): The number of qubits used in the job. + job_info(str): The information of the job. + transpiler_info(str): The information about the transpiler. + simulator_info(str): The information about the simulator. + mitigation_info(str): The information about the error mitigation. + job_type (str): The action to be performed by the job (sampling or estimation). + shots (int): The number of shots for the job. + status (str): The status of the job (submitted, ready, running, success, failed, cancelled). + created_at (datetime): The timestamp when the job was created. + updated_at(datetime): The timestamp when the job was last updated. + """ + + __tablename__ = "jobs" + + id: Mapped[str] = mapped_column( + String(64), + primary_key=True, + ) + owner: Mapped[str] = mapped_column( + String(64), + nullable=False, + ) + name: Mapped[str] = mapped_column(String(256), nullable=True) + description: Mapped[str] = mapped_column(String(1024), nullable=True) + device_id: Mapped[str] = mapped_column( + String(64), + nullable=False, + ) + job_info: Mapped[str] + transpiler_info: Mapped[str] + simulator_info: Mapped[str] + mitigation_info: Mapped[str] + job_type: Mapped[enum.Enum] = mapped_column( + Enum( + "sampling", + "estimation", + "sse", + ), + nullable=False, + ) + shots: Mapped[int] = mapped_column( + nullable=True, + ) + status: Mapped[enum.Enum] = mapped_column( + Enum( + "submitted", + "ready", + "running", + "success", + "failed", + "cancelled", + ), + nullable=False, + default="submitted", + ) + created_at: Mapped[datetime.datetime] = mapped_column( + TIMESTAMP, + ) + updated_at: Mapped[datetime.datetime] = mapped_column( + TIMESTAMP, + ) + + +class Error(Exception): + pass + + +class JobNotFound(Error): + """Exception raised when a job is not found. + + Args: + Error (type): The base error class. + + """ + + pass diff --git a/backend/oqtopus_cloud/common/models/result.py b/backend/oqtopus_cloud/common/models/result.py deleted file mode 100644 index 8f42516..0000000 --- a/backend/oqtopus_cloud/common/models/result.py +++ /dev/null @@ -1,60 +0,0 @@ -import enum -import uuid - -from sqlalchemy import ( - Enum, - ForeignKey, -) -from sqlalchemy.dialects.mysql import ( - VARBINARY, -) -from sqlalchemy.orm import Mapped, mapped_column - -from oqtopus_cloud.common.models.base import ( - Base, -) - - -class Result(Base): - """ - Represents the result of a task execution. - - See https://github.com/sqlalchemy/sqlalchemy/issues/5613 for the reason why we need to use nullable=True for some columns. - - Attributes: - task_id (bytes): The ID of the task associated with this result. - status (str): The status of the result (SUCCESS, FAILURE, CANCELLED). - result (str): The result of the task execution. - reason (str): The reason for the result (if any). - transpiled_code (str): The transpiled code generated during execution. - qubit_allocation (str): The allocation of qubits used during execution. - """ - - __tablename__ = "results" - - task_id: Mapped[uuid.UUID] = mapped_column( - VARBINARY(16), - ForeignKey( - "tasks.id", - ondelete="CASCADE", - ), - primary_key=True, - ) - status: Mapped[enum.Enum] = mapped_column( - Enum( - "SUCCESS", - "FAILURE", - "CANCELLED", - ), - nullable=False, - ) - result: Mapped[str] = mapped_column( - nullable=True, - ) - reason: Mapped[str] = mapped_column( - nullable=True, - ) - transpiled_code: Mapped[str] - qubit_allocation: Mapped[str] = mapped_column( - nullable=True, - ) diff --git a/backend/oqtopus_cloud/common/models/task.py b/backend/oqtopus_cloud/common/models/task.py deleted file mode 100644 index b042ee5..0000000 --- a/backend/oqtopus_cloud/common/models/task.py +++ /dev/null @@ -1,153 +0,0 @@ -import datetime -import enum -import uuid -from typing import Any, Literal - -from sqlalchemy import JSON, TIMESTAMP, Boolean, Enum, ForeignKey, Integer, String -from sqlalchemy.dialects.mysql import ( - VARBINARY, -) -from sqlalchemy.orm import Mapped, mapped_column - -from oqtopus_cloud.common.models.base import ( - Base, -) - - -class Task(Base): - """ - Represents a task in the system. - - See https://github.com/sqlalchemy/sqlalchemy/issues/5613 for the reason why we need to use nullable=True for some columns. - - Attributes: - id (UUID): The unique identifier of the task. - owner (str): The owner of the task. - name (str): The name of the task. - device (str): The device used for the task. - n_qubits (int): The number of qubits used in the task. - n_nodes (int): The number of nodes used in the task. - code (str): The code associated with the task. - action (str): The action to be performed by the task (sampling or estimation). - method (str): The method used for the task (state_vector or sampling). - shots (int): The number of shots for the task. - operator (str): The operator used in the task. - qubit_allocation (str): The qubit allocation for the task. - skip_transpilation (bool): Flag indicating whether transpilation should be skipped. - seed_transpilation (int): The seed used for transpilation. - seed_simulation (int): The seed used for simulation. - n_per_node (int): The number of tasks per node. - simulation_opt (str): The simulation optimization used for the task. - ro_error_mitigation (str): The error mitigation method used for readout errors. - note (str): Additional notes for the task. - status (str): The status of the task (QUEUED, QUEUED_FETCHED, RUNNING, COMPLETED, FAILED, CANCELLING, CANCELLING_FETCHED, CANCELLED). - created_at (datetime): The timestamp when the task was created. - """ - - __tablename__ = "tasks" - - id: Mapped[uuid.UUID] = mapped_column( - VARBINARY(16), - primary_key=True, - ) - owner: Mapped[str] = mapped_column( - String(64), - nullable=False, - ) - name: Mapped[str] = mapped_column(String(256), nullable=True) - device: Mapped[str] = mapped_column( - String(64), - ForeignKey("devices.id"), - nullable=False, - ) - n_qubits: Mapped[int] = mapped_column( - nullable=True, - ) - n_nodes: Mapped[int] = mapped_column( - nullable=True, - ) - code: Mapped[str] = mapped_column( - nullable=False, - ) - action: Mapped[enum.Enum] = mapped_column( - Enum( - "sampling", - "estimation", - ), - nullable=False, - ) - method: Mapped[enum.Enum] = mapped_column( - Enum( - "state_vector", - "sampling", - ), - nullable=True, - ) - shots: Mapped[int] = mapped_column( - nullable=True, - ) - operator: Mapped[str] = mapped_column( - String(1024), - nullable=True, - ) - qubit_allocation: Mapped[dict[str, int]] = mapped_column(JSON) - skip_transpilation: Mapped[bool] = mapped_column( - Boolean, - nullable=False, - default=False, - ) - seed_transpilation: Mapped[int] = mapped_column(nullable=True) - seed_simulation: Mapped[int] = mapped_column(nullable=True) - n_per_node: Mapped[int] = mapped_column( - Integer, - nullable=True, - ) - simulation_opt: Mapped[dict[str, Any]] = mapped_column(JSON, nullable=True) - ro_error_mitigation: Mapped[ - Literal[ - "none", - "pseudo_inverse", - "least_square", - ] - ] = mapped_column( - Enum( - "none", - "pseudo_inverse", - "least_square", - ), - nullable=True, - ) - note: Mapped[str] = mapped_column(String(1024), nullable=True) - status: Mapped[enum.Enum] = mapped_column( - Enum( - "QUEUED", - "QUEUED_FETCHED", - "RUNNING", - "COMPLETED", - "FAILED", - "CANCELLING", - "CANCELLING_FETCHED", - "CANCELLED", - ), - nullable=False, - default="QUEUED", - ) - created_at: Mapped[datetime.datetime] = mapped_column( - TIMESTAMP, - default="CURRENT_TIMESTAMP", - ) - - -class Error(Exception): - pass - - -class TaskNotFound(Error): - """Exception raised when a task is not found. - - Args: - Error (type): The base error class. - - """ - - pass diff --git a/backend/oqtopus_cloud/provider/lambda_function.py b/backend/oqtopus_cloud/provider/lambda_function.py index d17e8b0..895712e 100644 --- a/backend/oqtopus_cloud/provider/lambda_function.py +++ b/backend/oqtopus_cloud/provider/lambda_function.py @@ -16,10 +16,7 @@ hello as hello_router, ) from oqtopus_cloud.provider.routers import ( - results as result_router, -) -from oqtopus_cloud.provider.routers import ( - tasks as task_router, + jobs as job_router, ) from starlette.middleware.cors import CORSMiddleware @@ -43,12 +40,8 @@ tags=["device"], ) app.include_router( - task_router.router, - tags=["task"], -) -app.include_router( - result_router.router, - tags=["result"], + job_router.router, + tags=["job"], ) handler: Mangum = Mangum( diff --git a/backend/oqtopus_cloud/provider/routers/devices.py b/backend/oqtopus_cloud/provider/routers/devices.py index fd79d2a..f57d459 100644 --- a/backend/oqtopus_cloud/provider/routers/devices.py +++ b/backend/oqtopus_cloud/provider/routers/devices.py @@ -11,9 +11,9 @@ from oqtopus_cloud.provider.conf import logger, tracer from oqtopus_cloud.provider.schemas.devices import ( DeviceCalibrationUpdate, + DevicePendingJobsUpdate, DeviceDataUpdate, DeviceDataUpdateResponse, - DevicePendingTasksUpdate, DeviceStatusUpdate, ) from oqtopus_cloud.provider.schemas.errors import ( @@ -29,8 +29,8 @@ class DeviceStatus(Enum): - AVAILABLE = "AVAILABLE" - NOT_AVAILABLE = "NOT_AVAILABLE" + AVAILABLE = "available" + UNAVAILABLE = "unavailable" class DeviceType(Enum): @@ -56,44 +56,46 @@ def update_device_status( DeviceDataUpdateResponse: The response containing the update message. """ status = request.status - restart_at = request.restartAt - if status == DeviceStatus.NOT_AVAILABLE.value: - if not restart_at: - return BadRequestResponse("restartAt is required for status NOT_AVAILABLE") + available_at = request.available_at + if status == DeviceStatus.UNAVAILABLE.value: + if not available_at: + return BadRequestResponse("available_at is required for status unavailable") device.status = status # type: ignore - device.restart_at = restart_at + device.available_at = available_at else: - if restart_at: - return BadRequestResponse("restartAt is not required for status AVAILABLE") + if available_at: + return BadRequestResponse( + "available_at is not required for status available" + ) device.status = status # type: ignore - device.restart_at = None # type: ignore + device.available_at = None # type: ignore db.commit() return DeviceDataUpdateResponse(message="Device's data updated") -def update_device_pending_tasks( - device: Device, request: DevicePendingTasksUpdate, db: Session +def update_device_pending_jobs( + device: Device, request: DevicePendingJobsUpdate, db: Session ) -> DeviceDataUpdateResponse | ErrorResponse: """ - Update the number of pending tasks for a device. + Update the number of pending jobs for a device. Args: device (Device): The device to update. - request (DevicePendingTasksUpdate): The request object containing the new number of pending tasks. + request (DevicePendingJobsUpdate): The request object containing the new number of pending jobs. db (Session): The database session. Returns: DeviceDataUpdateResponse: The response object indicating the success of the update. Raises: - BadRequest: If the new number of pending tasks is not provided or is less than 0. + BadRequest: If the new number of pending jobs is not provided or is less than 0. """ - n_pending_tasks = request.nPendingTasks - if n_pending_tasks is None: - return BadRequestResponse("nPendingTasks is required") - if n_pending_tasks < 0: - return BadRequestResponse("nPendingTasks must be greater than or equal to 0") - device.pending_tasks = n_pending_tasks + n_pending_jobs = request.n_pending_jobs + if n_pending_jobs is None: + return BadRequestResponse("n_pending_jobs is required") + if n_pending_jobs < 0: + return BadRequestResponse("n_pending_jobs must be greater than or equal to 0") + device.pending_jobs = n_pending_jobs db.commit() return DeviceDataUpdateResponse(message="Device's data updated") @@ -115,22 +117,23 @@ def update_device_calibration( Raises: BadRequest: If the device is not a QPU device, or if the calibration data or calibrated timestamp is missing. """ - calibration_data = request.calibrationData - calibrated_at = request.calibratedAt + device_info = request.device_info + calibrated_at = request.calibrated_at if device.device_type != DeviceType.QPU.value: return BadRequestResponse("Calibration is only supported for QPU devices") - if calibration_data is None: - return BadRequestResponse(detail="calibrationData is required") + if device_info is None: + return BadRequestResponse(detail="device_info is required") if calibrated_at is None: - return BadRequestResponse(detail="calibratedAt is required") - device.calibration_data = calibration_data.model_dump_json() + return BadRequestResponse(detail="calibrated_at is required") + # device.calibration_data = calibration_data.model_dump_json() + device.device_info = device_info device.calibrated_at = calibrated_at db.commit() return DeviceDataUpdateResponse(message="Device's data updated") @router.patch( - "/internal/devices/{deviceId}", + "/devices/{device_id}", response_model=DeviceDataUpdateResponse, responses={ 400: {"model": Detail}, @@ -140,13 +143,13 @@ def update_device_calibration( ) @tracer.capture_method def update_device( - deviceId: str, request: DeviceDataUpdate, db: Session = Depends(get_db) + device_id: str, request: DeviceDataUpdate, db: Session = Depends(get_db) ) -> DeviceDataUpdateResponse | ErrorResponse: """ Update device information based on the given device ID and request data. Args: - deviceId (str): The ID of the device to be updated. + device_id (str): The ID of the device to be updated. request (DeviceDataUpdate): The request data containing the updated device information. db (Session, optional): The database session. Defaults to Depends(get_db). @@ -160,13 +163,13 @@ def update_device( """ logger.info("invoked update_device") try: - device = db.get(Device, deviceId) + device = db.get(Device, device_id) if device is None: - return NotFoundErrorResponse(f"deviceId={deviceId} is not found.") + return NotFoundErrorResponse(f"device_id={device_id} is not found.") if isinstance(request.root, DeviceStatusUpdate): return update_device_status(device, request.root, db) - elif isinstance(request.root, DevicePendingTasksUpdate): - return update_device_pending_tasks( + elif isinstance(request.root, DevicePendingJobsUpdate): + return update_device_pending_jobs( device, request.root, db, diff --git a/backend/oqtopus_cloud/provider/routers/jobs.py b/backend/oqtopus_cloud/provider/routers/jobs.py new file mode 100644 index 0000000..a3ba89a --- /dev/null +++ b/backend/oqtopus_cloud/provider/routers/jobs.py @@ -0,0 +1,189 @@ +import uuid +from ast import literal_eval +from datetime import datetime +from typing import Optional + +from fastapi import APIRouter, Depends +from oqtopus_cloud.common.model_util import model_to_schema_dict +from oqtopus_cloud.common.models.job import Job +from oqtopus_cloud.common.session import get_db +from oqtopus_cloud.provider.conf import logger, tracer +from oqtopus_cloud.provider.schemas.errors import ( + BadRequestResponse, + Detail, + ErrorResponse, + InternalServerErrorResponse, + NotFoundErrorResponse, +) +from oqtopus_cloud.provider.schemas.jobs import ( + JobId, + JobDef, + JobStatusUpdate, + JobStatusUpdateResponse, + UnfetchedJobsResponse, +) +from sqlalchemy import or_ +from sqlalchemy.orm import Session +from zoneinfo import ZoneInfo + +from . import LoggerRouteHandler + +router: APIRouter = APIRouter(route_class=LoggerRouteHandler) + +utc = ZoneInfo("UTC") +jst = ZoneInfo("Asia/Tokyo") + + +@router.get( + "/jobs", + response_model=list[JobDef], +) +@tracer.capture_method +def get_jobs( + device_id: str, + status: Optional[str] = None, + max_results: Optional[int] = None, + timestamp: Optional[str] = None, + db: Session = Depends(get_db), +) -> list[JobDef]: + logger.info("invoked get_jobs") + query = db.query(Job).filter(Job.device_id == device_id) + if status is not None: + query = query.filter(Job.status == status) + if timestamp is not None: + time = datetime.fromisoformat(timestamp).astimezone(jst) + query = query.filter(Job.created_at > time) + if max_results is not None: + query = query.limit(max_results) + jobs = query.all() + return [model_to_schema(job) for job in jobs] + + +@router.get( + "/jobs/unfetched", + response_model=UnfetchedJobsResponse, + responses={400: {"model": Detail}, 500: {"model": Detail}}, +) +@tracer.capture_method +def get_unfetched_jobs( + device_id: str, + status: str, + max_results: Optional[int] = None, + db: Session = Depends(get_db), +) -> UnfetchedJobsResponse | ErrorResponse: + logger.info("invoked get_job") + try: + if status not in ["submitted", "cancelling"]: + return BadRequestResponse("Invalid status") + if status == "submitted": + query = ( + db.query(Job) + .filter(Job.device_id == device_id, Job.status == "submitted") + .order_by(Job.created_at) + ) + update_status = "ready" + else: + query = ( + db.query(Job) + .filter(Job.device_id == device_id) + .order_by(Job.created_at) + ) + update_status = "cancelled" + + if max_results is not None: + query = query.limit(max_results) + + jobs = query.all() + if len(jobs) != 0: + for job in jobs: + job.status = update_status # type: ignore + db.commit() + job_ids = [JobId(job.id) for job in jobs] + return UnfetchedJobsResponse(root=job_ids) # type: ignore + except Exception as e: + return InternalServerErrorResponse(f"Error: {str(e)}") + + +@router.get( + "/jobs/{job_id}", + response_model=JobId, + responses={404: {"model": Detail}, 400: {"model": Detail}, 500: {"model": Detail}}, +) +@tracer.capture_method +def get_job( + job_id: str, + db: Session = Depends(get_db), +) -> JobId | ErrorResponse: + logger.info("invoked get_job") + try: + job = db.get(Job, job_id) + if job is None: + return NotFoundErrorResponse("Job not found") + return job.id + except Exception as e: + return InternalServerErrorResponse(f"Error: {str(e)}") + + +@router.patch( + "/jobs/{job_id}", + response_model=JobStatusUpdateResponse, + responses={404: {"model": Detail}, 400: {"model": Detail}, 500: {"model": Detail}}, +) +@tracer.capture_method +def update_job( + job_id: str, + request: JobStatusUpdate, + db: Session = Depends(get_db), +) -> JobStatusUpdateResponse | ErrorResponse: + logger.info("invoked get_job") + try: + job = ( + db.query(Job) + .filter( + Job.id == job_id, or_(Job.status == "ready", Job.status == "running") + ) + .first() + ) + if job is None: + return NotFoundErrorResponse("Job not found") + if request.status is not None: + job.status = request.status # type: ignore + db.commit() + return JobStatusUpdateResponse(message="Job status updated") + except Exception as e: + return InternalServerErrorResponse(f"Error: {str(e)}") + + +MAP_MODEL_TO_SCHEMA = { + "id": "id", + "owner": "owner", + "status": "status", + "name": "name", + "description": "description", + "device_id": "device_id", + "job_info": "job_info", + "transpiler_info": "transpiler_info", + "simulator_info": "simulator_info", + "mitigation_info": "mitigation_info", + "job_type": "job_type", + "shots": "shots", + "status": "status", + "created_at": "created_at", + "updated_at": "updated_at", +} + + +def model_to_schema(model: Job) -> JobDef: + schema_dict = model_to_schema_dict(model, MAP_MODEL_TO_SCHEMA) + + # load as json if not None. + # if schema_dict["basis_gates"]: + # schema_dict["basis_gates"] = json.loads(schema_dict["basis_gates"]) + # logger.info("schema_dict!!!:", schema_dict) + if schema_dict["created_at"]: + schema_dict["created_at"] = schema_dict["created_at"].astimezone(jst) + if schema_dict["updated_at"]: + schema_dict["updated_at"] = schema_dict["updated_at"].astimezone(jst) + + response = JobDef(**schema_dict) + return response diff --git a/backend/oqtopus_cloud/provider/routers/results.py b/backend/oqtopus_cloud/provider/routers/results.py deleted file mode 100644 index 33243d6..0000000 --- a/backend/oqtopus_cloud/provider/routers/results.py +++ /dev/null @@ -1,61 +0,0 @@ -from fastapi import APIRouter, Depends -from oqtopus_cloud.common.models.result import Result as ResultModel -from oqtopus_cloud.common.models.task import Task -from oqtopus_cloud.common.session import get_db -from oqtopus_cloud.provider.conf import logger, tracer -from oqtopus_cloud.provider.schemas.errors import ( - ConflictErrorResponse, - Detail, - ErrorResponse, - InternalServerErrorResponse, - NotFoundErrorResponse, -) -from oqtopus_cloud.provider.schemas.results import ( - CreateResultResponse, - ResultDef, -) -from sqlalchemy.orm import Session - -from . import LoggerRouteHandler - -router: APIRouter = APIRouter(route_class=LoggerRouteHandler) - - -@router.post( - "/internal/results", - response_model=CreateResultResponse, - responses={ - 404: {"model": Detail}, - 409: {"model": Detail}, - 500: {"model": Detail}, - }, -) -@tracer.capture_method -def create_result( - request: ResultDef, - db: Session = Depends(get_db), -) -> CreateResultResponse | ErrorResponse: - logger.info("invoked get_tasks") - task_id = request.taskId.root.bytes - if request.qubitAllocation is None: - qubitAllocation = None - try: - result = db.get(ResultModel, task_id) - if result is not None: - return ConflictErrorResponse("Result already exists") - task = db.get(Task, task_id) - if task is None: - return NotFoundErrorResponse("Task not found") - new_result = ResultModel( - task_id=task_id, - status=request.status.root, - result=request.result.model_dump_json(), - reason=request.reason, - transpiled_code=request.transpiledCode, - qubit_allocation=qubitAllocation, - ) - db.add(new_result) - db.commit() - return CreateResultResponse(message="success") - except Exception as e: - return InternalServerErrorResponse(str(e)) diff --git a/backend/oqtopus_cloud/provider/routers/tasks.py b/backend/oqtopus_cloud/provider/routers/tasks.py deleted file mode 100644 index 605a6c7..0000000 --- a/backend/oqtopus_cloud/provider/routers/tasks.py +++ /dev/null @@ -1,205 +0,0 @@ -import uuid -from ast import literal_eval -from datetime import datetime -from typing import Optional - -from fastapi import APIRouter, Depends -from oqtopus_cloud.common.models.task import Task -from oqtopus_cloud.common.session import get_db -from oqtopus_cloud.provider.conf import logger, tracer -from oqtopus_cloud.provider.schemas.errors import ( - BadRequestResponse, - Detail, - ErrorResponse, - InternalServerErrorResponse, - NotFoundErrorResponse, -) -from oqtopus_cloud.provider.schemas.tasks import ( - Action, - EstimationAction, - SamplingAction, - TaskId, - TaskInfo, - TaskStatusUpdate, - TaskStatusUpdateResponse, - UnfetchedTasksResponse, -) -from sqlalchemy.orm import Session -from zoneinfo import ZoneInfo - -from . import LoggerRouteHandler - -router: APIRouter = APIRouter(route_class=LoggerRouteHandler) - -utc = ZoneInfo("UTC") -jst = ZoneInfo("Asia/Tokyo") - - -def create_task_info(task: Task, status=None) -> TaskInfo: - if status is None: - status = task.status - return TaskInfo( - taskId=TaskId(task.id), - code=task.code, - device=task.device, - nQubits=task.n_qubits, - nNodes=task.n_nodes, - action=Action(recreate_task_action(task)), - qubitAllocation=task.qubit_allocation, - skipTranspilation=task.skip_transpilation, - seedTranspilation=task.seed_transpilation, - seedSimulation=task.seed_simulation, - roErrorMitigation=task.ro_error_mitigation, - nPerNode=task.n_per_node, - simulationOpt=task.simulation_opt, - status=status, # type: ignore - createdAt=task.created_at.astimezone(jst), - ) - - -@router.get( - "/internal/tasks", - response_model=list[TaskInfo], -) -@tracer.capture_method -def get_tasks( - deviceId: str, - status: Optional[str] = None, - maxResults: Optional[int] = None, - timestamp: Optional[str] = None, - db: Session = Depends(get_db), -) -> list[TaskInfo]: - logger.info("invoked get_tasks") - query = db.query(Task).filter(Task.device == deviceId) - if status is not None: - query = query.filter(Task.status == status) - if timestamp is not None: - time = datetime.fromisoformat(timestamp).astimezone(jst) - query = query.filter(Task.created_at > time) - if maxResults is not None: - query = query.limit(maxResults) - tasks = query.all() - return [create_task_info(task, status=None) for task in tasks] - - -@router.get( - "/internal/tasks/unfetched", - response_model=UnfetchedTasksResponse, - responses={400: {"model": Detail}, 500: {"model": Detail}}, -) -@tracer.capture_method -def get_unfetched_tasks( - deviceId: str, - status: str, - maxResults: Optional[int] = None, - db: Session = Depends(get_db), -) -> UnfetchedTasksResponse | ErrorResponse: - logger.info("invoked get_task") - try: - if status not in ["QUEUED", "CANCELLING"]: - return BadRequestResponse("Invalid status") - if status == "QUEUED": - query = ( - db.query(Task) - .filter(Task.device == deviceId, Task.status == "QUEUED") - .order_by(Task.created_at) - ) - update_status = "QUEUED_FETCHED" - else: - query = ( - db.query(Task).filter(Task.device == deviceId).order_by(Task.created_at) - ) - update_status = "CANCELLING_FETCHED" - - if maxResults is not None: - query = query.limit(maxResults) - - tasks = query.all() - if len(tasks) != 0: - for task in tasks: - task.status = update_status # type: ignore - db.commit() - if status == "QUEUED": - task_info = [create_task_info(task, status=update_status) for task in tasks] - return UnfetchedTasksResponse(root=task_info) # type: ignore - else: - task_ids = [TaskId(task.id) for task in tasks] - return UnfetchedTasksResponse(root=task_ids) # type: ignore - except Exception as e: - return InternalServerErrorResponse(f"Error: {str(e)}") - - -@router.get( - "/internal/tasks/{taskId}", - response_model=TaskInfo, - responses={404: {"model": Detail}, 400: {"model": Detail}, 500: {"model": Detail}}, -) -@tracer.capture_method -def get_task( - taskId: str, - db: Session = Depends(get_db), -) -> TaskInfo | ErrorResponse: - logger.info("invoked get_task") - try: - id = uuid.UUID(taskId).bytes - except Exception: - return BadRequestResponse("Invalid taskId") - try: - task = db.get(Task, id) - if task is None: - return NotFoundErrorResponse("Task not found") - return create_task_info(task) - except Exception as e: - return InternalServerErrorResponse(f"Error: {str(e)}") - - -@router.patch( - "/internal/tasks/{taskId}", - response_model=TaskStatusUpdateResponse, - responses={404: {"model": Detail}, 400: {"model": Detail}, 500: {"model": Detail}}, -) -@tracer.capture_method -def update_task( - taskId: str, - request: TaskStatusUpdate, - db: Session = Depends(get_db), -) -> TaskStatusUpdateResponse | ErrorResponse: - logger.info("invoked get_task") - try: - id = uuid.UUID(taskId).bytes - except Exception: - return BadRequestResponse("Invalid taskId") - try: - task = ( - db.query(Task) - .filter(Task.id == id, Task.status == "QUEUED_FETCHED") - .first() - ) - if task is None: - return NotFoundErrorResponse("Task not found") - if request.status is not None: - task.status = request.status # type: ignore - db.commit() - return TaskStatusUpdateResponse(message="Task status updated") - except Exception as e: - return InternalServerErrorResponse(f"Error: {str(e)}") - - -def recreate_task_action(task: Task): - action_name = task.action - action_shots = task.shots - action_method = task.method - action_operator = task.operator - if action_name == "sampling": - return SamplingAction( - name=action_name, - nShots=action_shots, - ) - else: - # :TODO: remove Enum - return EstimationAction( - name=action_name, # type: ignore - method=action_method, # type: ignore - nShots=action_shots, - operator=literal_eval(action_operator), - ) diff --git a/backend/oqtopus_cloud/provider/schemas/__init__.py b/backend/oqtopus_cloud/provider/schemas/__init__.py index d49117d..0ddc0ae 100644 --- a/backend/oqtopus_cloud/provider/schemas/__init__.py +++ b/backend/oqtopus_cloud/provider/schemas/__init__.py @@ -1,48 +1,4 @@ # generated by datamodel-codegen: # filename: openapi.yaml -# timestamp: 2024-08-29T09:11:46+00:00 -# version: 0.25.8 - -from __future__ import annotations - -from typing import Annotated, Optional - -from pydantic import BaseModel, Field - - -class CalibrationData(BaseModel): - """ - Calibration data available only for 'QPU' devices - """ - - qubitConnectivity: Annotated[ - Optional[list[str]], Field(None, examples=[["(1,4)", "(4,5)", "(5,8)"]]) - ] - t1: Annotated[ - Optional[dict[str, float]], - Field(None, examples=[{"0": 55.51, "1": 37.03, "2": 57.13}]), - ] - t2: Annotated[ - Optional[dict[str, float]], - Field(None, examples=[{"0": 99.31, "1": 111.03, "2": 30.12}]), - ] - roError: Annotated[ - Optional[dict[str, float]], - Field(None, examples=[{"0": 0.0467, "1": 0.18, "2": 0.355}]), - ] - gateError: Annotated[ - Optional[dict[str, dict[str, float]]], - Field(None, examples=[{"sx": {"0": 0.00692, "1": 0.00296, "2": 0.072}}]), - ] - measProb0As1: Annotated[ - Optional[dict[str, float]], - Field(None, examples=[{"0": 0.00608, "1": 0.012, "2": 0.248}]), - ] - measProb1As0: Annotated[ - Optional[dict[str, float]], - Field(None, examples=[{"0": 0.0281, "1": 0.386, "2": 0.0811}]), - ] - gateDuration: Annotated[ - Optional[dict[str, dict[str, float]]], - Field(None, examples=[{"sx": {"0": 29.3, "1": 50.9, "2": 45.4}}]), - ] +# timestamp: 2024-10-14T08:52:30+00:00 +# version: 0.25.9 diff --git a/backend/oqtopus_cloud/provider/schemas/devices.py b/backend/oqtopus_cloud/provider/schemas/devices.py index 1a23e3b..cb9955e 100644 --- a/backend/oqtopus_cloud/provider/schemas/devices.py +++ b/backend/oqtopus_cloud/provider/schemas/devices.py @@ -1,7 +1,7 @@ # generated by datamodel-codegen: # filename: openapi.yaml -# timestamp: 2024-08-29T09:11:46+00:00 -# version: 0.25.8 +# timestamp: 2024-10-14T08:52:30+00:00 +# version: 0.25.9 from __future__ import annotations @@ -9,37 +9,45 @@ from pydantic import AwareDatetime, BaseModel, Field, RootModel -from . import CalibrationData - class DeviceStatusUpdate(BaseModel): command: Annotated[ Literal["DeviceStatusUpdate"], Field(examples=["DeviceStatusUpdate"]) ] - status: Optional[Literal["AVAILABLE", "NOT_AVAILABLE"]] = None - restartAt: Annotated[ - Optional[AwareDatetime], Field(None, examples=["2023-09-10T14:00:00Z"]) + status: Optional[Literal["available", "unavailable"]] = None + available_at: Annotated[ + Optional[AwareDatetime], Field(None, examples=["2023-09-10T14:00:00+09:00"]) ] """ - Parameter mandatory and valid for status 'NOT_AVAILABLE' + Parameter mandatory and valid for status 'unavailable' """ -class DevicePendingTasksUpdate(BaseModel): +class DevicePendingJobsUpdate(BaseModel): command: Annotated[ - Literal["DevicePendingTasksUpdate"], - Field(examples=["DevicePendingTasksUpdate"]), + Literal["DevicePendingJobsUpdate"], Field(examples=["DevicePendingJobsUpdate"]) ] - nPendingTasks: Optional[int] = None + n_pending_jobs: Optional[int] = None class DeviceCalibrationUpdate(BaseModel): command: Annotated[ Literal["DeviceCalibrationUpdate"], Field(examples=["DeviceCalibrationUpdate"]) ] - calibrationData: Optional[CalibrationData] = None - calibratedAt: Annotated[ - Optional[AwareDatetime], Field(None, examples=["2023-09-10T14:00:00Z"]) + device_info: Annotated[ + Optional[str], + Field( + None, + examples=[ + "{'n_nodes': 512, 'calibration_data': {'qubit_connectivity': ['(1,4)', '(4,5)', '(5,8)'], 't1': {'0': 55.51, '1': 37.03, '2': 57.13}}" + ], + ), + ] + """ + json format calibration_data and n_nodes etc + """ + calibrated_at: Annotated[ + Optional[AwareDatetime], Field(None, examples=["2023-09-10T14:00:00+09:00"]) ] """ Parameter mandatory and valid if calibrationData not null @@ -48,11 +56,11 @@ class DeviceCalibrationUpdate(BaseModel): class DeviceDataUpdate( RootModel[ - Union[DeviceStatusUpdate, DevicePendingTasksUpdate, DeviceCalibrationUpdate] + Union[DeviceStatusUpdate, DevicePendingJobsUpdate, DeviceCalibrationUpdate] ] ): root: Annotated[ - Union[DeviceStatusUpdate, DevicePendingTasksUpdate, DeviceCalibrationUpdate], + Union[DeviceStatusUpdate, DevicePendingJobsUpdate, DeviceCalibrationUpdate], Field(discriminator="command"), ] diff --git a/backend/oqtopus_cloud/provider/schemas/error.py b/backend/oqtopus_cloud/provider/schemas/error.py index 73c6ead..111aceb 100644 --- a/backend/oqtopus_cloud/provider/schemas/error.py +++ b/backend/oqtopus_cloud/provider/schemas/error.py @@ -1,7 +1,7 @@ # generated by datamodel-codegen: # filename: openapi.yaml -# timestamp: 2024-08-29T09:11:46+00:00 -# version: 0.25.8 +# timestamp: 2024-10-14T08:52:30+00:00 +# version: 0.25.9 from __future__ import annotations @@ -18,7 +18,3 @@ class NotFoundError(BaseModel): class InternalServerError(BaseModel): detail: str - - -class ConflictError(BaseModel): - detail: str diff --git a/backend/oqtopus_cloud/provider/schemas/jobs.py b/backend/oqtopus_cloud/provider/schemas/jobs.py new file mode 100644 index 0000000..cf70702 --- /dev/null +++ b/backend/oqtopus_cloud/provider/schemas/jobs.py @@ -0,0 +1,101 @@ +# generated by datamodel-codegen: +# filename: openapi.yaml +# timestamp: 2024-10-14T08:52:30+00:00 +# version: 0.25.9 + +from __future__ import annotations + +from typing import Annotated, Literal, Optional, Union +from uuid import UUID + +from pydantic import AwareDatetime, BaseModel, Field, RootModel + + +class InternalJobStatus( + RootModel[ + Literal["submitted", "ready", "running", "success", "failed", "cancelled"] + ] +): + root: Annotated[ + Literal["submitted", "ready", "running", "success", "failed", "cancelled"], + Field(examples=["submitted"]), + ] + + +class JobId(RootModel[UUID]): + root: Annotated[UUID, Field(examples=["7af020f6-2e38-4d70-8cf0-4349650ea08c"])] + + +class JobInfo(RootModel[str]): + root: Annotated[ + str, + Field( + examples=[ + "{'code': '{type: string, example: \"OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;\"}', 'Operator': 'X 0 Y 1 Z 5 I 2', 'result': {'00': 5020, '11': 4980}, 'transpiled_code': '', 'reason': ''}" + ] + ), + ] + + +class TranspilerInfo(RootModel[str]): + root: Annotated[ + str, + Field( + examples=[ + "{'qubit_allocation': {'0': 12, '1': 16}, 'skip_transpilation': false, 'seed_transpilation': 873}" + ] + ), + ] + + +class SimulatorInfo(RootModel[str]): + root: Annotated[ + str, + Field( + examples=[ + "{'n_qubits': 5, 'n_nodes': 12, 'n_per_node': 2, 'seed_simulation': 39058567, 'simulation_opt': {'optimization_method': 'light', 'optimization_block_size': 1, 'optimization_swap_level': 1}}" + ] + ), + ] + + +class MitigationInfo(RootModel[str]): + root: Annotated[str, Field(examples=["{'ro_error_mitigation': 'pseudo_inverse'}"])] + + +class JobDef(BaseModel): + job_id: Optional[JobId] = None + name: Annotated[Optional[str], Field(None, examples=["Bell State Sampling"])] + description: Annotated[ + Optional[str], Field(None, examples=["Bell State Sampling Example"]) + ] + device_id: Annotated[str, Field(examples=["Kawasaki"])] + shots: Annotated[int, Field(examples=["1000"], ge=1, le=10000000)] + job_type: Annotated[ + Optional[str], Field(None, examples=["'sampling' or 'estimation', 'sse'"]) + ] + job_info: Optional[JobInfo] = None + transpiler_info: Optional[TranspilerInfo] = None + simulator_info: Optional[SimulatorInfo] = None + mitigation_info: Optional[MitigationInfo] = None + status: InternalJobStatus + created_at: Annotated[AwareDatetime, Field(examples=["2022-10-19T11:45:34+09:00"])] + updated_at: Annotated[ + Optional[AwareDatetime], Field(None, examples=["2022-10-19T11:45:34+09:00"]) + ] + + +class JobStatusUpdate(BaseModel): + status: Annotated[Literal["running"], Field(examples=["running"])] + + +class JobStatusUpdateResponse(BaseModel): + message: str + + +class InternalFetchableJobStatus(RootModel[Literal["submitted", "cancelling"]]): + root: Annotated[Literal["submitted", "cancelling"], Field(examples=["submitted"])] + + +class UnfetchedJobsResponse(RootModel[list[Union[JobDef, JobId]]]): + root: list[Union[JobDef, JobId]] diff --git a/backend/oqtopus_cloud/provider/schemas/results.py b/backend/oqtopus_cloud/provider/schemas/results.py deleted file mode 100644 index fb0b5c3..0000000 --- a/backend/oqtopus_cloud/provider/schemas/results.py +++ /dev/null @@ -1,51 +0,0 @@ -# generated by datamodel-codegen: -# filename: openapi.yaml -# timestamp: 2024-08-29T09:11:46+00:00 -# version: 0.25.8 - -from __future__ import annotations - -from typing import Annotated, Literal, Optional, Union - -from pydantic import BaseModel, Field, RootModel - -from . import tasks - - -class ResultStatus(RootModel[Literal["SUCCESS", "FAILURE", "CANCELLED"]]): - root: Annotated[ - Literal["SUCCESS", "FAILURE", "CANCELLED"], - Field("SUCCESS", examples=["SUCCESS"]), - ] = "SUCCESS" - - -class SamplingResult(RootModel[Optional[dict[str, int]]]): - root: Optional[dict[str, int]] = None - - -class EstimationResult(RootModel[list[float]]): - root: Annotated[ - list[float], Field(examples=[[1.5, 2.8]], max_length=2, min_length=2) - ] - - -class Result(RootModel[Optional[Union[SamplingResult, EstimationResult]]]): - root: Optional[Union[SamplingResult, EstimationResult]] - - -class ResultDef(BaseModel): - taskId: tasks.TaskId - status: ResultStatus - result: Result - reason: Annotated[Optional[str], Field(...)] - transpiledCode: Annotated[Optional[str], Field(...)] - qubitAllocation: Annotated[ - Optional[dict[str, Optional[int]]], Field(None, examples=[{"0": 0, "1": 4}]) - ] - """ - Parameter valid only for QPU devices - """ - - -class CreateResultResponse(BaseModel): - message: str diff --git a/backend/oqtopus_cloud/provider/schemas/tasks.py b/backend/oqtopus_cloud/provider/schemas/tasks.py deleted file mode 100644 index d7234ad..0000000 --- a/backend/oqtopus_cloud/provider/schemas/tasks.py +++ /dev/null @@ -1,165 +0,0 @@ -# generated by datamodel-codegen: -# filename: openapi.yaml -# timestamp: 2024-08-29T09:11:46+00:00 -# version: 0.25.8 - -from __future__ import annotations - -from typing import Annotated, Any, Literal, Optional, Union -from uuid import UUID - -from pydantic import AwareDatetime, BaseModel, Field, RootModel - - -class InternalTaskStatus( - RootModel[ - Literal[ - "QUEUED", - "QUEUED_FETCHED", - "RUNNING", - "COMPLETED", - "FAILED", - "CANCELLING", - "CANCELLING_FETCHED", - "CANCELLED", - ] - ] -): - root: Annotated[ - Literal[ - "QUEUED", - "QUEUED_FETCHED", - "RUNNING", - "COMPLETED", - "FAILED", - "CANCELLING", - "CANCELLING_FETCHED", - "CANCELLED", - ], - Field(examples=["QUEUED"]), - ] - - -class TaskId(RootModel[UUID]): - root: Annotated[UUID, Field(examples=["7af020f6-2e38-4d70-8cf0-4349650ea08c"])] - - -class SamplingAction(BaseModel): - name: Annotated[str, Field(examples=["sampling"], pattern="sampling")] - nShots: Annotated[int, Field(examples=["1000"], ge=1, le=10000000)] - - -class SingleOperator(RootModel[list[float]]): - root: Annotated[ - list[float], Field(examples=[[1.5, 2.8]], max_length=2, min_length=2) - ] - """ - Real and imaginary components of complex coef value - """ - - -class SingleOperatorModel(RootModel[list[Union[str, SingleOperator]]]): - root: Annotated[list[Union[str, SingleOperator]], Field(max_length=2, min_length=2)] - - -class Operator(RootModel[list[SingleOperatorModel]]): - root: Annotated[ - list[SingleOperatorModel], - Field(examples=[[["X 0 X 1", [1.5, 2.8]], ["Y 0 Z 1", [1.2, -2e-08]]]]), - ] - - -class EstimationAction(BaseModel): - name: Annotated[str, Field(examples=["estimation"], pattern="estimation")] - method: Annotated[Literal["state_vector", "sampling"], Field(examples=["sampling"])] - """ - state_vector method valid only for 'simulator' devices - """ - nShots: Annotated[Optional[int], Field(None, examples=["1000"], ge=1, le=10000000)] - """ - Parameter valid only for sampling method - """ - operator: Operator - - -class Action(RootModel[Union[SamplingAction, EstimationAction]]): - root: Union[SamplingAction, EstimationAction] - - -class TaskInfo(BaseModel): - taskId: TaskId - code: Annotated[ - str, - Field( - examples=[ - "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;" - ] - ), - ] - device: Annotated[str, Field(examples=["Kawasaki"])] - nQubits: Annotated[Optional[int], Field(None, examples=[None])] - nNodes: Annotated[Optional[int], Field(None, examples=[12])] - """ - Parameter valid only for 'simulator' devices - """ - action: Action - qubitAllocation: Annotated[ - Optional[dict[str, int]], Field(None, examples=[{"0": 12, "1": 16}]) - ] - """ - Parameter valid only for QPU devices - """ - skipTranspilation: Annotated[bool, Field(examples=[False])] - seedTranspilation: Annotated[Optional[int], Field(None, examples=[873])] - """ - Parameter valid only if skipTranspilation is false - """ - seedSimulation: Annotated[Optional[int], Field(None, examples=[39058567])] - """ - Parameter valid only for 'simulator' devices - """ - roErrorMitigation: Annotated[ - Optional[Literal["none", "pseudo_inverse", "least_square"]], - Field(None, examples=["pseudo_inverse"]), - ] - """ - Parameter valid only for QPU devices - """ - nPerNode: Annotated[Optional[int], Field(None, examples=[5], ge=1)] - """ - Parameter valid only for simulator devices - """ - simulationOpt: Annotated[ - Optional[dict[str, Any]], - Field( - None, - examples=[ - { - "optimizationMethod": "light", - "optimizationBlockSize": 1, - "optimizationSwapLevel": 1, - } - ], - ), - ] - """ - Parameter valid only for simulator devices - """ - status: InternalTaskStatus - createdAt: Annotated[AwareDatetime, Field(examples=["2022-10-19 11:45:34"])] - - -class TaskStatusUpdate(BaseModel): - status: Annotated[Literal["RUNNING"], Field(examples=["RUNNING"])] - - -class TaskStatusUpdateResponse(BaseModel): - message: str - - -class InternalFetchableTaskStatus(RootModel[Literal["QUEUED", "CANCELLING"]]): - root: Annotated[Literal["QUEUED", "CANCELLING"], Field(examples=["QUEUED"])] - - -class UnfetchedTasksResponse(RootModel[list[Union[TaskInfo, TaskId]]]): - root: list[Union[TaskInfo, TaskId]] diff --git a/backend/oqtopus_cloud/user/lambda_function.py b/backend/oqtopus_cloud/user/lambda_function.py index ea47499..a9e67ef 100644 --- a/backend/oqtopus_cloud/user/lambda_function.py +++ b/backend/oqtopus_cloud/user/lambda_function.py @@ -15,10 +15,7 @@ devices as device_router, ) from oqtopus_cloud.user.routers import ( - results as result_router, -) -from oqtopus_cloud.user.routers import ( - tasks as task_router, + jobs as job_router, ) app: FastAPI = FastAPI() @@ -37,12 +34,8 @@ tags=["device"], ) app.include_router( - task_router.router, - tags=["task"], -) -app.include_router( - result_router.router, - tags=["result"], + job_router.router, + tags=["job"], ) handler: Mangum = Mangum( diff --git a/backend/oqtopus_cloud/user/routers/devices.py b/backend/oqtopus_cloud/user/routers/devices.py index cfb1b64..2940bc7 100644 --- a/backend/oqtopus_cloud/user/routers/devices.py +++ b/backend/oqtopus_cloud/user/routers/devices.py @@ -11,7 +11,6 @@ ) from oqtopus_cloud.user.conf import logger, tracer from oqtopus_cloud.user.schemas.devices import ( - CalibrationData, DeviceInfo, ) from oqtopus_cloud.user.schemas.errors import ( @@ -33,11 +32,11 @@ "/devices", response_model=list[DeviceInfo], responses={500: {"model": Detail}} ) @tracer.capture_method -def list_devices( +def get_devices( db: Session = Depends(get_db), ) -> list[DeviceInfo] | ErrorResponse: try: - logger.info("invoked list_devices") + logger.info("invoked get_devices") devices = db.query(Device).all() return [model_to_schema(device) for device in devices] except Exception as e: @@ -46,19 +45,19 @@ def list_devices( @router.get( - "/devices/{deviceId}", + "/devices/{device_id}", response_model=DeviceInfo, responses={404: {"model": Detail}, 500: {"model": Detail}}, ) @tracer.capture_method def get_device( - deviceId: str, + device_id: str, db: Session = Depends(get_db), ) -> DeviceInfo | ErrorResponse: """_summary_ Args: - deviceId (str): _description_ + device_id (str): _description_ db (Session, optional): _description_. Defaults to Depends(get_db). Returns: @@ -66,13 +65,13 @@ def get_device( """ # TODO implement error handling try: - device = db.query(Device).where(Device.id == deviceId).first() + device = db.query(Device).where(Device.id == device_id).first() logger.info("invoked get_device") if device: response = model_to_schema(device) return response else: - detail = f"deviceId={deviceId} is not found." + detail = f"device_id={device_id} is not found." logger.info(detail) return NotFoundErrorResponse(detail=detail) except Exception as e: @@ -81,17 +80,16 @@ def get_device( MAP_MODEL_TO_SCHEMA = { - "id": "deviceId", - "device_type": "deviceType", + "id": "device_id", + "device_type": "device_type", "status": "status", - "restart_at": "restartAt", - "pending_tasks": "nPendingTasks", - "n_qubits": "nQubits", - "n_nodes": "nNodes", - "basis_gates": "basisGates", - "instructions": "supportedInstructions", - "calibration_data": "calibrationData", - "calibrated_at": "calibratedAt", + "available_at": "available_at", + "pending_jobs": "n_pending_jobs", + "n_qubits": "n_qubits", + "basis_gates": "basis_gates", + "instructions": "supported_instructions", + "device_info": "device_info", + "calibrated_at": "calibrated_at", "description": "description", } @@ -100,18 +98,18 @@ def model_to_schema(model: Device) -> DeviceInfo: schema_dict = model_to_schema_dict(model, MAP_MODEL_TO_SCHEMA) # load as json if not None. - if schema_dict["basisGates"]: - schema_dict["basisGates"] = json.loads(schema_dict["basisGates"]) - if schema_dict["supportedInstructions"]: - schema_dict["supportedInstructions"] = json.loads( - schema_dict["supportedInstructions"] + if schema_dict["basis_gates"]: + schema_dict["basis_gates"] = json.loads(schema_dict["basis_gates"]) + if schema_dict["supported_instructions"]: + schema_dict["supported_instructions"] = json.loads( + schema_dict["supported_instructions"] ) - if schema_dict["calibrationData"]: - calibration_data_dict = json.loads(schema_dict["calibrationData"]) - schema_dict["calibrationData"] = CalibrationData(**calibration_data_dict) - if schema_dict["restartAt"]: - schema_dict["restartAt"] = schema_dict["restartAt"].astimezone(jst) - if schema_dict["calibratedAt"]: - schema_dict["calibratedAt"] = schema_dict["calibratedAt"].astimezone(jst) + # if schema_dict["device_info"]: + # calibration_data_dict = json.loads(schema_dict["device_info"]) + # schema_dict["device_info"] = CalibrationData(**calibration_data_dict) + if schema_dict["available_at"]: + schema_dict["available_at"] = schema_dict["available_at"].astimezone(jst) + if schema_dict["calibrated_at"]: + schema_dict["calibrated_at"] = schema_dict["calibrated_at"].astimezone(jst) response = DeviceInfo(**schema_dict) return response diff --git a/backend/oqtopus_cloud/user/routers/jobs.py b/backend/oqtopus_cloud/user/routers/jobs.py new file mode 100644 index 0000000..3b3cbb0 --- /dev/null +++ b/backend/oqtopus_cloud/user/routers/jobs.py @@ -0,0 +1,282 @@ +import json + +import uuid +from ast import literal_eval +from datetime import datetime +from typing import Any, Literal, Optional, Tuple + +from fastapi import ( + APIRouter, + Depends, +) +from fastapi import Request as Event +from pydantic import ValidationError +from sqlalchemy import select +from sqlalchemy.orm import ( + Session, +) +from zoneinfo import ZoneInfo + +from oqtopus_cloud.common.model_util import model_to_schema_dict +from oqtopus_cloud.common.models.device import Device +from oqtopus_cloud.common.models.job import Job +from oqtopus_cloud.common.session import ( + get_db, +) +from oqtopus_cloud.user.conf import logger, tracer +from oqtopus_cloud.user.schemas.jobs import GetJobStatusResponse +from oqtopus_cloud.user.schemas.errors import ( + BadRequestResponse, + Detail, + ErrorResponse, + InternalServerErrorResponse, + NotFoundErrorResponse, +) +from oqtopus_cloud.user.schemas.success import SuccessResponse +from oqtopus_cloud.user.schemas.jobs import SubmitJobResponse, JobId, JobStatus, JobDef + +from . import LoggerRouteHandler + +jst = ZoneInfo("Asia/Tokyo") +utc = ZoneInfo("UTC") + +router: APIRouter = APIRouter(route_class=LoggerRouteHandler) + + +class BadRequest(Exception): + def __init__(self, detail: str): + self.detail = detail + + +@router.get( + "/jobs", + response_model=list[JobDef], + responses={500: {"model": Detail}}, +) +@tracer.capture_method +def get_jobs( + event: Event, + db: Session = Depends(get_db), +) -> list[JobDef] | ErrorResponse: + try: + owner = event.state.owner + logger.info("invoked!", extra={"owner": owner}) + stmt = select(Job).filter(Job.owner == owner).order_by(Job.created_at) + jobs = db.scalars(stmt).all() + return [model_to_schema(job) for job in jobs] + except Exception as e: + logger.info(f"error: {str(e)}") + return InternalServerErrorResponse(detail=str(e)) + + +def validate_name(request: JobDef) -> str | None: + if request.name is not None: + return request.name + return "" + + +def validate_description( + request: JobDef, +) -> str | None: + return request.description if (request.description is not None) else "" + + +@router.post( + "/jobs", + response_model=SubmitJobResponse, + responses={400: {"model": Detail}, 500: {"model": Detail}}, +) +@tracer.capture_method +def submit_jobs( + event: Event, + request: JobDef, + db: Session = Depends(get_db), +) -> SubmitJobResponse | ErrorResponse: + try: + device = db.get(Device, request.device_id) # type: ignore + if device is None: + return BadRequestResponse(detail="device not found") + owner = event.state.owner + logger.info("invoked!", extra={"owner": owner}) + if device.status != "available": + return BadRequestResponse(f"device {device.id} is not available") + + # NOTE: method and operator is validated by pydantic + shots = request.shots + # name is optional + name = validate_name(request) + # description is optional + description = validate_description(request) + + job = Job( + # TODO: UUIDv7 + id=uuid.uuid4(), + owner=owner, + name=name, + description=description, + device_id=request.device_id, + job_info=request.job_info, + transpiler_info=request.transpiler_info, + simulator_info=request.simulator_info, + mitigation_info=request.mitigation_info, + job_type=request.job_type, + shots=shots, + created_at=datetime.now(), + ) + db.add(job) + db.commit() + return SubmitJobResponse(job_id=JobId(job.id)) + except Exception as e: + logger.info(f"error: {str(e)}") + return InternalServerErrorResponse(detail=str(e)) + + +@router.get( + "/jobs/{job_id}", + response_model=JobDef, + responses={400: {"model": Detail}, 404: {"model": Detail}, 500: {"model": Detail}}, +) +@tracer.capture_method +def get_job( + event: Event, + job_id: str, + db: Session = Depends(get_db), +) -> JobDef | ErrorResponse: + try: + owner = event.state.owner + logger.info("invoked!", extra={"owner": owner, "job_id": job_id}) + job = db.query(Job).filter(Job.id == job_id, Job.owner == owner).first() + if job is None: + return NotFoundErrorResponse(detail="job not found with the given id") + return model_to_schema(job) + except Exception as e: + logger.info(f"error: {str(e)}") + return InternalServerErrorResponse(detail=str(e)) + + +@router.delete( + "/jobs/{job_id}", + response_model=SuccessResponse, + responses={400: {"model": Detail}, 404: {"model": Detail}, 500: {"model": Detail}}, +) +@tracer.capture_method +def delete_job( + event: Event, + job_id: str, + db: Session = Depends(get_db), +) -> SuccessResponse | ErrorResponse: + try: + owner = event.state.owner + logger.info("invoked!", extra={"owner": owner}) + job = db.get(Job, job_id) + + if job is None: + return NotFoundErrorResponse(detail="job not found with the given id") + + if job.owner != owner or job.status not in ["success", "failed", "cancelled"]: + return NotFoundErrorResponse( + detail=f"{job_id} job is not in valid status for deletion (valid statuses for deletion: 'success', 'failed' and 'cancelled')" + ) + + db.delete(job) + db.commit() + return SuccessResponse(message="job deleted") + except Exception as e: + logger.info(f"error: {str(e)}") + return InternalServerErrorResponse(detail=str(e)) + + +@router.get( + "/jobs/{job_id}/status", + response_model=GetJobStatusResponse, + responses={400: {"model": Detail}, 404: {"model": Detail}, 500: {"model": Detail}}, +) +@tracer.capture_method +def get_job_status( + event: Event, + job_id: str, + db: Session = Depends(get_db), +) -> GetJobStatusResponse | ErrorResponse: + owner = event.state.owner + logger.info("invoked!", extra={"owner": owner}) + job = ( + db.query(Job.id, Job.status) + .filter( + Job.id == job_id, + Job.owner == owner, + ) + .first() + ) + if job is None: + return NotFoundErrorResponse(detail="job not found with the given id") + return GetJobStatusResponse(job_id=JobId(job_id), status=JobStatus(job.status)) + + +@router.post( + "/jobs/{job_id}/cancel", + response_model=SuccessResponse, + responses={400: {"model": Detail}, 404: {"model": Detail}, 500: {"model": Detail}}, +) +@tracer.capture_method +def cancel_job( + event: Event, + job_id: str, + db: Session = Depends(get_db), +) -> SuccessResponse | ErrorResponse: + try: + owner = event.state.owner + logger.info("invoked!", extra={"owner": owner}) + + job = db.get(Job, job_id) + + if job is None: + return NotFoundErrorResponse(detail="job not found with the given id") + if job.owner != owner or job.status not in ["ready", "submitted", "running"]: + return NotFoundErrorResponse( + detail=f"{job_id} job is not in valid status for cancellation (valid statuses for cancellation: 'ready', 'submitted' and 'running')" + ) + if job.status in ["submitted", "ready", "running"]: + logger.info( + "job is in submitted or ready or running state, so it will be marked as cancelling" + ) + job.status = "cancelled" + db.commit() + return SuccessResponse(message="cancel request accepted") + except Exception as e: + logger.info(f"error: {str(e)}") + return InternalServerErrorResponse(detail=str(e)) + + +MAP_MODEL_TO_SCHEMA = { + "id": "id", + "owner": "owner", + "status": "status", + "name": "name", + "description": "description", + "device_id": "device_id", + "job_info": "job_info", + "transpiler_info": "transpiler_info", + "simulator_info": "simulator_info", + "mitigation_info": "mitigation_info", + "job_type": "job_type", + "shots": "shots", + "status": "status", + "created_at": "created_at", + "updated_at": "updated_at", +} + + +def model_to_schema(model: Job) -> JobDef: + schema_dict = model_to_schema_dict(model, MAP_MODEL_TO_SCHEMA) + + # load as json if not None. + # if schema_dict["basis_gates"]: + # schema_dict["basis_gates"] = json.loads(schema_dict["basis_gates"]) + # logger.info("schema_dict!!!:", schema_dict) + if schema_dict["created_at"]: + schema_dict["created_at"] = schema_dict["created_at"].astimezone(jst) + if schema_dict["updated_at"]: + schema_dict["updated_at"] = schema_dict["updated_at"].astimezone(jst) + + response = JobDef(**schema_dict) + return response diff --git a/backend/oqtopus_cloud/user/routers/results.py b/backend/oqtopus_cloud/user/routers/results.py deleted file mode 100644 index 7a4b5e5..0000000 --- a/backend/oqtopus_cloud/user/routers/results.py +++ /dev/null @@ -1,178 +0,0 @@ -import uuid -from ast import literal_eval - -from fastapi import APIRouter, Depends -from fastapi import Request as Event -from pydantic import ValidationError -from sqlalchemy.orm import Session -from zoneinfo import ZoneInfo - -from oqtopus_cloud.common.models.result import Result as ResultModel -from oqtopus_cloud.common.models.task import Task -from oqtopus_cloud.common.session import get_db -from oqtopus_cloud.user.conf import logger, tracer -from oqtopus_cloud.user.schemas.errors import ( - BadRequestResponse, - Detail, - ErrorResponse, - InternalServerErrorResponse, - NotFoundErrorResponse, -) -from oqtopus_cloud.user.schemas.results import ( - EstimationResultDef, - ResultStatus, - SamplingResultDef, -) -from oqtopus_cloud.user.schemas.tasks import TaskId - -from . import LoggerRouteHandler - -router: APIRouter = APIRouter(route_class=LoggerRouteHandler) -# jst = ZoneInfo("Asia/Tokyo") -tz = ZoneInfo("UTC") - - -def create_sampling_result(result_model: ResultModel) -> SamplingResultDef: - print(result_model.task_id) - print(result_model.status) - print(result_model.result) - print(result_model.reason) - print(result_model.transpiled_code) - print(result_model.qubit_allocation) - if result_model.status == "SUCCESS": - result = literal_eval(result_model.result) - reason = None - else: - result = None - reason = result_model.reason - if result_model.qubit_allocation is not None: - qubit_allocation = literal_eval(result_model.qubit_allocation) - else: - qubit_allocation = None - return SamplingResultDef( - taskId=TaskId(result_model.task_id), - status=ResultStatus(root=result_model.status), # type: ignore - result=result, - reason=reason, - transpiledCode=result_model.transpiled_code, - qubitAllocation=qubit_allocation, - ) - - -def create_estimation_result(result_model: ResultModel) -> EstimationResultDef: - print(result_model.task_id) - print(result_model.status) - print(result_model.result) - print(result_model.reason) - print(result_model.transpiled_code) - print(result_model.qubit_allocation) - if result_model.status == "SUCCESS": - result = literal_eval(result_model.result) - reason = None - else: - result = None - reason = result_model.reason - if result_model.qubit_allocation is not None: - qubit_allocation = literal_eval(result_model.qubit_allocation) - else: - qubit_allocation = None - return EstimationResultDef( - taskId=TaskId(result_model.task_id), - status=ResultStatus(root=result_model.status), # type: ignore - result=result, - reason=reason, - transpiledCode=result_model.transpiled_code, - qubitAllocation=qubit_allocation, - ) - - -@router.get( - "/results/sampling/{taskId}", - response_model=SamplingResultDef, - responses={ - 404: {"model": Detail}, - 409: {"model": Detail}, - 500: {"model": Detail}, - }, -) -@tracer.capture_method -def get_sampling_result( - event: Event, - taskId: str, - db: Session = Depends(get_db), -) -> SamplingResultDef | ErrorResponse: - logger.info("invoked get_tasks") - try: - task_id = uuid.UUID(taskId).bytes - except ValidationError: - logger.info(f"invalid task id: {taskId}") - return BadRequestResponse(detail="invalid task id") - try: - owner = event.state.owner - logger.info("invoked!", extra={"owner": owner}) - print(task_id) - task = db.query(Task).filter(Task.id == task_id).first() - print(task) - res = db.query(ResultModel).filter(ResultModel.task_id == task_id).first() - print(res) - result = ( - db.query(ResultModel) - .join(Task, ResultModel.task_id == Task.id) - .filter( - Task.owner == owner, - ResultModel.task_id == task_id, - Task.action == "sampling", - ) - .first() - ) - if result is None: - return NotFoundErrorResponse("result not found") - return create_sampling_result(result) - except Exception as e: - return InternalServerErrorResponse(str(e)) - - -@router.get( - "/results/estimation/{taskId}", - response_model=EstimationResultDef, - responses={ - 404: {"model": Detail}, - 409: {"model": Detail}, - 500: {"model": Detail}, - }, -) -@tracer.capture_method -def get_estimation_result( - event: Event, - taskId: str, - db: Session = Depends(get_db), -) -> EstimationResultDef | ErrorResponse: - logger.info("invoked get_tasks") - try: - task_id = uuid.UUID(taskId).bytes - except ValidationError: - logger.info(f"invalid task id: {taskId}") - return BadRequestResponse(detail="invalid task id") - try: - owner = event.state.owner - logger.info("invoked!", extra={"owner": owner}) - print(task_id) - task = db.query(Task).filter(Task.id == task_id).first() - print(task) - res = db.query(ResultModel).filter(ResultModel.task_id == task_id).first() - print(res) - result = ( - db.query(ResultModel) - .join(Task, ResultModel.task_id == Task.id) - .filter( - Task.owner == owner, - ResultModel.task_id == task_id, - Task.action == "estimation", - ) - .first() - ) - if result is None: - return NotFoundErrorResponse("result not found") - return create_estimation_result(result) - except Exception as e: - return InternalServerErrorResponse(str(e)) diff --git a/backend/oqtopus_cloud/user/routers/tasks.py b/backend/oqtopus_cloud/user/routers/tasks.py deleted file mode 100644 index 83253d6..0000000 --- a/backend/oqtopus_cloud/user/routers/tasks.py +++ /dev/null @@ -1,892 +0,0 @@ -import re -import uuid -from ast import literal_eval -from datetime import datetime -from typing import Any, Literal, Optional, Tuple - -from fastapi import ( - APIRouter, - Depends, -) -from fastapi import Request as Event -from pydantic import ValidationError -from sqlalchemy.orm import ( - Session, -) -from zoneinfo import ZoneInfo - -from oqtopus_cloud.common.models.device import Device -from oqtopus_cloud.common.models.result import Result -from oqtopus_cloud.common.models.task import Task -from oqtopus_cloud.common.session import ( - get_db, -) -from oqtopus_cloud.user.conf import logger, tracer -from oqtopus_cloud.user.schemas.errors import ( - BadRequestResponse, - Detail, - ErrorResponse, - InternalServerErrorResponse, - NotFoundErrorResponse, -) -from oqtopus_cloud.user.schemas.success import SuccessResponse -from oqtopus_cloud.user.schemas.tasks import ( - EstimationTaskDef, - EstimationTaskInfo, - GetEstimationTaskStatusResponse, - GetSamplingTaskStatusResponse, - Operator, - SamplingTaskDef, - SamplingTaskInfo, - SubmitTaskResponse, - TaskId, - TaskStatus, -) - -from . import LoggerRouteHandler - -jst = ZoneInfo("Asia/Tokyo") -utc = ZoneInfo("UTC") - -router: APIRouter = APIRouter(route_class=LoggerRouteHandler) - - -class BadRequest(Exception): - def __init__(self, detail: str): - self.detail = detail - - -def create_sampling_task_info(task: Task) -> SamplingTaskInfo: - status = task.status - if task.status == "QUEUED_FETCHED": - status = "QUEUED" - elif task.status == "CANCELIING_FETCHED": - status = "CANCELLING" - return SamplingTaskInfo( - taskId=TaskId(task.id), - code=task.code, - name=task.name, - device=task.device, - nQubits=task.n_qubits, - nNodes=task.n_nodes, - nShots=task.shots, - qubitAllocation=task.qubit_allocation, - skipTranspilation=task.skip_transpilation, - seedTranspilation=task.seed_transpilation, - seedSimulation=task.seed_simulation, - roErrorMitigation=task.ro_error_mitigation, - nPerNode=task.n_per_node, - simulationOpt=task.simulation_opt, - note=task.note, - status=TaskStatus(root=status), # type: ignore - createdAt=task.created_at.astimezone(jst), - ) - - -def serialize_operator(operator: Operator) -> str | BadRequestResponse: - pauli_regex = re.compile("([X|Y|Z|I]\\s+\\d+)(\\s+[X|Y|Z|I]\\s+\\d+)*\\s*$") - ops = literal_eval(operator.model_dump_json()) - if not isinstance(ops, list) or len(ops) == 0: - return BadRequestResponse(detail=f"Malformed operator format: {str(ops)}") - for op in ops: - if not isinstance(op, list) or len(op) != 2: - return BadRequestResponse(f"Malformed operator format: {str(op)}") - pauli_str = op[0] - if not isinstance(pauli_str, str): - return BadRequestResponse( - f"Malformed operator format: malformed Pauli string: {str(op)}" - ) - if not pauli_regex.match(pauli_str): - return BadRequestResponse( - f"Malformed operator format: malformed Pauli string: {str(op)}" - ) - coef = op[1] - try: - if isinstance(coef, list): - if len(coef) == 2: - op[1] = [float(coef[0]), float(coef[1])] - elif len(coef) == 1: - op[1] = [float(coef[0]), 0.0] - else: - return BadRequestResponse( - f"Malformed operator format: malformed coef value: {str(op)}" - ) - else: - op[1] = [float(coef), 0.0] - except (TypeError, ValueError): - return BadRequestResponse( - f"Malformed operator format: malformed coef value: {str(op)}" - ) - return str(ops) - - -def create_estimation_task_info(task: Task) -> EstimationTaskInfo: - status = task.status - if task.status == "QUEUED_FETCHED": - status = "QUEUED" - elif task.status == "CANCELIING_FETCHED": - status = "CANCELLING" - - return EstimationTaskInfo( - taskId=TaskId(task.id), - code=task.code, - name=task.name, - device=task.device, - nQubits=task.n_qubits, - nNodes=task.n_nodes, - method=task.method, # type: ignore - nShots=task.shots, - operator=Operator(literal_eval(task.operator)), # type: ignore - qubitAllocation=task.qubit_allocation, - skipTranspilation=task.skip_transpilation, - seedTranspilation=task.seed_transpilation, - seedSimulation=task.seed_simulation, - roErrorMitigation=task.ro_error_mitigation, - nPerNode=task.n_per_node, - simulationOpt=task.simulation_opt, - note=task.note, - status=TaskStatus(root=status), # type: ignore - createdAt=task.created_at.astimezone(jst), - ) - - -@router.get( - "/tasks/sampling", - response_model=list[SamplingTaskInfo], - responses={500: {"model": Detail}}, -) -@tracer.capture_method -def get_sampling_tasks( - event: Event, - db: Session = Depends(get_db), -) -> list[SamplingTaskInfo] | ErrorResponse: - try: - owner = event.state.owner - logger.info("invoked!", extra={"owner": owner}) - tasks = ( - db.query(Task) - .filter(Task.action == "sampling", Task.owner == owner) - .order_by(Task.created_at) - .all() - ) - return [create_sampling_task_info(task) for task in tasks] - except Exception as e: - logger.info(f"error: {str(e)}") - return InternalServerErrorResponse(detail=str(e)) - - -def validate_name(request: SamplingTaskDef | EstimationTaskDef) -> str | None: - if request.name is not None: - request.name - return None - - -def validate_qubit_allocation( - request: SamplingTaskDef | EstimationTaskDef, device_info: Device -) -> dict[str, int] | ErrorResponse | None: - if request.qubitAllocation is not None: - if device_info.device_type != "QPU": - return BadRequestResponse( - detail="qubitAllocation is valid only for QPU devices" - ) - return request.qubitAllocation - return None - - -def validate_skip_transpilation(request: SamplingTaskDef | EstimationTaskDef) -> bool: - return ( - request.skipTranspilation if (request.skipTranspilation is not None) else False - ) - - -def validate_seed_transpilation( - request: SamplingTaskDef | EstimationTaskDef, -) -> int | ErrorResponse | None: - if request.seedTranspilation is not None: - if request.skipTranspilation: - return BadRequestResponse( - detail="seedTranspilation is valid only for transpilation enabled tasks" - ) - return request.seedTranspilation - return None - - -def validate_seed_simulation( - request: SamplingTaskDef | EstimationTaskDef, device_info: Device -) -> int | ErrorResponse | None: - if request.seedSimulation is not None: - if device_info.device_type != "simulator": - return BadRequestResponse( - detail="seedSimulation is valid only for simulator devices" - ) - return request.seedSimulation - return None - - -def validate_ro_error_mitigation( - request: SamplingTaskDef | EstimationTaskDef, device_info: Device -) -> Literal["none", "pseudo_inverse", "least_square"] | ErrorResponse | None: - if request.roErrorMitigation is not None and request.roErrorMitigation != "none": - if device_info.device_type != "QPU": - return BadRequestResponse( - detail="roErrorMitigation is valid only for QPU devices" - ) - return request.roErrorMitigation - if device_info.device_type != "QPU": - return None - return "none" - - -def validate_n_per_node( - request: SamplingTaskDef | EstimationTaskDef, device_info: Device -) -> int | ErrorResponse | None: - if request.nPerNode is not None: - if device_info.device_type != "simulator": - return BadRequestResponse( - detail="nPerNode is valid only for simulator devices" - ) - return request.nPerNode - if device_info.device_type != "simulator": - return None - return 1 - - -def validate_simulation_opt( - request: SamplingTaskDef | EstimationTaskDef, device_info: Device -) -> dict[str, Any] | ErrorResponse | None: - if request.simulationOpt is not None: - if device_info.device_type != "simulator": - return BadRequestResponse( - detail="simulationOpt is valid only for simulator devices" - ) - return request.simulationOpt - return None - - -def validate_note( - request: SamplingTaskDef | EstimationTaskDef, -) -> str | None: - return request.note if (request.note is not None) else None - - -def get_resources( - request: SamplingTaskDef | EstimationTaskDef, device_info: Device -) -> Tuple[Optional[int], Optional[int]] | BadRequestResponse: - n_qubits = None - n_nodes = None - - if device_info.device_type == "simulator": - if (request.nQubits is not None) and (request.nNodes is not None): - return BadRequestResponse( - detail="nQubits and nNodes parameters are exclusive" - ) - - if request.nQubits is not None: - n_qubits = request.nQubits - if n_qubits > device_info.n_qubits: - return BadRequestResponse( - detail=f"Requested nQubits: {n_qubits} exceeds limit for device {device_info.id} (limit = {device_info.n_qubits})" - ) - - else: - n_nodes = 1 - if request.nNodes is not None: - n_nodes = request.nNodes - if n_nodes > device_info.n_nodes: - return BadRequestResponse( - detail=f"Requested nNodes: {n_nodes} exceeds limit for device {device_info.id} (limit = {device_info.n_nodes})" - ) - - else: # QPU - if request.nQubits is not None: - n_qubits = request.nQubits - if n_qubits > device_info.n_qubits: - return BadRequestResponse( - detail=f"Requested nQubits: {n_qubits} exceeds limit for device {device_info.id} (limit = {device_info.n_qubits})" - ) - if request.nNodes is not None: - return BadRequestResponse( - detail=f"nNodes parameter not supported for device: '{device_info.id}' (deviceType: {device_info.device_type}). nNodes requires deviceType: 'simulator'." - ) - - return (n_qubits, n_nodes) - - -@router.post( - "/tasks/sampling", - response_model=SubmitTaskResponse, - responses={400: {"model": Detail}, 500: {"model": Detail}}, -) -@tracer.capture_method -def submit_sampling_tasks( - event: Event, - request: SamplingTaskDef, - db: Session = Depends(get_db), -) -> SubmitTaskResponse | ErrorResponse: - try: - device_info = db.get(Device, request.device) # type: ignore - if device_info is None: - return BadRequestResponse(detail="device not found") - owner = event.state.owner - logger.info("invoked!", extra={"owner": owner}) - if device_info.status != "AVAILABLE": - return BadRequestResponse(f"device {device_info.id} is not available") - - # NOTE: method and operator is validated by pydantic - shots = request.nShots - # name is optional - name = validate_name(request) - code = request.code - - # NOTE:omit query from user_limits table logic - resource = get_resources(request, device_info) - if isinstance(resource, BadRequestResponse): - return resource - else: - n_qubits, n_nodes = resource - - # qubit allocation is valid only for QPU devices - qubit_allocation = validate_qubit_allocation(request, device_info) - if isinstance(qubit_allocation, BadRequestResponse): - return qubit_allocation - - # skip transpilation is False by default - skip_transpilation = validate_skip_transpilation(request) - if isinstance(skip_transpilation, BadRequestResponse): - return skip_transpilation - - # seed transpilation is valid only for transpilation enabled tasks - seed_transpilation = validate_seed_transpilation(request) - if isinstance(seed_transpilation, BadRequestResponse): - return seed_transpilation - - # seed simulation is valid only for simulator devices - seed_simulation = validate_seed_simulation(request, device_info) - if isinstance(seed_simulation, BadRequestResponse): - return seed_simulation - - # ro error mitigation is valid only for QPU devices - ro_error_mitigation = validate_ro_error_mitigation(request, device_info) - if isinstance(ro_error_mitigation, BadRequestResponse): - return ro_error_mitigation - - # n per node is valid only for simulator devices - n_per_node = validate_n_per_node(request, device_info) - if isinstance(n_per_node, BadRequestResponse): - return n_per_node - - # simulation opt is valid only for simulator devices - simulation_opt = validate_simulation_opt(request, device_info) - if isinstance(simulation_opt, BadRequestResponse): - return simulation_opt - - # note is optional - note = validate_note(request) - - task = Task( - id=uuid.uuid4().bytes, - owner=owner, - name=name, - device=request.device, - n_nodes=n_nodes, - n_qubits=n_qubits, - code=code, - action="sampling", - method=None, # sampling task is not using method - shots=shots, - operator=None, # sampling task is not using operator - qubit_allocation=qubit_allocation, - skip_transpilation=skip_transpilation, - seed_transpilation=seed_transpilation, - seed_simulation=seed_simulation, - ro_error_mitigation=ro_error_mitigation, - n_per_node=n_per_node, - simulation_opt=simulation_opt, - note=note, - created_at=datetime.now(), - ) - db.add(task) - db.commit() - return SubmitTaskResponse(taskId=TaskId(task.id)) - except Exception as e: - logger.info(f"error: {str(e)}") - return InternalServerErrorResponse(detail=str(e)) - - -@router.get( - "/tasks/sampling/{taskId}", - response_model=SamplingTaskInfo, - responses={400: {"model": Detail}, 404: {"model": Detail}, 500: {"model": Detail}}, -) -@tracer.capture_method -def get_sampling_task( - event: Event, - taskId: str, - db: Session = Depends(get_db), -) -> SamplingTaskInfo | ErrorResponse: - try: - TaskId(root=uuid.UUID(taskId)) - except ValidationError: - logger.info(f"invalid task id: {taskId}") - return BadRequestResponse(detail="invalid task id") - try: - task_id = uuid.UUID(taskId).bytes - owner = event.state.owner - logger.info("invoked!", extra={"owner": owner}) - task = ( - db.query(Task) - .filter(Task.id == task_id, Task.owner == owner, Task.action == "sampling") - .first() - ) - if task is None: - return NotFoundErrorResponse(detail="task not found with the given id") - return create_sampling_task_info(task) - except Exception as e: - logger.info(f"error: {str(e)}") - return InternalServerErrorResponse(detail=str(e)) - - -@router.delete( - "/tasks/sampling/{taskId}", - response_model=SuccessResponse, - responses={400: {"model": Detail}, 404: {"model": Detail}, 500: {"model": Detail}}, -) -@tracer.capture_method -def delete_sampling_task( - event: Event, - taskId: str, - db: Session = Depends(get_db), -) -> SuccessResponse | ErrorResponse: - try: - TaskId(root=uuid.UUID(taskId)) - except ValidationError: - logger.info(f"invalid task id: {taskId}") - return BadRequestResponse(detail="invalid task id") - try: - task_id = uuid.UUID(taskId).bytes - owner = event.state.owner - logger.info("invoked!", extra={"owner": owner}) - task = db.get(Task, task_id) - - if task is None: - return NotFoundErrorResponse(detail="task not found with the given id") - - if ( - task.owner != owner - or task.action != "sampling" - or task.status not in ["COMPLETED", "FAILED", "CANCELLED"] - ): - return NotFoundErrorResponse( - detail=f"{taskId} task is not in valid status for deletion (valid statuses for deletion: 'COMPLETED', 'FAILED' and 'CANCELLED')" - ) - - db.delete(task) - db.commit() - return SuccessResponse(message="task deleted") - except Exception as e: - logger.info(f"error: {str(e)}") - return InternalServerErrorResponse(detail=str(e)) - - -@router.get( - "/tasks/sampling/{taskId}/status", - response_model=GetSamplingTaskStatusResponse, - responses={400: {"model": Detail}, 404: {"model": Detail}, 500: {"model": Detail}}, -) -@tracer.capture_method -def get_sampling_task_status( - event: Event, - taskId: str, - db: Session = Depends(get_db), -) -> GetSamplingTaskStatusResponse | ErrorResponse: - try: - TaskId(root=uuid.UUID(taskId)) - except ValidationError: - logger.info(f"invalid task id: {taskId}") - return BadRequestResponse(detail="invalid task id") - owner = event.state.owner - logger.info("invoked!", extra={"owner": owner}) - task = ( - db.query(Task.id, Task.status) - .filter( - Task.id == uuid.UUID(taskId).bytes, - Task.action == "sampling", - Task.owner == owner, - ) - .first() - ) - if task is None: - return NotFoundErrorResponse(detail="task not found with the given id") - return GetSamplingTaskStatusResponse( - taskId=TaskId(uuid.UUID(taskId)), status=TaskStatus(root=task.status) - ) - - -@router.post( - "/tasks/sampling/{taskId}/cancel", - response_model=SuccessResponse, - responses={400: {"model": Detail}, 404: {"model": Detail}, 500: {"model": Detail}}, -) -@tracer.capture_method -def cancel_sampling_task( - event: Event, - taskId: str, - db: Session = Depends(get_db), -) -> SuccessResponse | ErrorResponse: - try: - TaskId(root=uuid.UUID(taskId)) - except ValidationError: - logger.info(f"invalid task id: {taskId}") - return BadRequestResponse(detail="invalid task id") - try: - task_id = uuid.UUID(taskId).bytes - owner = event.state.owner - logger.info("invoked!", extra={"owner": owner}) - - task = db.get(Task, task_id) - - if task is None: - return NotFoundErrorResponse(detail="task not found with the given id") - if ( - task.owner != owner - or task.action != "sampling" - or task.status not in ["QUEUED_FETCHED", "QUEUED", "RUNNING"] - ): - return NotFoundErrorResponse( - detail=f"{taskId} task is not in valid status for cancellation (valid statuses for cancellation: 'QUEUED_FETCHED', 'QUEUED' and 'RUNNING')" - ) - if task.status == "QUEUED": - logger.info("task is in QUEUED state, so it will be cancelled") - result = Result( - task_id=task_id, status="CANCELLED", reason="user cancelled" - ) - db.add(result) - db.commit() - elif task.status in ["QUEUED_FETCHED", "RUNNING"]: - logger.info( - "task is in QUEUED_FETCHED or RUNNING state, so it will be marked as CANCELLING" - ) - task.status = "CANCELLING" - db.commit() - return SuccessResponse(message="cancel request accepted") - except Exception as e: - logger.info(f"error: {str(e)}") - return InternalServerErrorResponse(detail=str(e)) - - -@router.get( - "/tasks/estimation", - response_model=list[EstimationTaskInfo], - responses={500: {"model": Detail}}, -) -@tracer.capture_method -def get_estimation_tasks( - event: Event, - db: Session = Depends(get_db), -) -> list[EstimationTaskInfo] | ErrorResponse: - try: - owner = event.state.owner - logger.info("invoked!", extra={"owner": owner}) - tasks = ( - db.query(Task) - .filter(Task.action == "estimation", Task.owner == owner) - .order_by(Task.created_at) - .all() - ) - return [create_estimation_task_info(task) for task in tasks] - except Exception as e: - logger.info(f"error: {str(e)}") - return InternalServerErrorResponse(detail=str(e)) - - -@router.post( - "/tasks/estimation", - response_model=SubmitTaskResponse, - responses={400: {"model": Detail}, 500: {"model": Detail}}, -) -@tracer.capture_method -def submit_estimation_tasks( - event: Event, - request: EstimationTaskDef, - db: Session = Depends(get_db), -) -> SubmitTaskResponse | ErrorResponse: - try: - device_info = db.get(Device, request.device) # type: ignore - if device_info is None: - return BadRequestResponse(detail="device not found") - owner = event.state.owner - - logger.info("invoked!", extra={"owner": owner}) - - if device_info.status != "AVAILABLE": - return BadRequestResponse(f"device {device_info.id} is not available") - - # NOTE: method and operator is needed for estimation task - method = request.method - - if method not in ["state_vector", "sampling"]: - return BadRequestResponse( - detail="method should be either 'state_vector' or 'sampling'" - ) - if request.method == "state_vector": - if device_info.device_type != "simulator": - return BadRequestResponse( - detail="state_vector method is valid only for simulator devices" - ) - if request.nShots is not None: - return BadRequestResponse( - detail="nShots is not valid for state_vector method" - ) - shots = None - else: # sampling - if request.nShots is None: - return BadRequestResponse( - detail="nShots is mandatory for sampling method" - ) - shots = request.nShots - - # operator is mandatory for estimation task - operator = serialize_operator(request.operator) - if isinstance(operator, BadRequestResponse): - return operator - # name is optional - name = validate_name(request) - code = request.code - - # NOTE:omit query from user_limits table logic - - resource = get_resources(request, device_info) - if isinstance(resource, BadRequestResponse): - return resource - else: - n_qubits, n_nodes = resource - - # qubit allocation is valid only for QPU devices - qubit_allocation = validate_qubit_allocation(request, device_info) - if isinstance(qubit_allocation, BadRequestResponse): - return qubit_allocation - - # skip transpilation is False by default - skip_transpilation = validate_skip_transpilation(request) - if isinstance(skip_transpilation, BadRequestResponse): - return skip_transpilation - - # seed transpilation is valid only for transpilation enabled tasks - seed_transpilation = validate_seed_transpilation(request) - if isinstance(seed_transpilation, BadRequestResponse): - return seed_transpilation - - # seed simulation is valid only for simulator devices - seed_simulation = validate_seed_simulation(request, device_info) - if isinstance(seed_simulation, BadRequestResponse): - return seed_simulation - - # ro error mitigation is valid only for QPU devices - ro_error_mitigation = validate_ro_error_mitigation(request, device_info) - if isinstance(ro_error_mitigation, BadRequestResponse): - return ro_error_mitigation - - # n per node is valid only for simulator devices - n_per_node = validate_n_per_node(request, device_info) - if isinstance(n_per_node, BadRequestResponse): - return n_per_node - - # simulation opt is valid only for simulator devices - simulation_opt = validate_simulation_opt(request, device_info) - if isinstance(simulation_opt, BadRequestResponse): - return simulation_opt - - # note is optional - note = validate_note(request) - - task = Task( - id=uuid.uuid4().bytes, - owner=owner, - name=name, - device=request.device, - n_nodes=n_nodes, - n_qubits=n_qubits, - code=code, - action="estimation", - method=method, # estimation task is using method - shots=shots, - operator=operator, # estimation task is using operator - qubit_allocation=qubit_allocation, - skip_transpilation=skip_transpilation, - seed_transpilation=seed_transpilation, - seed_simulation=seed_simulation, - ro_error_mitigation=ro_error_mitigation, - n_per_node=n_per_node, - simulation_opt=simulation_opt, - note=note, - created_at=datetime.now(), - ) - db.add(task) - db.commit() - return SubmitTaskResponse(taskId=TaskId(task.id)) - except Exception as e: - logger.info(f"error: {str(e)}") - return InternalServerErrorResponse(detail=str(e)) - - -@router.get( - "/tasks/estimation/{taskId}", - response_model=EstimationTaskInfo, - responses={400: {"model": Detail}, 404: {"model": Detail}, 500: {"model": Detail}}, -) -@tracer.capture_method -def get_estimation_task( - event: Event, - taskId: str, - db: Session = Depends(get_db), -) -> EstimationTaskInfo | ErrorResponse: - try: - TaskId(root=uuid.UUID(taskId)) - except ValidationError: - logger.info(f"invalid task id: {taskId}") - return BadRequestResponse(detail="invalid task id") - try: - task_id = uuid.UUID(taskId).bytes - owner = event.state.owner - logger.info("invoked!", extra={"owner": owner}) - task = ( - db.query(Task) - .filter( - Task.id == task_id, Task.owner == owner, Task.action == "estimation" - ) - .first() - ) - if task is None: - return NotFoundErrorResponse(detail="task not found with the given id") - return create_estimation_task_info(task) - except Exception as e: - logger.info(f"error: {str(e)}") - return InternalServerErrorResponse(detail=str(e)) - - -@router.delete( - "/tasks/estimation/{taskId}", - response_model=SuccessResponse, - responses={400: {"model": Detail}, 404: {"model": Detail}, 500: {"model": Detail}}, -) -@tracer.capture_method -def delete_estimation_task( - event: Event, - taskId: str, - db: Session = Depends(get_db), -) -> SuccessResponse | ErrorResponse: - try: - TaskId(root=uuid.UUID(taskId)) - except ValidationError: - logger.info(f"invalid task id: {taskId}") - return BadRequestResponse(detail="invalid task id") - try: - task_id = uuid.UUID(taskId).bytes - owner = event.state.owner - logger.info("invoked!", extra={"owner": owner}) - task = db.get(Task, task_id) - - if task is None: - return NotFoundErrorResponse(detail="task not found with the given id") - - if ( - task.owner != owner - or task.action != "estimation" - or task.status not in ["COMPLETED", "FAILED", "CANCELLED"] - ): - return NotFoundErrorResponse( - detail=f"{taskId} task is not in valid status for deletion (valid statuses for deletion: 'COMPLETED', 'FAILED' and 'CANCELLED')" - ) - - db.delete(task) - db.commit() - return SuccessResponse(message="task deleted") - except Exception as e: - logger.info(f"error: {str(e)}") - return InternalServerErrorResponse(detail=str(e)) - - -@router.get( - "/tasks/estimation/{taskId}/status", - response_model=GetEstimationTaskStatusResponse, - responses={400: {"model": Detail}, 404: {"model": Detail}, 500: {"model": Detail}}, -) -@tracer.capture_method -def get_estimation_task_status( - event: Event, - taskId: str, - db: Session = Depends(get_db), -) -> GetEstimationTaskStatusResponse | ErrorResponse: - try: - TaskId(root=uuid.UUID(taskId)) - except ValidationError: - logger.info(f"invalid task id: {taskId}") - return BadRequestResponse(detail="invalid task id") - owner = event.state.owner - logger.info("invoked!", extra={"owner": owner}) - task = ( - db.query(Task.id, Task.status) - .filter( - Task.id == uuid.UUID(taskId).bytes, - Task.action == "estimation", - Task.owner == owner, - ) - .first() - ) - if task is None: - return NotFoundErrorResponse(detail="task not found with the given id") - return GetEstimationTaskStatusResponse( - taskId=TaskId(uuid.UUID(taskId)), status=TaskStatus(root=task.status) - ) - - -@router.post( - "/tasks/estimation/{taskId}/cancel", - response_model=SuccessResponse, - responses={400: {"model": Detail}, 404: {"model": Detail}, 500: {"model": Detail}}, -) -@tracer.capture_method -def cancel_estimation_task( - event: Event, - taskId: str, - db: Session = Depends(get_db), -) -> SuccessResponse | ErrorResponse: - try: - TaskId(root=uuid.UUID(taskId)) - except ValidationError: - logger.info(f"invalid task id: {taskId}") - return BadRequestResponse(detail="invalid task id") - try: - task_id = uuid.UUID(taskId).bytes - owner = event.state.owner - logger.info("invoked!", extra={"owner": owner}) - - task = db.get(Task, task_id) - - if task is None: - return NotFoundErrorResponse(detail="task not found with the given id") - if ( - task.owner != owner - or task.action != "estimation" - or task.status not in ["QUEUED_FETCHED", "QUEUED", "RUNNING"] - ): - return NotFoundErrorResponse( - detail=f"{taskId} task is not in valid status for cancellation (valid statuses for cancellation: 'QUEUED_FETCHED', 'QUEUED' and 'RUNNING')" - ) - if task.status == "QUEUED": - logger.info("task is in QUEUED state, so it will be cancelled") - result = Result( - task_id=task_id, status="CANCELLED", reason="user cancelled" - ) - db.add(result) - db.commit() - elif task.status in ["QUEUED_FETCHED", "RUNNING"]: - logger.info( - "task is in QUEUED_FETCHED or RUNNING state, so it will be marked as CANCELLING" - ) - task.status = "CANCELLING" - db.commit() - return SuccessResponse(message="cancell request accepted") - except Exception as e: - logger.info(f"error: {str(e)}") - return InternalServerErrorResponse(detail=str(e)) diff --git a/backend/oqtopus_cloud/user/schemas/__init__.py b/backend/oqtopus_cloud/user/schemas/__init__.py index 3d3e436..ad02e71 100644 --- a/backend/oqtopus_cloud/user/schemas/__init__.py +++ b/backend/oqtopus_cloud/user/schemas/__init__.py @@ -1,4 +1,4 @@ # generated by datamodel-codegen: # filename: openapi.yaml -# timestamp: 2024-08-29T08:54:22+00:00 -# version: 0.25.8 +# timestamp: 2024-10-14T08:52:23+00:00 +# version: 0.25.9 diff --git a/backend/oqtopus_cloud/user/schemas/devices.py b/backend/oqtopus_cloud/user/schemas/devices.py index d5cf58e..31f08ad 100644 --- a/backend/oqtopus_cloud/user/schemas/devices.py +++ b/backend/oqtopus_cloud/user/schemas/devices.py @@ -1,7 +1,7 @@ # generated by datamodel-codegen: # filename: openapi.yaml -# timestamp: 2024-08-29T08:54:22+00:00 -# version: 0.25.8 +# timestamp: 2024-10-14T08:52:23+00:00 +# version: 0.25.9 from __future__ import annotations @@ -10,65 +10,26 @@ from pydantic import AwareDatetime, BaseModel, Field -class CalibrationData(BaseModel): - """ - Calibration data available only for 'QPU' devices - """ - - qubitConnectivity: Annotated[ - Optional[list[str]], Field(None, examples=[["(1,4)", "(4,5)", "(5,8)"]]) - ] - t1: Annotated[ - Optional[dict[str, float]], - Field(None, examples=[{"0": 55.51, "1": 37.03, "2": 57.13}]), - ] - t2: Annotated[ - Optional[dict[str, float]], - Field(None, examples=[{"0": 99.31, "1": 111.03, "2": 30.12}]), - ] - roError: Annotated[ - Optional[dict[str, float]], - Field(None, examples=[{"0": 0.0467, "1": 0.18, "2": 0.355}]), - ] - gateError: Annotated[ - Optional[dict[str, dict[str, float]]], - Field(None, examples=[{"sx": {"0": 0.00692, "1": 0.00296, "2": 0.072}}]), - ] - measProb0As1: Annotated[ - Optional[dict[str, float]], - Field(None, examples=[{"0": 0.00608, "1": 0.012, "2": 0.248}]), - ] - measProb1As0: Annotated[ - Optional[dict[str, float]], - Field(None, examples=[{"0": 0.0281, "1": 0.386, "2": 0.0811}]), - ] - gateDuration: Annotated[ - Optional[dict[str, dict[str, float]]], - Field(None, examples=[{"sx": {"0": 29.3, "1": 50.9, "2": 45.4}}]), - ] - - class DeviceInfo(BaseModel): - deviceId: Annotated[str, Field(examples=["SVSim"])] - deviceType: Annotated[Literal["QPU", "simulator"], Field(examples=["simulator"])] + device_id: Annotated[Optional[str], Field(None, examples=["SVSim"])] + device_type: Annotated[ + Optional[Literal["QPU", "simulator"]], Field(None, examples=["simulator"]) + ] status: Annotated[ - Literal["AVAILABLE", "NOT_AVAILABLE"], Field(examples=["AVAILABLE"]) + Literal["available", "unavailable"], Field(examples=["available"]) ] - restartAt: Annotated[ - Optional[AwareDatetime], Field(None, examples=["2022-10-19 11:45:34"]) + available_at: Annotated[ + Optional[AwareDatetime], Field(None, examples=["2022-10-19T11:45:34+09:00"]) ] """ - Parameter mandatory and valid for 'NOT_AVAILABLE' devices + Parameter mandatory and valid for 'unavailable' devices """ - nPendingTasks: Annotated[int, Field(examples=[8])] - nQubits: Annotated[Optional[int], Field(None, examples=[39])] - nNodes: Annotated[Optional[int], Field(None, examples=[512])] - """ - Parameter valid only for 'simulator' devices - """ - basisGates: Annotated[ - list[str], + n_pending_jobs: Annotated[Optional[int], Field(None, examples=[8])] + n_qubits: Annotated[Optional[int], Field(None, examples=[39])] + basis_gates: Annotated[ + Optional[list[str]], Field( + None, examples=[ [ "x", @@ -94,15 +55,26 @@ class DeviceInfo(BaseModel): "sx", "sxdg", ] - ] + ], ), ] - supportedInstructions: Annotated[ - list[str], Field(examples=[["measure", "barrier", "reset"]]) + supported_instructions: Annotated[ + Optional[list[str]], Field(None, examples=[["measure", "barrier", "reset"]]) ] - calibrationData: Optional[CalibrationData] = None - calibratedAt: Annotated[ - Optional[AwareDatetime], Field(None, examples=["2022-10-19 11:45:34"]) + device_info: Annotated[ + Optional[str], + Field( + None, + examples=[ + "{'n_nodes': 512, 'calibration_data': {'qubit_connectivity': ['(1,4)', '(4,5)', '(5,8)'], 't1': {'0': 55.51, '1': 37.03, '2': 57.13}}" + ], + ), + ] + """ + json format calibration_data and n_nodes etc + """ + calibrated_at: Annotated[ + Optional[AwareDatetime], Field(None, examples=["2022-10-19T11:45:34+09:00"]) ] """ Parameter available only for 'QPU' devices with available calibration data diff --git a/backend/oqtopus_cloud/user/schemas/error.py b/backend/oqtopus_cloud/user/schemas/error.py index 8a3f045..5822dec 100644 --- a/backend/oqtopus_cloud/user/schemas/error.py +++ b/backend/oqtopus_cloud/user/schemas/error.py @@ -1,7 +1,7 @@ # generated by datamodel-codegen: # filename: openapi.yaml -# timestamp: 2024-08-29T08:54:22+00:00 -# version: 0.25.8 +# timestamp: 2024-10-14T08:52:23+00:00 +# version: 0.25.9 from __future__ import annotations diff --git a/backend/oqtopus_cloud/user/schemas/jobs.py b/backend/oqtopus_cloud/user/schemas/jobs.py new file mode 100644 index 0000000..dc13d66 --- /dev/null +++ b/backend/oqtopus_cloud/user/schemas/jobs.py @@ -0,0 +1,101 @@ +# generated by datamodel-codegen: +# filename: openapi.yaml +# timestamp: 2024-10-14T08:52:23+00:00 +# version: 0.25.9 + +from __future__ import annotations + +from typing import Annotated, Literal, Optional + +from pydantic import AwareDatetime, BaseModel, Field, RootModel + + +class JobId(RootModel[str]): + root: Annotated[str, Field(examples=["7af020f6-2e38-4d70-8cf0-4349650ea08c"])] + + +class JobInfo(RootModel[str]): + root: Annotated[ + str, + Field( + examples=[ + "{'code': '{type: string, example: \"OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;\"}', 'Operator': 'X 0 Y 1 Z 5 I 2', 'result': {'00': 5020, '11': 4980}, 'transpiledCode': '', 'reason': ''}" + ] + ), + ] + + +class TranspilerInfo(RootModel[str]): + root: Annotated[ + str, + Field( + examples=[ + "{'qubitAllocation': {'0': 12, '1': 16}, 'skipTranspilation': false, 'seedTranspilation': 873}" + ] + ), + ] + + +class SimulatorInfo(RootModel[str]): + root: Annotated[ + str, + Field( + examples=[ + "{'nQubits': 5, 'nNodes': 12, 'nPerNode': 2, 'seedSimulation': 39058567, 'simulationOpt': {'optimizationMethod': 'light', 'optimizationBlockSize': 1, 'optimizationSwapLevel': 1}}" + ] + ), + ] + + +class MitigationInfo(RootModel[str]): + root: Annotated[str, Field(examples=["{'roErrorMitigation': 'pseudo_inverse'}"])] + + +class JobStatus( + RootModel[ + Literal["submitted", "ready", "running", "success", "failed", "cancelled"] + ] +): + root: Annotated[ + Literal["submitted", "ready", "running", "success", "failed", "cancelled"], + Field(examples=["submitted"]), + ] + + +class JobDef(BaseModel): + job_id: Optional[JobId] = None + name: Annotated[Optional[str], Field(None, examples=["Bell State Sampling"])] + description: Annotated[ + Optional[str], Field(None, examples=["Bell State Sampling Example"]) + ] + device_id: Annotated[str, Field(examples=["Kawasaki"])] + shots: Annotated[int, Field(examples=["1000"], ge=1, le=10000000)] + job_type: Annotated[ + Optional[str], Field(None, examples=["'sampling' or 'estimation', 'sse'"]) + ] + job_info: Optional[JobInfo] = None + transpiler_info: Optional[TranspilerInfo] = None + simulator_info: Optional[SimulatorInfo] = None + mitigation_info: Optional[MitigationInfo] = None + status: JobStatus + created_at: Annotated[AwareDatetime, Field(examples=["2022-10-19T11:45:34+09:00"])] + updated_at: Annotated[ + Optional[AwareDatetime], Field(None, examples=["2022-10-19T11:45:34+09:00"]) + ] + + +class SubmitJobResponse(BaseModel): + """ + submit a job + """ + + job_id: JobId + + +class GetJobStatusResponse(BaseModel): + """ + job status + """ + + job_id: JobId + status: JobStatus diff --git a/backend/oqtopus_cloud/user/schemas/results.py b/backend/oqtopus_cloud/user/schemas/results.py deleted file mode 100644 index 42d5228..0000000 --- a/backend/oqtopus_cloud/user/schemas/results.py +++ /dev/null @@ -1,70 +0,0 @@ -# generated by datamodel-codegen: -# filename: openapi.yaml -# timestamp: 2024-08-29T08:54:22+00:00 -# version: 0.25.8 - -from __future__ import annotations - -from typing import Annotated, Literal, Optional - -from pydantic import BaseModel, Field, RootModel - -from . import tasks - - -class ResultStatus(RootModel[Literal["SUCCESS", "FAILURE", "CANCELLED"]]): - root: Annotated[ - Literal["SUCCESS", "FAILURE", "CANCELLED"], - Field("SUCCESS", examples=["SUCCESS"]), - ] = "SUCCESS" - - -class SamplingResultDef(BaseModel): - taskId: tasks.TaskId - status: ResultStatus - result: Annotated[ - Optional[dict[str, int]], Field(None, examples=[{"11": 4980, "00": 5020}]) - ] - """ - Provided only for successful results - """ - reason: Optional[str] = None - """ - Provided only for unsuccessful (failed, cancelled) results - """ - transpiledCode: Optional[str] = None - """ - Provided only for tasks with transpilation (tasks created with skipTranspilation=False), if traspilation was successfull - """ - qubitAllocation: Annotated[ - Optional[dict[str, int]], Field(None, examples=[{"0": 0, "1": 4}]) - ] - """ - Parameter valid only for QPU devices - """ - - -class EstimationResultDef(BaseModel): - taskId: tasks.TaskId - status: ResultStatus - result: Annotated[ - Optional[list[float]], - Field(None, examples=[[1.5, 2.8]], max_length=2, min_length=1), - ] - """ - Real and imaginary components of complex estimation result value
Provided only for successful results - """ - reason: Optional[str] = None - """ - Provided only for unsuccessful (failed, cancelled) results - """ - transpiledCode: Optional[str] = None - """ - Provided only for tasks with transpilation (tasks created with skipTranspilation=False), if traspilation was successfull - """ - qubitAllocation: Annotated[ - Optional[dict[str, int]], Field(None, examples=[{"0": 0, "1": 4}]) - ] - """ - Parameter valid only for QPU devices - """ diff --git a/backend/oqtopus_cloud/user/schemas/success.py b/backend/oqtopus_cloud/user/schemas/success.py index fb24653..ad70e95 100644 --- a/backend/oqtopus_cloud/user/schemas/success.py +++ b/backend/oqtopus_cloud/user/schemas/success.py @@ -1,7 +1,7 @@ # generated by datamodel-codegen: # filename: openapi.yaml -# timestamp: 2024-08-29T08:54:22+00:00 -# version: 0.25.8 +# timestamp: 2024-10-14T08:52:23+00:00 +# version: 0.25.9 from __future__ import annotations diff --git a/backend/oqtopus_cloud/user/schemas/tasks.py b/backend/oqtopus_cloud/user/schemas/tasks.py deleted file mode 100644 index da7f931..0000000 --- a/backend/oqtopus_cloud/user/schemas/tasks.py +++ /dev/null @@ -1,362 +0,0 @@ -# generated by datamodel-codegen: -# filename: openapi.yaml -# timestamp: 2024-08-29T08:54:22+00:00 -# version: 0.25.8 - -from __future__ import annotations - -from typing import Annotated, Any, Literal, Optional, Union -from uuid import UUID - -from pydantic import AwareDatetime, BaseModel, Field, RootModel - - -class TaskId(RootModel[UUID]): - root: Annotated[UUID, Field(examples=["7af020f6-2e38-4d70-8cf0-4349650ea08c"])] - - -class TaskStatus( - RootModel[ - Literal["QUEUED", "RUNNING", "COMPLETED", "FAILED", "CANCELLING", "CANCELLED"] - ] -): - root: Annotated[ - Literal["QUEUED", "RUNNING", "COMPLETED", "FAILED", "CANCELLING", "CANCELLED"], - Field(examples=["QUEUED"]), - ] - - -class SamplingTaskInfo(BaseModel): - taskId: TaskId - code: Annotated[ - str, - Field( - examples=[ - "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;" - ] - ), - ] - name: Annotated[Optional[str], Field(None, examples=["Bell State Sampling"])] - device: Annotated[str, Field(examples=["Kawasaki"])] - nQubits: Optional[int] = None - """ - Parameter exclusive with nNodes - """ - nNodes: Annotated[Optional[int], Field(None, examples=[12])] - """ - Parameter exclusive with nQubits
Parameter valid only for 'simulator' devices - """ - nShots: Annotated[int, Field(examples=["1000"], ge=1, le=10000000)] - qubitAllocation: Annotated[ - Optional[dict[str, int]], Field(None, examples=[{"0": 12, "1": 16}]) - ] - """ - Parameter valid only for QPU devices - """ - skipTranspilation: Annotated[bool, Field(examples=[False])] - seedTranspilation: Annotated[Optional[int], Field(None, examples=[873])] - """ - Parameter valid only if skipTranspilation is false - """ - seedSimulation: Annotated[Optional[int], Field(None, examples=[39058567])] - """ - Parameter valid only for 'simulator' devices - """ - roErrorMitigation: Annotated[ - Optional[Literal["none", "pseudo_inverse", "least_square"]], - Field(None, examples=["pseudo_inverse"]), - ] - """ - Parameter valid only for QPU devices - """ - nPerNode: Annotated[Optional[int], Field(None, examples=[5], ge=1)] - """ - Parameter valid only for simulator devices - """ - simulationOpt: Annotated[ - Optional[dict[str, Any]], - Field( - None, - examples=[ - { - "optimizationMethod": "light", - "optimizationBlockSize": 1, - "optimizationSwapLevel": 1, - } - ], - ), - ] - """ - Parameter valid only for simulator devices - """ - note: Annotated[ - Optional[str], Field(None, examples=["Bell State Sampling Example"]) - ] - status: TaskStatus - createdAt: Annotated[AwareDatetime, Field(examples=["2022-10-19 11:45:34"])] - - -class SamplingTaskDef(BaseModel): - code: Annotated[ - str, - Field( - examples=[ - "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;" - ] - ), - ] - name: Annotated[Optional[str], Field(None, examples=["Bell State Sampling"])] - device: Annotated[str, Field(examples=["Kawasaki"])] - nQubits: Optional[int] = None - """ - Parameter exclusive with nNodes - """ - nNodes: Annotated[Optional[int], Field(None, examples=[12])] - """ - Parameter exclusive with nQubits
Parameter valid only for 'simulator' devices - """ - nShots: Annotated[int, Field(examples=["1000"], ge=1, le=10000000)] - qubitAllocation: Annotated[ - Optional[dict[str, int]], Field(None, examples=[{"0": 12, "1": 16}]) - ] - """ - Parameter valid only for QPU devices - """ - skipTranspilation: Annotated[bool, Field(False, examples=[False])] - seedTranspilation: Annotated[Optional[int], Field(None, examples=[873])] - """ - Parameter valid only if skipTranspilation is false - """ - seedSimulation: Annotated[Optional[int], Field(None, examples=[39058567])] - """ - Parameter valid only for 'simulator' devices - """ - roErrorMitigation: Annotated[ - Literal["none", "pseudo_inverse", "least_square"], - Field("none", examples=["pseudo_inverse"]), - ] - """ - Parameter valid only for QPU devices - """ - nPerNode: Annotated[Optional[int], Field(None, examples=[5], ge=1)] - """ - Parameter valid only for simulator devices - """ - simulationOpt: Annotated[ - Optional[dict[str, Any]], - Field( - None, - examples=[ - { - "optimizationMethod": "light", - "optimizationBlockSize": 1, - "optimizationSwapLevel": 1, - } - ], - ), - ] - """ - Parameter valid only for simulator devices - """ - note: Annotated[ - Optional[str], Field(None, examples=["Bell State Sampling Example"]) - ] - - -class SubmitTaskResponse(BaseModel): - """ - submit a task - """ - - taskId: TaskId - - -class GetSamplingTaskStatusResponse(BaseModel): - """ - task status - """ - - taskId: TaskId - status: TaskStatus - - -class SingleOperator(RootModel[list[float]]): - root: Annotated[ - list[float], Field(examples=[[1.5, 2.8]], max_length=2, min_length=2) - ] - """ - Real and imaginary components of complex coef value - """ - - -class SingleOperatorModel(RootModel[list[Union[str, SingleOperator]]]): - root: Annotated[list[Union[str, SingleOperator]], Field(max_length=2, min_length=2)] - - -class Operator(RootModel[list[SingleOperatorModel]]): - root: Annotated[ - list[SingleOperatorModel], - Field(examples=[[["X 0 X 1", [1.5, 2.8]], ["Y 0 Z 1", [1.2, -2e-08]]]]), - ] - - -class EstimationTaskInfo(BaseModel): - taskId: TaskId - code: Annotated[ - str, - Field( - examples=[ - "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;" - ] - ), - ] - name: Annotated[Optional[str], Field(None, examples=["Bell State Estimation"])] - device: Annotated[str, Field(examples=["Kawasaki"])] - nQubits: Optional[int] = None - """ - Parameter exclusive with nNodes - """ - nNodes: Annotated[Optional[int], Field(None, examples=[12])] - """ - Parameter exclusive with nQubits
Parameter valid only for 'simulator' devices - """ - method: Annotated[Literal["state_vector", "sampling"], Field(examples=["sampling"])] - """ - state_vector method valid only for 'simulator' devices - """ - nShots: Annotated[Optional[int], Field(None, examples=["1000"], ge=1, le=10000000)] - """ - Parameter valid only for sampling method - """ - operator: Operator - qubitAllocation: Annotated[ - Optional[dict[str, int]], Field(None, examples=[{"0": 12, "1": 16}]) - ] - """ - Parameter valid only for QPU devices - """ - skipTranspilation: Annotated[bool, Field(examples=[False])] - seedTranspilation: Annotated[Optional[int], Field(None, examples=[873])] - """ - Parameter valid only if skipTranspilation is false - """ - seedSimulation: Annotated[Optional[int], Field(None, examples=[39058567])] - """ - Parameter valid only for 'simulator' devices - """ - roErrorMitigation: Annotated[ - Optional[Literal["none", "pseudo_inverse", "least_square"]], - Field(None, examples=["pseudo_inverse"]), - ] - """ - Parameter valid only for QPU devices - """ - nPerNode: Annotated[Optional[int], Field(None, examples=[5], ge=1)] - """ - Parameter valid only for simulator devices - """ - simulationOpt: Annotated[ - Optional[dict[str, Any]], - Field( - None, - examples=[ - { - "optimizationMethod": "light", - "optimizationBlockSize": 1, - "optimizationSwapLevel": 1, - } - ], - ), - ] - """ - Parameter valid only for simulator devices - """ - note: Annotated[ - Optional[str], Field(None, examples=["Bell State Estimation Example"]) - ] - status: TaskStatus - createdAt: Annotated[AwareDatetime, Field(examples=["2022-10-19 11:45:34"])] - - -class EstimationTaskDef(BaseModel): - code: Annotated[ - str, - Field( - examples=[ - "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;" - ] - ), - ] - name: Annotated[Optional[str], Field(None, examples=["Bell State Estimation"])] - device: Annotated[str, Field(examples=["Kawasaki"])] - nQubits: Optional[int] = None - """ - Parameter exclusive with nNodes - """ - nNodes: Annotated[Optional[int], Field(None, examples=[12])] - """ - Parameter exclusive with nQubits
Parameter valid only for 'simulator' devices - """ - method: Annotated[Literal["state_vector", "sampling"], Field(examples=["sampling"])] - """ - state_vector method valid only for 'simulator' devices - """ - nShots: Annotated[Optional[int], Field(None, examples=["1000"], ge=1, le=10000000)] - """ - Parameter valid only for sampling method - """ - operator: Operator - qubitAllocation: Annotated[ - Optional[dict[str, int]], Field(None, examples=[{"0": 12, "1": 16}]) - ] - """ - Parameter valid only for QPU devices - """ - skipTranspilation: Annotated[bool, Field(False, examples=[False])] - seedTranspilation: Annotated[Optional[int], Field(None, examples=[873])] - """ - Parameter valid only if skipTranspilation is false - """ - seedSimulation: Annotated[Optional[int], Field(None, examples=[39058567])] - """ - Parameter valid only for 'simulator' devices - """ - roErrorMitigation: Annotated[ - Literal["none", "pseudo_inverse", "least_square"], - Field("none", examples=["pseudo_inverse"]), - ] - """ - Parameter valid only for QPU devices - """ - nPerNode: Annotated[Optional[int], Field(None, examples=[5], ge=1)] - """ - Parameter valid only for simulator devices - """ - simulationOpt: Annotated[ - Optional[dict[str, Any]], - Field( - None, - examples=[ - { - "optimizationMethod": "light", - "optimizationBlockSize": 1, - "optimizationSwapLevel": 1, - } - ], - ), - ] - """ - Parameter valid only for simulator devices - """ - note: Annotated[ - Optional[str], Field(None, examples=["Bell State Estimation Example"]) - ] - - -class GetEstimationTaskStatusResponse(BaseModel): - """ - task status - """ - - taskId: TaskId - status: TaskStatus diff --git a/backend/tests/oqtopus_cloud/common/test_model_util.py b/backend/tests/oqtopus_cloud/common/test_model_util.py index c45d6da..7262475 100644 --- a/backend/tests/oqtopus_cloud/common/test_model_util.py +++ b/backend/tests/oqtopus_cloud/common/test_model_util.py @@ -9,13 +9,12 @@ def _get_model_dict(): "id": "SVSim", "device_type": "simulator", "status": "AVAILABLE", - "restart_at": datetime(2023, 1, 2, 12, 34, 56), - "pending_tasks": 8, + "available_at": datetime(2023, 1, 2, 12, 34, 56), + "pending_jobs": 8, "n_qubits": 39, - "n_nodes": 512, "basis_gates": ["x", "sx", "rz", "cx"], "instructions": ["measure", "barrier", "reset"], - "calibration_data": ["measure", "barrier", "reset"], + "device_info": "{'n_nodes': 512, 'calibration_data': {'qubit_connectivity': ['(1,4)', '(4,5)', '(5,8)'], 't1': {'0': 55.51, '1': 37.03, '2': 57.13}}", "calibrated_at": datetime(2024, 3, 4, 12, 34, 56), "description": "State vector-based quantum circuit simulator", } @@ -40,16 +39,15 @@ def test_model_to_schema_dict(): # "description" is not mapped map_model_to_schema = { - "id": "deviceId", # transform field name + "id": "device_id", # transform field name "device_type": "deviceType", # transform field name "status": "status", - "restart_at": "restart_at", - "pending_tasks": "pending_tasks", + "available_at": "available_at", + "pending_jobs": "pending_jobs", "n_qubits": "n_qubits", - "n_nodes": "n_nodes", "basis_gates": "basis_gates", "instructions": "instructions", - "calibration_data": "calibration_data", + "device_info": "device_info", "calibrated_at": "calibrated_at", } @@ -58,7 +56,7 @@ def test_model_to_schema_dict(): # Assert expected = _get_model_dict() - expected["deviceId"] = expected["id"] + expected["device_id"] = expected["id"] del expected["id"] expected["deviceType"] = expected["device_type"] del expected["device_type"] diff --git a/backend/tests/oqtopus_cloud/provider/conftest.py b/backend/tests/oqtopus_cloud/provider/conftest.py index eba40ab..f7bead5 100644 --- a/backend/tests/oqtopus_cloud/provider/conftest.py +++ b/backend/tests/oqtopus_cloud/provider/conftest.py @@ -12,8 +12,8 @@ from oqtopus_cloud.common.models.device import ( Device, ) -from oqtopus_cloud.common.models.task import ( - Task, +from oqtopus_cloud.common.models.job import ( + Job, ) from oqtopus_cloud.common.session import ( get_db, @@ -53,14 +53,14 @@ def insert_initial_data(db: Session): Device( id="Kawasaki", device_type="QPU", - status="NOT_AVAILABLE", - restart_at=datetime(2024, 3, 4, 12, 34, 56), - pending_tasks=0, + status="unavailable", + available_at=datetime(2024, 3, 4, 12, 34, 56), + pending_jobs=0, n_qubits=64, n_nodes=0, basis_gates='["sx", "rx", "rzx90", "id"]', instructions='["measure", "barrier"]', - calibration_data="{}", + device_info="{}", calibrated_at=datetime(2024, 3, 4, 12, 34, 56), description="Superconducting quantum computer", ), diff --git a/backend/tests/oqtopus_cloud/provider/routers/test_devices.py b/backend/tests/oqtopus_cloud/provider/routers/test_devices.py index af0917d..7e484fb 100644 --- a/backend/tests/oqtopus_cloud/provider/routers/test_devices.py +++ b/backend/tests/oqtopus_cloud/provider/routers/test_devices.py @@ -7,14 +7,13 @@ ) from oqtopus_cloud.provider.routers.devices import ( update_device_calibration, - update_device_pending_tasks, + update_device_pending_jobs, update_device_status, ) -from oqtopus_cloud.provider.schemas import CalibrationData from oqtopus_cloud.provider.schemas.devices import ( DeviceCalibrationUpdate, DeviceDataUpdateResponse, - DevicePendingTasksUpdate, + DevicePendingJobsUpdate, DeviceStatusUpdate, ) from zoneinfo import ZoneInfo @@ -41,30 +40,29 @@ def _get_model(): mode_dict = { "id": "SC2", "device_type": "QPU", - "status": "AVAILABLE", - "restart_at": datetime(2023, 1, 2, 12, 34, 56), - "pending_tasks": 8, + "status": "available", + "available_at": datetime(2023, 1, 2, 12, 34, 56), + "pending_jobs": 8, "n_qubits": 39, - "n_nodes": 512, "basis_gates": '["x", "sx", "rz", "cx"]', "instructions": '["measure", "barrier", "reset"]', - "calibration_data": json.dumps(_get_calibration_dict()), # str + "device_info": "", # str "calibrated_at": datetime(2024, 3, 4, 12, 34, 56), "description": "State vector-based quantum circuit simulator", } return Device(**mode_dict) -def test_update_device_pending_tasks(test_db): +def test_update_device_pending_jobs(test_db): # Arrange test_db.add(_get_model()) test_db.commit() device = test_db.get(Device, "SC2") # Act - request = DevicePendingTasksUpdate( - command="DevicePendingTasksUpdate", nPendingTasks=8 + request = DevicePendingJobsUpdate( + command="DevicePendingJobsUpdate", nPendingTasks=8 ) - actual = update_device_pending_tasks(device=device, request=request, db=test_db) + actual = update_device_pending_jobs(device=device, request=request, db=test_db) # Assert expected = DeviceDataUpdateResponse(message="Device's data updated") assert actual == expected @@ -77,7 +75,7 @@ def test_update_device_status_available(test_db): device = test_db.get(Device, "SC2") # Act request = DeviceStatusUpdate( - command="DeviceStatusUpdate", status="AVAILABLE", restartAt=None + command="DeviceStatusUpdate", status="available", available_at=None ) actual = update_device_status(device=device, request=request, db=test_db) # Assert @@ -93,8 +91,8 @@ def test_update_device_status_not_available(test_db): # Act request = DeviceStatusUpdate( command="DeviceStatusUpdate", - status="NOT_AVAILABLE", - restartAt=datetime.now(utc), + status="unavailable", + available_at=datetime.now(utc), ) actual = update_device_status(device=device, request=request, db=test_db) # Assert @@ -111,7 +109,7 @@ def test_update_device_calibration(test_db): request = DeviceCalibrationUpdate( command="DeviceCalibrationUpdate", calibrationData=CalibrationData(**_get_calibration_dict()), - calibratedAt=datetime.now(utc), + calibrated_at=datetime.now(utc), ) actual = update_device_calibration(device=device, request=request, db=test_db) # Assert diff --git a/backend/tests/oqtopus_cloud/provider/routers/test_jobs.py b/backend/tests/oqtopus_cloud/provider/routers/test_jobs.py new file mode 100644 index 0000000..9721bb0 --- /dev/null +++ b/backend/tests/oqtopus_cloud/provider/routers/test_jobs.py @@ -0,0 +1,166 @@ +import json +import uuid +from datetime import datetime +from typing import Dict + +from oqtopus_cloud.common.models.device import ( + Device, +) +from oqtopus_cloud.common.models.job import ( + Job, +) +from oqtopus_cloud.provider.routers.jobs import ( + get_job, + get_jobs, + get_unfetched_jobs, + update_job, +) +from oqtopus_cloud.provider.schemas.jobs import ( + InternalJobStatus, + JobId, + JobStatusUpdate, + JobStatusUpdateResponse, + UnfetchedJobsResponse, +) +from zoneinfo import ZoneInfo + +# sqlite does not support jst timezone +# utc = ZoneInfo("UTC") +utc = ZoneInfo("UTC") +jst = ZoneInfo("Asia/Tokyo") + + +# def _get_calibration_dict() -> Dict: +# calib_dict = { +# "qubitConnectivity": ["(1,4)", "(4,5)", "(5,8)"], +# "t1": {"0": 55.51, "1": 37.03, "2": 57.13}, +# "t2": {"0": 99.31, "1": 111.03, "2": 30.12}, +# "roError": {"0": 4.67e-2, "1": 1.8e-1, "2": 3.55e-1}, +# "gateError": {"sx": {"0": 6.92e-3, "1": 2.96e-3, "2": 7.2e-2}}, +# "measProb0As1": {"0": 6.08e-3, "1": 1.2e-2, "2": 2.48e-1}, +# "measProb1As0": {"0": 2.81e-2, "1": 3.86e-1, "2": 8.11e-2}, +# "gateDuration": {"sx": {"0": 29.3, "1": 50.9, "2": 45.4}}, +# } +# return calib_dict + + +def _get_device_model(): + mode_dict = { + "id": "SC2", + "device_type": "QPU", + "status": "available", + "available_at": datetime(2023, 1, 2, 12, 34, 56), + "pending_jobs": 8, + "n_qubits": 39, + "basis_gates": '["x", "sx", "rz", "cx"]', + "instructions": '["measure", "barrier", "reset"]', + "device_info": "", + "calibrated_at": datetime(2024, 3, 4, 12, 34, 56, tzinfo=utc), + "description": "State vector-based quantum circuit simulator", + } + return Device(**mode_dict) + + +def _get_job_model(job_dict=None): + if job_dict is None: + job_dict = { + "id": uuid.UUID("e8a60c14-8838-46c9-816a-30191d6ab517").bytes, + "name": "Test job 3", + "owner": "admin", + "job_type": "sampling", + "shots": 1024, + "device": "SC2", + "n_qubits": 64, + "n_nodes": 112, + "status": "submitted", + "created_at": datetime(2024, 3, 4, 12, 34, 56, tzinfo=utc), + } + return Job(**job_dict) + + +def test_get_jobs(test_db): + # Arrange + test_db.add(_get_job_model(job_dict=None)) + test_db.add(_get_device_model()) + test_db.commit() + device_id = "SC2" + jobs = get_jobs(deviceId=device_id, db=test_db) + assert jobs.first.device_id == device_id + + +def test_get_job(test_db): + # Arrange + + test_db.add(_get_job_model(job_dict=None)) + test_db.add(_get_device_model()) + test_db.commit() + job_id = "e8a60c14-8838-46c9-816a-30191d6ab517" + jobs = get_job(jobId=job_id, db=test_db) + assert jobs.first.job_id == job_id + + +def test_update_job(test_db): + job_dict = { + "id": uuid.UUID("e8a60c14-8838-46c9-816a-30191d6ab517").bytes, + "owner": "admin", + "code": 'OPENQASM 2.0;\ninclude "qelib1.inc";\nqreg q[2];\nh q[0];\ncx q[0], q[1];\nmeasure q[0] -> c[0];\nmeasure q[1] -> c[1];', + "action": "sampling", + "shots": 1024, + "device": "SC2", + "n_qubits": 64, + "n_nodes": 112, + "qubit_allocation": None, + "skip_transpilation": True, + "seed_transpilation": None, + "seed_simulation": None, + "ro_error_mitigation": None, + "n_per_node": None, + "simulation_opt": None, + "status": "QUEUED_FETCHED", + "created_at": datetime(2024, 3, 4, 12, 34, 56, tzinfo=utc), + } + # Arrange + test_db.add(_get_job_model(job_dict=job_dict)) + test_db.add(_get_device_model()) + test_db.commit() + jobId = "e8a60c14-8838-46c9-816a-30191d6ab517" + request = JobStatusUpdate(status="RUNNING") + actual = update_job(jobId=jobId, request=request, db=test_db) + + expected = JobStatusUpdateResponse(message="Job status updated") + # Assert + + assert actual == expected + + +def test_get_unfetched_jobs(test_db): + job_dict = { + "id": uuid.UUID("e8a60c14-8838-46c9-816a-30191d6ab517").bytes, + "owner": "admin", + "job_type": "sampling", + "shots": 1024, + "device": "SC2", + "n_qubits": 64, + "status": "submitted", + "created_at": datetime(2024, 3, 4, 12, 34, 56, tzinfo=utc), + } + # Arrange + test_db.add(_get_job_model(job_dict=job_dict)) + test_db.add(_get_device_model()) + test_db.commit() + deviceId = "SC2" + status = "submitted" + actual = get_unfetched_jobs(deviceId=deviceId, status=status, db=test_db) + + expected = UnfetchedJobsResponse( + [ + JobId(root=uuid.UUID("e8a60c14-8838-46c9-816a-30191d6ab517")) + ] + ) + # Assert + + assert actual == expected + + +# TODO: add invalid test cases +# TODO: add test cases for handler diff --git a/backend/tests/oqtopus_cloud/provider/routers/test_results.py b/backend/tests/oqtopus_cloud/provider/routers/test_results.py deleted file mode 100644 index 29c8d39..0000000 --- a/backend/tests/oqtopus_cloud/provider/routers/test_results.py +++ /dev/null @@ -1,130 +0,0 @@ -import json -import uuid -from datetime import datetime -from typing import Dict - -from oqtopus_cloud.common.models.device import ( - Device, -) -from oqtopus_cloud.common.models.task import ( - Task, -) -from oqtopus_cloud.provider.routers.results import create_result -from oqtopus_cloud.provider.schemas.results import ( - CreateResultResponse, - Result, - ResultDef, - ResultStatus, - SamplingResult, -) -from oqtopus_cloud.provider.schemas.tasks import ( - TaskId, -) -from zoneinfo import ZoneInfo - -# jst = ZoneInfo("Asia/Tokyo") -utc = ZoneInfo("UTC") - - -def _get_calibration_dict() -> Dict: - calib_dict = { - "qubitConnectivity": ["(1,4)", "(4,5)", "(5,8)"], - "t1": {"0": 55.51, "1": 37.03, "2": 57.13}, - "t2": {"0": 99.31, "1": 111.03, "2": 30.12}, - "roError": {"0": 4.67e-2, "1": 1.8e-1, "2": 3.55e-1}, - "gateError": {"sx": {"0": 6.92e-3, "1": 2.96e-3, "2": 7.2e-2}}, - "measProb0As1": {"0": 6.08e-3, "1": 1.2e-2, "2": 2.48e-1}, - "measProb1As0": {"0": 2.81e-2, "1": 3.86e-1, "2": 8.11e-2}, - "gateDuration": {"sx": {"0": 29.3, "1": 50.9, "2": 45.4}}, - } - return calib_dict - - -def _get_device_model(): - mode_dict = { - "id": "SC2", - "device_type": "QPU", - "status": "AVAILABLE", - "restart_at": datetime(2023, 1, 2, 12, 34, 56), - "pending_tasks": 8, - "n_qubits": 39, - "n_nodes": 512, - "basis_gates": '["x", "sx", "rz", "cx"]', - "instructions": '["measure", "barrier", "reset"]', - "calibration_data": json.dumps(_get_calibration_dict()), # str - "calibrated_at": datetime(2024, 3, 4, 12, 34, 56), - "description": "State vector-based quantum circuit simulator", - } - return Device(**mode_dict) - - -def _get_task_model(task_dict=None): - if task_dict is None: - task_dict = { - "id": uuid.UUID("e8a60c14-8838-46c9-816a-30191d6ab517").bytes, - "owner": "admin", - "code": 'OPENQASM 2.0;\ninclude "qelib1.inc";\nqreg q[2];\nh q[0];\ncx q[0], q[1];\nmeasure q[0] -> c[0];\nmeasure q[1] -> c[1];', - "action": "sampling", - "shots": 1024, - "device": "SC2", - "n_qubits": 64, - "n_nodes": 112, - "qubit_allocation": None, - "skip_transpilation": True, - "seed_transpilation": None, - "seed_simulation": None, - "ro_error_mitigation": None, - "n_per_node": None, - "simulation_opt": None, - "status": "QUEUED", - "created_at": datetime(2024, 3, 4, 12, 34, 56), - } - return Task(**task_dict) - - -def test_create_result(test_db): - task_dict = { - "id": uuid.UUID("e8a60c14-8838-46c9-816a-30191d6ab517").bytes, - "owner": "admin", - "code": 'OPENQASM 2.0;\ninclude "qelib1.inc";\nqreg q[2];\nh q[0];\ncx q[0], q[1];\nmeasure q[0] -> c[0];\nmeasure q[1] -> c[1];', - "action": "sampling", - "shots": 1024, - "device": "SC2", - "n_qubits": 64, - "n_nodes": 112, - "qubit_allocation": None, - "skip_transpilation": True, - "seed_transpilation": None, - "seed_simulation": None, - "ro_error_mitigation": None, - "n_per_node": None, - "simulation_opt": None, - "status": "QUEUED", - "created_at": datetime(2024, 3, 4, 12, 34, 56), - } - # Arrange - test_db.add(_get_task_model(task_dict=task_dict)) - test_db.add(_get_device_model()) - test_db.commit() - request = ResultDef( - taskId=TaskId(root=uuid.UUID("e8a60c14-8838-46c9-816a-30191d6ab517")), - status=ResultStatus(root="SUCCESS"), - result=Result( - SamplingResult( - {"00": 0, "11": 1024}, - ) - ), - reason=None, - transpiledCode='OPENQASM 3;include "stdgates.inc";qubit[2] _all_qubits;let q = _all_qubits[0:1];h q[0];cx q[0], q[1];', - qubitAllocation=None, - ) - actual = create_result(request=request, db=test_db) - - expected = CreateResultResponse(message="success") - # Assert - - assert actual == expected - - -# TODO: add invalid test cases -# TODO: add test cases for handler diff --git a/backend/tests/oqtopus_cloud/provider/routers/test_tasks.py b/backend/tests/oqtopus_cloud/provider/routers/test_tasks.py deleted file mode 100644 index ba97ff0..0000000 --- a/backend/tests/oqtopus_cloud/provider/routers/test_tasks.py +++ /dev/null @@ -1,242 +0,0 @@ -import json -import uuid -from datetime import datetime -from typing import Dict - -from oqtopus_cloud.common.models.device import ( - Device, -) -from oqtopus_cloud.common.models.task import ( - Task, -) -from oqtopus_cloud.provider.routers.tasks import ( - get_task, - get_tasks, - get_unfetched_tasks, - update_task, -) -from oqtopus_cloud.provider.schemas.tasks import ( - Action, - InternalTaskStatus, - SamplingAction, - TaskId, - TaskInfo, - TaskStatusUpdate, - TaskStatusUpdateResponse, - UnfetchedTasksResponse, -) -from zoneinfo import ZoneInfo - -# sqlite does not support jst timezone -# utc = ZoneInfo("UTC") -utc = ZoneInfo("UTC") -jst = ZoneInfo("Asia/Tokyo") - - -def _get_calibration_dict() -> Dict: - calib_dict = { - "qubitConnectivity": ["(1,4)", "(4,5)", "(5,8)"], - "t1": {"0": 55.51, "1": 37.03, "2": 57.13}, - "t2": {"0": 99.31, "1": 111.03, "2": 30.12}, - "roError": {"0": 4.67e-2, "1": 1.8e-1, "2": 3.55e-1}, - "gateError": {"sx": {"0": 6.92e-3, "1": 2.96e-3, "2": 7.2e-2}}, - "measProb0As1": {"0": 6.08e-3, "1": 1.2e-2, "2": 2.48e-1}, - "measProb1As0": {"0": 2.81e-2, "1": 3.86e-1, "2": 8.11e-2}, - "gateDuration": {"sx": {"0": 29.3, "1": 50.9, "2": 45.4}}, - } - return calib_dict - - -def _get_device_model(): - mode_dict = { - "id": "SC2", - "device_type": "QPU", - "status": "AVAILABLE", - "restart_at": datetime(2023, 1, 2, 12, 34, 56), - "pending_tasks": 8, - "n_qubits": 39, - "n_nodes": 512, - "basis_gates": '["x", "sx", "rz", "cx"]', - "instructions": '["measure", "barrier", "reset"]', - "calibration_data": json.dumps(_get_calibration_dict()), # str - "calibrated_at": datetime(2024, 3, 4, 12, 34, 56, tzinfo=utc), - "description": "State vector-based quantum circuit simulator", - } - return Device(**mode_dict) - - -def _get_task_model(task_dict=None): - if task_dict is None: - task_dict = { - "id": uuid.UUID("e8a60c14-8838-46c9-816a-30191d6ab517").bytes, - "name": "Test task 3", - "owner": "admin", - "code": 'OPENQASM 2.0;\ninclude "qelib1.inc";\nqreg q[2];\nh q[0];\ncx q[0], q[1];\nmeasure q[0] -> c[0];\nmeasure q[1] -> c[1];', - "action": "sampling", - "shots": 1024, - "device": "SC2", - "n_qubits": 64, - "n_nodes": 112, - "qubit_allocation": None, - "skip_transpilation": True, - "seed_transpilation": None, - "seed_simulation": None, - "ro_error_mitigation": None, - "n_per_node": None, - "simulation_opt": None, - "status": "QUEUED", - "created_at": datetime(2024, 3, 4, 12, 34, 56, tzinfo=utc), - } - return Task(**task_dict) - - -def test_get_tasks(test_db): - # Arrange - test_db.add(_get_task_model(task_dict=None)) - test_db.add(_get_device_model()) - test_db.commit() - deviceId = "SC2" - actual = get_tasks(deviceId=deviceId, db=test_db) - # Assert - expected = [ - TaskInfo( - taskId=TaskId(root=uuid.UUID("e8a60c14-8838-46c9-816a-30191d6ab517")), - code='OPENQASM 2.0;\ninclude "qelib1.inc";\nqreg q[2];\nh q[0];\ncx q[0], q[1];\nmeasure q[0] -> c[0];\nmeasure q[1] -> c[1];', - device="SC2", - nQubits=64, - nNodes=112, - action=Action(SamplingAction(name="sampling", nShots=1024)), - qubitAllocation=None, - skipTranspilation=True, - seedTranspilation=None, - seedSimulation=None, - roErrorMitigation=None, - nPerNode=None, - simulationOpt=None, - status=InternalTaskStatus("QUEUED"), - createdAt=datetime(2024, 3, 4, 12, 34, 56, tzinfo=jst), - ) - ] - assert actual == expected - - -def test_get_task(test_db): - # Arrange - - test_db.add(_get_task_model(task_dict=None)) - test_db.add(_get_device_model()) - test_db.commit() - taskId = "e8a60c14-8838-46c9-816a-30191d6ab517" - actual = get_task(taskId=taskId, db=test_db) - # Assert - expected = TaskInfo( - taskId=TaskId(root=uuid.UUID("e8a60c14-8838-46c9-816a-30191d6ab517")), - code='OPENQASM 2.0;\ninclude "qelib1.inc";\nqreg q[2];\nh q[0];\ncx q[0], q[1];\nmeasure q[0] -> c[0];\nmeasure q[1] -> c[1];', - device="SC2", - nQubits=64, - nNodes=112, - action=Action(SamplingAction(name="sampling", nShots=1024)), - qubitAllocation=None, - skipTranspilation=True, - seedTranspilation=None, - seedSimulation=None, - roErrorMitigation=None, - nPerNode=None, - simulationOpt=None, - status=InternalTaskStatus("QUEUED"), - createdAt=datetime(2024, 3, 4, 12, 34, 56, tzinfo=jst), - ) - - assert actual == expected - - -def test_update_task(test_db): - task_dict = { - "id": uuid.UUID("e8a60c14-8838-46c9-816a-30191d6ab517").bytes, - "owner": "admin", - "code": 'OPENQASM 2.0;\ninclude "qelib1.inc";\nqreg q[2];\nh q[0];\ncx q[0], q[1];\nmeasure q[0] -> c[0];\nmeasure q[1] -> c[1];', - "action": "sampling", - "shots": 1024, - "device": "SC2", - "n_qubits": 64, - "n_nodes": 112, - "qubit_allocation": None, - "skip_transpilation": True, - "seed_transpilation": None, - "seed_simulation": None, - "ro_error_mitigation": None, - "n_per_node": None, - "simulation_opt": None, - "status": "QUEUED_FETCHED", - "created_at": datetime(2024, 3, 4, 12, 34, 56, tzinfo=utc), - } - # Arrange - test_db.add(_get_task_model(task_dict=task_dict)) - test_db.add(_get_device_model()) - test_db.commit() - taskId = "e8a60c14-8838-46c9-816a-30191d6ab517" - request = TaskStatusUpdate(status="RUNNING") - actual = update_task(taskId=taskId, request=request, db=test_db) - - expected = TaskStatusUpdateResponse(message="Task status updated") - # Assert - - assert actual == expected - - -def test_get_unfetched_tasks(test_db): - task_dict = { - "id": uuid.UUID("e8a60c14-8838-46c9-816a-30191d6ab517").bytes, - "owner": "admin", - "code": 'OPENQASM 2.0;\ninclude "qelib1.inc";\nqreg q[2];\nh q[0];\ncx q[0], q[1];\nmeasure q[0] -> c[0];\nmeasure q[1] -> c[1];', - "action": "sampling", - "shots": 1024, - "device": "SC2", - "n_qubits": 64, - "n_nodes": 112, - "qubit_allocation": None, - "skip_transpilation": True, - "seed_transpilation": None, - "seed_simulation": None, - "ro_error_mitigation": None, - "n_per_node": None, - "simulation_opt": None, - "status": "QUEUED", - "created_at": datetime(2024, 3, 4, 12, 34, 56, tzinfo=utc), - } - # Arrange - test_db.add(_get_task_model(task_dict=task_dict)) - test_db.add(_get_device_model()) - test_db.commit() - deviceId = "SC2" - status = "QUEUED" - actual = get_unfetched_tasks(deviceId=deviceId, status=status, db=test_db) - - expected = UnfetchedTasksResponse( - [ - TaskInfo( - taskId=TaskId(root=uuid.UUID("e8a60c14-8838-46c9-816a-30191d6ab517")), - code='OPENQASM 2.0;\ninclude "qelib1.inc";\nqreg q[2];\nh q[0];\ncx q[0], q[1];\nmeasure q[0] -> c[0];\nmeasure q[1] -> c[1];', - device="SC2", - nQubits=64, - nNodes=112, - action=Action(SamplingAction(name="sampling", nShots=1024)), - qubitAllocation=None, - skipTranspilation=True, - seedTranspilation=None, - seedSimulation=None, - roErrorMitigation=None, - nPerNode=None, - simulationOpt=None, - status=InternalTaskStatus("QUEUED_FETCHED"), - createdAt=datetime(2024, 3, 4, 12, 34, 56, tzinfo=jst), - ) - ] - ) - # Assert - - assert actual == expected - - -# TODO: add invalid test cases -# TODO: add test cases for handler diff --git a/backend/tests/oqtopus_cloud/user/conftest.py b/backend/tests/oqtopus_cloud/user/conftest.py index 34d84bb..74b9a2d 100644 --- a/backend/tests/oqtopus_cloud/user/conftest.py +++ b/backend/tests/oqtopus_cloud/user/conftest.py @@ -12,7 +12,7 @@ from oqtopus_cloud.common.models.device import ( Device, ) -from oqtopus_cloud.common.models.task import ( +from backend.oqtopus_cloud.common.models.job import ( Task, ) from oqtopus_cloud.common.session import ( @@ -54,13 +54,12 @@ def insert_initial_data(db: Session): id="Kawasaki", device_type="QPU", status="NOT_AVAILABLE", - restart_at=datetime(2024, 3, 4, 12, 34, 56), - pending_tasks=0, + available_at=datetime(2024, 3, 4, 12, 34, 56), + pending_jobs=0, n_qubits=64, - n_nodes=0, basis_gates='["sx", "rx", "rzx90", "id"]', instructions='["measure", "barrier"]', - calibration_data="{}", + device_info="{}", calibrated_at=datetime(2024, 3, 4, 12, 34, 56), description="Superconducting quantum computer", ), diff --git a/backend/tests/oqtopus_cloud/user/routers/test_devices.py b/backend/tests/oqtopus_cloud/user/routers/test_devices.py index d2304d1..59fa765 100644 --- a/backend/tests/oqtopus_cloud/user/routers/test_devices.py +++ b/backend/tests/oqtopus_cloud/user/routers/test_devices.py @@ -8,7 +8,7 @@ ) from oqtopus_cloud.user.lambda_function import app from oqtopus_cloud.user.routers.devices import get_device, model_to_schema -from oqtopus_cloud.user.schemas.devices import CalibrationData, DeviceInfo +from oqtopus_cloud.user.schemas.devices import DeviceInfo from zoneinfo import ZoneInfo jst = ZoneInfo("Asia/Tokyo") @@ -51,14 +51,14 @@ def _get_model(): mode_dict = { "id": "SVSim", "device_type": "simulator", - "status": "AVAILABLE", - "restart_at": datetime(2023, 1, 2, 12, 34, 56), - "pending_tasks": 8, + "status": "available", + "available_at": datetime(2023, 1, 2, 12, 34, 56), + "pending_jobs": 8, "n_qubits": 39, "n_nodes": 512, "basis_gates": '["x", "sx", "rz", "cx"]', "instructions": '["measure", "barrier", "reset"]', - "calibration_data": json.dumps(_get_calibration_dict()), # str + #"calibration_data": json.dumps(_get_calibration_dict()), # str "calibrated_at": datetime(2024, 3, 4, 12, 34, 56), "description": "State vector-based quantum circuit simulator", } @@ -75,17 +75,17 @@ def test_get_device(test_db): # Assert expected = DeviceInfo( - deviceId="SVSim", - deviceType="simulator", - status="AVAILABLE", - restartAt=datetime(2023, 1, 2, 12, 34, 56, tzinfo=jst), - nPendingTasks=8, - nQubits=39, - nNodes=512, - basisGates=["x", "sx", "rz", "cx"], - supportedInstructions=["measure", "barrier", "reset"], - calibrationData=CalibrationData(**_get_calibration_dict()), - calibratedAt=datetime(2024, 3, 4, 12, 34, 56, tzinfo=jst), + device_id="SVSim", + device_type="simulator", + status="available", + available_at=datetime(2023, 1, 2, 12, 34, 56, tzinfo=jst), + n_pending_tasks=8, + n_qubits=39, + basis_gates=["x", "sx", "rz", "cx"], + supported_instructions=["measure", "barrier", "reset"], + #device_info=CalibrationData(**_get_calibration_dict()), + device_info="", + calibrated_at=datetime(2024, 3, 4, 12, 34, 56, tzinfo=jst), description="State vector-based quantum circuit simulator", ) assert actual == expected @@ -100,17 +100,17 @@ def test_model_to_shema(): # Assert expected = DeviceInfo( - deviceId="SVSim", - deviceType="simulator", - status="AVAILABLE", - restartAt=datetime(2023, 1, 2, 12, 34, 56, tzinfo=jst), - nPendingTasks=8, - nQubits=39, - nNodes=512, - basisGates=["x", "sx", "rz", "cx"], - supportedInstructions=["measure", "barrier", "reset"], - calibrationData=CalibrationData(**_get_calibration_dict()), - calibratedAt=datetime(2024, 3, 4, 12, 34, 56, tzinfo=jst), + device_id="SVSim", + device_type="simulator", + status="available", + available_at=datetime(2023, 1, 2, 12, 34, 56, tzinfo=jst), + n_pending_tasks=8, + n_qubits=39, + basis_gates=["x", "sx", "rz", "cx"], + supported_instructions=["measure", "barrier", "reset"], + #calibrationData=CalibrationData(**_get_calibration_dict()), + device_info="", + calibrated_at=datetime(2024, 3, 4, 12, 34, 56, tzinfo=jst), description="State vector-based quantum circuit simulator", ) assert actual == expected @@ -126,17 +126,17 @@ def test_get_device_hadler(test_db): assert actual.status_code == 200 # Assert expected = { - "deviceId": "SVSim", - "deviceType": "simulator", - "status": "AVAILABLE", - "restartAt": "2023-01-02T12:34:56+09:00", - "nPendingTasks": 8, - "nQubits": 39, - "nNodes": 512, - "basisGates": ["x", "sx", "rz", "cx"], - "supportedInstructions": ["measure", "barrier", "reset"], - "calibrationData": _get_calibration_dict(), - "calibratedAt": "2024-03-04T12:34:56+09:00", + "device_id": "SVSim", + "device_type": "simulator", + "status": "available", + "available_at": "2023-01-02T12:34:56+09:00", + "n_pending_tasks": 8, + "n_qubits": 39, + "basis_gates": ["x", "sx", "rz", "cx"], + "supported_instructions": ["measure", "barrier", "reset"], + #"calibrationData": _get_calibration_dict(), + "device_info": "", + "calibrated_at": "2024-03-04T12:34:56+09:00", "description": "State vector-based quantum circuit simulator", } assert actual.json() == expected diff --git a/docs/en/architecture/sequence_diagram.md b/docs/en/architecture/sequence_diagram.md index 683893a..4451233 100644 --- a/docs/en/architecture/sequence_diagram.md +++ b/docs/en/architecture/sequence_diagram.md @@ -26,9 +26,9 @@ sequenceDiagram Cloud-->>User: HTTP 200 OK { "taskId": } User->>Cloud: GET /tasks//status - Cloud-->>User: HTTP 200 OK { "taskId": , "status": "QUEUED" } + Cloud-->>User: HTTP 200 OK { "taskId": , "status": "submitted" } - Provider->>Cloud: GET /internal/tasks/unfetched?deviceId=SC&status=QUEUED + Provider->>Cloud: GET /internal/tasks/unfetched?deviceId=SC&status=submitted Note over Cloud: The statuses of fetched tasks are updated to QUEUED_FETCHED. Cloud-->>Provider: HTTP 200 OK {[ {"taskId": , ... }, { "taskId: , ... }, ... ]} @@ -61,7 +61,7 @@ The above diagram shows one iteration of the repeated process. > [!NOTE] > Cloud exposes the information on whether a task is fetched (i.e., whether the status has the suffix of _FETCHED) to Provider only; Cloud does not expose it to User. -> For example, if User requests information of a task in QUEUED_FETCHED status from Cloud, the value of the task status is QUEUED in the response from Cloud. +> For example, if User requests information of a task in QUEUED_FETCHED status from Cloud, the value of the task status is submitted in the response from Cloud. > In contrast, the value of the task status is QUEUED_FETCHED in a response to Provider. ### Data in the DB at Each Time Point @@ -102,9 +102,9 @@ sequenceDiagram Cloud-->>User: HTTP 200 OK { "taskId": } User->>Cloud: GET /tasks//status - Cloud-->>User: HTTP 200 OK { "taskId": , "status": "QUEUED" } + Cloud-->>User: HTTP 200 OK { "taskId": , "status": "submitted" } - Provider->>Cloud: GET /internal/tasks/unfetched?deviceId=SVSim&status=QUEUED + Provider->>Cloud: GET /internal/tasks/unfetched?deviceId=SVSim&status=submitted Note over Cloud: The statuses of fetched tasks are updated to QUEUED_FETCHED. Cloud-->>Provider: HTTP 200 OK {[ {"taskId": , ... }, { "taskId: , ... }, ... ]} @@ -160,13 +160,13 @@ sequenceDiagram User->>Cloud: POST /tasks//cancel Note right of User: User sends a cancel requests for the task . - Note over Cloud: The task status is updated to CANCELLING + Note over Cloud: The task status is updated to cancelling Cloud-->>User: HTTP 200 OK User->>Cloud: GET /tasks//status - Cloud-->>User: HTTP 200 OK { "taskId": , "status": "CANCELLING" } + Cloud-->>User: HTTP 200 OK { "taskId": , "status": "cancelling" } - Provider->>Cloud: GET /internal/tasks/unfetched?deviceId=SVSim&status=CANCELLING + Provider->>Cloud: GET /internal/tasks/unfetched?deviceId=SVSim&status=cancelling Note over Cloud: The statuses of fetched tasks are updated to CANCELLING_FETCHED. Cloud-->>Provider: HTTP 200 OK {[ {"taskId": , ... }, { "taskId: , ... }, ... ]} @@ -184,7 +184,7 @@ sequenceDiagram Cloud-->>User: HTTP 200 OK { "taskId": , "status": "CANCELLED", "reason": ... } ``` -Provider periodically repeats the process of fetching cancel requests (i.e., tasks in CANCELLING status), cancelling task executions, and sending the cancellation results. +Provider periodically repeats the process of fetching cancel requests (i.e., tasks in cancelling status), cancelling task executions, and sending the cancellation results. The above diagram shows one iteration of the repeated process. ### Data in the DB at Each Time Point @@ -207,6 +207,6 @@ The numbers below correspond to the circled numbers in the sequence diagram. - results table: [cancel-case-results-08.csv](../../sample/architecture/cancel-case-results-08.csv) > [!NOTE] -> If the task is in QUEUED status (i.e., before Provider fetches the task) at (1), Cloud immediately changes the task status to CANCELLED. +> If the task is in submitted status (i.e., before Provider fetches the task) at (1), Cloud immediately changes the task status to CANCELLED. > It means the task state transitions from (1) to (8) directly. > In this case, the task is never fetched by Provider. diff --git a/docs/en/architecture/task_state_transition_diagram.md b/docs/en/architecture/task_state_transition_diagram.md index 3be2018..e0318d7 100644 --- a/docs/en/architecture/task_state_transition_diagram.md +++ b/docs/en/architecture/task_state_transition_diagram.md @@ -5,9 +5,9 @@ For example, QUEUED_FETCHED tasks can be transitioned to COMPLETED directly. ```mermaid stateDiagram-v2 - [*] --> QUEUED :task submitted + [*] --> submitted :task submitted - QUEUED --> QUEUED_FETCHED :fetched + submitted --> QUEUED_FETCHED :fetched QUEUED_FETCHED --> RUNNING :execution started state join_state <> @@ -17,12 +17,12 @@ stateDiagram-v2 state join_state <> join_state --> COMPLETED :execution succeeded join_state --> FAILED :execution failed - join_state --> CANCELLING :cancel requested + join_state --> cancelling :cancel requested COMPLETED --> [*] :deleted FAILED --> [*] :deleted - CANCELLING --> CANCELLING_FETCHED :fetched + cancelling --> CANCELLING_FETCHED :fetched CANCELLING_FETCHED --> CANCELLED :cancelled in a gateway - QUEUED --> CANCELLED :cancelled requested (cancelled in the cloud PF) + submitted --> CANCELLED :cancelled requested (cancelled in the cloud PF) CANCELLED --> [*] :deleted ``` diff --git a/docs/ja/architecture/sequence_diagram.md b/docs/ja/architecture/sequence_diagram.md index 4af2b38..893e66b 100644 --- a/docs/ja/architecture/sequence_diagram.md +++ b/docs/ja/architecture/sequence_diagram.md @@ -26,9 +26,9 @@ sequenceDiagram Cloud-->>User: HTTP 200 OK { "taskId": } User->>Cloud: GET /tasks//status - Cloud-->>User: HTTP 200 OK { "taskId": , "status": "QUEUED" } + Cloud-->>User: HTTP 200 OK { "taskId": , "status": "submitted" } - Provider->>Cloud: GET /internal/tasks/unfetched?deviceId=SC&status=QUEUED + Provider->>Cloud: GET /internal/tasks/unfetched?deviceId=SC&status=submitted Note over Cloud: The statuses of fetched tasks are updated to QUEUED_FETCHED. Cloud-->>Provider: HTTP 200 OK {[ {"taskId": , ... }, { "taskId: , ... }, ... ]} @@ -61,7 +61,7 @@ Provider は定期的に、タスクのフェッチ・タスクの実行・実 > [!NOTE] > Cloud はフェッチ済みか否か (status の末尾に _FETCHED が付くか否か) の情報を Provider に対してのみ公開します。 -> 例えば、ユーザーが QUEUED_FETCHED のタスク情報を Cloud から取得すると status は QUEUED になっており、Provider が取得すると status は QUEUED_FETCHED になっています。 +> 例えば、ユーザーが QUEUED_FETCHED のタスク情報を Cloud から取得すると status は submitted になっており、Provider が取得すると status は QUEUED_FETCHED になっています。 ### 各時点における DB 内のデータ @@ -100,9 +100,9 @@ sequenceDiagram Cloud-->>User: HTTP 200 OK { "taskId": } User->>Cloud: GET /tasks//status - Cloud-->>User: HTTP 200 OK { "taskId": , "status": "QUEUED" } + Cloud-->>User: HTTP 200 OK { "taskId": , "status": "submitted" } - Provider->>Cloud: GET /internal/tasks/unfetched?deviceId=SVSim&status=QUEUED + Provider->>Cloud: GET /internal/tasks/unfetched?deviceId=SVSim&status=submitted Note over Cloud: The statuses of fetched tasks are updated to QUEUED_FETCHED. Cloud-->>Provider: HTTP 200 OK {[ {"taskId": , ... }, { "taskId: , ... }, ... ]} @@ -158,13 +158,13 @@ sequenceDiagram User->>Cloud: POST /tasks//cancel Note right of User: User sends a cancel requests for the task . - Note over Cloud: The task status is updated to CANCELLING + Note over Cloud: The task status is updated to cancelling Cloud-->>User: HTTP 200 OK User->>Cloud: GET /tasks//status - Cloud-->>User: HTTP 200 OK { "taskId": , "status": "CANCELLING" } + Cloud-->>User: HTTP 200 OK { "taskId": , "status": "cancelling" } - Provider->>Cloud: GET /internal/tasks/unfetched?deviceId=SVSim&status=CANCELLING + Provider->>Cloud: GET /internal/tasks/unfetched?deviceId=SVSim&status=cancelling Note over Cloud: The statuses of fetched tasks are updated to CANCELLING_FETCHED. Cloud-->>Provider: HTTP 200 OK {[ {"taskId": , ... }, { "taskId: , ... }, ... ]} @@ -182,7 +182,7 @@ sequenceDiagram Cloud-->>User: HTTP 200 OK { "taskId": , "status": "CANCELLED", "reason": ... } ``` -Provider は定期的に、キャンセルリクエスト (status が CANCELLING のタスク) のフェッチ・タスク実行のキャンセル・キャンセル結果の送信、の流れを繰り返します。 +Provider は定期的に、キャンセルリクエスト (status が cancelling のタスク) のフェッチ・タスク実行のキャンセル・キャンセル結果の送信、の流れを繰り返します。 上図では 1 回分の流れを記載しています。 ### 各時点における DB 内のデータ @@ -205,6 +205,6 @@ QUEUED_FETCHED 状態の sampling タスクが DB に存在する状態で、`/t - results テーブル: [cancel-case-results-08.csv](../../sample/architecture/cancel-case-results-08.csv) > [!NOTE] -> (1) の時点でタスクが QUEUED 状態 (Provider によりフェッチされる前の状態) の場合、Cloud は即座にタスクを CANCELLED 状態に変更します。 +> (1) の時点でタスクが submitted 状態 (Provider によりフェッチされる前の状態) の場合、Cloud は即座にタスクを CANCELLED 状態に変更します。 > 上記のシーケンス図だと、(1) から (8) の状態に即座に遷移することになります。 > この場合、Provider によってタスクがフェッチされることはありません。 diff --git a/docs/ja/architecture/task_state_transition_diagram.md b/docs/ja/architecture/task_state_transition_diagram.md index e261cdd..108c801 100644 --- a/docs/ja/architecture/task_state_transition_diagram.md +++ b/docs/ja/architecture/task_state_transition_diagram.md @@ -4,9 +4,9 @@ RUNNING 状態に滞在する時間は非常に短いため、スキップされ ```mermaid stateDiagram-v2 - [*] --> QUEUED :task submitted + [*] --> submitted :task submitted - QUEUED --> QUEUED_FETCHED :fetched + submitted --> QUEUED_FETCHED :fetched QUEUED_FETCHED --> RUNNING : execution started state join_state <> @@ -16,13 +16,13 @@ stateDiagram-v2 state join_state <> join_state --> COMPLETED :execution succeeded join_state --> FAILED :execution failed - join_state --> CANCELLING :cancel requested + join_state --> cancelling :cancel requested COMPLETED --> [*] :deleted FAILED --> [*] :deleted - CANCELLING --> CANCELLING_FETCHED :fetched + cancelling --> CANCELLING_FETCHED :fetched CANCELLING_FETCHED --> CANCELLED :cancelled in a gateway - QUEUED --> CANCELLED :cancelled requested ( cancelled in the cloud PF) + submitted --> CANCELLED :cancelled requested ( cancelled in the cloud PF) CANCELLED --> [*] :deleted ``` diff --git a/docs/oas/provider/openapi.yaml b/docs/oas/provider/openapi.yaml index 77dce40..55543ab 100644 --- a/docs/oas/provider/openapi.yaml +++ b/docs/oas/provider/openapi.yaml @@ -5,7 +5,7 @@ info: contact: name: oqtopus-team email: oqtopus-team[at]googlegroups.com - description: OQTOPUS Cloud Provider API. This API is used to interact with the OQTOPUS Cloud service. The API provides endpoints to manage devices, tasks, and results. + description: OQTOPUS Cloud Provider API. This API is used to interact with the OQTOPUS Cloud service. The API provides endpoints to manage devices, jobs, and results. license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html @@ -13,17 +13,17 @@ servers: - url: http://localhost:8888 description: Local server url paths: - /internal/devices/{deviceId}: + /devices/{device_id}: patch: tags: - devices summary: Update data of selected device - description: Update data of selected device.
Modifiable device propeties are:

- status (all device types)
- number of pending tasks (all device types)
- calibrationData (QPU devices only) + description: Update data of selected device.
Modifiable device propeties are:

- status (all device types)
- number of pending jobs (all device types)
- calibrationData (QPU devices only) operationId: patchDeviceData security: [] parameters: - in: path - name: deviceId + name: device_id description: Device ID required: true schema: @@ -36,58 +36,24 @@ paths: schema: $ref: '#/components/schemas/devices.DeviceDataUpdate' examples: - status update (NOT_AVAILABLE): + status update (unavailable): value: command: DeviceStatusUpdate - status: NOT_AVAILABLE - restartAt: '2023-09-10T14:00:00Z' - status update (AVAILABLE): + status: unavailable + available_at: '2023-09-10T14:00:00Z' + status update (available): value: command: DeviceStatusUpdate - status: AVAILABLE - pending tasks update: + status: available + pending jobs update: value: - command: DevicePendingTasksUpdate - nPendingTasks: 6 + command: DevicePendingJobsUpdate + n_pending_jobs: 6 calibrationData update: value: command: DeviceCalibrationUpdate - calibrationData: - qubitConnectivity: - - (1,4) - - (4,5) - - (5,8) - t1: - '0': 55.51 - '1': 37.03 - '2': 57.13 - t2: - '0': 99.31 - '1': 111.03 - '2': 30.12 - roError: - '0': 0.0467 - '1': 0.18 - '2': 0.355 - gateError: - sx: - '0': 0.00692 - '1': 0.00296 - '2': 0.072 - measProb0As1: - '0': 0.00608 - '1': 0.012 - '2': 0.248 - measProb1As0: - '0': 0.0281 - '1': 0.386 - '2': 0.0811 - gateDuration: - sx: - '0': 29.3 - '1': 50.9 - '2': 45.4 - calibratedAt: '2023-09-10T14:00:00Z' + device_info: '{ ''calibration_data'': { ''qubit_connectivity'': [''(1,4)'', ''(4,5)'', ''(5,8)''], ''t1'': {''0'': 55.51, ''1'': 37.03, ''2'': 57.13}, ''t2'': {''0'': 99.31, ''1'': 111.03, ''2'': 30.12}, ''ro_error'': {''0'': 4.67e-2, ''1'': 1.8e-1, ''2'': 3.55e-1}, ''gate_error'': {''sx'': {''0'': 6.92e-3, ''1'': 2.96e-3, ''2'': 7.2e-2}}, ''meas_prob0_as1'': {''0'': 6.08e-3, ''1'': 1.2e-2, ''2'': 2.48e-1}, ''meas_prob1_as0'': {''0'': 2.81e-2, ''1'': 3.86e-1, ''2'': 8.11e-2}, ''gate_duration'': {''sx'': {''0'': 29.3, ''1'': 50.9, ''2'': 45.4}} }, }' + calibrated_at: '2023-09-10T14:00:00Z' responses: '200': description: Device's data updated @@ -121,17 +87,17 @@ paths: $ref: '#/components/schemas/error.InternalServerError' example: detail: Internal server error - /internal/tasks: + /jobs: get: tags: - - tasks - summary: Search tasks for a device - description: Search tasks for a device - operationId: gettasks + - jobs + summary: Search jobs for a device + description: Search jobs for a device + operationId: getjobs security: [] parameters: - in: query - name: deviceId + name: device_id required: true description: Device identifier schema: @@ -139,30 +105,30 @@ paths: example: Kawasaki - in: query name: status - description: Additional search parameter:
Search tasks with specified status only + description: Additional search parameter:
Search jobs with specified status only schema: - $ref: '#/components/schemas/tasks.InternalTaskStatus' + $ref: '#/components/schemas/jobs.InternalJobStatus' - in: query - name: maxResults - description: Additional search parameter:
Set max number of quantum tasks to return in single request + name: max_results + description: Additional search parameter:
Set max number of quantum jobs to return in single request schema: type: integer example: 1 - in: query name: timestamp - description: Additional search parameter:
Fetch tasks created after the specified timetsamp + description: Additional search parameter:
Fetch jobs created after the specified timetsamp schema: type: string example: '2022-12-15 15:54:46' responses: '200': - description: List of tasks for a device + description: List of jobs for a device content: application/json: schema: type: array items: - $ref: '#/components/schemas/tasks.TaskInfo' + $ref: '#/components/schemas/jobs.JobDef' '400': description: Bad Request content: @@ -179,28 +145,28 @@ paths: $ref: '#/components/schemas/error.InternalServerError' example: detail: Internal server error - /internal/tasks/{taskId}: + /jobs/{job_id}: get: - summary: Get a task by ID - description: Get a task by ID - operationId: getTask + summary: Get a job by ID + description: Get a job by ID + operationId: getJob security: [] tags: - - tasks + - jobs parameters: - in: path - name: taskId + name: job_id required: true - description: Task identifier + description: Job identifier schema: type: string responses: '200': - description: Return quantum task + description: Return quantum job content: application/json: schema: - $ref: '#/components/schemas/tasks.TaskInfo' + $ref: '#/components/schemas/jobs.JobDef' '400': description: Bad Request content: @@ -216,36 +182,36 @@ paths: schema: $ref: '#/components/schemas/error.NotFoundError' example: - detail: task not found + detail: job not found patch: - summary: Modify selected quantum task (update status). - description: Used by device to set task status to "RUNNING".
Other statuses are set by CloudAPI automatically when result is created - operationId: patchTask + summary: Modify selected quantum job (update status). + description: Used by device to set job status to "RUNNING".
Other statuses are set by CloudAPI automatically when result is created + operationId: patchJob security: [] tags: - - tasks + - jobs parameters: - in: path - name: taskId + name: job_id required: true - description: Task identifier + description: Job identifier schema: type: string requestBody: - description: 'New task status. ' + description: 'New job status. ' content: application/json: schema: - $ref: '#/components/schemas/tasks.TaskStatusUpdate' + $ref: '#/components/schemas/jobs.JobStatusUpdate' responses: '200': - description: task data updated + description: job data updated content: application/json: schema: - $ref: '#/components/schemas/tasks.TaskStatusUpdateResponse' + $ref: '#/components/schemas/jobs.JobStatusUpdateResponse' example: - message: task data updated + message: job data updated '400': description: Bad Request content: @@ -261,18 +227,18 @@ paths: schema: $ref: '#/components/schemas/error.NotFoundError' example: - detail: task not found - /internal/tasks/unfetched: + detail: job not found + /jobs/unfetched: get: - summary: Fetch tasks for device - description: 'Fetches tasks for execution/cancel

Operation is valid only for task with status: QUEUED or CANCELLING. After the operation task status is changed to appropriate FETCHED state (QUEUED_FETCHED or CANCELLING_FETCHED)' - operationId: getUnfetchedTasks + summary: Fetch jobs for device + description: 'Fetches jobs for execution/cancel

Operation is valid only for job with status: submitted or cancelling. After the operation job status is changed to appropriate FETCHED state (QUEUED_FETCHED or CANCELLING_FETCHED)' + operationId: getUnfetchedJobs security: [] tags: - - tasks + - jobs parameters: - in: query - name: deviceId + name: device_id required: true description: Device identifier schema: @@ -281,22 +247,22 @@ paths: - in: query name: status required: true - description: Fetch tasks with specified status + description: Fetch jobs with specified status schema: - $ref: '#/components/schemas/tasks.InternalFetchableTaskStatus' + $ref: '#/components/schemas/jobs.InternalFetchableJobStatus' - in: query - name: maxResults - description: Additional search parameter:
Set max number of quantum tasks to return in single request + name: max_results + description: Additional search parameter:
Set max number of quantum jobs to return in single request schema: type: integer example: 1 responses: '200': - description: List of tasks for execution (all task data) / cancel (taskIds only) + description: List of jobs for execution (all job data) / cancel (jobIds only) content: application/json: schema: - $ref: '#/components/schemas/tasks.UnfetchedTasksResponse' + $ref: '#/components/schemas/jobs.UnfetchedJobsResponse' '400': description: Bad Request content: @@ -305,94 +271,6 @@ paths: $ref: '#/components/schemas/error.BadRequest' example: detail: Bad request malformed input data - /internal/results: - post: - summary: Submit a quantum task result - tags: - - results - description: Submit a quantum task result - operationId: postResult - security: [] - requestBody: - description: Result to be submitted - content: - application/json: - schema: - $ref: '#/components/schemas/results.ResultDef' - examples: - success sampling: - value: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - status: SUCCESS - result: - '11': 4980 - '00': 5020 - reason: null - transpiledCode: OPENQASM 3;include "stdgates.inc";qubit[2] _all_qubits;let q = _all_qubits[0:1];h q[0];cx q[0], q[1]; - success estimation: - value: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - status: SUCCESS - result: - - 1.5 - - 2.8 - reason: null - transpiledCode: OPENQASM 3;include "stdgates.inc";qubit[2] _all_qubits;let q = _all_qubits[0:1];h q[0];cx q[0], q[1]; - failure: - value: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - status: FAILURE - result: null - reason: Invalid device parameter in request - transpiledCode: null - cancel: - value: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - status: CANCELLED - result: null - reason: User cancelled - transpiledCode: null - responses: - '200': - description: Results submitted - content: - application/json: - schema: - $ref: '#/components/schemas/results.CreateResultResponse' - example: - message: Results submitted - '400': - description: Bad Request - content: - application/json: - schema: - $ref: '#/components/schemas/error.BadRequest' - example: - detail: Bad request malformed input data - '404': - description: Not Found - content: - application/json: - schema: - $ref: '#/components/schemas/error.NotFoundError' - example: - detail: TaskID not found - '409': - description: Result for taskId already exists - content: - application/json: - schema: - $ref: '#/components/schemas/error.ConflictError' - example: - detail: Result for taskId already exists - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/error.InternalServerError' - example: - detail: Internal server error components: schemas: devices.DeviceStatusUpdate: @@ -404,112 +282,32 @@ components: status: type: string enum: - - AVAILABLE - - NOT_AVAILABLE - restartAt: - description: Parameter mandatory and valid for status 'NOT_AVAILABLE' + - available + - unavailable + available_at: + description: Parameter mandatory and valid for status 'unavailable' type: string format: date-time example: '2023-09-10T14:00:00+09:00' - devices.DevicePendingTasksUpdate: + devices.DevicePendingJobsUpdate: type: object properties: command: type: string - example: DevicePendingTasksUpdate - nPendingTasks: + example: DevicePendingJobsUpdate + n_pending_jobs: type: integer - CalibrationData: - description: Calibration data available only for 'QPU' devices - type: object - properties: - qubitConnectivity: - type: array - items: - type: string - format: (number, number) - example: - - (1,4) - - (4,5) - - (5,8) - t1: - type: object - additionalProperties: - type: number - format: float - example: - '0': 55.51 - '1': 37.03 - '2': 57.13 - t2: - type: object - additionalProperties: - type: number - format: float - example: - '0': 99.31 - '1': 111.03 - '2': 30.12 - roError: - type: object - additionalProperties: - type: number - format: float - example: - '0': 0.0467 - '1': 0.18 - '2': 0.355 - gateError: - type: object - additionalProperties: - type: object - additionalProperties: - type: number - format: float - example: - sx: - '0': 0.00692 - '1': 0.00296 - '2': 0.072 - measProb0As1: - type: object - additionalProperties: - type: number - format: float - example: - '0': 0.00608 - '1': 0.012 - '2': 0.248 - measProb1As0: - type: object - additionalProperties: - type: number - format: float - example: - '0': 0.0281 - '1': 0.386 - '2': 0.0811 - gateDuration: - type: object - additionalProperties: - type: object - additionalProperties: - type: number - format: float - example: - sx: - '0': 29.3 - '1': 50.9 - '2': 45.4 devices.DeviceCalibrationUpdate: type: object properties: command: type: string example: DeviceCalibrationUpdate - calibrationData: - $ref: '#/components/schemas/CalibrationData' - calibratedAt: + device_info: + description: json format calibration_data and n_nodes etc + type: string + example: '{''n_nodes'': 512, ''calibration_data'': {''qubit_connectivity'': [''(1,4)'', ''(4,5)'', ''(5,8)''], ''t1'': {''0'': 55.51, ''1'': 37.03, ''2'': 57.13}}' + calibrated_at: description: Parameter mandatory and valid if calibrationData not null type: string format: date-time @@ -519,11 +317,11 @@ components: propertyName: command mapping: DeviceStatusUpdate: '#/components/schemas/devices.DeviceStatusUpdate' - DevicePendingTasksUpdate: '#/components/schemas/devices.DevicePendingTasksUpdate' + DevicePendingJobsUpdate: '#/components/schemas/devices.DevicePendingJobsUpdate' DeviceCalibrationUpdate: '#/components/schemas/devices.DeviceCalibrationUpdate' oneOf: - $ref: '#/components/schemas/devices.DeviceStatusUpdate' - - $ref: '#/components/schemas/devices.DevicePendingTasksUpdate' + - $ref: '#/components/schemas/devices.DevicePendingJobsUpdate' - $ref: '#/components/schemas/devices.DeviceCalibrationUpdate' devices.DeviceDataUpdateResponse: type: object @@ -555,293 +353,117 @@ components: type: string required: - detail - tasks.InternalTaskStatus: + jobs.InternalJobStatus: type: string enum: - - QUEUED - - QUEUED_FETCHED - - RUNNING - - COMPLETED - - FAILED - - CANCELLING - - CANCELLING_FETCHED - - CANCELLED - example: QUEUED - tasks.TaskId: + - submitted + - ready + - running + - success + - failed + - cancelled + example: submitted + jobs.JobId: type: string format: uuid example: 7af020f6-2e38-4d70-8cf0-4349650ea08c - tasks.SamplingAction: + jobs.JobInfo: + type: string + example: '{''code'': ''{type: string, example: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;"}'', ''Operator'': ''X 0 Y 1 Z 5 I 2'', ''result'': {''00'': 5020, ''11'': 4980}, ''transpiled_code'': '''', ''reason'': ''''}' + jobs.TranspilerInfo: + type: string + example: '{''qubit_allocation'': {''0'': 12, ''1'': 16}, ''skip_transpilation'': false, ''seed_transpilation'': 873}' + jobs.SimulatorInfo: + type: string + example: '{''n_qubits'': 5, ''n_nodes'': 12, ''n_per_node'': 2, ''seed_simulation'': 39058567, ''simulation_opt'': {''optimization_method'': ''light'', ''optimization_block_size'': 1, ''optimization_swap_level'': 1}}' + jobs.MitigationInfo: + type: string + example: '{''ro_error_mitigation'': ''pseudo_inverse''}' + jobs.JobDef: type: object properties: + job_id: + $ref: '#/components/schemas/jobs.JobId' name: type: string - pattern: sampling - example: sampling - nShots: - type: integer - minimum: 1 - maximum: 10000000 - example: '1000' - required: - - name - - nShots - tasks.SingleOperator: - type: array - items: - anyOf: - - type: string - description: Pauli string - example: X 0 Y 1 Z 5 I 2 - - type: array - description: Real and imaginary components of complex coef value - items: - type: number - minItems: 2 - maxItems: 2 - example: - - 1.5 - - 2.8 - minItems: 2 - maxItems: 2 - tasks.Operator: - type: array - items: - $ref: '#/components/schemas/tasks.SingleOperator' - example: - - - X 0 X 1 - - - 1.5 - - 2.8 - - - Y 0 Z 1 - - - 1.2 - - -2.e-8 - tasks.EstimationAction: - type: object - properties: - name: + example: Bell State Sampling + description: type: string - pattern: estimation - example: estimation - method: + example: Bell State Sampling Example + device_id: type: string - enum: - - state_vector - - sampling - example: sampling - description: state_vector method valid only for 'simulator' devices - nShots: + example: Kawasaki + shots: type: integer minimum: 1 maximum: 10000000 example: '1000' - description: Parameter valid only for sampling method - operator: - $ref: '#/components/schemas/tasks.Operator' - required: - - name - - method - - operator - tasks.Action: - type: object - oneOf: - - $ref: '#/components/schemas/tasks.SamplingAction' - - $ref: '#/components/schemas/tasks.EstimationAction' - tasks.TaskInfo: - type: object - properties: - taskId: - $ref: '#/components/schemas/tasks.TaskId' - code: - type: string - example: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; - device: + job_type: type: string - example: Kawasaki - nQubits: - type: integer - example: null - nNodes: - description: Parameter valid only for 'simulator' devices - type: integer - example: 12 - action: - $ref: '#/components/schemas/tasks.Action' - qubitAllocation: - description: Parameter valid only for QPU devices - type: object - additionalProperties: - type: integer - example: - '0': 12 - '1': 16 - skipTranspilation: - type: boolean - example: false - seedTranspilation: - description: Parameter valid only if skipTranspilation is false - type: integer - example: 873 - seedSimulation: - description: Parameter valid only for 'simulator' devices - type: integer - example: 39058567 - roErrorMitigation: - description: Parameter valid only for QPU devices - type: string - enum: - - none - - pseudo_inverse - - least_square - example: pseudo_inverse - nPerNode: - description: Parameter valid only for simulator devices - type: integer - minimum: 1 - example: 5 - simulationOpt: - description: Parameter valid only for simulator devices - type: object - example: - optimizationMethod: light - optimizationBlockSize: 1 - optimizationSwapLevel: 1 + example: '''sampling'' or ''estimation'', ''sse''' + job_info: + $ref: '#/components/schemas/jobs.JobInfo' + transpiler_info: + $ref: '#/components/schemas/jobs.TranspilerInfo' + simulator_info: + $ref: '#/components/schemas/jobs.SimulatorInfo' + mitigation_info: + $ref: '#/components/schemas/jobs.MitigationInfo' status: - $ref: '#/components/schemas/tasks.InternalTaskStatus' - createdAt: + $ref: '#/components/schemas/jobs.InternalJobStatus' + created_at: + type: string + format: date-time + example: '2022-10-19T11:45:34+09:00' + updated_at: type: string format: date-time example: '2022-10-19T11:45:34+09:00' required: - - taskId - - code - - device - - action - - skipTranspilation + - device_id + - shots - status - - createdAt + - created_at example: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - code: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; - device: Kawasaki - nQubits: null - nNodes: 12 - action: - name: sampling - nShots: 1000 - qubitAllocation: null - skipTranspilation: false - seedTranspilation: 873 - seedSimulation: 39058567 - roErrorMitigation: null - nPerNode: 2 - simulationOpt: - optimizationMethod: light - optimizationBlockSize: 1 - optimizationSwapLevel: 1 - status: QUEUED_FETCHED - createdAt: '2022-10-19T11:45:34+09:00' - tasks.TaskStatusUpdate: + job_id: 7af020f6-2e38-4d70-8cf0-4349650ea08c + name: Bell State Sampling + description: Bell State Sampling Example + device_id: Kawasaki + job_info: '{''code'': ''{type: string, example: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;"}'', ''operator'': ''X 0 Y 1 Z 5 I 2''}' + transpiler_info: '{''qubit_allocation'': {''0'': 12, ''1'': 16}, ''skip_transpilation'': false, ''seed_transpilation'': 873}' + simulator_info: '{''n_qubits'': 5, ''n_nodes'': 12, ''n_per_node'': 2, ''seed_simulation'': 39058567, ''simulation_opt'': {''optimization_method'': ''light'', ''optimization_block_size'': 1, ''optimization_swap_level'': 1}}' + mitigation_info: '{''ro_error_mitigation'': ''pseudo_inverse''}' + job_type: sampling + shots: 1000 + status: submitted + created_at: '2022-10-19T11:45:34+09:00' + updated_at: '2022-10-19T11:45:34+09:00' + jobs.JobStatusUpdate: type: object properties: status: type: string enum: - - RUNNING - example: RUNNING + - running + example: running required: - status - tasks.TaskStatusUpdateResponse: + jobs.JobStatusUpdateResponse: type: object properties: message: type: string required: - message - tasks.InternalFetchableTaskStatus: + jobs.InternalFetchableJobStatus: type: string enum: - - QUEUED - - CANCELLING - example: QUEUED - tasks.UnfetchedTasksResponse: + - queued + - cancelling + example: queued + jobs.UnfetchedJobsResponse: type: array items: oneOf: - - $ref: '#/components/schemas/tasks.TaskInfo' - - $ref: '#/components/schemas/tasks.TaskId' - results.ResultStatus: - type: string - enum: - - SUCCESS - - FAILURE - - CANCELLED - default: SUCCESS - example: SUCCESS - results.SamplingResult: - type: object - additionalProperties: - type: integer - minProperties: 2 - example: - '11': 4980 - '00': 5020 - results.EstimationResult: - type: array - items: - type: number - minItems: 2 - maxItems: 2 - example: - - 1.5 - - 2.8 - results.Result: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/results.SamplingResult' - - $ref: '#/components/schemas/results.EstimationResult' - results.ResultDef: - type: object - properties: - taskId: - $ref: '#/components/schemas/tasks.TaskId' - status: - $ref: '#/components/schemas/results.ResultStatus' - result: - $ref: '#/components/schemas/results.Result' - reason: - type: string - nullable: true - transpiledCode: - type: string - nullable: true - qubitAllocation: - description: Parameter valid only for QPU devices - type: object - additionalProperties: - type: integer - nullable: true - example: - '0': 0 - '1': 4 - required: - - taskId - - status - - result - - reason - - transpiledCode - results.CreateResultResponse: - type: object - properties: - message: - type: string - required: - - message - example: - message: Results submitted - error.ConflictError: - type: object - properties: - detail: - type: string - required: - - detail + - $ref: '#/components/schemas/jobs.JobDef' + - $ref: '#/components/schemas/jobs.JobId' diff --git a/docs/oas/user/openapi.yaml b/docs/oas/user/openapi.yaml index 062ea79..0b8c5dd 100644 --- a/docs/oas/user/openapi.yaml +++ b/docs/oas/user/openapi.yaml @@ -5,7 +5,7 @@ info: contact: name: oqtopus-team email: oqtopus-team[at]googlegroups.com - description: OQTOPUS Cloud User API. This API is used to interact with the OQTOPUS Cloud service. The API provides endpoints to manage devices, tasks, and results. + description: OQTOPUS Cloud User API. This API is used to interact with the OQTOPUS Cloud service. The API provides endpoints to manage devices, jobs, and results. license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html @@ -45,7 +45,7 @@ paths: application/json: schema: $ref: '#/components/schemas/error.InternalServerError' - /devices/{deviceId}: + /devices/{device_id}: get: tags: - device @@ -55,7 +55,7 @@ paths: security: - BearerAuth: [] parameters: - - name: deviceId + - name: device_id in: path description: Device identifier required: true @@ -64,7 +64,7 @@ paths: example: Kawasaki responses: '200': - description: task response + description: job response content: application/json: schema: @@ -81,24 +81,24 @@ paths: application/json: schema: $ref: '#/components/schemas/error.InternalServerError' - /tasks/sampling: + /jobs: get: tags: - - task - summary: List all sampling quantum tasks - description: List all sampling quantum tasks - operationId: listSamplingTasks + - job + summary: List all quantum jobs + description: List all quantum jobs + operationId: listJobs security: - BearerAuth: [] responses: '200': - description: Return a list of submitted quantum tasks + description: Return a list of submitted quantum jobs content: application/json: schema: type: array items: - $ref: '#/components/schemas/tasks.SamplingTaskInfo' + $ref: '#/components/schemas/jobs.JobDef' '401': description: Unauthorized content: @@ -109,53 +109,58 @@ paths: detail: Unauthorized post: tags: - - task - summary: Submit a sampling quantum task - description: Submit a sampling quantum task - operationId: submitSamplingTask + - job + summary: Submit a quantum job + description: Submit a quantum job + operationId: submitJob security: - BearerAuth: [] requestBody: - description: Quantum task to be submitted + description: Quantum job to be submitted content: application/json: schema: - $ref: '#/components/schemas/tasks.SamplingTaskDef' + $ref: '#/components/schemas/jobs.JobDef' examples: simulator: description: Simulator example value: - code: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; name: Bell State Sampling - device: SVsim - nNodes: 12 - nShots: 1000 - skipTranspilation: false - seedTranspilation: 873 - seedSimulation: 39058567 - nPerNode: 2 - simulationOpt: - optimizationMethod: light - optimizationBlockSize: 1 - optimizationSwapLevel: 1 - note: Bell State Sampling Example + description: Bell State Sampling Example + device_id: Kawasaki + job_info: '{''code'': ''{type: string, example: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;"}'', ''operator'': ''X 0 Y 1 Z 5 I 2'', ''result'': {''00'': 5020, ''11'': 4980}, ''transpiled_code'': '''', ''reason'': ''''}' + transpiler_info: '' + simulator_info: '{''n_qubits'': 5, ''n_nodes'': 12, ''n_per_node'': 2, ''seed_simulation'': 39058567, ''simulation_opt'': {''optimization_method'': ''light'', ''optimization_block_size'': 1, ''optimization_swap_level'': 1}}' + mitigation_info: '' + job_type: sampling + shots: 1000 + status: submitted + created_at: '2022-10-19T11:45:34+09:00' + updated_at: '2022-10-19T11:45:34+09:00' qpu: description: QPU example value: - code: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; name: Bell State Sampling - device: Kawasaki - nShots: 1000 - note: Bell State Sampling Example + description: Bell State Sampling Example + device_id: Kawasaki + job_info: '{''code'': ''{type: string, example: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;"}'', ''operator'': ''X 0 Y 1 Z 5 I 2'', ''result'': {''00'': 5020, ''11'': 4980}, ''transpiled_code'': '''', ''reason'': ''''}' + transpiler_info: '{''qubit_allocation'': {''0'': 12, ''1'': 16}, ''skip_transpilation'': false, ''seed_transpilation'': 873}' + simulator_info: '' + mitigation_info: '{''ro_error_mitigation'': ''pseudo_inverse''}' + job_type: sampling + shots: 1000 + status: submitted + created_at: '2022-10-19T11:45:34+09:00' + updated_at: '2022-10-19T11:45:34+09:00' responses: '200': - description: Task submitted + description: Job submitted content: application/json: schema: - $ref: '#/components/schemas/tasks.SubmitTaskResponse' + $ref: '#/components/schemas/jobs.SubmitJobResponse' example: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c + job_id: 7af020f6-2e38-4d70-8cf0-4349650ea08c '400': description: Bad Request content: @@ -172,29 +177,29 @@ paths: $ref: '#/components/schemas/error.UnauthorizedError' example: detail: Unauthorized - /tasks/sampling/{taskId}: + /jobs/{job_id}: get: tags: - - task - summary: Get selected sampling task - description: Get selected sampling task - operationId: getSamplingTask + - job + summary: Get selected job + description: Get selected job + operationId: getSamplingJob security: - BearerAuth: [] parameters: - in: path - name: taskId + name: job_id required: true - description: Task identifier + description: Job identifier schema: type: string responses: '200': - description: Return quantum task + description: Return quantum job content: application/json: schema: - $ref: '#/components/schemas/tasks.SamplingTaskInfo' + $ref: '#/components/schemas/jobs.JobDef' '400': description: Bad Request content: @@ -218,31 +223,31 @@ paths: schema: $ref: '#/components/schemas/error.NotFoundError' example: - detail: task not found + detail: job not found delete: tags: - - task - summary: Delete sampling task - description: 'Deletes quantum task and related result

Operation is valid only for task with status: COMPLETED, FAILED and CANCELLED. QUEUED and RUNNING tasks must be cancelled before deletion.' - operationId: deleteSamplingTask + - job + summary: Delete job + description: 'Deletes quantum job and related result

Operation is valid only for job with status: COMPLETED, FAILED and CANCELLED. submitted and RUNNING jobs must be cancelled before deletion.' + operationId: deleteSamplingJob security: - BearerAuth: [] parameters: - in: path - name: taskId + name: job_id required: true - description: Task identifier + description: Job identifier schema: type: string responses: '200': - description: Quantum task deleted + description: Quantum job deleted content: application/json: schema: $ref: '#/components/schemas/success.SuccessResponse' example: - message: Quantum task deleted + message: Quantum job deleted '400': description: Bad Request content: @@ -266,30 +271,30 @@ paths: schema: $ref: '#/components/schemas/error.NotFoundError' example: - detail: task not found - /tasks/sampling/{taskId}/status: + detail: job not found + /jobs/{job_id}/status: get: tags: - - task - summary: Get selected sampling task's status - description: Get selected sampling task's status - operationId: getSamplingTaskStatus + - job + summary: Get selected job's status + description: Get selected job's status + operationId: getSamplingJobStatus security: - BearerAuth: [] parameters: - in: path - name: taskId + name: job_id required: true - description: Task identifier + description: Job identifier schema: type: string responses: '200': - description: Return quantum task status + description: Return quantum job status content: application/json: schema: - $ref: '#/components/schemas/tasks.GetSamplingTaskStatusResponse' + $ref: '#/components/schemas/jobs.GetJobStatusResponse' '400': description: Bad Request content: @@ -313,26 +318,26 @@ paths: schema: $ref: '#/components/schemas/error.NotFoundError' example: - detail: task not found - /tasks/sampling/{taskId}/cancel: + detail: job not found + /jobs/{job_id}/cancel: post: tags: - - task - summary: Cancel sampling task - description: 'Start a procedure to cancel quantum task.

Operation is valid only for task with status: QUEUED or RUNNING.' - operationId: cancelSamplingTask + - job + summary: Cancel job + description: 'Start a procedure to cancel quantum job.

Operation is valid only for job with status: submitted or RUNNING.' + operationId: cancelSamplingJob security: - BearerAuth: [] parameters: - in: path - name: taskId + name: job_id required: true - description: Task identifier + description: Job identifier schema: type: string responses: '200': - description: Task cancelled + description: Job cancelled content: application/json: schema: @@ -362,461 +367,7 @@ paths: schema: $ref: '#/components/schemas/error.NotFoundError' example: - detail: task not found - /tasks/estimation: - post: - tags: - - task - summary: Submit estimation quantum task - description: Submit estimation quantum task - operationId: submitEstimationTask - security: - - BearerAuth: [] - requestBody: - description: Quantum task to be submitted - content: - application/json: - schema: - $ref: '#/components/schemas/tasks.EstimationTaskDef' - examples: - simulator: - description: Simulator example - value: - code: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; - name: Bell State Estimation - device: SVsim - nNodes: 12 - method: sampling - nShots: 1000 - operator: - - - X 0 X 1 - - - 1.5 - - 2.8 - - - Y 0 Z 1 - - - 1.2 - - -2.e-8 - skipTranspilation: false - seedTranspilation: 873 - seedSimulation: 39058567 - nPerNode: 2 - simulationOpt: - optimizationMethod: light - optimizationBlockSize: 1 - optimizationSwapLevel: 1 - note: Bell State Estimation Example - simulator2: - description: Simulator example with statevector - value: - code: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; - name: Bell State Estimation - device: SVsim - nNodes: 12 - method: state_vector - operator: - - - X 0 X 1 - - - 1.5 - - 2.8 - - - Y 0 Z 1 - - - 1.2 - - -2.e-8 - skipTranspilation: false - seedTranspilation: 873 - seedSimulation: 39058567 - nPerNode: 2 - simulationOpt: - optimizationMethod: light - optimizationBlockSize: 1 - optimizationSwapLevel: 1 - note: Bell State Estimation Example - qpu: - description: QPU example - value: - code: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; - name: Bell State Estimation - device: Kawasaki - method: sampling - nShots: 1000 - operator: - - - X 0 X 1 - - - 1.5 - - 2.8 - - - Y 0 Z 1 - - - 1.2 - - -2.e-8 - note: Bell State Estimation Example - responses: - '200': - description: Task submitted - content: - application/json: - schema: - $ref: '#/components/schemas/tasks.SubmitTaskResponse' - example: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - '400': - description: Bad Request - content: - application/json: - schema: - $ref: '#/components/schemas/error.BadRequest' - example: - detail: Bad request malformed input data - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/error.UnauthorizedError' - example: - detail: Unauthorized - get: - tags: - - task - summary: List all estimation quantum tasks - description: List all estimation quantum tasks - operationId: listEstimationTasks - security: - - BearerAuth: [] - responses: - '200': - description: Return a list of submitted quantum tasks - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/tasks.EstimationTaskInfo' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/error.UnauthorizedError' - example: - detail: Unauthorized - /tasks/estimation/{taskId}: - get: - tags: - - task - summary: Get selected estimation task - description: Get selected estimation task - operationId: getEstimationTask - security: - - BearerAuth: [] - parameters: - - in: path - name: taskId - required: true - description: Task identifier - schema: - type: string - responses: - '200': - description: Return quantum task - content: - application/json: - schema: - $ref: '#/components/schemas/tasks.EstimationTaskInfo' - '400': - description: Bad Request - content: - application/json: - schema: - $ref: '#/components/schemas/error.BadRequest' - example: - detail: Bad request malformed input data - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/error.UnauthorizedError' - example: - detail: Unauthorized - '404': - description: Not Found - content: - application/json: - schema: - $ref: '#/components/schemas/error.NotFoundError' - example: - detail: task not found - delete: - tags: - - task - summary: Deletes estimation task - description: 'Deletes quantum task and related result

Operation is valid only for task with status: COMPLETED, FAILED and CANCELLED. QUEUED and RUNNING tasks must be cancelled before deletion.' - operationId: deleteEstimationTask - security: - - BearerAuth: [] - parameters: - - in: path - name: taskId - required: true - description: Task identifier - schema: - type: string - responses: - '200': - description: Quantum task deleted - content: - application/json: - schema: - $ref: '#/components/schemas/success.SuccessResponse' - example: - message: Quantum task deleted - '400': - description: Bad Request - content: - application/json: - schema: - $ref: '#/components/schemas/error.BadRequest' - example: - detail: Bad request malformed input data - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/error.UnauthorizedError' - example: - detail: Unauthorized - '404': - description: Not Found - content: - application/json: - schema: - $ref: '#/components/schemas/error.NotFoundError' - example: - detail: task not found - /tasks/estimation/{taskId}/status: - get: - tags: - - task - summary: Get selected estimation task's status - description: Get selected estimation task's status - operationId: getEstimationTaskStatus - security: - - BearerAuth: [] - parameters: - - in: path - name: taskId - required: true - description: Task identifier - schema: - type: string - responses: - '200': - description: Return quantum task status - content: - application/json: - schema: - $ref: '#/components/schemas/tasks.GetEstimationTaskStatusResponse' - '400': - description: Bad Request - content: - application/json: - schema: - $ref: '#/components/schemas/error.BadRequest' - example: - detail: Bad request malformed input data - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/error.UnauthorizedError' - example: - detail: Unauthorized - '404': - description: Not Found - content: - application/json: - schema: - $ref: '#/components/schemas/error.NotFoundError' - example: - detail: task not found - /tasks/estimation/{taskId}/cancel: - post: - tags: - - task - summary: Cancel estimation task - description: 'Start a procedure to cancel quantum task.

Operation is valid only for task with status: QUEUED or RUNNING.' - operationId: cancelEstimationTask - security: - - BearerAuth: [] - parameters: - - in: path - name: taskId - required: true - description: Task identifier - schema: - type: string - responses: - '200': - description: cancel request accepted - content: - application/json: - schema: - $ref: '#/components/schemas/success.SuccessResponse' - example: - message: Task cancelled - '400': - description: Bad Request - content: - application/json: - schema: - $ref: '#/components/schemas/error.BadRequest' - example: - detail: Bad request malformed input data - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/error.UnauthorizedError' - example: - detail: Unauthorized - '404': - description: Not Found - content: - application/json: - schema: - $ref: '#/components/schemas/error.NotFoundError' - example: - detail: task not found - /results/sampling/{taskId}: - get: - tags: - - result - summary: Get result of a sampling task - description: Gets a result of quantum task.

Any finished quantum task must generate a result. The result contains either simulation result (for successfully completed tasks) or reason why simulation outcome is not provided (for unsuccessful and cancelled tasks)

Operation is valid only for COMPLETED, FAILED and CANCELLED tasks - operationId: getSamplingResult - security: - - BearerAuth: [] - parameters: - - in: path - name: taskId - required: true - description: Task identifier - schema: - type: string - responses: - '200': - description: Return quantum task result - content: - application/json: - schema: - $ref: '#/components/schemas/results.SamplingResultDef' - examples: - success sampling: - value: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - status: SUCCESS - result: - '11': 4980 - '00': 5020 - transpiledCode: OPENQASM 3;include "stdgates.inc";qubit[2] _all_qubits;let q = _all_qubits[0:1];h q[0];cx q[0], q[1]; - failure: - value: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - status: FAILURE - reason: Invalid device parameter in request - cancel: - value: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - status: CANCELLED - reason: User cancelled - '400': - description: Bad Request - content: - application/json: - schema: - $ref: '#/components/schemas/error.BadRequest' - example: - detail: Bad request malformed input data - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/error.UnauthorizedError' - example: - detail: Unauthorized - '404': - description: Not Found - content: - application/json: - schema: - $ref: '#/components/schemas/error.NotFoundError' - example: - detail: task not found - /results/estimation/{taskId}: - get: - tags: - - result - summary: Get result of estimation task - description: Gets a result of quantum task.

Any finished quantum task must generate a result. The result contains either simulation result (for successfully completed tasks) or reason why simulation outcome is not provided (for unsuccessful and cancelled tasks)

Operation is valid only for COMPLETED, FAILED and CANCELLED tasks - operationId: getEstimationResult - security: - - BearerAuth: [] - parameters: - - in: path - name: taskId - required: true - description: Task identifier - schema: - type: string - responses: - '200': - description: Return quantum task result - content: - application/json: - schema: - $ref: '#/components/schemas/results.EstimationResultDef' - examples: - success estimation: - value: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - status: SUCCESS - result: - - 1.5 - - 2.8 - transpiledCode: OPENQASM 3;include "stdgates.inc";qubit[2] _all_qubits;let q = _all_qubits[0:1];h q[0];cx q[0], q[1]; - failure: - value: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - status: FAILURE - reason: Invalid device parameter in request - cancel: - value: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - status: CANCELLED - reason: User cancelled - '400': - description: Bad Request - content: - application/json: - schema: - $ref: '#/components/schemas/error.BadRequest' - example: - detail: Bad request malformed input data - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/error.UnauthorizedError' - example: - detail: Unauthorized - '404': - description: Not Found - content: - application/json: - schema: - $ref: '#/components/schemas/error.NotFoundError' - example: - detail: task not found + detail: job not found components: securitySchemes: BearerAuth: @@ -824,95 +375,13 @@ components: scheme: bearer bearerFormat: JWT schemas: - devices.CalibrationData: - description: Calibration data available only for 'QPU' devices - type: object - properties: - qubitConnectivity: - type: array - items: - type: string - format: (number, number) - example: - - (1,4) - - (4,5) - - (5,8) - t1: - type: object - additionalProperties: - type: number - format: float - example: - '0': 55.51 - '1': 37.03 - '2': 57.13 - t2: - type: object - additionalProperties: - type: number - format: float - example: - '0': 99.31 - '1': 111.03 - '2': 30.12 - roError: - type: object - additionalProperties: - type: number - format: float - example: - '0': 0.0467 - '1': 0.18 - '2': 0.355 - gateError: - type: object - additionalProperties: - type: object - additionalProperties: - type: number - format: float - example: - sx: - '0': 0.00692 - '1': 0.00296 - '2': 0.072 - measProb0As1: - type: object - additionalProperties: - type: number - format: float - example: - '0': 0.00608 - '1': 0.012 - '2': 0.248 - measProb1As0: - type: object - additionalProperties: - type: number - format: float - example: - '0': 0.0281 - '1': 0.386 - '2': 0.0811 - gateDuration: - type: object - additionalProperties: - type: object - additionalProperties: - type: number - format: float - example: - sx: - '0': 29.3 - '1': 50.9 - '2': 45.4 devices.DeviceInfo: type: object properties: - deviceId: + device_id: type: string example: SVSim - deviceType: + device_type: type: string enum: - QPU @@ -921,25 +390,21 @@ components: status: type: string enum: - - AVAILABLE - - NOT_AVAILABLE - example: AVAILABLE - restartAt: - description: Parameter mandatory and valid for 'NOT_AVAILABLE' devices + - available + - unavailable + example: available + available_at: + description: Parameter mandatory and valid for 'unavailable' devices type: string format: date-time example: '2022-10-19T11:45:34+09:00' - nPendingTasks: + n_pending_jobs: type: integer example: 8 - nQubits: + n_qubits: type: integer example: 39 - nNodes: - description: Parameter valid only for 'simulator' devices - type: integer - example: 512 - basisGates: + basis_gates: type: array items: type: string @@ -966,7 +431,7 @@ components: - id - sx - sxdg - supportedInstructions: + supported_instructions: type: array items: type: string @@ -974,9 +439,11 @@ components: - measure - barrier - reset - calibrationData: - $ref: '#/components/schemas/devices.CalibrationData' - calibratedAt: + device_info: + description: json format calibration_data and n_nodes etc + type: string + example: '{''n_nodes'': 512, ''calibration_data'': {''qubit_connectivity'': [''(1,4)'', ''(4,5)'', ''(5,8)''], ''t1'': {''0'': 55.51, ''1'': 37.03, ''2'': 57.13}}' + calibrated_at: description: Parameter available only for 'QPU' devices with available calibration data type: string format: date-time @@ -988,18 +455,18 @@ components: - deviceId - deviceType - status - - nPendingTasks + - nPendingJobs - basisGates - supportedInstructions - description example: - - deviceId: SVSim - deviceType: simulator + - device_id: SVSim + device_type: simulator status: AVAILABLE - nPendingTasks: 8 - nQubits: 39 - nNodes: 512 - basisGates: + n_pending_jobs: 8 + n_qubits: 39 + n_nodes: 512 + basis_gates: - x - 'y' - z @@ -1022,10 +489,12 @@ components: - id - sx - sxdg - supportedInstructions: + supported_instructions: - measure - barrier - reset + device_info: '{''n_nodes'': 512, ''calibration_data'': {''qubit_connectivity'': [''(1,4)'', ''(4,5)'', ''(5,8)''], ''t1'': {''0'': 55.51, ''1'': 37.03, ''2'': 57.13}}' + calibrated_at: '2022-10-19T11:45:34+09:00' description: State vector-based quantum circuit simulator error.UnauthorizedError: type: object @@ -1048,200 +517,98 @@ components: type: string required: - detail - tasks.TaskId: + jobs.JobId: type: string - format: uuid example: 7af020f6-2e38-4d70-8cf0-4349650ea08c - tasks.TaskStatus: + jobs.JobInfo: + type: string + example: '{''code'': ''{type: string, example: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;"}'', ''Operator'': ''X 0 Y 1 Z 5 I 2'', ''result'': {''00'': 5020, ''11'': 4980}, ''transpiledCode'': '''', ''reason'': ''''}' + jobs.TranspilerInfo: + type: string + example: '{''qubitAllocation'': {''0'': 12, ''1'': 16}, ''skipTranspilation'': false, ''seedTranspilation'': 873}' + jobs.SimulatorInfo: + type: string + example: '{''nQubits'': 5, ''nNodes'': 12, ''nPerNode'': 2, ''seedSimulation'': 39058567, ''simulationOpt'': {''optimizationMethod'': ''light'', ''optimizationBlockSize'': 1, ''optimizationSwapLevel'': 1}}' + jobs.MitigationInfo: + type: string + example: '{''roErrorMitigation'': ''pseudo_inverse''}' + jobs.JobStatus: type: string enum: - - QUEUED - - RUNNING - - COMPLETED - - FAILED - - CANCELLING - - CANCELLED - example: QUEUED - tasks.SamplingTaskInfo: + - submitted + - ready + - running + - success + - failed + - cancelled + example: submitted + jobs.JobDef: type: object properties: - taskId: - $ref: '#/components/schemas/tasks.TaskId' - code: - type: string - example: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; + job_id: + $ref: '#/components/schemas/jobs.JobId' name: type: string example: Bell State Sampling - device: + description: + type: string + example: Bell State Sampling Example + device_id: type: string example: Kawasaki - nQubits: - description: Parameter exclusive with nNodes - type: integer - nNodes: - description: Parameter exclusive with nQubits
Parameter valid only for 'simulator' devices - type: integer - example: 12 - nShots: + shots: type: integer minimum: 1 maximum: 10000000 example: '1000' - qubitAllocation: - description: Parameter valid only for QPU devices - type: object - additionalProperties: - type: integer - example: - '0': 12 - '1': 16 - skipTranspilation: - type: boolean - example: false - seedTranspilation: - description: Parameter valid only if skipTranspilation is false - type: integer - example: 873 - seedSimulation: - description: Parameter valid only for 'simulator' devices - type: integer - example: 39058567 - roErrorMitigation: - description: Parameter valid only for QPU devices - type: string - enum: - - none - - pseudo_inverse - - least_square - example: pseudo_inverse - nPerNode: - description: Parameter valid only for simulator devices - type: integer - minimum: 1 - example: 5 - simulationOpt: - description: Parameter valid only for simulator devices - type: object - example: - optimizationMethod: light - optimizationBlockSize: 1 - optimizationSwapLevel: 1 - note: - type: string - example: Bell State Sampling Example + job_type: + type: string + example: '''sampling'' or ''estimation'', ''sse''' + job_info: + $ref: '#/components/schemas/jobs.JobInfo' + transpiler_info: + $ref: '#/components/schemas/jobs.TranspilerInfo' + simulator_info: + $ref: '#/components/schemas/jobs.SimulatorInfo' + mitigation_info: + $ref: '#/components/schemas/jobs.MitigationInfo' status: - $ref: '#/components/schemas/tasks.TaskStatus' - createdAt: + $ref: '#/components/schemas/jobs.JobStatus' + created_at: + type: string + format: date-time + example: '2022-10-19T11:45:34+09:00' + updated_at: type: string format: date-time example: '2022-10-19T11:45:34+09:00' required: - - taskId - - code - - device - - nShots - - skipTranspilation + - device_id + - shots - status - - createdAt + - created_at example: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - code: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; + job_id: 7af020f6-2e38-4d70-8cf0-4349650ea08c name: Bell State Sampling - device: Kawasaki - nNodes: 12 - nShots: 1000 - skipTranspilation: false - seedTranspilation: 387 - seedSimulation: 39058567 - nPerNode: 2 - simulationOpt: - optimizationMethod: light - optimizationBlockSize: 1 - optimizationSwapLevel: 1 - note: Bell State Sampling Example - status: QUEUED - createdAt: '2022-10-19T11:45:34+09:00' - tasks.SamplingTaskDef: + description: Bell State Sampling Example + device_id: Kawasaki + job_info: '{''code'': ''{type: string, example: "OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q;"}'', ''Operator'': ''X 0 Y 1 Z 5 I 2'', ''result'': {''00'': 5020, ''11'': 4980}, ''transpiled_code'': '''', ''reason'': ''''}' + transpiler_info: '{''qubit_allocation'': {''0'': 12, ''1'': 16}, ''skip_transpilation'': false, ''seed_transpilation'': 873}' + simulator_info: '{''n_qubits'': 5, ''n_nodes'': 12, ''n_per_node'': 2, ''seed_simulation'': 39058567, ''simulation_opt'': {''optimization_method'': ''light'', ''optimization_block_size'': 1, ''optimization_swap_level'': 1}}' + mitigation_info: '{''ro_error_mitigation'': ''pseudo_inverse''}' + job_type: sampling + shots: 1000 + status: submitted + created_at: '2022-10-19T11:45:34+09:00' + updated_at: '2022-10-19T11:45:34+09:00' + jobs.SubmitJobResponse: + description: submit a job type: object properties: - code: - type: string - example: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; - name: - type: string - example: Bell State Sampling - device: - type: string - example: Kawasaki - nQubits: - description: Parameter exclusive with nNodes - type: integer - nNodes: - description: Parameter exclusive with nQubits
Parameter valid only for 'simulator' devices - type: integer - example: 12 - nShots: - type: integer - minimum: 1 - maximum: 10000000 - example: '1000' - qubitAllocation: - description: Parameter valid only for QPU devices - type: object - additionalProperties: - type: integer - example: - '0': 12 - '1': 16 - skipTranspilation: - type: boolean - default: false - example: false - seedTranspilation: - description: Parameter valid only if skipTranspilation is false - type: integer - example: 873 - seedSimulation: - description: Parameter valid only for 'simulator' devices - type: integer - example: 39058567 - roErrorMitigation: - description: Parameter valid only for QPU devices - type: string - enum: - - none - - pseudo_inverse - - least_square - default: none - example: pseudo_inverse - nPerNode: - description: Parameter valid only for simulator devices - type: integer - minimum: 1 - example: 5 - simulationOpt: - description: Parameter valid only for simulator devices - type: object - example: - optimizationMethod: light - optimizationBlockSize: 1 - optimizationSwapLevel: 1 - note: - type: string - example: Bell State Sampling Example + job_id: + $ref: '#/components/schemas/jobs.JobId' required: - - code - - device - - nShots - tasks.SubmitTaskResponse: - description: submit a task - type: object - properties: - taskId: - $ref: '#/components/schemas/tasks.TaskId' - required: - - taskId + - job_id error.BadRequest: type: object properties: @@ -1256,331 +623,14 @@ components: type: string required: - message - tasks.GetSamplingTaskStatusResponse: - description: task status - type: object - properties: - taskId: - $ref: '#/components/schemas/tasks.TaskId' - status: - $ref: '#/components/schemas/tasks.TaskStatus' - required: - - taskId - - status - tasks.SingleOperator: - type: array - items: - anyOf: - - type: string - description: Pauli string - example: X 0 Y 1 Z 5 I 2 - - type: array - description: Real and imaginary components of complex coef value - items: - type: number - minItems: 2 - maxItems: 2 - example: - - 1.5 - - 2.8 - minItems: 2 - maxItems: 2 - tasks.Operator: - type: array - items: - $ref: '#/components/schemas/tasks.SingleOperator' - example: - - - X 0 X 1 - - - 1.5 - - 2.8 - - - Y 0 Z 1 - - - 1.2 - - -2.e-8 - tasks.EstimationTaskInfo: - type: object - properties: - taskId: - $ref: '#/components/schemas/tasks.TaskId' - code: - type: string - example: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; - name: - type: string - example: Bell State Estimation - device: - type: string - example: Kawasaki - nQubits: - description: Parameter exclusive with nNodes - type: integer - nNodes: - description: Parameter exclusive with nQubits
Parameter valid only for 'simulator' devices - type: integer - example: 12 - method: - type: string - enum: - - state_vector - - sampling - example: sampling - description: state_vector method valid only for 'simulator' devices - nShots: - type: integer - minimum: 1 - maximum: 10000000 - example: '1000' - description: Parameter valid only for sampling method - operator: - $ref: '#/components/schemas/tasks.Operator' - qubitAllocation: - description: Parameter valid only for QPU devices - type: object - additionalProperties: - type: integer - example: - '0': 12 - '1': 16 - skipTranspilation: - type: boolean - example: false - seedTranspilation: - description: Parameter valid only if skipTranspilation is false - type: integer - example: 873 - seedSimulation: - description: Parameter valid only for 'simulator' devices - type: integer - example: 39058567 - roErrorMitigation: - description: Parameter valid only for QPU devices - type: string - enum: - - none - - pseudo_inverse - - least_square - example: pseudo_inverse - nPerNode: - description: Parameter valid only for simulator devices - type: integer - minimum: 1 - example: 5 - simulationOpt: - description: Parameter valid only for simulator devices - type: object - example: - optimizationMethod: light - optimizationBlockSize: 1 - optimizationSwapLevel: 1 - note: - type: string - example: Bell State Estimation Example - status: - $ref: '#/components/schemas/tasks.TaskStatus' - createdAt: - type: string - format: date-time - example: '2022-10-19T11:45:34+09:00' - required: - - taskId - - code - - device - - method - - operator - - skipTranspilation - - status - - createdAt - example: - taskId: 7af020f6-2e38-4d70-8cf0-4349650ea08c - code: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; - name: Bell State Estimation - device: Kawasaki - nNodes: 12 - method: sampling - nShots: 1000 - operator: - - - X 0 X 1 - - - 1.5 - - 2.8 - - - Y 0 Z 1 - - - 1.2 - - -2.e-8 - skipTranspilation: false - seedTranspilation: 387 - seedSimulation: 39058567 - nPerNode: 2 - simulationOpt: - optimizationMethod: light - optimizationBlockSize: 1 - optimizationSwapLevel: 1 - note: Bell State Estimation Example - status: QUEUED - createdAt: '2022-10-19T11:45:34+09:00' - tasks.EstimationTaskDef: - type: object - properties: - code: - type: string - example: OPENQASM 3; qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; - name: - type: string - example: Bell State Estimation - device: - type: string - example: Kawasaki - nQubits: - description: Parameter exclusive with nNodes - type: integer - nNodes: - description: Parameter exclusive with nQubits
Parameter valid only for 'simulator' devices - type: integer - example: 12 - method: - type: string - enum: - - state_vector - - sampling - example: sampling - description: state_vector method valid only for 'simulator' devices - nShots: - type: integer - minimum: 1 - maximum: 10000000 - example: '1000' - description: Parameter valid only for sampling method - operator: - $ref: '#/components/schemas/tasks.Operator' - qubitAllocation: - description: Parameter valid only for QPU devices - type: object - additionalProperties: - type: integer - example: - '0': 12 - '1': 16 - skipTranspilation: - type: boolean - default: false - example: false - seedTranspilation: - description: Parameter valid only if skipTranspilation is false - type: integer - example: 873 - seedSimulation: - description: Parameter valid only for 'simulator' devices - type: integer - example: 39058567 - roErrorMitigation: - description: Parameter valid only for QPU devices - type: string - enum: - - none - - pseudo_inverse - - least_square - default: none - example: pseudo_inverse - nPerNode: - description: Parameter valid only for simulator devices - type: integer - minimum: 1 - example: 5 - simulationOpt: - description: Parameter valid only for simulator devices - type: object - example: - optimizationMethod: light - optimizationBlockSize: 1 - optimizationSwapLevel: 1 - note: - type: string - example: Bell State Estimation Example - required: - - code - - device - - method - - operator - tasks.GetEstimationTaskStatusResponse: - description: task status - type: object - properties: - taskId: - $ref: '#/components/schemas/tasks.TaskId' - status: - $ref: '#/components/schemas/tasks.TaskStatus' - required: - - taskId - - status - results.ResultStatus: - type: string - enum: - - SUCCESS - - FAILURE - - CANCELLED - default: SUCCESS - example: SUCCESS - results.SamplingResultDef: + jobs.GetJobStatusResponse: + description: job status type: object properties: - taskId: - $ref: '#/components/schemas/tasks.TaskId' + job_id: + $ref: '#/components/schemas/jobs.JobId' status: - $ref: '#/components/schemas/results.ResultStatus' - result: - description: Provided only for successful results - type: object - additionalProperties: - type: integer - minProperties: 2 - example: - '11': 4980 - '00': 5020 - reason: - description: Provided only for unsuccessful (failed, cancelled) results - type: string - transpiledCode: - description: Provided only for tasks with transpilation (tasks created with skipTranspilation=False), if traspilation was successfull - type: string - qubitAllocation: - description: Parameter valid only for QPU devices - type: object - additionalProperties: - type: integer - example: - '0': 0 - '1': 4 - required: - - taskId - - status - results.EstimationResultDef: - type: object - properties: - taskId: - $ref: '#/components/schemas/tasks.TaskId' - status: - $ref: '#/components/schemas/results.ResultStatus' - result: - description: Real and imaginary components of complex estimation result value
Provided only for successful results - type: array - items: - type: number - minItems: 1 - maxItems: 2 - example: - - 1.5 - - 2.8 - reason: - description: Provided only for unsuccessful (failed, cancelled) results - type: string - transpiledCode: - description: Provided only for tasks with transpilation (tasks created with skipTranspilation=False), if traspilation was successfull - type: string - qubitAllocation: - description: Parameter valid only for QPU devices - type: object - additionalProperties: - type: integer - example: - '0': 0 - '1': 4 + $ref: '#/components/schemas/jobs.JobStatus' required: - - taskId + - job_id - status diff --git a/docs/sample/architecture/cancel-case-tasks-02.csv b/docs/sample/architecture/cancel-case-tasks-02.csv index eb281bc..619e833 100644 --- a/docs/sample/architecture/cancel-case-tasks-02.csv +++ b/docs/sample/architecture/cancel-case-tasks-02.csv @@ -1,2 +1,2 @@ id,owner,name,device,n_qubits,n_nodes,code,action,method,shots,operator,qubit_allocation,skip_transpilation,seed_transpilation,seed_simulation,n_per_node,simulation_opt,ro_error_mitigation,note,status,created_at -2c7a254b-4985-43eb-b0f3-598c88a8c36f,bob,sampling task,SVSim,null,1,"OPENQASM 3.0;include ""stdgates.inc"";qubit[2] q;h q[0];cx q[0], q[1];",sampling,null,1000,null,null,1,null,456,1,"{""optimizationMethod"": ""normal"", ""optimizationBlockSize"": 1, ""optimizationSwapLevel"": 1}",null,sampling task example,CANCELLING,2024-06-27 01:16:08 +2c7a254b-4985-43eb-b0f3-598c88a8c36f,bob,sampling task,SVSim,null,1,"OPENQASM 3.0;include ""stdgates.inc"";qubit[2] q;h q[0];cx q[0], q[1];",sampling,null,1000,null,null,1,null,456,1,"{""optimizationMethod"": ""normal"", ""optimizationBlockSize"": 1, ""optimizationSwapLevel"": 1}",null,sampling task example,cancelling,2024-06-27 01:16:08 diff --git a/docs/sample/architecture/success-case-tasks-02.csv b/docs/sample/architecture/success-case-tasks-02.csv index 861fd43..5a4d112 100644 --- a/docs/sample/architecture/success-case-tasks-02.csv +++ b/docs/sample/architecture/success-case-tasks-02.csv @@ -1,3 +1,3 @@ id,owner,name,device,n_qubits,n_nodes,code,action,method,shots,operator,qubit_allocation,skip_transpilation,seed_transpilation,seed_simulation,n_per_node,simulation_opt,ro_error_mitigation,note,status,created_at -0b45f006-8276-4bd4-9d97-ce149bc236d0,alice,Bell State Sampling,SC,null,null,"OPENQASM 3.0;include ""stdgates.inc"";qubit[2] q;h q[0];cx q[0], q[1];",sampling,null,1000,null,null,0,null,null,null,null,pseudo_inverse,Bell State Sampling,QUEUED,2024-05-28 05:46:22 -4eae977e-c9ae-4cb2-9dc4-97b09a3668f6,bob,null,SC,null,null,"OPENQASM 3.0;include ""stdgates.inc"";qubit[2] q;h q[0];cx q[0], q[1];",estimation,sampling,100,"[[""X 0 X 1"", [1.2, 0.0001]], [""Z 1"", [1.5, 0.0]]]","{""q[0]"": 2, ""q[1]"": 1}",1,null,null,null,null,null,null,QUEUED,2024-06-20 03:20:12 +0b45f006-8276-4bd4-9d97-ce149bc236d0,alice,Bell State Sampling,SC,null,null,"OPENQASM 3.0;include ""stdgates.inc"";qubit[2] q;h q[0];cx q[0], q[1];",sampling,null,1000,null,null,0,null,null,null,null,pseudo_inverse,Bell State Sampling,submitted,2024-05-28 05:46:22 +4eae977e-c9ae-4cb2-9dc4-97b09a3668f6,bob,null,SC,null,null,"OPENQASM 3.0;include ""stdgates.inc"";qubit[2] q;h q[0];cx q[0], q[1];",estimation,sampling,100,"[[""X 0 X 1"", [1.2, 0.0001]], [""Z 1"", [1.5, 0.0]]]","{""q[0]"": 2, ""q[1]"": 1}",1,null,null,null,null,null,null,submitted,2024-06-20 03:20:12 diff --git a/docs/sample/schema/devices.csv b/docs/sample/schema/devices.csv index 544d2c1..cecda89 100644 --- a/docs/sample/schema/devices.csv +++ b/docs/sample/schema/devices.csv @@ -1,3 +1,3 @@ -id,device_type,status,restart_at,pending_tasks,n_qubits,n_nodes,basis_gates,instructions,calibration_data,calibrated_at,description +id,device_type,status,available_at,pending_tasks,n_qubits,n_nodes,basis_gates,instructions,calibration_data,calibrated_at,description SC,QPU,NOT_AVAILABLE,2024-10-01 00:00:00,0,3,null,"[""sx"", ""rz"", ""rzx""]","[""measure"", ""barrier""]","{""qubitConnectivity"": [""(0,1)"", ""(1,2)""],""t1"": {""0"": 55.51, ""1"": 37.03, ""2"": 57.13},""t2"": {""0"": 99.31, ""1"": 111.03, ""2"": 30.12},""gateError"": {""sx"": {""0"": 6.92e-3, ""1"": 2.96e-3, ""2"": 7.2e-2}, ""rzx"": {""(0, 1)"": 0.2, ""(1, 2)"": 0.15}},""measProb0As1"": {""0"": 6.08e-3, ""1"": 1.2e-2, ""2"": 2.48e-1},""measProb1As0"": {""0"": 2.81e-2, ""1"": 3.86e-1, ""2"": 8.11e-2},""gateDuration"": {""sx"": {""0"": 29.3, ""1"": 50.9, ""2"": 45.4}, ""rzx"": {""(0, 1)"": 150, ""(1, 2)"": 200}}}",2024-05-28 11:45:34,Superconducting quantum computer SVSim,simulator,AVAILABLE,null,116,40,1024,"[""x"", ""y"", ""z"", ""rx"", ""ry"", ""rz"", ""cx""]","[""measure"", ""barrier"", ""reset""]",null,null,State vector-based quantum circuit simulator diff --git a/docs/sample/schema/tasks.csv b/docs/sample/schema/tasks.csv index 06f210b..2bc76f2 100644 --- a/docs/sample/schema/tasks.csv +++ b/docs/sample/schema/tasks.csv @@ -12,7 +12,7 @@ cx q[0], q[1]; barrier q[0], q[1]; meas[0] = measure q[0]; meas[1] = measure q[1];",estimation,sampling,1024,"[[""I"", [1.0, 0.0]], [""X 0"", [1.0, 0.0]], [""X 0 X 1"", [0.5, 0.0]], [""Y 0 Y 1"", [0.5, 0.0]], [""Z 0 Z 1"", [-1.5, 0.0]]]",null,0,null,null,1,null,null,null,FAILED,2024-06-25 07:17:36 -c89d6302-fa42-40be-b9ab-7bb04a8514b1,alice,sampling task,SC,null,null,"OPENQASM 3.0;include ""stdgates.inc"";qubit[2] q;h q[0];cx q[0], q[1];",sampling,null,100,null,null,1,null,null,null,null,none,sampling task example,QUEUED,2024-05-28 13:50:04 +c89d6302-fa42-40be-b9ab-7bb04a8514b1,alice,sampling task,SC,null,null,"OPENQASM 3.0;include ""stdgates.inc"";qubit[2] q;h q[0];cx q[0], q[1];",sampling,null,100,null,null,1,null,null,null,null,none,sampling task example,submitted,2024-05-28 13:50:04 d4a56fd4-a5bb-4450-a5fb-716ef26e33c5,alice,My sampling circuit,SVSim,null,null,"OPENQASM 3.0; include ""stdgates.inc""; qubit[2] q; bit[1] c; h q[0]; cx q[0], q[1];",sampling,null,100,null,null,0,0,1214,1,null,null,null,COMPLETED,2024-06-18 02:40:49 da7a2b86-a87a-4ea6-a6ca-fdd96810f7c9,bob,sampling task,SVSim,null,1,"OPENQASM 3.0;include ""stdgates.inc"";qubit[2] q;h q[0];cx q[0], q[1];",sampling,null,100,null,null,1,null,456,1,"{""optimizationMethod"": ""normal"", ""optimizationBlockSize"": 1, ""optimizationSwapLevel"": 1}",null,sampling task example,COMPLETED,2024-06-27 00:25:58 eb25ef48-9056-460d-820c-249e8edef0cc,alice,null,SVSim,null,null,"OPENQASM 3; diff --git a/docs/schema/schema.json b/docs/schema/schema.json index 1bfe758..4ddbce2 100644 --- a/docs/schema/schema.json +++ b/docs/schema/schema.json @@ -1 +1,465 @@ -{"name":"main","desc":"","tables":[{"name":"devices","type":"BASE TABLE","comment":"","columns":[{"name":"id","type":"varchar(64)","nullable":false,"default":null,"comment":""},{"name":"device_type","type":"enum('QPU','simulator')","nullable":false,"default":null,"comment":""},{"name":"status","type":"enum('AVAILABLE','NOT_AVAILABLE')","nullable":false,"default":"NOT_AVAILABLE","comment":""},{"name":"restart_at","type":"datetime","nullable":true,"default":null,"comment":""},{"name":"pending_tasks","type":"int","nullable":false,"default":"0","comment":""},{"name":"n_qubits","type":"int","nullable":false,"default":null,"comment":""},{"name":"n_nodes","type":"int","nullable":true,"default":null,"comment":""},{"name":"basis_gates","type":"varchar(256)","nullable":false,"default":null,"comment":""},{"name":"instructions","type":"varchar(64)","nullable":false,"default":null,"comment":""},{"name":"calibration_data","type":"text","nullable":true,"default":null,"comment":""},{"name":"calibrated_at","type":"datetime","nullable":true,"default":null,"comment":""},{"name":"description","type":"varchar(128)","nullable":false,"default":null,"comment":""}],"indexes":[{"name":"PRIMARY","def":"PRIMARY KEY (id) USING BTREE","table":"devices","columns":["id"],"comment":""}],"constraints":[{"name":"PRIMARY","type":"PRIMARY KEY","def":"PRIMARY KEY (id)","table":"devices","referenced_table":null,"columns":["id"],"referenced_columns":null,"comment":""}],"triggers":[],"def":"CREATE TABLE `devices` (\n `id` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,\n `device_type` enum('QPU','simulator') COLLATE utf8mb4_unicode_ci NOT NULL,\n `status` enum('AVAILABLE','NOT_AVAILABLE') COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'NOT_AVAILABLE',\n `restart_at` datetime DEFAULT NULL,\n `pending_tasks` int NOT NULL DEFAULT '0',\n `n_qubits` int NOT NULL,\n `n_nodes` int DEFAULT NULL,\n `basis_gates` varchar(256) COLLATE utf8mb4_unicode_ci NOT NULL,\n `instructions` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,\n `calibration_data` text COLLATE utf8mb4_unicode_ci,\n `calibrated_at` datetime DEFAULT NULL,\n `description` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL,\n PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"},{"name":"results","type":"BASE TABLE","comment":"","columns":[{"name":"task_id","type":"varbinary(16)","nullable":false,"default":null,"comment":""},{"name":"status","type":"enum('SUCCESS','FAILURE','CANCELLED')","nullable":false,"default":null,"comment":""},{"name":"result","type":"text","nullable":true,"default":null,"comment":""},{"name":"reason","type":"text","nullable":true,"default":null,"comment":""},{"name":"transpiled_code","type":"text","nullable":true,"default":null,"comment":""},{"name":"qubit_allocation","type":"text","nullable":true,"default":null,"comment":""}],"indexes":[{"name":"PRIMARY","def":"PRIMARY KEY (task_id) USING BTREE","table":"results","columns":["task_id"],"comment":""}],"constraints":[{"name":"PRIMARY","type":"PRIMARY KEY","def":"PRIMARY KEY (task_id)","table":"results","referenced_table":null,"columns":["task_id"],"referenced_columns":null,"comment":""},{"name":"results_ibfk_1","type":"FOREIGN KEY","def":"FOREIGN KEY (task_id) REFERENCES tasks (id)","table":"results","referenced_table":"tasks","columns":["task_id"],"referenced_columns":["id"],"comment":""}],"triggers":[{"name":"update_tasks_status_trigger","def":"CREATE TRIGGER update_tasks_status_trigger AFTER INSERT ON results\nFOR EACH ROW\nBEGIN\n\tIF NEW.status = 'SUCCESS' THEN\n \t\tUPDATE main.tasks SET status = 'COMPLETED' WHERE id = NEW.task_id;\n \tELSEIF NEW.status = 'FAILURE' THEN\n \t\tUPDATE main.tasks SET status = 'FAILED' WHERE id = NEW.task_id;\n \tELSEIF NEW.status = 'CANCELLED' THEN\n \t\tUPDATE main.tasks SET status = 'CANCELLED' WHERE id = NEW.task_id;\n \tEND IF;\nEND","comment":""}],"def":"CREATE TABLE `results` (\n `task_id` varbinary(16) NOT NULL,\n `status` enum('SUCCESS','FAILURE','CANCELLED') COLLATE utf8mb4_unicode_ci NOT NULL,\n `result` text COLLATE utf8mb4_unicode_ci,\n `reason` text COLLATE utf8mb4_unicode_ci,\n `transpiled_code` text COLLATE utf8mb4_unicode_ci,\n `qubit_allocation` text COLLATE utf8mb4_unicode_ci,\n PRIMARY KEY (`task_id`),\n CONSTRAINT `results_ibfk_1` FOREIGN KEY (`task_id`) REFERENCES `tasks` (`id`) ON DELETE CASCADE\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"},{"name":"tasks","type":"BASE TABLE","comment":"","columns":[{"name":"id","type":"varbinary(16)","nullable":false,"default":null,"comment":""},{"name":"owner","type":"varchar(64)","nullable":false,"default":null,"comment":""},{"name":"name","type":"varchar(256)","nullable":true,"default":null,"comment":""},{"name":"device","type":"varchar(64)","nullable":false,"default":null,"comment":""},{"name":"n_qubits","type":"int","nullable":true,"default":null,"comment":""},{"name":"n_nodes","type":"int","nullable":true,"default":null,"comment":""},{"name":"code","type":"text","nullable":false,"default":null,"comment":""},{"name":"action","type":"enum('sampling','estimation')","nullable":false,"default":null,"comment":""},{"name":"method","type":"enum('state_vector','sampling')","nullable":true,"default":null,"comment":""},{"name":"shots","type":"int","nullable":true,"default":null,"comment":""},{"name":"operator","type":"varchar(1024)","nullable":true,"default":null,"comment":""},{"name":"qubit_allocation","type":"text","nullable":true,"default":null,"comment":""},{"name":"skip_transpilation","type":"tinyint(1)","nullable":false,"default":"0","comment":""},{"name":"seed_transpilation","type":"int","nullable":true,"default":null,"comment":""},{"name":"seed_simulation","type":"int","nullable":true,"default":null,"comment":""},{"name":"n_per_node","type":"int unsigned","nullable":true,"default":null,"comment":""},{"name":"simulation_opt","type":"text","nullable":true,"default":null,"comment":""},{"name":"ro_error_mitigation","type":"enum('none','pseudo_inverse','least_square')","nullable":true,"default":null,"comment":""},{"name":"note","type":"varchar(1024)","nullable":true,"default":null,"comment":""},{"name":"status","type":"enum('QUEUED','QUEUED_FETCHED','RUNNING','COMPLETED','FAILED','CANCELLING','CANCELLING_FETCHED','CANCELLED')","nullable":false,"default":"QUEUED","comment":""},{"name":"created_at","type":"timestamp","nullable":true,"default":"CURRENT_TIMESTAMP","extra_def":"DEFAULT_GENERATED","comment":""}],"indexes":[{"name":"device","def":"KEY device (device) USING BTREE","table":"tasks","columns":["device"],"comment":""},{"name":"PRIMARY","def":"PRIMARY KEY (id) USING BTREE","table":"tasks","columns":["id"],"comment":""}],"constraints":[{"name":"PRIMARY","type":"PRIMARY KEY","def":"PRIMARY KEY (id)","table":"tasks","referenced_table":null,"columns":["id"],"referenced_columns":null,"comment":""},{"name":"tasks_ibfk_1","type":"FOREIGN KEY","def":"FOREIGN KEY (device) REFERENCES devices (id)","table":"tasks","referenced_table":"devices","columns":["device"],"referenced_columns":["id"],"comment":""}],"triggers":[],"def":"CREATE TABLE `tasks` (\n `id` varbinary(16) NOT NULL,\n `owner` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,\n `name` varchar(256) COLLATE utf8mb4_unicode_ci DEFAULT NULL,\n `device` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,\n `n_qubits` int DEFAULT NULL,\n `n_nodes` int DEFAULT NULL,\n `code` text COLLATE utf8mb4_unicode_ci NOT NULL,\n `action` enum('sampling','estimation') COLLATE utf8mb4_unicode_ci NOT NULL,\n `method` enum('state_vector','sampling') COLLATE utf8mb4_unicode_ci DEFAULT NULL,\n `shots` int DEFAULT NULL,\n `operator` varchar(1024) COLLATE utf8mb4_unicode_ci DEFAULT NULL,\n `qubit_allocation` text COLLATE utf8mb4_unicode_ci,\n `skip_transpilation` tinyint(1) NOT NULL DEFAULT '0',\n `seed_transpilation` int DEFAULT NULL,\n `seed_simulation` int DEFAULT NULL,\n `n_per_node` int unsigned DEFAULT NULL,\n `simulation_opt` text COLLATE utf8mb4_unicode_ci,\n `ro_error_mitigation` enum('none','pseudo_inverse','least_square') COLLATE utf8mb4_unicode_ci DEFAULT NULL,\n `note` varchar(1024) COLLATE utf8mb4_unicode_ci DEFAULT NULL,\n `status` enum('QUEUED','QUEUED_FETCHED','RUNNING','COMPLETED','FAILED','CANCELLING','CANCELLING_FETCHED','CANCELLED') COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'QUEUED',\n `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (`id`),\n KEY `device` (`device`),\n CONSTRAINT `tasks_ibfk_1` FOREIGN KEY (`device`) REFERENCES `devices` (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"}],"relations":[{"table":"results","columns":["task_id"],"cardinality":"Zero or one","parent_table":"tasks","parent_columns":["id"],"parent_cardinality":"Exactly one","def":"FOREIGN KEY (task_id) REFERENCES tasks (id)","virtual":false},{"table":"tasks","columns":["device"],"cardinality":"Zero or more","parent_table":"devices","parent_columns":["id"],"parent_cardinality":"Exactly one","def":"FOREIGN KEY (device) REFERENCES devices (id)","virtual":false}],"functions":[],"driver":{"name":"mysql","database_version":"8.0.37","meta":{"dict":{"Functions":"Stored procedures and functions"}}}} +{ + "name": "main", + "desc": "", + "tables": [ + { + "name": "devices", + "type": "BASE TABLE", + "comment": "", + "columns": [ + { + "name": "id", + "type": "varchar(64)", + "nullable": false, + "default": null, + "comment": "" + }, + { + "name": "device_type", + "type": "enum('QPU','simulator')", + "nullable": false, + "default": null, + "comment": "" + }, + { + "name": "status", + "type": "enum('AVAILABLE','NOT_AVAILABLE')", + "nullable": false, + "default": "NOT_AVAILABLE", + "comment": "" + }, + { + "name": "restart_at", + "type": "datetime", + "nullable": true, + "default": null, + "comment": "" + }, + { + "name": "pending_tasks", + "type": "int", + "nullable": false, + "default": "0", + "comment": "" + }, + { + "name": "n_qubits", + "type": "int", + "nullable": false, + "default": null, + "comment": "" + }, + { + "name": "n_nodes", + "type": "int", + "nullable": true, + "default": null, + "comment": "" + }, + { + "name": "basis_gates", + "type": "varchar(256)", + "nullable": false, + "default": null, + "comment": "" + }, + { + "name": "instructions", + "type": "varchar(64)", + "nullable": false, + "default": null, + "comment": "" + }, + { + "name": "calibration_data", + "type": "text", + "nullable": true, + "default": null, + "comment": "" + }, + { + "name": "calibrated_at", + "type": "datetime", + "nullable": true, + "default": null, + "comment": "" + }, + { + "name": "description", + "type": "varchar(128)", + "nullable": false, + "default": null, + "comment": "" + } + ], + "indexes": [ + { + "name": "PRIMARY", + "def": "PRIMARY KEY (id) USING BTREE", + "table": "devices", + "columns": [ + "id" + ], + "comment": "" + } + ], + "constraints": [ + { + "name": "PRIMARY", + "type": "PRIMARY KEY", + "def": "PRIMARY KEY (id)", + "table": "devices", + "referenced_table": null, + "columns": [ + "id" + ], + "referenced_columns": null, + "comment": "" + } + ], + "triggers": [], + "def": "CREATE TABLE `devices` (\n `id` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,\n `device_type` enum('QPU','simulator') COLLATE utf8mb4_unicode_ci NOT NULL,\n `status` enum('AVAILABLE','NOT_AVAILABLE') COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'NOT_AVAILABLE',\n `restart_at` datetime DEFAULT NULL,\n `pending_tasks` int NOT NULL DEFAULT '0',\n `n_qubits` int NOT NULL,\n `n_nodes` int DEFAULT NULL,\n `basis_gates` varchar(256) COLLATE utf8mb4_unicode_ci NOT NULL,\n `instructions` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,\n `calibration_data` text COLLATE utf8mb4_unicode_ci,\n `calibrated_at` datetime DEFAULT NULL,\n `description` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL,\n PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci" + }, + { + "name": "results", + "type": "BASE TABLE", + "comment": "", + "columns": [ + { + "name": "task_id", + "type": "varbinary(16)", + "nullable": false, + "default": null, + "comment": "" + }, + { + "name": "status", + "type": "enum('SUCCESS','FAILURE','CANCELLED')", + "nullable": false, + "default": null, + "comment": "" + }, + { + "name": "result", + "type": "text", + "nullable": true, + "default": null, + "comment": "" + }, + { + "name": "reason", + "type": "text", + "nullable": true, + "default": null, + "comment": "" + }, + { + "name": "transpiled_code", + "type": "text", + "nullable": true, + "default": null, + "comment": "" + }, + { + "name": "qubit_allocation", + "type": "text", + "nullable": true, + "default": null, + "comment": "" + } + ], + "indexes": [ + { + "name": "PRIMARY", + "def": "PRIMARY KEY (task_id) USING BTREE", + "table": "results", + "columns": [ + "task_id" + ], + "comment": "" + } + ], + "constraints": [ + { + "name": "PRIMARY", + "type": "PRIMARY KEY", + "def": "PRIMARY KEY (task_id)", + "table": "results", + "referenced_table": null, + "columns": [ + "task_id" + ], + "referenced_columns": null, + "comment": "" + }, + { + "name": "results_ibfk_1", + "type": "FOREIGN KEY", + "def": "FOREIGN KEY (task_id) REFERENCES tasks (id)", + "table": "results", + "referenced_table": "tasks", + "columns": [ + "task_id" + ], + "referenced_columns": [ + "id" + ], + "comment": "" + } + ], + "triggers": [ + { + "name": "update_tasks_status_trigger", + "def": "CREATE TRIGGER update_tasks_status_trigger AFTER INSERT ON results\nFOR EACH ROW\nBEGIN\n\tIF NEW.status = 'SUCCESS' THEN\n \t\tUPDATE main.tasks SET status = 'COMPLETED' WHERE id = NEW.task_id;\n \tELSEIF NEW.status = 'FAILURE' THEN\n \t\tUPDATE main.tasks SET status = 'FAILED' WHERE id = NEW.task_id;\n \tELSEIF NEW.status = 'CANCELLED' THEN\n \t\tUPDATE main.tasks SET status = 'CANCELLED' WHERE id = NEW.task_id;\n \tEND IF;\nEND", + "comment": "" + } + ], + "def": "CREATE TABLE `results` (\n `task_id` varbinary(16) NOT NULL,\n `status` enum('SUCCESS','FAILURE','CANCELLED') COLLATE utf8mb4_unicode_ci NOT NULL,\n `result` text COLLATE utf8mb4_unicode_ci,\n `reason` text COLLATE utf8mb4_unicode_ci,\n `transpiled_code` text COLLATE utf8mb4_unicode_ci,\n `qubit_allocation` text COLLATE utf8mb4_unicode_ci,\n PRIMARY KEY (`task_id`),\n CONSTRAINT `results_ibfk_1` FOREIGN KEY (`task_id`) REFERENCES `tasks` (`id`) ON DELETE CASCADE\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci" + }, + { + "name": "tasks", + "type": "BASE TABLE", + "comment": "", + "columns": [ + { + "name": "id", + "type": "varbinary(16)", + "nullable": false, + "default": null, + "comment": "" + }, + { + "name": "owner", + "type": "varchar(64)", + "nullable": false, + "default": null, + "comment": "" + }, + { + "name": "name", + "type": "varchar(256)", + "nullable": true, + "default": null, + "comment": "" + }, + { + "name": "device", + "type": "varchar(64)", + "nullable": false, + "default": null, + "comment": "" + }, + { + "name": "n_qubits", + "type": "int", + "nullable": true, + "default": null, + "comment": "" + }, + { + "name": "n_nodes", + "type": "int", + "nullable": true, + "default": null, + "comment": "" + }, + { + "name": "code", + "type": "text", + "nullable": false, + "default": null, + "comment": "" + }, + { + "name": "action", + "type": "enum('sampling','estimation')", + "nullable": false, + "default": null, + "comment": "" + }, + { + "name": "method", + "type": "enum('state_vector','sampling')", + "nullable": true, + "default": null, + "comment": "" + }, + { + "name": "shots", + "type": "int", + "nullable": true, + "default": null, + "comment": "" + }, + { + "name": "operator", + "type": "varchar(1024)", + "nullable": true, + "default": null, + "comment": "" + }, + { + "name": "qubit_allocation", + "type": "text", + "nullable": true, + "default": null, + "comment": "" + }, + { + "name": "skip_transpilation", + "type": "tinyint(1)", + "nullable": false, + "default": "0", + "comment": "" + }, + { + "name": "seed_transpilation", + "type": "int", + "nullable": true, + "default": null, + "comment": "" + }, + { + "name": "seed_simulation", + "type": "int", + "nullable": true, + "default": null, + "comment": "" + }, + { + "name": "n_per_node", + "type": "int unsigned", + "nullable": true, + "default": null, + "comment": "" + }, + { + "name": "simulation_opt", + "type": "text", + "nullable": true, + "default": null, + "comment": "" + }, + { + "name": "ro_error_mitigation", + "type": "enum('none','pseudo_inverse','least_square')", + "nullable": true, + "default": null, + "comment": "" + }, + { + "name": "note", + "type": "varchar(1024)", + "nullable": true, + "default": null, + "comment": "" + }, + { + "name": "status", + "type": "enum('submitted','QUEUED_FETCHED','RUNNING','COMPLETED','FAILED','cancelling','CANCELLING_FETCHED','CANCELLED')", + "nullable": false, + "default": "submitted", + "comment": "" + }, + { + "name": "created_at", + "type": "timestamp", + "nullable": true, + "default": "CURRENT_TIMESTAMP", + "extra_def": "DEFAULT_GENERATED", + "comment": "" + } + ], + "indexes": [ + { + "name": "device", + "def": "KEY device (device) USING BTREE", + "table": "tasks", + "columns": [ + "device" + ], + "comment": "" + }, + { + "name": "PRIMARY", + "def": "PRIMARY KEY (id) USING BTREE", + "table": "tasks", + "columns": [ + "id" + ], + "comment": "" + } + ], + "constraints": [ + { + "name": "PRIMARY", + "type": "PRIMARY KEY", + "def": "PRIMARY KEY (id)", + "table": "tasks", + "referenced_table": null, + "columns": [ + "id" + ], + "referenced_columns": null, + "comment": "" + }, + { + "name": "tasks_ibfk_1", + "type": "FOREIGN KEY", + "def": "FOREIGN KEY (device) REFERENCES devices (id)", + "table": "tasks", + "referenced_table": "devices", + "columns": [ + "device" + ], + "referenced_columns": [ + "id" + ], + "comment": "" + } + ], + "triggers": [], + "def": "CREATE TABLE `tasks` (\n `id` varbinary(16) NOT NULL,\n `owner` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,\n `name` varchar(256) COLLATE utf8mb4_unicode_ci DEFAULT NULL,\n `device` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,\n `n_qubits` int DEFAULT NULL,\n `n_nodes` int DEFAULT NULL,\n `code` text COLLATE utf8mb4_unicode_ci NOT NULL,\n `action` enum('sampling','estimation') COLLATE utf8mb4_unicode_ci NOT NULL,\n `method` enum('state_vector','sampling') COLLATE utf8mb4_unicode_ci DEFAULT NULL,\n `shots` int DEFAULT NULL,\n `operator` varchar(1024) COLLATE utf8mb4_unicode_ci DEFAULT NULL,\n `qubit_allocation` text COLLATE utf8mb4_unicode_ci,\n `skip_transpilation` tinyint(1) NOT NULL DEFAULT '0',\n `seed_transpilation` int DEFAULT NULL,\n `seed_simulation` int DEFAULT NULL,\n `n_per_node` int unsigned DEFAULT NULL,\n `simulation_opt` text COLLATE utf8mb4_unicode_ci,\n `ro_error_mitigation` enum('none','pseudo_inverse','least_square') COLLATE utf8mb4_unicode_ci DEFAULT NULL,\n `note` varchar(1024) COLLATE utf8mb4_unicode_ci DEFAULT NULL,\n `status` enum('submitted','QUEUED_FETCHED','RUNNING','COMPLETED','FAILED','cancelling','CANCELLING_FETCHED','CANCELLED') COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'submitted',\n `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (`id`),\n KEY `device` (`device`),\n CONSTRAINT `tasks_ibfk_1` FOREIGN KEY (`device`) REFERENCES `devices` (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci" + } + ], + "relations": [ + { + "table": "results", + "columns": [ + "task_id" + ], + "cardinality": "Zero or one", + "parent_table": "tasks", + "parent_columns": [ + "id" + ], + "parent_cardinality": "Exactly one", + "def": "FOREIGN KEY (task_id) REFERENCES tasks (id)", + "virtual": false + }, + { + "table": "tasks", + "columns": [ + "device" + ], + "cardinality": "Zero or more", + "parent_table": "devices", + "parent_columns": [ + "id" + ], + "parent_cardinality": "Exactly one", + "def": "FOREIGN KEY (device) REFERENCES devices (id)", + "virtual": false + } + ], + "functions": [], + "driver": { + "name": "mysql", + "database_version": "8.0.37", + "meta": { + "dict": { + "Functions": "Stored procedures and functions" + } + } + } +} \ No newline at end of file diff --git a/docs/schema/tasks.md b/docs/schema/tasks.md index 038c9e0..938f597 100644 --- a/docs/schema/tasks.md +++ b/docs/schema/tasks.md @@ -26,7 +26,7 @@ CREATE TABLE `tasks` ( `simulation_opt` text COLLATE utf8mb4_unicode_ci, `ro_error_mitigation` enum('none','pseudo_inverse','least_square') COLLATE utf8mb4_unicode_ci DEFAULT NULL, `note` varchar(1024) COLLATE utf8mb4_unicode_ci DEFAULT NULL, - `status` enum('QUEUED','QUEUED_FETCHED','RUNNING','COMPLETED','FAILED','CANCELLING','CANCELLING_FETCHED','CANCELLED') COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'QUEUED', + `status` enum('submitted','QUEUED_FETCHED','RUNNING','COMPLETED','FAILED','cancelling','CANCELLING_FETCHED','CANCELLED') COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'submitted', `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `device` (`device`), @@ -59,7 +59,7 @@ CREATE TABLE `tasks` ( | simulation_opt | text | | true | | | | | | ro_error_mitigation | enum('none','pseudo_inverse','least_square') | | true | | | | | | note | varchar(1024) | | true | | | | | -| status | enum('QUEUED','QUEUED_FETCHED','RUNNING','COMPLETED','FAILED','CANCELLING','CANCELLING_FETCHED','CANCELLED') | QUEUED | false | | | | | +| status | enum('submitted','QUEUED_FETCHED','RUNNING','COMPLETED','FAILED','cancelling','CANCELLING_FETCHED','CANCELLED') | submitted | false | | | | | | created_at | timestamp | CURRENT_TIMESTAMP | true | DEFAULT_GENERATED | | | | ## Constraints diff --git a/operation/db/init.sql b/operation/db/init.sql index 4aac0cf..63f218f 100644 --- a/operation/db/init.sql +++ b/operation/db/init.sql @@ -1,94 +1,67 @@ -DROP TABLE IF EXISTS main.results; -DROP TABLE IF EXISTS main.tasks; +-- DROP TABLE IF EXISTS main.results; +-- DROP TABLE IF EXISTS main.tasks; +-- DROP TRIGGER IF EXISTS main.update_tasks_status_trigger; +DROP TABLE IF EXISTS main.jobs; DROP TABLE IF EXISTS main.devices; -DROP TRIGGER IF EXISTS main.update_tasks_status_trigger; - +drop table main.devices; CREATE TABLE IF NOT EXISTS main.devices ( id VARCHAR(64) PRIMARY KEY, - device_type ENUM ('QPU', 'simulator') NOT NULL, - status ENUM ('AVAILABLE', 'NOT_AVAILABLE') DEFAULT 'NOT_AVAILABLE' NOT NULL, - restart_at DATETIME, - pending_tasks INT DEFAULT 0 NOT NULL, - n_qubits INT NOT NULL, - n_nodes INT, + device_type VARCHAR(32) DEFAULT 'QPU' NOT NULL, + status VARCHAR(64) DEFAULT 'available' NOT NULL, + available_at DATETIME, + pending_jobs INT DEFAULT 0 NOT NULL, + n_qubits INT DEFAULT 1 NOT NULL, basis_gates VARCHAR(256) NOT NULL, instructions VARCHAR(64) NOT NULL, - calibration_data TEXT, + device_info TEXT, calibrated_at DATETIME, - description VARCHAR(128) NOT NULL + description VARCHAR(128) NOT NULL, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ); -CREATE TABLE IF NOT EXISTS main.tasks ( - id VARBINARY(16) PRIMARY KEY, +drop table main.jobs; +CREATE TABLE IF NOT EXISTS main.jobs ( + id VARCHAR(64) PRIMARY KEY, owner VARCHAR(64) NOT NULL, - name varchar(256), - device VARCHAR(64) NOT NULL, - n_qubits INT, - n_nodes INT, - code TEXT NOT NULL, - action ENUM ('sampling', 'estimation') NOT NULL, - method ENUM ('state_vector', 'sampling'), - shots INT, - operator VARCHAR(1024), - qubit_allocation TEXT, - skip_transpilation BOOLEAN DEFAULT false NOT NULL, - seed_transpilation INT, - seed_simulation INT, - n_per_node INT UNSIGNED, - simulation_opt text, - ro_error_mitigation enum('none', 'pseudo_inverse', 'least_square'), - note VARCHAR(1024), - status ENUM ('QUEUED', 'QUEUED_FETCHED', 'RUNNING', 'COMPLETED', 'FAILED', 'CANCELLING', 'CANCELLING_FETCHED', 'CANCELLED') NOT NULL DEFAULT 'QUEUED', - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (device) REFERENCES devices(id) + name varchar(256) DEFAULT '' NOT NULL, + description VARCHAR(1024), + device_id VARCHAR(64) NOT NULL, + job_info TEXT, + transpiler_info TEXT, + simulator_info TEXT, + mitigation_info TEXT, + job_type VARCHAR(32) DEFAULT 'sampling' NOT NULL, + shots INT DEFAULT 1000 NOT NULL, + status VARCHAR(32) DEFAULT 'submitted' NOT NULL, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ); -CREATE TABLE IF NOT EXISTS main.results ( - task_id VARBINARY(16) PRIMARY KEY, - status ENUM('SUCCESS', 'FAILURE', 'CANCELLED') NOT NULL, - result TEXT, - reason TEXT, - transpiled_code TEXT, - qubit_allocation TEXT, - FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE -); - -DELIMITER $$ - -CREATE TRIGGER main.update_tasks_status_trigger -AFTER INSERT ON main.results -FOR EACH ROW -BEGIN - IF NEW.status = 'SUCCESS' THEN - UPDATE main.tasks SET status = 'COMPLETED' WHERE id = NEW.task_id; - ELSEIF NEW.status = 'FAILURE' THEN - UPDATE main.tasks SET status = 'FAILED' WHERE id = NEW.task_id; - ELSEIF NEW.status = 'CANCELLED' THEN - UPDATE main.tasks SET status = 'CANCELLED' WHERE id = NEW.task_id; - END IF; -END$$ - -DELIMITER ; - -# Insert devices -INSERT INTO main.devices (id, device_type, n_qubits, n_nodes, basis_gates, instructions, description) -SELECT 'SC', 'QPU', 64, NULL, '["sx", "rz", "rzx90", "id"]', '["measure", "barrier"]', 'Superconducting quantum computer' +-- Insert devices +INSERT INTO main.devices (id, device_type, status, available_at, pending_jobs, n_qubits, basis_gates, instructions, device_info, calibrated_at, description) +SELECT 'SC', 'QPU','available', CURRENT_TIMESTAMP, 9, 64, '["sx", "rz", "rzx90", "id"]', '["measure", "barrier"]', '', CURRENT_TIMESTAMP, 'Superconducting quantum computer' WHERE NOT EXISTS (SELECT * FROM main.devices WHERE id = 'SC'); -INSERT INTO main.devices (id, device_type, n_qubits, n_nodes, basis_gates, instructions, description) -SELECT 'SVSim', 'simulator', 39, 512, '["x", "y", "z", "h", "s", "sdg", "t", "tdg", "rx", "ry", "rz", "cx", "cz", "swap", "u1", "u2", "u3", "u", "p", "id", "sx", "sxdg"]', '["measure", "barrier", "reset"]', 'State vector-based quantum circuit simulator' +INSERT INTO main.devices (id, device_type, status, available_at, pending_jobs, n_qubits, basis_gates, instructions, device_info, calibrated_at, description) +SELECT 'SVSim', 'simulator','available', CURRENT_TIMESTAMP, 0, 39, '["x", "y", "z", "h", "s", "sdg", "t", "tdg", "rx", "ry", "rz", "cx", "cz", "swap", "u1", "u2", "u3", "u", "p", "id", "sx", "sxdg"]', '["measure", "barrier", "reset"]', '', CURRENT_TIMESTAMP, 'State vector-based quantum circuit simulator' WHERE NOT EXISTS (SELECT * FROM main.devices WHERE id = 'SVSim'); -INSERT INTO main.devices (id, device_type, n_qubits, n_nodes, basis_gates, instructions, description) -SELECT 'Kawasaki', 'QPU', 64, NULL, '["sx", "rz", "rzx90", "id"]', '["measure", "barrier"]', 'Superconducting quantum computer' +INSERT INTO main.devices (id, device_type, status, available_at, pending_jobs, n_qubits, basis_gates, instructions, device_info, calibrated_at, description) +SELECT 'Kawasaki', 'QPU','available', CURRENT_TIMESTAMP, 2, 64, '["sx", "rz", "rzx90", "id"]', '["measure", "barrier"]', '', CURRENT_TIMESTAMP, 'Superconducting quantum computer' WHERE NOT EXISTS (SELECT * FROM main.devices WHERE id = 'Kawasaki'); -INSERT INTO main.devices (id, device_type, n_qubits, n_nodes, basis_gates, instructions, description) -SELECT 'test', 'QPU', 64, NULL, '["sx", "rz", "rzx90", "id"]', '["measure", "barrier"]', 'Superconducting quantum computer' -WHERE NOT EXISTS (SELECT * FROM main.devices WHERE id = 'test'); +INSERT INTO main.devices (id, device_type, status, available_at, pending_jobs, n_qubits, basis_gates, instructions, device_info, calibrated_at, description) +SELECT '01927422-86d4-7597-b724-b08a5e7781fc', 'QPU','unavailable', CURRENT_TIMESTAMP, 0, 64, '["sx", "rz", "rzx90", "id"]', '["measure", "barrier"]', '', CURRENT_TIMESTAMP, 'Superconducting quantum computer' +WHERE NOT EXISTS (SELECT * FROM main.devices WHERE id = '01927422-86d4-7597-b724-b08a5e7781fc'); + +-- Insert jobs +INSERT INTO main.jobs (id, owner, name, description, device_id, job_info, transpiler_info, simulator_info, mitigation_info, job_type, shots, status) +SELECT '01927422-86d4-73d6-abb4-f2de6a4f5910', 'admin', 'Test job 1', 'Test job 1 description', 'Kawasaki', '{\'code\': \'todo\'}', '', '', '', 'sampling', 1000, 'submitted' +WHERE NOT EXISTS (SELECT * FROM main.jobs WHERE owner = 'admin' AND name = 'Test job 1'); + +INSERT INTO main.jobs (id, owner, name, description, device_id, job_info, transpiler_info, simulator_info, mitigation_info, job_type, shots, status) +SELECT '01927422-86d4-7cbf-98d3-32f5f1263cd9', 'admin', 'Test job 2', 'Test job 2 description', 'Kawasaki', '{\'code\': \'todo\'}', '', '', '', 'sampling', 1000, 'submitted' +WHERE NOT EXISTS (SELECT * FROM main.jobs WHERE owner = 'admin' AND name = 'Test job 2'); -# Insert tasks -INSERT INTO main.tasks (id, owner, name, device, n_qubits, n_nodes, code, action, method, shots, operator, qubit_allocation, skip_transpilation, seed_transpilation, seed_simulation, n_per_node, simulation_opt, ro_error_mitigation, note, status, created_at) -SELECT UNHEX(REPLACE('7af020f6-2e38-4d70-8cf0-4349650ea08c', '-', '')), 'admin', 'Test task', 'Kawasaki', 2, 12, 'OPENQASM 2.0;\ninclude "qelib1.inc";\nqreg q[2];\nh q[0];\ncx q[0], q[1];\nmeasure q[0] -> c[0];\nmeasure q[1] -> c[1];', 'sampling', 'state_vector', 1024, 'Z0*Z1', NULL, false, NULL, NULL, 1, NULL, 'none', NULL, 'QUEUED', CURRENT_TIMESTAMP -WHERE NOT EXISTS (SELECT * FROM main.tasks WHERE owner = 'admin' AND name = 'Test task'); diff --git a/runnbooks/provider/tasks/get-task.yaml b/runnbooks/provider/tasks/get-task.yaml index 0fc91dd..3414a1d 100644 --- a/runnbooks/provider/tasks/get-task.yaml +++ b/runnbooks/provider/tasks/get-task.yaml @@ -15,4 +15,4 @@ steps: # status code is 200 current.res.status == 200 # body is as expected - && compare(current.res.body, {"action":{"nShots":1024,"name":"sampling"},"code":"OPENQASM 2.0;\ninclude \"qelib1.inc\";\nqreg q[2];\nh q[0];\ncx q[0], q[1];\nmeasure q[0] -\u003e c[0];\nmeasure q[1] -\u003e c[1];","createdAt":"2024-03-28T16:50:27+09:00","device":"Kawasaki","nNodes":12,"nPerNode":1,"nQubits":2,"qubitAllocation":null,"roErrorMitigation":"none","seedSimulation":null,"seedTranspilation":null,"simulationOpt":null,"skipTranspilation":false,"status":"QUEUED","taskId":"7af020f6-2e38-4d70-8cf0-4349650ea08c"}) + && compare(current.res.body, {"action":{"shots":1024,"name":"sampling"},"code":"OPENQASM 2.0;\ninclude \"qelib1.inc\";\nqreg q[2];\nh q[0];\ncx q[0], q[1];\nmeasure q[0] -\u003e c[0];\nmeasure q[1] -\u003e c[1];","createdAt":"2024-03-28T16:50:27+09:00","device_id":"Kawasaki","nNodes":12,"nPerNode":1,"nQubits":2,"qubitAllocation":null,"roErrorMitigation":"none","seedSimulation":null,"seedTranspilation":null,"simulationOpt":null,"skipTranspilation":false,"status":"submitted","taskId":"7af020f6-2e38-4d70-8cf0-4349650ea08c"}) diff --git a/runnbooks/provider/tasks/get-tasks.yaml b/runnbooks/provider/tasks/get-tasks.yaml index 518449f..91522ac 100644 --- a/runnbooks/provider/tasks/get-tasks.yaml +++ b/runnbooks/provider/tasks/get-tasks.yaml @@ -15,4 +15,4 @@ steps: # status code is 200 current.res.status == 200 # body is as expected - && compare(current.res.body, [{"action":{"nShots":1024,"name":"sampling"},"code":"OPENQASM 2.0;\ninclude \"qelib1.inc\";\nqreg q[2];\nh q[0];\ncx q[0], q[1];\nmeasure q[0] -\u003e c[0];\nmeasure q[1] -\u003e c[1];","createdAt":"2024-03-28T16:50:27+09:00","device":"Kawasaki","nNodes":12,"nPerNode":1,"nQubits":2,"qubitAllocation":null,"roErrorMitigation":"none","seedSimulation":null,"seedTranspilation":null,"simulationOpt":null,"skipTranspilation":false,"status":"QUEUED","taskId":"7af020f6-2e38-4d70-8cf0-4349650ea08c"}]) + && compare(current.res.body, [{"action":{"shots":1024,"name":"sampling"},"code":"OPENQASM 2.0;\ninclude \"qelib1.inc\";\nqreg q[2];\nh q[0];\ncx q[0], q[1];\nmeasure q[0] -\u003e c[0];\nmeasure q[1] -\u003e c[1];","createdAt":"2024-03-28T16:50:27+09:00","device_id":"Kawasaki","nNodes":12,"nPerNode":1,"nQubits":2,"qubitAllocation":null,"roErrorMitigation":"none","seedSimulation":null,"seedTranspilation":null,"simulationOpt":null,"skipTranspilation":false,"status":"submitted","taskId":"7af020f6-2e38-4d70-8cf0-4349650ea08c"}]) diff --git a/runnbooks/user/get-task.yaml b/runnbooks/user/get-task.yaml index 1a77210..2383a0f 100644 --- a/runnbooks/user/get-task.yaml +++ b/runnbooks/user/get-task.yaml @@ -14,4 +14,4 @@ steps: # status code is 200 current.res.status == 200 # body is as expected - && compare(current.res.body, {"code":"OPENQASM 2.0;\ninclude \"qelib1.inc\";\nqreg q[2];\nh q[0];\ncx q[0], q[1];\nmeasure q[0] -\u003e c[0];\nmeasure q[1] -\u003e c[1];","device":"Kawasaki","n_nodes":12,"n_per_node":1,"n_qubits":2,"qubit_allocation":null,"ro_error_mitigation":"none","seed_simulation":null,"seed_transpilation":null,"simulation_opt":null,"skip_transpilation":false,"task_id":"7af020f6-2e38-4d70-8cf0-4349650ea08c"}) + && compare(current.res.body, {"code":"OPENQASM 2.0;\ninclude \"qelib1.inc\";\nqreg q[2];\nh q[0];\ncx q[0], q[1];\nmeasure q[0] -\u003e c[0];\nmeasure q[1] -\u003e c[1];","device_id":"Kawasaki","n_nodes":12,"n_per_node":1,"n_qubits":2,"qubit_allocation":null,"ro_error_mitigation":"none","seed_simulation":null,"seed_transpilation":null,"simulation_opt":null,"skip_transpilation":false,"task_id":"7af020f6-2e38-4d70-8cf0-4349650ea08c"})