static void Main(string[] args)
        {
            Clauses C = new Clauses();

            //add KB to Clauses in CNF form
            C.Add(new List <string> {
                "a", "!b"
            });                                   //a+!b
            C.Add(new List <string> {
                "b", "!c", "!d"
            });                                         //b+!c+!d
            C.Add(new List <string> {
                "b", "c", "!d"
            });                                        //b+c+!d
            C.Add(new List <string> {
                "d"
            });                             //d


            //CHANGE THIS LINE TO CHECK OTHER LITERALS
            List <string> formula = new List <string>()
            {
                "!b"
            };                                                  //define as CNF, KB:=a --> formula/clause = !a to proof nonsatisfaction,

            Console.WriteLine(C.Print() + " =: " + formula[0]);
            //Console.ReadLine();

            //bool enumerates = Algorithm.linearResolution(C, new List<string>(formula));

            bool enumerates = Algorithm.Astar(C, formula);

            Console.WriteLine("KB := !" + C.Print(formula) + " is " + enumerates.ToString());
            Console.ReadLine();
        }
        public List <Node> getChildren()
        {
            List <Node> children = new List <Node>();

            for (int i = 0; i < Kb.allClauses.Count; i++)
            {
                if (canSolve(Kb.allClauses[i]))
                {
                    var clause1      = new List <string>(Kb.allClauses[i]);
                    var clause2      = new List <string>(ResolvedClause);
                    var solvedClause = Algorithm.resolutionRule(clause1, clause2, out int heuristic);
                    //Kb.allClauses.Add(solvedClause);
                    var tempKb = new Clauses {
                        allClauses = new List <List <string> >(Kb.allClauses)
                    };
                    tempKb.allClauses.Add(ResolvedClause);
                    //Need to add pathCost
                    var node = new Node()
                    {
                        Kb             = tempKb, //I wonder if it works, since syntax is a bit weird xD
                        parent         = this,
                        ResolvedClause = solvedClause,
                        Cost           = Cost + heuristic
                    };

                    children.Add(node);
                }
            }

            return(children);
        }
        //it is like Uniform cost search, but we have an ordered queue
        //path cost is set in problem class..
        // algo from Book: figure 3.14
        public static Boolean Astar(Clauses kb, List <string> formula)
        {
            //Node node = new Node(problem.initial(), null, null, 0);
            var node = new Node
            {
                Kb             = kb,
                ResolvedClause = formula,
                Cost           = 0
            };
            List <Node> frontier = new List <Node>(); //priority queue

            frontier.Add(node);
            List <Node> expanded = new List <Node>();
            var         index    = 0;

            while (frontier.Any())
            {
                frontier.OrderBy(x => x.Cost); //orders frontier in ascending order
                node = frontier[0];            //picks the one with lowest value
                Console.WriteLine(node.Kb.Print() + " =: " + node.Kb.Print(node.ResolvedClause));
                //Console.WriteLine("current node: " + node.State().print());
                if (node.Kb.allClauses.Count == 0 || frontier.Exists(x => x.ResolvedClause.Count() == 0))
                {
                    return(true);
                }

                frontier.Remove(node);
                expanded.Add(node);
                foreach (Node child in node.getChildren())
                {   //if child state not in frontier and not in expanded
                    if ((!frontier.Exists(x => x.Kb == child.Kb)))
                    {
                        if (!expanded.Exists(x => x.Kb == child.Kb))
                        {
                            frontier.Add(child);
                        }
                    }
                    else//here we know that chil is in frontier, as above if failed.
                    {   //if node already exist in frontier, but child can reach it wirh less cost, then replace node in frontier.
                        int i = frontier.FindIndex(x => x.Kb == child.Kb);
                        if (frontier[i].Cost > child.Cost)
                        {
                            frontier[i] = child;
                        }
                    }
                }
            }
            Console.WriteLine("\n" + "Frontier is empty, no solution found.");
            return(false); //if frontier is empty
        }