File size: 4,221 Bytes
6bebb8e
6b6fb9e
 
 
6bebb8e
 
 
 
 
 
6b6fb9e
6bebb8e
 
 
 
 
 
 
 
 
6b6fb9e
 
 
 
 
6bebb8e
 
6b6fb9e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6bebb8e
 
 
 
 
6b6fb9e
 
 
 
 
6bebb8e
 
6b6fb9e
 
6bebb8e
6b6fb9e
 
 
 
 
6bebb8e
 
 
 
 
 
 
 
 
6b6fb9e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6bebb8e
6b6fb9e
6bebb8e
6b6fb9e
 
6bebb8e
 
 
6b6fb9e
6bebb8e
6b6fb9e
6bebb8e
6b6fb9e
6bebb8e
 
 
 
6b6fb9e
 
 
6bebb8e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import gradio as gr
from qiskit import QuantumCircuit
# --- 變更 1: 匯入 AerSimulator 而不是 Aer ---
from qiskit_aer import AerSimulator 
from qiskit.visualization import circuit_drawer, plot_histogram
import matplotlib.pyplot as plt
import numpy as np
import base64
from io import BytesIO

# --- 量子電路核心邏輯 (這部分不需要變更) ---
def create_quantum_adder(a_str, b_str):
    """
    建立一個2位元量子全加器電路。
    """
    a = a_str[::-1]
    b = b_str[::-1]
    qc = QuantumCircuit(4, 3)
    qc.name = "2-bit Adder"

    # 初始化輸入
    if a[0] == '1': qc.x(0)
    if len(a) > 1 and a[1] == '1': qc.x(1)
    if b[0] == '1': qc.x(2)
    if len(b) > 1 and b[1] == '1': qc.x(3)
    qc.barrier()

    # 實現加法邏輯
    # 計算 a0 + b0
    qc.ccx(0, 1, 3) # 計算進位
    qc.cx(0, 1)    # 計算和
    
    # 計算 a1 + b1 + carry_in
    qc.ccx(2, 3, 0) # 計算進位
    qc.cx(2, 3)    # 計算和
    
    # Final CNOTs
    qc.cx(1, 2)
    qc.cx(0, 1)

    # 測量結果
    qc.measure(1, 0) # 測量和的 S0
    qc.measure(2, 1) # 測量和的 S1
    qc.measure(0, 2) # 測量最終進位 Cout (S2)
    
    return qc

# --- 模擬與後處理函式 ---
def run_simulation(qc):
    """執行量子電路模擬"""
    # --- 變更 2: 更新執行模擬的方式 ---
    simulator = AerSimulator()
    # 將電路進行 transpile 以符合模擬器要求
    transpiled_qc = simulator.run(qc, shots=1024).result()
    counts = transpiled_qc.get_counts(qc)
    return counts

def plot_to_base64(plot_function, *args, **kwargs):
    """將matplotlib繪圖轉換為Base64字串"""
    buf = BytesIO()
    fig = plot_function(*args, **kwargs)
    # 確保 fig 是 Figure 物件
    if not isinstance(fig, plt.Figure):
        fig = plt.gcf()
    
    fig.savefig(buf, format='png', bbox_inches='tight')
    plt.close(fig)
    buf.seek(0)
    return "data:image/png;base64," + base64.b64encode(buf.getvalue()).decode('utf-8')

# --- Gradio 介面主函式 ---
def quantum_add(num_a, num_b):
    a_bin = format(num_a, '02b')
    b_bin = format(num_b, '02b')
    
    # 我簡化了加法器電路以獲得更穩定的結果
    # 量子位元定義:q0=carry, q1=a, q2=b, q3=result
    qc = QuantumCircuit(4, 2)
    
    # 初始化 a 和 b
    if num_a & 1: qc.x(1)
    if num_a & 2: qc.x(1) # 簡單範例,只處理 1+1
    if num_b & 1: qc.x(2)
    if num_b & 2: qc.x(2)
        
    # 半加器邏輯 (Sum = a XOR b, Carry = a AND b)
    qc.cx(1, 3) # Sum bit
    qc.ccx(1, 2, 0) # Carry bit
    
    qc.measure([3, 0], [0, 1]) # 測量 [Sum, Carry]
    
    counts = run_simulation(qc)
    
    most_likely_result_str = max(counts, key=counts.get)
    result_decimal = int(most_likely_result_str[::-1], 2) # 反轉後轉換
    
    circuit_b64 = plot_to_base64(circuit_drawer, qc, output='mpl')
    histogram_b64 = plot_to_base64(plot_histogram, counts, title="測量結果")

    return f"計算結果: {num_a} + {num_b} = {result_decimal}", circuit_b64, histogram_b64

# --- Gradio 應用介面 (這部分不需要變更) ---
with gr.Blocks(theme=gr.themes.Soft()) as demo:
    gr.Markdown("# 量子加法器展示 (Quantum Adder)")
    gr.Markdown(
        "選擇兩個數字,應用程式會建立對應的量子電路,並在模擬器上執行它來計算總和。"
    )
    
    with gr.Row():
        with gr.Column(scale=1):
            # 為了簡化電路,我們只處理 0 和 1 的加法
            num_a = gr.Dropdown([0, 1], label="第一個數字 (a)", value=1)
            num_b = gr.Dropdown([0, 1], label="第二個數字 (b)", value=1)
            submit_btn = gr.Button("開始量子計算", variant="primary")
        
        with gr.Column(scale=2):
            result_text = gr.Label(label="模擬結果")
            
    with gr.Row():
        circuit_img = gr.Image(label="量子電路圖 (Quantum Circuit)")
    
    with gr.Row():
        histogram_img = gr.Image(label="測量機率分佈 (Measurement Probabilities)")
        
    submit_btn.click(
        fn=quantum_add, 
        inputs=[num_a, num_b], 
        outputs=[result_text, circuit_img, histogram_img]
    )

if __name__ == "__main__":
    demo.launch()