From dc2e70237385ebea6e93031149ce02778d674a99 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Sat, 8 Aug 2015 09:29:59 -0700 Subject: [PATCH] =?UTF-8?q?feat(library/unifier):=20generate=20approximate?= =?UTF-8?q?=20solution=20for=20universe=20constraints=20of=20the=20form=20?= =?UTF-8?q?(max=20u=20=3Fm=20=3D=3F=3D=20max=20u=20v)?= closes #777 --- src/library/unifier.cpp | 67 ++++++++++++++++++++++++++++++++++++--- tests/lean/hott/777.hlean | 6 ++++ 2 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 tests/lean/hott/777.hlean diff --git a/src/library/unifier.cpp b/src/library/unifier.cpp index 1e4f041f1..e72282dd6 100644 --- a/src/library/unifier.cpp +++ b/src/library/unifier.cpp @@ -2574,6 +2574,57 @@ struct unifier_fn { return try_merge_max_core(rhs, lhs, j); } + + static void get_max_args(level const & m, buffer & args) { + if (is_max(m)) { + get_max_args(max_lhs(m), args); + get_max_args(max_rhs(m), args); + } else { + args.push_back(m); + } + } + + static level mk_max_args(buffer const & args) { + lean_assert(!args.empty()); + level r = args[0]; + for (unsigned i = 1; i < args.size(); i++) + r = mk_max(r, args[i]); + return r; + } + + /** + Given a constraint of the form (or commutative variants) + max u t =?= max u v + reduce it to t =?= v + + \remark we may miss solutions since this is an approximation + + see issue #777 + */ + status try_max_max_cancel(constraint const & c) { + lean_assert(is_level_eq_cnstr(c)); + level const & lhs = cnstr_lhs_level(c); + level const & rhs = cnstr_rhs_level(c); + justification const & j = c.get_justification(); + if (is_max(lhs) && is_max(rhs)) { + buffer lhs_args, rhs_args; + get_max_args(lhs, lhs_args); + get_max_args(rhs, rhs_args); + for (level const & l : lhs_args) { + if (std::find(rhs_args.begin(), rhs_args.end(), l) != rhs_args.end()) { + lhs_args.erase_elem(l); + rhs_args.erase_elem(l); + constraint new_c = mk_level_eq_cnstr(mk_max_args(lhs_args), mk_max_args(rhs_args), j); + if (process_constraint(new_c)) + return Solved; + else + return Continue; + } + } + } + return Continue; + } + /** \brief Process the next constraint in the constraint queue m_cnstrs */ bool process_next() { lean_assert(!m_cnstrs.empty()); @@ -2604,16 +2655,24 @@ struct unifier_fn { st = process_succ_eq_max(c); if (st != Continue) return st == Solved; if (m_config.m_discard) { - // we only try try_level_eq_zero and try_merge_max when we are discarding - // constraints that canno be solved. + // we only try try_level_eq_zero, try_max_max_cancel and try_merge_max when we are discarding + // constraints that cannot be solved. st = try_level_eq_zero(c); - if (st != Continue) return st == Solved; + if (st != Continue) { + return st == Solved; + } if (cidx < get_group_first_index(cnstr_group::FlexFlex)) { add_cnstr(c, cnstr_group::FlexFlex); return true; } + st = try_max_max_cancel(c); + if (st != Continue) { + return st == Solved; + } st = try_merge_max(c); - if (st != Continue) return st == Solved; + if (st != Continue) { + return st == Solved; + } return process_plugin_constraint(c); } else { discard(c); diff --git a/tests/lean/hott/777.hlean b/tests/lean/hott/777.hlean new file mode 100644 index 000000000..803afd309 --- /dev/null +++ b/tests/lean/hott/777.hlean @@ -0,0 +1,6 @@ +namespace sum + definition code.{u v} {A : Type.{u}} {B : Type.{v}} : A + B → A + B → Type.{max u v} + | code (inl a) (inl a') := lift (a = a') + | code (inr b) (inr b') := lift (b = b') + | code _ _ := lift empty +end sum