----------------------------------------------------------------------------
-- HNU CE 데이터베이스(2025년 2학기 02분반): FD 관련 프로그래밍 과제
----------------------------------------------------------------------------
-- 이름: 이재혁
-- 학번: 20210501
----------------------------------------------------------------------------
import Data. List
-- representing sets withi lists
subset xs ys
= null ( xs\\ys
) -- subset test in terms of set subtraction
-- functional dependency A B C -> D E encoded as (["A","B","C"],["D","E"])
type FD = ( [ Attr] , [ Attr] )
type Attr
= String -- attributes are represented as strings
-- 3.2.4절 Algorithm 3.7
closure :: [ FD] -> [ Attr] -> [ Attr]
closure fds xs = if xs/= xs1 then closure fds xs1 else sort xs
where xs1
= foldr union xs
[ cs
| ( bs
, cs
) <- fds
, bs `subset` xs
]
-- fd가 기존의 fds로부터 유도 가능한지 검사 (closure 활용한 간단한 함수)
is
_ derived
_ from
:: FD
-> [ FD
] -> Bool is
_ derived
_ from fd fds
= all ( `
elem ` closureSet
) rhs
where
closureSet = closure fds lhs
-- 3.2.7절 관련 fds의 basis인지 검사
is
_ basis
_ of
:: [ FD
] -> [ FD
] -> Bool is_ basis_ of basis fds =
equivalent basis fds &&
all singletonRHS basis
&& all nonredundant basis
&& where
singletonRHS
( _, rhs
) = length rhs
== 1 nonredundant fd
= not ( ( is
_ derived
_ from fd
( remove fd basis
) ) )
minimalLHS ( lhs, rhs) =
all ( \a
-> not ( is
_ derived
_ from
( lhs \\
[ a
] , rhs
) basis
) ) lhs
equivalent a b =
all ( `is
_ derived
_ from` a
) b
&& all ( `is
_ derived
_ from` b
) a
-- 3.2.7절 basis가 미니멀한지 검사
is
_ minimal
:: [ FD
] -> Bool
-- 3.2.8절 Algorithm 3.12
project_ FDs :: [ Attr] -> [ FD] -> [ Attr] -> [ FD]
-- the main function for running test examples
main = do
putStrLn "== Example 3.8 for closure test =============================" let fds = [ ( [ "A" , "B" ] , [ "C" ] ) ,
( [ "B" , "C" ] , [ "A" , "D" ] ) ,
( [ "D" ] , [ "E" ] ) ,
( [ "C" , "F" ] , [ "B" ] ) ]
let xs = [ "A" , "B" ]
putStrLn $ showAttrSet xs
++ "+ = " ++ showAttrSet
( closure fds xs
)
let fds_ 1 = [ ( [ "A" ] , [ "D" ] ) ,
( [ "B" , "C" ] , [ "A" , "D" ] ) ,
( [ "F" , "G" ] , [ "H" ] ) ,
( [ "C" , "F" ] , [ "B" ] ) ]
let xs_ 1 = [ "A" , "D" ]
putStrLn $ showAttrSet xs
_ 1
++ "+ = " ++ showAttrSet
( closure fds xs
_ 1
) --
putStrLn "== Example ... for is_derived_from test ====================="
let fds2 = [ ( [ "A" ] , [ "C" ] )
, ( [ "C" ] , [ "D" ] )
, ( [ "C" , "F" ] , [ "G" ] ) ]
let fd_ test1 = ( [ "A" ] , [ "D" ] )
let fd_ test2 = ( [ "A" ] , [ "G" ] )
putStrLn $ "A -> D is derived from S : " ++ show ( is
_ derived
_ from fd
_ test1 fds2
) putStrLn $ "A -> G is derived from S : " ++ show ( is
_ derived
_ from fd
_ test2 fds2
)
let fds2_ 2 = [ ( [ "A" ] , [ "D" ] )
, ( [ "D" ] , [ "G" ] )
, ( [ "C" ] , [ "F" ] ) ]
let fd_ test1_ 1 = ( [ "A" ] , [ "F" ] )
let fd_ test2_ 2 = ( [ "D" ] , [ "G" ] )
putStrLn $ "A -> F is derived from S : " ++ show ( is
_ derived
_ from fd
_ test1
_ 1 fds2
_ 2
) putStrLn $ "D -> G is derived from S : " ++ show ( is
_ derived
_ from fd
_ test2
_ 2 fds2
_ 2
)
--
putStrLn "== Example ... for is_basis_of test ========================="
let s_ fds = [ ( [ "A" ] , [ "B" ] ) , ( [ "B" ] , [ "C" ] ) , ( [ "C" ] , [ "D" ] ) ]
let b_ basis = [ ( [ "A" ] , [ "B" ] ) , ( [ "B" ] , [ "C" ] ) , ( [ "C" ] , [ "D" ] ) ]
putStrLn $ "B is basis of S : " ++ show ( is
_ basis
_ of b
_ basis s
_ fds
)
let s_ fds2 = [ ( [ "A" ] , [ "C" ] ) , ( [ "C" ] , [ "D" ] ) , ( [ "D" ] , [ "G" ] ) ]
let b_ basis2 = [ ( [ "A" , "B" ] , [ "E" ] ) , ( [ "G" ] , [ "A" ] ) ]
putStrLn $ "B is basis of S : " ++ show ( is
_ basis
_ of b
_ basis2 s
_ fds2
)
let s_ fds3 = [ ( [ "A" , "B" ] , [ "C" ] ) , ( [ "C" ] , [ "D" ] ) , ( [ "D" ] , [ "G" ] ) ]
let b_ basis3 = [ ( [ "A" , "B" ] , [ "C" ] ) , ( [ "C" ] , [ "D" ] ) , ( [ "D" ] , [ "G" ] ) ]
putStrLn $ "B is basis of S : " ++ show ( is
_ basis
_ of b
_ basis3 s
_ fds3
) --
putStrLn "== Example ... for is_minimal test ==========================" --
putStrLn "== Example ... for project_FDs test =========================" putStrLn "S = { ..->.., ..->.., ... ... ... }" putStrLn "S1 = { ..->.., ..->.., ... ... }" --
-- helper functions for pretty printing
showFD
( as , bs
) = concat $ intersperse
" " ( as ++ "->" : bs
)
showFDs fds
= "{" ++ concat ( intersperse
", " $ map showFD fds
) ++ "}"
showAttrSet
:: [ Attr
] -> String showAttrSet
as = "{" ++ concat ( intersperse
"," as ) ++ "}"
IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KLS0gSE5VIENFIOuNsOydtO2EsOuyoOydtOyKpCgyMDI164WEIDLtlZnquLAgMDLrtoTrsJgpOiBGRCDqtIDroKgg7ZSE66Gc6re4656Y67CNIOqzvOygnAotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCi0tIOydtOumhDog7J207J6s7ZiBCi0tIO2VmeuyiDogMjAyMTA1MDEKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKaW1wb3J0IERhdGEuTGlzdAotLSByZXByZXNlbnRpbmcgc2V0cyB3aXRoaSBsaXN0cwoKc3Vic2V0IHhzIHlzID0gbnVsbCAoeHNcXHlzKQktLSBzdWJzZXQgdGVzdCBpbiB0ZXJtcyBvZiBzZXQgc3VidHJhY3Rpb24KCi0tIGZ1bmN0aW9uYWwgZGVwZW5kZW5jeSBBIEIgQyAtPiBEIEUgZW5jb2RlZCBhcyAoWyJBIiwiQiIsIkMiXSxbIkQiLCJFIl0pCnR5cGUgRkQgPSAoW0F0dHJdLCBbQXR0cl0pCnR5cGUgQXR0ciA9IFN0cmluZyAgLS0gYXR0cmlidXRlcyBhcmUgcmVwcmVzZW50ZWQgYXMgc3RyaW5ncwoKCi0tICAzLjIuNOygiCBBbGdvcml0aG0gMy43CmNsb3N1cmUgOjogW0ZEXSAtPiBbQXR0cl0gLT4gW0F0dHJdICAgCmNsb3N1cmUgZmRzIHhzID0gaWYgeHMvPXhzMSB0aGVuIGNsb3N1cmUgZmRzIHhzMSBlbHNlIHNvcnQgeHMKCXdoZXJlIHhzMSA9IGZvbGRyIHVuaW9uIHhzIFtjcyB8IChicyxjcykgPC0gZmRzLCBicyBgc3Vic2V0YCB4c10KCi0tIGZk6rCAIOq4sOyhtOydmCBmZHProZzrtoDthLAg7Jyg64+EIOqwgOuKpe2VnOyngCDqsoDsgqwgKGNsb3N1cmUg7Zmc7Jqp7ZWcIOqwhOuLqO2VnCDtlajsiJgpCmlzX2Rlcml2ZWRfZnJvbSA6OiBGRCAtPiBbRkRdIC0+IEJvb2wKaXNfZGVyaXZlZF9mcm9tIGZkIGZkcyA9IGFsbCAoYGVsZW1gIGNsb3N1cmVTZXQpIHJocwogIHdoZXJlCiAgICBsaHMgPSBmc3QgZmQKICAgIHJocyA9IHNuZCBmZAogICAgY2xvc3VyZVNldCA9IGNsb3N1cmUgZmRzIGxocwoKCgotLSAgMy4yLjfsoIgg6rSA66CoIGZkc+ydmCBiYXNpc+yduOyngCDqsoDsgqwKaXNfYmFzaXNfb2YgOjogW0ZEXSAtPiBbRkRdIC0+IEJvb2wKaXNfYmFzaXNfb2YgYmFzaXMgZmRzID0KICAgIGVxdWl2YWxlbnQgYmFzaXMgZmRzICYmICAgICAgICAgICAgIAogICAgYWxsIHNpbmdsZXRvblJIUyBiYXNpcyAmJiAgICAgICAgICAgCiAgICBhbGwgbm9ucmVkdW5kYW50IGJhc2lzICYmICAgICAgIAogICAgYWxsIG1pbmltYWxMSFMgYmFzaXMgICAgICAgICAgICAgICAgIAogIHdoZXJlCiAgICAKICAgIHNpbmdsZXRvblJIUyAoXywgcmhzKSA9IGxlbmd0aCByaHMgPT0gMQogICAgbm9ucmVkdW5kYW50IGZkID0gbm90ICgoaXNfZGVyaXZlZF9mcm9tIGZkIChyZW1vdmUgZmQgYmFzaXMpKSkKCiAgICBtaW5pbWFsTEhTIChsaHMsIHJocykgPQogICAgICAgIGFsbCAoXGEgLT4gbm90IChpc19kZXJpdmVkX2Zyb20gKGxocyBcXCBbYV0sIHJocykgYmFzaXMpKSBsaHMKCiAgICByZW1vdmUgeCA9IGZpbHRlciAoLz0geCkKICAgIGVxdWl2YWxlbnQgYSBiID0KICAgICAgICBhbGwgKGBpc19kZXJpdmVkX2Zyb21gIGEpIGIgJiYKICAgICAgICBhbGwgKGBpc19kZXJpdmVkX2Zyb21gIGIpIGEKCgotLSAgMy4yLjfsoIggYmFzaXPqsIAg66+464uI66mA7ZWc7KeAIOqygOyCrAppc19taW5pbWFsIDo6IFtGRF0gLT4gQm9vbCAgICAgICAgICAgICAKaXNfbWluaW1hbCBiYXNpcyA9IHVuZGVmaW5lZAoKLS0gMy4yLjjsoIggQWxnb3JpdGhtIDMuMTIKcHJvamVjdF9GRHMgOjogW0F0dHJdIC0+IFtGRF0gLT4gW0F0dHJdIC0+IFtGRF0KcHJvamVjdF9GRHMgYXMgZmRzIGFzMSA9IHVuZGVmaW5lZAoKCi0tIHRoZSBtYWluIGZ1bmN0aW9uIGZvciBydW5uaW5nIHRlc3QgZXhhbXBsZXMKbWFpbiA9IGRvCglwdXRTdHJMbiAiPT0gRXhhbXBsZSAzLjggZm9yIGNsb3N1cmUgdGVzdCA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PSIKCWxldCBmZHMgPSBbIChbIkEiLCJCIl0sWyJDIl0pLAkJCgkJCQkoWyJCIiwiQyJdLFsiQSIsIkQiXSksICAKCQkJCShbIkQiXSxbIkUiXSksCQkJCgkJCQkoWyJDIiwiRiJdLFsiQiJdKSBdCQoJbGV0IHhzID0gWyJBIiwiQiJdCglwdXRTdHJMbiAkICJTID0gIiArKyBzaG93RkRzIGZkcwoJcHV0U3RyTG4gJCBzaG93QXR0clNldCB4cyArKyAiKyA9ICIgKysgc2hvd0F0dHJTZXQgKGNsb3N1cmUgZmRzIHhzKQoJcHV0U3RyTG4gIiIKCQoJbGV0IGZkc18xID0gWyAoWyJBIl0sWyJEIl0pLAkJCgkJCQkoWyJCIiwiQyJdLFsiQSIsIkQiXSksICAKCQkJCShbIkYiLCAiRyJdLFsiSCJdKSwJCQoJCQkJKFsiQyIsIkYiXSxbIkIiXSkgXQkJCglsZXQgeHNfMSA9IFsiQSIsIkQiXQoJcHV0U3RyTG4gJCAiUyA9ICIgKysgc2hvd0ZEcyBmZHNfMQoJcHV0U3RyTG4gJCBzaG93QXR0clNldCB4c18xICsrICIrID0gIiArKyBzaG93QXR0clNldCAoY2xvc3VyZSBmZHMgeHNfMSkKCXB1dFN0ckxuICIiCgktLQoJCglwdXRTdHJMbiAiPT0gRXhhbXBsZSAuLi4gZm9yIGlzX2Rlcml2ZWRfZnJvbSB0ZXN0ID09PT09PT09PT09PT09PT09PT09PSIKCglsZXQgZmRzMiA9IFsgKFsiQSJdLCBbIkMiXSkgCiAgICAgICAgICAgICAgICwgKFsiQyJdLCBbIkQiXSkKICAgICAgICAgICAgICAgLCAoWyJDIiwiRiJdLCBbIkciXSkgXSAgCglsZXQgZmRfdGVzdDEgPSAoWyJBIl0sIFsiRCJdKSAKCWxldCBmZF90ZXN0MiA9IChbIkEiXSwgWyJHIl0pICAgICAKCXB1dFN0ckxuICQgIlMgPSAiICsrIHNob3dGRHMgZmRzMgoJcHV0U3RyTG4gJCAiQSAtPiBEIGlzIGRlcml2ZWQgZnJvbSBTIDogIiArKyBzaG93IChpc19kZXJpdmVkX2Zyb20gZmRfdGVzdDEgZmRzMikgIAoJcHV0U3RyTG4gJCAiQSAtPiBHIGlzIGRlcml2ZWQgZnJvbSBTIDogIiArKyBzaG93IChpc19kZXJpdmVkX2Zyb20gZmRfdGVzdDIgZmRzMikgICAKCXB1dFN0ckxuICIiCgkKCQoJbGV0IGZkczJfMiA9IFsgKFsiQSJdLCBbIkQiXSkgCiAgICAgICAgICAgICAgICwgKFsiRCJdLCBbIkciXSkgCiAgICAgICAgICAgICAgICwgKFsiQyJdLCBbIkYiXSkgXSAgCglsZXQgZmRfdGVzdDFfMSA9IChbIkEiXSwgWyJGIl0pIAoJbGV0IGZkX3Rlc3QyXzIgPSAoWyJEIl0sIFsiRyJdKSAgICAgCglwdXRTdHJMbiAkICJTID0gIiArKyBzaG93RkRzIGZkczJfMgoJcHV0U3RyTG4gJCAiQSAtPiBGIGlzIGRlcml2ZWQgZnJvbSBTIDogIiArKyBzaG93IChpc19kZXJpdmVkX2Zyb20gZmRfdGVzdDFfMSBmZHMyXzIpICAKCXB1dFN0ckxuICQgIkQgLT4gRyBpcyBkZXJpdmVkIGZyb20gUyA6ICIgKysgc2hvdyAoaXNfZGVyaXZlZF9mcm9tIGZkX3Rlc3QyXzIgZmRzMl8yKSAgIAoJcHV0U3RyTG4gIiIKCgoJLS0KCXB1dFN0ckxuICI9PSBFeGFtcGxlIC4uLiBmb3IgaXNfYmFzaXNfb2YgdGVzdCA9PT09PT09PT09PT09PT09PT09PT09PT09IgogICAgCglsZXQgc19mZHMgPSBbIChbIkEiXSwgWyJCIl0pLCAoWyJCIl0sIFsiQyJdKSwgKFsiQyJdLCBbIkQiXSkgXQkJCglsZXQgYl9iYXNpcyA9IFsgKFsiQSJdLCBbIkIiXSksIChbIkIiXSwgWyJDIl0pLCAoWyJDIl0sIFsiRCJdKSBdIAkKCQkJCQoJcHV0U3RyTG4gJCAiUyA9ICIgKysgc2hvd0ZEcyBzX2ZkcwoJcHV0U3RyTG4gJCAiQiA9ICIgKysgc2hvd0ZEcyBiX2Jhc2lzCglwdXRTdHJMbiAkICJCIGlzIGJhc2lzIG9mIFMgOiAiICsrIHNob3cgKGlzX2Jhc2lzX29mIGJfYmFzaXMgc19mZHMpCglwdXRTdHJMbiAiIgoKCWxldCBzX2ZkczIgPSBbIChbIkEiXSwgWyJDIl0pLCAoWyJDIl0sIFsiRCJdKSwgKFsiRCJdLCBbIkciXSkgXQkJCglsZXQgYl9iYXNpczIgPSBbIChbIkEiLCJCIl0sIFsiRSJdKSwgKFsiRyJdLCBbIkEiXSkgXQkJCQkKCXB1dFN0ckxuICQgIlMgPSAiICsrIHNob3dGRHMgc19mZHMyCglwdXRTdHJMbiAkICJCID0gIiArKyBzaG93RkRzIGJfYmFzaXMyCglwdXRTdHJMbiAkICJCIGlzIGJhc2lzIG9mIFMgOiAiICsrIHNob3cgKGlzX2Jhc2lzX29mIGJfYmFzaXMyIHNfZmRzMikKCXB1dFN0ckxuICIiCgkKCWxldCBzX2ZkczMgPSBbIChbIkEiLCAiQiJdLCBbIkMiXSksIChbIkMiXSwgWyJEIl0pLCAoWyJEIl0sIFsiRyJdKSBdCSAKCWxldCBiX2Jhc2lzMyA9IFsgKFsiQSIsIkIiXSwgWyJDIl0pLCAoWyJDIl0sIFsiRCJdKSwgKFsiRCJdLCBbIkciXSkgXQkJCQoJcHV0U3RyTG4gJCAiUyA9ICIgKysgc2hvd0ZEcyBzX2ZkczMKCXB1dFN0ckxuICQgIkIgPSAiICsrIHNob3dGRHMgYl9iYXNpczMKCXB1dFN0ckxuICQgIkIgaXMgYmFzaXMgb2YgUyA6ICIgKysgc2hvdyAoaXNfYmFzaXNfb2YgYl9iYXNpczMgc19mZHMzKQoJcHV0U3RyTG4gIiIKCS0tCgkKCQoJcHV0U3RyTG4gIj09IEV4YW1wbGUgLi4uIGZvciBpc19taW5pbWFsIHRlc3QgPT09PT09PT09PT09PT09PT09PT09PT09PT0iCglwdXRTdHJMbiAiQiA9IHsgLi4tPi4sIC4uLT4uLCAuLi4gfSIKCXB1dFN0ckxuICJCIGlzIG1pbmltYWwgOiBUcnVlL0ZhbHNlIgoJcHV0U3RyTG4gIiIKCS0tCglwdXRTdHJMbiAiPT0gRXhhbXBsZSAuLi4gZm9yIHByb2plY3RfRkRzIHRlc3QgPT09PT09PT09PT09PT09PT09PT09PT09PSIKCXB1dFN0ckxuICJMID0gey4uLi4uLn0iCglwdXRTdHJMbiAiUyA9IHsgLi4tPi4uLCAuLi0+Li4sIC4uLiAuLi4gLi4uIH0iCglwdXRTdHJMbiAiTDEgPSB7Li4ufSIKCXB1dFN0ckxuICJTMSA9IHsgLi4tPi4uLCAuLi0+Li4sIC4uLiAuLi4gfSIKCXB1dFN0ckxuICIiCgktLQoKLS0gaGVscGVyIGZ1bmN0aW9ucyBmb3IgcHJldHR5IHByaW50aW5nCnNob3dGRCA6OiBGRCAtPiBTdHJpbmcKc2hvd0ZEIChhcyxicykgPSBjb25jYXQgJCBpbnRlcnNwZXJzZSAiICIgKGFzICsrICItPiIgOiBicykKCnNob3dGRHMgOjogW0ZEXSAtPiBTdHJpbmcKc2hvd0ZEcyBmZHMgPSAieyIgKysgY29uY2F0IChpbnRlcnNwZXJzZSAiLCAiICQgbWFwIHNob3dGRCBmZHMpICsrICJ9IgoKc2hvd0F0dHJTZXQgOjogW0F0dHJdIC0+IFN0cmluZwpzaG93QXR0clNldCBhcyA9ICJ7IiArKyBjb25jYXQgKGludGVyc3BlcnNlICIsIiBhcykgKysgIn0iCg==