public void PartyGeneratorTest() { var prog = new Problem("Party generator"); var cast = new[] { "fred", "jenny", "sally" }; var character = Predicate <string>("character"); var human = Predicate <string>("human"); var electroid = Predicate <string>("electroid"); var insectoid = Predicate <string>("insectoid"); var fighter = Predicate <string>("fighter"); var magicUser = Predicate <string>("magic_user"); var cleric = Predicate <string>("cleric"); var thief = Predicate <string>("thief"); var landia = Predicate <string>("landia"); var placeville = Predicate <string>("placeville"); var cityburgh = Predicate <string>("cityburgh"); var monotheist = Predicate <string>("monotheist"); var pantheist = Predicate <string>("pantheist"); var lovecraftian = Predicate <string>("lovecraftian"); var dawkinsian = Predicate <string>("dawkinsian"); foreach (var who in cast) { prog.Assert(character(who)); // Races Partition(character(who), human(who), electroid(who), insectoid(who)); // Classes Partition(character(who), fighter(who), magicUser(who), cleric(who), thief(who)); prog.Inconsistent(electroid(who), cleric(who)); // Nationalities of humans Partition(human(who), landia(who), placeville(who), cityburgh(who)); // Religions of clerics Partition(cleric(who), monotheist(who), pantheist(who), lovecraftian(who), dawkinsian(who)); // Lovecraftianism is outlawed in Landia prog.Inconsistent(landia(who), lovecraftian(who)); // Insectoids believe in strict hierarchies prog.Inconsistent(insectoid(who), pantheist(who)); // Lovecraftianism is the state religion of cityburgh prog.Inconsistent(cityburgh(who), cleric(who), Not(lovecraftian(who))); } prog.AtMost(1, cast, fighter); prog.AtMost(1, cast, magicUser); prog.AtMost(1, cast, cleric); prog.AtMost(1, cast, thief); for (int i = 0; i < 100; i++) { Console.WriteLine(prog.Solve().Model); } }
public void NRooksHarderTest() { var n = 8; var p = new Problem("N rooks hard") { Timeout = 2000000 }; // rook(i, j) means there's a root at row i, column j var rook = Predicate <int, int>("rook"); // // Add constraint to the program // // There should be a total of n rooks p.Exactly(n, Range(0, n).SelectMany(i => Range(0, n).Select(j => rook(i, j)))); // There should be at most one rook in each row foreach (var i in Range(0, n)) { p.AtMost(1, Range(0, n), j => rook(i, j)); } // There should be at most one rook in each column foreach (var j in Range(0, n)) { p.AtMost(1, Range(0, n), i => rook(i, j)); } var m = p.Solve(); // // Test the constraint in the solution // m.Exactly(n, Range(0, n).SelectMany(i => Range(0, n).Select(j => rook(i, j)))); foreach (var i in Range(0, n)) { m.AtMost(1, Range(0, n).Select(j => rook(i, j))); } foreach (var j in Range(0, n)) { m.AtMost(1, Range(0, n).Select(i => rook(i, j))); } }
public void StoryTellerDemoTest() { var p = new Problem("Storyteller demo rebuild"); var cast = new[] { "red", "green", "blue" }; // characters don't have names and gender doesn't matter var rich = Predicate <string>("rich"); var caged = Predicate <string>("caged"); var hasSword = Predicate <string>("hasSword"); var evil = Predicate <string>("evil"); var kill = Predicate <string, string>("kill"); var loves = Predicate <string, string>("loves"); var dead = Predicate <string>("dead"); var tombstone = Predicate <string>("tombstone"); var someoneFree = (Proposition)"someoneFree"; // Panel 1 -> panel 2 foreach (var x in cast) { p.Assert( evil(x) == Not(rich(x)), caged(x) > rich(x), hasSword(x) == (rich(x) & Not(caged(x))), someoneFree <= Not(caged(x)), Not(kill(x, x)) ); // You can't kill multiple people p.AtMost(1, cast, y => kill(x, y)); foreach (var y in cast) { p.Assert( kill(x, y) > hasSword(x), kill(x, y) > evil(y) ); } } // Panel 2 -> panel 3 foreach (var x in cast) { foreach (var y in cast) { p.Assert( dead(y) <= kill(x, y), tombstone(x) <= (caged(x) & evil(y) & Not(dead(y))), tombstone(x) <= (Expression)Not(someoneFree), tombstone(x) <= dead(x) ); foreach (var z in cast) { p.Assert(loves(x, y) <= (caged(x) & kill(y, z))); } } } Console.WriteLine(p.Stats); for (int i = 0; i < 100; i++) { var s = p.Solve(); Console.WriteLine(s.Model); } }
public void StoryTest() { var p = new Problem("murder test") { TimeHorizon = 4, Timeout = 50000 }; var cast = new[] { "Fred", "Betty", "Frieda" }; // FLUENTS // alive(a, t) iff a alive at time t var alive = Fluent("alive", cast); var married = Fluent("married", cast); // Everyone is initially alive an unmarried foreach (var c in cast) { p.Assert(alive(c, 0), Not(married(c, 0))); } var hates = Fluent("hates", cast, cast); var loves = Fluent("loves", cast, cast); var marriedTo = SymmetricFluent("marriedTo", cast); foreach (var c1 in cast) { foreach (var c2 in cast) { p.Assert(Not(marriedTo(c1, c2, 0)), Not(loves(c1, c2, 0))); } } // Love and hate disable one another foreach (var agent in cast) { foreach (var patient in cast) { foreach (var t in ActionTimePoints) { p.Assert(Deactivate(hates(agent, patient, t)) <= Activate(loves(agent, patient, t)), Deactivate(loves(agent, patient, t)) <= Activate(hates(agent, patient, t))); } } } // ACTIONS // kill(a,b,t) means a kills b at time t var kill = Action("kill", cast, cast); Precondition(kill, (a, b, t) => alive(b, t)); Precondition(kill, (a, b, t) => alive(a, t)); Precondition(kill, (a, b, t) => hates(a, b, t)); Deletes(kill, (a, b, t) => alive(b, t)); // fallFor(faller, loveInterest, time) var fallFor = Action("fallFor", cast, cast); Precondition(fallFor, (f, l, t) => Not(loves(f, l, t))); Precondition(fallFor, (f, l, t) => alive(f, t)); Precondition(fallFor, (f, l, t) => alive(l, t)); Precondition(fallFor, (f, l, t) => f != l); Adds(fallFor, (f, l, t) => loves(f, l, t)); // marry(a, b, t) var marry = SymmetricAction("marry", cast); Precondition(marry, (a, b, t) => loves(a, b, t)); Precondition(marry, (a, b, t) => loves(b, a, t)); Precondition(marry, (a, b, t) => a != b); Precondition(marry, (a, b, t) => alive(a, t)); Precondition(marry, (a, b, t) => alive(b, t)); Precondition(marry, (a, b, t) => Not(married(a, t))); Precondition(marry, (a, b, t) => Not(married(b, t))); Adds(marry, (a, b, t) => marriedTo(a, b, t)); Adds(marry, (a, b, t) => married(a, t)); Adds(marry, (a, b, t) => married(b, t)); // You can't marry or fall in love with yourself foreach (var t in ActionTimePoints) { foreach (var c in cast) { p.Assert(Not(marry(c, c, t)), Not(fallFor(c, c, t))); } } IEnumerable <ActionInstantiation> PossibleActions(int t) { return(Instances(kill, t).Concat(Instances(fallFor, t)).Concat(Instances(marry, t))); } foreach (var t in ActionTimePoints) { // Exactly one action per time point p.AtMost(1, PossibleActions(t)); } // Tragedy strikes //foreach (var c in cast) // p.Assert(Not(alive(c, TimeHorizon-1))); //p.Assert(married("Fred", 3)); p.Optimize(); Console.WriteLine(p.Stats); var s = p.Solve(); foreach (var t in ActionTimePoints) { Console.Write($"Time {t}: "); foreach (var a in PossibleActions(t)) { if (s[a]) { Console.Write($"{a}, "); } } Console.WriteLine(); } }
public void MurderTest() { var p = new Problem("murder test") { TimeHorizon = 10 }; var cast = new[] { "fred", "lefty" }; // FLUENT // alive(a, t) iff a alive at time t var alive = Fluent("alive", cast); // ACTION // kill(a,b,t) means a kills b at time t var kill = Action("kill", cast, cast); Precondition(kill, (a, b, t) => alive(b, t)); Precondition(kill, (a, b, t) => alive(a, t)); Deletes(kill, (a, b, t) => alive(b, t)); // AXIOMS // No suicide foreach (var t in ActionTimePoints) { foreach (var a in cast) { p.Assert(Not(kill(a, a, t))); } } // INITIAL CONDITIONS // Everyone is initially alive foreach (var c in cast) { p.Assert(alive(c, 0)); } // GOAL // At least one character has to die. p.AtMost(1, cast, who => alive(who, TimeHorizon - 1)); // SOLVE for (int i = 0; i < 100; i++) { var s = p.Solve(); var murders = new List <Proposition>(); // Find all the murders foreach (var t in ActionTimePoints) { foreach (var a in cast) { foreach (var b in cast) { if (s[kill(a, b, t)]) { murders.Add(kill(a, b, t)); } } } } // There should be one, and at most two Assert.IsTrue(murders.Count > 0 && murders.Count <= 2); // If there are two, then they'd better have been simultaneous. if (murders.Count == 2) { Assert.IsTrue(Equals(murders[0].Arg(2), murders[1].Arg(2))); } } }