functional dependencies involving the empty set - database

I am trying to grasp the concept of the empty set with FDs. Say i have
R(A,B,C,D)
A-> E
B-> C
B-> D
where E is the empty set, from what I understand, this is a trivial FD, since you are learn nothing new from having A. But when you have
E-> A
B-> C
B-> D
what does this mean exactly? Is it simply "Nothing implies A", so A can have any value it wants within the defined domain or is it A must be a NULL value?

The empty set is usually written as ∅ or {}.
A->{} is trivial. (because {} is a subset of A).
{}->A is not trivial. (except if A is {}, since {} is the subset of every set, and so a subset of {} as well).
{}->A means the value of A can be determined without using any other value, in other words the value of A must be the same for every tuple in R. This is not the same as saying that A has no determinants or that A is null. If there were no determinants for A then A would be unconstrained and could have different values in different tuples.
An example of a dependency on the empty set might be the Sex attribute in a Members relation that defines the membership of a men-only club: {}->Sex.

Related

Any name for a data structure like an array/list but with additional elements between the usual elements?

I sometimes find myself needing a one-dimensional collection of items of alternating "outer" and "inner" types. For example, for types A and B, the structure could hold a sequence of types:
A, B, A, B, A
where A and B are respectively the "outer" and "inner" types. (The sequence always starts and ends with the "outer" type.)
It's like an array/vector/list, but with additional members (of a different type) inserted "between" the array/vector/list's elements.
Such a structure is of course easy to implement using, for example, two arrays (of sizes n and n-1), or a special linked list using two types of nodes. But I feel a clean interface is warranted.
I have no idea what to call it. Is there any existing or sensible name for such a thing?

Why is LINKED_SET unable to compare objects?

