示例#1
0
        public void TransitiveClosureTest()
        {
            // Compute the transitive closure of a 5-node graph using Floyd-Warshall
            // This *should* get constant-folded away
            var p        = new Problem("transitive closure test");
            var vertices = new[] { "a", "b", "c", "d", "e" };
            var edges    = new[]
            {
                new[] { "a", "b" },
                new[] { "a", "d" },
                new[] { "b", "c" },
                new[] { "d", "c" },
            };

            Proposition Adjacent(string v1, string v2) => edges.Any(e => (v1 == v2) || (e[0] == v1 && e[1] == v2) || (e[0] == v2 && e[1] == v1));

            var connected = SymmetricPredicate <string>("connected");

            foreach (var from in vertices)
            {
                foreach (var to in vertices)
                {
                    if (from == to)
                    {
                        continue;
                    }
                    p.Assert(connected(from, to) <= Adjacent(from, to));
                    foreach (var intermediary in vertices)
                    {
                        if (intermediary != from && intermediary != to)
                        {
                            p.Assert(connected(from, to) <= (Adjacent(from, intermediary) & connected(intermediary, to)));
                        }
                    }
                }
            }

            p.Optimize();

            for (int i = 0; i < 100; i++)
            {
                var s = p.Solve();

                // a, b, c, d should be a connected component, e should be unconnected to anything but e
                foreach (var v1 in vertices)
                {
                    foreach (var v2 in vertices)
                    {
                        Assert.IsTrue(s[connected(v1, v2)] == (v1 == v2) || (v1 != "e" && v2 != "e"));
                    }
                }
            }
        }
示例#2
0
        public void SkipPropagationTest()
        {
            var p = new Problem("Skip last test's propagation during initialization");

            p.AddClause("b", "c");
            p.AddClause("a", "d");
            p.AddClause("d", "c");
            p.AddClause("e", "c");
            p.AddClause("f", "g");
            p.AddClause("g", "c");
            p.AddClause("h", "k");
            p.AddClause("i", "c");
            p.AddClause("j", "g");
            p.AddClause("k", "c");
            p.AddClause("l", "c");
            p.AddClause("m", "c");
            p.AddClause("n", "r");
            p.AddClause(1, 1, "e", "f");
            p.AddClause("w");
            p.QuantifyIf("a", 2, 2, "a", "c");
            p.AddClause(1, 1, "b", "c");
            p.PropagateConstraintsDuringInitialization = false;
            int[] flip = new int[1000];
            for (int i = 0; i < 1000; i++)
            {
                var m = p.Solve();
                flip[i] = m.Problem.BooleanSolver.SolveFlips;
            }
            int average = flip.Sum() / flip.Length;

            p.Assert(average == 4);
        }
示例#3
0
        public void LowTechCharacterGeneratorTest()
        {
            var prog = new Problem("Character generator");

            prog.Assert("character");

            // Races
            Partition("character", "human", "electroid", "insectoid");

            // Classes
            Partition("character", "fighter", "magic user", "cleric", "thief");
            prog.Inconsistent("electroid", "cleric");

            // Nationalities of humans
            Partition("human", "landia", "placeville", "cityburgh");

            // Religions of clerics
            Partition("cleric", "monotheist", "pantheist", "lovecraftian", "dawkinsian");

            // Lovecraftianism is outlawed in Landia
            prog.Inconsistent("landia", "lovecraftian");

            // Insectoids believe in strict hierarchies
            prog.Inconsistent("insectoid", "pantheist");

            // Lovecraftianism is the state religion of cityburgh
            prog.Inconsistent("cityburgh", "cleric", Not("lovecraftian"));

            for (int i = 0; i < 100; i++)
            {
                Console.WriteLine(prog.Solve().Model);
            }
        }
示例#4
0
        public void NonstrictTest()
        {
            var n = 8;

            var p    = new Problem("induction test");
            var pred = Predicate <int>("pred");

            for (var i = 1; i < n - 1; i++)
            // cell set iff neighbor is set.
            {
                p.Assert(
                    pred(i) <= pred(i - 1),
                    pred(i) <= pred(i + 1)
                    );
            }

            // Solve it.
            for (int t = 0; t < 100; t++)
            {
                var m = p.Solve();
                // This has 3 solutions: all false, all true, all but one end true, all but either end true.
                var c = m.Count(Range(0, n).Select(pred));
                Assert.IsTrue(c == 0 || c >= n - 2);
            }
        }
