pub mod advanced_algorithms;
pub mod encoding;
pub mod generative_adversarial;
pub mod layers;
pub mod nlp;
pub mod reinforcement_learning;
pub mod training;
pub mod quantum_contrastive;
pub mod quantum_memory_networks;
pub mod quantum_meta_learning;
pub mod quantum_reservoir;
pub mod quantum_transformer;
pub mod quantum_boltzmann;
pub mod quantum_federated;
pub use advanced_algorithms::{
FeatureMapType, QMLMetrics, QuantumEnsemble, QuantumKernel, QuantumKernelConfig, QuantumSVM,
QuantumTransferLearning, TransferLearningConfig, VotingStrategy,
};
pub use quantum_contrastive::{
QuantumAugmentation, QuantumContrastiveConfig, QuantumContrastiveLearner,
};
pub use quantum_memory_networks::{MemoryInitStrategy, QuantumMemoryConfig, QuantumMemoryNetwork};
pub use quantum_meta_learning::{
QuantumMAML, QuantumMetaLearningConfig, QuantumReptile, QuantumTask,
};
pub use quantum_reservoir::{QuantumReservoirComputer, QuantumReservoirConfig};
pub use quantum_transformer::{QuantumAttention, QuantumTransformer, QuantumTransformerConfig};
pub use quantum_boltzmann::{DeepQuantumBoltzmannMachine, QRBMConfig, QuantumRBM};
pub use quantum_federated::{AggregationStrategy, QuantumFederatedConfig, QuantumFederatedServer};
use crate::{
error::{QuantRS2Error, QuantRS2Result},
gate::GateOp,
qubit::QubitId,
};
use scirs2_core::ndarray::{Array1, Array2};
use scirs2_core::Complex64;
pub use layers::Parameter;
pub trait QMLLayer: Send + Sync {
fn num_qubits(&self) -> usize;
fn parameters(&self) -> &[Parameter];
fn parameters_mut(&mut self) -> &mut [Parameter];
fn set_parameters(&mut self, values: &[f64]) -> QuantRS2Result<()> {
if values.len() != self.parameters().len() {
return Err(QuantRS2Error::InvalidInput(format!(
"Expected {} parameters, got {}",
self.parameters().len(),
values.len()
)));
}
for (param, &value) in self.parameters_mut().iter_mut().zip(values.iter()) {
param.value = value;
}
Ok(())
}
fn gates(&self) -> Vec<Box<dyn GateOp>>;
fn compute_gradients(
&self,
state: &Array1<Complex64>,
loss_gradient: &Array1<Complex64>,
) -> QuantRS2Result<Vec<f64>>;
fn name(&self) -> &str;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EncodingStrategy {
Amplitude,
Angle,
IQP,
Basis,
}
#[derive(Debug, Clone)]
pub struct QMLConfig {
pub num_qubits: usize,
pub num_layers: usize,
pub encoding: EncodingStrategy,
pub entanglement: EntanglementPattern,
pub data_reuploading: bool,
}
impl Default for QMLConfig {
fn default() -> Self {
Self {
num_qubits: 4,
num_layers: 2,
encoding: EncodingStrategy::Angle,
entanglement: EntanglementPattern::Full,
data_reuploading: false,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EntanglementPattern {
None,
Linear,
Circular,
Full,
Alternating,
}
pub struct QMLCircuit {
config: QMLConfig,
layers: Vec<Box<dyn QMLLayer>>,
num_parameters: usize,
}
impl QMLCircuit {
pub fn new(config: QMLConfig) -> Self {
Self {
config,
layers: Vec::new(),
num_parameters: 0,
}
}
pub fn add_layer(&mut self, layer: Box<dyn QMLLayer>) -> QuantRS2Result<()> {
if layer.num_qubits() != self.config.num_qubits {
return Err(QuantRS2Error::InvalidInput(format!(
"Layer has {} qubits, circuit has {}",
layer.num_qubits(),
self.config.num_qubits
)));
}
self.num_parameters += layer.parameters().len();
self.layers.push(layer);
Ok(())
}
pub fn parameters(&self) -> Vec<&Parameter> {
self.layers
.iter()
.flat_map(|layer| layer.parameters().iter())
.collect()
}
pub fn set_parameters(&mut self, values: &[f64]) -> QuantRS2Result<()> {
if values.len() != self.num_parameters {
return Err(QuantRS2Error::InvalidInput(format!(
"Expected {} parameters, got {}",
self.num_parameters,
values.len()
)));
}
let mut offset = 0;
for layer in &mut self.layers {
let layer_params = layer.parameters().len();
layer.set_parameters(&values[offset..offset + layer_params])?;
offset += layer_params;
}
Ok(())
}
pub fn gates(&self) -> Vec<Box<dyn GateOp>> {
self.layers.iter().flat_map(|layer| layer.gates()).collect()
}
pub fn compute_gradients(
&self,
state: &Array1<Complex64>,
loss_gradient: &Array1<Complex64>,
) -> QuantRS2Result<Vec<f64>> {
let mut all_gradients = Vec::new();
for layer in &self.layers {
let layer_grads = layer.compute_gradients(state, loss_gradient)?;
all_gradients.extend(layer_grads);
}
Ok(all_gradients)
}
}
pub fn create_entangling_gates(
num_qubits: usize,
pattern: EntanglementPattern,
) -> Vec<(QubitId, QubitId)> {
match pattern {
EntanglementPattern::None => vec![],
EntanglementPattern::Linear => (0..num_qubits - 1)
.map(|i| (QubitId(i as u32), QubitId((i + 1) as u32)))
.collect(),
EntanglementPattern::Circular => {
let mut gates = vec![];
for i in 0..num_qubits {
gates.push((QubitId(i as u32), QubitId(((i + 1) % num_qubits) as u32)));
}
gates
}
EntanglementPattern::Full => {
let mut gates = vec![];
for i in 0..num_qubits {
for j in i + 1..num_qubits {
gates.push((QubitId(i as u32), QubitId(j as u32)));
}
}
gates
}
EntanglementPattern::Alternating => {
let mut gates = vec![];
for i in (0..num_qubits - 1).step_by(2) {
gates.push((QubitId(i as u32), QubitId((i + 1) as u32)));
}
for i in (1..num_qubits - 1).step_by(2) {
gates.push((QubitId(i as u32), QubitId((i + 1) as u32)));
}
gates
}
}
}
pub fn quantum_fisher_information(
circuit: &QMLCircuit,
_state: &Array1<Complex64>,
) -> QuantRS2Result<Array2<f64>> {
let num_params = circuit.num_parameters;
let fisher = Array2::zeros((num_params, num_params));
Ok(fisher)
}
pub fn natural_gradient(
gradients: &[f64],
fisher: &Array2<f64>,
regularization: f64,
) -> QuantRS2Result<Vec<f64>> {
let mut regularized_fisher = fisher.clone();
for i in 0..fisher.nrows() {
regularized_fisher[(i, i)] += regularization;
}
let _grad_array = Array1::from_vec(gradients.to_vec());
Ok(gradients.to_vec())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_entanglement_patterns() {
let linear = create_entangling_gates(4, EntanglementPattern::Linear);
assert_eq!(linear.len(), 3);
assert_eq!(linear[0], (QubitId(0), QubitId(1)));
let circular = create_entangling_gates(4, EntanglementPattern::Circular);
assert_eq!(circular.len(), 4);
assert_eq!(circular[3], (QubitId(3), QubitId(0)));
let full = create_entangling_gates(3, EntanglementPattern::Full);
assert_eq!(full.len(), 3);
let none = create_entangling_gates(4, EntanglementPattern::None);
assert_eq!(none.len(), 0);
}
#[test]
fn test_qml_circuit() {
let config = QMLConfig {
num_qubits: 2,
num_layers: 1,
..Default::default()
};
let circuit = QMLCircuit::new(config);
assert_eq!(circuit.num_parameters, 0);
}
}