IQuantumProcessor
membuatnya sangat mudah untuk membuat simulator Anda sendiri dan mengintegrasikannya ke dalam proyek Q # Anda.
Posting ini adalah yang pertama dalam seri antarmuka ini. Kami akan mulai dengan menerapkan simulator yang dapat dibalik sebagai contoh pertama, yang akan kami kembangkan di posting blog mendatang. Simulator reversibel dapat mensimulasikan program kuantum yang hanya terdiri dari operasi klasik:
X
, CNOT
,CCNOT
(Gerbang Toffoli) atau operasi X yang dikontrol secara acak. Karena simulator yang dapat dibalik dapat merepresentasikan status kuantum dengan menetapkan satu nilai boolean ke setiap qubit, ia bahkan dapat menjalankan program kuantum ribuan qubit. Simulator ini sangat berguna untuk menguji operasi kuantum yang mengevaluasi fungsi boolean.
Implementasi simulator di C #
Posting blog ini mencakup cuplikan kode dasar. Kode sumber lengkap dapat ditemukan di repositori Microsoft QDK Samples.
Anda mulai membuat simulator Anda sendiri dengan memperluas kelas
QuantumProcessorBase
:
class ReversibleSimulatorProcessor : QuantumProcessorBase {
private IDictionary<Qubit, bool> simulationValues = new Dictionary<Qubit, bool>();
// (intrinsic operations)...
}
Kamus yang akan menyimpan nilai simulasi saat ini untuk setiap qubit dalam program telah ditambahkan ke kelas. Status kuantum klasik | 0⟩ dan | 1⟩ direpresentasikan sebagai nilai Boolean false dan true. Simulator menentukan operasi internal dalam program Q #.
QuantumProcessorBase
berisi metode untuk setiap operasi internal yang dapat Anda ganti untuk menentukan perilakunya di simulator baru. Perhatikan bahwa metode yang tidak diimplementasikan akan memunculkan pengecualian default. Ini akan membantu Anda mengidentifikasi kasus di mana operasi masih perlu dilaksanakan dan akan memberi tahu pengguna simulator bahwa operasi inline tidak didukung oleh simulator. Misalnya, simulator yang dapat dibalik tidak dapat digunakan untuk mensimulasikan program kuantum yang berisi operasi non-klasik seperti H atau T.
Mari kita mulai dengan salah menginisialisasi qubit yang baru dialokasikan dengan mengganti metode OnAllocateQubits. Demikian juga, qubit akan dihapus dari kamus saat dirilis. Dalam hal ini, OnReleaseQubits dipanggil.
public override void OnAllocateQubits(IQArray qubits) {
foreach (var qubit in qubits) {
simulationValues[qubit] = false;
}
}
public override void OnReleaseQubits(IQArray qubits) {
foreach (var qubit in qubits) {
simulationValues.Remove(qubit);
}
}
Dengan dua operasi ini, dijamin bahwa nilai simulasi tersedia saat operasi diterapkan ke beberapa qubit, dan tidak ada nilai simulasi yang tersisa di kamus untuk qubit yang tidak ada di wilayah saat ini.
Sebagai langkah selanjutnya, mari terapkan tindakan operasi klasik. Dalam kasus ini, dua metode sudah cukup: metode X dipanggil saat operasi X disimulasikan, dan metode ControlledX dipanggil saat operasi X disimulasikan, yang juga menyertakan CNOT dan CCNOT. Operasi X membalikkan nilai simulasi qubit, sedangkan dalam kasus operasi X yang dikontrol secara sewenang-wenang, qubit target dibalik jika dan hanya jika semua qubit kontrol disetel ke true.
public override void X(Qubit qubit) {
simulationValues[qubit] = !simulationValues[qubit];
}
public override void ControlledX(IQArray controls, Qubit qubit) {
simulationValues[qubit] ^= And(controls);
}
Akhirnya, mengukur qubit dalam program Q # mengembalikan hasil (Satu atau Nol), yang dapat dihitung berdasarkan nilai simulasi qubit saat ini. Kami juga menerapkan metode Reset yang dipanggil ketika operasi reset dipanggil dalam program Q #. Yang terakhir tidak menghapus qubit dari wilayah saat ini, tetapi menyetel ulang nilai simulasi kembali ke nilai awalnya, yang salah.
public override Result M(Qubit qubit) {
return simulationValues[qubit] ? Result.One : Result.Zero;
}
public override void Reset(Qubit qubit) {
simulationValues[qubit] = false;
}
ReversibleSimulatorProcessor dapat digunakan sebagai simulator dengan membuat instance QuantumProcessorDispatcher. Gaya desain yang disarankan adalah menyediakan kelas khusus untuk simulator:
public class ReversibleSimulator : QuantumProcessorDispatcher {
public ReversibleSimulator() : base(new ReversibleSimulatorProcessor()) {}
}
Menggunakan simulator baru
Mari kita coba simulator baru pada operasi Q # berikut:
operation ApplyMajority(a : Qubit, b : Qubit, c : Qubit, f : Qubit) : Unit {
within {
CNOT(b, a);
CNOT(b, c);
} apply {
CCNOT(a, c, f);
CNOT(b, f);
}
}
Kami juga menulis operasi yang melakukan operasi mayoritas dengan menyediakan tiga input boolean:
operation RunMajority(a : Bool, b : Bool, c : Bool) : Bool {
using ((qa, qb, qc, f) = (Qubit(), Qubit(), Qubit(), Qubit())) {
within {
ApplyPauliFromBitString(PauliX, true, [a, b, c], [qa, qb, qc]);
} apply {
ApplyMajority(qa, qb, qc, f);
}
return MResetZ(f) == One;
}
}
Terakhir, Anda dapat menggabungkan semuanya dengan menjalankan operasi Q # dengan simulator baru dalam program host C #. Contoh berikut mengevaluasi operasi utama untuk semua tujuan masukan dan keluaran yang berbeda untuk semua hasil simulasi:
public static void Main(string[] args) {
var sim = new ReversibleSimulator();
var bits = new[] {false, true};
foreach (var a in bits) {
foreach (var b in bits) {
foreach (var c in bits) {
var f = RunMajority.Run(sim, a, b, c).Result;
Console.WriteLine($"Majority({a,5}, {b,5}, {c,5}) = {f,5}");
}
}
}
}
Siap menulis simulator Anda sendiri?
Kami harap postingan ini menginspirasi Anda untuk membuat simulator sendiri. Pada langkah selanjutnya, kita akan membahas bagaimana meningkatkan kinerja implementasi saat ini (misalnya, dengan tidak menggunakan kamus untuk menyimpan nilai simulasi), bagaimana mengubahnya menjadi proyek Q # mandiri, bagaimana menyediakan tindakan kustom untuk operasi non-intrinsik, dan bagaimana menyediakan operasi diagnostik yang membantu debugging.