示例#5
0
        public void CompletionTest()
        {
            var p = new Problem("Completion test");

            var s = (Proposition)"s";
            var t = (Proposition)"t";
            var u = (Proposition)"u";

            var a = (Proposition)"a";
            var b = (Proposition)"b";

            var c = (Proposition)"c";

            p.Assert(
                s <= (t & u),
                s <= (a & b),
                s <= c
                );

            for (int i = 0; i < 100; i++)
            {
                var m = p.Solve();
                Assert.AreEqual(m.IsTrue(s),
                                (m.IsTrue(t) && m.IsTrue("u")) || (m.IsTrue(a) && m.IsTrue(b) || m.IsTrue(c)));
            }
        }
示例#6
0
        public void FloatTest()
        {
            var p   = new Problem(nameof(FloatTest));
            var dom = new FloatDomain("unit", 0, 1);
            var x   = (FloatVariable)dom.Instantiate("x");
            var y   = (FloatVariable)dom.Instantiate("y");

            var a = (Proposition)"a";
            var b = (Proposition)"b";
            var c = (Proposition)"c";
            var d = (Proposition)"d";
            var e = (Proposition)"e";

            p.Assert(a > (x > .2f));
            p.Assert(b > (x > .3f));
            p.Assert(c > (x < .5f));
            p.Assert(d > (x < .8f));
            p.Assert(e > (x == y));
            for (int i = 0; i < 100; i++)
            {
                var s = p.Solve();
                Console.WriteLine(s.Model);
                var xVal = x.Value(s);
                var yVal = y.Value(s);
                if (s[a])
                {
                    Assert.IsTrue(xVal >= .2f);
                }
                if (s[b])
                {
                    Assert.IsTrue(xVal >= .3f);
                }
                if (s[c])
                {
                    Assert.IsTrue(xVal <= .5f);
                }
                if (s[d])
                {
                    Assert.IsTrue(xVal <= .8f);
                }
                if (s[e])
                {
                    Assert.AreEqual(xVal, yVal);
                }
            }
        }
示例#7
0
        public void InductionTest()
        {
            var n = 8;

            var p    = new Problem("induction test");
            var pred = Predicate <int>("pred");

            p.Assert(pred(0));
            for (var i = 0; i < n; i++)
            {
                p.Assert(pred(i) == pred(i - 1));
            }
            for (int t = 0; t < 100; t++)
            {
                var m = p.Solve();
                Assert.IsTrue(m.All(Range(0, n).Select(i => pred(i))));
            }
        }
示例#8
0
        public void PredeterminedContradictionTest()
        {
            var p = new Problem();

            p.Assert((Proposition)"a" > "b");
            p["a"] = true;
            p["b"] = false;
            p.Solve(false);
        }
示例#9
0
        public void UndefinedFloatVarEquationHasNoEffectTest()
        {
            var p    = new Problem("test");
            var dom  = new FloatDomain("signed unit", -1, 1);
            var prop = (Proposition)"prop";
            var x    = new FloatVariable("x", dom, prop, p);
            var y    = (FloatVariable)dom.Instantiate("y");

            p.Assert(Not(prop));
            p.Assert(x == y);

            for (int i = 0; i < 100; i++)
            {
                var s = p.Solve();
                Assert.IsFalse(x.IsDefinedInInternal(s));
                Assert.IsTrue(y.IsDefinedInInternal(s));
                Assert.IsFalse(ReferenceEquals(x.Representative, y.Representative));
            }
        }
示例#10
0
        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);
            }
        }
示例#11
0
        public void FloydWarshallTest()
        {
            // Compute the transitive closure of a 5-node graph using Floyd-Warshall
            // This *should* get constant-folded away
            var p        = new Problem("transitive closure test");
            var vertices = new[] { "a", "b", "c", "d", "e" };
            var edges    = new[]
            {
                new[] { "a", "b" },
                new[] { "a", "d" },
                new[] { "b", "c" },
                new[] { "d", "c" },
            };

            Proposition Adjacent(string v1, string v2) => edges.Any(e => (v1 == v2) || (e[0] == v1 && e[1] == v2) || (e[0] == v2 && e[1] == v1));

            var floyd = Predicate <string, string, int>("d");

            // Inlines either adjacent or floyd, depending on k
            Proposition D(string v1, string v2, int k) => k == 0 ? Adjacent(v1, v2) : floyd(v1, v2, k);

            for (int k = 1; k < vertices.Length; k++)
            {
                var vk = vertices[k];
                foreach (var v1 in vertices)
                {
                    foreach (var v2 in vertices)
                    {
                        p.Assert(
                            D(v1, v2, k) <= D(v1, v2, k - 1),
                            D(v1, v2, k) <= (D(v1, vk, k - 1) & D(vk, v2, k - 1))
                            );
                    }
                }
            }

            Proposition Connected(string v1, string v2) => D(v1, v2, vertices.Length - 1);

            p.Optimize();

            for (int i = 0; i < 100; i++)
            {
                var s = p.Solve();

                // a, b, c, d should be a connected component, e should be unconnected to anything but e
                foreach (var v1 in vertices)
                {
                    foreach (var v2 in vertices)
                    {
                        Assert.IsTrue(s[Connected(v1, v2)] == (v1 == v2) || (v1 != "e" && v2 != "e"));
                    }
                }
            }
        }
