use crate::error::{MLError, Result};
use scirs2_core::ndarray::{Array1, Array2};
use scirs2_core::Complex64;
use super::*;
pub fn amplitude_encode(data: &Array1<f64>) -> Result<Array1<Complex64>> {
let norm: f64 = data.iter().map(|x| x * x).sum::<f64>().sqrt();
if norm < 1e-10 {
return Err(MLError::ComputationError(
"Cannot amplitude encode zero vector".to_string(),
));
}
let encoded = data.mapv(|x| Complex64::new(x / norm, 0.0));
Ok(encoded)
}
pub fn angle_encode(data: &Array1<f64>, scale: f64) -> Result<Array1<f64>> {
let pi = std::f64::consts::PI;
let encoded = data.mapv(|x| (x * scale).rem_euclid(2.0 * pi));
Ok(encoded)
}
pub fn basis_encode(data: &Array1<usize>, num_qubits: usize) -> Result<Array2<u8>> {
let max_val = 1 << num_qubits;
for &val in data.iter() {
if val >= max_val {
return Err(MLError::InvalidInput(format!(
"Value {} exceeds maximum {} for {} qubits",
val,
max_val - 1,
num_qubits
)));
}
}
let mut encoded = Array2::zeros((data.len(), num_qubits));
for (i, &val) in data.iter().enumerate() {
for j in 0..num_qubits {
encoded[(i, num_qubits - 1 - j)] = ((val >> j) & 1) as u8;
}
}
Ok(encoded)
}
pub fn product_encode(data: &Array1<f64>) -> Result<Array1<f64>> {
let pi = std::f64::consts::PI;
let min_val = data.iter().cloned().fold(f64::INFINITY, f64::min);
let max_val = data.iter().cloned().fold(f64::NEG_INFINITY, f64::max);
let range = max_val - min_val;
if range < 1e-10 {
return Ok(Array1::from_elem(data.len(), pi / 2.0));
}
let encoded = data.mapv(|x| ((x - min_val) / range) * pi);
Ok(encoded)
}
pub fn dense_angle_encode(data: &Array1<f64>) -> Result<Array1<f64>> {
let pi = std::f64::consts::PI;
let encoded = data.mapv(|x| {
let normalized = (x.atan() / (pi / 2.0) + 1.0) * pi;
normalized
});
Ok(encoded)
}
pub fn iqp_encode(data: &Array1<f64>, degree: usize) -> Result<Array1<f64>> {
let n = data.len();
let mut encoded = Vec::new();
for &x in data.iter() {
encoded.push(x);
}
if degree >= 2 {
for i in 0..n {
for j in i..n {
encoded.push(data[i] * data[j]);
}
}
}
if degree >= 3 {
for i in 0..n {
for j in i..n {
for k in j..n {
encoded.push(data[i] * data[j] * data[k]);
}
}
}
}
Ok(Array1::from_vec(encoded))
}
pub fn pauli_feature_map_encode(data: &Array1<f64>, reps: usize) -> Result<Array1<f64>> {
let pi = std::f64::consts::PI;
let n = data.len();
let mut encoded = Vec::new();
for _ in 0..reps {
for &x in data.iter() {
encoded.push(2.0 * x);
}
for i in 0..n {
for j in (i + 1)..n {
let angle = (pi - data[i]) * (pi - data[j]);
encoded.push(2.0 * angle);
}
}
}
Ok(Array1::from_vec(encoded))
}