Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions examples/readme_bin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use ernst::spin_network::SpinNetwork;
use ernst::types::{ExternalMagneticField, Interactions};
use std::time::Instant;
use ernst::nodelib::logic_gates::OR;

fn main() {
let some_h: ExternalMagneticField = vec![
5.0, 5.0, 5.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, -1.0, 0.5, 0.5, -1.0, 0.5, 0.5, -1.0, 0.5,
0.5, -1.0,
];
let some_j: Interactions = vec![
(0, 7, 1.0),
(1, 8, 1.0),
(7, 8, -0.5),
(7, 9, 1.0),
(8, 9, 1.0),
(1, 10, 1.0),
(2, 11, 1.0),
(10, 11, -0.5),
(10, 12, 1.0),
(11, 12, 1.0),
(0, 13, 1.0),
(4, 14, 1.0),
(13, 14, -0.5),
(13, 15, 1.0),
(14, 15, 1.0),
(3, 16, 1.0),
(2, 17, 1.0),
(16, 17, -0.5),
(16, 18, 1.0),
(17, 18, 1.0),
(3, 9, 1.0),
(4, 12, 1.0),
(5, 15, 1.0),
(6, 18, 1.0),
];

let now = Instant::now();
let exact_ground_states = ernst::solvers::find_all_ground_states(&some_j, &some_h);
let time_to_compute = now.elapsed().as_millis();
println!("Complex spin glass ground state - took: {} ms", time_to_compute);
for ground_state in exact_ground_states {
println!(
"\tEnergy: {} - State: {:?}",
ground_state.0, ground_state.1
);
}

let now = Instant::now();
let approximate_ground_states = ernst::solvers::simulated_annealing(&some_j, &some_h, None);
let time_to_compute = now.elapsed().as_millis();
println!("\nComplex spin glass ground state with simulated annealing - took: {} ms", time_to_compute);
for ground_state in approximate_ground_states {
println!(
"\tEnergy: {} - State: {:?} - Found in sweep number: {}",
ground_state.0, ground_state.1, ground_state.2
);
}

let mut spin_network = SpinNetwork::new();
let s0 = spin_network.add_input_node(0.0);
let s1 = spin_network.add_input_node(0.0);
let or_gate = OR::default();
let z = spin_network.add_binary_node(s0, s1, &or_gate);

let interesting_spins = vec![s0, s1, z];
let binary_or_ground_states = spin_network.find_all_ground_states(Some(interesting_spins.clone()));
println!("\nBinary OR spin glass ground states:");
for ground_state in binary_or_ground_states {
println!("\tEnergy: {} - State: {:?}", ground_state.0, ground_state.1);
}

let copy_ground_states = spin_network.run_simulated_annealing(None, Some(interesting_spins));
println!("\nBinary OR spin glass ground states with simulated annealing:");
for ground_state in copy_ground_states {
println!("\tEnergy: {} - State: {:?} - Found in sweep number: {}", ground_state.0, ground_state.1, ground_state.2);
}
}
27 changes: 27 additions & 0 deletions examples/readme_ter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use ernst::spin_network::SpinNetwork;
use ernst::types::{ExternalMagneticField, Interactions};
use std::time::Instant;
use ernst::nodelib::logic_gates::OR;

fn main() {
let mut spin_network = SpinNetwork::new();
let s0 = spin_network.add_input_node(0.0);
let s1 = spin_network.add_input_node(0.0);
let s2 = spin_network.add_input_node(0.0);
let or_gate = OR::default();
let z: usize = spin_network.add_ternary_node(s0, s1, s2, &or_gate);

let interesting_spins = vec![s0, s1, s2, z];
let ternary_or_ground_states = spin_network.find_all_ground_states(Some(interesting_spins.clone()));
println!("\nTernary OR spin glass ground states:");
for ground_state in ternary_or_ground_states {
println!("\tEnergy: {} - State: {:?}", ground_state.0, ground_state.1);
}

let copy_ground_states = spin_network.run_simulated_annealing(None, Some(interesting_spins));
println!("\nTernary OR spin glass ground states with simulated annealing:");
for ground_state in copy_ground_states {
println!("\tEnergy: {} - State: {:?} - Found in sweep number: {}", ground_state.0, ground_state.1, ground_state.2);
}

}
27 changes: 27 additions & 0 deletions examples/readme_ter_aux.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use ernst::spin_network::SpinNetwork;
use ernst::types::{ExternalMagneticField, Interactions};
use std::time::Instant;
use ernst::nodelib::logic_gates::OR;

