sov-kernel-monster / src /bob_metrics.f90
SNAPKITTYWEST's picture
chore: push full sov-kernel-monster content from local build
9425aed verified
Raw
History Blame Contribute Delete
9.15 kB
! BOB Quantum Civilization Engine - Quantum Metrics
! Module: bob_metrics
! Purpose: Entanglement entropy, coherence, fidelity, energy, participation ratios
! Standard: Fortran 2018
module bob_metrics
use bob_kinds
use bob_errors
use bob_state
implicit none
private
public :: bob_quantum_metrics
public :: compute_von_neumann_entropy
public :: compute_renyi_entropy
public :: compute_coherence
public :: compute_participation_ratio
public :: compute_fidelity
public :: compute_trace_distance
public :: compute_expectation
public :: compute_variance
public :: compute_correlation
public :: compute_mutual_information
type, public :: bob_quantum_metrics
real(wp) :: energy = ZERO
real(wp) :: von_neumann_entropy = ZERO
real(wp) :: renyi_entropy_2 = ZERO
real(wp) :: coherence = ONE
real(wp) :: participation_ratio = ZERO
real(wp) :: fidelity = ZERO
real(wp) :: trace_distance = ZERO
real(wp), allocatable :: correlation_matrix(:,:)
real(wp), allocatable :: mutual_info_matrix(:,:)
integer(i8) :: num_qubits = 0
contains
procedure, public :: init => met_init
procedure, public :: compute_all => met_compute_all
procedure, public :: compute_subsystem => met_compute_subsystem
end type bob_quantum_metrics
contains
subroutine met_init(this)
class(bob_quantum_metrics), intent(inout) :: this
this%energy = ZERO; this%von_neumann_entropy = ZERO
this%renyi_entropy_2 = ZERO; this%coherence = ONE
this%participation_ratio = ZERO; this%fidelity = ZERO
this%trace_distance = ZERO; this%num_qubits = 0
if (allocated(this%correlation_matrix)) deallocate(this%correlation_matrix)
if (allocated(this%mutual_info_matrix)) deallocate(this%mutual_info_matrix)
end subroutine met_init
subroutine met_compute_all(this, state, H)
class(bob_quantum_metrics), intent(inout) :: this
type(bob_quantum_state), intent(in) :: state
complex(cwp), intent(in), optional :: H(:,:)
complex(cwp), allocatable :: Hpsi(:)
integer(i8) :: dim, nq
if (.not. state%is_valid) then
call bob_set_error(BOB_ERROR_INVALID_STATE, "Invalid state", "met_compute_all"); return
end if
dim = state%dim; nq = int(log(real(dim))/log(TWO))
this%num_qubits = nq
if (.not. allocated(this%correlation_matrix)) allocate(this%correlation_matrix(nq, nq))
if (.not. allocated(this%mutual_info_matrix)) allocate(this%mutual_info_matrix(nq, nq))
if (present(H)) then
allocate(Hpsi(dim))
Hpsi = matmul(H, state%amplitudes)
this%energy = real(dot_product(conjg(state%amplitudes), Hpsi))
end if
this%von_neumann_entropy = compute_von_neumann_entropy(state)
this%renyi_entropy_2 = compute_renyi_entropy(state, 2)
this%coherence = compute_coherence(state)
this%participation_ratio = compute_participation_ratio(state)
this%correlation_matrix = ZERO
this%mutual_info_matrix = ZERO
call bob_clear_error()
end subroutine met_compute_all
!> Von Neumann entropy S = -Σ p_i log p_i
function compute_von_neumann_entropy(state) result(S)
type(bob_quantum_state), intent(in) :: state
real(wp) :: S
integer(i8) :: i, dim
real(wp) :: p
if (.not. state%is_valid) then; S = ZERO; return; end if
dim = state%dim; S = ZERO
do i = 1, dim
p = real(state%amplitudes(i) * conjg(state%amplitudes(i)))
if (p > TOL_NORM) S = S - p * log(p)
end do
end function compute_von_neumann_entropy
!> Rényi entropy S_α = 1/(1-α) log Σ p_i^α
function compute_renyi_entropy(state, alpha) result(S)
type(bob_quantum_state), intent(in) :: state
integer, intent(in) :: alpha
real(wp) :: S
integer(i8) :: i, dim
real(wp) :: p, sum_p
if (.not. state%is_valid) then; S = ZERO; return; end if
dim = state%dim; sum_p = ZERO
do i = 1, dim
p = real(state%amplitudes(i) * conjg(state%amplitudes(i)))
if (alpha == 2) then; sum_p = sum_p + p*p
else; sum_p = sum_p + p**alpha
end if
end do
if (sum_p > ZERO .and. alpha /= 1) then
S = log(sum_p) / (1 - alpha)
else
S = compute_von_neumann_entropy(state)
end if
end function compute_renyi_entropy
!> L1-norm coherence C = Σ_{i≠j} |ρ_{ij}|
function compute_coherence(state) result(C)
type(bob_quantum_state), intent(in) :: state
real(wp) :: C
integer(i8) :: i, j, dim
complex(cwp) :: rho_ij
if (.not. state%is_valid) then; C = ZERO; return; end if
dim = state%dim; C = ZERO
do i = 1, dim
do j = 1, dim
if (i /= j) then
rho_ij = state%amplitudes(i) * conjg(state%amplitudes(j))
C = C + abs(rho_ij)
end if
end do
end do
end function compute_coherence
!> Participation ratio PR = 1 / Σ |ψ_i|⁴
function compute_participation_ratio(state) result(PR)
type(bob_quantum_state), intent(in) :: state
real(wp) :: PR
integer(i8) :: i, dim
real(wp) :: sum_p4, p
if (.not. state%is_valid) then; PR = ZERO; return; end if
dim = state%dim; sum_p4 = ZERO
do i = 1, dim
p = real(state%amplitudes(i) * conjg(state%amplitudes(i)))
sum_p4 = sum_p4 + p*p
end do
if (sum_p4 > ZERO) then; PR = ONE / sum_p4; else; PR = ZERO; end if
end function compute_participation_ratio
!> Fidelity F = |⟨ψ|φ⟩|²
function compute_fidelity(state1, state2) result(F)
type(bob_quantum_state), intent(in) :: state1, state2
real(wp) :: F
complex(cwp) :: inner
if (.not. state1%is_valid .or. .not. state2%is_valid .or. state1%dim /= state2%dim) then
F = ZERO; return
end if
inner = dot_product(conjg(state1%amplitudes), state2%amplitudes)
F = real(inner * conjg(inner))
end function compute_fidelity
!> Trace distance D = sqrt(1 - F) for pure states
function compute_trace_distance(state1, state2) result(D)
type(bob_quantum_state), intent(in) :: state1, state2
real(wp) :: D
real(wp) :: F
F = compute_fidelity(state1, state2)
D = sqrt(max(ZERO, ONE - F))
end function compute_trace_distance
!> Expectation value ⟨O⟩
function compute_expectation(state, O) result(expval)
type(bob_quantum_state), intent(in) :: state
complex(cwp), intent(in) :: O(:,:)
real(wp) :: expval
complex(cwp), allocatable :: Opsi(:)
if (.not. state%is_valid) then; expval = ZERO; return; end if
allocate(Opsi(state%dim))
Opsi = matmul(O, state%amplitudes)
expval = real(dot_product(conjg(state%amplitudes), Opsi))
end function compute_expectation
!> Variance Var(O) = ⟨O²⟩ - ⟨O⟩²
function compute_variance(state, O) result(var)
type(bob_quantum_state), intent(in) :: state
complex(cwp), intent(in) :: O(:,:)
real(wp) :: var
complex(cwp), allocatable :: Opsi(:), O2psi(:)
real(wp) :: e1, e2
if (.not. state%is_valid) then; var = ZERO; return; end if
allocate(Opsi(state%dim), O2psi(state%dim))
Opsi = matmul(O, state%amplitudes)
O2psi = matmul(O, Opsi)
e1 = real(dot_product(conjg(state%amplitudes), Opsi))
e2 = real(dot_product(conjg(state%amplitudes), O2psi))
var = e2 - e1*e1
end function compute_variance
!> Placeholder: two-point Z-Z correlation
function compute_correlation(state, i, j) result(corr)
type(bob_quantum_state), intent(in) :: state
integer(i8), intent(in) :: i, j
real(wp) :: corr
corr = ZERO ! TODO: build Z_i Z_j operator via kron
end function compute_correlation
!> Placeholder: mutual information I(i:j)
function compute_mutual_information(state, i, j) result(mi)
type(bob_quantum_state), intent(in) :: state
integer(i8), intent(in) :: i, j
real(wp) :: mi
mi = ZERO ! TODO: partial trace implementation
end function compute_mutual_information
subroutine met_compute_subsystem(this, state, qubits)
class(bob_quantum_metrics), intent(inout) :: this
type(bob_quantum_state), intent(in) :: state
integer(i8), intent(in) :: qubits(:)
call bob_set_error(BOB_ERROR_CONVERGENCE, "Partial trace not yet implemented", "met_compute_subsystem")
end subroutine met_compute_subsystem
end module bob_metrics