private GraphNet LoadGraphNet()
        {
            //1: create a GraphNet for predicting if a super is good or bad
            var supers = new GraphNet("supers", maxPathLenght: 20);

            supers.LimitNumberOfPaths = true;
            supers.RegisterDynamic("enitiy", (node, graph) =>
            {
                graph.Node(node, "word", node.ToString().Split('_'));
                Node.BaseOnAdd(node, graph);
            });
            supers.AddDynamic("enitiy", "spider_man", "is_a", "hero");
            supers.AddDynamic("enitiy", "hulk", "is_a", "hero");
            supers.AddDynamic("enitiy", "green_goblin", "is_a", "villain");
            supers.AddDynamic("enitiy", "red_king", "is_a", "villain");
            supers.Add("red", "a", "colour");
            supers.Add("green", "a", "colour");
            supers.Add("blue", "a", "colour");
            supers.Add("hero", "is", "good", true);
            supers.Add("villain", "is", "bad", true);

            //2: create a GraphNet that knows about cities
            var cities = new GraphNet("cities", maxNumberOfPaths: 20);

            cities.Add("london", "is_a", "city");
            cities.Add("paris", "is_a", "city");
            cities.Add("uk", "is_a", "country");
            cities.Add("france", "is_a", "country");
            cities.Add("paris", "capital_of", "france");
            cities.Add("london", "capital_of", "uk");
            var yes = cities.Node(cities.Node(true), "input", "country", "city", "london", "paris", "uk", "france");
            var no  = cities.Node(cities.Node(false), "input", "country", "city", "london", "paris", "uk", "france");

            cities.Add(yes, true);
            cities.Add(no, true);

            //3: create a GraphNet that can do caculations
            var calc = new GraphNet("calc", maxPathLenght: 20, maxNumberOfPaths: 20);

            calc.LimitNumberOfPaths = true;
            calc.Add("add_opp", "lable", "+");
            calc.Add("times_opp", "lable", "*");
            calc.Add("times_opp", "lable", "x");
            calc.Add("minus_opp", "lable", "-");
            calc.Add(new Node("number"));
            calc.Add(new Node("a"));
            calc.Add(new Node("word"));

            Func <List <NodePath>, IEnumerable <int> > pullNumbers = (paths) =>
            {
                var numbers = paths.Where(p => p[2].Value.ToString() != "" && p[2].Value.ToString().All(char.IsDigit) && p[4].Equals(calc.Node("number")))
                              .Select(p => int.Parse(p[2].Value.ToString())).Distinct();
                return(numbers);
            };
            var sum = new DynamicNode("sum"
                                      , onProcess: (node, graph, input, paths) => node.Result = pullNumbers(paths).Sum());

            sum.AddEdge("input", "number", calc);
            sum.AddEdge("opp", "add_opp", calc);
            calc.Add(sum, true);


            //subtract
            var minus = (new DynamicNode("minus"
                                         , onProcess: (node, graph, input, paths) =>
            {
                var n = pullNumbers(paths);
                if (n.Count() > 0)
                {
                    node.Result = n.Aggregate((a, b) => a - b);
                }
            }));

            minus.AddEdge("input", "number", calc);
            minus.AddEdge("opp", "minus_opp", calc);
            calc.Add(minus, true);

            //multiply
            var times = new DynamicNode("times"
                                        , onProcess: (node, graph, input, paths) => node.Result = pullNumbers(paths).Aggregate(1, (acc, val) => acc * val));

            times.AddEdge("input", "number", calc);
            times.AddEdge("opp", "times_opp", calc);
            calc.Add(times, true);

            //4: create a GraphNet for parsing text
            var nlp = new GraphNet("nlp", maxNumberOfPaths: 10, maxPathLenght: 10);

            nlp.Add(new DynamicNode("nlp_out", (node, graph) =>
            {
                node.Result = graph.AllEdges();
            }), true);
            nlp.RegisterDynamic("parse", (node, graph) =>
            {
                //add word nodes and mark if they are numbers
                nlp.Node(node, "word", node.ToString().Split(' '));
                foreach (var word in node.Edges.Select(e => e.Obj).ToList())
                {
                    if (word.ToString().All(char.IsDigit))
                    {
                        var edge = new Edge(word, nlp.Node("a"), nlp.Node("number"))
                        {
                            Internal = true
                        };
                        word.Edges.Add(edge);
                    }
                }
                Node.BaseOnAdd(node, graph);
            });

            //5: create the master GraphNet that contains the other GraphNets as nodes within it
            var gn = new GraphNet("Master", maxNumberOfPaths: 20, maxPathLenght: 20);

            gn.LimitNumberOfPaths = true;
            gn.RegisterDynamic("ask", (node, graph) =>
            {
                Node ask = nlp.DynamicNode("parse")(node.Value.ToString());
                //TODO: this would be better: node.AddEdge(graph.Node("nlp"), ask);
                nlp.Add(ask);
                node.Edges = nlp.AllEdges();
                nlp.Remove(ask);
                Node.BaseOnAdd(node, graph);
            });
            gn.DefaultInput = "ask";
            gn.Add(supers, true);
            gn.Add(cities, true);
            gn.Add(calc, true);
            gn.LimitNumberOfPaths = true;

            //train the master GraphNet with some examples
            gn.Train(
                new Example(gn.Node("spider man"), "good"),
                new Example(gn.Node("green goblin"), "bad"),
                new Example(gn.Node("4 + 1"), 5),
                new Example(gn.Node("12 - 10"), 2),
                new Example(gn.Node("5 * 3"), 15),
                new Example(gn.Node("london is a city"), true),
                new Example(gn.Node("london is a country"), false),
                new Example(gn.Node("uk is a country"), true),
                new Example(gn.Node("uk is a city"), false)
                );

            return(gn);
        }