示例#12
0
        public void FalseRuleTest()
        {
            var prog = new Problem("False rule test");
            var p    = (Proposition)"p";

            prog.Assert(p <= false);
            prog.Solve();  // Force it to expand rule to completion

            // This should not generate any clauses
            Assert.AreEqual(0, prog.Constraints.Count);
        }
示例#13
0
        public void AntecedentTrackingTest()
        {
            var p = new Problem(nameof(AntecedentTrackingTest));
            var x = (Proposition)"x";
            var y = (Proposition)"y";
            var z = (Proposition)"z";
            var w = (Proposition)"w";

            foreach (var prop in new[] { x, y, z, w })
            {
                Assert.IsFalse(prop.IsImplicationConsequent);
                Assert.IsFalse(prop.IsRuleHead);
                Assert.IsFalse(prop.IsAntecedent);
            }
            p.Assert(w > x);
            Assert.IsTrue(x.IsImplicationConsequent);
            Assert.IsFalse(x.IsRuleHead);
            Assert.IsFalse(x.IsDependency);
            Assert.IsFalse(x.IsAntecedent);
            Assert.IsTrue(w.IsAntecedent);
            Assert.IsFalse(w.IsImplicationConsequent);
            Assert.IsFalse(w.IsRuleHead);
            Assert.IsTrue(w.IsDependency);
            p.Assert(x <= (y & z));
            Assert.IsTrue(x.IsRuleHead);
            Assert.IsTrue(x.IsDependency);
            Assert.IsTrue(y.IsAntecedent);
            Assert.IsFalse(y.IsRuleHead);
            Assert.IsFalse(y.IsImplicationConsequent);
            Assert.IsTrue(y.IsDependency);
            Assert.IsTrue(z.IsAntecedent);
            Assert.IsFalse(z.IsRuleHead);
            Assert.IsFalse(z.IsImplicationConsequent);
            Assert.IsTrue(z.IsDependency);
            var a = (Proposition)"a";

            p.Assert(Language.Not(x) > a);
            Assert.IsTrue(x.IsAntecedent);
            Assert.IsTrue(x.IsImplicationConsequent);
            Assert.IsTrue(x.IsRuleHead);
        }
示例#14
0
        public void ConnectedChainTest()
        {
            var n = 8;

            var p = new Problem("connected chain test");
            Func <int, int, Proposition> adjacent = (i, j) => Math.Abs(i - j) < 2;
            var connected = Predicate <int, int>("connected");

            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    if (i == j)
                    {
                        p.Assert(connected(i, i));
                    }
                    else
                    {
                        // i is connected to j if the node on either side is connected to j and i is adjacent to the neighbor.
                        p.Assert(
                            connected(i, j) <= adjacent(i, i - 1), connected(i - 1, j),
                            connected(i, j) <= adjacent(i, i + 1), connected(i + 1, j)
                            );
                    }
                }
            }

            var m = p.Solve();

            for (int trial = 0; trial < 100; trial++)
            {
                for (int i = 0; i < n; i++)
                {
                    for (int j = 0; j < n; j++)
                    {
                        Assert.IsTrue(m.IsTrue(connected(i, j)));
                    }
                }
            }
        }
示例#15
0
        public void BiconditionalTest()
        {
            var p = new Problem("Biconditional test");
            var s = (Proposition)"s";
            var t = (Proposition)"t";

            p.Assert(s == t);
            for (int i = 0; i < 100; i++)
            {
                var m = p.Solve();
                Assert.AreEqual(m.IsTrue(s), m.IsTrue(t));
            }
        }
