Skip to content

Commit

Permalink
Major update and refactoring
Browse files Browse the repository at this point in the history
* Define Cauchy maps and lifts for them
* Prove that minimal Cauchy filters are regular
* Define completion of uniform spaces
* Refactor the structure of the hierarchy of space
* Refactor the field structure on real numbers
* Allow several actions in 'in' meta
* Introduce a hierarchy of continuous maps
* Prove some facts about metric spaces
* Define normed abelian groups
* Define topological abelian groups
* Define products of topological spaces, topological abelian groups, and uniform spaces
* Fix some bugs in linear solver
* Implement 'defaultImpl' meta
* Define 'Refines' relation for covers
* Define Hausdorff topological spaces
  • Loading branch information
valis committed May 26, 2024
1 parent 25f0f63 commit fb2aa23
Show file tree
Hide file tree
Showing 44 changed files with 2,283 additions and 1,203 deletions.
3 changes: 2 additions & 1 deletion meta/src/main/java/org/arend/lib/StdExtension.java
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ public void declareDefinitions(@NotNull DefinitionContributor contributor) {
Precedence.DEFAULT, new HidingMeta());
contributor.declare(meta, new LongName("run"), "`run { e_1, ... e_n }` is equivalent to `e_1 $ e_2 $ ... $ e_n`", Precedence.DEFAULT, new RunMeta(this));
contributor.declare(meta, new LongName("at"), "`((f_1, ... f_n) at x) r` replaces variable `x` with `f_1 (... (f_n x) ...)` and runs `r` in the modified context", new Precedence(Precedence.Associativity.NON_ASSOC, (byte) 1, true), new AtMeta(this));
contributor.declare(meta, new LongName("in"), "`f in x` is equivalent to `\\let r => f x \\in r`. It is usually used with `f` a meta such that `rewrite`, `simplify`, `simp_coe`, or `unfold`.", new Precedence(Precedence.Associativity.RIGHT_ASSOC, (byte) 1, true), new InMeta(this));
contributor.declare(meta, new LongName("in"), "`f in x` is equivalent to `\\let r => f x \\in r`. Also, `(f_1, ... f_n) in x` is equivalent to `f_1 in ... f_n in x`. This meta is usually used with `f` being a meta such as `rewrite`, `simplify`, `simp_coe`, or `unfold`.", new Precedence(Precedence.Associativity.RIGHT_ASSOC, (byte) 1, true), new InMeta(this));
casesMeta = new CasesMeta(this);
contributor.declare(meta, new LongName("cases"),
"""
Expand Down Expand Up @@ -216,6 +216,7 @@ public void declareDefinitions(@NotNull DefinitionContributor contributor) {
* `assumption` {n} returns the n-th variables from the context counting from the end.
* `assumption` {n} a1 ... ak applies n-th variable from the context to arguments a1, ... ak.
""", Precedence.DEFAULT, new AssumptionMeta(this));
contributor.declare(meta, new LongName("defaultImpl"), "`defaultImpl C F E` returns the default implementation of field `F` in class `C` applied to expression `E`. The third argument can be omitted, in which case either `\\this` or `_` will be used instead,", Precedence.DEFAULT, new DefaultImplMeta(this));

