Solution for closest string 2

This commit is contained in:
hal8174 2025-01-13 20:45:28 +01:00
parent 162759abcb
commit 8c1aa032d5
13 changed files with 511707 additions and 54 deletions

View file

@ -1,8 +1,13 @@
use std::path::{Path, PathBuf};
use std::{
collections::HashMap,
path::{Path, PathBuf},
};
use clap::Parser;
use gurobi::*;
use expr::LinExpr;
use grb::*;
use itertools::Itertools;
use ModelSense::Minimize;
fn read_input(filename: impl AsRef<Path>) -> Vec<Vec<u8>> {
let text = std::fs::read_to_string(filename).unwrap();
@ -19,9 +24,10 @@ fn read_input(filename: impl AsRef<Path>) -> Vec<Vec<u8>> {
#[derive(Debug, Parser)]
struct Args {
filename: PathBuf,
outfilename: PathBuf,
}
fn solve(input: &[Vec<u8>], d: usize) {
fn solve(input: &[Vec<u8>]) -> String {
let mut columns = Vec::new();
for i in 0..input[0].len() {
@ -42,59 +48,77 @@ fn solve(input: &[Vec<u8>], d: usize) {
let counts = columns.iter().counts();
let env = Env::new("logfile.log").unwrap();
let mut model = Model::new("model1").unwrap();
let mut model = Model::new("model1", &env).unwrap();
let mut variables = HashMap::new();
let mut variables = Vec::new();
for (k, &c) in &counts {
for (&k, &c) in &counts {
let mut v = Vec::new();
let mut sum = LinExpr::new();
let mut sum = Expr::Linear(LinExpr::new());
for i in 0..=(k.iter().max().copied().unwrap()) {
let var = model
.add_var(
&format!("{:?}:{}", k, i),
Integer,
0.0,
-INFINITY,
INFINITY,
&[],
&[],
)
.unwrap();
let var = add_intvar!(model, name: &format!("{:?}:{}", k, i), bounds: 0..).unwrap();
sum = sum + &var;
sum = sum + var;
v.push(var);
}
model
.add_constr(&format!("{:?}", k), sum, Equal, c as f64)
.unwrap();
variables.push(v);
model.add_constr(&format!("{:?}", k), c!(sum == c)).unwrap();
variables.insert(k, v);
}
for i in 0..input.len() {
let mut sum = LinExpr::new();
let d = add_intvar!(model, name: "D", bounds: 0..).unwrap();
for (l, (k, _)) in counts.iter().enumerate() {
for j in 0..input.len() {
if k[i] != k[j] {
sum = sum + &variables[l][k[j] as usize];
for i in 0..input.len() {
let mut sum = Expr::Linear(LinExpr::new());
for &k in counts.keys() {
for j in 0..=*k.iter().max().unwrap() {
if k[i] != j {
sum = sum + variables[k][j as usize];
}
}
}
model
.add_constr(&format!("{:?}", i), sum, Less, d as f64)
.unwrap();
model.add_constr(&format!("{:?}", i), c!(sum <= d)).unwrap();
}
model.set_objective(d, Minimize).unwrap();
model.update().unwrap();
// model.write("test.lp").unwrap();
model.optimize().unwrap();
dbg!(model.status().unwrap());
// for vars in &variables {
// for v in vars {
// dbg!(model.get_obj_attr(attr::X, v).unwrap());
// }
// }
let mut result = String::new();
for (i, col) in columns.iter().enumerate() {
let t = model
.get_obj_attr_batch(attr::X, variables[col].clone())
.unwrap();
let mut p = columns[0..i].iter().filter(|&c| c == col).count();
let mut j = 0;
while t[j] as usize <= p {
p -= t[j] as usize;
j += 1;
}
let l = col.iter().position(|&c| c as usize == j).unwrap();
// dbg!(i, col, t, j, l, char::from_u32(input[l][i] as u32).unwrap());
result.push(char::from_u32(input[l][i] as u32).unwrap());
}
result
}
fn main() {
@ -102,5 +126,7 @@ fn main() {
let input = read_input(args.filename);
solve(&input, 6);
let r = solve(&input);
std::fs::write(args.outfilename, r).unwrap();
}