示例#16
0
        public void BiconditionalTest2()
        {
            var p = new Problem("Biconditional test 2");
            var s = (Proposition)"s";
            var t = (Proposition)"t";
            var u = (Proposition)"u";

            p.Assert(s == (t & u));
            for (int i = 0; i < 100; i++)
            {
                var m = p.Solve();
                Assert.AreEqual(m[s], m[t] && m[u]);
            }
        }
示例#17
0
        public void ConstantBoundDependencyTest()
        {
            var p   = new Problem(nameof(FloatTest));
            var dom = new FloatDomain("unit", 0, 1);
            var x   = (FloatVariable)dom.Instantiate("x");
            var a   = (Proposition)"a";

            p.Assert((x > 0.1f) > a);
            for (int i = 0; i < 100; i++)
            {
                var s = p.Solve();
                Assert.IsTrue(x.Value(s) <= 0.1f || s[a]);
            }
        }
示例#18
0
        public void ContradictionTest()
        {
            var prog = new Problem("Contradiction test");
            var p    = (Proposition)"p";
            var q    = (Proposition)"q";
            var r    = (Proposition)"r";

            prog.Assert(
                p <= q,
                p <= r,
                Not(p),
                q
                );
            prog.Optimize();
            Assert.Fail();
        }
示例#19
0
        public void SolveTwoDependent()
        {
            SMTVar.Reset();
            var p = new Problem("SolveTwoDependent");
            var x = new SMTVar("x", 0, 10);
            var y = new SMTVar("y", 0, 10);

            p.Assert(x < y);
            for (int i = 0; i < 100; i++)
            {
                Assert.IsTrue(SMTVar.Solve(p.Solve()));
                AssertValid(x);
                AssertValid(y);
                Assert.IsTrue(x.Value <= y.Value, $"Trial {i}: {x.Value} > {y.Value}");
            }
        }
示例#20
0
        public void TrueRuleTest()
        {
            var prog = new Problem("True rule test");
            var p    = (Proposition)"p";
            var q    = (Proposition)"q";

            prog.Assert(
                p <= true,
                p <= false,
                p <= q
                );
            var s = prog.Solve();  // Force it to expand rule to completion

            // This should have compiled to zero clauses but p should still always be true
            Assert.AreEqual(0, prog.Constraints.Count);
            Assert.IsTrue(s[p]);
        }
示例#21
0
        public void ImplicationTest()
        {
            var p = new Problem("Implication test");
            var s = (Proposition)"s";
            var t = (Proposition)"t";

            p.Assert(
                (t & (Proposition)true) > s,
                t
                );

            for (int i = 0; i < 100; i++)
            {
                var m = p.Solve();
                Assert.IsTrue(m.IsTrue(s));
                Assert.IsTrue(m.IsTrue(t));
            }
        }
示例#22
0
        public void UndefinedFloatVarTest()
        {
            var p    = new Problem("test");
            var dom  = new FloatDomain("signed unit", -1, 1);
            var prop = (Proposition)"prop";
            var x    = new FloatVariable("x", dom, prop, p);

            p.Assert(Not(prop));
            Solution s = null;

            for (int i = 0; i < 100; i++)
            {
                s = p.Solve();
                Console.WriteLine(s.Model);
                Assert.IsFalse(s[prop]);
                Assert.IsFalse(x.IsDefinedInInternal(s));
            }
            Console.WriteLine(x.Value(s));
        }
示例#23
0
        public void OptimizationTest()
        {
            var prog = new Problem("Optimzer test");
            var p    = (Proposition)"p";
            var q    = (Proposition)"q";
            var r    = (Proposition)"r";
            var s    = (Proposition)"s";

            prog.Assert(
                p <= q,
                p <= r,
                Not(p)
                );
            prog.Optimize();
            Assert.IsTrue(prog.IsAlwaysFalse(p));
            Assert.IsTrue(prog.IsAlwaysFalse(q));
            Assert.IsTrue(prog.IsAlwaysFalse(r));
            Assert.IsFalse(prog.IsConstant(s));
        }
示例#24
0
        public void ContrapositiveTest()
        {
            var prog = new Problem("Contrapositive test");
            var p    = (Proposition)"p";
            var q    = (Proposition)"q";
            var r    = (Proposition)"r";

            prog.Assert(
                p <= q,
                p <= r,
                Not(p)
                );
            for (int i = 0; i < 100; i++)
            {
                var m = prog.Solve();

                // Under completion semantics, only model should be the empty model.
                Assert.IsFalse(m.IsTrue(p));
                Assert.IsFalse(m.IsTrue(q));
                Assert.IsFalse(m.IsTrue(r));
            }
        }
