5 changed files with 423 additions and 0 deletions
@ -0,0 +1,39 @@ |
|||||||
|
module ArithmeticsPL where |
||||||
|
import Unification |
||||||
|
import Resolution |
||||||
|
import Data.Semigroup |
||||||
|
import Data.Maybe |
||||||
|
|
||||||
|
vw = Var "w" |
||||||
|
vx = Var "x" |
||||||
|
vy = Var "y" |
||||||
|
vz = Var "z" |
||||||
|
z = Func "0" [] |
||||||
|
s n = Func "s" [n] |
||||||
|
|
||||||
|
sn 0 b = b |
||||||
|
sn n b = s (sn (n-1) b) |
||||||
|
|
||||||
|
add x y z = Func "add" [x, y, z] |
||||||
|
mult x y z = Func "mult" [x, y, z] |
||||||
|
|
||||||
|
s1 = Star [Pos (add z vy vy)] |
||||||
|
s2 = Star [Pos (add (s vx) vy (s vz)), Neg (add vx vy vz)] |
||||||
|
|
||||||
|
cadd :: Constellation |
||||||
|
cadd = Const [ |
||||||
|
Star [Pos (add z vy vy)], |
||||||
|
Star [Pos (add (s vx) vy (s vz)), Neg (add vx vy vz)]] |
||||||
|
|
||||||
|
qadd :: Int -> Int -> Constellation |
||||||
|
qadd n m = cadd <> |
||||||
|
Const [Star [Neg (add (sn n z) (sn m z) (Var "r")), NC (Var "r")]] |
||||||
|
|
||||||
|
cmult :: Constellation |
||||||
|
cmult = Const [ |
||||||
|
Star [Pos (mult z vx z)], |
||||||
|
Star [Pos (mult (s vx) vy vz), Neg (mult vx vy vw), Neg (add vy vw vz)]] |
||||||
|
|
||||||
|
qmult :: Int -> Int -> Constellation |
||||||
|
qmult n m = cadd <> cmult <> |
||||||
|
Const [Star [Neg (mult (sn n z) (sn m z) (Var "r")), NC (Var "r")]] |
@ -0,0 +1,9 @@ |
|||||||
|
module Main where |
||||||
|
import Unification |
||||||
|
import Resolution |
||||||
|
import Data.Maybe |
||||||
|
import ArithmeticsPL |
||||||
|
import qualified Data.Set as Set |
||||||
|
|
||||||
|
main = do |
||||||
|
return () |
@ -0,0 +1,21 @@ |
|||||||
|
module PrettyPrinter where |
||||||
|
import Data.Maybe |
||||||
|
import qualified Data.Set as Set |
||||||
|
|
||||||
|
{- Stars -} |
||||||
|
|
||||||
|
addsymbol :: Char -> Maybe Char -> [String] -> String |
||||||
|
addsymbol _ after [] = "" |
||||||
|
addsymbol sym after (w:ws) = w ++ go ws |
||||||
|
where |
||||||
|
go [] = "" |
||||||
|
go (v:vs) = |
||||||
|
case after of |
||||||
|
Nothing -> sym : (v ++ go vs) |
||||||
|
Just after' -> sym : after' : (v ++ go vs) |
||||||
|
|
||||||
|
addop :: Char -> [String] -> String |
||||||
|
addop op w = addsymbol op Nothing w |
||||||
|
|
||||||
|
addcomma :: [String] -> String |
||||||
|
addcomma = addsymbol ',' (Just ' ') |
@ -0,0 +1,260 @@ |
|||||||
|
module Resolution where |
||||||
|
import qualified Unification |
||||||
|
import Data.Maybe |
||||||
|
import Data.List |
||||||
|
import Data.Tuple |
||||||
|
import PrettyPrinter as PrettyPrinter |
||||||
|
import Control.Arrow |
||||||
|
import Control.Monad |
||||||
|
import Data.Semigroup |
||||||
|
import qualified Data.Set as Set |
||||||
|
|
||||||
|
{- ======================================== |
||||||
|
Definitions |
||||||
|
======================================== -} |
||||||
|
|
||||||
|
data Polarized a = Pos a | Neg a | NC a deriving (Ord, Eq) |
||||||
|
type Ray = Polarized Unification.Term |
||||||
|
newtype Star = Star { get_star :: [Ray] } |
||||||
|
newtype Constellation = Const { get_const :: [Star] } |
||||||
|
newtype Link = Link { get_link :: ((Ray, Ray), Int, Int) } |
||||||
|
newtype StarGraph = StarGraph { get_graph :: ([Star], [Link]) } |
||||||
|
type UGraph = StarGraph |
||||||
|
type Diagram = StarGraph |
||||||
|
|
||||||
|
instance Functor Polarized where |
||||||
|
fmap f (Pos t) = Pos (f t) |
||||||
|
fmap f (Neg t) = Neg (f t) |
||||||
|
fmap f (NC t) = NC (f t) |
||||||
|
|
||||||
|
instance Eq Star where |
||||||
|
(Star s1) == (Star s2) = sort s1 == sort s2 |
||||||
|
|
||||||
|
instance Eq Constellation where |
||||||
|
(Const s1) == (Const s2) = sort s1 == sort s2 |
||||||
|
|
||||||
|
instance Eq Link where |
||||||
|
Link (e, i, j) == Link (e', i', j') = |
||||||
|
(i==i' && j==j' && i/=j) || (i==i' && j==j' && i==j && e==swap e') |
||||||
|
|
||||||
|
instance Ord Star where |
||||||
|
compare (Star s1) (Star s2) = compare s1 s2 |
||||||
|
|
||||||
|
instance Show a => Show (Polarized a) where |
||||||
|
show (Pos t) = "+" ++ show t |
||||||
|
show (Neg t) = "-" ++ show t |
||||||
|
show (NC t) = show t |
||||||
|
|
||||||
|
instance Show Star where |
||||||
|
show (Star s) = show s |
||||||
|
|
||||||
|
instance Show Constellation where |
||||||
|
show (Const c) = show $ PrettyPrinter.addop '+' (map show c) |
||||||
|
|
||||||
|
instance Show Link where |
||||||
|
show (Link x) = show x |
||||||
|
|
||||||
|
instance Show StarGraph where |
||||||
|
show (StarGraph (v, e)) = |
||||||
|
"------------------------\n" ++ |
||||||
|
"Vertices:\n" ++ unlines (mapInd (\x i -> show i ++ ":" ++ show x) v) ++ |
||||||
|
"Edges:\n" ++ unlines (map show e) |
||||||
|
|
||||||
|
instance Semigroup Constellation where |
||||||
|
(Const c1) <> (Const c2) = Const (c1 ++ c2) |
||||||
|
|
||||||
|
mapInd :: (a -> Int -> b) -> [a] -> [b] |
||||||
|
mapInd f l = zipWith f l [0..] |
||||||
|
|
||||||
|
change_color :: String -> String -> Ray -> Ray |
||||||
|
change_color s s' r@(Neg (Unification.Func f ts)) |
||||||
|
| f==s = Neg (Unification.Func s' ts) |
||||||
|
change_color s s' r@(Pos (Unification.Func f ts)) |
||||||
|
| f==s = Neg (Unification.Func s' ts) |
||||||
|
change_color _ _ r = r |
||||||
|
|
||||||
|
dual :: Ray -> Ray -> Bool |
||||||
|
dual (Pos _) (Neg _) = True |
||||||
|
dual (Neg _) (Pos _) = True |
||||||
|
dual _ _ = False |
||||||
|
|
||||||
|
get_term :: Ray -> Unification.Term |
||||||
|
get_term (Pos t) = t |
||||||
|
get_term (Neg t) = t |
||||||
|
get_term (NC t) = t |
||||||
|
|
||||||
|
vars_ray :: Ray -> [Unification.Id] |
||||||
|
vars_ray (Pos t) = Unification.vars t |
||||||
|
vars_ray (Neg t) = Unification.vars t |
||||||
|
vars_ray (NC t) = Unification.vars t |
||||||
|
|
||||||
|
vars_star :: Star -> [Unification.Id] |
||||||
|
vars_star (Star s) = concat $ map vars_ray s |
||||||
|
|
||||||
|
subst_ray :: Unification.Subst -> Ray -> Ray |
||||||
|
subst_ray = fmap . Unification.subst |
||||||
|
|
||||||
|
subst_rays :: Unification.Subst -> [Ray] -> [Ray] |
||||||
|
subst_rays = map . subst_ray |
||||||
|
|
||||||
|
extends_ray :: String -> Ray -> Ray |
||||||
|
extends_ray = fmap . Unification.extends_varname |
||||||
|
|
||||||
|
extends_star :: String -> Star -> Star |
||||||
|
extends_star s (Star e) = Star (map (extends_ray s) e) |
||||||
|
|
||||||
|
rays :: Constellation -> [Ray] |
||||||
|
rays (Const cs) = [r | s<-cs, r<-(get_star s)] |
||||||
|
|
||||||
|
{- ======================================== |
||||||
|
Unification graph |
||||||
|
======================================== -} |
||||||
|
|
||||||
|
matchable_rays :: Ray -> Ray -> Bool |
||||||
|
matchable_rays r1 r2 = dual r1 r2 && |
||||||
|
Unification.matchable (get_term r1, get_term r2) |
||||||
|
|
||||||
|
get_links :: Star -> Star -> [(Ray, Ray)] |
||||||
|
get_links (Star s1) (Star s2) = |
||||||
|
[(r1, r2) | r1<-s1, r2<-s2, matchable_rays r1 r2] |
||||||
|
|
||||||
|
ugraph :: Constellation -> UGraph |
||||||
|
ugraph (Const cs) = |
||||||
|
let imax = length cs - 1 in |
||||||
|
let pairs = [(i, j) | i<-[0..imax], j<-[0..imax], i<=j] in |
||||||
|
let e = foldl (\acc (i, j) -> |
||||||
|
let links = get_links (cs!!i) (cs!!j) in |
||||||
|
let make_edge e = Link (e, i, j) in |
||||||
|
if links==[] then acc else (map make_edge links) ++ acc) [] pairs in |
||||||
|
StarGraph (cs, nub e) |
||||||
|
|
||||||
|
{- ======================================== |
||||||
|
Actualisation |
||||||
|
======================================== -} |
||||||
|
|
||||||
|
make_edge :: [Star] -> (Int, Int) -> (Int, Int) -> Link |
||||||
|
make_edge xs (is1, ir1) (is2, ir2) = |
||||||
|
let (Star s1) = xs !! is1 in |
||||||
|
let (Star s2) = xs !! is2 in |
||||||
|
Link ((s1!!ir1, s2!!ir2), is1, is2) |
||||||
|
|
||||||
|
equations :: Diagram -> [Unification.Equation] |
||||||
|
equations (StarGraph (v, e)) = |
||||||
|
map (\(Link ((t, u), i, j)) -> |
||||||
|
let new_t = Unification.extends_varname (show i) (get_term t) in |
||||||
|
let new_u = Unification.extends_varname (show j) (get_term u) in |
||||||
|
(new_t, new_u)) e |
||||||
|
|
||||||
|
appears_in_link :: Ray -> Link -> Bool |
||||||
|
appears_in_link r (Link ((t, u), _, _)) = r==t || r==u |
||||||
|
|
||||||
|
already_linked :: Link -> [Link] -> Bool |
||||||
|
already_linked (Link ((t, u), i, j)) ls = |
||||||
|
any (\(Link ((t', u'), i', j')) -> |
||||||
|
(t==t' && i==i') || (u==u' && j==j') || |
||||||
|
(t==u' && i==j') || (u==t' && j==i')) ls |
||||||
|
|
||||||
|
free_rays :: Diagram -> [Ray] |
||||||
|
free_rays (StarGraph (v, e)) = |
||||||
|
let linked = concat [[(extends_ray (show i) r, i), (extends_ray (show j) r', j)] | (Link ((r, r'), i, j))<-e] in |
||||||
|
let stars = mapInd (curry id) v in |
||||||
|
let rays = concat $ map (\(Star s, i) -> map (\r -> (extends_ray (show i) r, i)) s) stars in |
||||||
|
map fst (rays \\ linked) |
||||||
|
|
||||||
|
correct :: Diagram -> Bool |
||||||
|
correct d = free_rays d /= [] && (isJust $ Unification.solution (equations d)) |
||||||
|
|
||||||
|
actualise :: Diagram -> Maybe Star |
||||||
|
actualise d = do |
||||||
|
u <- Unification.solution (equations d) |
||||||
|
pure $ Star (subst_rays u (free_rays d)) |
||||||
|
|
||||||
|
fusions :: Star -> Star -> [Star] |
||||||
|
fusions (Star star1) (Star star2) = do |
||||||
|
ray1 <- star1 |
||||||
|
ray2 <- star2 |
||||||
|
guard (ray1 `matchable_rays` ray2) |
||||||
|
u <- maybeToList $ Unification.solution [(get_term ray1, get_term ray2)] |
||||||
|
[Star (subst_rays u (delete ray1 star1 ++ delete ray2 star2))] |
||||||
|
|
||||||
|
{- ======================================== |
||||||
|
Execution |
||||||
|
======================================== -} |
||||||
|
|
||||||
|
connect :: (Star, Int) -> (Star, Int) -> [Link] |
||||||
|
connect (Star s1, i) (Star s2, j) = do |
||||||
|
r1 <- s1 |
||||||
|
r2 <- s2 |
||||||
|
guard (r1 `matchable_rays` r2) |
||||||
|
[Link ((r1, r2), i, j)] |
||||||
|
|
||||||
|
saturated :: Constellation -> Diagram -> Bool |
||||||
|
saturated cs d = |
||||||
|
let free = free_rays d in |
||||||
|
let rs = rays cs in |
||||||
|
free_rays d /= [] && |
||||||
|
[(r1, r2) | r1<-free, r2<-rs, r1 `matchable_rays` r2] == [] |
||||||
|
|
||||||
|
shift_link :: Int -> Link -> Link |
||||||
|
shift_link k (Link (e, i, j)) = Link (e, i+k, j+k) |
||||||
|
|
||||||
|
singleStep :: Constellation -> Diagram -> [Diagram] |
||||||
|
singleStep (Const cs) d@(StarGraph (stars, links)) = |
||||||
|
let cs' = mapInd (curry id) cs in |
||||||
|
let stars' = mapInd (curry id) stars in |
||||||
|
do |
||||||
|
(s1, i) <- cs' |
||||||
|
(s2, j) <- stars' |
||||||
|
link <- connect (s1, 0) (s2, j+1) |
||||||
|
guard (not $ already_linked link (map (shift_link 1) links)) |
||||||
|
pure (StarGraph (s1:stars, link:map (shift_link 1) links)) |
||||||
|
|
||||||
|
allCorrectDiagrams :: Constellation -> [Diagram] |
||||||
|
allCorrectDiagrams (Const []) = [] |
||||||
|
allCorrectDiagrams (Const cs) = go [StarGraph ([cs!!0], [])] where |
||||||
|
go (d : ds) = do |
||||||
|
d : go (ds ++ filter correct (singleStep (Const cs) d)) |
||||||
|
go [] = [] |
||||||
|
|
||||||
|
allCorrectSaturatedDiagrams :: Constellation -> [Diagram] |
||||||
|
allCorrectSaturatedDiagrams cs = filter (saturated cs) $ allCorrectDiagrams cs |
||||||
|
|
||||||
|
execution :: Constellation -> Constellation |
||||||
|
execution cs = Const (catMaybes $ map actualise (allCorrectSaturatedDiagrams cs)) |
||||||
|
|
||||||
|
|
||||||
|
skeleton :: Constellation -> Constellation |
||||||
|
|
||||||
|
|
||||||
|
deleteAt :: Int -> [a] -> [a] |
||||||
|
deleteAt idx xs = lft ++ rgt |
||||||
|
where (lft, (_:rgt)) = splitAt idx xs |
||||||
|
|
||||||
|
fusion :: (Star, Int) -> (Star, Int) -> [Star] |
||||||
|
fusion (Star s1, i) (Star s2, j) = |
||||||
|
let r1 = s1 !! i in |
||||||
|
let r2 = s2 !! j in |
||||||
|
case Unification.solution [(get_term r1, get_term r2)] of |
||||||
|
Just u -> [Star (subst_rays u (deleteAt i s1 ++ deleteAt j s2))] |
||||||
|
Nothing -> [] |
||||||
|
|
||||||
|
step :: Constellation -> [Star] -> [Star] |
||||||
|
step (Const cs) stars = do |
||||||
|
s1' <- cs |
||||||
|
s2' <- stars |
||||||
|
let s1 = get_star s1' |
||||||
|
let s2 = get_star s2' |
||||||
|
guard (s1 /= s2) |
||||||
|
i <- [0..length s1 - 1] |
||||||
|
j <- [0..length s2 - 1] |
||||||
|
guard ((s1 !! i) `matchable_rays` (s2 !! j)) |
||||||
|
fusion (s1', i) (s2', j) |
||||||
|
|
||||||
|
steps :: Int -> Constellation -> [Star] -> [Star] |
||||||
|
steps 0 _ mem = mem |
||||||
|
steps k cs mem = |
||||||
|
let new = step cs mem in |
||||||
|
if new == [] then mem else mem ++ steps (k-1) cs new |
||||||
|
|
||||||
|
exec :: Constellation -> Constellation |
||||||
|
exec wcs@(Const cs) = Const (steps 0 wcs cs) |
@ -0,0 +1,94 @@ |
|||||||
|
module Unification where |
||||||
|
import PrettyPrinter |
||||||
|
import Data.List |
||||||
|
import Data.Maybe |
||||||
|
import Control.Arrow |
||||||
|
|
||||||
|
{- ======================================== |
||||||
|
Definitions |
||||||
|
======================================== -} |
||||||
|
|
||||||
|
type Id = String |
||||||
|
data Term = |
||||||
|
Var Id |
||||||
|
| Func Id [Term] |
||||||
|
deriving Eq |
||||||
|
|
||||||
|
type Subst = [(Id, Term)] |
||||||
|
type Equation = (Term, Term) |
||||||
|
|
||||||
|
instance Show Term where |
||||||
|
show (Var x) = x |
||||||
|
show (Func f []) = f |
||||||
|
show (Func f xs) = f ++ "(" ++ (addcomma (map show xs)) ++ ")" |
||||||
|
|
||||||
|
instance Ord Term where |
||||||
|
compare (Var x) (Var y) = compare x y |
||||||
|
compare (Var _) (Func _ _) = LT |
||||||
|
compare (Func _ _) (Var _) = GT |
||||||
|
compare (Func f fs) (Func g gs) = |
||||||
|
case compare f g of |
||||||
|
EQ -> compare fs gs |
||||||
|
LT -> LT |
||||||
|
GT -> GT |
||||||
|
|
||||||
|
{- ======================================== |
||||||
|
Predicates |
||||||
|
======================================== -} |
||||||
|
|
||||||
|
indom :: Id -> Subst -> Bool |
||||||
|
indom x s = isJust $ lookup x s |
||||||
|
|
||||||
|
occurs :: Id -> Term -> Bool |
||||||
|
occurs x (Var y) = (x==y) |
||||||
|
occurs x (Func _ ts) = any (occurs x) ts |
||||||
|
|
||||||
|
{- ======================================== |
||||||
|
Renaming |
||||||
|
======================================== -} |
||||||
|
|
||||||
|
extends_varname :: String -> Term -> Term |
||||||
|
extends_varname e (Var x) = Var (x++e) |
||||||
|
extends_varname e (Func f ts) = Func f (map (extends_varname e) ts) |
||||||
|
|
||||||
|
vars :: Term -> [Id] |
||||||
|
vars (Var x) = [x] |
||||||
|
vars (Func _ xs) = concat (map vars xs) |
||||||
|
|
||||||
|
{- ======================================== |
||||||
|
Substitution |
||||||
|
======================================== -} |
||||||
|
|
||||||
|
apply :: Subst -> Id -> Term |
||||||
|
apply ((y, t):s) x = if (x==y) then t else apply s x |
||||||
|
|
||||||
|
subst :: Subst -> Term -> Term |
||||||
|
subst s (Var x) = if indom x s then (apply s x) else (Var x) |
||||||
|
subst s (Func f ts) = Func f (map (subst s) ts) |
||||||
|
|
||||||
|
{- ======================================== |
||||||
|
Unification |
||||||
|
======================================== -} |
||||||
|
|
||||||
|
solve' :: [Equation] -> Subst -> Maybe Subst |
||||||
|
solve' [] s = Just s |
||||||
|
solve' ((Var x, t):ps) s = if (Var x == t) then solve' ps s else elim x t ps s |
||||||
|
solve' ((t, Var x):ps) s = elim x t ps s |
||||||
|
solve' ((Func f fs, Func g gs):ps) s = |
||||||
|
if (f == g) then solve' (zip fs gs ++ ps) s else Nothing |
||||||
|
|
||||||
|
elim :: Id -> Term -> [Equation] -> Subst -> Maybe Subst |
||||||
|
elim x t ps s = |
||||||
|
if occurs x t then Nothing |
||||||
|
else let sigma_xy = subst [(x, t)] in |
||||||
|
solve' (map (\(t1, t2) -> (sigma_xy t1, sigma_xy t2)) ps) |
||||||
|
((x,t):map (\(y,u) -> (y, sigma_xy u)) s) |
||||||
|
|
||||||
|
solution :: [Equation] -> Maybe Subst |
||||||
|
solution p = solve' p [] |
||||||
|
|
||||||
|
solvable :: [Equation] -> Bool |
||||||
|
solvable p = isJust (solution p) |
||||||
|
|
||||||
|
matchable :: Equation -> Bool |
||||||
|
matchable p = isJust $ solution [(extends_varname "0" *** extends_varname "1") p] |
Loading…
Reference in new issue