ModulePath paths = ModulePath.fromString("Paths.Meta");
contributor.declare(paths, new LongName("rewrite"),
Expand Down
88 changes: 88 additions & 0 deletions meta/src/main/java/org/arend/lib/meta/DefaultImplMeta.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package org.arend.lib.meta;

import org.arend.ext.concrete.ConcreteFactory;
import org.arend.ext.concrete.expr.ConcreteArgument;
import org.arend.ext.concrete.expr.ConcreteExpression;
import org.arend.ext.core.context.CoreBinding;
import org.arend.ext.core.definition.CoreClassDefinition;
import org.arend.ext.core.definition.CoreClassField;
import org.arend.ext.core.definition.CoreDefinition;
import org.arend.ext.core.expr.CoreAbsExpression;
import org.arend.ext.core.expr.CoreClassCallExpression;
import org.arend.ext.core.expr.CoreExpression;
import org.arend.ext.core.level.LevelSubstitution;
import org.arend.ext.core.ops.SubstitutionPair;
import org.arend.ext.error.TypecheckingError;
import org.arend.ext.reference.ArendRef;
import org.arend.ext.typechecking.BaseMetaDefinition;
import org.arend.ext.typechecking.ContextData;
import org.arend.ext.typechecking.ExpressionTypechecker;
import org.arend.ext.typechecking.TypedExpression;
import org.arend.lib.StdExtension;
import org.arend.lib.util.Utils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collections;
import java.util.List;

public class DefaultImplMeta extends BaseMetaDefinition {
private final StdExtension ext;

public DefaultImplMeta(StdExtension ext) {
this.ext = ext;
}

@Override
public boolean @Nullable [] argumentExplicitness() {
return new boolean[] { true, true };
}

@Override
public int @Nullable [] desugarArguments(@NotNull List<? extends ConcreteArgument> arguments) {
if (arguments.size() <= 2) {
return new int[] {};
} else {
int[] result = new int[arguments.size() - 2];
for (int i = 2; i < arguments.size(); i++) {
result[i - 2] = i;
}
return result;
}
}

@Override
public @Nullable TypedExpression invokeMeta(@NotNull ExpressionTypechecker typechecker, @NotNull ContextData contextData) {
var args = contextData.getArguments();
ArendRef ref1 = Utils.getReference(args.get(0).getExpression(), typechecker.getErrorReporter());
if (ref1 == null) return null;
ArendRef ref2 = Utils.getReference(args.get(1).getExpression(), typechecker.getErrorReporter());
if (ref2 == null) return null;
ConcreteExpression arg = args.size() >= 3 ? args.get(2).getExpression() : null;

CoreDefinition def1 = ext.definitionProvider.getCoreDefinition(ref1);
if (!(def1 instanceof CoreClassDefinition classDef)) {
typechecker.getErrorReporter().report(new TypecheckingError("Expected a class", args.get(0).getExpression()));
return null;
}
CoreDefinition def2 = ext.definitionProvider.getCoreDefinition(ref2);
if (!(def2 instanceof CoreClassField fieldDef)) {
typechecker.getErrorReporter().report(new TypecheckingError("Expected a field", args.get(1).getExpression()));
return null;
}

CoreAbsExpression expr = classDef.getDefault(fieldDef);
if (expr == null) {
typechecker.getErrorReporter().report(new TypecheckingError("The default value is not defined", contextData.getMarker()));
return null;
}

ConcreteFactory factory = ext.factory.withData(contextData.getMarker());
if (arg == null) {
CoreBinding binding = typechecker.getThisBinding();
arg = binding != null && binding.getTypeExpr() instanceof CoreClassCallExpression classCall && classCall.getDefinition().isSubClassOf(classDef) ? factory.ref(binding) : factory.hole();
}
CoreExpression result = typechecker.substitute(expr.getExpression(), LevelSubstitution.EMPTY, Collections.singletonList(new SubstitutionPair(expr.getBinding(), arg)));
return result == null ? null : args.size() <= 3 ? result.computeTyped() : typechecker.typecheck(factory.app(factory.core(result.computeTyped()), args.subList(3, args.size())), contextData.getExpectedType());
}
}
22 changes: 21 additions & 1 deletion meta/src/main/java/org/arend/lib/meta/InMeta.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package org.arend.lib.meta;

import org.arend.ext.concrete.ConcreteFactory;
import org.arend.ext.concrete.expr.ConcreteArgument;
import org.arend.ext.concrete.expr.ConcreteExpression;
import org.arend.ext.concrete.expr.ConcreteTupleExpression;
import org.arend.ext.typechecking.BaseMetaDefinition;
import org.arend.ext.typechecking.ContextData;
import org.arend.ext.typechecking.ExpressionTypechecker;
Expand All @@ -9,6 +12,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.List;

public class InMeta extends BaseMetaDefinition {
Expand All @@ -25,7 +29,23 @@ public boolean[] argumentExplicitness() {

@Override
public @Nullable TypedExpression invokeMeta(@NotNull ExpressionTypechecker typechecker, @NotNull ContextData contextData) {
ConcreteFactory factory = ext.factory.withData(contextData.getMarker());
List<? extends ConcreteArgument> args = contextData.getArguments();
return typechecker.typecheck(ext.factory.withData(contextData.getMarker()).app(args.get(0).getExpression(), args.subList(1, args.size())), null);
ConcreteExpression arg = args.get(0).getExpression();
if (arg instanceof ConcreteTupleExpression tuple && tuple.getFields().size() != 1) {
var fields = tuple.getFields();
if (fields.isEmpty()) {
return typechecker.typecheck(factory.app(args.get(1).getExpression(), args.subList(2, args.size())), null);
}
List<ConcreteArgument> newArgs = new ArrayList<>(args);
newArgs.set(0, factory.arg(fields.get(0), true));
ConcreteExpression result = factory.app(contextData.getReferenceExpression(), newArgs);
for (int i = 1; i < fields.size() - 1; i++) {
result = factory.app(contextData.getReferenceExpression(), true, fields.get(i), result);
}
return typechecker.typecheck(factory.app(contextData.getReferenceExpression(), true, fields.get(fields.size() - 1), result), null);
} else {
return typechecker.typecheck(factory.app(arg, args.subList(1, args.size())), null);
}
}
}
2 changes: 1 addition & 1 deletion meta/src/main/java/org/arend/lib/meta/UnfoldLetMeta.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public boolean allowExcessiveArguments() {
if (arg == null) {
return null;
}
return typechecker.replaceType(arg, arg.getType().normalize(NormalizationMode.RNF).unfold(Collections.emptySet(), null, true, false), contextData.getMarker());
return typechecker.replaceType(arg, arg.getType().normalize(NormalizationMode.RNF).unfold(Collections.emptySet(), null, true, false), contextData.getMarker(), false);
}
}
}
2 changes: 1 addition & 1 deletion meta/src/main/java/org/arend/lib/meta/UnfoldMeta.java
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public boolean allowExcessiveArguments() {
if (arg == null) {
return null;
}
result = typechecker.replaceType(arg, arg.getType().normalize(NormalizationMode.RNF).unfold(functions, unfolded, false, unfoldFields), contextData.getMarker());
result = typechecker.replaceType(arg, arg.getType().normalize(NormalizationMode.RNF).unfold(functions, unfolded, false, unfoldFields), contextData.getMarker(), false);
}