Esempio n. 2
0
        public void TestNestedGraphNets()
        {
            //GraphNets are nodes themselves so they can be added into another GraphNets

            //1: create a GraphNet for predicting if a super is good or bad
            var supers = new GraphNet("supers", maxPathLenght: 20);

            supers.RegisterDynamic("enitiy", (node, graph) => {
                graph.Node(node, "word", node.ToString().Split('_'));
                Node.BaseOnAdd(node, graph);
            });
            supers.AddDynamic("enitiy", "spider_man", "is_a", "hero");
            supers.AddDynamic("enitiy", "hulk", "is_a", "hero");
            supers.AddDynamic("enitiy", "green_goblin", "is_a", "villain");
            supers.AddDynamic("enitiy", "red_king", "is_a", "villain");
            supers.Add("hero", "is", "good", true);
            supers.Add("villain", "is", "bad", true);

            //2: create a GraphNet that knows about cities
            var cities = new GraphNet("cities", maxNumberOfPaths: 20);

            cities.Add("london", "is_a", "city");
            cities.Add("paris", "is_a", "city");
            cities.Add("uk", "is_a", "country");
            cities.Add("france", "is_a", "country");
            cities.Add("paris", "capital_of", "france");
            cities.Add("london", "capital_of", "uk");
            var yes = cities.Node(cities.Node(true), "input", "country", "city", "london", "paris", "uk", "france");
            var no  = cities.Node(cities.Node(false), "input", "country", "city", "london", "paris", "uk", "france");

            cities.Add(yes, true);
            cities.Add(no, true);


            //3: create a GraphNet that can do caculations
            var calc = new GraphNet("calc", maxPathLenght: 20);

            calc.Add("add_opp", "lable", "+");
            calc.Add(new Node("number"));
            Func <List <NodePath>, IEnumerable <int> > pullNumbers = (paths) =>
            {
                var numbers = paths.Where(p => p[2].Value.ToString().All(char.IsDigit) && p[4].Equals(calc.Node("number")))
                              .Select(p => int.Parse(p[2].Value.ToString()))
                              .Distinct();
                return(numbers);
            };
            var sum = new DynamicNode("sum"
                                      , onProcess: (node, graph, input, paths) => node.Result = pullNumbers(paths).Sum());

            sum.AddEdge("input", "number", calc);
            sum.AddEdge("opp", "add_opp", calc);
            calc.Add(sum, true);



            //4: create a GraphNet for parsing text
            var nlp = new GraphNet("nlp", maxNumberOfPaths: 5, maxPathLenght: 20);

            nlp.Add(new DynamicNode("nlp_out", (node, graph) => {
                node.Result = graph.AllEdges();
            }), true);
            nlp.RegisterDynamic("parse", (node, graph) =>
            {
                //add word nodes and mark if they are numbers
                nlp.Node(node, "word", node.ToString().Split(' '));
                foreach (var word in node.Edges.Select(e => e.Obj).ToList())
                {
                    if (word.ToString().All(char.IsDigit))
                    {
                        var edge = new Edge(word, nlp.Node("a"), nlp.Node("number"))
                        {
                            Internal = true
                        };
                        word.Edges.Add(edge);
                    }
                }
                Node.BaseOnAdd(node, graph);
            });

            //5: create the master GraphNet that contains the other GraphNets as nodes within it
            var gn = new GraphNet("gn", maxNumberOfPaths: 20, maxPathLenght: 20);

            gn.RegisterDynamic("ask", (node, graph) => {
                Node ask = nlp.DynamicNode("parse")(node.Value.ToString());
                //TODO: this would be better: node.AddEdge(graph.Node("nlp"), ask);
                nlp.Add(ask);
                node.Edges = nlp.AllEdges();
                nlp.Remove(ask);
                Node.BaseOnAdd(node, graph);
            });
            gn.DefaultInput = "ask";
            gn.Add(supers, true);
            gn.Add(cities, true);
            gn.Add(calc, true);
            //gn.LimitNumberOfPaths = true;

            //train the master GraphNet with some examples
            gn.Train(

                new Example(gn.Node("spider man"), "good"),
                new Example(gn.Node("4 + 1"), 5),
                new Example(gn.Node("10 + 12"), 22),
                new Example(gn.Node("green goblin"), "bad"),
                new Example(gn.Node("london is a city"), true),
                new Example(gn.Node("london is a country"), false),
                new Example(gn.Node("uk is a country"), true),
                new Example(gn.Node("uk is a city"), false)
                );

            //this master GraphNet can parse text and answer different types of questions:
            Assert.AreEqual("good", gn.Predict("hulk"));
            Assert.AreEqual("bad", gn.Predict("red king"));
            Assert.AreEqual(17, gn.Predict("5 + 12"));
            Assert.AreEqual(27, gn.Predict("7 + 20"));
            Assert.AreEqual(false, gn.Predict("paris is a country"));
            Assert.AreEqual(true, gn.Predict("paris is a city"));


            //TODO: Assert.AreEqual(27, gn.Predict("7 + 7"));
        }
        private GraphNet LoadCalcGraph()
        {
            var calc = new GraphNet("calc", maxPathLenght: 20, maxNumberOfPaths: 20);

            calc.LimitNumberOfPaths = true;
            calc.Add("add_opp", "lable", "+");
            calc.Add("times_opp", "lable", "*");
            calc.Add("times_opp", "lable", "x");
            calc.Add("minus_opp", "lable", "-");
            calc.Add(new Node("number"));
            calc.Add(new Node("a"));
            calc.Add(new Node("word"));

            Func <List <NodePath>, IEnumerable <int> > pullNumbers = (paths) =>
            {
                var numbers = paths.Where(p => p[2].Value.ToString() != "" && p[2].Value.ToString().All(char.IsDigit) && p[4].Equals(calc.Node("number")))
                              .Select(p => int.Parse(p[2].Value.ToString())).Distinct();
                return(numbers);
            };
            var sum = new DynamicNode("sum"
                                      , onProcess: (node, graph, input, paths) => node.Result = pullNumbers(paths).Sum());

            sum.AddEdge("input", "number", calc);
            sum.AddEdge("opp", "add_opp", calc);
            calc.Add(sum, true);


            //subtract
            var minus = (new DynamicNode("minus"
                                         , onProcess: (node, graph, input, paths) =>
            {
                var n = pullNumbers(paths);
                if (n.Count() > 0)
                {
                    node.Result = n.Aggregate((a, b) => a - b);
                }
            }));

            minus.AddEdge("input", "number", calc);
            minus.AddEdge("opp", "minus_opp", calc);
            calc.Add(minus, true);

            //multiply
            var times = new DynamicNode("times"
                                        , onProcess: (node, graph, input, paths) => node.Result = pullNumbers(paths).Aggregate(1, (acc, val) => acc * val));

            times.AddEdge("input", "number", calc);
            times.AddEdge("opp", "times_opp", calc);
            calc.Add(times, true);

            calc.RegisterDynamic("parse", (node, graph) =>
            {
                //add nodes for words
                var words = node.Value.ToString().Split(' ');
                graph.Node(node, "word", words);
                //mark any of those words that are numbers by adding an edge to the number node
                foreach (var e in node.Edges.ToArray().Where(e => e.Obj.ToString().All(char.IsDigit)))
                {
                    e.Obj.AddEdge(graph.Node("a"), graph.Node("number"));
                }

                Node.BaseOnAdd(node, graph);
            });

            calc.DefaultInput = "parse";

            calc.Train(new Example(calc.Node("4 + 1"), 5),
                       new Example(calc.Node("12 - 10"), 2),
                       new Example(calc.Node("5 * 3"), 15));


            return(calc);
        }
