Skip to content

qsci_algorithms

Implementation of QSCI and TE-QSCI algorithms using quri-parts framework.

This module provides implementations of: 1. Vanilla QSCI algorithm 2. Time-Evolved QSCI (TE-QSCI) variants 3. Algorithm interfaces compatible with quri-algo

Key algorithms: - QSCI: Quantum Selected Configuration Interaction - TE-QSCI: Time-Evolved QSCI (single-time and time-average variants)

Classes:

Name Description
QSCIVariant

Enumeration of QSCI algorithm variants.

QSCIResult

Result of QSCI algorithm execution.

QSCIBase

Base class for QSCI algorithms.

VanillaQSCI

Vanilla QSCI algorithm implementation.

TimeEvolvedQSCI

Time-Evolved QSCI (TE-QSCI) algorithm implementation.

SingleTimeTE_QSCI

Single-time TE-QSCI wrapper for testing compatibility.

TimeAverageTE_QSCI

Time-average TE-QSCI wrapper for testing compatibility.

FfsimStateVectorQSCI

QSCI algorithm for direct ffsim state vector input.

StateVectorTE_QSCI

State vector TE-QSCI wrapper for testing compatibility.

QSCIVariant

Bases: Enum

Enumeration of QSCI algorithm variants.

Attributes:

Name Type Description
VANILLA
SINGLE_TIME_TE
TIME_AVERAGE_TE
STATE_VECTOR

VANILLA class-attribute instance-attribute

VANILLA = 'vanilla'

SINGLE_TIME_TE class-attribute instance-attribute

SINGLE_TIME_TE = 'single_time_te'

TIME_AVERAGE_TE class-attribute instance-attribute

TIME_AVERAGE_TE = 'time_average_te'

STATE_VECTOR class-attribute instance-attribute

STATE_VECTOR = 'state_vector'

QSCIResult dataclass

QSCIResult(
    eigenvalues,
    eigenstates,
    selected_states,
    subspace_dimension,
    total_shots,
    algorithm_variant,
    execution_time=None,
    computational_basis_probabilities=None,
)

Result of QSCI algorithm execution.

Attributes:

Name Type Description
eigenvalues Sequence[float]
eigenstates Sequence[ComputationalBasisSuperposition]
selected_states Sequence[ComputationalBasisState]
subspace_dimension int
total_shots int
algorithm_variant QSCIVariant
execution_time Optional[float]
computational_basis_probabilities Optional[Dict[int, float]]
ground_state_energy float

Ground state energy (lowest eigenvalue).

ground_state ComputationalBasisSuperposition

Ground state (eigenstate corresponding to lowest eigenvalue).

ground_state_probability float

Probability of measuring the ground state in computational basis.

eigenvalues instance-attribute

eigenvalues

eigenstates instance-attribute

eigenstates

selected_states instance-attribute

selected_states

subspace_dimension instance-attribute

subspace_dimension

total_shots instance-attribute

total_shots

algorithm_variant instance-attribute

algorithm_variant

execution_time class-attribute instance-attribute

execution_time = None

computational_basis_probabilities class-attribute instance-attribute

computational_basis_probabilities = None

ground_state_energy property

ground_state_energy

Ground state energy (lowest eigenvalue).

ground_state property

ground_state

Ground state (eigenstate corresponding to lowest eigenvalue).

ground_state_probability property

ground_state_probability

Probability of measuring the ground state in computational basis.

QSCIBase

QSCIBase(
    hamiltonian, sampler=None, num_states_pick_out=None
)

Bases: ABC

Base class for QSCI algorithms.

Parameters:

Name Type Description Default

hamiltonian

Operator

Target Hamiltonian to diagonalize

required

sampler

Optional[ConcurrentSampler]

Quantum sampler for measurement

None

num_states_pick_out

Optional[int]

Number of states to select for subspace

None

Methods:

Name Description
run

Run the QSCI algorithm.

Attributes:

Name Type Description
hamiltonian
sampler
num_states_pick_out
Source code in src/qsci_algorithms.py
def __init__(
    self,
    hamiltonian: Operator,
    sampler: Optional[ConcurrentSampler] = None,
    num_states_pick_out: Optional[int] = None
):
    """Initialize QSCI algorithm.

    Args:
        hamiltonian: Target Hamiltonian to diagonalize
        sampler: Quantum sampler for measurement
        num_states_pick_out: Number of states to select for subspace
    """
    if not is_hermitian(hamiltonian):
        raise ValueError("Hamiltonian must be Hermitian")

    self.hamiltonian = hamiltonian
    self.sampler = sampler
    self.num_states_pick_out = num_states_pick_out

hamiltonian instance-attribute

hamiltonian = hamiltonian

sampler instance-attribute

sampler = sampler

num_states_pick_out instance-attribute

num_states_pick_out = num_states_pick_out

run abstractmethod

Run the QSCI algorithm.

Parameters:

Name Type Description Default

input_states

Sequence[CircuitQuantumState]

Input quantum states for sampling

required

total_shots

int

Total number of measurement shots

required

**kwargs

Additional algorithm-specific parameters

{}

Returns:

Type Description
QSCIResult

QSCIResult containing eigenvalues, eigenstates, and metadata

Source code in src/qsci_algorithms.py
@abstractmethod
def run(
    self,
    input_states: Sequence[CircuitQuantumState],
    total_shots: int,
    **kwargs
) -> QSCIResult:
    """Run the QSCI algorithm.

    Args:
        input_states: Input quantum states for sampling
        total_shots: Total number of measurement shots
        **kwargs: Additional algorithm-specific parameters

    Returns:
        QSCIResult containing eigenvalues, eigenstates, and metadata
    """
    pass

VanillaQSCI

VanillaQSCI(
    hamiltonian, sampler=None, num_states_pick_out=None
)

Bases: QSCIBase

Vanilla QSCI algorithm implementation.

Parameters:

Name Type Description Default

hamiltonian

Operator

Target Hamiltonian to diagonalize

required

sampler

Optional[ConcurrentSampler]

Quantum sampler for measurement

None

num_states_pick_out

Optional[int]

Number of states to select for subspace

None

Methods:

Name Description
run

Run vanilla QSCI algorithm.

Attributes:

Name Type Description
hamiltonian
sampler
num_states_pick_out
Source code in src/qsci_algorithms.py
def __init__(
    self,
    hamiltonian: Operator,
    sampler: Optional[ConcurrentSampler] = None,
    num_states_pick_out: Optional[int] = None
):
    """Initialize QSCI algorithm.

    Args:
        hamiltonian: Target Hamiltonian to diagonalize
        sampler: Quantum sampler for measurement
        num_states_pick_out: Number of states to select for subspace
    """
    if not is_hermitian(hamiltonian):
        raise ValueError("Hamiltonian must be Hermitian")

    self.hamiltonian = hamiltonian
    self.sampler = sampler
    self.num_states_pick_out = num_states_pick_out

