Newer
Older
RDLProofSystem / src / main / java / inference / ProofSystem.java
@Sakoda2269 Sakoda2269 5 days ago 13 KB map compositionの推論を作成
package inference;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
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.DependencyTerm;
import models.terms.EvaluatableTerm;
import models.terms.RDLTerm;
import models.terms.Resource;
import models.terms.ResourceConstant;
import models.terms.meta.MetaEvaluatableTermVariable;
import models.terms.meta.OrderConstraint;
import utils.Permutation;
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 constantMapping1 = new InferenceRule(
			"Constant Mapping",
			List.of(),
			new MetaDependencyFormula(
					new MetaEvaluatableTermVariable(new Variable("se"), new Variable("n")),
					new MetaEvaluatableTermVariable(new Variable("te"), new Variable("m"))
			),
			new InferenceOrderConstraint(new Variable("n"), OrderConstraint.LT, new Variable("m"))
	); 
	
	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,
			constantMapping1,
			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,
			constantMapping1,
			uncurriedMapping,
			dependencyExtension
	);
	
	private Set<? extends Formula> assumptions;
	private Formula conclusion;
	@Getter
	private ProofState state;
	
	
	public ProofSystem(Set<? extends Formula> assumptions, Formula conclusion) {
		this(assumptions, conclusion, Set.of());
	}
	
	public ProofSystem(Set<? extends Formula> assumptions, Formula conclusion, Set<Resource> existResources) {
		state = new ProofState(assumptions);
		this.assumptions = assumptions;
		this.conclusion = conclusion;
		state.getEvaluatableTerms().addAll(existResources);
		checkDefinitionFormulaFormat();
	}
	
	private void checkDefinitionFormulaFormat() {
		Set<EvaluatableTerm> leftSideHands = new HashSet<>(assumptions.stream()
					.filter(f -> f instanceof EquationFormula)
					.map(v -> ((EquationFormula) v).getLeftHandSide())
					.toList());
		for (EvaluatableTerm te: leftSideHands) {
			if (te instanceof Resource | te instanceof ResourceConstant) {
				throw new IllegalArgumentException("Resource or ResourceConstant can't be placed left-hand side.");
			}
			Set<Dependency> dependencies = state.getDependencies();
			DependencyTerm dt = (DependencyTerm) te;
			Set<Dependency> requiredDependencies = dt.requiredDependenciesForAdmissible();
			requiredDependencies.retainAll(dependencies);
			if (requiredDependencies.isEmpty()) {
				for (Dependency d: dt.requiredDependenciesForAdmissible()) {
					if (! dependencyInference(new DependencyFormula(d))) {
						throw new IllegalArgumentException(dt.toString() + "is not definition formula format.");
					}
				}
			}
		}
	}
	
	public void inference() {
		if (conclusion instanceof DependencyFormula) {
			dependencyInference();
			return;
		}
		EquationFormula conclusion = (EquationFormula) this.conclusion;
		DependencyTerm dt = (DependencyTerm) conclusion.getLeftHandSide();
		DependencyFormula df = new DependencyFormula(dt.getNoArgumentDependency());
		dependencyInference(df);
		List<InferenceHistoryNode> inferenceHisotries = this.state.getHistory().getHistoryByBFS(df);
//		Collections.reverse(inferenceHisotry);
		Set<EvaluatableTerm> curTerms = new HashSet<>();
		curTerms.add(conclusion.getLeftHandSide());
		for (InferenceHistoryNode history: inferenceHisotries) {
			Set<EvaluatableTerm> nextTerms = new HashSet<>();
			for (EvaluatableTerm curTerm: curTerms) {
				Set<EvaluatableTerm> inferenceRes = new HashSet<>();
				if (history.getUsedRule() == compositeMapping) {
					inferenceRes = applyAxiom(new HashSet<>(history.getAssumptions()), curTerm, mapComposition);
				}
				for (EvaluatableTerm te: inferenceRes) {
					for (EquationFormula eq: state.getDefinitionFormulas()) {
						nextTerms.addAll(applyAxiom(Set.of(eq, new DependencyFormula(te.getDependency())), te, rightSubstitution));
						nextTerms.addAll(applyAxiom(Set.of(eq), te, leftSubstitution));
					}
				}
			}
			curTerms = nextTerms;
		}
		applyTransitivity();
	}
	
	private Set<EvaluatableTerm> applyAxiom (Set<Formula> assumptions, EvaluatableTerm term, EquationAxiom axiom) {
		Set<EvaluatableTerm> res = new HashSet<>();
		for (List<Formula> perm: Permutation.permutation(assumptions, assumptions.size())) {
			for (EvaluatableTerm rsh: axiom.apply(perm, term)) {
				res.add(rsh);
				state.addHistory(perm, axiom, new EquationFormula(term, rsh));
				state.addFormuals(Set.of(new EquationFormula(term, rsh)));
			}
		}
		return res;
	}
	
	private void applyTransitivity() {
		Set<EquationFormula> eq = new HashSet<>(state.getEquationFormulas());
		Map<EquationFormula, Set<EquationFormula>> used = new HashMap<>();
		while (true) {
			Set<EquationFormula> derived = new HashSet<>();
			for (EquationFormula eq1: eq) {
				for (EquationFormula eq2: eq) {
					if (used.computeIfAbsent(eq1, k -> new HashSet<>()).contains(eq2)) {
						continue;
					}
					used.computeIfAbsent(eq1, k -> new HashSet<>()).add(eq2);
					Set<Formula> formulas = transitivity.derive(List.of(eq1, eq2));
					for (Formula f: formulas) {
						derived.add((EquationFormula) f);
						state.addHistory(List.of(eq1, eq2), transitivity, f);
					}
				}
			}
			if (derived.isEmpty()) {
				break;
			}
			eq.addAll(derived);
		}
		
	}
	
	public String getInferenceHistoryString() {
		return state.getHistory().getHistoryString(conclusion);
	}
	
	public boolean dependencyInference() {
		return dependencyInference(this.conclusion);
	}
	
	public boolean dependencyInference(Formula conclusion) {
		if (conclusion instanceof EquationFormula eq) {
			RDLTerm lhs = eq.getLeftHandSide();
			RDLTerm rhs = eq.getRightHandSide();
			Dependency leftDependency = lhs.getDependency();
			Dependency rightDependency = rhs.getDependency();
			while((! state.getDependencies().contains(leftDependency)) && (! state.getDependencies().contains(rightDependency))) {
				state.addFormuals(dependencyInferenceStep());
			}
			return true;
		} 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.getDependency().getSize() >= df.getDependency().getSize()) {
						if (! state.getFormulas().contains(df)) {
							sizeConstraintOk.add(df);
						}
					}
				}
				if (sizeConstraintOk.size() == 0) {
					return false;
				}
				state.addFormuals(sizeConstraintOk);
			}
			return true;
		}
		return false;
	}
	
	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));
			}
			if (rule.getAssumptions().size() == 0) {
				result.addAll(dependencyDerive(List.of(), rule));
			} else {
				for (List<Formula> formulas: Product.product(matchedFormulas)) {
					result.addAll(dependencyDerive(formulas, rule));
				}
			}
		}
		return result;
	}
	
	private Set<DependencyFormula> dependencyDerive(List<Formula> assumptions, InferenceRule rule) {
		Set<DependencyFormula> result = new HashSet<>();
		for (Formula res: rule.derive(assumptions, state.getExistTerms())) {
			if (state.formulaExist(res)) continue;
			state.addHistory(assumptions, rule, res);
			if (res 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;
	}
	
	private void checkAdmissibility(DependencyTerm dt) {
		checkRequiredDependency(dt);
		checkMembership(dt);
	}
	
	private void checkRequiredDependency(DependencyTerm dt) {
	}
	
	private void checkMembership(DependencyTerm dt) {
	}
	
}