Translating Minimal Cover into 3NF - decomposition

I have the below functional dependencies in minimal cover, and I am looking to put them into 3NF lossless join and dependency preserving decomposition.
FD 1: {A} -> {B,C,D,E};
FD 2: {F} -> {G,H,I,J,K};
FD 3: {G,H,I,L} -> {M};
FD 4: {N} -> {O,P,F};
FD 5: {N,B} -> {Q,L};
Key: {A,N}
The key is A,N and are the determinants of FD1 and FD4, I am unsure whether my 3NF decomposition should contain and extra table that contains all of the attributes from the FD1 and FD4 so that I can preserve the key? or that they should not be merged so that I can reduce redundancy if they were to be merged?
Thanks in advance!

In general the 3NF is found through an algorithm that details all the steps that produce a correct decomposition. Such algorithms are described in all good books on databases. For instance, in your case, the so-called “synthesis” algorithm produces the following decomposition:
R1 {A B C D E}
R2 {B L N Q}
R3 {F G H I J K}
R4 {G H I L M}
R5 {F N O P}
R6 {A N}
Note that the relation R6 contains the key of the original relation, and this is necessary to guarantee the lossless join property.

Related

Looking for some help understanding where I'm going from (Software Foundations, Binom.v)

I am working through Software Foundations and am a bit stuck. Here is a link for reference: https://softwarefoundations.cis.upenn.edu/vfa-current/Binom.html
I am stuck on the proof "abs_perm," reproduced here.
Theorem abs_perm: forall p al bl,
priq p -> Abs p al -> Abs p bl -> Permutation al bl.
This is a "2 star" question, so it should be pretty easy. The fact that it is proving to be difficult makes me think that the issue is my "Abs" relation. My inductive relation is as follows:
Inductive priqueue_elems: list tree -> list key -> Prop :=
| priqueue_elems_base: priqueue_elems [] nil
| priqueue_elems_next_list: forall l b b' v,
priqueue_elems l b ->
Permutation b' (v::b) ->
priqueue_elems (insert v l) b'
The issue I end up having is that I get something like "insert x1 l1 = insert x2 l2" (via inversions in my proof) and I can't go anywhere from there.
insert in this case is not injective...it seems like insert x [] = insert x [Leaf].
The above relation allows me to directly know that I have "priq l" available, but priq is defined such that if there is more than one element, the first is a Leaf so...yeah.
I think the issue is with my relation (which is modeled after their tree_elems), but I'm having a bit of "proof block." My guess is that I shouldn't have insert in the relation construction, but it's unclear what other structure there is to the priqueue.
Another avenue would just to have it straight up on "list tree," but then it seems like well-formedness could be an issue.
Otherwise I need some sort of theorem on insert. I tried a bunch, but wasn't able to get a proof together.
For example,
Lemma equals_inserts_permute: forall l1 l2 p1 p2 v1 v2,
priqueue_elems l1 p1 ->
priqueue_elems l2 p2 ->
insert v1 l1 = insert v2 l2 -> Permutation (v1::p1) (v2::p2)
Which would give me the ability to relate insert that I need, but...I haven't been able to crack that proof either.
Would appreciate any help!

Surprising implicit assumptions in intuitionistic definitions

