package inference;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import inference.axioms.ArgumentConstraint;
import inference.axioms.ArgumentExtension;
import inference.axioms.ArgumentReduction;
import inference.axioms.CompositeMapping;
import inference.axioms.ConstantMapping;
import inference.axioms.Constantness;
import inference.axioms.DependencyExtension;
import inference.axioms.Identity;
import inference.axioms.LeftSubstitution;
import inference.axioms.MapComposition;
import inference.axioms.PseudoConstantness;
import inference.axioms.RightSubstitution;
import inference.axioms.UncurriedMapping;
import inference.axioms.Uncurrying;
import lombok.Getter;
import models.algebra.Variable;
import models.formulas.DependencyFormula;
import models.formulas.EquationFormula;
import models.formulas.Formula;
import models.formulas.meta.MetaDependencyFormula;
import models.formulas.meta.MetaEquationFormula;
import models.terms.Dependency;
import models.terms.EvaluatableTerm;
import models.terms.RDLTerm;
import models.terms.meta.MetaEvaluatableTermVariable;
import utils.Product;
public class ProofSystem {
//======================Equality Axioms=============================
public static final EquationAxiom reflexivity = new EquationAxiom(
"Reflexivity",
List.of(),
new MetaEquationFormula(
new MetaEvaluatableTermVariable(new Variable("te")),
new MetaEvaluatableTermVariable(new Variable("te"))
)
);
public static final EquationAxiom symmetry = new EquationAxiom(
"Symmetry",
List.of(
new MetaEquationFormula(
new MetaEvaluatableTermVariable(new Variable("te")),
new MetaEvaluatableTermVariable(new Variable("se"))
)
),
new MetaEquationFormula(
new MetaEvaluatableTermVariable(new Variable("se")),
new MetaEvaluatableTermVariable(new Variable("te"))
)
);
public static final EquationAxiom transitivity = new EquationAxiom(
"Transitivity",
List.of(
new MetaEquationFormula(
new MetaEvaluatableTermVariable(new Variable("se")),
new MetaEvaluatableTermVariable(new Variable("te"))
),
new MetaEquationFormula(
new MetaEvaluatableTermVariable(new Variable("te")),
new MetaEvaluatableTermVariable(new Variable("ue"))
)
),
new MetaEquationFormula(
new MetaEvaluatableTermVariable(new Variable("se")),
new MetaEvaluatableTermVariable(new Variable("ue"))
)
);
public static final EquationAxiom rightSubstitution = new RightSubstitution();
public static final EquationAxiom leftSubstitution = new LeftSubstitution();
public static final EquationAxiom identity = new Identity();
public static final EquationAxiom mapComposition = new MapComposition();
//
public static final EquationAxiom constantness = new Constantness();
//
// public static final InferenceRule rightNormalization = new RightNormalization();
//
public static final EquationAxiom pseudoConstantness = new PseudoConstantness();
public static final EquationAxiom uncurrying = new Uncurrying();
//
// //======================Dependency Axioms=============================
//
public static final InferenceRule identityMapping = new InferenceRule(
"Identity Mapping",
List.of(
new MetaEquationFormula(
new MetaEvaluatableTermVariable(new Variable("te")),
new MetaEvaluatableTermVariable(new Variable("se"))
)
),
new MetaDependencyFormula(
new MetaEvaluatableTermVariable(new Variable("te")),
new MetaEvaluatableTermVariable(new Variable("se"))
)
);
public static final InferenceRule argumentExtension = new ArgumentExtension();
public static final InferenceRule argumentReduction = new ArgumentReduction();
public static final InferenceRule argumentConstraint = new ArgumentConstraint();
public static final InferenceRule compositeMapping = new CompositeMapping();
public static final InferenceRule constantMapping = new ConstantMapping();
public static final InferenceRule uncurriedMapping = new UncurriedMapping();
public static final InferenceRule dependencyExtension = new DependencyExtension();
public static final List<InferenceRule> axioms = List.of(
reflexivity,
symmetry,
transitivity,
rightSubstitution,
leftSubstitution,
identity,
mapComposition,
constantness,
pseudoConstantness,
uncurrying,
identityMapping,
argumentExtension,
argumentReduction,
compositeMapping,
constantMapping,
uncurriedMapping,
dependencyExtension
);
public static final List<EquationAxiom> equationAxioms = List.of(
reflexivity,
symmetry,
transitivity,
rightSubstitution,
leftSubstitution,
identity,
mapComposition,
constantness,
pseudoConstantness,
uncurrying
);
public static final List<InferenceRule> dependencyAxioms = List.of(
identityMapping,
argumentExtension,
argumentReduction,
compositeMapping,
constantMapping,
uncurriedMapping,
dependencyExtension
);
private Set<Formula> assumptions;
private Formula conclusion;
@Getter
private ProofState state;
public ProofSystem(Set<Formula> assumptions, Formula conclusion) {
state = new ProofState(assumptions);
this.assumptions = assumptions;
this.conclusion = conclusion;
}
public void inference() {
}
public void dependencyInference() {
if (conclusion instanceof EquationFormula eq) {
RDLTerm lhs = eq.getLeftSideHand();
RDLTerm rhs = eq.getRightSideHand();
Dependency leftDependency = lhs.getDependency();
Dependency rightDependency = rhs.getDependency();
while((! state.getDependencies().contains(leftDependency)) && (! state.getDependencies().contains(rightDependency))) {
state.addFormuals(dependencyInferenceStep());
}
} else if (conclusion instanceof DependencyFormula dep) {
while((! state.getDependencyFormulas().contains(dep))) {
Set<DependencyFormula> result = dependencyInferenceStep();
Set<DependencyFormula> sizeConstraintOk = new HashSet<>();
for (DependencyFormula df: result) {
if (dep.getMaxIndex() >= df.getMaxIndex()) {
if (! state.getFormulas().contains(df)) {
sizeConstraintOk.add(df);
}
}
}
if (sizeConstraintOk.size() == 0) {
break;
}
state.addFormuals(sizeConstraintOk);
}
}
}
public Set<DependencyFormula> dependencyInferenceStep() {
Set<DependencyFormula> result = new HashSet<>();
for (InferenceRule rule: dependencyAxioms) {
List<List<Formula>> matchedFormulas = new ArrayList<>();
for (Set<Formula> formulas: state.getMatchedFormulas().get(rule)) {
matchedFormulas.add(new ArrayList<>(formulas));
}
for (List<Formula> formulas: Product.product(matchedFormulas)) {
Set<Formula> results = rule.derive(formulas, state.getExistTerms());
for (Formula res: results) {
state.addHistory(formulas, rule, res);
}
for (Formula f: results) {
if (f instanceof DependencyFormula df) {
result.add(df);
}
}
}
}
return result;
}
public Set<Formula> equationInferenceStep() {
Set<Formula> result = new HashSet<>();
for (EquationAxiom rule: equationAxioms) {
List<List<Formula>> matchedFormulas = new ArrayList<>();
for (Set<Formula> formulas: state.getMatchedFormulas().get(rule)) {
matchedFormulas.add(new ArrayList<>(formulas));
}
for (EvaluatableTerm left: state.getMatchedTerms().get(rule).leftSideHands()) {
for (List<Formula> formulas: Product.product(matchedFormulas)) {
for (EvaluatableTerm right: rule.apply(formulas, left)) {
result.add(new EquationFormula(left, right));
state.addHistory(formulas, rule, new EquationFormula(left, right));
}
}
}
for (EvaluatableTerm right: state.getMatchedTerms().get(rule).rightSideHands()) {
for (List<Formula> formulas: Product.product(matchedFormulas)) {
for (EvaluatableTerm left: rule.apply(formulas, right)) {
result.add(new EquationFormula(left, right));
state.addHistory(formulas, rule, new EquationFormula(left, right));
}
}
}
}
return result;
}
}