Skip to content

Commit

Permalink
Merge pull request #14 from UST-QuAntiL/feature/generate-circuits-and…
Browse files Browse the repository at this point in the history
…-post-process

Feature/generate circuits and post process
  • Loading branch information
salmma authored Aug 6, 2024
2 parents 0410727 + 4db5267 commit ba3b225
Show file tree
Hide file tree
Showing 43 changed files with 2,369 additions and 313 deletions.
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
FROM python:3.9-slim
FROM python:3.11

MAINTAINER Marie Salm "[email protected]"

COPY ./requirements.txt /app/requirements.txt
WORKDIR /app
RUN apt-get update
RUN apt-get install -y gcc python3-dev
COPY ./requirements.txt /app/requirements.txt
RUN pip install -r requirements.txt
COPY . /app

Expand All @@ -16,4 +16,4 @@ ENV FLASK_ENV=development
ENV FLASK_DEBUG=0
RUN echo "python -m flask db upgrade" > /app/startup.sh
RUN echo "gunicorn pytket-service:app -b 0.0.0.0:5015 -w 4 --timeout 500 --log-level info" >> /app/startup.sh

CMD [ "sh", "/app/startup.sh" ]
144 changes: 10 additions & 134 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ This service takes a Qiskit, OpenQASM, or PyQuil implementation as data or via a
## Setup
* Clone repository:
```
git clone https://github.com/UST-QuAntiL/qiskit-service.git
git clone [email protected]:UST-QuAntiL/qiskit-service.git
git clone https://github.com/UST-QuAntiL/pytket-service.git
git clone [email protected]:UST-QuAntiL/pytket-service.git
```

* Start containers:
Expand All @@ -20,8 +20,8 @@ Now the pytket-service is available on http://localhost:5015/.
## After implementation changes
* Update container:
```
docker build -t planqk/qiskit-service:latest .
docker push planqk/qiskit-service:latest
docker build -t planqk/pytket-service:latest .
docker push planqk/pytket-service:latest
```

