Implement basics
parent
0fc53b26d8
commit
b165a07788
@ -1,11 +0,0 @@
|
||||
import { Example } from "src/index.js";
|
||||
import * as assert from "assert";
|
||||
|
||||
describe("Example", () => {
|
||||
describe("example", () => {
|
||||
it("should equal 'example'", () => {
|
||||
const example = new Example();
|
||||
assert.equal(example.example(), "example");
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1,5 +1,185 @@
|
||||
export class Example {
|
||||
example(): string {
|
||||
return "example";
|
||||
import { getSubsets } from "./subsets.js";
|
||||
|
||||
abstract class Var {
|
||||
public name: string;
|
||||
|
||||
abstract getValue(): boolean | null;
|
||||
|
||||
abstract hasValue(): boolean;
|
||||
|
||||
abstract getCoreVar(): Var;
|
||||
}
|
||||
|
||||
class BoolVar extends Var {
|
||||
private value: boolean | null = null;
|
||||
private has_value = false;
|
||||
|
||||
constructor(name: string) {
|
||||
super();
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
hasValue() {
|
||||
return this.has_value;
|
||||
}
|
||||
|
||||
setValue(value: boolean) {
|
||||
this.value = value;
|
||||
this.has_value = true;
|
||||
}
|
||||
|
||||
getCoreVar(): Var {
|
||||
return this;
|
||||
}
|
||||
|
||||
toString() {
|
||||
if (!this.hasValue()) {
|
||||
return this.name.replaceAll("~~", "");
|
||||
}
|
||||
return this.getValue() ? "1" : "0";
|
||||
}
|
||||
}
|
||||
|
||||
class NotVar extends BoolVar {
|
||||
constructor(public boolvar: BoolVar) {
|
||||
super("~" + boolvar.name);
|
||||
}
|
||||
|
||||
getValue() {
|
||||
if (!this.boolvar.hasValue()) {
|
||||
return null;
|
||||
}
|
||||
return !this.boolvar.getValue();
|
||||
}
|
||||
|
||||
hasValue() {
|
||||
return this.boolvar.hasValue();
|
||||
}
|
||||
|
||||
setValue(value: boolean) {
|
||||
this.boolvar.setValue(value);
|
||||
}
|
||||
|
||||
getCoreVar() {
|
||||
return this.boolvar.getCoreVar();
|
||||
}
|
||||
}
|
||||
|
||||
class Or {
|
||||
constructor(private vars: Var[]) {}
|
||||
|
||||
getVars() {
|
||||
return this.vars;
|
||||
}
|
||||
|
||||
valueIsKnown() {
|
||||
return this.getVars().every((v) => v.hasValue());
|
||||
}
|
||||
|
||||
isTrue() {
|
||||
const result = this.getVars().some(
|
||||
(variable) => variable.hasValue() && variable.getValue()
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
isFalse() {
|
||||
return !this.isTrue();
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `(${this.vars.map((e) => e.toString()).join(" v ")})`;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This is totally wrong
|
||||
function And(...vars: BoolVar[]): Or[] {
|
||||
const all_subsets = getSubsets(vars).slice(1);
|
||||
return all_subsets
|
||||
.filter((s) => s.length > 0)
|
||||
.map(
|
||||
(subset) =>
|
||||
new Or(
|
||||
vars.map((v) => (subset.includes(v) ? v : new NotVar(v)))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
class CNF {
|
||||
ors: Or[];
|
||||
constructor(...ors: Or[]) {
|
||||
this.ors = ors;
|
||||
}
|
||||
|
||||
getVars() {
|
||||
return this.ors.map((or) => or.getVars()).flat();
|
||||
}
|
||||
|
||||
getCoreVars() {
|
||||
return Array.from(
|
||||
new Set(this.getVars().map((v) => v.getCoreVar())).values()
|
||||
);
|
||||
}
|
||||
|
||||
valueIsKnown() {
|
||||
return (
|
||||
this.ors.some((or) => or.valueIsKnown() && or.isFalse()) ||
|
||||
this.ors.every((or) => or.valueIsKnown())
|
||||
);
|
||||
}
|
||||
|
||||
getValue() {
|
||||
if (!this.valueIsKnown()) {
|
||||
throw new Error("Value is not yet known");
|
||||
}
|
||||
for (const or of this.ors) {
|
||||
if (or.isFalse()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this.ors.map((or) => or.toString()).join(" & ");
|
||||
}
|
||||
|
||||
printAnswers() {
|
||||
return this.getCoreVars()
|
||||
.filter((v) => v.hasValue())
|
||||
.map((v) => `${v.name}: ${v.getValue()}`)
|
||||
.join(", ");
|
||||
}
|
||||
|
||||
printState() {
|
||||
console.log(this.printAnswers());
|
||||
console.log("Value is known?", this.valueIsKnown());
|
||||
if (this.valueIsKnown()) {
|
||||
console.log("The result is", this.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const is_poznan = new BoolVar("is_poznan");
|
||||
const is_droga_wojewodzka = new BoolVar("is_droga_wojewodzka");
|
||||
const is_droga_powiatowa = new BoolVar("is_droga_powiatowa");
|
||||
const is_less_than_6m = new BoolVar("is_less_than_6m");
|
||||
const is_less_than_8m = new BoolVar("is_less_than_8m");
|
||||
const is_ekran = new BoolVar("is_ekran");
|
||||
|
||||
const is_legal = new CNF(
|
||||
...And(is_droga_wojewodzka, new NotVar(is_less_than_8m)),
|
||||
...And(is_droga_powiatowa, new NotVar(is_less_than_6m)),
|
||||
...And(is_poznan, new NotVar(is_ekran))
|
||||
);
|
||||
|
||||
is_poznan.setValue(true);
|
||||
is_ekran.setValue(false);
|
||||
is_droga_wojewodzka.setValue(true);
|
||||
is_less_than_8m.setValue(true);
|
||||
console.log(is_legal.toString());
|
||||
is_legal.printState();
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
export function getSubsets<T>(arr: T[]) {
|
||||
const subsets = [[]] as T[][]; // start with empty set
|
||||
|
||||
for (const element of arr) {
|
||||
const newSubsets = subsets.map((subset) => [...subset, element]);
|
||||
subsets.push(...newSubsets);
|
||||
}
|
||||
|
||||
return subsets;
|
||||
}
|
||||
Loading…
Reference in New Issue