Skip to content

Instantly share code, notes, and snippets.

@hodzanassredin
Created October 29, 2011 18:53
Show Gist options
  • Save hodzanassredin/1324924 to your computer and use it in GitHub Desktop.
Save hodzanassredin/1324924 to your computer and use it in GitHub Desktop.
prolog in csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Prolog1
{
class Program
{
static void Main(string[] args)
{
var p = new Prolog();
p.AddFact(new Fact("like", "dima", "apple"));
p.AddFact(new Fact("like", "alex", "apple"));
p.AddFact(new Fact("like", "serg", "microsoft"));
p.AddRule(IfSombodyLikeSomethingThenFrendIsSomeoneWhoLikeTheSame);
p.AddRule(EveryFactIsCommutattive);
var dimaAndAlexAreFriends = new Fact("friend", "dima", "alex");
Console.WriteLine(dimaAndAlexAreFriends + " " + p.Is(dimaAndAlexAreFriends).ToString());
var friends = p.Match(new Fact("friend", "", "dima"), true);
foreach (var friend in friends)
{
Console.WriteLine(friend);
}
Console.ReadKey();
}
public static IEnumerable<Fact> IfSombodyLikeSomethingThenFrendIsSomeoneWhoLikeTheSame(Fact newFact, IEnumerable<Fact> existingFacts)
{
if (newFact.Predicate != "like") return new List<Fact>();
return existingFacts.Where(f => f.Predicate == "like"
&& f.Subject != newFact.Subject
&& f.Object == newFact.Object).Select(x=>new Pair(x.Subject,newFact.Subject))
.GenerateCommutativeFacts("friend");
}
public static IEnumerable<Fact> EveryFactIsCommutattive(Fact newFact, IEnumerable<Fact> existingFacts)
{
return new List<Fact> { newFact.ToCommutative() };
}
}
public class Fact
{
public Fact(string predicate, string subject, string @object)
{
Predicate = predicate;
Subject = subject;
Object = @object;
}
public string Predicate;
public string Subject;
public string Object;
public bool Match(Fact f, bool commutative)
{
var res = (f.Object.Empty() || f.Object == Object)
&& (f.Subject.Empty() || f.Subject == Subject)
&& (f.Predicate.Empty() || f.Predicate == Predicate);
if (!res && commutative)
return (f.Object.Empty() || f.Object == Subject)
&& (f.Subject.Empty() || f.Subject == Object)
&& (f.Predicate.Empty() || f.Predicate == Predicate);
return res;
}
public override string ToString()
{
return Predicate + "(" + Subject + ", " + Object + ")";
}
public Fact ToCommutative()
{
return new Fact(Predicate, Object, Subject);
}
public static bool operator ==(Fact c1, Fact c2)
{
return c1.Object == c2.Object && c1.Subject == c2.Subject && c1.Predicate == c2.Predicate;
}
public static bool operator !=(Fact c1, Fact c2)
{
return !(c1 == c2);
}
public override bool Equals(object obj)
{
return obj is Fact && (obj as Fact) == this;
}
}
public class Pair
{
public Pair(string a, string b)
{
A = a;
B = b;
}
public string A;
public string B;
public override string ToString()
{
return B + " and " + A;
}
}
public static class Exts
{
public static bool Empty(this string str)
{
return string.IsNullOrEmpty(str);
}
public static IEnumerable<Fact> GenerateCommutativeFacts(this IEnumerable<Pair> pairs, String predicate)
{
return pairs.Select(x => new List<Fact>{ new Fact(predicate, x.A, x.B)
, new Fact(predicate, x.A, x.B)}).SelectMany(x => x);
}
public static IEnumerable<Fact> GenerateFacts(this IEnumerable<Pair> pairs, String predicate)
{
return pairs.Select(x => new Fact(predicate, x.A, x.B));
}
}
public class Prolog
{
public readonly List<Fact> facts = new List<Fact>();
List<Func<Fact, IEnumerable<Fact>, IEnumerable<Fact>>> rules = new List<Func<Fact, IEnumerable<Fact>, IEnumerable<Fact>>>();
private bool AddFact(Fact triplet, bool useRules)
{
if (facts.Count(x => x == triplet) == 0)
{
facts.Add(triplet);
if (rules.Count > 0 && useRules) GenerateNewFacts();
return true;
}
return false;
}
public bool AddFact(Fact triplet)
{
return AddFact(triplet, true);
}
private int AddFacts(IEnumerable<Fact> triplets, bool useRules)
{
int res = 0;
foreach (var fact in triplets)
{
if (AddFact(fact, useRules)) res++; ;
}
return res;
}
public void AddRule(Func<Fact, IEnumerable<Fact>, IEnumerable<Fact>> r)
{
rules.Add(r);
GenerateNewFacts();
}
private void GenerateNewFacts()
{
var done = false;
while (!done)
{
var newFacts = new List<Fact>();
foreach (var rule in rules)
{
foreach (var fact in facts)
{
newFacts.AddRange(rule(fact, facts));
}
}
;
done = AddFacts(newFacts, false) == 0;
}
}
public bool Is(Fact factToCheck)
{
return facts.Count(f => f == factToCheck) == 1;
}
public IEnumerable<Fact> Match(Fact factToMatch, bool commutative)
{
return facts.Where(f => f.Match(factToMatch, commutative));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment