Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jl projection #25

Draft
wants to merge 36 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
c974041
branch up to date with main
mattsuffern Feb 12, 2025
0c15b62
up to date with main
mattsuffern Feb 12, 2025
9c0fafc
up to date with main | fmt solved
mattsuffern Feb 12, 2025
db44611
up to date with main
mattsuffern Feb 12, 2025
52ff5a5
feat(zq): add modular arithmetic primitive using wrapping operations
pycckuu Feb 13, 2025
fbc2eb7
up to date with igor/feat/primitives
mattsuffern Feb 13, 2025
cb284a2
poly_ring is now based on Zq
mattsuffern Feb 13, 2025
ded244c
Clippy error fixed
mattsuffern Feb 13, 2025
f49e374
other clippy error fixed
mattsuffern Feb 13, 2025
7c3248b
struct renamed to Rq
mattsuffern Feb 14, 2025
426ea9f
macro for direct arithmetic and From/into function
mattsuffern Feb 17, 2025
f1fcf19
trait From implemented and polynomial multiplication fixed
mattsuffern Feb 17, 2025
9f82df5
fmt fixed
mattsuffern Feb 17, 2025
720a52e
division by monomial removed
mattsuffern Feb 17, 2025
adb0c70
Merge branch 'main' into poly_ring
mattsuffern Feb 17, 2025
d201aa4
merge solved
mattsuffern Feb 17, 2025
ad5ef13
new tests added
mattsuffern Feb 18, 2025
8bc411a
typo fixed
mattsuffern Feb 18, 2025
2499d1a
docs updated
mattsuffern Feb 18, 2025
19435e1
Implementation of Horner method and Matrix multiplication on stack
mattsuffern Feb 19, 2025
863343d
multiplication fixed
mattsuffern Feb 19, 2025
5d816b1
Clippy issue solved
mattsuffern Feb 19, 2025
555faa1
Neg trait implemented
mattsuffern Feb 19, 2025
78b85e1
Cloning instead of Copy operation
mattsuffern Feb 19, 2025
47bd1b2
random matrix for projection
mattsuffern Feb 20, 2025
a2a69e6
warnings solved
mattsuffern Feb 20, 2025
eb391dc
Random matrix and Projection
mattsuffern Feb 20, 2025
7ba6b9b
typo fixed
mattsuffern Feb 20, 2025
a8ac2b6
typo fixed 2
mattsuffern Feb 20, 2025
7379aa5
Random projection matrix and norms implemented
mattsuffern Feb 21, 2025
68343b0
fmt error fixed
mattsuffern Feb 21, 2025
8804369
Clippy error fixed
mattsuffern Feb 21, 2025
959baf8
norm fixed | error fixed | test fixed
mattsuffern Feb 24, 2025
10038f5
fmt fixed
mattsuffern Feb 24, 2025
058cbb8
norm test fixed
mattsuffern Feb 24, 2025
3a84533
tests removed
mattsuffern Feb 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
237 changes: 236 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions labrador/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ license.workspace = true

[dependencies]
base64 = "0.22.1"
rand = "0.9"
124 changes: 124 additions & 0 deletions labrador/src/jl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
use crate::rq::Rq;
use crate::zq::Zq;
use rand::prelude::*;
use rand::rng;

/// Projection matrix with values in {1,0,-1} mod q
pub struct ProjectionMatrix {
matrix: Vec<Vec<Zq>>,
}

impl ProjectionMatrix {
/// Defines a matrix of size 256xn
pub fn new(n: usize) -> Self {
let mut matrix = vec![vec![Zq::zero(); n]; 256];
let mut rng = rng();
// Fill the matrix with random values from {-1, 0, 1}
for row in matrix.iter_mut() {
for elem in row.iter_mut() {
let rand_val: f64 = rng.random();
*elem = if rand_val < 0.25 {
Zq::new(u32::MAX) // -1 in Zq
} else if rand_val < 0.75 {
Zq::zero()
} else {
Zq::one()
};
}
}
ProjectionMatrix { matrix }
}
/// Returns the matrix
pub fn get_matrix(&self) -> &Vec<Vec<Zq>> {
&self.matrix
}
}

/// Calculate projection vector
#[derive(Debug)]
pub struct ProjectionVector<const D: usize> {
projection: Vec<Zq>, // 256-dimensional projection vector
}

impl<const D: usize> ProjectionVector<D> {
// Function to concatenate coefficients from multiple Rq into a Vec<Zq>
fn concatenate_coefficients(rqs: Vec<Rq<D>>) -> Vec<Zq> {
let mut concatenated_coeffs: Vec<Zq> = Vec::new();

// Iterate over each Rq, extracting the coefficients and concatenating them
for rq in rqs {
let coeffs = rq.get_coefficients();
concatenated_coeffs.extend_from_slice(&coeffs);
}

concatenated_coeffs
}
// Euclidean norm
pub fn norm(&self) -> Zq {
self.projection.iter().map(|coeff| *coeff * *coeff).sum()
}

/// Calculates Projection
pub fn new(matrix: &ProjectionMatrix, s_i: &[Rq<D>]) -> Self {
let mut projection = vec![Zq::zero(); 256];
let coefficients = Self::concatenate_coefficients(s_i.to_vec());
for (i, item) in projection.iter_mut().enumerate().take(256) {
*item = matrix.get_matrix()[i]
.iter()
.zip(coefficients.iter())
.map(|(m, s)| *m * *s)
.sum::<Zq>();
}
ProjectionVector { projection }
}
/// Obtain projection
pub fn get_projection(&self) -> &Vec<Zq> {
&self.projection
}
}

/// Returns a vector of `n` random polynomials, each of degree `d`, for testing purposes.
pub fn generate_random_polynomials<R: Rng, const D: usize>(
n: usize,
rng: &mut R,
beta: Zq, // vector norm bound
) -> Vec<Rq<D>> {
let mut polynomials = Vec::with_capacity(n);

for _ in 0..n {
loop {
// Generate random coefficients
let coeffs: [Zq; D] = std::array::from_fn(|_| {
// Small values so we get a vector of 'small norm'
let small_value: u32 = rng.random_range(0..100);
Zq::new(small_value)
});

// Create the polynomial
let polynomial = Rq::new(coeffs);

// Compute the norm of all polynomials including the new one
let mut all_polynomials = polynomials.clone();
all_polynomials.push(polynomial.clone());
let norm = compute_norm(&all_polynomials);

// If the norm is smaller than beta, add the polynomial to the list
if norm.value() < beta.value() {
polynomials.push(polynomial);
break; // Exit the loop as the polynomial is valid
}
// If the norm is greater than or equal to beta, try again with a new random polynomial
}
}

polynomials
}

// Helper function to compute the norm of the polynomial
pub fn compute_norm<const D: usize>(polynomials: &[Rq<D>]) -> Zq {
polynomials
.iter()
.flat_map(|poly| poly.get_coefficients()) // Collect coefficients from all polynomials
.map(|coeff| coeff * coeff)
.sum()
}
Loading