量子计算实战:IBM Q Experience 和量子猜球游戏

jielysong 6年前
   <p>一起来玩这个游戏!想看看如何在实际生活中玩这个游戏? <a href="/misc/goto?guid=4959757022308967887" rel="nofollow,noindex">在这里试试!</a></p>    <p>您可以玩玩这个经典的猜球游戏,并查看 QASM 代码和执行结果。祝您玩得愉快!</p>    <p>我在博客文章 <a href="/misc/goto?guid=4959757022398282317" rel="nofollow,noindex">通过量子计算、量子比特和 IBM Q 解决猜球游戏问题</a> 中提到过,一次高中同学聚会上与好友的一番对话,引起了我对如何使用量子计算解决实际问题的思考。作为对我自己的挑战,我想使用 IBM 的量子技术(具体来讲是 IBM Q Experience)重新创建经典的猜球游戏。</p>    <p>在这个猜球游戏中,用户选择要将球藏在一个盒子下,然后让量子计算机猜测是藏在哪个盒子下。在本教程中,将介绍我使用 IBM Q Experience 创建的猜球游戏版本的步骤。</p>    <p><a href="/misc/goto?guid=4959757022485956853" rel="nofollow,noindex">在 GitHub 上获取代码</a></p>    <h2>预备知识</h2>    <p>如果您有一点创建网站的经验,而且比较熟悉 HTML 和 JavaScript,您会发现这是一次非常简单(而轻松)的体验。我不会介绍 C#、HTML 或 JavaScript 代码的细节,因为这与如何使用 Q Experience 平台没有多大关系。您会看到,棘手的部分是后端发生的事情。</p>    <p>如果您对 IBM Q Experience 的 Quantum Composer 和 Quantum Assembler 的性质有一定的了解,也会对您有所帮助 - 但这不是理解这个简单的操作教程所必需的。</p>    <h2>系统要求</h2>    <p>首先,您需要有一个 IBM Q Experience 帐户。这个帐户是免费的!是不是很不错?要进行注册,请 <a href="/misc/goto?guid=4959757022576255376" rel="nofollow,noindex">访问 Quantum experience 页面</a> 。</p>    <p>您需要一个集成开发编辑器 (IDE) 来编写代码。出于我的目的,我使用了 Microsoft Visual Studio 2015。如果您非要坚持的话,您可以使用记事本,但我不推荐使用它。</p>    <p>您可以在自己的系统上本地运行实验,或者在您选择的云平台上运行实验。我已将我的代码发布到 IBM Cloud 上,以便与您分享。</p>    <h2>一种解决方法</h2>    <p>在思考如何使用量子计算解决我的难题时,我首先将此项目构想为一个完全基于浏览器的 JavaScript 任务。我编写了一些 HTML 5 代码,添加了一些出色的 JS 功能,让这些盒子会在屏幕上移动。我可以在 JavaScript 中构建量子汇编代码 (QASM),并通过一个简单的 Web 服务调用将它传递给 IBM Q Experience 平台。</p>    <p>不幸的是,IBM 不允许从外部域进行跨来源资源共享 (CORS),所以浏览器阻止了我们执行任何服务调用。让人焦头烂额!</p>    <p>其实,没那么糟糕。但让我们回到起点。</p>    <p>另一种替代方案是从服务器端代码发出请求,而不是从无法应用 CORS 的浏览器发出请求。这使情况变得有点复杂。</p>    <p>现在,我们的猜球游戏必须将它的布局提交给服务器。服务器将请求汇编为 QASM 代码并提交给 IBM 的平台。然后,从这个 Web 服务请求返回的 JSON 经过服务器解析并反馈到网页上,在其中显示量子计算机选择了哪个盒子。基本来讲,我们插入了一个中间媒介来解决该问题。很快,游戏就成功实现了。</p>    <h2>量子解决方案</h2>    <p>可以通过多种方式创建、编辑 ASP.NET Core 应用程序并将它部署到 IBM Cloud。我首先在 Visual Studio 中创建一个 ASP.NET Core 1.0 项目。删除模板中默认包含的 Contact 和 About 页面后,我修改了 Views\Shared\_Layout.cshtml 文件和 Views\Home\Index.cshtml,使它们符合我的要求。</p>    <p>然后,我在 Controllers 目录下创建了一个文件夹来存储一些类文件,这些文件将用于与 IBM Q 平台进行通信。</p>    <p>图 1. ASP.NET Core 解决方案</p>    <p><img src="https://simg.open-open.com/show/2745426ece326d8ea06d2b3a373b8eb2.png"></p>    <p><img src="https://simg.open-open.com/show/51f3381678469a044c9760bf19030d0e.png" alt="量子计算实战:IBM Q Experience 和量子猜球游戏" width="550" height="1003"></p>    <p>我们首先将注意力集中在 IBMQ 文件夹上,因为它是这个程序的真正核心。</p>    <p>这个文件夹中的类负责登录到 IBM Q Experience 平台,汇编量子汇编代码 (QASM),对 IBM 的量子处理器执行该代码,并解析执行的结果。执行和解析代码是通过公开的 Web 接口完成的。</p>    <ul>     <li><em>QProcessor</em> 类是此操作的核心。它处理登录功能和 QASM 代码的执行,以及两个实用工具和清理例程。它还持久保存执行各种 Web 服务调用所需的安全信息,并包装实现。请注意用于删除实验的函数。IBM Q Experience 平台将每次执行都保存为一次实验 - 随着时间的推移,尤其是在测试某些想法时,您的 Q Experience 平台上的帐户下执行的实验将会泛滥成灾。我发现最佳的管理方式是在运行实验后立即将其删除。</li>     <li><em>QResult</em> 类是一个简单的构造方法,用于在组件之间来回传递一次操作的成功情况。</li>     <li><em>QUser</em> 类是一个对象,用于保存登录 Q Experience 平台的结果。在本实验中,您需要在登录后记录用户的 userId,因为以后会使用此信息作为访问令牌,向您授予对帐户执行操作的权限</li>     <li><em>QCode</em> 类将用于汇编 QASM 代码。它也包含尝试次数(可执行量子运算的次数)。请记住,返回的量子比特是一个为 0 或 1 的概率。在这个应用程序中,我尝试运行该量子代码 500 次(这足以收敛到 1 或 0 的近 100% 概率),这从一定程度上消除了量子处理的乏味。</li>     <li><em>QExecutionOutput</em> 是这 5 个类中最复杂的。但是,出于本应用程序的目的,我们将忽略它的大部分内容。最重要的部分是隐藏在 Data 类中的 P 类。有两个属性(labels 和 values)可以保存结果。labels 属性告诉我们一个给定的量子比特得到了经典二进制位的 1 还是 0,values 属性告诉我们得到该结果的概率。该类本身是从对 IBM 平台执行样本代码的 JSON 结果中生成的。我使用了一个在线转换器(在本例中为 <a href="/misc/goto?guid=4959757022661217666" rel="nofollow,noindex">json2csharp.com</a> )来构建 QExecutionOutput 类。无可否认,此类或许不是处理 JSON 结果的完美方式,但它比手动编写类更快。</li>    </ul>    <p>让我们分析一下这些类将执行的步骤。</p>    <h2>与 IBM Q Experience 平台进行通信</h2>    <p>我们需要做的第一件事是将数据发送到 IBM Q Experience 平台。无需反复编写和重写相同的代码,我将它组合成一个名为 FetchAPIData 的函数。这样,PerformLogin 等其他函数只需要传递相对 URL、一个 HTTP 方法(post、delete、get 等)和内容(如果提交)。FetchApiData 会完成剩余工作。</p>    <p>它首先会将该 URL 的相对部分添加到基础 URL 中:https://quantumexperience.ng.bluemix.net/api。如果我们没有执行删除,而且我们有一个 User 对象,它还将传递 User.id 作为 access_token。当执行删除时,我们传递 User.id 作为请求标头 (X-Access-Token),而不将 access_token 附加到 URL。</p>    <p>下面这段代码只构建请求消息,添加内容,然后设置请求标头。如果我们获得了成功状态代码,则证明我们正确地发送了 QResult 对象,任务完成。</p>    <p>清单 1. 发送我们的 QResult 对象</p>    <pre>  <code class="language-cs">private QResult FetchAPIData(string urlRelativePath,                                       HttpMethod httpMethod,                                       HttpContent contentToSend)          {              QResult result = new QResult();                //add auth token if we have a user and we arent deleting              if (User != null && httpMethod !=HttpMethod.Delete)                 {                   urlRelativePath = urlRelativePath +  "&access_token=" + User.id;              }              string url = _baseUrl + urlRelativePath;                Debug.WriteLine("Performing " + httpMethod.ToString() + " to " + url);                if (contentToSend!=null) {                   Debug.WriteLine("Sending data " + contentToSend.ReadAsStringAsync().Result);              }                HttpRequestMessage request = new HttpRequestMessage(httpMethod, url);              request.Content = contentToSend;              if (User != null) request.Headers.Add("X-Access-Token", User.id);              using (HttpResponseMessage response = _client.SendAsync(request).Result)                  if (response.IsSuccessStatusCode)                  {                      using (HttpContent content = response.Content)                      {                          // ...Read the string.                          result.Message = content.ReadAsStringAsync().Result;                          result.Success = response.IsSuccessStatusCode;                                              }                  } else                  {                      result.Message = response.ReasonPhrase;                      result.Success = false;                  }              return result;          }</code></pre>    <p>就这么简单!砰!</p>    <p>现在我们已确定如何与 IBM 平台进行通信,接下来需要理解我们必须传递什么信息。幸运的是,这非常简单 - 分两个阶段。</p>    <ol>     <li>第一阶段是交换凭证。</li>     <li>第二阶段是传输 QASM 代码本身,并接受表示量子代码执行结果的 JSON 数据。</li>    </ol>    <h3>第 1 阶段.交换凭证</h3>    <p>让我们从处理凭证开始。对于 IBM Q Experience 平台,我们需要一个 API 密钥。要获取此密钥,请执行以下操作:</p>    <ol>     <li>转到您的 <a href="/misc/goto?guid=4959757022737768651" rel="nofollow,noindex">IBM Quantum experience 帐户页面</a> 。</li>     <li>单击 Regenerate 按钮,以便为您创建一个 API 密钥。 <p>图 2. IBM 的 Q Experience 概况页面中的 API 令牌</p> <img src="https://simg.open-open.com/show/0660aacc8ed617045e5a9ce55a70eacf.png"> <p><img src="https://simg.open-open.com/show/f9bc9c462d8e3c8342c77133c3a74ab3.png" alt="量子计算实战:IBM Q Experience 和量子猜球游戏" width="550" height="99"></p> </li>     <li>有了 API 令牌后,将它传递给位于“/users/loginWithToken”端点上的 Web 服务。下面的代码清单给出了我们用于完成此任务的 PerformLogin 例程。</li>    </ol>    <p>清单 2. 传递 API 令牌</p>    <pre>  <code class="language-cs">private QResult PerformLogin()          {              if (_token == string.Empty) throw new Exception("A token is required.");                QResult result = new QResult();                HttpContent content= new StringContent("apiToken=" + _token,                                      System.Text.Encoding.UTF8,                                      "application/x-www-form-urlencoded");//CONTENT-TYPE header                result = FetchAPIData("/users/loginWithToken", HttpMethod.Post, content);              if (result.Success)              {                  User = JsonConvert.DeserializeObject<QUser>(result.Message);                  Debug.WriteLine("Logged in and have UserID: " + User.userid);              } else              {                  User = null;              }                return result;            }</code></pre>    <p>这里只有一个需要注意的地方:您没有将 JSON 数据提交到此端点,而是提交了 application/x-www-form-urlencoded 数据。这需要花点精力才能理解 - 同样幸运的是,Fiddler 和 Wireshark 是对这些功能执行逆向工程的好工具。</p>    <p>如果令牌经过了验证,我们会获得类似下面这样的 JSON 包:</p>    <p>清单 3. 返回的 JSON 包</p>    <pre>  <code class="language-cs">"{\"id\":\"XXXXXXXXXXXXXXXXXXXXXXXXXX\",\"ttl\":1209600,\"created\":   \"2017-10-03T14:51:51.918Z\",\"userId\":   \"XXXXXXXXXXXXXXXXXXXXXXXXXXX7999a6\"}"</code></pre>    <p>在对 IBM 平台的后续调用中会使用 userId 字段的值。该值在存活时间 (ttl) 过期之前工作正常 - 在这段简单的演示代码中,我们忽略了这一点。所以,在我们的登录步骤中,我们对结果消息数据中的 userId 进行了反序列化,并将结果隐藏在我们的全局 user 对象中。</p>    <h3>第 2 阶段.执行代码</h3>    <p>现在是时候提交 QASM 代码来执行它了。我们将创建一个包含以下信息的 ExecuteCode 函数:</p>    <ul>     <li>一个包含以下 3 个参数的 URL 字符串:      <ul>       <li>Shots:要执行实验的次数</li>       <li>Seed</li>       <li>deviceRunType:我们使用了“simulator”,但是,如果您愿意的话,可以在真正的量子处理器上运行此代码</li>      </ul> </li>     <li>其他数据包括:      <ul>       <li>QASM 代码本身</li>       <li>codeType:对我们而言,代码类型为 QASM2</li>       <li>分配给这次运行的名称</li>      </ul> </li>    </ul>    <p>下面是完整的 ExecuteCode 函数:</p>    <p>清单 4. ExecuteCode 函数</p>    <pre>  <code class="language-cs">public QResult ExecuteCode(QCode code)          {              if (this.User == null) throw new Exception("Not logged in.");                QResult result = new QResult();              string url = string.Format("/codes/execute?shots={0}&seed={1}&deviceRunType={2}",                       code.shots.ToString(),                      code.seed.ToString(),                      code.deviceRunType                      );                string data = string.Format("qasm={0}&codeType={1}&name={2}",                       code.qasm,                       code.codeType,                       code.name                      );                var kvp = new List<KeyValuePair<string, string>>();              kvp.Add(new KeyValuePair<string, string>("qasm", code.qasm));              kvp.Add(new KeyValuePair<string, string>("codeType", code.codeType));              kvp.Add(new KeyValuePair<string, string>("name", code.name));                HttpContent content = new FormUrlEncodedContent(kvp);                           result = FetchAPIData(url, HttpMethod.Post, content);                Debug.WriteLine("ExecuteCode received the following JSON from the API:");              Debug.WriteLine(result.Message);                  return result;            }</code></pre>    <p>我们将数据打包到一个 KeyValuePair 中,然后对它执行 FormUrlEncode,以便可以通过 FetchAPIData 调用,使用 POST 将它提交到该 URL。</p>    <p>不错的开端。但是现在该做什么?量子处理器如何解决猜球游戏?</p>    <h2>Grover 算法和振幅放大技巧</h2>    <p>要理解量子计算的工作原理,需要了解 Grover 算法和振幅放大技巧</p>    <p>如果您需要更详细的解释,IBM Q Experience 中的 <a href="https://quantumexperience.ng.bluemix.net/qx/tutorial?sectionId=full-user-guide&page=004-Quantum_Algorithms~2F070-Grover%27s_Algorithm" rel="nofollow,noindex">Grover 算法教程</a> 透彻地剖析了该算法。</p>    <p>在物理现实中,如果向您提供一组盒子,您会逐个翻开它们,直到找到球。在计算机世界中,这个猜球游戏只是一种非结构化搜索。</p>    <p>在非结构化搜索流程中,通过对一个集合内的每个元素应用布尔运算(一种具有明确的 f(x)=1 形式的函数),对该集合内的 N 个元素进行搜索。</p>    <p>给定一个包含 N 个元素的集合 X ={x1, x2,…xN} 并给定一个函数 f:X=>{0,1},找到 X 中满足条件 f(x*)=1 的元素 x*。</p>    <p>在我们的例子中,我们有一些盒子(假设数量为 N),我们想找到下面藏有球的盒子。我们选择一个盒子时,如果它下方有一个球,则会得到结果“true”或“1”。如果我们在盒子下找到球以外的任何东西,那么结果将为值“false”或“0”。通过这种方式,如果在盒子下找到球,函数表示为 f(x) = 1,如果不是球,函数表示为 f(x) = 0。</p>    <p>在经典计算领域和我们的猜球游戏中,我们读取每个盒子,应用该函数,直到找到球。这有时称为“占卜”,因为我们将该函数视为一个黑盒。我们没有必要关心盒子内是什么,只需关心函数的结果是 1 还是 0。给定 N 个盒子,经典计算机的最糟糕性能为 O(N) 次运算(例如,球在最后的盒子下)。</p>    <p>使用量子计算机和振幅放大技巧,我们可以在 O(sqr(N)) 次运算内解决此问题。但是,量子计算从来都不是那么简单。量子计算得到一个小于 1 的概率 - 而不是准确的答案。即便如此,我们可以多次运行计算,直到结果是任何一个随意选择的高概率(比如 0.99 或更高)。出于我们的目的,我们将进行 500 次尝试。该计算几乎总是得到接近 100% 的概率(或者至少可以舍入为 100% 的概率)。</p>    <h2>映射</h2>    <p>请记住,我们希望将真实问题映射到量子处理器的物理状态,执行逻辑,然后将结果逆向映射回真实问题。</p>    <p>那么在我们的猜球游戏中,我们需要:</p>    <ol>     <li>将用户选择的盒子数量传递到后端。</li>     <li>让后端将该数据以 QASM 代码形式传递给量子处理器,由该处理器执行 Grover 算法。</li>     <li>检索并解析这些结果。</li>     <li>将结果数据映射回真实问题(例如显示用户选择了哪个盒子)。</li>    </ol>    <p>呼!很难讲清,但还没有难到讲不清。在实例化期间,QCode 类执行了所有工作。在这里,我们将逐个步骤进行剖析。</p>    <h3>第 1 步.将用户选择的盒子数量传递到后端</h3>    <p>我们向 QCode 构造方法传递一个参数,表明用户选择了哪个盒子。这会指导创建 QASM 代码来正确反映实际环境与量子处理器的执行环境的映射。QCode 构造方法代码首先设置 QASM 代码的第一部分,这部分建立 5 个量子比特和 5 个经典寄存器。</p>    <p>清单 5. 设置 QASM 代码</p>    <pre>  <code class="language-cs">//5 qubits and 5 classical registers  string preCode = "include \"qelib1.inc\";qreg q[5];creg c[5];";</code></pre>    <p>为什么是 5 个?说实话,我们只需要两个,我们使用 5 个是为了让此演示与 Q Experience 网站上的 <a href="https://quantumexperience.ng.bluemix.net/qx/tutorial?sectionId=full-user-guide&page=004-Quantum_Algorithms~2F070-Grover%27s_Algorithm" rel="nofollow,noindex">教程</a> 中提供的 Composer 分数保持一致。</p>    <h3>第 2 步.让后端将该数据以 QASM 代码形式传递给量子处理器,由该处理器执行 Grover 算法。</h3>    <p>我们为这些量子比特分配状态。系统根据我们尝试表示哪个状态来构建 QASM。请记住,如果用户选择了盒子 #1,我们希望将量子比特的状态设置为“00”状态。盒子 #2 的状态为“01”,依此类推。switch 语句负责设置这些状态。下面的代码清单展示了如何分配这些状态:</p>    <p>清单 6. 分配状态</p>    <pre>  <code class="language-cs">switch (coinUnderShellNumber)              {                    case 1:  //#State=00                      initCode = @"h q[1];                                  h q[2];                                  s q[1];                                  s q[2];                                  h q[2];                                  cx q[1],q[2];                                  h q[2];                                  s q[1];                                  s q[2];                                  ";                      break;                  case 2:  //#State=01                      initCode = @"h q[1];                                  h q[2];                                  s q[2];                                  h q[2];                                  cx q[1],q[2];                                  h q[2];                                  s q[2];";                      break;                  case 3: //#State=10                      initCode = @"h q[1];                                  h q[2];                                  s q[1];                                  h q[2];                                  cx q[1],q[2];                                  h q[2];                                  s q[1];";                      break;                  case 4: //#State=11                      initCode = @"h q[1];                              h q[2];                              h q[2];                              cx q[1],q[2];                              h q[2];                              ";                      break;                  default:                       throw new Exception("There can only be 4 shells.");              }</code></pre>    <p>最后,我们将 Grover 算法添加到这段 QASM 代码的末尾,如下面的代码清单所示:</p>    <p>清单 7. 添加 Grover 算法</p>    <pre>  <code class="language-cs">//everything starting at the "double Hadamard"              string postControlledNot = @"h q[1];                                          h q[2];                                          x q[1];                                          x q[2];                                          h q[2];                                          cx q[1], q[2];                                          h q[2];                                          x q[1];                                          x q[2];                                          h q[1];                                          h q[2];                                          measure q[1] -> c[1];                                          measure q[2] -> c[2];";</code></pre>    <p>我们将所有这些信息组合为一个字符串:</p>    <p>清单 8. 组合为一个字符串</p>    <pre>  <code class="language-cs">this.qasm = preCode + initCode + postControlledNot;</code></pre>    <p>将尝试次数设置为 500,以便我们的实验运行次数足以收敛到这些概率。</p>    <p>清单 9. 设置尝试次数</p>    <pre>  <code class="language-cs">this.shots = 500;</code></pre>    <h3>第 3 步.检索并解析这些结果</h3>    <p>我们之前讨论的 ExecuteCode 函数负责将代码传递到 Q Experience 平台。如果代码成功执行,我们会获得类似下面的代码清单的 JSON:</p>    <p>清单 10. JSON 输出</p>    <pre>  <code class="language-cs">{"result":{"date":"2017-10-  03T17:07:21.819Z","data":{"creg_labels":"c[5]","p":   {"qubits":[1,2],"labels":["00110"],"values":[1]},  "additionalData":{"seed":1},"qasm    ...    ,"userDeleted":false,"id":"7012d29df79ba1fca3e5eda009069d3d",  "userId":"a3e5c196cb90688ba9a50dd7607999a6"}}</code></pre>    <p>该 JSON 输出中隐藏的“labels”字段中包含我们的答案 - 在本例中为“00110”(已在上面突出显示)。“values”字段列出了该答案的概率。因为我们运行了 500 次模拟,所以最终结果非常接近 100%,足以让结果舍入为 1。因此,解析该结果很简单,只需将该 JSON 合成为一个对象并读取 labels 属性:</p>    <p>清单 11. 解析结果</p>    <pre>  <code class="language-cs">QExecutionOutput x= JsonConvert.DeserializeObject  <QExecutionOutput>(result.Message);              Debug.WriteLine("The values are: " + x.result.data.p.labels[0]);</code></pre>    <h3>第 4 步.将结果映射回真实问题</h3>    <p>将结果映射回真实问题是另一个 switch 语句,如下面的代码清单所示:</p>    <p>清单 12. 映射结果</p>    <pre>  <code class="language-cs">//parse the result and output the location of the coin                      QExecutionOutput x = qp.GetOutputFromMessageData(result.Message);                        string labels = x.result.data.p.labels[0];                      switch (labels)                      {                          case "00000":                               Debug.WriteLine("The coin was under Shell #1");                              ComputedShell.Value = "1";                              break;                          case "00100":                               Debug.WriteLine("The coin was under Shell #2");                              ComputedShell.Value = "2";                              break;                          case "00010":                               Debug.WriteLine("The coin was under Shell #3");                              ComputedShell.Value = "3";                              break;                          case "00110":                               Debug.WriteLine("The coin was under Shell #4");                              ComputedShell.Value = "4";                              break;                          default:                               Debug.WriteLine("Something broke!");                              ComputedShell.Value = "0";                              break;                      }</code></pre>    <p>如果您仅尝试了两次,可能会获得完全不同的结果。 或许我们应检查 values 数组并选择具有最高概率的数组索引,然后选择具有匹配的数组索引的标签作为答案。但是,因为我们运行了 500 次,所以我们的结果几乎总是只有 1 个答案的数组。就像下面的 JSON 中一样:</p>    <p>”qubits":[1,2],"labels":["00110"],"values":[1]},”</p>    <p>概率被舍入为 1,而且只有一个标签“00110”,所以在我们的猜球游戏中,我们仅读取了索引 0 处的结果。在本例中,球隐藏在第 4 个盒子下!</p>    <h2>总结</h2>    <p>在我们的 ASP.NET 网页中,当用户按 Submit 按钮时,会在 ShellGameModel 类的“ShellSelected”属性中传回盒子的编号。我们读取此值,创建我们的 QProcessor 对象(使用我们的令牌将其实例化)。然后登录。</p>    <p>如果登录成功,我们将实例化我们的 QCode 对象,向它传入所选的盒子的值。然后,我们将代码传递给 ExecuteCode 函数。我们利用该代码创建了一个 QExecutionOutput 对象,并读取结果的 labels 属性。</p>    <p>请记住,我们的 labels 是以经典方式表达的量子比特状态(1 或 0)。通过另一个简单的 switch 语句,我们可以传回量子处理器能够推断出的球位置信息。</p>    <p>清单 13. 查找球的位置</p>    <pre>  <code class="language-cs">[HttpPost]          public IActionResult Index(ShellGameModel model)          {              model.ComputedShell = "0";              model.QASM = "";              model.ExecutionResults = "";                string token = "INSERTYOURTOKENHERE";                //Build the processor              QProcessor qp = new QProcessor(token);                    //login              QResult result = qp.Login();              Debug.WriteLine(string.Format("Login result.  Success={0} Message={1}", result.Success.ToString(), result.Message));                if (result.Success)              {                  int shell = 0;                  Int32.TryParse(model.ShellSelected, out shell);                    //build the QASM code                  QCode code = new QCode(shell);                  code.name = string.Format("ExperimentID {0} with Shell at {1} ", System.Guid.NewGuid().ToString(), shell.ToString());                  Debug.WriteLine("Code:"+ Environment.NewLine + code.qasm);                      //execute the code                  result = qp.ExecuteCode(code);                  Debug.WriteLine(string.Format("Code Executed Success={0}, Data={1}", result.Success.ToString(), result.Message));                    //parse the result and output the location of the coin                  QExecutionOutput x = qp.GetOutputFromMessageData(result.Message);                    string labels = x.result.data.p.labels[0];                  switch (labels)                  {                      case "00000":                           Debug.WriteLine("The coin was under Shell #1");                          model.ComputedShell = "1";                          break;                      case "00100":                           Debug.WriteLine("The coin was under Shell #2");                          model.ComputedShell = "2";                          break;                      case "00010":                           Debug.WriteLine("The coin was under Shell #3");                          model.ComputedShell = "3";                          break;                      case "00110":                           Debug.WriteLine("The coin was under Shell #4");                          model.ComputedShell = "4";                          break;                      default:                           Debug.WriteLine("Something broke!");                          model.ComputedShell = "0";                          break;                  }                    model.QASM = JsonConvert.SerializeObject(x.code, Formatting.Indented);                  model.ExecutionResults = JsonConvert.SerializeObject(x.result, Formatting.Indented);                    //now cleanup and delete the results                  QResult deleteResult = qp.DeleteExperiment(x.code.idCode);              }                return View(model);          }</code></pre>    <p>瞧!我们将猜球游戏的实际问题映射到了代码中,在量子处理器上执行了它,处理了结果并将解决方案映射回实际环境中。</p>    <p>这可能不是您见过的最出色的工作(我可以想到 100 种改进它的方式),但它简单有效,而且足够表达本演示的目的。</p>    <h2>亲自玩玩该游戏</h2>    <p>想看看如何在实际生活中玩这个游戏? <a href="/misc/goto?guid=4959757022308967887" rel="nofollow,noindex">玩游戏</a> 并查看 QASM 代码和执行结果。祝您玩得愉快!</p>    <h2>结束语</h2>    <p>感谢您跟我一起学习了 IBM Q Experience 的教程。尝试这项实验性技术很有趣,而且可以使用它创建有趣的小游戏。希望您能够利用本教程中的知识,使用这项量子技术亲自创建游戏或解决难题。</p>    <h2>后续行动</h2>    <ul>     <li>量子计算初学者指南:在这个初学者为其他初学者编写的指南中,Talia Gershon 博士向开发人员解释了量子计算的基础操作。</li>     <li><a href="/misc/goto?guid=4959757022923654553" rel="nofollow,noindex">量子计算:IBM Q Experience 的初学者笔记和概述</a> :在这篇博客文章中,Kevin Casey 介绍了他第一次使用 IBM Q Experience 的经历。</li>     <li>IBM Q:进一步了解量子计算,阅读教程,并亲自实验该技术。</li>     <li>QISKit API:轻量型、开源的 QISKit API 是一个围绕 IBM Quantum experience HTTP API 的瘦 Python 包装器,它使您能够连接和执行 OPENQASM 代码。</li>    </ul>    <p> </p>    <p>来自:http://www.ibm.com/developerworks/cn/opensource/os-quantum-computing-shell-game/index.html?ca=drs-</p>    <p> </p>