* Start containers:
Expand All @@ -30,137 +30,13 @@ docker-compose pull
docker-compose up
```

## Analysis of Original Circuit
Request an analysis of the original circuit.
## API Documentation
The pytket-service provides a Swagger UI, specifying the request schemas and showcasing exemplary requests for all API endpoints.
* http://localhost:5013/api/swagger-ui

`POST /pytket-service/api/v1.0/analyze-original-circuit`
```
{
"impl-url": "URL-OF-IMPLEMENTATION",
"impl-language": "Qiskit"/"OpenQASM"/"PyQuil",
}
```

## Transpilation/Compilation Request
Send implementation, input, QPU information, and your IBM Quantum Experience token to the API to get properties of the transpiled circuit and the transpiled OpenQASM circuit itself.
`POST /pytket-service/api/v1.0/transpile`

#### Transpilation/Compilation via URL
```
{
"impl-url": "URL-OF-IMPLEMENTATION",
"impl-language": "Qiskit"/"OpenQASM/PyQuil"
"qpu-name": "NAME-OF-QPU",
"provider": "PROVIDER, e.g. IBMQ",
"input-params": {
"PARAM-NAME-1": {
"rawValue": "YOUR-VALUE-1",
"type": "Integer"
},
"PARAM-NAME-2": {
"rawValue": "YOUR-VALUE-2",
"type": "String"
},
...
"token": {
"rawValue": "YOUR-IBMQ-TOKEN",
"type": "Unknown"
}
}
}
```
#### Transpilation via File
```
{
"impl-data": "BASE64-ENCODED-IMPLEMENTATION",
"impl-language": "Qiskit"/"OpenQASM/PyQuil"
"qpu-name": "NAME-OF-QPU",
"provider": "PROVIDER, e.g. IBMQ",
"input-params": {
"PARAM-NAME-1": {
"rawValue": "YOUR-VALUE-1",
"type": "Integer"
},
"PARAM-NAME-2": {
"rawValue": "YOUR-VALUE-2",
"type": "String"
},
...
"token": {
"rawValue": "YOUR-IBMQ-TOKEN",
"type": "Unknown"
}
}
}
```

## Execution Request
Send implementation, input, QPU information, and your IBM Quantum Experience token to the API to execute your circuit and get the result.

`POST /pytket-service/api/v1.0/execute`
#### Execution via URL
```
{
"impl-url": "URL-OF-IMPLEMENTATION",
"impl-language": "Qiskit"/"OpenQASM/PyQuil",
"qpu-name": "NAME-OF-QPU",
"provider": "PROVIDER, e.g. IBMQ",
"input-params": {
"PARAM-NAME-1": {
"rawValue": "YOUR-VALUE-1",
"type": "Integer"
},
"PARAM-NAME-2": {
"rawValue": "YOUR-VALUE-2",
"type": "String"
},
...
"token": {
"rawValue": "YOUR-IBMQ-TOKEN",
"type": "Unknown"
}
}
}
```
#### Execution via data
```
{
"impl-data": "BASE64-ENCODED-IMPLEMENTATION",
"impl-language": "Qiskit"/"OpenQASM/PyQuil",
"qpu-name": "NAME-OF-QPU",
"provider": "PROVIDER, e.g. IBMQ",
"input-params": {
"PARAM-NAME-1": {
"rawValue": "YOUR-VALUE-1",
"type": "Integer"
},
"PARAM-NAME-2": {
"rawValue": "YOUR-VALUE-2",
"type": "String"
},
...
"token": {
"rawValue": "YOUR-IBMQ-TOKEN",
"type": "Unknown"
}
}
}
```
#### Execution via transpiled OpenQASM String
```
{
"transpiled-qasm": "TRANSPILED-QASM-STRING",
"qpu-name": "NAME-OF-QPU",
"provider": "PROVIDER, e.g. IBMQ",
"input-params": {
"token": {
"rawValue": "YOUR-IBMQ-TOKEN",
"type": "Unknown"
}
}
}
```
Returns a content location for the result. Access it via `GET`.
The OpenAPI specifications are also statically available:
[OpenAPI JSON](./docs/openapi.json)
[OpenAPI YAML](./docs/openapi.yaml)

## Haftungsausschluss

Expand Down
14 changes: 12 additions & 2 deletions app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,19 @@
db = SQLAlchemy(app)
migrate = Migrate(app, db)

from app import routes, result_model, errors
from app import routes, result_model, errors, generated_circuit_model
from app.controller import register_blueprints
from flask_smorest import Api

app.app_context().push()
app.redis = Redis.from_url(app.config['REDIS_URL'], port=5040)
app.execute_queue = rq.Queue('pytket-service_execute', connection=app.redis, default_timeout=3600)
app.execute_queue = rq.Queue('pytket-service_execute', connection=app.redis, default_timeout=10000)
app.implementation_queue = rq.Queue('pytket-service_implementation_exe', connection=app.redis, default_timeout=10000)
app.logger.setLevel(logging.INFO)

api = Api(app)
register_blueprints(api)

@app.route("/")
def heartbeat():
return '<h1>pytket-service is running</h1> <h3>View the API Docs <a href="/api/swagger-ui">here</a></h3>'
20 changes: 20 additions & 0 deletions app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,23 @@ class Config(object):
SQLALCHEMY_TRACK_MODIFICATIONS = False

REDIS_URL = os.environ.get('REDIS_URL') or 'redis://localhost:5040'

API_TITLE = "pytket-service"
API_VERSION = "0.1"
OPENAPI_VERSION = "3.0.2"
OPENAPI_URL_PREFIX = "/api"
OPENAPI_SWAGGER_UI_PATH = "/swagger-ui"
OPENAPI_SWAGGER_UI_VERSION = "3.24.2"
OPENAPI_SWAGGER_UI_URL = "https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/3.24.2/"

API_SPEC_OPTIONS = {
"info": {
"description": "This is the API Specification of the pytket-service ("
"https://github.com/UST-QuAntiL/pytket-service).",
},
"license": {"name": "Apache v2 License"},
}

@staticmethod
def init_app(app):
pass
10 changes: 10 additions & 0 deletions app/controller/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from app.controller import transpile, execute, analysis_original_circuit, result, generated_circuit, generate_circuit

MODULES = (transpile, execute, analysis_original_circuit, result,
generated_circuit, generate_circuit)


def register_blueprints(api):
"""Initialize application with all modules"""
for module in MODULES:
api.register_blueprint(module.blp)
1 change: 1 addition & 0 deletions app/controller/analysis_original_circuit/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from app.controller.analysis_original_circuit.analysis_original_circuit_controller import blp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from flask_smorest import Blueprint

from app import routes
from app.model.calculation_request import (AnalysisOriginalCircuitRequest, AnalysisOriginalCircuitRequestSchema)
from app.model.circuit_response import (AnalysisOriginalCircuitResponseSchema)

blp = Blueprint("Analysis of Original Circuit", __name__, description="Request an analysis of the original circuit.", )


@blp.route("/pytket-service/api/v1.0/analyze-original-circuit", methods=["POST"])
@blp.arguments(AnalysisOriginalCircuitRequestSchema, description='''\
\"input-params\" should be of the form:
\"input-params\":{
\"PARAM-NAME-1\": {
\"rawValue\": \"YOUR-VALUE-1\",
\"type\": \"Integer\"
},
\"PARAM-NAME-2\": {
\"rawValue\": \"YOUR-VALUE-2\",
\"type\": \"String\"
}''', example={
"impl-url": "https://raw.githubusercontent.com/UST-QuAntiL/nisq-analyzer-content/master/example-implementations/Grover-SAT/grover-fix-sat-qiskit.py",
"impl-language": "qiskit",
"input-params": {}},
)
@blp.response(200, AnalysisOriginalCircuitResponseSchema)
def encoding(json: AnalysisOriginalCircuitRequest):
if json:
return routes.analyze_original_circuit(json)
1 change: 1 addition & 0 deletions app/controller/execute/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from app.controller.execute.execute_controller import blp
79 changes: 79 additions & 0 deletions app/controller/execute/execute_controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
from flask_smorest import Blueprint

from app import routes
from app.model.circuit_response import (
ExecuteResponseSchema
)
from app.model.algorithm_request import (
ExecuteRequest,
ExecuteRequestSchema
)

blp = Blueprint(
"Execute",
__name__,
description="Send implementation, input, QPU information, and your access token to the API to "
"execute your circuit and get the result.",
)


@blp.route("/pytket-service/api/v1.0/execute", methods=["POST"])
@blp.doc(description="*Note*: \"token\" should either be in \"input-params\" or extra. Both variants are combined "
"here for illustration purposes. *Note*: \"url\", \"hub\", \"group\", \"project\" are optional "
"such that otherwise the standard values are used.")
@blp.arguments(
ExecuteRequestSchema,
description='''\
Execution via URL:
\"impl-url\": \"URL-OF-IMPLEMENTATION\"
Execution via data:
\"impl-data\": \"BASE64-ENCODED-IMPLEMENTATION\"
Execution via transpiled OpenQASM String:
\"transpiled-qasm\":\"TRANSPILED-QASM-STRING\"
for Batch Execution of multiple circuits use:
\"impl-url\": [\"URL-OF-IMPLEMENTATION-1\", \"URL-OF-IMPLEMENTATION-2\"]
the \"input-params\"are of the form:
\"input-params\": {
\"PARAM-NAME-1\": {
\"rawValue\": \"YOUR-VALUE-1\",
\"type\": \"Integer\"
},
\"PARAM-NAME-2\": {
\"rawValue\": \"YOUR-VALUE-2\",
\"type\": \"String\"
},
...
\"token\": {
\"rawValue\": \"YOUR-IBMQ-TOKEN\",
\"type\": \"Unknown\"
},
\"url\": {
\"rawValue\": \"YOUR-IBMQ-AUTHENTICATION-URL\",
\"type\": \"Unknown\"
},
\"hub\": {
\"rawValue\": \"YOUR-IBMQ-HUB\",
\"type\": \"Unknown\"
},
\"group\": {
\"rawValue\": \"YOUR-IBMQ-GROUP\",
\"type\": \"Unknown\"
},
\"project\": {
\"rawValue\": \"YOUR-IBMQ-PROJECT\",
\"type\": \"Unknown\"
}''',
example={
"impl-url": "https://raw.githubusercontent.com/UST-QuAntiL/nisq-analyzer-content/master/example-implementations"
"/Grover-SAT/grover-fix-sat-qiskit.py",
"qpu-name": "aer_simulator",
"provider": "ibmq",
"impl-language": "qiskit",
"token": "YOUR-IBMQ-TOKEN",
"input-params": {}
}
)
@blp.response(200, ExecuteResponseSchema, description="Returns a content location for the result. Access it via GET")
def encoding(json: ExecuteRequest):
if json:
return routes.execute_circuit()
1 change: 1 addition & 0 deletions app/controller/generate_circuit/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from app.controller.generate_circuit.generate_circuit_controller import blp
35 changes: 35 additions & 0 deletions app/controller/generate_circuit/generate_circuit_controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from flask_smorest import Blueprint

from app import routes
from app.model.algorithm_request import (GenerateCircuitRequest, GenerateCircuitRequestSchema)
from app.model.circuit_response import (GenerateCircuitResponseSchema)

blp = Blueprint("Generate Circuit", __name__, description="Send implementation and input parameters to the API to "
"generate your circuit and get its properties.", )


@blp.route("/pytket-service/api/v1.0/generate-circuit", methods=["POST"])
@blp.arguments(GenerateCircuitRequestSchema, description='''\
Generation via URL:
\"impl-url\": \"URL-OF-IMPLEMENTATION\"
Generation via data:
\"impl-data\": \"BASE64-ENCODED-IMPLEMENTATION\"
the \"input-params\"are of the form:
\"input-params\": {
\"PARAM-NAME-1\": {
\"rawValue\": \"YOUR-VALUE-1\",
\"type\": \"Integer\"
},
\"PARAM-NAME-2\": {
\"rawValue\": \"YOUR-VALUE-2\",
\"type\": \"String\"
},
...
''', example={
"impl-url": "https://raw.githubusercontent.com/UST-QuAntiL/nisq-analyzer-content/master/example-implementations"
"/Grover-SAT/grover-fix-sat-qiskit.py", "impl-language": "qiskit", "input-params": {}})
@blp.response(200, GenerateCircuitResponseSchema,
description="Returns a content location for the generated circuit and its properties. Access it via GET")
def encoding(json: GenerateCircuitRequest):
if json:
return routes.generate_circuit()
Loading

0 comments on commit ba3b225

Please sign in to comment.