fn main() {
let mut spin_network = SpinNetwork::new();
let s0 = spin_network.add_input_node(0.0);
let s1 = spin_network.add_input_node(0.0);
let s2 = spin_network.add_input_node(0.0);
let or_gate = OR::default();
let z_aux = spin_network.add_binary_node(s0, s1, &or_gate);
let z = spin_network.add_binary_node(z_aux, s2, &or_gate);

let interesting_spins = vec![s0, s1, s2, z];
let ternary_or_ground_states = spin_network.find_all_ground_states(Some(interesting_spins.clone()));
println!("\nTernary OR spin glass ground states:");
for ground_state in ternary_or_ground_states {
println!("\tEnergy: {} - State: {:?}", ground_state.0, ground_state.1);
}

let copy_ground_states = spin_network.run_simulated_annealing(None, Some(interesting_spins));
println!("\nTernary OR spin glass ground states with simulated annealing:");
for ground_state in copy_ground_states {
println!("\tEnergy: {} - State: {:?} - Found in sweep number: {}", ground_state.0, ground_state.1, ground_state.2);
}
}
38 changes: 37 additions & 1 deletion src/nodelib/logic_gates.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::spin_network::SpinNetwork;
use crate::types::{BinaryNode, Energy, MagneticFieldStrength, Node, UnaryNode};
use crate::types::{BinaryNode, TernaryNode, Energy, MagneticFieldStrength, Node, UnaryNode};

#[derive(Default)]
pub struct COPY {
Expand Down Expand Up @@ -106,6 +106,42 @@ impl BinaryNode for OR {
output_node_index
}
}
impl TernaryNode for OR {
fn connect_to_three(
&self,
spin_network: &mut SpinNetwork,
first_input: usize,
second_input: usize,
third_input: usize,
) -> usize {
let ouput_node_index: usize = self.connect(spin_network);
let copy_with_minus_third = COPY::new(-1.0 / 3.0);
let first_copy_output_index = spin_network.add_unary_node(first_input, &copy_with_minus_third);
let second_copy_output_index =
spin_network.add_unary_node(second_input, &copy_with_minus_third);
let third_copy_output_index = spin_network.add_unary_node(third_input, &copy_with_minus_third);

let first_to_second = (first_copy_output_index, second_copy_output_index, -1.0 / 3.0);
let first_to_third = (first_copy_output_index, third_copy_output_index, -1.0 / 3.0);
let second_to_third = (second_copy_output_index, third_copy_output_index, -1.0 / 3.0);
let first_to_output = (first_copy_output_index, ouput_node_index, 1.0);
let second_to_output = (second_copy_output_index, ouput_node_index, 1.0);
let third_to_output = (third_copy_output_index, ouput_node_index, 1.0);

spin_network.interactions.push(first_to_second);
spin_network.interactions.push(first_to_third);
spin_network.interactions.push(second_to_third);
spin_network.interactions.push(first_to_output);
spin_network.interactions.push(second_to_output);
spin_network.interactions.push(third_to_output);

ouput_node_index
}

}//

//


#[derive(Default)]
pub struct NAND {}
Expand Down
21 changes: 19 additions & 2 deletions src/spin_network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ use crate::solvers::{
find_all_ground_states, simulated_annealing, Epoch, SimulatedAnnealingConfiguration,
};
use crate::types::{
BinaryNode, Energy, ExternalMagneticField, Interactions, MagneticFieldStrength, SpinIndex,
State, UnaryNode
BinaryNode, TernaryNode, Energy, ExternalMagneticField, Interactions, MagneticFieldStrength, NAryNode, SpinIndex, State, UnaryNode
};

/// A SpinNetwork is meant to represent a 2D Spin Glass.
Expand Down Expand Up @@ -103,6 +102,24 @@ impl SpinNetwork {
) -> usize {
return BinaryNode::connect_to_two(binary_node, self, left_input, right_input);
}
pub fn add_ternary_node(
&mut self,
first_input: usize,
second_input: usize,
third_input: usize,
ternary_node: &impl TernaryNode,
) -> usize {
return TernaryNode::connect_to_three(ternary_node, self, first_input, second_input, third_input);
}
// problem here: how to make it accept variable n number of inputs in rust?
pub fn add_NAry_node(
&mut self,
inputs: &Vec<usize>,
nary_node: &impl NAryNode,
) -> usize {
NAryNode::connect_to_n(nary_node, self, inputs)
}

/// Finds all ground states of the spin glass represented by the SpinNetwork. The argument `spin_ordering`, when
/// given, will ensure that the `State`s will be projected according to it.
///
Expand Down
9 changes: 9 additions & 0 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ pub trait BinaryNode: Node {
right_input: SpinIndex,
) -> SpinIndex;
}
pub trait TernaryNode: Node {
fn connect_to_three(
&self,
spin_network: &mut SpinNetwork,
first_input: SpinIndex,
second_input: SpinIndex,
third_input: SpinIndex,
) -> SpinIndex;
}
pub trait NAryNode: Node {
fn connect_to_n(&self, spin_network: &mut SpinNetwork, inputs: &Vec<SpinIndex>) -> SpinIndex;
}