in meta/src/main/java/org/arend/lib/meta/equation/MonoidSolver.java [430:539]
public ConcreteExpression solve(CompiledTerm term1, CompiledTerm term2, List<Equality> axioms) {
int alphabetSize = term1.nf.isEmpty() ? 0 : Collections.max(term1.nf) + 1;
alphabetSize = term2.nf.isEmpty() ? alphabetSize : Integer.max(alphabetSize, Collections.max(term2.nf) + 1);
for (Equality axiom : axioms) {
if (!axiom.lhsNF.isEmpty()) {
alphabetSize = Integer.max(alphabetSize, Collections.max(axiom.lhsNF) + 1);
}
if (!axiom.rhsNF.isEmpty()) {
alphabetSize = Integer.max(alphabetSize, Collections.max(axiom.rhsNF) + 1);
}
}
var word1Pow = ComMonoidWP.elemsSeqToPowersSeq(term1.nf, alphabetSize);
var word2Pow = ComMonoidWP.elemsSeqToPowersSeq(term2.nf, alphabetSize);
List<Pair<List<Integer>, List<Integer>>> axiomsPow = new ArrayList<>();
for (Equality axiom : axioms) {
axiomsPow.add(new Pair<>(ComMonoidWP.elemsSeqToPowersSeq(axiom.lhsNF, alphabetSize), ComMonoidWP.elemsSeqToPowersSeq(axiom.rhsNF, alphabetSize)));
}
var wpAlgorithm = new ComMonoidWP(new GroebnerIM(new Buchberger()));
var axiomsToApply = wpAlgorithm.solve(word1Pow, word2Pow, axiomsPow);
List<Integer> curWord = new ArrayList<>(term1.nf);
if (axiomsToApply == null) return null;
ConcreteExpression proofTerm = null;
for (Pair<Integer, Boolean> axiom : axiomsToApply) {
var equalityToApply = axioms.get(axiom.proj1);
var isDirect = axiom.proj2;
var powsToRemove = isDirect ? axiomsPow.get(axiom.proj1).proj1 : axiomsPow.get(axiom.proj1).proj2;
var rhsNF = isDirect ? equalityToApply.rhsNF : equalityToApply.lhsNF;
var lhsTerm = isDirect ? equalityToApply.lhsTerm : equalityToApply.rhsTerm;
var rhsTerm = isDirect ? equalityToApply.rhsTerm : equalityToApply.lhsTerm;
ConcreteExpression rhsTermNF = computeNFTerm(rhsNF);
ConcreteExpression nfProofTerm = equalityToApply.binding; // factory.ref(equalityToApply.binding);
if (!isDirect) {
nfProofTerm = factory.app(factory.ref(meta.ext.inv.getRef()), true, singletonList(nfProofTerm));
}
//if (!isNF(equalityToApply.lhsTerm) || !isNF(equalityToApply.rhsTerm)) {
nfProofTerm = factory.appBuilder(factory.ref(meta.commTermsEqConv.getRef()))
.app(factory.ref(dataRef), false)
.app(lhsTerm)
.app(rhsTerm)
.app(nfProofTerm)
.build();
//}
var indexesToReplace = ComMonoidWP.findIndexesToRemove(curWord, powsToRemove);
var subwordToReplace = new ArrayList<Integer>();
var newWord = new ArrayList<>(curWord);
for (Integer integer : indexesToReplace) {
subwordToReplace.add(newWord.get(integer));
newWord.remove(integer.intValue());
}
int prefix = 0;
for (int i = 0; i < indexesToReplace.size(); ++i) {
int ind = indexesToReplace.get(i);
indexesToReplace.set(i, ind + i - prefix);
prefix = ind + i + 1;
}
for (int i = rhsNF.size() - 1; i >= 0; --i) {
newWord.add(0, rhsNF.get(i));
}
if (subwordToReplace.size() > 1) {
ConcreteExpression sortProofLeft = factory.appBuilder(factory.ref(meta.sortDef.getRef())).app(computeNFTerm(subwordToReplace)).build();
nfProofTerm = factory.app(factory.ref(meta.ext.concat.getRef()), true, Arrays.asList(sortProofLeft, nfProofTerm));
}
ConcreteExpression sortProofRight = factory.appBuilder(factory.ref(meta.sortDef.getRef())).app(rhsTermNF).build();
sortProofRight = factory.app(factory.ref(meta.ext.inv.getRef()), true, singletonList(sortProofRight));
nfProofTerm = factory.app(factory.ref(meta.ext.concat.getRef()), true, Arrays.asList(nfProofTerm, sortProofRight));
ConcreteExpression stepProofTerm = factory.appBuilder(factory.ref(meta.commReplaceDef.getRef()))
.app(factory.ref(dataRef), false)
.app(computeNFTerm(curWord))
.app(computeNFTerm(indexesToReplace))
.app(rhsTermNF)
.app(nfProofTerm)
.build();
if (proofTerm == null) {
proofTerm = stepProofTerm;
} else {
proofTerm = factory.app(factory.ref(meta.ext.concat.getRef()), true, Arrays.asList(proofTerm, stepProofTerm));
}
curWord = newWord;
}
if (proofTerm == null) {
proofTerm = factory.ref(meta.ext.prelude.getIdp().getRef());
} else {
ConcreteExpression sortProof = factory.appBuilder(factory.ref(meta.sortDef.getRef())).app(computeNFTerm(curWord)).build();
proofTerm = factory.app(factory.ref(meta.ext.concat.getRef()), true, Arrays.asList(proofTerm, sortProof));
}
return factory.appBuilder(factory.ref(meta.commTermsEq.getRef()))
.app(factory.ref(dataRef), false)
.app(term1.concrete)
.app(term2.concrete)
.app(proofTerm)
.build();
}