#[macro_use] extern crate lazy_static; use rand::Rng; use parmesan::userovo::encryption; use parmesan::*; #[allow(dead_code)] mod common; use common::*; // ----------------------------------------------------------------------------- // Test Cases #[test] /// NN Evaluation over encrypted sub-samples only. fn t_nn_eval_non_triv() { println!("Non-Triv ..."); t_impl_nn_eval_with_mode(EncrVsTriv::ENCR); } #[test] /// NN Evaluation over trivial sub-samples only. fn t_nn_eval_all_triv() { println!("All-Triv ..."); t_impl_nn_eval_with_mode(EncrVsTriv::TRIV); } #[test] /// NN Evaluation over mixed sub-samples. fn t_nn_eval_some_triv() { println!("Mixed ..."); t_impl_nn_eval_with_mode(EncrVsTriv::ENCRTRIV); } // ----------------------------------------------------------------------------- // Test Implementations /// Implementation for three variants of vector to be evaluated. fn t_impl_nn_eval_with_mode(mode: EncrVsTriv) { for _ in 0..common::TESTS_REPEAT_NNE { // generate random NN let nn = t_gen_nn(); // generate random inputs let mut m_in_vec = vec![]; let mut m_in = vec![]; let mut c_in = vec![]; for i in 0..nn.n_inputs { // generate random input let m_vec = gen_rand_vec(common::TESTS_BITLEN_NNE); // convert to integer let m = encryption::convert_from_vec(&m_vec).expect("convert failed."); println!(" m[{}] = {} ({}-bit: {:?})", i, m, common::TESTS_BITLEN_NNE, m_vec); // encrypt let c = encrypt_with_mode(&m_vec, mode); // push to input vectors m_in_vec.push(m_vec); m_in.push(m); c_in.push(c); } // homomorphic eval let c_he = nn.eval(&common::TEST_PC, &c_in); // decrypt let mut m_he = vec![]; for co in c_he { m_he.push(common::TEST_PU.decrypt(&co).expect("ParmesanUserovo::decrypt failed.")); } // plain eval let m_pl = nn.eval(&common::TEST_PC, &m_in); println!(" nn_eval = {:?}\n (exp. {:?})", m_he, m_pl); // compare results assert_eq!(m_he, m_pl); } } // ----------------------------------------------------------------------------- // Generate Random NN fn t_gen_nn() -> NeuralNetwork { let mut rng = rand::thread_rng(); // generate NN depth let depth = rng.gen_range(1..=common::TESTS_NNE_DEPTH); // prepare layers let mut layers = vec![]; // generate & save input length let mut in_len: usize = rng.gen_range(1..=common::TESTS_NNE_LAYER_SIZE); let n_inputs = in_len; for _ in 0..depth { // generate number of perceptrons let layer_len = rng.gen_range(1..common::TESTS_NNE_LAYER_SIZE); let mut layer = vec![]; for _ in 0..layer_len { // generate perceptron //~ let t: PercType = rng.gen(); // push to layer layer.push(Perceptron { t: rand::random(), w: gen_w(in_len), b: rng.gen_range(-common::TESTS_NNE_B_ABS_MAX..=common::TESTS_NNE_B_ABS_MAX), }); } layers.push(layer); // number of perceptrons is the number of inputs to the next layer in_len = layer_len; } NeuralNetwork {layers, n_inputs} } fn gen_w(wlen: usize) -> Vec { let mut rng = rand::thread_rng(); let mut w = vec![]; for _ in 0..wlen { w.push(rng.gen_range(-7..=7)) } w } // ############################################################################# //~ fn gen_perctype() -> PercType { //~ let mut rng = rand::thread_rng(); //~ let k = rng.gen_range(0..3); //~ if k == 0 { //~ println!("t : MAX, "); //~ return PercType::MAX; //~ } //~ if k == 1 { //~ println!("t : LIN, "); //~ return PercType::LIN; //~ } //~ println!("t: ACT, "); //~ return PercType::ACT; //~ }