Refactor (2)
This commit is contained in:
@@ -1,7 +1,14 @@
|
||||
import { power } from "@cannorin/utils";
|
||||
import { expect, test } from "vitest";
|
||||
import { validWorlds } from "../sat";
|
||||
import { validWorlds as validWorldsNaive } from "../semantics";
|
||||
import { prettyPrint } from "../syntax";
|
||||
import { validWorlds } from "../src/sat";
|
||||
import { type Frame, type World, satisfy, worlds } from "../src/semantics";
|
||||
import {
|
||||
type Formula,
|
||||
type PropVar,
|
||||
prettyPrint,
|
||||
propVars,
|
||||
vars,
|
||||
} from "../src/syntax";
|
||||
import { randomFormula, randomFrame, testFormulas } from "./utils";
|
||||
|
||||
const elapsed = <T>(f: () => T) => {
|
||||
@@ -11,15 +18,43 @@ const elapsed = <T>(f: () => T) => {
|
||||
return { value, elapsed: end - start };
|
||||
};
|
||||
|
||||
export function validWorldsNaive(
|
||||
f: Frame,
|
||||
fml: Formula,
|
||||
allValuations: `${World}${PropVar}`[][],
|
||||
) {
|
||||
const result: World[] = [];
|
||||
for (const w of worlds) {
|
||||
let valid = true;
|
||||
for (const v of allValuations) {
|
||||
if (!satisfy({ ...f, valuations: new Set(v) }, w, fml)) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (valid) result.push(w);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
for (const fml of testFormulas.concat(
|
||||
[...Array(50)].map(() => randomFormula()),
|
||||
[...Array(100)].map(() => randomFormula()),
|
||||
)) {
|
||||
test(`SAT works for ${prettyPrint(fml)}`, () => {
|
||||
const count = 100;
|
||||
let diff = 0;
|
||||
const allValuations = power(
|
||||
worlds.flatMap((w) =>
|
||||
(fml ? Array.from(vars(fml)) : propVars).map(
|
||||
(p) => `${w}${p}` as const,
|
||||
),
|
||||
),
|
||||
);
|
||||
for (let i = 0; i < count; i++) {
|
||||
const frame = randomFrame();
|
||||
const expected = elapsed(() => validWorldsNaive(frame, fml));
|
||||
const expected = elapsed(() =>
|
||||
validWorldsNaive(frame, fml, allValuations),
|
||||
);
|
||||
const actual = elapsed(() => validWorlds(frame, fml));
|
||||
|
||||
expect(actual.value.sort()).toStrictEqual(expected.value.sort());
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { sample } from "@cannorin/utils/array";
|
||||
import { parse } from "../parser";
|
||||
import { getFrame, nontrivials } from "../semantics";
|
||||
import { sample } from "@cannorin/utils";
|
||||
import { parse } from "../src/parser";
|
||||
import { getFrame, nontrivials } from "../src/semantics";
|
||||
import {
|
||||
type Formula,
|
||||
and,
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
propvar,
|
||||
to,
|
||||
top,
|
||||
} from "../syntax";
|
||||
} from "../src/syntax";
|
||||
|
||||
const formulaTypes = [
|
||||
"top",
|
||||
@@ -52,9 +52,24 @@ export const testFormulas: Formula[] = [
|
||||
parse("LLp -> p"),
|
||||
parse("p -> LLp"),
|
||||
|
||||
parse("M(p -> Mp)"),
|
||||
parse("r -> M((p -> Mp) & Mr)"),
|
||||
parse("p -> MMp"),
|
||||
parse("M(p -> Lp)"),
|
||||
parse("L0"),
|
||||
parse("ML0"),
|
||||
parse("L(p -> Mp)"),
|
||||
parse("p -> MMMp"),
|
||||
parse("p -> MMMMp"),
|
||||
parse("M1"),
|
||||
parse("ML(p -> Mp)"),
|
||||
parse("Lp -> LMp"),
|
||||
parse("M(p -> LLp)"),
|
||||
|
||||
// pathological
|
||||
parse("L(M(1 & p) v LM1) -> (s <-> 1)"),
|
||||
parse("L(M((q v ~q) & p) v LM(s v ~s)) -> (s <-> (p v ~p))"),
|
||||
parse("~(Lr & ¬Mp) & M~L(q v q)"),
|
||||
];
|
||||
|
||||
export function randomFormula(depth = 5): Formula {
|
||||
|
||||
Reference in New Issue
Block a user