As I'd like to know if some object is into a LINKED_SET to prune it in my context, I'm unable to compare it as an object instead of its reference.
changeable_comparison_criterion: BOOLEAN
-- May `object_comparison' be changed?
-- (Answer: only if set empty; otherwise insertions might
-- introduce duplicates, destroying the set property.)
do
Result := is_empty
ensure then
only_on_empty: Result = is_empty
end
Into the SET class (as above) it seems that its not possible to change a set to compare_objects. So my questions are:
What is the semantic of not being able to compare objects into a SET
If my choice of LINKED_SET is wrong by misunderstanding of its semantic, how should I do for having a unique items collection based on object comparison and then being able to prune an item again based on object comparison again
The comparison criterion should be set right after container creation, then it works without a problem. If there are some objects in the set already, it becomes unclear what should be done to them if the comparison criterion changes.
For example, if there is a set {A, B} of two distinct objects A and B that have the same value, i.e. are equal, what should be done if the comparison criterion changes from compare_references to compare_objects? Clearly, the set now should have only one object, because according to the new setting, it cannot hold two or more equal objects. Does it mean, object A should be removed and B should be kept? Or should it be done in reverse order? The precondition you are referring to removes this ambiguity.
The solution is to modify the setting before there are any objects in the container:
create my_set.make
my_set.compare_objects

Functional dependencies in database

I have the following set of functional dependencies on the relation
schema r(A, B, C, D, E, F ) :
A -> BCD
BC -> DE
B -> D
D -> A
Can anyone show with explanation how to find the candidate keys for this relation ?
Short answer: The candidate keys are (A,F), (B,F) and (D,F).
Like this Wikipedia article says:
The set of all candidate keys can be computed e.g. from the set of
functional dependencies. To this end we need to define the attribute
closure α+ for an attribute set α. The set
α+ contains all attributes that are functionally
implied by α.
It is quite simple to find a single candidate key. We start with a
set α of attributes and try to remove successively each
attribute. If after removing an attribute the attribute closure
stays the same, then this attribute is not necessary and we can
remove it permanently. We call the result minimize(α). If α is the set of all attributes, then minimize(α) is a candidate key.
So now we only need to put this into practice. Let's start with all attributes α0=(A,B,C,D,E,F). Now we can look whether removing A generates a problem. With α'0=(B,C,D,E,F), α'0+ is (B,C,D,E,F,A) (since D→ A holds). Now by kicking out A permanently and trying to remove B, we will end up with a candidate key.
α1=(B,C,D,E,F). Can we throw out B? Yes because α'1=(C,D,E,F) will result in α'1+=(A,B,C,D,E,F) (since D→A and A→BCD).
α2=(C,D,E,F). Can we throw out C? Yes because α'2=(D,E,F) will result in α'2+=(A,B,C,D,E,F) (since D→A and A→BCD).
α3=(D,E,F). Can we throw out D? No because α'3=(E,F) will result in α'3+=(E,F).
α3=(D,E,F). Can we throw out E? Yes because α'3=(D,F) will result in α'3+=(A,B,C,D,E,F) (since D→A; A→BCD; and BC→DE).
α4=(D,F). Can we throw out F? No because α'4=(D) will result in α'4+=(A,B,C,D,E) (since D→A; A→BCD; and BC→DE).
So now we generated minimize(α0)=α4=(D,F). We could use a brute force approach where in each iteration we iterate over all possible keys we can remove. But this will cost exponential time to generate.
The Wikipedia article however includes a way to generate all candidate keys polynomial in the number of keys and the functional dependencies. The algorithm is defined as:
function find_candidate_keys(A, F)
/* A is the set of all attributes and F is the set of functional dependencies */
K[0] := minimize(A);
n := 1; /* Number of Keys known so far */
i := 0; /* Currently processed key */
while i < n do
foreach α → β ∈ F do
/* Build a new potential key from the previous known key and the current FD */
S := α ∪ (K[i] − β);
/* Search whether the new potential key is part of the already known keys */
found := false;
for j := 0 to n-1 do
if K[j] ⊆ S then found := true;
/* If not, add if
if not found then
K[n] := minimize(S);
n := n + 1;
i := i + 1
return K
So if we run the algorithm, we first have to calculate minimize(A), but the nice thing is: we already did that above. So K[0] = (D,F), n=1 and i=0.
Now we take the while loop and start iterating over all functional dependencies.
for A&rightarrow; BCD. So now we construct a key (A,F). We check if there is already a subset defined as key (which is not the case). Now we minimize it, like: (A,F)&rightarrow;(A,F). So we add a new key (A,F).
for BC&rightarrow;DE. So now we construct a key (B,C,F). We check if there is already a subset defined as key (which is not the case). Now we minimize it, like (B,C,F)&rightarrow;(B,F)&rightarrow;(B,F). So we add (B,F).
for B&rightarrow;D. So now we construct a key (B,F). We check if there is already a subset defined as key (this is the case). We don't add this one.
for D&rightarrow;A. So now we construct a key (D,F). We check if there is already a subset defined as key (this is the case). We don't add this one.
This is the end of the first iteration. So K is now K=[(D,F),(A,F),(B,F)]. n=3 and now i=1. So for K[i]=(A,F) we now iterate:
for A&rightarrow; BCD. So now we construct a key (A,F). We check if there is already a subset defined as key (this is the case). We don't add this one.
for BC&rightarrow;DE. So now we construct a key (B,C,F). We check if there is already a subset defined as key (this is the case). We don't add this one.
for B&rightarrow;D. So now we construct a key (A,B,F). We check if there is already a subset defined as key (this is the case). We don't add this one.
for D&rightarrow;A. So now we construct a key (D,F). We check if there is already a subset defined as key (this is the case). We don't add this one.
This is the end of the second iteration. So K is now K=[(D,F),(A,F),(B,F)]. n=3 and now i=2. So for K[i]=(B,F) we now iterate:
for A&rightarrow; BCD. So now we construct a key (A,F). We check if there is already a subset defined as key (this is the case). We don't add this one.
for BC&rightarrow;DE. So now we construct a key (B,C,F). We check if there is already a subset defined as key (this is the case). We don't add this one.
for B&rightarrow;D. So now we construct a key (B,F). We check if there is already a subset defined as key (this is the case). We don't add this one.
for D&rightarrow;A. So now we construct a key (B,D,F). We check if there is already a subset defined as key (this is the case). We don't add this one.
So at the end K=[(D,F),(A,F),(B,F)]. These are all candidate keys.

Tuple Relational Calculas

Consider the following relational schema.
Students(rollno: integer, sname: string)
Courses(courseno: integer, cname: string)
Registration(rollno: integer, courseno: integer, percent: real)
For the following query:
{T ∣ ∃S∈Students,∃R∈Registration(
S.rollno=R.rollno ∧ R.courseno=107 ∧ R.percent>90 ∧ T.sname=S.sname)}
Will the whole of satisfying tuples be retrieved or only their T.sname? (If so, will it be distinct?)
A relational calculus or algebra expression returns a relation value. Relations hold sets of tuples. Sets do not contain duplicates.
The attributes in the result depend on how your particular version of tuple relational calculus is defined. Two reasonable possibilities are:
The right hand side says that the tuple value named T is an element of some relation defined in terms of given relations to have certain attributes.
We take T to name a tuple value that has exactly the attributes that are used after T. on the right.
(Otherwise, any time a tuple value for name T with just attribute sname satisfies the right hand side, every other tuple with any additional attributes whatsoever with any values whatsoever also satisfies the right hand side.)
(Some versions of tuple relational calculus give just the attribute names on the left. Some versions give the attribute names plus values (in terms of tuple names used on the right) on the left. Some versions give expressions of the form R.a on the left, hence giving both the attribute names and values. Some versions are like one of those but also give a tuple name T on the left.)

What does a.{X} mean in OCaml?

I'm currently trying to port some OCaml to F#. I'm "in at the deep end" with OCaml and my F# is a bit rusty.
Anyway, the OCaml code builds fine in the OCaml compiler, but (not surprisingly) gives a load of errors in the F# compiler even with ML compatibility switched on. Some of the errors look to be reserved words, but the bulk of the errors are complaining about the .{ in lines such as:
m.(a).(b) <- w.{a + b * c};
a,b,c are integers.
I've done a lot of searching through OCaml websites, Stackoverflow, the English translation of the French O'Reilly book, etc. and cannot find anything like this. Of course it doesn't help that most search facilities have problems with punctuation characters! Yes I've found references to . being used to refer to record members, and { } being used to define records, but both together? From the usage, I assume it is some kind of associative or sparse array?
What does this syntax mean? What is the closest F# equivalent?
There is a pdf of the oCaml documentation/manual available here:
http://caml.inria.fr/distrib/ocaml-3.12/ocaml-3.12-refman.pdf
On page 496 (toward the bottom of the page), it says of generic arrays and their get method:
val get : (’a, ’b, ’c) t -> int array -> ’a
Read an element of a generic big array. Genarray.get a [|i1; ...; iN|] returns
the element of a whose coordinates are i1 in the first dimension, i2 in the second
dimension, . . ., iN in the N-th dimension.
If a has C layout, the coordinates must be greater or equal than 0 and strictly less than
the corresponding dimensions of a. If a has Fortran layout, the coordinates must be
greater or equal than 1 and less or equal than the corresponding dimensions of a. Raise
Invalid_argument if the array a does not have exactly N dimensions, or if the
coordinates are outside the array bounds.
If N > 3, alternate syntax is provided: you can write a.{i1, i2, ..., iN} instead of
Genarray.get a [|i1; ...; iN|]. (The syntax a.{...} with one, two or three
coordinates is reserved for accessing one-, two- and three-dimensional arrays as
described below.)
Further, it says (specifically about one dimensional arrays):
val get : (’a, ’b, ’c) t -> int -> ’a
Array1.get a x, or alternatively a.{x}, returns the element of a at index x. x must
be greater or equal than 0 and strictly less than Array1.dim a if a has C layout. If a
has Fortran layout, x must be greater or equal than 1 and less or equal than
Array1.dim a. Otherwise, Invalid_argument is raised.
In F#, you can access array elements using the Array.get method as well. But, a closer syntax would be w.[a + b * c]. In short, in F#, use [] instead of {}.

Resources