Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions dev_tools/snippets_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,10 @@ def test_can_run_readme_code_snippets():

def find_docs_code_snippets_paths() -> Iterator[str]:
for filename in DOCS_FOLDER.rglob('*.md'):
# Skip files under either 'hardware' and 'google'
# Skip files under 'hardware'
# TODO: #7787 - revisit which of these can be fixed and enabled later.
path = str(filename.relative_to(DOCS_FOLDER))
if not path.startswith(('hardware', 'google')):
if not path.startswith('hardware'):
yield path


Expand Down Expand Up @@ -114,7 +114,7 @@ def find_markdown_code_snippets(content: str) -> list[tuple[str, int]]:

def find_markdown_test_overrides(content: str) -> list[tuple[Pattern, str]]:
test_sub_text = find_code_snippets("<!---test_substitution\n(.*?)--->", content)
substitutions = [line.split('\n')[:-1] for line, _ in test_sub_text]
substitutions = [line.rstrip().split('\n', maxsplit=1) for line, _ in test_sub_text]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the behavior changed, maybe add a short explanation?

"""This function finds all the `<!---test_substitution-->` blocks in `content`, and replace `pattern` with `substitutions`:
```
<!---test_substitution
pattern
substitutions
-->
```

noted that `substitutions` could be a multi-line string because `maxsplit` is set to 1, while `pattern` is strictly to be a single line string.
"""

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, done in 7b5e4ba.

return [(re.compile(match), sub) for match, sub in substitutions]