I'm trying to make sense of something that surprised me. Consider the following two definitions.
Require Import List.
Variable A:Type.
Inductive NoDup : list A -> Prop :=
NoDup_nil : NoDup nil
| NoDup_cons : forall x l, ~ In x l -> NoDup l -> NoDup (x :: l).
Inductive Dup : list A -> Prop :=
Dup_hd : forall x l, In x l -> Dup (x :: l)
| Dup_tl : forall x l, Dup l -> Dup (x :: l).
My first intuition was that they say the same thing (but negated). However, #Arthur Azevedo De Amorim showed that they are not exactly equivalent (or see here). If ~ NoDup l -> Dup l then it must be the case that forall (a b:A), ~ a <> b -> a = b. Thus, an extra assumption on the type A sneaks in if one uses ~ NoDup rather than Dup when stating one's proof goal.
I tried to spot where this extra assumption is introduced, to get a mental model of what happened, so I will see it myself next time. My current explanation is that
it is the ~ In x l argument to NoDup_cons that is responsible, because
~ In x l terms can only be created if one can prove that a certain x is different from the first element in the list, the second element in the list, etc.
So when I destruct a term om type NoDup (_::_) I get a term ~ In _ _ that can only have been created for a type A for which ~ a <> b -> a = b must hold.
Q: is that an ok 'informal' way to think about it, or is there a better way to understand it, so I don't fall into that trap again?
Also, I found that the Coq library contains NoDup and not Dup, so perhaps some lemmas are weaker than they need to be, because they were formulated using NoDup instead of Dup. However, they could be formulated with Dup because ~Dup l -> NoDup l.
I think the lesson to take out of this example is that you need to be more careful when thinking about negations in intuitionistic logic. In particular, your statement "they say the same thing (but negated)" makes sense in classical logic: it means either of the equivalent statements P <-> ~Q or ~P <-> Q. However, in intuitionistic logic these two statements are not equivalent, so you would have to be more specific about which of these two (if either) is actually true.
In this case, it is true that NoDup l is equivalent to ~ Dup l. What is not true in general is that Dup l is a normal proposition (recall that a proposition P is called normal if ~~P -> P, in which case it's easy to conclude that P <-> ~~P). Therefore, ~ NoDup l is equivalent to ~~ Dup l, which in general is a strictly weaker statement than Dup l.
One possible way to think about the difference between the two is: from a concrete proof of Dup l, it would be possible to extract a pair of indices such that the corresponding entries of l are equal (not literally as a function in Coq due to the restrictions on eliminating from Prop to Type, but you could definitely prove a lemma that there exists such a pair of indices). On the other hand, a concrete proof of ~ NoDup l simply gives a way to take a purported proof of NoDup l and derive a contradiction from it - from which you can't necessarily extract any particular pair of indices.
(I do agree it's somewhat odd that the standard library has only NoDup and not Dup.)

BCNF Decomposition algorithm not working

I have the following problem: R(ABCDEFG) and F ={ AB->CD, C->EF, G->A, G->F, CE ->F}. Clearly, B & G should be part of the key as they are not part of the dependent set. Further, BG+ = ABCDEFG, hence candidate key. Clearly, AB->CD violates BCNF. But when I follow the algorithm, I do not end up in any answer. Probably doing something wrong. Can anyone show me how to apply the algorithm correctly to reach the decomposition?
Thanks in advance.
First, you should calculate a canonical cover of the dependencies. In this case it is:
{ A B → C
A B → D
C → E
C → F
G → A
G → F } >
Since the (unique) candidate key is B G, no functional dependency satisfies the BNCF. Then, starting from any functional dependency X → Y that violates the BCNF, we calculate the closure of X, X+, and replace the original relation R<T,F> with two relations, R1<X+> and R2<T - X+ + X>. So, chosing in this case the dependency A B → C, we replace the original relation with:
R1 < (A B C D E F) ,
{ A B → C
A B → D
C → E
C → F} >
and:
R2 < (A B G) ,
{ G → A } >
Then we check each decomposed relation to see if it satisfies the BCNF, otherwise we apply recursively the algorithm.
In this case, for instance, in R1 the key is A B, so C -> E violates the BCNF, and we replace R1 with:
R3 < (C E F) ,
{ C → E
C → F } >
and:
R4 < (A B C D) ,
{ A B → C
A B → D } >
two relations that satisfy the BCNF.
Finally, since R2 too does not satisfy the BCNF (beacuse the key is B G), we decompose R2 in:
R5 < (A G) ,
{ G → A } >
and:
R6 < (B G) ,
{ } >
that are in BCNF.
So the final decomposition is constituted by the relations: R3, R4, R5, and R6. We can also note that the dependency G → F on the original relation is lost in the decomposition.

The right way to normalize database into 3NF

I have this database:
R(A, B, C, D, E)
Keys: A
F = {A -> B, D -> E, C -> D}
I normalize it into 3NF like this:
R(A, B, C, D, E)
Keys: AD
F = {AD -> B, AD -> E, C -> D}
What I do is when I check D -> E, D is not a superkey and E is not a key attribute, so I treat D and A as a superkey {AD}. When I check C -> D, C is not a key but D is a key attribute so it's OK.
Is my normalization correctly?
There is a problem in your input data. If the relation R has the dependencies F = {A -> B, D -> E, C -> D}, then A cannot be a key. In fact, a key is a set of attributes whose closure determines all the attributes of the relation, which is not the case here, since:
A+ = AB
From F, the (only) possible key is AC, in fact
AC+ = ABCD
Normalizing means to reduce the redundancy by decomposing a relation in other relations in which the functional dependencies do not violate the normal form, and such that joining the decomposed relations, one can obtain the original one.
In you solution, you do not decompose the relation, but only change the set of dependencies with other dependencies not implied by the first set.
A correct decomposition would be instead the following:
R1 < (A B) ,
{ A → B } >
R2 < (C D) ,
{ C → D } >
R3 < (D E) ,
{ D → E } >
R4 < (A C) ,
{ } >
The algorithm to decompose a relation into 3NF can be found on any good book on databases.

Can I extract a Coq proof as a Haskell function?

Ever since I learned a little bit of Coq I wanted to learn to write a Coq proof of the so-called division algorithm that is actually a logical proposition: forall n m : nat, exists q : nat, exists r : nat, n = q * m + r
I recently accomplished that task using what I learned from Software Foundations.
Coq being a system for developing constructive proofs, my proof is in effect a method to construct suitable values q and r from values m and n.
Coq has an intriguing facility for "extracting" an algorithm in Coq's algorithm language (Gallina) to general-purpose functional programming languages including Haskell.
Separately I have managed to write the divmod operation as a Gallina Fixpoint and extract that. I want to note carefully that that task is not what I'm considering here.
Adam Chlipala has written in Certified Programming with Dependent Types that "Many fans of the Curry-Howard correspondence support the idea of extracting programs from proofs. In reality, few users of Coq and related tools do any such thing."
Is it even possible to extract the algorithm implicit in my proof to Haskell? If it is possible, how would it be done?
Thanks to Prof. Pierce's summer 2012 video 4.1 as Dan Feltey suggested, we see that the key is that the theorem to be extracted must provide a member of Type rather than the usual kind of propositions, which is Prop.
For the particular theorem the affected construct is the inductive Prop ex and its notation exists. Similarly to what Prof. Pierce has done, we can state our own alternate definitions ex_t and exists_t that replace occurrences of Prop with occurrences of Type.
Here is the usual redefinition of ex and exists similarly as they are defined in Coq's standard library.
Inductive ex (X:Type) (P : X->Prop) : Prop :=
ex_intro : forall (witness:X), P witness -> ex X P.
Notation "'exists' x : X , p" := (ex _ (fun x:X => p))
(at level 200, x ident, right associativity) : type_scope.
Here are the alternate definitions.
Inductive ex_t (X:Type) (P : X->Type) : Type :=
ex_t_intro : forall (witness:X), P witness -> ex_t X P.
Notation "'exists_t' x : X , p" := (ex_t _ (fun x:X => p))
(at level 200, x ident, right associativity) : type_scope.
Now, somewhat unfortunately, it is necessary to repeat both the statement and the proof of the theorem using these new definitions.
What in the world??
Why is it necessary to make a reiterated statement of the theorem and a reiterated proof of the theorem, that differ only by using an alternative definition of the quantifier??
I had hoped to use the existing theorem in Prop to prove the theorem over again in Type. That strategy fails when Coq rejects the proof tactic inversion for a Prop in the environment when that Prop uses exists and the goal is a Type that uses exists_t. Coq reports "Error: Inversion would require case analysis on sort Set which is not allowed
for inductive definition ex." This behavior occurred in Coq 8.3. I am not certain that it
still occurs in Coq 8.4.
I think the need to repeat the proof is actually profound although I doubt that I personally am quite managing to perceive its profundity. It involves the facts that Prop is "impredicative" and Type is not impredicative, but rather, tacitly "stratified". Predicativity is (if I understand correctly) vulnerability to Russell's paradox that the set S of sets that are not members of themselves can neither be a member of S, nor a non-member of S. Type avoids Russell's paradox by tacitly creating a sequence of higher types that contain lower types. Because Coq is drenched in the formulae-as-types interpretation of the Curry-Howard correspondence, and if I am getting this right, we can even understand stratification of types in Coq as a way to avoid Gödel incompleteness, the phenomenon that certain formulae express constraints on formulae such as themselves and thereby become unknowable as to their truth or falsehood.
Back on planet Earth, here is the repeated statement of the theorem using "exists_t".
Theorem divalg_t : forall n m : nat, exists_t q : nat,
exists_t r : nat, n = plus (mult q m) r.
As I have omitted the proof of divalg, I will also omit the proof of divalg_t. I will only mention that we do have the good fortune that proof tactics including "exists" and "inversion" work just the same with our new definitions "ex_t" and "exists_t".
Finally, the extraction itself is accomplished easily.
Extraction Language Haskell.
Extraction "divalg.hs" divalg_t.
The resulting Haskell file contains a number of definitions, the heart of which is the reasonably nice code, below. And I was only slightly hampered by my near-total ignorance of the Haskell programming language. Note that Ex_t_intro creates a result whose type is Ex_t; O and S are the zero and the successor function from Peano arithmetic; beq_nat tests Peano numbers for equality; nat_rec is a higher-order function that recurs over the function among its arguments. The definition of nat_rec is not shown here. At any rate it is generated by Coq according to the inductive type "nat" that was defined in Coq.
divalg :: Nat -> Nat -> Ex_t Nat (Ex_t Nat ())
divalg n m =
case m of {
O -> Ex_t_intro O (Ex_t_intro n __);
S m' ->
nat_rec (Ex_t_intro O (Ex_t_intro O __)) (\n' iHn' ->
case iHn' of {
Ex_t_intro q' hq' ->
case hq' of {
Ex_t_intro r' _ ->
let {k = beq_nat r' m'} in
case k of {
True -> Ex_t_intro (S q') (Ex_t_intro O __);
False -> Ex_t_intro q' (Ex_t_intro (S r') __)}}}) n}
Update 2013-04-24: I know a bit more Haskell now. To assist others in reading the extracted code above, I'm presenting the following hand-rewritten code that I claim is equivalent and more readable. I'm also presenting the extracted definitions Nat, O, S, and nat_rec that I did not eliminate.
-- Extracted: Natural numbers (non-negative integers)
-- in the manner in which Peano defined them.
data Nat =
O
| S Nat
deriving (Eq, Show)
-- Extracted: General recursion over natural numbers,
-- an interpretation of Nat in the manner of higher-order abstract syntax.
nat_rec :: a1 -> (Nat -> a1 -> a1) -> Nat -> a1
nat_rec f f0 n =
case n of {
O -> f;
S n0 -> f0 n0 (nat_rec f f0 n0)}
-- Given non-negative integers n and m, produce (q, r) with n = q * m + r.
divalg_t :: Nat -> Nat -> (Nat, Nat)
divalg_t n O = (O, n) -- n/0: Define quotient 0, remainder n.
divalg_t n (S m') = divpos n m' -- n/(S m')
where
-- Given non-negative integers n and m',
-- and defining m = m' + 1,
-- produce (q, r) with n = q * m + r
-- so that q = floor (n / m) and r = n % m.
divpos :: Nat -> Nat -> (Nat, Nat)
divpos n m' = nat_rec (O, O) (incrDivMod m') n
-- Given a non-negative integer m' and
-- a pair of non-negative integers (q', r') with r <= m',
-- and defining m = m' + 1,
-- produce (q, r) with q*m + r = q'*m + r' + 1 and r <= m'.
incrDivMod :: Nat -> Nat -> (Nat, Nat) -> (Nat, Nat)
incrDivMod m' _ (q', r')
| r' == m' = (S q', O)
| otherwise = (q', S r')
The current copy of Software Foundations dated July 25, 2012, answers this quite concisely in the late chapter "Extraction2". The answer is that it can certainly be done, much like this:
Extraction Language Haskell
Extraction "divalg.hs" divalg
One more trick is necessary. Instead of a Prop, divalg must be a Type. Otherwise it will be erased in the process of extraction.
Uh oh, #Anthill is correct, I haven't answered the question because I don't know how to explain how Prof. Pierce accomplished that in his NormInType.v variant of his Norm.v and MoreStlc.v.
OK, here's the rest of my partial answer anyway.
Where "divalg" appears above, it will be necessary to provide a space-separated list of all of the propositions (which must each be redefined as a Type rather than a Prop) on which divalg relies. For a thorough, interesting, and working example of a proof extraction, one may consult the chapter Extraction2 mentioned above. That example extracts to OCaml, but adapting it for Haskell is simply a matter of using Extraction Language Haskell as above.
In part, the reason that I spent some time not knowing the above answer is that I have been using the copy of Software Foundations dated October 14, 2010, that I downloaded in 2011.