Skip to content

Commit

Permalink
Implement move application for PhaseLookupTable.
Browse files Browse the repository at this point in the history
  • Loading branch information
lgarron committed Oct 18, 2024
1 parent d2734af commit 1724160
Show file tree
Hide file tree
Showing 10 changed files with 227 additions and 44 deletions.
6 changes: 3 additions & 3 deletions src/rs/_internal/canonical_fsm/canonical_fsm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ pub struct CanonicalFSM {
impl CanonicalFSM {
// TODO: Return a more specific error.
pub fn try_new(generators: SearchGenerators) -> Result<CanonicalFSM, SearchError> {
let num_move_classes = generators.grouped.len();
let num_move_classes = generators.by_move_class.len();
if num_move_classes > MAX_NUM_MOVE_CLASSES {
return Err(SearchError {
description: "Too many move classes!".to_owned(),
Expand All @@ -113,8 +113,8 @@ impl CanonicalFSM {
for i in 0..num_move_classes {
for j in 0..num_move_classes {
if !do_transformations_commute(
&generators.grouped[i][0].transformation,
&generators.grouped[j][0].transformation,
&generators.by_move_class[i][0].transformation,
&generators.by_move_class[j][0].transformation,
) {
commutes[i] &= MoveClassMask(!(1 << j));
commutes[j] &= MoveClassMask(!(1 << i));
Expand Down
16 changes: 9 additions & 7 deletions src/rs/_internal/canonical_fsm/search_generators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@ use cubing::{
};
use rand::{seq::SliceRandom, thread_rng};

use crate::_internal::{
cli::options::{Generators, MetricEnum},
SearchError,
use crate::{
_internal::{
cli::options::{Generators, MetricEnum},
SearchError,
},
index_type,
};

use super::MoveClassIndex;

#[derive(Clone, Debug)]
pub struct FlatMoveIndex(usize);
index_type!(FlatMoveIndex);

#[derive(Clone, Debug)]
pub struct MoveTransformationInfo {
Expand All @@ -34,7 +36,7 @@ pub type MoveTransformationMultiples = Vec<MoveTransformationInfo>;
#[derive(Clone, Debug)]
pub struct SearchGenerators {
// TODO: figure out the most reusable abstraction
pub grouped: Vec<MoveTransformationMultiples>,
pub by_move_class: Vec<MoveTransformationMultiples>,
pub flat: Vec<MoveTransformationInfo>, // TODO: avoid duplicate data
pub by_move: HashMap<Move, (MoveClassIndex, MoveTransformationInfo)>, // TODO: avoid duplicate data
}
Expand Down Expand Up @@ -181,7 +183,7 @@ impl SearchGenerators {
}

Ok(Self {
grouped,
by_move_class: grouped,
flat,
by_move,
})
Expand Down
2 changes: 1 addition & 1 deletion src/rs/_internal/gods_algorithm/gods_algorithm_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ impl GodsAlgorithmSearch {
let mut patterns_at_current_depth = BulkQueue::new(None);
for queue_item in last_depth_patterns.into_iter() {
for move_class_index in &self.canonical_fsm.move_class_indices {
let moves_in_class = &self.search_moves.grouped[move_class_index.0];
let moves_in_class = &self.search_moves.by_move_class[move_class_index.0];
let next_state = self
.canonical_fsm
.next_state(queue_item.canonical_fsm_state, *move_class_index);
Expand Down
8 changes: 6 additions & 2 deletions src/rs/_internal/search/idf_search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,12 @@ impl<T: CheckPattern> IDFSearch<T> {
if prune_table_depth > remaining_depth {
return SearchRecursionResult::ContinueSearchingDefault();
}
for (move_class_index, move_transformation_multiples) in
self.api_data.search_generators.grouped.iter().enumerate()
for (move_class_index, move_transformation_multiples) in self
.api_data
.search_generators
.by_move_class
.iter()
.enumerate()
{
let Some(next_state) = self
.api_data
Expand Down
2 changes: 1 addition & 1 deletion src/rs/_internal/search/prune_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ impl<T: CheckPattern> PruneTable<T> {
for (move_class_index, move_transformation_multiples) in immutable_data
.search_api_data
.search_generators
.grouped
.by_move_class
.iter()
.enumerate()
{
Expand Down
4 changes: 2 additions & 2 deletions src/rs/scramble/puzzles/big_cubes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,13 @@ fn scramble_big_cube(scramble_info: &ScrambleInfo, num_random_moves: usize) -> A
// TODO: we can forward-cache the valid move classes for each state instead of rejection sampling.
loop {
let move_class_index =
MoveClassIndex(rng.gen_range(0..scramble_info.generators.grouped.len()));
MoveClassIndex(rng.gen_range(0..scramble_info.generators.by_move_class.len()));
let next = scramble_info
.canonical_fsm
.next_state(current_fsm_state, move_class_index);
if let Some(next) = next {
nodes.push(AlgNode::MoveNode(
scramble_info.generators.grouped[move_class_index.0]
scramble_info.generators.by_move_class[move_class_index.0]
.choose(&mut rng)
.unwrap()
.r#move
Expand Down
64 changes: 64 additions & 0 deletions src/rs/scramble/puzzles/indexed_vec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use std::marker::PhantomData;

/// Contains some direct convenience methods. Use `.0` to access the underlying array.
#[derive(Debug)]
pub struct IndexedVec<K: From<usize> + Into<usize> + Default, V>(pub(crate) Vec<V>, PhantomData<K>);

impl<K: From<usize> + Into<usize> + Default, V> IndexedVec<K, V> {
// pub fn new(v: Vec<V>) -> Self {
// Self(v, Default::default())
// }

// Convenience wrapper
pub fn push(&mut self, v: V) {
self.0.push(v);
}

pub fn at(&self, k: K) -> &V {
&self.0[k.into()]
}

pub fn len(&self) -> usize {
self.0.len()
}

// TODO Implement `IntoIterator`
pub fn iter(&self) -> impl Iterator<Item = (K, &V)> {
self.0
.iter()
.enumerate()
.map(|(i, v)| (std::convert::Into::<K>::into(i), v))
}
}

impl<K: From<usize> + Into<usize> + Default, V> Default for IndexedVec<K, V> {
fn default() -> Self {
Self(Default::default(), Default::default())
}
}

// TODO: use inside the project without exporting.
#[macro_export]
/// Do not use outside `twsearch`.
macro_rules! index_type {
($e: ident) => {
#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash, Default)]
pub struct $e(pub usize);

// TODO: Make this a derived trait?
impl From<$e> for usize {
fn from(v: $e) -> usize {
v.0
}
}

// TODO: Make this a derived trait?
impl From<usize> for $e {
fn from(v: usize) -> Self {
Self(v)
}
}
};
}

pub use index_type;
2 changes: 2 additions & 0 deletions src/rs/scramble/puzzles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ pub mod square1_phase_lookup_table;

mod definitions;
mod mask_pattern;

pub mod indexed_vec; // TODO: avoid making this fully public
mod static_move_list;
40 changes: 36 additions & 4 deletions src/rs/scramble/puzzles/square1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use rand::seq::SliceRandom;
use rand::thread_rng;

use crate::{
_internal::CheckPattern,
_internal::{CheckPattern, FlatMoveIndex},
scramble::{
randomize::{basic_parity, BasicParity, PieceZeroConstraint},
scramble_search::FilteredSearch,
Expand All @@ -27,7 +27,7 @@ use super::{
},
definitions::{square1_square_square_shape_kpattern, square1_unbandaged_kpuzzle},
mask_pattern::mask,
square1_phase_lookup_table::build_phase_lookup_table,
square1_phase_lookup_table::{build_phase_lookup_table, PhasePatternIndex},
};

#[derive(PartialEq, Eq)]
Expand Down Expand Up @@ -135,11 +135,43 @@ pub fn scramble_square1() -> Alg {
let kpuzzle = square1_unbandaged_kpuzzle();
let generators = generators_from_vec_str(vec!["U_SQ_", "D_SQ_", "_SLASH_"]); // TODO: cache

let _phase_lookup_table = build_phase_lookup_table::<Phase1Checker>(
let (phase_lookup_table, search_generators) = build_phase_lookup_table::<Phase1Checker>(
kpuzzle.clone(),
&generators,
square1_square_square_shape_kpattern().to_owned(),
&square1_square_square_shape_kpattern().to_owned(),
);
// let idx = phase_lookup_table
// .index_to_lookup_pattern
// .at(PhasePatternIndex(0));
#[allow(non_snake_case)]
let U_SQ_ = phase_lookup_table.apply_move(PhasePatternIndex(0), FlatMoveIndex(22));
dbg!(U_SQ_);
dbg!(phase_lookup_table
.index_to_lookup_pattern
.at(U_SQ_.unwrap()));
dbg!(phase_lookup_table.apply_move(U_SQ_.unwrap(), FlatMoveIndex(10)));
#[allow(non_snake_case)]
let U_SQ_SLICE = phase_lookup_table
.index_to_lookup_pattern
.at(phase_lookup_table
.apply_move(U_SQ_.unwrap(), FlatMoveIndex(22))
.unwrap());
dbg!(U_SQ_SLICE);
dbg!(
U_SQ_,
phase_lookup_table
.move_application_table
.at(U_SQ_.unwrap())
.at(FlatMoveIndex(22))
);
dbg!(
U_SQ_,
phase_lookup_table
.index_to_lookup_pattern
.at(PhasePatternIndex(1))
);

dbg!(&search_generators.flat[10]);

// dbg!(wedge_parity(
// &kpuzzle
Expand Down
Loading

0 comments on commit 1724160

Please sign in to comment.