quantumlib / Cirq

A Python framework for creating, editing, and invoking Noisy Intermediate Scale Quantum (NISQ) circuits.
Apache License 2.0
4.3k stars 1.02k forks source link

Instructions for defining serializable custom objects are obscure #3098

Open dkafri opened 4 years ago

dkafri commented 4 years ago

The instructions in the documentation basically tell you to look at the source code. I was able to figure out how to do it by looking at the tests.

This would be a useful example:

from typing import Dict, Any

import cirq

class MyClass(object):

    def __init__(self, foo: Any) -> None:
        self.foo = foo  # should be a serializable type

    # The following magic methods are required by cirq to make this operation
    # JSON serializable.

    def _json_dict_(self) -> Dict[str, Any]:
        # Construct a dictionary storing all data required to construct my
        # object. We also need to specify a 'cirq_type' argument.

        return dict(foo=self.foo, cirq_type='MyClass')

    @classmethod
    def _from_json_dict_(cls, foo: Any, **kwargs) -> 'MyClass':
        # This must construct my object when passed the dictionary output of
        # _json_dict_. I.e., we should be able to call
        # MyClass._from_json_dict_(**json_dict).
        return MyClass(foo)

# To be able to decode the serialized object, we need to specify a custom
# "resolver", which is a function taking a cirq_type string and returning the
# appropriate class object.
def custom_resolver(cirq_type: str) -> Any:
    if cirq_type == 'MyClass':
        return MyClass

# We can now save to and load from JSON
bar = MyClass('foo')
# If we also passed a filename, the object is saved in that location.
json_text = cirq.to_json(bar, file_or_fn=None)

# we need to specify the custom resolver among the default resolvers
bar2 = cirq.read_json(json_text=json_text,
                      resolvers=[custom_resolver] + cirq.DEFAULT_RESOLVERS)
assert bar2.foo == bar.foo
balopat commented 4 years ago

Thank you @dkafri for opening this and taking the time to capture a useful example! This should be added to the docs on interoperability.