Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ######### Python Version ##########
- def run(nodes, colors, connections, available_colors, entropy, output):
- global min_index
- global affected_nodes
- global FINISHED
- global RESTART_FLAG
- FINISHED = False
- RESTART_FLAG = False
- affected_nodes = []
- min_index = -1
- def restart_wfc():
- global available_colors, entropy, output
- available_colors = [[True for _ in range(colors)] for _1 in range(nodes)]
- entropy = [colors for _ in range(nodes)]
- output = [-1 for _ in range(nodes)]
- #returns the index of the lowest entropy
- def find_lowest_entropy():
- global colors
- global min_index
- global FINISHED
- global RESTART_FLAG
- min_value = colors+1
- FINISHED = True
- for index, val in enumerate(entropy):
- #collapsed nodes
- if val == -1:
- continue
- if val == 0:
- RESTART_FLAG = True
- restart_wfc()
- if(min_value > val):
- min_value = val
- min_index = index
- FINISHED = False
- def observe():
- find_lowest_entropy()
- def collapse(index):
- global entropy, available_colors, output, affected_nodes
- if not(FINISHED):
- if(entropy[index] == 0):
- raise Exception("Impossible pattern")
- entropy[index] = -1
- affected_nodes.append(index)
- #pick lowest available color
- flag = True
- color_index = available_colors[index].index(True)
- available_colors[index] = [False] * colors
- available_colors[index][color_index] = True
- output[index] = color_index
- def propogate():
- visisted = [False for _ in range(nodes)]
- while len(affected_nodes) > 0:
- index = affected_nodes.pop()
- #find first available color
- color_index = available_colors[index].index(True)
- #calculate impact
- for node_index in range(nodes):
- #check if connected and is not collapsed
- if connections[index][node_index] and entropy[node_index] != -1:
- if(available_colors[node_index][color_index] == True):
- available_colors[node_index][color_index] = False
- entropy[node_index] -= 1
- if entropy[node_index] == 0:
- raise Exception("Found error in propogation")
- if entropy[node_index] == 1 and not(visisted[node_index]):
- visisted[node_index] = True
- #collapse
- affected_nodes.append(node_index)
- while not(FINISHED):
- RESTART_FLAG = False
- observe()
- if(min_index == -1):
- break
- if RESTART_FLAG:
- continue
- collapse(min_index)
- propogate()
- return output
- ############# Rust Version #############
- #[derive(Debug)]
- struct WfcState {
- nodes: usize,
- colors: usize,
- connections: Vec<Vec<bool>>,
- available_colors: Vec<Vec<bool>>,
- entropy: Vec<usize>,
- output: Vec<isize>,
- affected_nodes: VecDeque<usize>,
- min_index: Option<usize>,
- finished: bool,
- restart_flag: bool,
- }
- impl WfcState {
- fn new(nodes: usize, colors: usize, connections: Vec<Vec<bool>>) -> Self {
- Self {
- nodes,
- colors,
- connections,
- available_colors: vec![vec![true; colors]; nodes],
- entropy: vec![colors; nodes],
- output: vec![-1; nodes],
- affected_nodes: VecDeque::new(),
- min_index: None,
- finished: false,
- restart_flag: false,
- }
- }
- fn restart_wfc(&mut self) {
- self.available_colors = vec![vec![true; self.colors]; self.nodes];
- self.entropy = vec![self.colors; self.nodes];
- self.output = vec![-1; self.nodes];
- self.affected_nodes.clear();
- self.min_index = None;
- self.finished = false;
- self.restart_flag = false;
- }
- fn find_lowest_entropy(&mut self) {
- let mut min_value = self.colors + 1;
- self.finished = true;
- self.min_index = None;
- for (index, &val) in self.entropy.iter().enumerate() {
- if val == usize::MAX {
- continue; // Collapsed node
- }
- if val == 0 {
- self.restart_flag = true;
- self.restart_wfc();
- return;
- }
- if val < min_value {
- min_value = val;
- self.min_index = Some(index);
- self.finished = false;
- }
- }
- }
- fn collapse(&mut self, index: usize) -> Result<(), String> {
- if self.finished {
- return Ok(());
- }
- if self.entropy[index] == 0 {
- return Err("Impossible pattern".to_string());
- }
- self.entropy[index] = usize::MAX; // Mark as collapsed
- self.affected_nodes.push_back(index);
- // Pick the lowest available color
- let color_index = self
- .available_colors[index]
- .iter()
- .position(|&x| x)
- .ok_or_else(|| "No available color".to_string())?;
- self.available_colors[index] = vec![false; self.colors];
- self.available_colors[index][color_index] = true;
- self.output[index] = color_index as isize;
- Ok(())
- }
- fn propagate(&mut self) -> Result<(), String> {
- let mut visited = vec![false; self.nodes];
- while let Some(index) = self.affected_nodes.pop_front() {
- let color_index = self
- .available_colors[index]
- .iter()
- .position(|&x| x)
- .ok_or_else(|| "No available color during propagation".to_string())?;
- for node_index in 0..self.nodes {
- if self.connections[index][node_index] && self.entropy[node_index] != usize::MAX {
- if self.available_colors[node_index][color_index] {
- self.available_colors[node_index][color_index] = false;
- self.entropy[node_index] -= 1;
- if self.entropy[node_index] == 0 {
- return Err("Propagation error: no valid configuration".to_string());
- }
- if self.entropy[node_index] == 1 && !visited[node_index] {
- visited[node_index] = true;
- self.affected_nodes.push_back(node_index);
- }
- }
- }
- }
- }
- Ok(())
- }
- fn run(&mut self) -> Result<Vec<isize>, String> {
- while !self.finished {
- self.restart_flag = false;
- self.find_lowest_entropy();
- if let Some(index) = self.min_index {
- if self.restart_flag {
- continue;
- }
- self.collapse(index)?;
- self.propagate()?;
- } else {
- break; // No valid index found
- }
- }
- Ok(self.output.clone())
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement