mirror of
https://github.com/mii443/independent_randomized_projections.git
synced 2025-08-22 07:55:45 +00:00
first commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/target
|
333
Cargo.lock
generated
Normal file
333
Cargo.lock
generated
Normal file
@ -0,0 +1,333 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "approx"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.23.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"r-efi",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "independent_randomized_projections"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nalgebra",
|
||||
"rand",
|
||||
"rand_chacha",
|
||||
"rand_distr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.174"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
|
||||
|
||||
[[package]]
|
||||
name = "matrixmultiply"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"rawpointer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nalgebra"
|
||||
version = "0.33.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26aecdf64b707efd1310e3544d709c5c0ac61c13756046aaaba41be5c4f66a3b"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"matrixmultiply",
|
||||
"nalgebra-macros",
|
||||
"num-complex",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
"simba",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nalgebra-macros"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.46"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
version = "5.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
|
||||
dependencies = [
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_distr"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a8615d50dcf34fa31f7ab52692afec947c4dd0ab803cc87cb3b0b4570ff7463"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rawpointer"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
||||
|
||||
[[package]]
|
||||
name = "safe_arch"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simba"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3a386a501cd104797982c15ae17aafe8b9261315b5d07e3ec803f2ea26be0fa"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"num-complex",
|
||||
"num-traits",
|
||||
"paste",
|
||||
"wide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.14.2+wasi-0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
|
||||
dependencies = [
|
||||
"wit-bindgen-rt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wide"
|
||||
version = "0.7.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"safe_arch",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen-rt"
|
||||
version = "0.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
10
Cargo.toml
Normal file
10
Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "independent_randomized_projections"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
nalgebra = "0.33.2"
|
||||
rand = "0.9.1"
|
||||
rand_chacha = "0.9.0"
|
||||
rand_distr = "0.5.1"
|
44
src/client.rs
Normal file
44
src/client.rs
Normal file
@ -0,0 +1,44 @@
|
||||
use nalgebra::SMatrix;
|
||||
|
||||
use crate::{
|
||||
common,
|
||||
constant::{GRID_SIZE, NUM_OF_PROJECTIONS},
|
||||
};
|
||||
|
||||
pub struct Client {
|
||||
pub i: usize,
|
||||
pub projection_matrix: Vec<SMatrix<f32, GRID_SIZE, 1>>,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub fn new(i: usize, projection_matrix: Vec<SMatrix<f32, GRID_SIZE, 1>>) -> Self {
|
||||
Client {
|
||||
i,
|
||||
projection_matrix,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn observe(&mut self, current_grid: (usize, usize)) -> (usize, f32) {
|
||||
let index = common::grid_to_index(current_grid);
|
||||
let projection = &self.projection_matrix[self.i];
|
||||
|
||||
let observation = projection[(index, 0)];
|
||||
|
||||
let result = (self.i, observation);
|
||||
|
||||
if self.i < NUM_OF_PROJECTIONS {
|
||||
self.i += 1;
|
||||
} else {
|
||||
self.i = 0;
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
pub fn observe_quantized(&mut self, current_grid: (usize, usize)) -> (usize, i8) {
|
||||
let normal_observation = self.observe(current_grid);
|
||||
let quantized_observation = common::quantize(normal_observation.1);
|
||||
|
||||
(normal_observation.0, quantized_observation)
|
||||
}
|
||||
}
|
24
src/common.rs
Normal file
24
src/common.rs
Normal file
@ -0,0 +1,24 @@
|
||||
use crate::constant::{GRID_SIZE, GRID_WIDTH};
|
||||
|
||||
pub fn quantize(value: f32) -> i8 {
|
||||
let std_dev = 1.0 / (GRID_SIZE as f32).sqrt();
|
||||
|
||||
let three_sigma = 3.0 * std_dev;
|
||||
|
||||
let scale_factor = 120.0 / three_sigma;
|
||||
|
||||
let scaled = value * scale_factor;
|
||||
let clamped = scaled.clamp(-128.0, 127.0);
|
||||
|
||||
clamped.round() as i8
|
||||
}
|
||||
|
||||
pub fn grid_to_index(grid: (usize, usize)) -> usize {
|
||||
grid.0 * GRID_WIDTH + grid.1
|
||||
}
|
||||
|
||||
pub fn index_to_grid(index: usize) -> (usize, usize) {
|
||||
let x = index / GRID_WIDTH;
|
||||
let y = index % GRID_WIDTH;
|
||||
(x, y)
|
||||
}
|
5
src/constant.rs
Normal file
5
src/constant.rs
Normal file
@ -0,0 +1,5 @@
|
||||
pub const GRID_HEIGHT: usize = 500;
|
||||
pub const GRID_WIDTH: usize = 500;
|
||||
pub const GRID_SIZE: usize = GRID_HEIGHT * GRID_WIDTH;
|
||||
|
||||
pub const NUM_OF_PROJECTIONS: usize = 256;
|
55
src/main.rs
Normal file
55
src/main.rs
Normal file
@ -0,0 +1,55 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use rand::seq::IndexedRandom;
|
||||
|
||||
use crate::constant::NUM_OF_PROJECTIONS;
|
||||
|
||||
pub mod client;
|
||||
pub mod common;
|
||||
pub mod constant;
|
||||
pub mod server;
|
||||
|
||||
fn main() {
|
||||
println!("Generating projections...");
|
||||
let projections = server::generate_projection_matrix();
|
||||
|
||||
println!("Generating fingerprint database...");
|
||||
let fingerprint_database = server::generate_fingerprint_database(projections.clone());
|
||||
|
||||
let mut client = client::Client::new(0, projections);
|
||||
|
||||
let grid_candidates: Vec<(usize, usize)> = vec![(5, 5), (120, 50), (200, 200), (10, 5)];
|
||||
|
||||
let mut rng = rand::rng();
|
||||
|
||||
let mut count: HashMap<usize, usize> = HashMap::new();
|
||||
for i in 0..NUM_OF_PROJECTIONS {
|
||||
let current_grid = *grid_candidates.choose(&mut rng).unwrap();
|
||||
|
||||
let (index, observation) = client.observe_quantized(current_grid);
|
||||
println!("Observation {i}: index = {index}, observation = {observation}");
|
||||
let predictions = server::predict_location_from_database_quantized(
|
||||
&fingerprint_database,
|
||||
(index, observation),
|
||||
);
|
||||
for location in predictions.iter() {
|
||||
count.entry(*location).and_modify(|e| *e += 1).or_insert(1);
|
||||
}
|
||||
}
|
||||
|
||||
let sorted = count.iter().collect::<Vec<_>>();
|
||||
let mut sorted = sorted
|
||||
.into_iter()
|
||||
.map(|(k, v)| (*k, *v))
|
||||
.collect::<Vec<_>>();
|
||||
sorted.sort_by(|a, b| b.1.cmp(&a.1));
|
||||
|
||||
println!("Top 10 locations:");
|
||||
for (i, (location, count)) in sorted.iter().take(10).enumerate() {
|
||||
println!(
|
||||
"Rank {}: Location: {:?}, Count: {count}",
|
||||
i + 1,
|
||||
common::index_to_grid(*location)
|
||||
);
|
||||
}
|
||||
}
|
79
src/server.rs
Normal file
79
src/server.rs
Normal file
@ -0,0 +1,79 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use nalgebra::SMatrix;
|
||||
use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng};
|
||||
use rand_distr::{Distribution, Normal};
|
||||
|
||||
use crate::{
|
||||
common,
|
||||
constant::{GRID_SIZE, NUM_OF_PROJECTIONS},
|
||||
};
|
||||
|
||||
pub fn generate_projection_matrix() -> Vec<SMatrix<f32, GRID_SIZE, 1>> {
|
||||
let mut rng = ChaCha20Rng::from_rng(&mut rand::rng());
|
||||
|
||||
let std_dev = 1.0 / (GRID_SIZE as f64).sqrt();
|
||||
let normal = Normal::new(0.0, std_dev).unwrap();
|
||||
|
||||
(0..NUM_OF_PROJECTIONS)
|
||||
.map(|_| {
|
||||
let mut projection = SMatrix::<f32, GRID_SIZE, 1>::zeros();
|
||||
for i in 0..GRID_SIZE {
|
||||
projection[(i, 0)] = normal.sample(&mut rng) as f32;
|
||||
}
|
||||
projection
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn generate_fingerprint_database(
|
||||
projections: Vec<SMatrix<f32, GRID_SIZE, 1>>,
|
||||
) -> HashMap<usize, (usize, Vec<f32>)> {
|
||||
let mut fingerprint_database = HashMap::new();
|
||||
|
||||
for (i, projection) in projections.iter().enumerate() {
|
||||
let mut fingerprint = Vec::with_capacity(GRID_SIZE);
|
||||
for j in 0..GRID_SIZE {
|
||||
let observation = projection[(j, 0)];
|
||||
fingerprint.push(observation);
|
||||
}
|
||||
fingerprint_database.insert(i, (i, fingerprint));
|
||||
}
|
||||
|
||||
fingerprint_database
|
||||
}
|
||||
|
||||
pub fn predict_location_from_database(
|
||||
fingerprint_database: &HashMap<usize, (usize, Vec<f32>)>,
|
||||
observation: (usize, f32),
|
||||
) -> usize {
|
||||
let ideal_observation = fingerprint_database.get(&observation.0).unwrap();
|
||||
let mut min_distance = f32::MAX;
|
||||
let mut predicted_location = None;
|
||||
for (i, ideal) in ideal_observation.1.iter().enumerate() {
|
||||
let distance = (ideal - observation.1).abs();
|
||||
if distance < min_distance {
|
||||
min_distance = distance;
|
||||
predicted_location = Some(i);
|
||||
}
|
||||
}
|
||||
|
||||
predicted_location.unwrap()
|
||||
}
|
||||
|
||||
pub fn predict_location_from_database_quantized(
|
||||
fingerprint_database: &HashMap<usize, (usize, Vec<f32>)>,
|
||||
observation: (usize, i8),
|
||||
) -> Vec<usize> {
|
||||
let ideal_observation = fingerprint_database.get(&observation.0).unwrap();
|
||||
let locations: Vec<usize> = ideal_observation
|
||||
.1
|
||||
.iter()
|
||||
.map(|o| common::quantize(*o))
|
||||
.enumerate()
|
||||
.filter(|(_, quantized)| *quantized == observation.1)
|
||||
.map(|(i, _)| i)
|
||||
.collect();
|
||||
|
||||
locations
|
||||
}
|
Reference in New Issue
Block a user