hamiltonian instance-attribute

hamiltonian = hamiltonian

sampler instance-attribute

sampler = sampler

num_states_pick_out instance-attribute

num_states_pick_out = num_states_pick_out

run

run(input_states, total_shots, **kwargs)

Run vanilla QSCI algorithm.

Source code in src/qsci_algorithms.py
def run(
    self,
    input_states: Sequence[CircuitQuantumState],
    total_shots: int,
    **kwargs
) -> QSCIResult:
    """Run vanilla QSCI algorithm."""
    if not self.sampler:
        raise ValueError("Sampler is required for vanilla QSCI")

    start_time = kwargs.get("start_time")
    qubit_count = input_states[0].qubit_count
    num_eigs_calc = len(input_states)

    # Validate num_states_pick_out
    if self.num_states_pick_out and self.num_states_pick_out < num_eigs_calc:
        raise ValueError(
            "num_states_pick_out must be larger than or equal to the number of input_states"
        )

    # Sample from input states
    circuits = [state.circuit for state in input_states]
    meas_counts_list = self.sampler(
        [(circuit, total_shots // num_eigs_calc) for circuit in circuits]
    )

    # Merge measurement counts
    merged_meas_counts: Dict[int, Union[int, float]] = {}
    for meas_counts in meas_counts_list:
        for bits, counts in meas_counts.items():
            merged_meas_counts[bits] = merged_meas_counts.get(bits, 0) + counts

    # Select important states
    selected_states = self._pick_out_states(
        qubit_count, merged_meas_counts, self.num_states_pick_out
    )

    # Generate and diagonalize truncated Hamiltonian
    truncated_hamiltonian = self._generate_truncated_hamiltonian(selected_states)
    # Fix: Use adaptive eigenvalue computation instead of fixed num_eigs_calc=1
    k = min(len(selected_states), max(1, len(selected_states) // 4))  # 25% of subspace
    eigvals, eigvecs = self._diagonalize_truncated_hamiltonian(
        truncated_hamiltonian, k
    )

    # Construct eigenstates
    eigenstates = [(eigvecs[i], selected_states) for i in range(min(k, len(eigvecs)))]

    execution_time = None
    if start_time:
        import time
        execution_time = time.time() - start_time

    return QSCIResult(
        eigenvalues=eigvals,
        eigenstates=eigenstates,
        selected_states=selected_states,
        subspace_dimension=len(selected_states),
        total_shots=total_shots,
        algorithm_variant=QSCIVariant.VANILLA,
        execution_time=execution_time
    )

TimeEvolvedQSCI

TimeEvolvedQSCI(
    hamiltonian,
    sampler=None,
    num_states_pick_out=None,
    time_evolution_method="trotter",
)

Bases: QSCIBase

Time-Evolved QSCI (TE-QSCI) algorithm implementation.

Parameters:

Name Type Description Default

hamiltonian

Operator

Target Hamiltonian

required

sampler

Optional[ConcurrentSampler]

Quantum sampler (None for state vector variant)

None

num_states_pick_out

Optional[int]

Number of states to select

None

time_evolution_method

str

Method for time evolution ("trotter", "exact")

'trotter'

Methods:

Name Description
run_single_time

Run single-time TE-QSCI algorithm.

run_time_average

Run time-average TE-QSCI algorithm.

run_state_vector

Run TE-QSCI with direct state vector calculation.

run

General run method for TE-QSCI (defaults to single-time).

Attributes:

Name Type Description
time_evolution_method
hamiltonian
sampler
num_states_pick_out
Source code in src/qsci_algorithms.py
def __init__(
    self,
    hamiltonian: Operator,
    sampler: Optional[ConcurrentSampler] = None,
    num_states_pick_out: Optional[int] = None,
    time_evolution_method: str = "trotter"
):
    """Initialize TE-QSCI algorithm.

    Args:
        hamiltonian: Target Hamiltonian
        sampler: Quantum sampler (None for state vector variant)
        num_states_pick_out: Number of states to select
        time_evolution_method: Method for time evolution ("trotter", "exact")
    """
    super().__init__(hamiltonian, sampler, num_states_pick_out)
    self.time_evolution_method = time_evolution_method

    # Store hamiltonian input for lazy factory creation
    self._hamiltonian_input = None  # Will be created when needed
    self._trotter_factory = None    # Lazy instantiation
    self._exact_factory = None      # Lazy instantiation

time_evolution_method instance-attribute

time_evolution_method = time_evolution_method

hamiltonian instance-attribute

hamiltonian = hamiltonian

sampler instance-attribute

sampler = sampler

num_states_pick_out instance-attribute

num_states_pick_out = num_states_pick_out

run_single_time

run_single_time(
    initial_state,
    evolution_time,
    total_shots,
    trotter_steps=None,
    **kwargs
)

Run single-time TE-QSCI algorithm.

Parameters:

Name Type Description Default

initial_state

CircuitQuantumState

Initial quantum state

required

evolution_time

float

Time for evolution

required

total_shots

int

Number of measurement shots

required

trotter_steps

Optional[int]

Number of Trotter steps (if using Trotter method)

None

Returns:

Type Description
QSCIResult

QSCIResult with TE-QSCI results

Source code in src/qsci_algorithms.py
def run_single_time(
    self,
    initial_state: CircuitQuantumState,
    evolution_time: float,
    total_shots: int,
    trotter_steps: Optional[int] = None,
    **kwargs
) -> QSCIResult:
    """Run single-time TE-QSCI algorithm.

    Args:
        initial_state: Initial quantum state
        evolution_time: Time for evolution
        total_shots: Number of measurement shots
        trotter_steps: Number of Trotter steps (if using Trotter method)

    Returns:
        QSCIResult with TE-QSCI results
    """
    if not self.sampler:
        raise ValueError("Sampler is required for single-time TE-QSCI")

    start_time = kwargs.get("start_time")

    # Create time-evolved state
    time_evolved_state = self._create_time_evolved_state(
        initial_state, evolution_time, trotter_steps
    )

    # Calculate computational basis probabilities for Figure 1
    probabilities = self._calculate_computational_basis_probabilities(time_evolved_state)

    # Run QSCI on time-evolved state
    result = self._run_qsci_on_states(
        [time_evolved_state], 
        total_shots, 
        QSCIVariant.SINGLE_TIME_TE,
        start_time
    )

    # Add probability information to result
    result.computational_basis_probabilities = probabilities

    return result

run_time_average

run_time_average(
    initial_state,
    evolution_times,
    shots_per_time,
    trotter_steps=None,
    **kwargs
)

Run time-average TE-QSCI algorithm.

Parameters:

Name Type Description Default

initial_state

CircuitQuantumState

Initial quantum state

required

evolution_times

Sequence[float]

Times for evolution

required

shots_per_time

int

Number of shots per time point

required

trotter_steps

Optional[int]

Number of Trotter steps

None

Returns:

Type Description
QSCIResult

QSCIResult with time-average TE-QSCI results

Source code in src/qsci_algorithms.py
def run_time_average(
    self,
    initial_state: CircuitQuantumState,
    evolution_times: Sequence[float],
    shots_per_time: int,
    trotter_steps: Optional[int] = None,
    **kwargs
) -> QSCIResult:
    """Run time-average TE-QSCI algorithm.

    Args:
        initial_state: Initial quantum state
        evolution_times: Times for evolution
        shots_per_time: Number of shots per time point
        trotter_steps: Number of Trotter steps

    Returns:
        QSCIResult with time-average TE-QSCI results
    """
    if not self.sampler:
        raise ValueError("Sampler is required for time-average TE-QSCI")

    start_time = kwargs.get("start_time")

    # Create time-evolved states
    time_evolved_states = []
    for t in evolution_times:
        evolved_state = self._create_time_evolved_state(
            initial_state, t, trotter_steps
        )
        time_evolved_states.append(evolved_state)

    # Sample from all time-evolved states
    qubit_count = initial_state.qubit_count
    circuits = [state.circuit for state in time_evolved_states]
    meas_counts_list = self.sampler(
        [(circuit, shots_per_time) for circuit in circuits]
    )

    # Merge all measurement counts
    merged_meas_counts: Dict[int, Union[int, float]] = {}
    for meas_counts in meas_counts_list:
        for bits, counts in meas_counts.items():
            merged_meas_counts[bits] = merged_meas_counts.get(bits, 0) + counts

    # Select states and diagonalize
    selected_states = self._pick_out_states(
        qubit_count, merged_meas_counts, self.num_states_pick_out
    )

    truncated_hamiltonian = self._generate_truncated_hamiltonian(selected_states)
    eigvals, eigvecs = self._diagonalize_truncated_hamiltonian(
        truncated_hamiltonian, 1  # Typically only ground state for time-average
    )

    eigenstates = [(eigvecs[i], selected_states) for i in range(len(eigvals))]

    execution_time = None
    if start_time:
        import time
        execution_time = time.time() - start_time

    return QSCIResult(
        eigenvalues=eigvals,
        eigenstates=eigenstates,
        selected_states=selected_states,
        subspace_dimension=len(selected_states),
        total_shots=len(evolution_times) * shots_per_time,
        algorithm_variant=QSCIVariant.TIME_AVERAGE_TE,
        execution_time=execution_time
    )

run_state_vector

run_state_vector(
    initial_state,
    evolution_time,
    num_eigenstates=1,
    **kwargs
)

Run TE-QSCI with direct state vector calculation.

Parameters:

Name Type Description Default

initial_state

QuantumState

Initial quantum state

required

evolution_time

float

Time for evolution

required

num_eigenstates

int

Number of eigenstates to compute

1

Returns:

Type Description
QSCIResult

QSCIResult with state vector TE-QSCI results

Source code in src/qsci_algorithms.py
def run_state_vector(
    self,
    initial_state: QuantumState,
    evolution_time: float,
    num_eigenstates: int = 1,
    **kwargs
) -> QSCIResult:
    """Run TE-QSCI with direct state vector calculation.

    Args:
        initial_state: Initial quantum state
        evolution_time: Time for evolution
        num_eigenstates: Number of eigenstates to compute

    Returns:
        QSCIResult with state vector TE-QSCI results
    """
    start_time = kwargs.get("start_time")

    # Create time-evolved state using exact simulation
    time_evolved_state = self._create_time_evolved_state(
        initial_state, evolution_time, kwargs.get("trotter_steps")
    )

    # Calculate exact computational basis probabilities
    probabilities = self._calculate_computational_basis_probabilities(time_evolved_state)

    # For state vector method, select the most probable states for QSCI subspace
    sorted_probs = sorted(probabilities.items(), key=lambda x: x[1], reverse=True)
    num_states_to_select = self.num_states_pick_out or min(100, len(sorted_probs))

    # Create computational basis states from most probable outcomes
    qubit_count = initial_state.qubit_count
    selected_states = []
    for bits_int, prob in sorted_probs[:num_states_to_select]:
        state = ComputationalBasisState(qubit_count, bits=bits_int)
        selected_states.append(state)

    # Generate and diagonalize truncated Hamiltonian
    truncated_hamiltonian = self._generate_truncated_hamiltonian(selected_states)
    eigvals, eigvecs = self._diagonalize_truncated_hamiltonian(
        truncated_hamiltonian, num_eigenstates
    )

    # Construct eigenstates
    eigenstates = [(eigvecs[i], selected_states) for i in range(num_eigenstates)]

    execution_time = None
    if start_time:
        import time
        execution_time = time.time() - start_time

    return QSCIResult(
        eigenvalues=eigvals,
        eigenstates=eigenstates,
        selected_states=selected_states,
        subspace_dimension=len(selected_states),
        total_shots=0,  # No sampling in state vector method
        algorithm_variant=QSCIVariant.STATE_VECTOR,
        execution_time=execution_time,
        computational_basis_probabilities=probabilities
    )

run

run(input_states, total_shots, **kwargs)

General run method for TE-QSCI (defaults to single-time).

Source code in src/qsci_algorithms.py
def run(
    self,
    input_states: Sequence[CircuitQuantumState],
    total_shots: int,
    **kwargs
) -> QSCIResult:
    """General run method for TE-QSCI (defaults to single-time)."""
    if len(input_states) != 1:
        raise ValueError("TE-QSCI expects exactly one initial state")

    evolution_time = kwargs.get("evolution_time", 1.0)
    trotter_steps = kwargs.get("trotter_steps")

    return self.run_single_time(
        input_states[0], evolution_time, total_shots, trotter_steps, **kwargs
    )

SingleTimeTE_QSCI

SingleTimeTE_QSCI(
    hamiltonian,
    sampler,
    evolution_time,
    num_states_pick_out=None,
)

Bases: TimeEvolvedQSCI

Single-time TE-QSCI wrapper for testing compatibility.

Methods:

Name Description
run
run_single_time

Run single-time TE-QSCI algorithm.

run_time_average

Run time-average TE-QSCI algorithm.

run_state_vector

Run TE-QSCI with direct state vector calculation.

Attributes:

Name Type Description
evolution_time
hamiltonian
sampler
num_states_pick_out
time_evolution_method
Source code in src/qsci_algorithms.py
def __init__(self, hamiltonian, sampler, evolution_time, num_states_pick_out=None):
    super().__init__(hamiltonian, sampler, num_states_pick_out)
    self.evolution_time = evolution_time

evolution_time instance-attribute

evolution_time = evolution_time

hamiltonian instance-attribute

hamiltonian = hamiltonian

sampler instance-attribute

sampler = sampler

num_states_pick_out instance-attribute

num_states_pick_out = num_states_pick_out

time_evolution_method instance-attribute

time_evolution_method = time_evolution_method

run

run(input_states, total_shots, **kwargs)
Source code in src/qsci_algorithms.py
def run(self, input_states, total_shots, **kwargs):
    if len(input_states) != 1:
        raise ValueError("SingleTimeTE_QSCI expects exactly one initial state")
    return self.run_single_time(
        input_states[0], self.evolution_time, total_shots, **kwargs
    )

run_single_time

run_single_time(
    initial_state,
    evolution_time,
    total_shots,
    trotter_steps=None,
    **kwargs
)

Run single-time TE-QSCI algorithm.

Parameters:

Name Type Description Default

initial_state

CircuitQuantumState

Initial quantum state

required

evolution_time

float

Time for evolution

required

total_shots

int

Number of measurement shots

required

trotter_steps

Optional[int]

Number of Trotter steps (if using Trotter method)

None

Returns:

Type Description
QSCIResult

QSCIResult with TE-QSCI results

Source code in src/qsci_algorithms.py
def run_single_time(
    self,
    initial_state: CircuitQuantumState,
    evolution_time: float,
    total_shots: int,
    trotter_steps: Optional[int] = None,
    **kwargs
) -> QSCIResult:
    """Run single-time TE-QSCI algorithm.

    Args:
        initial_state: Initial quantum state
        evolution_time: Time for evolution
        total_shots: Number of measurement shots
        trotter_steps: Number of Trotter steps (if using Trotter method)

    Returns:
        QSCIResult with TE-QSCI results
    """
    if not self.sampler:
        raise ValueError("Sampler is required for single-time TE-QSCI")

    start_time = kwargs.get("start_time")

    # Create time-evolved state
    time_evolved_state = self._create_time_evolved_state(
        initial_state, evolution_time, trotter_steps
    )

    # Calculate computational basis probabilities for Figure 1
    probabilities = self._calculate_computational_basis_probabilities(time_evolved_state)

    # Run QSCI on time-evolved state
    result = self._run_qsci_on_states(
        [time_evolved_state], 
        total_shots, 
        QSCIVariant.SINGLE_TIME_TE,
        start_time
    )

    # Add probability information to result
    result.computational_basis_probabilities = probabilities

    return result

run_time_average

run_time_average(
    initial_state,
    evolution_times,
    shots_per_time,
    trotter_steps=None,
    **kwargs
)

Run time-average TE-QSCI algorithm.

Parameters:

Name Type Description Default

initial_state

CircuitQuantumState

Initial quantum state

required

evolution_times

Sequence[float]

Times for evolution

required

shots_per_time

int

Number of shots per time point

required

trotter_steps

Optional[int]

Number of Trotter steps

None

Returns:

Type Description
QSCIResult

QSCIResult with time-average TE-QSCI results

Source code in src/qsci_algorithms.py
def run_time_average(
    self,
    initial_state: CircuitQuantumState,
    evolution_times: Sequence[float],
    shots_per_time: int,
    trotter_steps: Optional[int] = None,
    **kwargs
) -> QSCIResult:
    """Run time-average TE-QSCI algorithm.

    Args:
        initial_state: Initial quantum state
        evolution_times: Times for evolution
        shots_per_time: Number of shots per time point
        trotter_steps: Number of Trotter steps

    Returns:
        QSCIResult with time-average TE-QSCI results
    """
    if not self.sampler:
        raise ValueError("Sampler is required for time-average TE-QSCI")

    start_time = kwargs.get("start_time")

    # Create time-evolved states
    time_evolved_states = []
    for t in evolution_times:
        evolved_state = self._create_time_evolved_state(
            initial_state, t, trotter_steps
        )
        time_evolved_states.append(evolved_state)

    # Sample from all time-evolved states
    qubit_count = initial_state.qubit_count
    circuits = [state.circuit for state in time_evolved_states]
    meas_counts_list = self.sampler(
        [(circuit, shots_per_time) for circuit in circuits]
    )

    # Merge all measurement counts
    merged_meas_counts: Dict[int, Union[int, float]] = {}
    for meas_counts in meas_counts_list:
        for bits, counts in meas_counts.items():
            merged_meas_counts[bits] = merged_meas_counts.get(bits, 0) + counts

    # Select states and diagonalize
    selected_states = self._pick_out_states(
        qubit_count, merged_meas_counts, self.num_states_pick_out
    )

    truncated_hamiltonian = self._generate_truncated_hamiltonian(selected_states)
    eigvals, eigvecs = self._diagonalize_truncated_hamiltonian(
        truncated_hamiltonian, 1  # Typically only ground state for time-average
    )

    eigenstates = [(eigvecs[i], selected_states) for i in range(len(eigvals))]

    execution_time = None
    if start_time:
        import time
        execution_time = time.time() - start_time

    return QSCIResult(
        eigenvalues=eigvals,
        eigenstates=eigenstates,
        selected_states=selected_states,
        subspace_dimension=len(selected_states),
        total_shots=len(evolution_times) * shots_per_time,
        algorithm_variant=QSCIVariant.TIME_AVERAGE_TE,
        execution_time=execution_time
    )

run_state_vector

run_state_vector(
    initial_state,
    evolution_time,
    num_eigenstates=1,
    **kwargs
)

Run TE-QSCI with direct state vector calculation.

Parameters:

Name Type Description Default

initial_state

QuantumState

Initial quantum state

required

evolution_time

float

Time for evolution

required

num_eigenstates

int

Number of eigenstates to compute

1

Returns:

Type Description
QSCIResult

QSCIResult with state vector TE-QSCI results

Source code in src/qsci_algorithms.py
def run_state_vector(
    self,
    initial_state: QuantumState,
    evolution_time: float,
    num_eigenstates: int = 1,
    **kwargs
) -> QSCIResult:
    """Run TE-QSCI with direct state vector calculation.

    Args:
        initial_state: Initial quantum state
        evolution_time: Time for evolution
        num_eigenstates: Number of eigenstates to compute

    Returns:
        QSCIResult with state vector TE-QSCI results
    """
    start_time = kwargs.get("start_time")

    # Create time-evolved state using exact simulation
    time_evolved_state = self._create_time_evolved_state(
        initial_state, evolution_time, kwargs.get("trotter_steps")
    )

    # Calculate exact computational basis probabilities
    probabilities = self._calculate_computational_basis_probabilities(time_evolved_state)

    # For state vector method, select the most probable states for QSCI subspace
    sorted_probs = sorted(probabilities.items(), key=lambda x: x[1], reverse=True)
    num_states_to_select = self.num_states_pick_out or min(100, len(sorted_probs))

    # Create computational basis states from most probable outcomes
    qubit_count = initial_state.qubit_count
    selected_states = []
    for bits_int, prob in sorted_probs[:num_states_to_select]:
        state = ComputationalBasisState(qubit_count, bits=bits_int)
        selected_states.append(state)

    # Generate and diagonalize truncated Hamiltonian
    truncated_hamiltonian = self._generate_truncated_hamiltonian(selected_states)
    eigvals, eigvecs = self._diagonalize_truncated_hamiltonian(
        truncated_hamiltonian, num_eigenstates
    )

    # Construct eigenstates
    eigenstates = [(eigvecs[i], selected_states) for i in range(num_eigenstates)]

    execution_time = None
    if start_time:
        import time
        execution_time = time.time() - start_time

    return QSCIResult(
        eigenvalues=eigvals,
        eigenstates=eigenstates,
        selected_states=selected_states,
        subspace_dimension=len(selected_states),
        total_shots=0,  # No sampling in state vector method
        algorithm_variant=QSCIVariant.STATE_VECTOR,
        execution_time=execution_time,
        computational_basis_probabilities=probabilities
    )

TimeAverageTE_QSCI

TimeAverageTE_QSCI(
    hamiltonian,
    sampler,
    evolution_times,
    num_states_pick_out=None,
)

Bases: TimeEvolvedQSCI

Time-average TE-QSCI wrapper for testing compatibility.

Methods:

Name Description
run
run_single_time

Run single-time TE-QSCI algorithm.

run_time_average

Run time-average TE-QSCI algorithm.

run_state_vector

Run TE-QSCI with direct state vector calculation.

Attributes:

Name Type Description
evolution_times
hamiltonian
sampler
num_states_pick_out
time_evolution_method
Source code in src/qsci_algorithms.py
def __init__(self, hamiltonian, sampler, evolution_times, num_states_pick_out=None):
    super().__init__(hamiltonian, sampler, num_states_pick_out)
    self.evolution_times = evolution_times

evolution_times instance-attribute

evolution_times = evolution_times

hamiltonian instance-attribute

hamiltonian = hamiltonian

sampler instance-attribute

sampler = sampler

num_states_pick_out instance-attribute

num_states_pick_out = num_states_pick_out

time_evolution_method instance-attribute

time_evolution_method = time_evolution_method

run

run(input_states, total_shots, **kwargs)
Source code in src/qsci_algorithms.py
def run(self, input_states, total_shots, **kwargs):
    if len(input_states) != 1:
        raise ValueError("TimeAverageTE_QSCI expects exactly one initial state")
    shots_per_time = total_shots // len(self.evolution_times)
    return self.run_time_average(
        input_states[0], self.evolution_times, shots_per_time, **kwargs
    )

run_single_time

run_single_time(
    initial_state,
    evolution_time,
    total_shots,
    trotter_steps=None,
    **kwargs
)

Run single-time TE-QSCI algorithm.

Parameters:

Name Type Description Default

initial_state

CircuitQuantumState

Initial quantum state

required

evolution_time

float

Time for evolution

required

total_shots

int

Number of measurement shots

required

trotter_steps

Optional[int]

Number of Trotter steps (if using Trotter method)

None

Returns:

Type Description
QSCIResult

QSCIResult with TE-QSCI results

Source code in src/qsci_algorithms.py
def run_single_time(
    self,
    initial_state: CircuitQuantumState,
    evolution_time: float,
    total_shots: int,
    trotter_steps: Optional[int] = None,
    **kwargs
) -> QSCIResult:
    """Run single-time TE-QSCI algorithm.

    Args:
        initial_state: Initial quantum state
        evolution_time: Time for evolution
        total_shots: Number of measurement shots
        trotter_steps: Number of Trotter steps (if using Trotter method)

    Returns:
        QSCIResult with TE-QSCI results
    """
    if not self.sampler:
        raise ValueError("Sampler is required for single-time TE-QSCI")

    start_time = kwargs.get("start_time")

    # Create time-evolved state
    time_evolved_state = self._create_time_evolved_state(
        initial_state, evolution_time, trotter_steps
    )

    # Calculate computational basis probabilities for Figure 1
    probabilities = self._calculate_computational_basis_probabilities(time_evolved_state)

    # Run QSCI on time-evolved state
    result = self._run_qsci_on_states(
        [time_evolved_state], 
        total_shots, 
        QSCIVariant.SINGLE_TIME_TE,
        start_time
    )

    # Add probability information to result
    result.computational_basis_probabilities = probabilities

    return result

run_time_average

run_time_average(
    initial_state,
    evolution_times,
    shots_per_time,
    trotter_steps=None,
    **kwargs
)

Run time-average TE-QSCI algorithm.

Parameters:

Name Type Description Default

initial_state

CircuitQuantumState

Initial quantum state

required

evolution_times

Sequence[float]

Times for evolution

required

shots_per_time

int

Number of shots per time point

required

trotter_steps

Optional[int]

Number of Trotter steps

None

Returns:

Type Description
QSCIResult

QSCIResult with time-average TE-QSCI results

Source code in src/qsci_algorithms.py
def run_time_average(
    self,
    initial_state: CircuitQuantumState,
    evolution_times: Sequence[float],
    shots_per_time: int,
    trotter_steps: Optional[int] = None,
    **kwargs
) -> QSCIResult:
    """Run time-average TE-QSCI algorithm.

    Args:
        initial_state: Initial quantum state
        evolution_times: Times for evolution
        shots_per_time: Number of shots per time point
        trotter_steps: Number of Trotter steps

    Returns:
        QSCIResult with time-average TE-QSCI results
    """
    if not self.sampler:
        raise ValueError("Sampler is required for time-average TE-QSCI")

    start_time = kwargs.get("start_time")

    # Create time-evolved states
    time_evolved_states = []
    for t in evolution_times:
        evolved_state = self._create_time_evolved_state(
            initial_state, t, trotter_steps
        )
        time_evolved_states.append(evolved_state)

    # Sample from all time-evolved states
    qubit_count = initial_state.qubit_count
    circuits = [state.circuit for state in time_evolved_states]
    meas_counts_list = self.sampler(
        [(circuit, shots_per_time) for circuit in circuits]
    )

    # Merge all measurement counts
    merged_meas_counts: Dict[int, Union[int, float]] = {}
    for meas_counts in meas_counts_list:
        for bits, counts in meas_counts.items():
            merged_meas_counts[bits] = merged_meas_counts.get(bits, 0) + counts

    # Select states and diagonalize
    selected_states = self._pick_out_states(
        qubit_count, merged_meas_counts, self.num_states_pick_out
    )

    truncated_hamiltonian = self._generate_truncated_hamiltonian(selected_states)
    eigvals, eigvecs = self._diagonalize_truncated_hamiltonian(
        truncated_hamiltonian, 1  # Typically only ground state for time-average
    )

    eigenstates = [(eigvecs[i], selected_states) for i in range(len(eigvals))]

    execution_time = None
    if start_time:
        import time
        execution_time = time.time() - start_time

    return QSCIResult(
        eigenvalues=eigvals,
        eigenstates=eigenstates,
        selected_states=selected_states,
        subspace_dimension=len(selected_states),
        total_shots=len(evolution_times) * shots_per_time,
        algorithm_variant=QSCIVariant.TIME_AVERAGE_TE,
        execution_time=execution_time
    )

run_state_vector

run_state_vector(
    initial_state,
    evolution_time,
    num_eigenstates=1,
    **kwargs
)

Run TE-QSCI with direct state vector calculation.

Parameters:

Name Type Description Default

initial_state

QuantumState

Initial quantum state

required

evolution_time

float

Time for evolution

required

num_eigenstates

int

Number of eigenstates to compute

1

Returns:

Type Description
QSCIResult

QSCIResult with state vector TE-QSCI results

Source code in src/qsci_algorithms.py
def run_state_vector(
    self,
    initial_state: QuantumState,
    evolution_time: float,
    num_eigenstates: int = 1,
    **kwargs
) -> QSCIResult:
    """Run TE-QSCI with direct state vector calculation.

    Args:
        initial_state: Initial quantum state
        evolution_time: Time for evolution
        num_eigenstates: Number of eigenstates to compute

    Returns:
        QSCIResult with state vector TE-QSCI results
    """
    start_time = kwargs.get("start_time")

    # Create time-evolved state using exact simulation
    time_evolved_state = self._create_time_evolved_state(
        initial_state, evolution_time, kwargs.get("trotter_steps")
    )

    # Calculate exact computational basis probabilities
    probabilities = self._calculate_computational_basis_probabilities(time_evolved_state)

    # For state vector method, select the most probable states for QSCI subspace
    sorted_probs = sorted(probabilities.items(), key=lambda x: x[1], reverse=True)
    num_states_to_select = self.num_states_pick_out or min(100, len(sorted_probs))

    # Create computational basis states from most probable outcomes
    qubit_count = initial_state.qubit_count
    selected_states = []
    for bits_int, prob in sorted_probs[:num_states_to_select]:
        state = ComputationalBasisState(qubit_count, bits=bits_int)
        selected_states.append(state)

    # Generate and diagonalize truncated Hamiltonian
    truncated_hamiltonian = self._generate_truncated_hamiltonian(selected_states)
    eigvals, eigvecs = self._diagonalize_truncated_hamiltonian(
        truncated_hamiltonian, num_eigenstates
    )

    # Construct eigenstates
    eigenstates = [(eigvecs[i], selected_states) for i in range(num_eigenstates)]

    execution_time = None
    if start_time:
        import time
        execution_time = time.time() - start_time

    return QSCIResult(
        eigenvalues=eigvals,
        eigenstates=eigenstates,
        selected_states=selected_states,
        subspace_dimension=len(selected_states),
        total_shots=0,  # No sampling in state vector method
        algorithm_variant=QSCIVariant.STATE_VECTOR,
        execution_time=execution_time,
        computational_basis_probabilities=probabilities
    )

FfsimStateVectorQSCI

FfsimStateVectorQSCI(hamiltonian, num_states_pick_out=None)

Bases: QSCIBase

QSCI algorithm for direct ffsim state vector input.

This class provides direct integration with ffsim's LUCJ/UCJ ansatz state vectors, bypassing circuit sampling and using exact computational basis probabilities for more accurate QSCI analysis.

Parameters:

Name Type Description Default

hamiltonian

Operator

Target Hamiltonian to diagonalize (quri-parts Operator)

required

num_states_pick_out

Optional[int]

Number of states to select for subspace

None

Methods:

Name Description
run

Run QSCI algorithm - maintained for interface compatibility.

run_ffsim_state_vector

Run QSCI with direct ffsim state vector input.

Attributes:

Name Type Description
hamiltonian
sampler
num_states_pick_out
Source code in src/qsci_algorithms.py
def __init__(
    self,
    hamiltonian: Operator,
    num_states_pick_out: Optional[int] = None
):
    """Initialize FfsimStateVectorQSCI.

    Args:
        hamiltonian: Target Hamiltonian to diagonalize (quri-parts Operator)
        num_states_pick_out: Number of states to select for subspace
    """
    # No sampler needed for state vector method
    super().__init__(hamiltonian, sampler=None, num_states_pick_out=num_states_pick_out)

hamiltonian instance-attribute

hamiltonian = hamiltonian

sampler instance-attribute

sampler = sampler

num_states_pick_out instance-attribute

num_states_pick_out = num_states_pick_out

run

run(input_states, total_shots, **kwargs)

Run QSCI algorithm - maintained for interface compatibility.

Note: This method maintains the standard QSCI interface but is not the primary entry point for ffsim integration. Use run_ffsim_state_vector() instead.

Source code in src/qsci_algorithms.py
def run(
    self,
    input_states: Sequence[CircuitQuantumState],
    total_shots: int,
    **kwargs
) -> QSCIResult:
    """Run QSCI algorithm - maintained for interface compatibility.

    Note: This method maintains the standard QSCI interface but is not the primary
    entry point for ffsim integration. Use run_ffsim_state_vector() instead.
    """
    raise NotImplementedError(
        "FfsimStateVectorQSCI is designed for direct state vector input. "
        "Use run_ffsim_state_vector() method instead."
    )

run_ffsim_state_vector

run_ffsim_state_vector(
    ffsim_state_vector,
    n_qubits,
    num_eigenstates=1,
    nelec=None,
    **kwargs
)

Run QSCI with direct ffsim state vector input.

Parameters:

Name Type Description Default

ffsim_state_vector

ndarray

State vector from ffsim LUCJ/UCJ ansatz (numpy array)

required

n_qubits

int

Number of qubits in the system (typically 2 * norb)

required

num_eigenstates

int

Number of eigenstates to compute

1

**kwargs

Additional parameters

{}

Returns:

Type Description
QSCIResult

QSCIResult with exact QSCI analysis results

Source code in src/qsci_algorithms.py
def run_ffsim_state_vector(
    self,
    ffsim_state_vector: np.ndarray,
    n_qubits: int,
    num_eigenstates: int = 1,
    nelec: tuple[int, int] = None,
    **kwargs
) -> QSCIResult:
    """Run QSCI with direct ffsim state vector input.

    Args:
        ffsim_state_vector: State vector from ffsim LUCJ/UCJ ansatz (numpy array)
        n_qubits: Number of qubits in the system (typically 2 * norb)
        num_eigenstates: Number of eigenstates to compute
        **kwargs: Additional parameters

    Returns:
        QSCIResult with exact QSCI analysis results
    """
    import time
    start_time = kwargs.get("start_time", time.time())

    print(f"Running FfsimStateVectorQSCI...")
    print(f"  Input state vector dimension: {len(ffsim_state_vector)}")
    print(f"  Target qubit space dimension: 2^{n_qubits} = {2**n_qubits}")

    # Convert ffsim state vector to computational basis probabilities
    probabilities = self._ffsim_to_computational_probabilities(
        ffsim_state_vector, n_qubits, nelec
    )

    print(f"  Extracted {len(probabilities)} non-zero computational basis states")

    # Select the most probable states for QSCI subspace
    sorted_probs = sorted(probabilities.items(), key=lambda x: x[1], reverse=True)
    num_states_to_select = self.num_states_pick_out or min(100, len(sorted_probs))

    print(f"  Selecting top {num_states_to_select} states for QSCI subspace")

    # Create computational basis states from most probable outcomes  
    selected_states = []
    for bits_int, prob in sorted_probs[:num_states_to_select]:
        state = ComputationalBasisState(n_qubits, bits=bits_int)
        selected_states.append(state)

    # Show selected states for debugging
    print(f"  Top selected states:")
    for i, (bits_int, prob) in enumerate(sorted_probs[:min(5, num_states_to_select)]):
        bits_str = format(bits_int, f'0{n_qubits}b')
        print(f"    {i+1}: |{bits_str}⟩ = {bits_int}, prob = {prob:.6f}")

    # Generate and diagonalize truncated Hamiltonian
    print(f"  Generating truncated Hamiltonian in {len(selected_states)}-dimensional subspace...")
    truncated_hamiltonian = self._generate_truncated_hamiltonian(selected_states)

    print(f"  Diagonalizing for {num_eigenstates} eigenstate(s)...")
    eigvals, eigvecs = self._diagonalize_truncated_hamiltonian(
        truncated_hamiltonian, num_eigenstates
    )

    # Construct eigenstates
    eigenstates = [(eigvecs[i], selected_states) for i in range(num_eigenstates)]

    execution_time = time.time() - start_time

    print(f"  QSCI ground state energy: {eigvals[0]:.6f} Ha")
    print(f"  Execution time: {execution_time:.3f} seconds")

    return QSCIResult(
        eigenvalues=eigvals,
        eigenstates=eigenstates,
        selected_states=selected_states,
        subspace_dimension=len(selected_states),
        total_shots=0,  # No sampling in state vector method
        algorithm_variant=QSCIVariant.STATE_VECTOR,
        execution_time=execution_time,
        computational_basis_probabilities=probabilities
    )

StateVectorTE_QSCI

StateVectorTE_QSCI(
    hamiltonian,
    sampler,
    evolution_time,
    num_states_pick_out=None,
)

Bases: TimeEvolvedQSCI

State vector TE-QSCI wrapper for testing compatibility.

Methods:

Name Description
run
run_single_time

Run single-time TE-QSCI algorithm.

run_time_average

Run time-average TE-QSCI algorithm.

run_state_vector

Run TE-QSCI with direct state vector calculation.

Attributes:

Name Type Description
evolution_time
hamiltonian
sampler
num_states_pick_out
time_evolution_method
Source code in src/qsci_algorithms.py
def __init__(self, hamiltonian, sampler, evolution_time, num_states_pick_out=None):
    super().__init__(hamiltonian, sampler, num_states_pick_out)
    self.evolution_time = evolution_time

evolution_time instance-attribute

evolution_time = evolution_time

hamiltonian instance-attribute

hamiltonian = hamiltonian

sampler instance-attribute

sampler = sampler

num_states_pick_out instance-attribute

num_states_pick_out = num_states_pick_out

time_evolution_method instance-attribute

time_evolution_method = time_evolution_method

run

run(input_states, total_shots, **kwargs)
Source code in src/qsci_algorithms.py
def run(self, input_states, total_shots, **kwargs):
    if len(input_states) != 1:
        raise ValueError("StateVectorTE_QSCI expects exactly one initial state")

    initial_state = input_states[0]

    # Validate that the state has the required circuit attribute
    if not hasattr(initial_state, 'circuit'):
        raise TypeError(
            f"StateVectorTE_QSCI requires a GeneralCircuitQuantumState with a 'circuit' attribute, "
            f"but received {type(initial_state)}. Please ensure you're using "
            f"create_circuit_state_from_amplitudes() instead of create_custom_state_vector()."
        )

    # For state vector method, we don't need shots but keeping interface consistent
    return self.run_state_vector(
        initial_state, self.evolution_time, **kwargs
    )

run_single_time

run_single_time(
    initial_state,
    evolution_time,
    total_shots,
    trotter_steps=None,
    **kwargs
)

Run single-time TE-QSCI algorithm.

Parameters:

Name Type Description Default

initial_state

CircuitQuantumState

Initial quantum state

required

evolution_time

float

Time for evolution

required

total_shots

int

Number of measurement shots

required

trotter_steps

Optional[int]

Number of Trotter steps (if using Trotter method)

None

Returns:

Type Description
QSCIResult

QSCIResult with TE-QSCI results

Source code in src/qsci_algorithms.py
def run_single_time(
    self,
    initial_state: CircuitQuantumState,
    evolution_time: float,
    total_shots: int,
    trotter_steps: Optional[int] = None,
    **kwargs
) -> QSCIResult:
    """Run single-time TE-QSCI algorithm.

    Args:
        initial_state: Initial quantum state
        evolution_time: Time for evolution
        total_shots: Number of measurement shots
        trotter_steps: Number of Trotter steps (if using Trotter method)

    Returns:
        QSCIResult with TE-QSCI results
    """
    if not self.sampler:
        raise ValueError("Sampler is required for single-time TE-QSCI")

    start_time = kwargs.get("start_time")

    # Create time-evolved state
    time_evolved_state = self._create_time_evolved_state(
        initial_state, evolution_time, trotter_steps
    )

    # Calculate computational basis probabilities for Figure 1
    probabilities = self._calculate_computational_basis_probabilities(time_evolved_state)

    # Run QSCI on time-evolved state
    result = self._run_qsci_on_states(
        [time_evolved_state], 
        total_shots, 
        QSCIVariant.SINGLE_TIME_TE,
        start_time
    )

    # Add probability information to result
    result.computational_basis_probabilities = probabilities

    return result

run_time_average

run_time_average(
    initial_state,
    evolution_times,
    shots_per_time,
    trotter_steps=None,
    **kwargs
)

Run time-average TE-QSCI algorithm.

Parameters:

Name Type Description Default

initial_state

CircuitQuantumState

Initial quantum state

required

evolution_times

Sequence[float]

Times for evolution

required

shots_per_time

int

Number of shots per time point

required

trotter_steps

Optional[int]

Number of Trotter steps

None

Returns:

Type Description
QSCIResult

QSCIResult with time-average TE-QSCI results

Source code in src/qsci_algorithms.py
def run_time_average(
    self,
    initial_state: CircuitQuantumState,
    evolution_times: Sequence[float],
    shots_per_time: int,
    trotter_steps: Optional[int] = None,
    **kwargs
) -> QSCIResult:
    """Run time-average TE-QSCI algorithm.

    Args:
        initial_state: Initial quantum state
        evolution_times: Times for evolution
        shots_per_time: Number of shots per time point
        trotter_steps: Number of Trotter steps

    Returns:
        QSCIResult with time-average TE-QSCI results
    """
    if not self.sampler:
        raise ValueError("Sampler is required for time-average TE-QSCI")

    start_time = kwargs.get("start_time")

    # Create time-evolved states
    time_evolved_states = []
    for t in evolution_times:
        evolved_state = self._create_time_evolved_state(
            initial_state, t, trotter_steps
        )
        time_evolved_states.append(evolved_state)

    # Sample from all time-evolved states
    qubit_count = initial_state.qubit_count
    circuits = [state.circuit for state in time_evolved_states]
    meas_counts_list = self.sampler(
        [(circuit, shots_per_time) for circuit in circuits]
    )

    # Merge all measurement counts
    merged_meas_counts: Dict[int, Union[int, float]] = {}
    for meas_counts in meas_counts_list:
        for bits, counts in meas_counts.items():
            merged_meas_counts[bits] = merged_meas_counts.get(bits, 0) + counts

    # Select states and diagonalize
    selected_states = self._pick_out_states(
        qubit_count, merged_meas_counts, self.num_states_pick_out
    )

    truncated_hamiltonian = self._generate_truncated_hamiltonian(selected_states)
    eigvals, eigvecs = self._diagonalize_truncated_hamiltonian(
        truncated_hamiltonian, 1  # Typically only ground state for time-average
    )

    eigenstates = [(eigvecs[i], selected_states) for i in range(len(eigvals))]

    execution_time = None
    if start_time:
        import time
        execution_time = time.time() - start_time

    return QSCIResult(
        eigenvalues=eigvals,
        eigenstates=eigenstates,
        selected_states=selected_states,
        subspace_dimension=len(selected_states),
        total_shots=len(evolution_times) * shots_per_time,
        algorithm_variant=QSCIVariant.TIME_AVERAGE_TE,
        execution_time=execution_time
    )

run_state_vector

run_state_vector(
    initial_state,
    evolution_time,
    num_eigenstates=1,
    **kwargs
)

Run TE-QSCI with direct state vector calculation.

Parameters:

Name Type Description Default

initial_state

QuantumState

Initial quantum state

required

evolution_time

float

Time for evolution

required

num_eigenstates

int

Number of eigenstates to compute

1

Returns:

Type Description
QSCIResult

QSCIResult with state vector TE-QSCI results

Source code in src/qsci_algorithms.py
def run_state_vector(
    self,
    initial_state: QuantumState,
    evolution_time: float,
    num_eigenstates: int = 1,
    **kwargs
) -> QSCIResult:
    """Run TE-QSCI with direct state vector calculation.

    Args:
        initial_state: Initial quantum state
        evolution_time: Time for evolution
        num_eigenstates: Number of eigenstates to compute

    Returns:
        QSCIResult with state vector TE-QSCI results
    """
    start_time = kwargs.get("start_time")

    # Create time-evolved state using exact simulation
    time_evolved_state = self._create_time_evolved_state(
        initial_state, evolution_time, kwargs.get("trotter_steps")
    )

    # Calculate exact computational basis probabilities
    probabilities = self._calculate_computational_basis_probabilities(time_evolved_state)

    # For state vector method, select the most probable states for QSCI subspace
    sorted_probs = sorted(probabilities.items(), key=lambda x: x[1], reverse=True)
    num_states_to_select = self.num_states_pick_out or min(100, len(sorted_probs))

    # Create computational basis states from most probable outcomes
    qubit_count = initial_state.qubit_count
    selected_states = []
    for bits_int, prob in sorted_probs[:num_states_to_select]:
        state = ComputationalBasisState(qubit_count, bits=bits_int)
        selected_states.append(state)

    # Generate and diagonalize truncated Hamiltonian
    truncated_hamiltonian = self._generate_truncated_hamiltonian(selected_states)
    eigvals, eigvecs = self._diagonalize_truncated_hamiltonian(
        truncated_hamiltonian, num_eigenstates
    )

    # Construct eigenstates
    eigenstates = [(eigvecs[i], selected_states) for i in range(num_eigenstates)]

    execution_time = None
    if start_time:
        import time
        execution_time = time.time() - start_time

    return QSCIResult(
        eigenvalues=eigvals,
        eigenstates=eigenstates,
        selected_states=selected_states,
        subspace_dimension=len(selected_states),
        total_shots=0,  # No sampling in state vector method
        algorithm_variant=QSCIVariant.STATE_VECTOR,
        execution_time=execution_time,
        computational_basis_probabilities=probabilities
    )