Expand Down Expand Up @@ -255,6 +255,9 @@ def assert_code_snippets_run_in_sequence(snippets: list[tuple[str, int]], assume

if assume_import:
exec('import cirq', state)
exec('import cirq_google', state)
exec('import unittest.mock as mock', state)
exec('import sympy', state)

for content, line_number in snippets:
assert_code_snippet_executes_correctly(content, state, line_number)
Expand Down
26 changes: 19 additions & 7 deletions docs/google/calibration.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,23 @@ A dropdown menu will let you choose the current characterization or historical
metrics from a previous run. Calibration metrics can also be retrieved
programmatically using an engine instance or with a job.

<!---test_substitution
engine = cg.Engine\(project_id=.*
\g<0>
engine = mock.create_autospec(cirq_google.Engine, instance=True)
mock_engine_processor = mock.create_autospec(cirq_google.EngineProcessor, instance=True)
engine.configure_mock(**{"get_processor.return_value": mock_engine_processor})
--->
<!---test_substitution
PROJECT_ID|PROGRAM_ID|PROCESSOR_ID|CALIBRATION_SECONDS|START_SECONDS|END_SECONDS|JOB_ID
'placeholder'
--->
```python
import cirq_google as cg

# Create an Engine object to use.
# Replace YOUR_PROJECT_ID with the id from your cloud project.
engine = cg.Engine(project_id=YOUR_PROJECT_ID)
# Replace PROJECT_ID with the id from your cloud project.
engine = cg.Engine(project_id=PROJECT_ID)
processor = engine.get_processor(processor_id=PROCESSOR_ID)

# Get the latest calibration metrics.
Expand All @@ -36,13 +47,14 @@ latest_calibration = processor.get_current_calibration()
previous_calibration = processor.get_calibration(CALIBRATION_SECONDS)

# If you would like to find a calibration from a time-frame, use this.
calibration_list = processor.list_calibration(START_SECONDS, END_SECONDS)
calibration_list = processor.list_calibrations(START_SECONDS, END_SECONDS)

## TODO: #7910 - fix or delete this block
# If you know the job-id, you can retrieve the calibration that the job used.
job = engine.get_job("projects/" + PROJECT_ID
+ "/programs/"+PROGRAM_ID
+ "/jobs/" + JOB_ID)
job_calibration = cg.EngineJob(cg.JobConfig(), job, engine).get_calibration()
# job = engine.get_job("projects/" + PROJECT_ID
# + "/programs/"+ PROGRAM_ID
# + "/jobs/" + JOB_ID)
# job_calibration = cg.EngineJob(PROJECT_ID, PROGRAM_ID, JOB_ID, cg.engine.engine.EngineContext()).get_calibration()

# The calibration can be iterated through using something like the following.
for metric_name in latest_calibration:
Expand Down
87 changes: 60 additions & 27 deletions docs/google/engine.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ gcloud client:

From a colab, you can execute:

<!---test_substitution
from google\.colab import auth
auth = mock.MagicMock()
--->
```python
from google.colab import auth
auth.authenticate_user(clear_output=False)
Expand All @@ -41,28 +45,38 @@ You can use this instance to run quantum circuits or sweeps (parameterized
variants of a general circuit).

<!---test_substitution
results = job.results.*
results = None
engine = cirq_google.Engine\b.*
# This pattern matches in all snippets.
# We repeat the expression first to ensure Engine argumets are correct.
\g<0>
# Then we create various mock objects that derive from engine calls.
engine = mock_engine = mock.create_autospec(cirq_google.Engine, instance=True)
mock_sampler = mock.create_autospec(cirq.Sampler, instance=True)
mock_engine_job = mock.create_autospec(cirq_google.EngineJob, instance=True,
program_id="program_id", job_id="job_id")
mock_engine_program = mock.create_autospec(cirq_google.EngineProgram, instance=True,
program_id="program_id")
# Finally let us import datetime for snippets that use it below
import datetime
--->
<!---test_substitution
print.results.idx.*
print()
sampler = engine.get_sampler.processor_id=PROCESSOR_ID.*
mock_engine.configure_mock(**{"get_sampler.return_value": mock_sampler})
\g<0>
--->
<!---test_substitution
engine = cirq_google.Engine(.*)
engine = MockEngine()
results = sampler.run\b
mock_result = mock.create_autospec(cirq.Result, instance=True)
mock_sampler.configure_mock(**{"run.return_value": mock_result})
\g<0>
--->
<!---test_substitution
cg.Engine(.*)
cirq.Simulator()
--->
<!---test_substitution
sampler = .*
sampler = engine
PROJECT_ID|PROCESSOR_ID
'placeholder'
--->
```python
import cirq
import cirq_google as cg
import cirq_google

# A simple sample circuit
qubit = cirq.GridQubit(5, 2)
Expand All @@ -72,11 +86,11 @@ circuit = cirq.Circuit(
)

# Create an Engine object.
# Replace YOUR_PROJECT_ID with the id from your cloud project.
engine = cg.Engine(project_id=YOUR_PROJECT_ID)
# Replace PROJECT_ID with the id from your cloud project.
engine = cirq_google.Engine(project_id=PROJECT_ID)

# Create a sampler from the engine
sampler = engine.get_sampler(processor_id='PROCESSOR_ID')
sampler = engine.get_sampler(processor_id=PROCESSOR_ID)

# This will run the circuit and return the results in a 'Result'
results = sampler.run(circuit, repetitions=1000)
Expand Down Expand Up @@ -152,9 +166,18 @@ Currently, getting the program and job ids can only be done through the
You can then use `get_program` and `get_job` to retrieve the results.
See below for an example:

<!---test_substitution
job = engine.run_sweep.program=circuit
mock_engine.configure_mock(**{
"run_sweep.return_value": mock_engine_job,
"get_program.return_value": mock_engine_program,
})
mock_engine_program.configure_mock(**{"get_job.return_value": mock_engine_job})
\g<0>
--->
```python
# Initialize the engine object
engine = cirq_google.Engine(project_id='YOUR_PROJECT_ID')
engine = cirq_google.Engine(project_id=PROJECT_ID)

# Create an example circuit
qubit = cirq.GridQubit(5, 2)
Expand All @@ -165,13 +188,12 @@ circuit = cirq.Circuit(
param_sweep = cirq.Linspace('t', start=0, stop=1, length=10)

# Run the circuit
job = e.run_sweep(program=circuit,
job = engine.run_sweep(program=circuit,
params=param_sweep,
repetitions=1000,
processor_id='PROCESSOR_ID',
gate_set=GATE_SET)
processor_id=PROCESSOR_ID)

# Save the program and jo id for later
# Save the program and job id for later
program_id = job.program_id
job_id = job.job_id

Expand Down Expand Up @@ -200,15 +222,20 @@ by using our list methods.
To list the executions of your circuit, i.e., the jobs, you can use `cirq_google.Engine.list_jobs()`.
You can search in all the jobs within your project using filtering criteria on creation time, execution state and labels.

<!---test_substitution
jobs = engine.list_jobs.created_after=datetime.date.*
mock_engine.configure_mock(**{"list_jobs.return_value": [mock_engine_job]})
\g<0>
--->
```python
from cirq_google.engine.client.quantum import enums
from cirq_google.cloud import quantum

# Initialize the engine object
engine = cirq_google.Engine(project_id='YOUR_PROJECT_ID')
engine = cirq_google.Engine(project_id=PROJECT_ID)

# List all the jobs on the project since 2020/09/20 that succeeded:
jobs = engine.list_jobs(created_after=datetime.date(2020,9,20),
execution_states=[enums.ExecutionStatus.State.SUCCESS])
execution_states=[quantum.ExecutionStatus.State.SUCCESS])
for j in jobs:
print(j.job_id, j.status(), j.create_time())
```
Expand All @@ -219,11 +246,17 @@ To list the different instances of your circuits uploaded, i.e., the programs, y
Similar to jobs, filtering makes it possible to list programs by creation time and labels.
With an existing `cirq_google.EngineProgram` object, you can list any jobs that were run using that program.

<!---test_substitution
programs = engine.list_programs[(].*
mock_engine.configure_mock(**{"list_programs.return_value": [mock_engine_program]})
mock_engine_program.configure_mock(**{"list_jobs.return_value": [mock_engine_job]})
\g<0>
--->
```python
from cirq_google.engine.client.quantum import enums
from cirq_google.cloud import quantum

# Initialize the engine object
engine = cirq_google.Engine(project_id='YOUR_PROJECT_ID')
engine = cirq_google.Engine(project_id=PROJECT_ID)

# List all the programs on the project since 2020/09/20 that have
# the "variational" label with any value and the "experiment" label
Expand All @@ -236,6 +269,6 @@ for p in programs:
print(p.program_id, p.create_time())
# the same filtering parametrization is available as in engine.list_jobs()
# for example here we list the jobs under the programs that failed
for j in p.list_jobs(execution_states=[enums.ExecutionStatus.State.FAILURE]):
for j in p.list_jobs(execution_states=[quantum.ExecutionStatus.State.FAILURE]):
print(j.job_id, j.status())
```
24 changes: 16 additions & 8 deletions docs/google/specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,22 @@ specification. This time is stored as an integer number of picoseconds.
Example code to print out the gate durations for every gate supported by the
device is shown below:

<!---test_substitution
engine = cirq_google.Engine\(project_id=.*
PROJECT_ID = "placeholder"
PROCESSOR_ID = "willow_pink"
\g<0>
from cirq_google.engine import virtual_engine_factory as factory
engine = factory.create_noiseless_virtual_engine_from_latest_templates()
--->
```python
import cirq
import cirq_google

# Create an Engine object to use.
engine = cirq_google.Engine(project_id='your_project_id')
engine = cirq_google.Engine(project_id=PROJECT_ID)

# Replace the processor id to get the device specification with that id.
spec = engine.get_processor('processor_id').get_device_specification()
spec = engine.get_processor(PROCESSOR_ID).get_device_specification()

# Iterate through each gate set valid on the device.
for gateset in spec.valid_gate_sets:
Expand Down Expand Up @@ -101,16 +109,16 @@ from the engine and then using it to validate a circuit.

```python
import cirq
import cirq_google as cg
import cirq_google

# Create an Engine object to use.
engine = cg.Engine(project_id='your_project_id',
proto_version=cirq_google.ProtoVersion.V2)
engine = cirq_google.Engine(project_id=PROJECT_ID)

# Replace the processor id to get the device with that id.
device = engine.get_processor('processor_id').get_device()
device = engine.get_processor(PROCESSOR_ID).get_device()

q0, q1 = cirq.LineQubit.range(2)
q0 = cirq.GridQubit(6, 6)
q1 = cirq.GridQubit(6, 7)
circuit = cirq.Circuit(cirq.CZ(q0, q1))

# Raises a ValueError, since CZ is not a supported gate.
Expand Down
Loading