if (firstArgList != null && unfolded.size() != functions.size()) {
Expand Down
2 changes: 1 addition & 1 deletion meta/src/main/java/org/arend/lib/meta/UnfoldsMeta.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ private CoreExpression unfold(CoreExpression expr) {
return typechecker.typecheck(contextData.getArguments().get(contextData.getArguments().size() - 1).getExpression(), unfold(contextData.getExpectedType()));
} else {
TypedExpression arg = typechecker.typecheck(contextData.getArguments().get(contextData.getArguments().size() - 1).getExpression(), null);
return arg == null ? null : typechecker.replaceType(arg, unfold(arg.getType()), contextData.getMarker());
return arg == null ? null : typechecker.replaceType(arg, unfold(arg.getType()), contextData.getMarker(), true);
}
}
}
11 changes: 2 additions & 9 deletions meta/src/main/java/org/arend/lib/meta/linear/CompiledTerm.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,9 @@

import java.math.BigInteger;
import java.util.List;
import java.util.Set;

public class CompiledTerm {
public final ConcreteExpression concrete;
public final List<BigInteger> coefficients;

public CompiledTerm(ConcreteExpression concrete, List<BigInteger> coefficients) {
this.concrete = concrete;
this.coefficients = coefficients;
}

public record CompiledTerm(ConcreteExpression concrete, List<BigInteger> coefficients, Set<Integer> vars) {
public BigInteger getCoef(int i) {
return i < coefficients.size() ? coefficients.get(i) : BigInteger.ZERO;
}
Expand Down
40 changes: 30 additions & 10 deletions meta/src/main/java/org/arend/lib/meta/linear/LinearSolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ private List<BigInteger> solveEquations(List<? extends Equation<CompiledTerm>> e
: equation1.operation == Equation.Operation.LESS || equation2.operation == Equation.Operation.LESS
? Equation.Operation.LESS
: Equation.Operation.LESS_OR_EQUALS,
new CompiledTerm(null, lhs), new CompiledTerm(null, rhs)));
new CompiledTerm(null, lhs, Collections.emptySet()), new CompiledTerm(null, rhs, Collections.emptySet())));
}
}

