Working MILP version of predicate splitter

This commit is contained in:
Rob Knight 2026-04-30 16:56:42 +01:00
parent e9e3241263
commit 2443f85520
No known key found for this signature in database
4 changed files with 705 additions and 600 deletions

View file

@ -399,6 +399,16 @@ pub enum SplittingError {
max_allowed: usize,
suggestion: Option<Box<RefactorSuggestion>>,
},
#[error("Could not split predicate '{predicate}' into a chain: no feasible partition exists with up to {max_links} links. \
The predicate's wildcard structure may be too dense for any chain to fit within max_statement_args ({max_statement_args}) \
and max_custom_predicate_wildcards ({max_wildcards}) per link.")]
Infeasible {
predicate: String,
max_links: usize,
max_statement_args: usize,
max_wildcards: usize,
},
}
impl From<ParseError> for LangError {

View file

@ -134,6 +134,18 @@ pub struct StatementTmpl {
pub span: Option<Span>,
}
impl StatementTmpl {
/// Names of all wildcards referenced by this statement's arguments,
/// in argument order with duplicates included.
pub fn wildcard_names(&self) -> impl Iterator<Item = &str> {
self.args.iter().filter_map(|arg| match arg {
StatementTmplArg::Wildcard(id) => Some(id.name.as_str()),
StatementTmplArg::AnchoredKey(ak) => Some(ak.root.name.as_str()),
StatementTmplArg::Literal(_) | StatementTmplArg::SelfPredicateHash(_) => None,
})
}
}
/// Reference to a predicate (local or qualified with module name)
#[derive(Debug, Clone, PartialEq)]
pub enum PredicateRef {

View file

@ -528,21 +528,9 @@ impl<'a> Lowerer<'a> {
names: &mut Vec<String>,
seen: &mut HashSet<String>,
) {
for arg in &stmt.args {
match arg {
StatementTmplArg::Wildcard(id) => {
if !seen.contains(&id.name) {
seen.insert(id.name.clone());
names.push(id.name.clone());
}
}
StatementTmplArg::AnchoredKey(ak) => {
if !seen.contains(&ak.root.name) {
seen.insert(ak.root.name.clone());
names.push(ak.root.name.clone());
}
}
StatementTmplArg::Literal(_) | StatementTmplArg::SelfPredicateHash(_) => {}
for name in stmt.wildcard_names() {
if seen.insert(name.to_string()) {
names.push(name.to_string());
}
}
}

File diff suppressed because it is too large Load diff