----------------------------------------------------------------------------
-- 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
)
putStrLn "== my Example closure test =============================" 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 "== my 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 "== my Example for is_basis_of test ========================="
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
) --
-- 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+IFtGRF0KcHJvamVjdF9GRHMgYXMgZmRzIGFzMSA9IHVuZGVmaW5lZAoKCi0tIHRoZSBtYWluIGZ1bmN0aW9uIGZvciBydW5uaW5nIHRlc3QgZXhhbXBsZXMKbWFpbiA9IGRvCglwdXRTdHJMbiAiPT0gRXhhbXBsZSAzLjggZm9yIGNsb3N1cmUgdGVzdCA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PSIKCWxldCBmZHMgPSBbIChbIkEiLCJCIl0sWyJDIl0pLAkJCgkJCQkoWyJCIiwiQyJdLFsiQSIsIkQiXSksICAKCQkJCShbIkQiXSxbIkUiXSksCQkJCgkJCQkoWyJDIiwiRiJdLFsiQiJdKSBdCQoJbGV0IHhzID0gWyJBIiwiQiJdCglwdXRTdHJMbiAkICJTID0gIiArKyBzaG93RkRzIGZkcwoJcHV0U3RyTG4gJCBzaG93QXR0clNldCB4cyArKyAiKyA9ICIgKysgc2hvd0F0dHJTZXQgKGNsb3N1cmUgZmRzIHhzKQoJcHV0U3RyTG4gIiIKCQoJcHV0U3RyTG4gIj09IG15IEV4YW1wbGUgY2xvc3VyZSB0ZXN0ID09PT09PT09PT09PT09PT09PT09PT09PT09PT09IgoJbGV0IGZkc18xID0gWyAoWyJBIl0sWyJEIl0pLAkJCgkJCQkoWyJCIiwiQyJdLFsiQSIsIkQiXSksICAKCQkJCShbIkYiLCAiRyJdLFsiSCJdKSwJCQoJCQkJKFsiQyIsIkYiXSxbIkIiXSkgXQkJCglsZXQgeHNfMSA9IFsiQSIsIkQiXQoJcHV0U3RyTG4gJCAiUyA9ICIgKysgc2hvd0ZEcyBmZHNfMQoJcHV0U3RyTG4gJCBzaG93QXR0clNldCB4c18xICsrICIrID0gIiArKyBzaG93QXR0clNldCAoY2xvc3VyZSBmZHMgeHNfMSkKCXB1dFN0ckxuICIiCgktLQoJCglwdXRTdHJMbiAiPT0gbXkgRXhhbXBsZSBmb3IgaXNfZGVyaXZlZF9mcm9tIHRlc3QgPT09PT09PT09PT09PT09PT09PT09IgoKCWxldCBmZHMyID0gWyAoWyJBIl0sIFsiQyJdKSAKICAgICAgICAgICAgICAgLCAoWyJDIl0sIFsiRCJdKQogICAgICAgICAgICAgICAsIChbIkMiLCJGIl0sIFsiRyJdKSBdICAKCWxldCBmZF90ZXN0MSA9IChbIkEiXSwgWyJEIl0pIAoJbGV0IGZkX3Rlc3QyID0gKFsiQSJdLCBbIkciXSkgICAgIAoJcHV0U3RyTG4gJCAiUyA9ICIgKysgc2hvd0ZEcyBmZHMyCglwdXRTdHJMbiAkICJBIC0+IEQgaXMgZGVyaXZlZCBmcm9tIFMgOiAiICsrIHNob3cgKGlzX2Rlcml2ZWRfZnJvbSBmZF90ZXN0MSBmZHMyKSAgCglwdXRTdHJMbiAkICJBIC0+IEcgaXMgZGVyaXZlZCBmcm9tIFMgOiAiICsrIHNob3cgKGlzX2Rlcml2ZWRfZnJvbSBmZF90ZXN0MiBmZHMyKSAgIAoJcHV0U3RyTG4gIiIKCQoJCglsZXQgZmRzMl8yID0gWyAoWyJBIl0sIFsiRCJdKSAKICAgICAgICAgICAgICAgLCAoWyJEIl0sIFsiRyJdKSAKICAgICAgICAgICAgICAgLCAoWyJDIl0sIFsiRiJdKSBdICAKCWxldCBmZF90ZXN0MV8xID0gKFsiQSJdLCBbIkYiXSkgCglsZXQgZmRfdGVzdDJfMiA9IChbIkQiXSwgWyJHIl0pICAgICAKCXB1dFN0ckxuICQgIlMgPSAiICsrIHNob3dGRHMgZmRzMl8yCglwdXRTdHJMbiAkICJBIC0+IEYgaXMgZGVyaXZlZCBmcm9tIFMgOiAiICsrIHNob3cgKGlzX2Rlcml2ZWRfZnJvbSBmZF90ZXN0MV8xIGZkczJfMikgIAoJcHV0U3RyTG4gJCAiRCAtPiBHIGlzIGRlcml2ZWQgZnJvbSBTIDogIiArKyBzaG93IChpc19kZXJpdmVkX2Zyb20gZmRfdGVzdDJfMiBmZHMyXzIpICAgCglwdXRTdHJMbiAiIgoKCgktLQoJcHV0U3RyTG4gIj09IG15IEV4YW1wbGUgZm9yIGlzX2Jhc2lzX29mIHRlc3QgPT09PT09PT09PT09PT09PT09PT09PT09PSIKICAgCgoJbGV0IHNfZmRzMiA9IFsgKFsiQSJdLCBbIkMiXSksIChbIkMiXSwgWyJEIl0pLCAoWyJEIl0sIFsiRyJdKSBdCQkKCWxldCBiX2Jhc2lzMiA9IFsgKFsiQSIsIkIiXSwgWyJFIl0pLCAoWyJHIl0sIFsiQSJdKSBdCQkJCQoJcHV0U3RyTG4gJCAiUyA9ICIgKysgc2hvd0ZEcyBzX2ZkczIKCXB1dFN0ckxuICQgIkIgPSAiICsrIHNob3dGRHMgYl9iYXNpczIKCXB1dFN0ckxuICQgIkIgaXMgYmFzaXMgb2YgUyA6ICIgKysgc2hvdyAoaXNfYmFzaXNfb2YgYl9iYXNpczIgc19mZHMyKQoJcHV0U3RyTG4gIiIKCQoJbGV0IHNfZmRzMyA9IFsgKFsiQSIsICJCIl0sIFsiQyJdKSwgKFsiQyJdLCBbIkQiXSksIChbIkQiXSwgWyJHIl0pIF0JIAoJbGV0IGJfYmFzaXMzID0gWyAoWyJBIiwiQiJdLCBbIkMiXSksIChbIkMiXSwgWyJEIl0pLCAoWyJEIl0sIFsiRyJdKSBdCQkJCglwdXRTdHJMbiAkICJTID0gIiArKyBzaG93RkRzIHNfZmRzMwoJcHV0U3RyTG4gJCAiQiA9ICIgKysgc2hvd0ZEcyBiX2Jhc2lzMwoJcHV0U3RyTG4gJCAiQiBpcyBiYXNpcyBvZiBTIDogIiArKyBzaG93IChpc19iYXNpc19vZiBiX2Jhc2lzMyBzX2ZkczMpCglwdXRTdHJMbiAiIgoJLS0KCgotLSBoZWxwZXIgZnVuY3Rpb25zIGZvciBwcmV0dHkgcHJpbnRpbmcKc2hvd0ZEIDo6IEZEIC0+IFN0cmluZwpzaG93RkQgKGFzLGJzKSA9IGNvbmNhdCAkIGludGVyc3BlcnNlICIgIiAoYXMgKysgIi0+IiA6IGJzKQoKc2hvd0ZEcyA6OiBbRkRdIC0+IFN0cmluZwpzaG93RkRzIGZkcyA9ICJ7IiArKyBjb25jYXQgKGludGVyc3BlcnNlICIsICIgJCBtYXAgc2hvd0ZEIGZkcykgKysgIn0iCgpzaG93QXR0clNldCA6OiBbQXR0cl0gLT4gU3RyaW5nCnNob3dBdHRyU2V0IGFzID0gInsiICsrIGNvbmNhdCAoaW50ZXJzcGVyc2UgIiwiIGFzKSArKyAifSIK