use rand::Rng;
pub enum BinOp {
AND,
OR,
XOR,
NOR,
}
pub fn binop_2str<'a>(input : BinOp) -> &'a str {
match input {
BinOp::AND => "AND",
BinOp::OR => "OR",
BinOp::XOR => "XOR",
BinOp::NOR => "NOR",
}
}
#[derive(PartialEq, Debug)]
enum AndPseudoMatrixValue {
NEITHER,
REQUIRED,
COMPLEMENT,
}
fn get_null_and_row(vector_size: usize) -> Vec<AndPseudoMatrixValue> {
let mut v: Vec<AndPseudoMatrixValue> = Vec::with_capacity(vector_size);
for _i in 0..vector_size {
v.push(AndPseudoMatrixValue::NEITHER);
}
v
}
fn increment_and_row(and_row: &mut Vec<AndPseudoMatrixValue>) {
for i in 0..and_row.len() {
if and_row[i] == AndPseudoMatrixValue::NEITHER {
and_row[i] = AndPseudoMatrixValue::REQUIRED;
for j in 0..i {
and_row[j] = AndPseudoMatrixValue::NEITHER;
}
return;
} else if and_row[i] == AndPseudoMatrixValue::REQUIRED {
and_row[i] = AndPseudoMatrixValue::COMPLEMENT;
for j in 0..i {
and_row[j] = AndPseudoMatrixValue::NEITHER;
}
return;
}
}
panic!("AndPseudoMatrixValue vector overflow");
}
fn compare_and_row(and_row: &Vec<AndPseudoMatrixValue>, input: &Vec<bool>) -> bool {
assert_eq!(and_row.len(), input.len());
let mut to_return = false;
for i in 0..and_row.len() {
if and_row[i] != AndPseudoMatrixValue::NEITHER {
to_return = true;
}
if and_row[i] == AndPseudoMatrixValue::REQUIRED && !input[i] {
return false
} else if and_row[i] == AndPseudoMatrixValue::COMPLEMENT && input[i] {
return false
}
}
assert!(to_return); to_return
}
pub struct ProgrammableLogicArray {
or_matrix: Vec< Vec<bool> >,
}
impl ProgrammableLogicArray {
fn calculate_or_column_size(in_size: usize) -> usize {
3usize.pow(in_size as u32) - 1
}
pub fn new_null(in_size: usize, out_size: usize) -> ProgrammableLogicArray {
let mut pla = ProgrammableLogicArray {
or_matrix: Vec::with_capacity(out_size),
};
let or_column_size = ProgrammableLogicArray::calculate_or_column_size(in_size);
for _i in 0..out_size {
pla.or_matrix.push(get_null_bitvector(or_column_size));
}
pla
}
pub fn new_rand(in_size: usize, out_size: usize) -> ProgrammableLogicArray {
let mut pla = ProgrammableLogicArray {
or_matrix: Vec::with_capacity(out_size),
};
let or_column_size = ProgrammableLogicArray::calculate_or_column_size(in_size);
for _i in 0..out_size {
pla.or_matrix.push(get_rand_bitvector(or_column_size));
}
pla
}
pub fn new_mutated(in_size: usize, out_size: usize, num_mutations: u32) -> ProgrammableLogicArray {
let mut pla = ProgrammableLogicArray {
or_matrix: Vec::with_capacity(out_size),
};
let or_column_size = ProgrammableLogicArray::calculate_or_column_size(in_size);
for _i in 0..out_size {
pla.or_matrix.push(get_null_bitvector(or_column_size));
}
for _i in 0..num_mutations {
pla.random_mutation();
}
pla
}
pub fn random_mutation(&mut self) {
let chosen_bit = rand::thread_rng().gen_range(0, self.or_matrix.len());
let chosen_output = rand::thread_rng().gen_range(0, self.or_matrix[0].len());
self.or_matrix[chosen_bit][chosen_output] = !self.or_matrix[chosen_bit][chosen_output];
}
pub fn calculate_output(&self, input : &Vec<bool>) -> Vec<bool> {
let in_size = input.len();
let or_column_size = ProgrammableLogicArray::calculate_or_column_size(in_size);
let mut and_matrix_row = get_null_and_row(in_size);
increment_and_row(&mut and_matrix_row);
let out_size = self.or_matrix.len();
let mut output : Vec<bool> = Vec::with_capacity(out_size);
for _i in 0..out_size {
output.push(false);
}
println!("----------------------------------------------------------");
println!("or_column_size {}", or_column_size);
println!("or_column_size * {} = {}", out_size, or_column_size * out_size);
println!("----------------------------------------------------------");
for j in 0..or_column_size {
for i in 0..out_size {
if !output[i] && self.or_matrix[i][j] && compare_and_row(&and_matrix_row, &input) {
output[i] = true;
}
}
println!("i: {}", j);
println!("output: {:?}", &output);
println!("and_matrix_row: {:?}", &and_matrix_row);
if j < or_column_size - 1 {
increment_and_row(&mut and_matrix_row);
}
}
output
}
pub fn print(&self) {
let max_bitvector_print = 32;
for i in 0..self.or_matrix.len() {
print!("or matrix column {}:", i);
print_limited_bitvector(&self.or_matrix[i], max_bitvector_print);
}
}
}
fn compare_and(bitvector: &Vec<bool>, other: &Vec<bool>) -> bool {
assert_eq!(bitvector.len(), other.len());
let mut to_return = false;
for i in 0..bitvector.len() {
if bitvector[i] {
to_return = true;
if !other[i] {
return false
}
}
}
to_return
}
pub fn calculate_result(operation_type : &BinOp, v_a: &Vec<bool>, v_b: &Vec<bool>) -> Vec<bool> {
assert_eq!(v_a.len(), v_b.len());
let mut v_result: Vec<bool> = Vec::new();
for i in 0..v_a.len() {
v_result.push(
match operation_type {
BinOp::AND => v_a[i] && v_b[i],
BinOp::OR => v_a[i] || v_b[i],
BinOp::XOR => v_a[i] != v_b[i],
BinOp::NOR => v_a[i] == v_b[i],
}
);
}
v_result
}
pub fn calculate_fitness_result(v_result: &Vec<bool>, v_tested: &Vec<bool>) -> i32 {
assert_eq!(v_result.len(), v_tested.len());
let mut fitness = 0;
for i in 0..v_result.len() {
if v_result[i] == v_tested[i] {
fitness += 1;
}
}
fitness
}
fn increment_bitvector(bitvector: &mut Vec<bool>) {
for i in 0..bitvector.len() {
if !bitvector[i] {
bitvector[i] = true;
for j in 0..i {
bitvector[j] = false;
}
return;
}
}
panic!("bitvector overflow");
}
pub fn get_null_bitvector(vector_size: usize) -> Vec<bool> {
let mut v: Vec<bool> = Vec::with_capacity(vector_size);
for _i in 0..vector_size {
v.push(false);
}
v
}
pub fn get_rand_bitvector(vector_size: usize) -> Vec<bool> {
let mut v: Vec<bool> = Vec::with_capacity(vector_size);
for _i in 0..vector_size {
v.push(
if rand::thread_rng().gen_range(0, 2) > 0 {
true
} else {
false
}
);
}
v
}
pub fn print_bitvector(v: &Vec<bool>) {
for &i in v {
let bit_str : &str = if i {
"1"
} else {
"0"
};
print!("{} ", bit_str);
}
println!("");
}
fn print_limited_bitvector(v: &Vec<bool>, max: usize) {
for i in 0..v.len() {
print!("{} ", if v[i] {
"1"
} else {
"0"
});
if i > max {
print!("...({} bits)", v.len());
break;
}
}
println!("");
}