use clingo::*;
use std::env;
pub struct OnStatementData<'a, 'b> {
atom: &'b ast::Term<'b>,
control: &'a mut Control,
}
impl<'a, 'b> StatementHandler for OnStatementData<'a, 'b> {
fn on_statement(&mut self, stm: &ast::Statement) -> bool {
let mut builder = ast::ProgramBuilder::from(self.control).unwrap();
match stm.statement_type() {
ast::StatementType::Rule(rule) => {
let body = rule.body();
let mut extended_body = std::vec::Vec::with_capacity(body.len() + 1);
for e in body {
extended_body.push(e.clone());
}
let lit = ast::Literal::from_term(ast::Sign::None, &self.atom);
let blit = ast::BodyLiteral::from_literal(ast::Sign::None, &lit);
extended_body.push(blit);
let head = rule.head();
let rule = ast::Rule::new(*head, &extended_body);
let stm2 = rule.ast_statement();
builder
.add(&stm2)
.expect("Failed to add statement to ProgramBuilder.");
true
}
_ => {
builder
.add(stm)
.expect("Failed to add statement to ProgramBuilder.");
true
}
}
}
}
fn print_model(model: &Model) {
let atoms = model
.symbols(ShowType::SHOWN)
.expect("Failed to retrieve symbols in the model.");
print!("Model:");
for atom in atoms {
print!(" {}", atom.to_string().unwrap());
}
println!();
}
fn solve(ctl: &mut Control) {
let mut handle = ctl
.solve(SolveMode::YIELD, &[])
.expect("Failed retrieving solve handle.");
loop {
handle.resume().expect("Failed resume on solve handle.");
match handle.model() {
Ok(Some(model)) => print_model(model),
Ok(None) => break,
Err(e) => panic!("Error: {}", e),
}
}
handle
.get()
.expect("Failed to get result from solve handle.");
handle.close().expect("Failed to close solve handle.");
}
fn main() {
let options = env::args().skip(1).collect();
let mut ctl = Control::new(options).expect("Failed creating Control.");
let sym = Symbol::create_id("enable", true).unwrap();
{
let mut data = OnStatementData {
atom: &ast::Term::from(sym),
control: &mut ctl,
};
parse_program("a :- not b. b :- not a.", &mut data)
.expect("Failed to parse logic program.");
let ext = ast::External::new(ast::Term::from(sym), &[]);
let mut builder = ast::ProgramBuilder::from(&mut ctl).unwrap();
let stm = ext.ast_statement();
builder
.add(&stm)
.expect("Failed to add statement to ProgramBuilder.");
builder.end().expect("Failed to finish building a program.");
}
let part = Part::new("base", &[]).unwrap();
let parts = vec![part];
ctl.ground(&parts)
.expect("Failed to ground a logic program.");
let atoms = ctl.symbolic_atoms().unwrap();
let mut atm_it = atoms.iter().unwrap();
let item = atm_it.find(|e| e.symbol().unwrap() == sym).unwrap();
let atm = item.literal().unwrap();
println!("Solving with enable = false...");
solve(&mut ctl);
println!("Solving with enable = true...");
ctl.assign_external(atm, TruthValue::True)
.expect("Failed to assign #external enable true.");
solve(&mut ctl);
println!("Solving with enable = false...");
ctl.assign_external(atm, TruthValue::False)
.expect("Failed to assign #external enable false.");
solve(&mut ctl);
}