示例#25
0
        public void PSMTNPCStatsTest()
        {
            SMTVar.Reset();
            var p        = new Problem("NPC stats");
            var str      = new SMTVar("str", 0, 10);
            var con      = new SMTVar("con", 0, 10);
            var dex      = new SMTVar("dex", 0, 10);
            var intel    = new SMTVar("int", 0, 10);
            var wis      = new SMTVar("wis", 0, 10);
            var charisma = new SMTVar("char", 0, 10);

            p.Unique("fighter", "magic user", "cleric", "thief");
            p.Assert(
                ((Expression)(Proposition)"fighter") > (str > intel),
                ((Expression)(Proposition)"fighter") > (str > 5),
                ((Expression)(Proposition)"fighter") > (con > 5),
                ((Expression)(Proposition)"fighter") > (intel < 8),
                ((Expression)(Proposition)"magic") > (str < intel),
                ((Expression)(Proposition)"magic") > (intel > 5),
                ((Expression)(Proposition)"magic") > (str < 8),
                ((Expression)(Proposition)"cleric") > (wis > 5),
                ((Expression)(Proposition)"cleric") > (con < wis),
                ((Expression)(Proposition)"theif") > (dex > 5),
                ((Expression)(Proposition)"theif") > (charisma > 5),
                ((Expression)(Proposition)"theif") > (wis < 5),
                ((Expression)(Proposition)"theif") > (dex > str),
                ((Expression)(Proposition)"theif") > (charisma > intel)
                );
            for (int i = 0; i < 100; i++)
            {
                Solution solution;
                do
                {
                    solution = p.Solve();
                } while (!SMTVar.Solve(solution));
            }
        }
示例#26
0
        public void IgnoreFalseRuleTest()
        {
            var prog = new Problem("Ignore false rule test");
            var p    = (Proposition)"p";
            var q    = (Proposition)"q";

            prog.Assert(
                p <= false,
                p <= q,
                p <= false
                );
            prog.Solve();  // Force it to expand rule to completion

            // This should have compiled to two clauses
            Assert.AreEqual(2, prog.Constraints.Count);
            // First clause should be q => p
            Assert.AreEqual(2, prog.Constraints[0].Disjuncts.Length);
            Assert.AreEqual(1, prog.Constraints[0].Disjuncts[0]);
            Assert.AreEqual(-2, prog.Constraints[0].Disjuncts[1]);
            // Section clause should be p => q
            Assert.AreEqual(2, prog.Constraints[1].Disjuncts.Length);
            Assert.AreEqual(-1, prog.Constraints[1].Disjuncts[0]);
            Assert.AreEqual(2, prog.Constraints[1].Disjuncts[1]);
        }
示例#27
0
        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();
            }
        }
示例#28
0
        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)));
                }
            }
        }
示例#29
0
        public void FamilyGeneratorTest()
        {
            var p = new Problem("family generator");

            var FamilySize       = 25;
            var generationCount  = 5;
            var matriarch        = 1;
            var cast             = Enumerable.Range(matriarch, FamilySize).ToArray();
            var kids             = Enumerable.Range(matriarch + 1, FamilySize - 1).ToArray();
            var childGenerations = Enumerable.Range(1, generationCount - 1).ToArray();
            var female           = Predicate <int>("female");
            var generation       = Predicate <int, int>("generation");
            var parent           = Predicate <int, int>("parent");

            // Interestingly, this doesn't seem to speed things up.
            //Func<int, int, Proposition> parent = (child, par) =>
            //    child > par ? p.GetProposition(Call.FromArgs(Problem.Current, "parent", child, par)) : false;

            // Make of person # who is person number -who
            int Mate(int who) => - who;

            // Family must be 40-60% female
            p.Quantify((int)(FamilySize * .4), (int)(FamilySize * .6), kids, female);

            // Matriarch is the generation 0 female
            p.Assert(female(matriarch), Not(female(Mate(matriarch))));
            p.Assert(generation(matriarch, 0));

            foreach (var child in kids)
            {
                // Everyone has exactly one parent from within the family (and one from outside)
                p.Unique(cast, par => parent(child, par));
                foreach (var par in cast)
                {
                    parent(child, par).InitialProbability = 0;
                }
                // Everyone has a generation number
                p.Unique(childGenerations, g => generation(child, g));
                p.Assert(
                    // Only matriarch and patriarch are generation 0
                    Not(generation(child, 0)),
                    // Heteronormativity
                    female(child) == Not(female(Mate(child))));
                foreach (var par in cast)
                {
                    foreach (var g in childGenerations)
                    {
                        // Child's generation is one more than parent's generation
                        p.Assert(generation(child, g) <= (parent(child, par) & generation(par, g - 1)));
                    }
                }
            }
            // Every generation has at least one kid
            foreach (var g in childGenerations)
            {
                p.Exists(kids, k => generation(k, g));
            }
            p.Optimize();

            Console.WriteLine(p.Stats);
            Console.WriteLine(p.PerformanceStatistics);
            Console.WriteLine();

            for (int i = 0; i < 100; i++)
            {
                var s = p.Solve();
                Console.WriteLine(p.PerformanceStatistics);
                void PrintTree(int who, int depth)
                {
                    for (int j = 0; j < depth; j++)
                    {
                        Console.Write("    ");
                    }
                    Console.WriteLine($"{Gender(who)} {who}: + {Mate(who)}");
                    foreach (var child in kids.Where(k => s[parent(k, who)]))
                    {
                        PrintTree(child, depth + 1);
                    }
                }

                string Gender(int who)
                {
                    return(s[female(who)] ? "female" : "male");
                }

                PrintTree(matriarch, 0);
            }
        }
