예제 #1
0
        //[TestMethod]
        //public void InverseFloyWarshall10Test()
        //{
        //    // Make a random 5-node undirected graph with designated connected components.
        //    // Computes transitive closure of using Floyd-Warshall
        //    InverseFWTest("IFW10", new[] { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" });
        //}

        //[TestMethod]
        //public void InverseFloyWarshall20Test()
        //{
        //    // Make a random 5-node undirected graph with designated connected components.
        //    // Computes transitive closure of using Floyd-Warshall
        //    InverseFWTest("IFW20", new[]
        //    {
        //        "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
        //        "11", "12", "13", "14", "15", "16", "17", "18", "19", "20"
        //    });
        //}

        private static void InverseFWTest(string name, string[] vertices)
        {
            var p        = new Problem(name);
            var adjacent = Predicate <string, string>("adjacent");
            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);

            // Now constrain its connectivity
            foreach (var v1 in vertices)
            {
                foreach (var v2 in vertices)
                {
                    if (v1 == v2 || (v1 != "e" && v2 != "e"))
                    {
                        p.Assert(Connected(v1, v2));
                    }
                    else
                    {
                        p.Assert(Not(Connected(v1, v2)));
                    }
                }
            }

            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"));
                    }
                }
            }
            p.LogPerformanceData();
        }
예제 #2
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"));
                    }
                }
            }
        }
예제 #3
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"));
                    }
                }
            }
        }
예제 #4
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();
        }
예제 #5
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));
        }
예제 #6
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();
            }
        }
예제 #7
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);
            }
        }