Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
project-3-draft [2021/04/19 11:01] pdmatei |
project-3-draft [2021/04/25 16:07] (current) roxana_elena.stiuca prerequisite for taskset3 |
||
|---|---|---|---|
| Line 26: | Line 26: | ||
| | Cartesian (Row -> Row -> Row) [String] Query Query | | Cartesian (Row -> Row -> Row) [String] Query Query | ||
| | Projection [String] Query | | Projection [String] Query | ||
| - | -- | forall a. Filter (FilterCondition a) Query | + | | forall a. FEval a => Filter (FilterCondition a) Query |
| - | | Graph EdgeOp query | + | | Graph EdgeOp Query |
| | | ||
| -- where EdgeOp is defined: | -- where EdgeOp is defined: | ||
| - | type EdgeOp = Row -> Row -> Value | + | type EdgeOp = Row -> Row -> Maybe Value |
| </code> | </code> | ||
| **Don't worry about Graph or Filter queries yet.** | **Don't worry about Graph or Filter queries yet.** | ||
| - | + | ==== Prerequisite ==== | |
| + | Add the following lines at the beginning of your .hs files: | ||
| + | <code haskell> | ||
| + | {-# LANGUAGE ExistentialQuantification #-} | ||
| + | {-# LANGUAGE FlexibleInstances #-} | ||
| + | </code> | ||
| + | |||
| + | The first line allows ''forall a''. | ||
| + | The second allows ''instance FEval String''. | ||
| ===== Query Evaluation ===== | ===== Query Evaluation ===== | ||
| Line 101: | Line 110: | ||
| === FilterCondition Evaluation === | === FilterCondition Evaluation === | ||
| - | Let's take a look at FilterCondition. It is used in a Filter query, in order | + | |
| - | to filter the entries (rows) in a table, based on a condition. | + | A ''FilterCondition'' must evaluate to an actual filtering function, which has type: |
| - | We are going to define class FEval, which contains function feval, through | + | <code haskell> |
| - | which we evaluate a FilterCondition to a function of type FilterOp (defined | + | type FilterOp = Row -> Bool |
| - | also below). In order to do so, feval will also receive the column names | + | </code> |
| - | (the table head). | + | |
| + | Since such filtering functions work differently for ''FilterCondition Float'' and ''FilterCondition String'', we need a class ''FEval'' which contains function ''feval''. The latter is used to evaluate a ''FilterCondition a'' to a function of type ''FilterOp''. In order to do so, ''feval'' needs to have information about column names (the table head), hence it's type is shown below. | ||
| <code haskell> | <code haskell> | ||
| class FEval a where | class FEval a where | ||
| feval :: [String] -> (FilterCondition a) -> FilterOp | feval :: [String] -> (FilterCondition a) -> FilterOp | ||
| - | type FilterOp = Row -> Bool | ||
| </code> | </code> | ||
| - | Your task is to write the instances for (FEval Float) and (FEval String). | + | |
| + | **Task 3.x.**: Your task is to write the instances for ''(FEval Float)'' and ''(FEval String)''. | ||
| <code haskell> | <code haskell> | ||
| instance FEval Float where | instance FEval Float where | ||
| Line 119: | Line 129: | ||
| ... | ... | ||
| </code> | </code> | ||
| - | Now you can write the evaluation for Filter query (**eval**). | + | |
| - | === Graph Query === | + | Now you can write the evaluation for the data constructor ''Filter query'' (see function **eval** from the previous section). |
| - | We define a graph as a table with column names: ["From", "To", "Value"]. | + | |
| - | Each row defines a weighted edge between node "From" and node "To". | + | |
| - | - **Graph edgeop query**: creates a graph starting from the table | + | ===== Graph queries ===== |
| - | query evaluates to. | + | |
| - | The nodes are the rows in table T. | + | A **graph** is a special kind of table which has precisely the following column names: ''["From", "To", "Value"]''. Each row defines a **weighted edge** between node ''From'' and node ''To''. |
| - | The weight of an edge between 2 nodes is given by edgeop. We will only | + | |
| - | keep the edge between row1 and row2 if (edgeop row1 row2) > 0. | + | The query ''Graph edgeop query'': creates such a table starting from the result of the evaluation of ''query''. Suppose the query evaluates to a table **T**. |
| - | In the resulting table, a row describes an edge between node_i and node_j | + | |
| - | and will have the values: | + | * The nodes are the **rows** in table **T**. |
| - | "From" = first column from node_i | + | * The weight of an edge between 2 nodes is given by ''edgeop'', which returns a ''Maybe Value''. If ''edgeop row1 row2'' returns ''Nothing'', then we don't have an edge between those 2 nodes. If it returns ''Just val'' then we have an edge between ''row1'' and ''row2'' of weight ''val''. |
| - | "To" = first column from node_j | + | * In the resulting table, each row describes an edge between node_i and node_j and will have the values: |
| - | "Value" = edgeop node_i node_j | + | * "From" = first column from node_i |
| - | The edge node_i-node_j is the same as node_j-node_i, so it should only | + | * "To" = first column from node_j |
| - | appear once. "From" value should be lexicographically before "To". | + | * "Value" = edgeop node_i node_j |
| - | === Similarities graph, using queries === | + | |
| + | The edge //node_i-node_j// is the same as //node_j-node_i//, so it should only appear once (graphs are unoriented). "From" value should be lexicographically before "To". | ||
| + | |||
| + | **Example:** Suppose **T** is the table shown below: | ||
| + | <code> | ||
| + | Name Grade Class | ||
| + | Mihai 9 321 | ||
| + | Andrei 8 322 | ||
| + | Stefan 10 321 | ||
| + | Ana 9 322 | ||
| + | </code> | ||
| + | |||
| + | If we would like to build a graph that connects all students in the same class, then: | ||
| + | <code haskell> | ||
| + | edgeop [_,_,z] [_,_,c] | ||
| + | | z == c = Just c | ||
| + | | otherwise = Nothing | ||
| + | </code> | ||
| + | |||
| + | and the resulting graph will be: | ||
| + | <code> | ||
| + | From To Value | ||
| + | Mihai Stefan 321 | ||
| + | Ana Andrei 322 | ||
| + | </code> | ||
| + | |||
| + | If we would like to build a graph that connects students with grades equal or with a difference of **at least** a point, then: | ||
| + | <code haskell> | ||
| + | edgeop [_,x,_] [_,y,_] | ||
| + | | abs $ (read x :: Int) - (read y :: Int) <= 1 = Just "similar" | ||
| + | | otherwise = Nothing | ||
| + | </code> | ||
| + | |||
| + | and the resulting graph is: | ||
| + | <code> | ||
| + | From To Value | ||
| + | Andrei Mihai similar | ||
| + | Mihai Stefan similar | ||
| + | Ana Mihai similar | ||
| + | Ana Andrei similar | ||
| + | Ana Stefan similar | ||
| + | </code> | ||
| + | |||
| + | |||
| + | ==== Similarities graph, using queries ==== | ||
| We want to check the similarities between students lecture points. | We want to check the similarities between students lecture points. | ||
| - | For that, we want to obtain a graph where "From" and "To" are students' | + | * For that, we want to obtain a graph where "From" and "To" are students' emails and "Value" is the distance between the 2 students' points. |
| - | emails and "Value" is the distance between the 2 students' points. | + | * We define the distance between stud1 and stud2 as ''the sum of questions where they both received the same points''. Keep only the rows with ''distance >= 5''. |
| - | We define the distance between stud1 and stud2 as the sum of questions | + | * The edges in the resulting graph (the rows in the resulting table) should be sorted by the "Value" column. If email is missing, don't include that entry. |
| - | where they both received the same points. | + | |
| - | Also, the edges in the resulting graph (the rows in the resulting table) | + | Your task is to write ''similarities_query'' as a **sequence of queries**, that once evaluated results in the graph described above. |
| - | should be sorted by the "Value" column. Keep only the rows with | + | |
| - | distance >= 5. If email is missing, ignore that entry. | + | **Note**: ''similarities_query'' is a Query. The checker applies ''eval'' on it. |
| - | Your task is to write **similarities_query** as a sequence of | + | |
| - | queries, that once evaluated results in the graph described above. | + | ===== TL;DR Tasks ===== |
| - | === TL;DR Tasks === | + | - Enroll ''Query'' in class ''Eval'' (without ''Filter'' or ''Graph''). **0.3p** |
| - | 1. Enroll Query in class Eval (without Filter or Graph). 0.2p | + | - Enroll ''FilterCondition'' in class ''FEval'' and implement ''eval'' for ''Filter'' query. **0.2p** |
| - | 2. Enroll FilterCondition in class FEval and implement eval for Filter query. 0.2p | + | - Implement ''eval'' for ''Graph'' query. 0.2p |
| - | 3. Implement eval for Graph query. 0.2p | + | - Extract similarity graph. 0.3p |
| - | 4. Get graph for similarities. 0.3p | + | |
| - | === Checker === | + | ===== Checker ===== |
| - | === Submit === | + | |
| + | ===== Submit ===== | ||
| **Deadline**: 16.05, 23:50. | **Deadline**: 16.05, 23:50. | ||
| **Vmchecker**: TBA. | **Vmchecker**: TBA. | ||