private static SubstitutionMap Unify(Atom a, Atom b, SubstitutionMap subMap)
        {
            var output = new SubstitutionMap(subMap);

            if (a.Name != b.Name || a.Arguments.Count != b.Arguments.Count)
            {
                output.Failure = true;
                return(output);
            }

            var atomA = new Atom(a);
            var atomB = new Atom(b);

            atomA.ApplySubMap(output);
            atomB.ApplySubMap(output);

            var disagreement = false;

            for (var i = 0; i < atomA.Arguments.Count; i++)
            {
                var argA = atomA.Arguments[i];
                var argB = atomB.Arguments[i];
                if (argA.EqualTo(argB))
                {
                    continue;
                }

                disagreement = true;
                if (argA.CanMapTo(argB))
                {
                    subMap.Add(argA, argB);
                    var newOutput = Unify(atomA, atomB, subMap);
                    newOutput.Changed = true;
                    return(newOutput);
                }
                if (argB.CanMapTo(argA))
                {
                    subMap.Add(argB, argA);
                    var newOutput = Unify(atomA, atomB, subMap);
                    newOutput.Changed = true;
                    return(newOutput);
                }
                break;
            }
            if (disagreement)
            {
                output.Failure = true;
            }
            return(output);
        }
        private static SubstitutionMap UnifySubMap(SubstitutionMap subMapA, SubstitutionMap subMapB)
        {
            var output = new SubstitutionMap();

            foreach (var keyA in subMapA.Keys)
            {
                if (subMapB.ContainsKey(keyA))
                {
                    output.Failure = true;
                    return(output);
                }
                output.Add(keyA, subMapA.Get(keyA));
            }
            foreach (var keyB in subMapB.Keys)
            {
                output.Add(keyB, subMapB.Get(keyB));
            }

            return(output);
        }