示例#30
0
        // ReSharper disable once IdentifierTypo
        // ReSharper disable once InconsistentNaming
        public void PSMTNPCStatTest()
        {
            var p           = new Problem("NPC stats");
            var str         = new FloatVariable("str", 0, 10);
            var con         = new FloatVariable("con", 0, 10);
            var dex         = new FloatVariable("dex", 0, 10);
            var intel       = new FloatVariable("int", 0, 10);
            var wis         = new FloatVariable("wis", 0, 10);
            var charisma    = new FloatVariable("char", 0, 10);
            var classDomain = new FDomain <string>("character class",
                                                   "fighter", "magic user", "cleric", "thief");
            var cClass = classDomain.Instantiate("class");

            p.Assert(
                (cClass == "fighter") > (str > intel),
                (cClass == "fighter") > (str > 5),
                (cClass == "fighter") > (con > 5),
                (cClass == "fighter") > (intel < 8),
                (cClass == "magic user") > (str < intel),
                (cClass == "magic user") > (intel > 5),
                (cClass == "magic user") > (str < 8),
                (cClass == "cleric") > (wis > 5),
                (cClass == "cleric") > (con < wis),
                (cClass == "thief") > (dex > 5),
                (cClass == "thief") > (charisma > 5),
                (cClass == "thief") > (wis < 5),
                (cClass == "thief") > (dex > str),
                (cClass == "thief") > (charisma > intel)
                );
            for (int i = 0; i < 100; i++)
            {
                var s = p.Solve();
                if (s[(cClass == "fighter")])
                {
                    Assert.IsTrue(str.Value(s) >= intel.Value(s));
                }
                if (s[(cClass == "fighter")])
                {
                    Assert.IsTrue(str.Value(s) >= 5);
                }
                if (s[(cClass == "fighter")])
                {
                    Assert.IsTrue(con.Value(s) >= 5);
                }
                if (s[(cClass == "fighter")])
                {
                    Assert.IsTrue(intel.Value(s) <= 8);
                }

                if (s[(cClass == "magic user")])
                {
                    Assert.IsTrue(str.Value(s) <= intel.Value(s));
                }
                if (s[(cClass == "magic user")])
                {
                    Assert.IsTrue(intel.Value(s) >= 5);
                }
                if (s[(cClass == "magic user")])
                {
                    Assert.IsTrue(str.Value(s) <= 8);
                }

                if (s[(cClass == "cleric")])
                {
                    Assert.IsTrue(wis.Value(s) >= 5);
                }
                if (s[(cClass == "cleric")])
                {
                    Assert.IsTrue(con.Value(s) <= wis.Value(s));
                }

                if (s[(cClass == "thief")])
                {
                    Assert.IsTrue(dex.Value(s) >= 5);
                }
                if (s[(cClass == "thief")])
                {
                    Assert.IsTrue(charisma.Value(s) >= 5);
                }
                if (s[(cClass == "thief")])
                {
                    Assert.IsTrue(wis.Value(s) <= 5);
                }
                if (s[(cClass == "thief")])
                {
                    Assert.IsTrue(dex.Value(s) >= str.Value(s));
                }
                if (s[(cClass == "thief")])
                {
                    Assert.IsTrue(charisma.Value(s) >= intel.Value(s));
                }

                Console.WriteLine(s.Model);
            }
        }