【问题标题】:Passing complex objects to Q# operations将复杂对象传递给 Q# 操作
【发布时间】:2020-11-15 10:34:10
【问题描述】:

我想通过 Python 代码将复杂对象传递给 Q# 操作。我在两边都定义了相同的数据结构:在 Python 中作为 class,在 Q# 中作为 newtype。 然后我在 Python 中准备了复杂对象的 JSON 表示(利用 json 包和 this answer)并尝试将其传递给 Q# 操作,但出现以下错误:

Received invalid parameters. Please fix and try again:
n: Unexpected initial token 'String' when populating object. Expected JSON object or array. Path '', line 1, position 171.

这是 Python 代码

import qsharp
import json
import inspect

from json.test import JsonTest

class ObjectEncoder(json.JSONEncoder):
    def default(self, obj):
        if hasattr(obj, "to_json"):
            return self.default(obj.to_json())
        elif hasattr(obj, "__dict__"):
            d = dict(
                (key, value)
                for key, value in inspect.getmembers(obj)
                if not key.startswith("__")
                and not inspect.isabstract(value)
                and not inspect.isbuiltin(value)
                and not inspect.isfunction(value)
                and not inspect.isgenerator(value)
                and not inspect.isgeneratorfunction(value)
                and not inspect.ismethod(value)
                and not inspect.ismethoddescriptor(value)
                and not inspect.isroutine(value)
            )
            return self.default(d)
        return obj

class U:
    x = 0
    y = 0
    z = 0
    def __init__(self, x, y, z) :
        self.x = x
        self.y = y
        self.z = z

class N:
    t = [U(0,0,0), U(3.14,0,0)]
    q = 3
    def __init__(self, t, q) :
        self.t = t
        self.q = q

obj = N([U(3.14, 0, 0), U(0, 3.14, 0)], 3)
jsonObj = json.dumps(obj, cls=ObjectEncoder, indent=2, sort_keys=False)
print(jsonObj)
JsonTest.simulate(n=jsonObj)

这是该代码打印的 JSON 表示

{
  "q": 3,
  "t": [
    {
      "x": 3.14,
      "y": 0,
      "z": 0
    },
    {
      "x": 0,
      "y": 3.14,
      "z": 0
    }
  ]
}

这是Q#代码

namespace json.test {

    open Microsoft.Quantum.Convert;
    open Microsoft.Quantum.Intrinsic;

    newtype U = (
        x : Double,
        y : Double,
        z : Double  
    );

    newtype N = (
        t : U[],
        q : Int
    );

    operation JsonTest(n : N) : Int {
        let r = n::q * Length(n::t); // just do sometinhg
        Message($"t = {n::t}  q = {n::q}");
        return r;
    }
}

Q# 真的支持复杂对象的 JSON 表示吗?

【问题讨论】:

  • 我还尝试以更类似于 Q# 的方式手动编码复杂对象 ([(3.1, 0.0, 0.0),(0.0, 3.1, 0.0)], 3) 但我总是遇到同样的错误

标签: python json q#


【解决方案1】:

是的,Q# 支持通过 Python 表示这些用户定义类型的实例,但不支持使用 dicts 或 JSON 字符串。要使用 Q# 接口,我们需要改用tuples。如果你想要一个包含你正在使用的标签的数据结构(xyz 等等),我建议使用namedtuples,例如:

from collections import namedtuple

U = namedtuple("U", ["x", "y", "z"])
N = namedtuple("N", ["t", "q"])

obj = N(q=3, t=[U(x=3.14, y=0, z=0), U(x=0, y=3.14, z=0)])

这样

>>> obj
N(t=[U(x=3.14, y=0, z=0), U(x=0, y=3.14, z=0)], q=3)

然后您可以像这样简单地将其传递给您编译的 Q# 程序:

import qsharp

qsharp.compile("""
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Intrinsic;

newtype U = (
    x: Double, 
    y: Double, 
    z: Double
);

newtype N = (
    t: U[],
    q: Int
);
""")

JsonTest = qsharp.compile("""
operation JsonTest(n : N) : Int {
    let r = n::q * Length(n::t); // just do sometinhg
    Message($"t = {n::t}  q = {n::q}");
    return r;
}
""")

from collections import namedtuple

U = namedtuple("U", ["x", "y", "z"])
N = namedtuple("N", ["t", "q"])

obj = N(q=3, t=[U(x=3.14, y=0, z=0), U(x=0, y=3.14, z=0)])
JsonTest.simulate(n=obj)

返回

t = [U((3.14, 0, 0)),U((0, 3.14, 0))]  q = 3
6

如果你想使用 JSON 字符串,你可以像这样创建一个自定义函数:

import json

def N_from_json(data: str):
    """Create N object from JSON-formatted string
    """
    _data = json.loads(data)
    t = _data.get("t", [])
    q = _data.get("q", 0) # Or some other default value of your choosing

    return N(t=[U(**_t) for _t in t], q=q)


jsonObj = json.dumps({
  "t": [
    {
      "x": 3.14,
      "y": 0,
      "z": 0
    },
    {
      "x": 0,
      "y": 3.14,
      "z": 0
    }
  ],
  "q": 3,
})

obj = N_from_json(jsonObj)

【讨论】:

  • 谢谢@Guen namedtuple 解决了我的问题!也许可以改进明确指出 JSON 对象 的错误消息。
  • 感谢@Stefano,这是很好的反馈,如果不是太麻烦,您介意将其作为问题发布到我们的 iqsharp 存储库中,以便我们的团队可以看看吗? (见github.com/microsoft/iqsharp/issues)非常感谢!
猜你喜欢
  • 1970-01-01
  • 2013-02-26
  • 1970-01-01
  • 2014-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-09
  • 2017-02-07
相关资源
最近更新 更多