1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
use clingo::*;
use std::env;
fn print_prefix(depth: u8) {
println!();
for _ in 0..depth {
print!(" ");
}
}
// recursively print the configuartion object
fn print_configuration(conf: &Configuration, key: Id, depth: u8) {
// get the type of an entry and switch over its various values
let configuration_type = conf.configuration_type(key).unwrap();
match configuration_type {
// print values
ConfigurationType::VALUE => {
let value = conf
.value_get(key)
.expect("Failed to retrieve statistics value.");
println!("{}", value);
}
// print arrays
ConfigurationType::ARRAY => {
// loop over array elements
let size = conf
.array_size(key)
.expect("Failed to retrieve statistics array size.");
for i in 0..size {
// print array offset (with prefix for readability)
let subkey = conf
.array_at(key, i)
.expect("Failed to retrieve statistics array.");
print_prefix(depth);
print!("{}:", i);
// recursively print subentry
print_configuration(conf, subkey, depth + 1);
}
}
// print maps
ConfigurationType::MAP => {
// loop over map elements
let size = conf.map_size(key).unwrap();
for i in 0..size {
// get and print map name (with prefix for readability)
let name = conf.map_subkey_name(key, i).unwrap();
let subkey = conf.map_at(key, name).unwrap();
print_prefix(depth);
print!("{}:", name);
// recursively print subentry
print_configuration(conf, subkey, depth + 1);
}
}
// this case won't occur if the configuration are traversed like this
_ => {
let bla = conf.value_get(key).unwrap();
print!(" {}", bla);
// println!("Unknown ConfigurationType");
}
}
}
fn print_model(model: &Model) {
// retrieve the symbols in the model
let atoms = model
.symbols(ShowType::SHOWN)
.expect("Failed to retrieve symbols in the model.");
print!("Model:");
for atom in atoms {
// retrieve and print the symbol's string
print!(" {}", atom.to_string().unwrap());
}
println!();
}
fn solve(ctl: &mut Control) {
// get a solve handle
let mut handle = ctl
.solve(SolveMode::YIELD, &[])
.expect("Failed retrieving solve handle.");
// loop over all models
loop {
handle.resume().expect("Failed resume on solve handle.");
match handle.model() {
// print the model
Ok(Some(model)) => print_model(model),
// stop if there are no more models
Ok(None) => break,
Err(e) => panic!("Error: {}", e),
}
}
// close the solve handle
handle
.get()
.expect("Failed to get result from solve handle.");
handle.close().expect("Failed to close solve handle.");
}
fn main() {
// collect clingo options from the command line
let options = env::args().skip(1).collect();
// create a control object and pass command line arguments
let mut ctl = Control::new(options).expect("Failed creating Control.");
{
// get the configuration object and its root key
let conf = ctl.configuration_mut().unwrap();
let root_key = conf.root().unwrap();
print_configuration(conf, root_key, 0);
let mut sub_key;
// configure to enumerate all models
sub_key = conf.map_at(root_key, "solve.models").unwrap();
conf.value_set(sub_key, "0")
.expect("Failed to set solve.models to 0.");
// configure the first solver to use the berkmin heuristic
sub_key = conf.map_at(root_key, "solver").unwrap();
sub_key = conf.array_at(sub_key, 0).unwrap();
sub_key = conf.map_at(sub_key, "heuristic").unwrap();
conf.value_set(sub_key, "berkmin")
.expect("Failed to set heuristic to berkmin.");
}
// note that the solver entry can be used both as an array and a map
// if used as a map, this simply sets the configuration of the first solver and
// is equivalent to the code above
// add a logic program to the base part
ctl.add("base", &[], "a :- not b. b :- not a.")
.expect("Failed to add a logic program.");
// ground the base part
let part = Part::new("base", &[]).unwrap();
let parts = vec![part];
ctl.ground(&parts)
.expect("Failed to ground a logic program.");
// solve
solve(&mut ctl);
}