Expand Down Expand Up @@ -274,7 +274,7 @@ private ConcreteExpression equationToConcrete(Equation<CompiledTerm> equation) {
case LESS_OR_EQUALS -> ext.linearSolverMeta.lessOrEquals;
case EQUALS -> ext.linearSolverMeta.equals;
};
return factory.tuple(equation.lhsTerm.concrete, factory.ref(constructor.getRef()), equation.rhsTerm.concrete);
return factory.tuple(equation.lhsTerm.concrete(), factory.ref(constructor.getRef()), equation.rhsTerm.concrete());
}

private ConcreteExpression equationsToConcrete(List<? extends Hypothesis<CompiledTerm>> equations) {
Expand Down Expand Up @@ -304,17 +304,30 @@ private ConcreteExpression certificateToConcrete(List<BigInteger> certificate, L
return factory.tuple(result, factory.number(certificate.get(0)), factory.ref(ext.prelude.getIdp().getRef()), factory.app(factory.ref(ext.prelude.getIdp().getRef()), factory.arg(factory.ref(ext.Bool.getRef()), false), factory.arg(factory.ref(ext.true_.getRef()), false)));
}

private <E> void removeUnusedVariables(List<Hypothesis<CompiledTerm>> hypotheses, List<E> values) {
Set<Integer> vars = new HashSet<>();
for (Hypothesis<CompiledTerm> hypothesis : hypotheses) {
vars.addAll(hypothesis.lhsTerm.vars());
vars.addAll(hypothesis.rhsTerm.vars());
}
for (int i = 0; i < values.size(); i++) {
if (!vars.contains(i)) {
values.set(i, null);
}
}
}

private ConcreteExpression makeData(CoreClassCallExpression classCall, ConcreteExpression instanceArg, RingKind kind, List<CoreExpression> valueList) {
boolean isRing = kind != RingKind.NAT && kind != RingKind.NONE || classCall.getDefinition().isSubClassOf(ext.equationMeta.OrderedRing);
ConcreteExpression varsArg = factory.ref(ext.prelude.getEmptyArray().getRef());
for (int i = valueList.size() - 1; i >= 0; i--) {
varsArg = factory.app(factory.ref(ext.prelude.getArrayCons().getRef()), true, factory.core(null, valueList.get(i).computeTyped()), varsArg);
varsArg = factory.app(factory.ref(ext.prelude.getArrayCons().getRef()), true, valueList.get(i) == null ? factory.ref(ext.zro.getRef()) : factory.core(valueList.get(i).computeTyped()), varsArg);
}
return factory.newExpr(factory.classExt(factory.ref((kind == RingKind.RAT_ALG ? ext.linearSolverMeta.LinearRatAlgebraData : kind == RingKind.RAT ? ext.linearSolverMeta.LinearRatData : isRing ? ext.linearSolverMeta.LinearRingData : ext.linearSolverMeta.LinearSemiringData).getRef()), Arrays.asList(factory.implementation((ext.equationMeta.RingDataCarrier).getRef(), instanceArg), factory.implementation(ext.equationMeta.DataFunction.getRef(), varsArg))));
}

private Equation<CompiledTerm> makeZeroLessOne(CoreExpression instance) {
return new Equation<>(instance, Equation.Operation.LESS, new CompiledTerm(null, Collections.emptyList()), new CompiledTerm(null, Collections.singletonList(BigInteger.ONE)));
return new Equation<>(instance, Equation.Operation.LESS, new CompiledTerm(null, Collections.emptyList(), Collections.emptySet()), new CompiledTerm(null, Collections.singletonList(BigInteger.ONE), Collections.emptySet()));
}

private void makeZeroLessVar(CoreExpression instance, TermCompiler compiler, List<Hypothesis<CompiledTerm>> result) {
Expand All @@ -339,7 +352,8 @@ private void makeZeroLessVar(CoreExpression instance, TermCompiler compiler, Lis
proof = factory.app(factory.ref(ext.linearSolverMeta.fromIntLE.getRef()), true, proof);
}
}
result.add(new Hypothesis<>(proof, instance, Equation.Operation.LESS_OR_EQUALS, new CompiledTerm(factory.ref(ext.equationMeta.zroTerm.getRef()), Collections.emptyList()), new CompiledTerm(factory.app(factory.ref(ext.equationMeta.varTerm.getRef()), true, factory.number(i - 1)), coefs), BigInteger.ONE));
int var = i - 1;
result.add(new Hypothesis<>(proof, instance, Equation.Operation.LESS_OR_EQUALS, new CompiledTerm(factory.ref(ext.equationMeta.zroTerm.getRef()), Collections.emptyList(), Collections.emptySet()), new CompiledTerm(factory.app(factory.ref(ext.equationMeta.varTerm.getRef()), true, factory.number(var)), coefs, Collections.singleton(var)), BigInteger.ONE));
}
}

