use std::fs::File;
use std::io::{self, BufRead};
use std::path::Path;
use std::time::Instant;
use mimalloc::MiMalloc;
use smallvec::SmallVec;
#[global_allocator]
static GLOBAL: MiMalloc = MiMalloc;
fn main() {
// We iterate through all R(K4, J5, 18), add a vertex without any edges to each graph (simulating a degree-18 vertex in the dual), and vertex extend
if let Ok(lines) = read_lines("./rk4j5_18.g6") {
lines.flatten().for_each(|line| {
let now = Instant::now();
let graph= decode_g6(line);
let n = graph.len();
vertex_extend(vec![[0u32, (1 << n) - 1]], &max_subgraph(&graph, n), &graph, n);
let elapsed = now.elapsed();
println!("Elapsed: {:.3?}", elapsed);
});
}
// The largest graph size generated was 24.
}
/////////////////////////////////////////
#[inline]
fn read_lines
(filename: P) -> io::Result>>
where P: AsRef, {
let file = File::open(filename)?;
Ok(io::BufReader::new(file).lines())
}
/////////////////////////////////////////
enum SubGraph {
Triangle(u32),
IndSet(u32),
IndJ(u32),
}
#[inline(always)]
fn value(sub_graph: &SubGraph) -> u32 {
match sub_graph {
SubGraph::Triangle(val) => *val,
SubGraph::IndSet(val) => *val,
SubGraph::IndJ(val) => *val,
}
}
/////////////////////////////////////////
#[inline(always)]
fn bit_to_vect_3(mut x: u32) -> SmallVec::<[u32; 3]> {
let mut bit_vect = SmallVec::<[u32; 3]>::new();
for _i in 0..x.count_ones() {
let pw = 1 << x.ilog2();
bit_vect.push(pw);
x ^= pw;
}
bit_vect
}
#[inline(always)]
fn bit_to_vect_4(mut x: u32) -> SmallVec::<[u32; 4]> {
let mut bit_vect = SmallVec::<[u32; 4]>::new();
for _i in 0..x.count_ones() {
let pw = 1 << x.ilog2();
bit_vect.push(pw);
x ^= pw;
}
bit_vect
}
#[inline(always)]
fn bit_to_vect_5(mut x: u32) -> SmallVec::<[u32; 5]> {
let mut bit_vect = SmallVec::<[u32;5]>::new();
for _i in 0..x.count_ones() {
let pw = 1 << x.ilog2();
bit_vect.push(pw);
x ^= pw;
}
bit_vect
}
#[inline(always)]
fn bit_to_index(mut x: u32) -> Vec {
let num_ones = x.count_ones() as usize;
let mut index_vect = Vec::with_capacity(num_ones);
for _i in 0..num_ones {
let index = x.ilog2() as usize;
index_vect.push(index + 1);
x ^= 1 << index;
}
index_vect
}
fn expand_intervals(intervals: &mut [[u32; 2]], n: usize) -> Vec{
let mut expanded = vec![];
for interval in intervals.iter_mut() {
let mut insert = bit_to_index((interval[0] | !interval[1]) & ((1 << n) - 1));
insert.reverse();
for mut i in 0..1<<(n - insert.len()) {
for index in insert.iter(){
i = (i >> (index - 1) << index) | (i & ((1 << (index - 1)) - 1));
}
expanded.push(i | interval[0]);
}
interval[0] <<= 1;
interval[1] = (interval[1] << 1) + 1;
}
expanded
}
/////////////////////////////////////////
fn decode_g6(line: String) -> Vec {
let line_vec = &line.into_bytes()[..];
let num_vertices = line_vec[0] - 63;
let size = u16::from(num_vertices) * (u16::from(num_vertices) - 1) / 2;
let mut bit_vect: Vec = vec![0; (size + 6).into()];
let mut i = 0;
let mut fixed_letter;
for letter in line_vec[1..].iter() {
fixed_letter = letter - 63;
for bit_place in (0..6).rev() {
bit_vect[i] = (fixed_letter & (1 << bit_place)) >> bit_place;
i += 1;
}
}
let mut graph: Vec = vec![0; num_vertices.into()];
i = 0;
for column in 1..num_vertices {
for row in 0..column {
graph[usize::from(row)] |= u32::from(bit_vect[i]) << (num_vertices - column - 1);
graph[usize::from(column)] |= u32::from(bit_vect[i]) << (num_vertices - row - 1);
i += 1;
}
}
graph.insert(0, 0); // Attach a vertex with degree 18 in the dual
graph
}
/////////////////////////////////////////
fn max_clique(r: &mut u32, p: &mut u32, x: &mut u32, max_subgraphs: &mut Vec, graph: &Vec, n: usize) {
if *p == 0 && *x == 0 {
if r.count_ones() == 3 {
max_subgraphs.push(SubGraph::Triangle(*r));
}
return;
}
for index in bit_to_index(*p & !graph[n - ((*p | *x).ilog2() as usize) - 1]) {
let neighbors = graph[n - index];
let pointer = 1 << (index - 1);
max_clique(&mut (*r | pointer), &mut (*p & neighbors), &mut (*x & neighbors), max_subgraphs, graph, n);
*p &= !pointer;
*x |= pointer;
}
}
fn max_set(r: &mut u32, p: &mut u32, x: &mut u32, max_subgraphs: &mut Vec, max_sets_4: &mut Vec, graph: &Vec, n: usize) {
if *p == 0 && *x == 0 {
let num_vertices = r.count_ones();
if num_vertices == 5 {
max_subgraphs.push(SubGraph::IndSet(*r));
} else if num_vertices == 4 {
for max_set_4 in max_sets_4.iter() {
if (*r & max_set_4).count_ones() == 3 {
max_subgraphs.push(SubGraph::IndJ(*r | max_set_4));
}
}
max_sets_4.push(*r);
}
return;
}
let pivot = (*p | *x).ilog2() as usize;
for index in bit_to_index(*p & (graph[n - pivot - 1] | (1 << pivot))) {
let pointer = 1 << (index - 1);
let neighbors = !graph[n - index] ^ pointer;
max_set(&mut (*r | pointer), &mut (*p & neighbors), &mut (*x & neighbors), max_subgraphs, max_sets_4, graph, n);
*p &= !pointer;
*x |= pointer;
}
}
fn max_subgraph(graph: &Vec, n: usize) -> Vec{
let mut max_subgraphs = vec![];
max_clique(&mut 0, &mut ((1 << n) - 1), &mut 0, &mut max_subgraphs, graph, n);
max_set(&mut 0, &mut ((1 << n) - 1), &mut 0, &mut max_subgraphs, &mut vec![], graph, n);
max_subgraphs.sort_by_key(value);
max_subgraphs
}
fn max_subgraph_last(graph: &Vec, n: usize) -> Vec{
let mut max_subgraphs = vec![];
max_clique(&mut 1, &mut (graph[n - 1].clone()), &mut 0, &mut max_subgraphs, graph, n);
max_set(&mut 0, &mut ((1 << n) - 1), &mut 0, &mut max_subgraphs, &mut vec![], graph, n);
max_subgraphs.retain(|subgraph| value(subgraph) & 1 == 1);
max_subgraphs.sort_by_key(value); //special
max_subgraphs
}
/////////////////////////////////////////
fn vertex_extend(mut intervals: Vec<[u32; 2]>, max_subgraphs: &[SubGraph], graph: &[u32], n: usize) {
for subgraph in max_subgraphs.iter() {
match subgraph {
SubGraph::Triangle(val) => {
let mut new_intervals: Vec<[u32; 2]> = Vec::with_capacity(intervals.len() * 2);
for [bottom, top] in intervals.into_iter() {
if val & top == *val {
let diff = bit_to_vect_3(val & !bottom);
let diff_len = diff.len();
if diff_len >= 1 {
new_intervals.push([bottom, top & !diff[0]]);
}
if diff_len >= 2 {
new_intervals.push([bottom | diff[0], top & !diff[1]]);
}
if diff_len == 3 {
new_intervals.push([bottom | diff[0] | diff[1], top & !diff[2]]);
}
} else {
new_intervals.push([bottom, top]);
}
}
intervals = new_intervals;
},
SubGraph::IndSet(val) => {
let mut new_intervals: Vec<[u32; 2]> = Vec::with_capacity(intervals.len() * 3);
for [bottom, top] in intervals.into_iter() {
let count = (val & bottom).count_ones();
if count == 0 {
let inter = bit_to_vect_5(val & top);
let inter_len = inter.len();
if inter_len >= 2 {
new_intervals.push([bottom | inter[0] | inter[1], top]);
}
if inter_len >= 3 {
new_intervals.push([bottom | inter[0] | inter[2], top & !inter[1]]);
new_intervals.push([bottom | inter[1] | inter[2], top & !inter[0]]);
}
if inter_len >= 4 {
new_intervals.push([bottom | inter[0] | inter[3], top & !(inter[1] | inter[2])]);
new_intervals.push([bottom | inter[1] | inter[3], top & !(inter[0] | inter[2])]);
new_intervals.push([bottom | inter[2] | inter[3], top & !(inter[0] | inter[1])]);
}
if inter_len == 5 {
new_intervals.push([bottom | inter[0] | inter[4], top & !(inter[1] | inter[2] | inter[3])]);
new_intervals.push([bottom | inter[1] | inter[4], top & !(inter[0] | inter[2] | inter[3])]);
new_intervals.push([bottom | inter[2] | inter[4], top & !(inter[0] | inter[1] | inter[3])]);
new_intervals.push([bottom | inter[3] | inter[4], top & !(inter[0] | inter[1] | inter[2])]);
}
} else if count == 1 {
let inter = bit_to_vect_4(val & top & !bottom);
let inter_len = inter.len();
if inter_len >= 1 {
new_intervals.push([bottom | inter[0], top]);
}
if inter_len >= 2 {
new_intervals.push([bottom | inter[1], top & !inter[0]]);
}
if inter_len >= 3 {
new_intervals.push([bottom | inter[2], top & !(inter[0] | inter[1])]);
}
if inter_len == 4 {
new_intervals.push([bottom | inter[3], top & !(inter[0] | inter[1] | inter[2])]);
}
} else {
new_intervals.push([bottom, top]);
}
}
intervals = new_intervals;
},
SubGraph::IndJ(val) => {
let mut new_intervals: Vec<[u32; 2]> = Vec::with_capacity(intervals.len() * 2);
for [bottom, top] in intervals.into_iter() {
if val & bottom == 0 {
let inter = bit_to_vect_5(val & top);
let inter_len = inter.len();
if inter_len >= 1 {
new_intervals.push([bottom | inter[0], top]);
}
if inter_len >= 2 {
new_intervals.push([bottom | inter[1], top & !inter[0]]);
}
if inter_len >= 3 {
new_intervals.push([bottom | inter[2], top & !(inter[0] | inter[1])]);
}
if inter_len >= 4 {
new_intervals.push([bottom | inter[3], top & !(inter[0] | inter[1] | inter[2])]);
}
if inter_len == 5 {
new_intervals.push([bottom | inter[4], top & !(inter[0] | inter[1] | inter[2] | inter[3])]);
}
} else {
new_intervals.push([bottom, top]);
}
}
intervals = new_intervals;
},
}
}
if !intervals.is_empty() {
let expanded = expand_intervals(&mut intervals, n);
for gluing in expanded {
let mut new_graph = Vec::with_capacity(n + 1);
for (i, row) in graph.iter().enumerate().take(n) {
new_graph.push((row << 1) | ((gluing & (1 << (n - i - 1))) >> (n - i - 1)));
}
new_graph.push(gluing << 1);
if n >= 24 {
println!("{}, {:?},", new_graph.len(), new_graph); // Print graphs with size greater than 24
}
vertex_extend(intervals.clone(), &max_subgraph_last(&new_graph, n + 1), &new_graph, n + 1);
}
}
}
/////////////////////////////////////////