Esempio n. 4
0
        public void Calculator()
        {
            //create small graph of maths operators
            var gn = new GraphNet("calc");

            gn.Add("add_opp", "lable", "+");
            gn.Add("times_opp", "lable", "*");
            gn.Add("times_opp", "lable", "x");
            gn.Add("minus_opp", "lable", "-");
            gn.Add(new Node("number"));
            gn.Add(new Node("a"));
            gn.Add(new Node("word"));

            //and some output nodes that can do maths opperations (add,subtract and multiply)
            //these nodes pull all the numbers from the paths through the graph and apply their operation on them
            Func <List <NodePath>, IEnumerable <int> > pullNumbers = (paths) =>
            {
                var numbers = paths.Where(p => p[2].Value.ToString().All(char.IsDigit) && p[4].Equals(gn.Node("number")))
                              .Select(p => int.Parse(p[2].Value.ToString()));
                return(numbers);
            };

            //add
            var sum = new DynamicNode("sum", onProcess: (node, graph, input, paths) => node.Result = pullNumbers(paths).Sum());

            sum.AddEdge("input", "number", gn);
            sum.AddEdge("opp", "add_opp", gn);
            gn.Add(sum, true);


            //subtract
            var minus = new DynamicNode("minus"
                                        , onProcess: (node, graph, input, paths) => {
                var n = pullNumbers(paths);
                if (n.Count() > 0)
                {
                    node.Result = n.Aggregate((a, b) => a - b);
                }
            });

            minus.AddEdge("input", "number", gn);
            minus.AddEdge("opp", "minus_opp", gn);
            gn.Add(minus, true);


            //multiply
            var times = new DynamicNode("times", onProcess: (node, graph, input, paths) => node.Result = pullNumbers(paths).Aggregate(1, (acc, val) => acc * val));

            times.AddEdge("input", "number", gn);
            times.AddEdge("opp", "times_opp", gn);
            gn.Add(times, true);


            //then we register a tokeniser that adds the word nodes and marks any numbers
            gn.RegisterDynamic("parse", (node, graph) =>
            {
                //add nodes for words
                var words = node.Value.ToString().Split(' ');
                gn.Node(node, "word", words);
                //mark any of those words that are numbers by adding an edge to the number node
                foreach (var e in node.Edges.Where(e => e.Obj.ToString().All(char.IsDigit)))
                {
                    e.Obj.AddEdge(gn.Node("a"), gn.Node("number"));
                }

                Node.BaseOnAdd(node, graph);
            });

            //teach it the basic math funcitons
            gn.Train(
                new NodeExample(gn.DynamicNode("parse")("1 + 2"), gn.Node("sum"))
                , new NodeExample(gn.DynamicNode("parse")("1 - 2"), gn.Node("minus"))
                , new NodeExample(gn.DynamicNode("parse")("1 * 2"), gn.Node("times"))
                );

            //test
            Assert.AreEqual(15, gn.Predict(gn.DynamicNode("parse")("5 + 10")));
            Assert.AreEqual(2, gn.Predict(gn.DynamicNode("parse")("5 - 3")));
            Assert.AreEqual(4, gn.Predict(gn.DynamicNode("parse")("what is 5 - 1")));
            Assert.AreEqual(21, gn.Predict(gn.DynamicNode("parse")("3 * 7")));
            Assert.AreEqual(15, gn.Predict(gn.DynamicNode("parse")("3 x 5")));
        }