Expand Down Expand Up @@ -471,11 +485,15 @@ public TypedExpression solve(CoreExpression expectedType, ConcreteExpression hin
}
}
dropUnusedHypotheses(combinedSolutions, compiledRules);
List<CoreExpression> values = compiler.getValues().getValues();
List<Hypothesis<CompiledTerm>> newCompiledRules = new ArrayList<>(compiledRules);
newCompiledRules.add(new Hypothesis<>(null, null, null, compiledResults.term1, compiledResults.term2, BigInteger.ONE));
removeUnusedVariables(newCompiledRules, values);
ConcreteAppBuilder builder = factory.appBuilder(factory.ref(function.getRef()))
.app(makeData(classCall, factory.core(instance), compiler.getKind(), compiler.getValues().getValues()), false)
.app(makeData(classCall, factory.core(instance), compiler.getKind(), values), false)
.app(equationsToConcrete(compiledRules))
.app(compiledResults.term1.concrete)
.app(compiledResults.term2.concrete);
.app(compiledResults.term1.concrete())
.app(compiledResults.term2.concrete());
for (int i = 0; i < solutions.size(); i++) {
dropUnusedHypotheses(combinedSolutions, solutions.get(i).subList(2, solutions.get(i).size()));
dropUnusedHypotheses(combinedSolutions, rulesSet.get(i).subList(2, rulesSet.get(i).size()));
Expand All @@ -501,7 +519,7 @@ public TypedExpression solve(CoreExpression expectedType, ConcreteExpression hin
break;
} else if (kind != RingKind.NAT) {
RingKind newKind = BaseTermCompiler.getTermCompilerKind(newRules.get(0).instance, ext.equationMeta);
if (kind == RingKind.NONE || newKind == RingKind.NONE || kind.ordinal() > newKind.ordinal()) {
if (kind == RingKind.NONE && newKind != RingKind.RAT || newKind == RingKind.NONE || kind.ordinal() > newKind.ordinal() && !(newKind == RingKind.RAT && kind == RingKind.NONE)) {
found = true;
List<Hypothesis<CoreExpression>> newRules2 = new ArrayList<>(newRules.size() + 1);
boolean remove = true;
Expand Down Expand Up @@ -548,8 +566,10 @@ public TypedExpression solve(CoreExpression expectedType, ConcreteExpression hin
dropUnusedHypotheses(subList, compiledEquations1.subList(1, compiledEquations1.size()));
dropUnusedHypotheses(subList, subList);
solutionFound[0] = true;
List<CoreExpression> values = compiler.getValues().getValues();
removeUnusedVariables(compiledEquations, values);
return tc.typecheck(factory.appBuilder(factory.ref(ext.linearSolverMeta.solveContrProblem.getRef()))
.app(makeData(classCall, factory.core(instance), compiler.getKind(), compiler.getValues().getValues()), false)
.app(makeData(classCall, factory.core(instance), compiler.getKind(), values), false)
.app(equationsToConcrete(compiledEquations))
.app(certificateToConcrete(solution, compiledEquations1))
.app(witnessesToConcrete(compiledEquations))
Expand Down
Loading

0 comments on commit fb2aa23

Please sign in to comment.