language-ext prelude modal logic in csharp

Here's an example of how to implement the Kripke semantics of modal logic using the language-ext and prelude libraries in C#:

main.cs
using static LanguageExt.Prelude;

// Define types for modal formulas and Kripke structures
public abstract class ModalFormula<A>
{
    public abstract bool Eval(Func<A, bool> valuation, Map<string, Set<A>> worlds);
}

public class AtomFormula<A> : ModalFormula<A>
{
    public readonly string Name;

    public AtomFormula(string name)
    {
        Name = name;
    }

    public override bool Eval(Func<A, bool> valuation, Map<string, Set<A>> worlds)
    {
        return worlds[Name].ForAll(valuation);
    }
}

public class NotFormula<A> : ModalFormula<A>
{
    public readonly ModalFormula<A> Inner;

    public NotFormula(ModalFormula<A> inner)
    {
        Inner = inner;
    }

    public override bool Eval(Func<A, bool> valuation, Map<string, Set<A>> worlds)
    {
        return !Inner.Eval(valuation, worlds);
    }
}

public class AndFormula<A> : ModalFormula<A>
{
    public readonly ModalFormula<A> Left;
    public readonly ModalFormula<A> Right;

    public AndFormula(ModalFormula<A> left, ModalFormula<A> right)
    {
        Left = left;
        Right = right;
    }

    public override bool Eval(Func<A, bool> valuation, Map<string, Set<A>> worlds)
    {
        return Left.Eval(valuation, worlds) && Right.Eval(valuation, worlds);
    }
}

public class OrFormula<A> : ModalFormula<A>
{
    public readonly ModalFormula<A> Left;
    public readonly ModalFormula<A> Right;

    public OrFormula(ModalFormula<A> left, ModalFormula<A> right)
    {
        Left = left;
        Right = right;
    }

    public override bool Eval(Func<A, bool> valuation, Map<string, Set<A>> worlds)
    {
        return Left.Eval(valuation, worlds) || Right.Eval(valuation, worlds);
    }
}

public class BoxFormula<A> : ModalFormula<A>
{
    public readonly string Relation;
    public readonly ModalFormula<A> Inner;

    public BoxFormula(string relation, ModalFormula<A> inner)
    {
        Relation = relation;
        Inner = inner;
    }

    public override bool Eval(Func<A, bool> valuation, Map<string, Set<A>> worlds)
    {
        return worlds[Relation].ForAll(w => Inner.Eval(valuation, worlds.MapValues(s => s.Filter(x => w.IsRelatedTo(x)))));
    }
}

public class DiamondFormula<A> : ModalFormula<A>
{
    public readonly string Relation;
    public readonly ModalFormula<A> Inner;

    public DiamondFormula(string relation, ModalFormula<A> inner)
    {
        Relation = relation;
        Inner = inner;
    }

    public override bool Eval(Func<A, bool> valuation, Map<string, Set<A>> worlds)
    {
        return worlds[Relation].Exists(w => Inner.Eval(valuation, worlds.MapValues(s => s.Filter(x => w.IsRelatedTo(x)))));
    }
}

public class World<A>
{
    public readonly Set<A> Valuation;
    public readonly Map<string, Set<World<A>>> Relations;

    public World(Set<A> valuation, Map<string, Set<World<A>>> relations)
    {
        Valuation = valuation;
        Relations = relations;
    }

    public bool IsRelatedTo(A a)
    {
        return Relations.Values.Exists(ws => ws.Exists(w => w.Valuation.Contains(a)));
    }
}

// Define a function to validate a Kripke structure for a given set of formulas
public static bool ValidateKripke<A>(Set<ModalFormula<A>> formulas, Set<World<A>> worlds)
{
    bool IsValuation(A a, World<A> w) => w.Valuation.Contains(a);

    bool IsRelatedTo(World<A> v1, string r, World<A> v2) =>
        v1.Relations.ContainsKey(r) && v1.Relations[r].Contains(v2);

    bool ValidateFormula(ModalFormula<A> formula, Func<World<A>, bool> In)
    {
        return formula switch
        {
            AtomFormula<A> f => In(_ => IsValuation(f.Name, _)),
            NotFormula<A> f => !ValidateFormula(f.Inner, In),
            AndFormula<A> f => ValidateFormula(f.Left, In) && ValidateFormula(f.Right, In),
            OrFormula<A> f => ValidateFormula(f.Left, In) || ValidateFormula(f.Right, In),
            BoxFormula<A> f => worlds.ForAll(w => IsRelatedTo(In(w) ? w : null, f.Relation, w) => ValidateFormula(f.Inner, _ => IsValuation(_, w))),
            DiamondFormula<A> f => worlds.Exists(w => IsRelatedTo(In(w) ? w : null, f.Relation, w) => ValidateFormula(f.Inner, _ => IsValuation(_, w))),
            _ => throw new InvalidOperationException(),
        };
    }

    return formulas.ForAll(f => worlds.ForAll(w => ValidateFormula(f, _ => _ == w)));
}
4327 chars
148 lines

This code defines a set of classes to represent modal formulas and Kripke structures, along with a function ValidateKripke that validates a Kripke structure for a given set of formulas. The language-ext library is used to provide functional programming constructs like Set and Map, and the prelude library is used to provide utility functions like ForAll and MapValues.

gistlibby LogSnag