use crate::{dynamic::storage::{GridPoint, SparseGridData}, errors::SGError};
pub trait Generator : Default
{
#[allow(non_snake_case)]
fn regular(&self, storage: &mut SparseGridData, levels: &[usize], T :Option<f64>) -> Result<(), SGError>;
fn full(&self, storage: &mut SparseGridData, level: usize) -> Result<(), SGError>;
fn full_with_boundaries(&self, storage: &mut SparseGridData, level: usize) -> Result<(), SGError>;
#[allow(non_snake_case)]
fn regular_with_boundaries(&self, storage: &mut SparseGridData, levels: &[usize], boundary_level: Option<usize>, T :Option<f64>) -> Result<(), SGError>;
}
#[allow(non_snake_case)]
fn regular_generator_iterative(storage: &mut SparseGridData, levels: &[usize], T :Option<f64>) -> Result<(), SGError>
{
let mut point = GridPoint::new(&vec![1; storage.num_inputs], &vec![1; storage.num_inputs], false);
let t = T.unwrap_or(0.0); let n = levels[0] as u32;
for l in 1..=n
{
for i in (1..(1 << l)).step_by(2)
{
let is_leaf = l == n;
point.level[0] = l as u8;
point.index[0] = i;
point.set_is_leaf(is_leaf);
storage.insert_point(point.clone());
}
}
#[allow(clippy::needless_range_loop)]
for d in 1..storage.num_inputs
{
let ngrids = storage.len();
for g in 0..ngrids
{
let mut first = true;
let mut point: GridPoint = storage.point(g);
let level_sum = point.level_sum() - 1;
let level_max = point.level_max();
let mut l = 1;
let n = levels[d] as u32;
while (l + level_sum) as f64 - (t * l.max(level_max) as f64) <= (n + storage.num_inputs as u32 - 1) as f64 - (t * n as f64) && l.max(level_max) as u32 <= n
{
for i in (1..(1 << l)).step_by(2)
{
let is_leaf = (l + level_sum) as u32 == n + storage.num_inputs as u32 - 1;
point.level[d] = l;
point.index[d] = i;
point.set_is_leaf(is_leaf);
if !first
{
storage.insert_point(point.clone());
}
else
{
storage.update(point.clone(), g)?;
first = false;
}
}
l += 1;
}
}
}
Ok(())
}
#[allow(non_snake_case)]
pub fn regular(storage: &mut SparseGridData, levels: &[usize], T :Option<f64>) -> Result<(), SGError>
{
regular_generator_iterative(storage, levels, T)
}
fn full_iterative(storage: &mut SparseGridData, level: usize) -> Result<(), SGError>
{
let mut point = GridPoint::new(&vec![1; storage.num_inputs], &vec![1;storage.num_inputs], false);
let n = level as u32;
for l in 1..=n
{
for i in (1..(1 << l)).step_by(2)
{
let is_leaf = l == n;
point.level[0] = l as u8;
point.index[0] = i;
point.set_is_leaf(is_leaf);
storage.insert_point(point.clone());
}
}
for d in 1..storage.num_inputs
{
let ngrids = storage.len();
for g in 0..ngrids
{
let mut first = true;
let mut point: GridPoint = storage.point(g);
for l in 1..=n
{
for i in (1..(1 << l)).step_by(2)
{
let is_leaf = point.level_sum() as u32 == n * storage.num_inputs as u32;
point.level[d] = l as u8;
point.index[d] = i;
point.set_is_leaf(is_leaf);
if !first
{
storage.insert_point(point.clone());
}
else
{
storage.update(point.clone(), g)?;
first = false;
}
}
}
}
}
Ok(())
}
pub fn full(storage: &mut SparseGridData, level: usize) -> Result<(), SGError> {
full_iterative(storage, level)
}
pub fn full_with_boundaries(storage: &mut SparseGridData, level: usize) -> Result<(), SGError> {
full_with_boundaries_iter(storage, level)?;
storage.has_boundary = true;
Ok(())
}
#[allow(non_snake_case)]
pub fn regular_with_boundaries(storage: &mut SparseGridData, levels: &[usize], boundary_level: Option<usize>, T :Option<f64>) -> Result<(), SGError> {
let boundary_level = boundary_level.unwrap_or(1);
if boundary_level > 0
{
regular_with_boundaries_iter(storage, levels, Some(boundary_level), T)?;
storage.has_boundary = true;
Ok(())
}
else
{
Err(SGError::NotImplemented)
}
}
#[allow(non_snake_case)]
fn regular_with_boundaries_iter(storage: &mut SparseGridData, levels: &[usize], boundary_level: Option<usize>, T :Option<f64>) -> Result<(), SGError>
{
let boundary_level = boundary_level.unwrap_or(1) as u32;
let mut point = GridPoint::new(&vec![1; storage.num_inputs], &vec![1;storage.num_inputs], false);
let t = T.unwrap_or(0.0); let n = levels[0] as u32;
point.level[0] = 0;
point.index[0] = 0;
storage.insert_point(point.clone());
point.index[0] = 1;
storage.insert_point(point.clone());
for l in 1..=n
{
for i in (1..(1 << l)).step_by(2)
{
let is_leaf = l == n;
point.level[0] = l as u8;
point.index[0] = i;
point.set_is_leaf(is_leaf);
storage.insert_point(point.clone());
}
}
for d in 1..storage.num_inputs as u32
{
let ngrids = storage.len();
let cur_dim = d+1;
for g in 0..ngrids
{
let mut point: GridPoint = storage.point(g);
let mut level_sum = 0;
let mut num_zero_levels = 0;
for j in 0..d as usize
{
let lvl = point.level[j];
if lvl == 0
{
num_zero_levels += 1;
}
level_sum += lvl;
}
let mut first_point = true;
if (level_sum as u32 + boundary_level + num_zero_levels < n + cur_dim) || (num_zero_levels == cur_dim - 1)
{
point.level[d as usize] = 0;
point.index[d as usize] = 0;
point.set_is_leaf(false);
storage.update(point.clone(), g)?;
point.index[d as usize] = 1;
storage.insert_point(point.clone());
first_point = false;
}
let mut upper_bound = if num_zero_levels > 0
{
if n + cur_dim < boundary_level + num_zero_levels
{
continue;
} else {
(n + cur_dim - num_zero_levels - boundary_level) as f64
}
}
else
{
(n + cur_dim - 1) as f64
};
upper_bound -= t * n as f64;
let level_max = point.level_max();
let mut l = 1;
let d = d as usize;
let n = levels[d];
while (l + level_sum) as f64 - (t * l.max(level_max) as f64) <= upper_bound && l.max(level_max) <= n as u8
{
for i in (1..(1 << l)).step_by(2)
{
let is_leaf = if l as u32 +level_sum as u32 == n as u32 + storage.num_inputs as u32 - 1 { num_zero_levels == 0 } else { false};
point.level[d] = l;
point.index[d] = i;
point.set_is_leaf(is_leaf);
if !first_point
{
storage.insert_point(point.clone());
}
else
{
storage.update(point.clone(), g)?;
first_point = false;
}
}
l += 1;
}
}
}
Ok(())
}
fn full_with_boundaries_iter(storage: &mut SparseGridData, level: usize) -> Result<(), SGError>
{
let mut point = GridPoint::new(&vec![1; storage.num_inputs], &vec![1;storage.num_inputs], false);
let n = level as u32;
for l in 1..=n
{
if l == 1
{
point.level[0] = 0;
point.index[0] = 0;
point.set_is_leaf(false);
storage.insert_point(point.clone());
point.index[0] = 1;
storage.insert_point(point.clone());
}
for i in (1..(1 << l)).step_by(2)
{
let is_leaf = l == n;
point.level[0] = l as u8;
point.index[0] = i;
point.set_is_leaf(is_leaf);
storage.insert_point(point.clone());
}
}
for d in 1..storage.num_inputs as u32
{
let ngrids = storage.len();
for g in 0..ngrids
{
let mut point: GridPoint = storage.point(g);
for l in 1..=n
{
if l == 1
{
point.level[d as usize] = 0;
point.index[d as usize] = 0;
point.set_is_leaf(false);
storage.update(point.clone(), g)?;
point.index[d as usize] = 1;
storage.insert_point(point.clone());
}
point.level[d as usize] = l as u8;
for i in (1..(1 <<l)).step_by(2)
{
point.index[d as usize] = i;
point.set_is_leaf(point.level_sum() as u32 == n * storage.num_inputs as u32);
storage.insert_point(point.clone());
}
}
}
}
Ok(())
}
#[test]
fn test_regular()
{
let mut storage = SparseGridData::new(2, 1);
regular(&mut storage, &[3,3], Some(0.0)).expect("Could not generate grid");
assert_eq!(storage.len(), 17);
}
#[test]
fn test_truncated_boundaries_1d()
{
let mut storage = SparseGridData::new(1, 1);
regular_with_boundaries(&mut storage, &[2], Some(1), None).expect("Could not generate grid");
assert_eq!(storage.len(), 5);
}
#[test]
fn test_truncated_boundaries_2d()
{
let mut storage = SparseGridData::new(2,1);
regular_with_boundaries(&mut storage, &[2,2], Some(1), None).expect("Could not generate grid");
assert_eq!(storage.len(), 21);
let mut storage2 = SparseGridData::new(2,1);
regular_with_boundaries(&mut storage2, &[3,3], Some(1), None).expect("Could not generate grid");
assert_eq!(storage2.len(), 49);
assert!(storage2.contains(&GridPoint::new(&[1,1], &[1,1], false)));
assert!(storage2.contains(&GridPoint::new(&[1,2], &[1,1], false)));
assert!(storage2.contains(&GridPoint::new(&[2,2], &[3,1], false)));
assert!(!storage2.contains(&GridPoint::new(&[3,2], &[5,1], false)));
assert!(storage2.contains(&GridPoint::new(&[3,1], &[5,1], false)));
assert!(storage2.contains(&GridPoint::new(&[3,0], &[5,0], false)));
assert!(storage2.contains(&GridPoint::new(&[0,0], &[0,0], false)));
}