Packages

A comprehensive Elixir object system with AI integration, hierarchical coordination, and meta-schema evolution capabilities

Current section

Files

Jump to
object lib quantum_measurement.ex
Raw

lib/quantum_measurement.ex

defmodule Object.QuantumMeasurement do
@moduledoc """
Quantum measurement simulation with probabilistic outcomes and real-time correlation.
Implements the fundamental postulates of quantum mechanics:
1. State collapse upon measurement
2. Born rule for measurement probabilities
3. Instantaneous correlation for entangled systems
4. Measurement basis transformations
"""
alias Object.QuantumEntanglement.{Complex, QubitState, EntangledPair}
# Helper function to generate unique IDs
defp generate_id do
:crypto.strong_rand_bytes(16) |> Base.encode16(case: :lower)
end
defmodule MeasurementResult do
defstruct [
:qubit_id, :measurement_basis, :outcome, :probability,
:timestamp, :correlation_id, :entangled_partner_outcome
]
@type t :: %__MODULE__{
qubit_id: String.t(),
measurement_basis: :z | :x | :y | {:custom, float()},
outcome: 0 | 1,
probability: float(),
timestamp: DateTime.t(),
correlation_id: String.t() | nil,
entangled_partner_outcome: 0 | 1 | nil
}
end
@doc """
Performs Z-basis measurement on a single qubit.
Returns {measurement_result, collapsed_state}
"""
def measure_z_basis(%QubitState{measured: true} = state) do
# Already measured - return previous result
result = %MeasurementResult{
qubit_id: generate_id(),
measurement_basis: :z,
outcome: state.measurement_result,
probability: 1.0,
timestamp: DateTime.utc_now(),
correlation_id: nil,
entangled_partner_outcome: nil
}
{result, state}
end
def measure_z_basis(%QubitState{} = state) do
prob_0 = QubitState.probability_0(state)
# Generate quantum random outcome based on Born rule
outcome = if :rand.uniform() < prob_0, do: 0, else: 1
# Collapse state vector
collapsed_state = case outcome do
0 -> %QubitState{
amplitude_0: Complex.new(1.0),
amplitude_1: Complex.new(0.0),
measured: true,
measurement_result: 0
}
1 -> %QubitState{
amplitude_0: Complex.new(0.0),
amplitude_1: Complex.new(1.0),
measured: true,
measurement_result: 1
}
end
result = %MeasurementResult{
qubit_id: generate_id(),
measurement_basis: :z,
outcome: outcome,
probability: if(outcome == 0, do: prob_0, else: 1.0 - prob_0),
timestamp: DateTime.utc_now(),
correlation_id: nil,
entangled_partner_outcome: nil
}
{result, collapsed_state}
end
@doc """
Performs X-basis (Hadamard rotated) measurement on a single qubit.
Transforms |0⟩ → (|0⟩ + |1⟩)/√2, |1⟩ → (|0⟩ - |1⟩)/√2
"""
def measure_x_basis(%QubitState{} = state) do
# Apply Hadamard transformation before Z-measurement
hadamard_state = apply_hadamard(state)
{result, collapsed} = measure_z_basis(hadamard_state)
# Transform result back to X-basis interpretation
x_result = %MeasurementResult{result | measurement_basis: :x}
{x_result, collapsed}
end
@doc """
Performs Y-basis measurement on a single qubit.
"""
def measure_y_basis(%QubitState{} = state) do
# Apply Y-basis rotation: |0⟩ → (|0⟩ + i|1⟩)/√2, |1⟩ → (|0⟩ - i|1⟩)/√2
y_rotated_state = apply_y_rotation(state)
{result, collapsed} = measure_z_basis(y_rotated_state)
y_result = %MeasurementResult{result | measurement_basis: :y}
{y_result, collapsed}
end
@doc """
Measures one qubit of an entangled pair, causing instantaneous correlation.
Returns {local_result, partner_result, collapsed_pair_state}
"""
def measure_entangled_pair(%EntangledPair{measured_qubits: measured} = pair, qubit_index, basis \\ :z)
when qubit_index in [0, 1] do
if MapSet.member?(measured, qubit_index) do
# Qubit already measured
{:error, :already_measured}
else
case basis do
:z -> measure_entangled_z_basis(pair, qubit_index)
:x -> measure_entangled_x_basis(pair, qubit_index)
:y -> measure_entangled_y_basis(pair, qubit_index)
end
end
end
defp measure_entangled_z_basis(%EntangledPair{} = pair, qubit_index) do
# Calculate joint measurement probabilities
probs = %{
"00" => EntangledPair.probability_00(pair),
"01" => EntangledPair.probability_01(pair),
"10" => EntangledPair.probability_10(pair),
"11" => EntangledPair.probability_11(pair)
}
# Generate correlated measurement outcomes
rand_val = :rand.uniform()
{outcome_local, outcome_partner, joint_prob} = cond do
rand_val < probs["00"] ->
{0, 0, probs["00"]}
rand_val < probs["00"] + probs["01"] ->
{0, 1, probs["01"]}
rand_val < probs["00"] + probs["01"] + probs["10"] ->
{1, 0, probs["10"]}
true ->
{1, 1, probs["11"]}
end
# Adjust outcomes based on which qubit is measured first
{local_outcome, partner_outcome} = if qubit_index == 0 do
{outcome_local, outcome_partner}
else
{outcome_partner, outcome_local}
end
timestamp = DateTime.utc_now()
correlation_id = generate_id()
local_result = %MeasurementResult{
qubit_id: "entangled_#{pair.entanglement_id}_qubit_#{qubit_index}",
measurement_basis: :z,
outcome: local_outcome,
probability: joint_prob,
timestamp: timestamp,
correlation_id: correlation_id,
entangled_partner_outcome: partner_outcome
}
partner_result = %MeasurementResult{
qubit_id: "entangled_#{pair.entanglement_id}_qubit_#{1 - qubit_index}",
measurement_basis: :z,
outcome: partner_outcome,
probability: joint_prob,
timestamp: timestamp,
correlation_id: correlation_id,
entangled_partner_outcome: local_outcome
}
# Collapse the entangled state
collapsed_pair = collapse_entangled_state(pair, local_outcome, partner_outcome, qubit_index)
{local_result, partner_result, collapsed_pair}
end
defp measure_entangled_x_basis(%EntangledPair{} = pair, qubit_index) do
# Transform to X-basis before measurement
x_transformed_pair = apply_hadamard_to_pair(pair, qubit_index)
{local, partner, collapsed} = measure_entangled_z_basis(x_transformed_pair, qubit_index)
# Update measurement basis in results
local_x = %MeasurementResult{local | measurement_basis: :x}
partner_x = %MeasurementResult{partner | measurement_basis: :x}
{local_x, partner_x, collapsed}
end
defp measure_entangled_y_basis(%EntangledPair{} = pair, qubit_index) do
# Transform to Y-basis before measurement
y_transformed_pair = apply_y_rotation_to_pair(pair, qubit_index)
{local, partner, collapsed} = measure_entangled_z_basis(y_transformed_pair, qubit_index)
# Update measurement basis in results
local_y = %MeasurementResult{local | measurement_basis: :y}
partner_y = %MeasurementResult{partner | measurement_basis: :y}
{local_y, partner_y, collapsed}
end
@doc """
Calculate Bell inequality CHSH correlation for entangled pair measurements.
CHSH inequality: |E(a,b) - E(a,b') + E(a',b) + E(a',b')| ≤ 2 (classical)
Quantum mechanics can violate this up to 2√2 ≈ 2.828 (Tsirelson bound)
"""
def calculate_bell_correlation(measurements) when is_list(measurements) do
# Group measurements by correlation_id
correlated_pairs = measurements
|> Enum.filter(& &1.correlation_id)
|> Enum.group_by(& &1.correlation_id)
|> Enum.filter(fn {_id, results} -> length(results) == 2 end)
if length(correlated_pairs) < 4 do
{:error, :insufficient_measurements}
else
# Calculate E(a,b) = ⟨AB⟩ correlation function
correlation_sum = correlated_pairs
|> Enum.map(fn {_id, [result1, result2]} ->
# Convert 0,1 outcomes to -1,+1 for correlation calculation
outcome1 = if result1.outcome == 0, do: -1, else: 1
outcome2 = if result2.outcome == 0, do: -1, else: 1
outcome1 * outcome2
end)
|> Enum.sum()
correlation = correlation_sum / length(correlated_pairs)
%{
correlation: correlation,
measurement_pairs: length(correlated_pairs),
bell_parameter: abs(correlation),
violates_local_realism: abs(correlation) > 2.0,
quantum_correlation_strength: abs(correlation) / 2.828 # Normalized to Tsirelson bound
}
end
end
# Private helper functions
defp apply_hadamard(%QubitState{amplitude_0: a0, amplitude_1: a1}) do
# H|0⟩ = (|0⟩ + |1⟩)/√2, H|1⟩ = (|0⟩ - |1⟩)/√2
inv_sqrt2 = 1.0 / :math.sqrt(2)
new_amp_0 = Complex.add(
Complex.scale(a0, inv_sqrt2),
Complex.scale(a1, inv_sqrt2)
)
new_amp_1 = Complex.add(
Complex.scale(a0, inv_sqrt2),
Complex.scale(a1, -inv_sqrt2)
)
%QubitState{amplitude_0: new_amp_0, amplitude_1: new_amp_1, measured: false}
end
defp apply_y_rotation(%QubitState{amplitude_0: a0, amplitude_1: a1}) do
# Y-basis rotation: complex transformation with imaginary components
inv_sqrt2 = 1.0 / :math.sqrt(2)
new_amp_0 = Complex.add(
Complex.scale(a0, inv_sqrt2),
Complex.multiply(Complex.scale(a1, inv_sqrt2), Complex.new(0.0, 1.0))
)
new_amp_1 = Complex.add(
Complex.scale(a0, inv_sqrt2),
Complex.multiply(Complex.scale(a1, -inv_sqrt2), Complex.new(0.0, 1.0))
)
%QubitState{amplitude_0: new_amp_0, amplitude_1: new_amp_1, measured: false}
end
defp apply_hadamard_to_pair(%EntangledPair{} = pair, qubit_index) do
# Apply Hadamard gate to specified qubit in entangled pair
# This is a simplified implementation - full tensor product transformation needed
inv_sqrt2 = 1.0 / :math.sqrt(2)
if qubit_index == 0 do
# Apply H ⊗ I (Hadamard on first qubit, identity on second)
%EntangledPair{pair |
amplitude_00: Complex.scale(Complex.add(pair.amplitude_00, pair.amplitude_10), inv_sqrt2),
amplitude_01: Complex.scale(Complex.add(pair.amplitude_01, pair.amplitude_11), inv_sqrt2),
amplitude_10: Complex.scale(Complex.add(pair.amplitude_00, Complex.scale(pair.amplitude_10, -1)), inv_sqrt2),
amplitude_11: Complex.scale(Complex.add(pair.amplitude_01, Complex.scale(pair.amplitude_11, -1)), inv_sqrt2)
}
else
# Apply I ⊗ H (identity on first qubit, Hadamard on second)
%EntangledPair{pair |
amplitude_00: Complex.scale(Complex.add(pair.amplitude_00, pair.amplitude_01), inv_sqrt2),
amplitude_01: Complex.scale(Complex.add(pair.amplitude_00, Complex.scale(pair.amplitude_01, -1)), inv_sqrt2),
amplitude_10: Complex.scale(Complex.add(pair.amplitude_10, pair.amplitude_11), inv_sqrt2),
amplitude_11: Complex.scale(Complex.add(pair.amplitude_10, Complex.scale(pair.amplitude_11, -1)), inv_sqrt2)
}
end
end
defp apply_y_rotation_to_pair(%EntangledPair{} = pair, qubit_index) do
# Similar to Hadamard but with Y-gate transformation
# Simplified implementation - would need full tensor algebra in production
inv_sqrt2 = 1.0 / :math.sqrt(2)
i = Complex.new(0.0, 1.0)
if qubit_index == 0 do
%EntangledPair{pair |
amplitude_00: Complex.scale(Complex.add(pair.amplitude_00, Complex.multiply(pair.amplitude_10, i)), inv_sqrt2),
amplitude_01: Complex.scale(Complex.add(pair.amplitude_01, Complex.multiply(pair.amplitude_11, i)), inv_sqrt2),
amplitude_10: Complex.scale(Complex.add(pair.amplitude_00, Complex.multiply(pair.amplitude_10, Complex.scale(i, -1))), inv_sqrt2),
amplitude_11: Complex.scale(Complex.add(pair.amplitude_01, Complex.multiply(pair.amplitude_11, Complex.scale(i, -1))), inv_sqrt2)
}
else
%EntangledPair{pair |
amplitude_00: Complex.scale(Complex.add(pair.amplitude_00, Complex.multiply(pair.amplitude_01, i)), inv_sqrt2),
amplitude_01: Complex.scale(Complex.add(pair.amplitude_00, Complex.multiply(pair.amplitude_01, Complex.scale(i, -1))), inv_sqrt2),
amplitude_10: Complex.scale(Complex.add(pair.amplitude_10, Complex.multiply(pair.amplitude_11, i)), inv_sqrt2),
amplitude_11: Complex.scale(Complex.add(pair.amplitude_10, Complex.multiply(pair.amplitude_11, Complex.scale(i, -1))), inv_sqrt2)
}
end
end
defp collapse_entangled_state(%EntangledPair{} = pair, outcome_0, outcome_1, measured_qubit) do
# Collapse to definite computational basis state
{new_00, new_01, new_10, new_11} = case {outcome_0, outcome_1} do
{0, 0} -> {Complex.new(1.0), Complex.new(0.0), Complex.new(0.0), Complex.new(0.0)}
{0, 1} -> {Complex.new(0.0), Complex.new(1.0), Complex.new(0.0), Complex.new(0.0)}
{1, 0} -> {Complex.new(0.0), Complex.new(0.0), Complex.new(1.0), Complex.new(0.0)}
{1, 1} -> {Complex.new(0.0), Complex.new(0.0), Complex.new(0.0), Complex.new(1.0)}
end
updated_stats = %{
measurements: pair.correlation_stats.measurements + 1,
correlations: [
%{outcome_0: outcome_0, outcome_1: outcome_1, timestamp: DateTime.utc_now()} |
pair.correlation_stats.correlations
]
}
%EntangledPair{pair |
amplitude_00: new_00,
amplitude_01: new_01,
amplitude_10: new_10,
amplitude_11: new_11,
measured_qubits: MapSet.put(pair.measured_qubits, measured_qubit),
correlation_stats: updated_stats
}
end
end