|
1 | 1 | import LineBasedGrader from "./lineGrader"; |
2 | 2 | import { DiGraph } from "jsnetworkx/node/classes"; |
3 | 3 | import { hasPath } from "jsnetworkx/node/algorithms/shortestPaths/generic"; |
| 4 | +import { isDirectedAcyclicGraph } from "jsnetworkx/node/algorithms/dag"; |
4 | 5 |
|
5 | 6 | function graphToNX(answerLines) { |
6 | 7 | var graph = new DiGraph(); |
7 | | - for (let line of answerLines) { |
8 | | - graph.addNode(line.tag); |
9 | | - for (let line2 of line.depends) { |
| 8 | + for (let line1 of answerLines) { |
| 9 | + graph.addNode(line1.tag); |
| 10 | + for (let line2tag of line1.depends) { |
10 | 11 | // the depends graph lists the *incoming* edges of a node |
11 | | - graph.addEdge(line2, line); |
| 12 | + graph.addEdge(line2tag, line1.tag); |
12 | 13 | } |
13 | 14 | } |
14 | 15 | return graph; |
@@ -46,63 +47,63 @@ function allSubsets(arr) { |
46 | 47 |
|
47 | 48 | export default class DAGGrader extends LineBasedGrader { |
48 | 49 |
|
49 | | - |
50 | 50 | inverseLISIndices(arr) { |
51 | 51 | // For more details and a proof of the correctness of the algorithm, see the paper: https://arxiv.org/abs/2204.04196 |
52 | 52 |
|
53 | 53 | var solution = this.problem.solution; |
54 | 54 | var answerLines = this.problem.answerLines(); |
55 | 55 |
|
56 | | - let graph = graphToNX(answerLines); |
57 | | - console.log(allSubsets([1,2,3])) |
| 56 | + let graph = graphToNX(solution); |
58 | 57 |
|
59 | 58 | let seen = new Set(); |
60 | 59 | let problematicSubgraph = new DiGraph(); |
61 | | - let distractors = []; |
62 | | - for (let block of solution) { |
| 60 | + let tagsToRemove = []; |
| 61 | + for (let line1 of answerLines) { |
63 | 62 |
|
64 | | - if (block.distractor) { |
65 | | - distractors.push(block); |
| 63 | + if (line1.distractor) { |
| 64 | + tagsToRemove.push(line1.tag); |
66 | 65 | continue; |
67 | 66 | } |
68 | 67 |
|
69 | | - for (let block2 of seen) { |
70 | | - let problematic = hasPath(graph, block, block2); |
71 | | - if (hasPath(graph, block, block2)) { |
72 | | - problematicSubgraph.addEdge(block, block2); |
| 68 | + for (let line2 of seen) { |
| 69 | + let problematic = hasPath(graph, {source: line1.tag, target: line2.tag}); |
| 70 | + if (problematic) { |
| 71 | + problematicSubgraph.addEdge(line1.tag, line2.tag); |
73 | 72 | } |
74 | 73 | } |
75 | 74 |
|
76 | | - seen.add(block); |
| 75 | + seen.add(line1); |
77 | 76 | } |
78 | 77 |
|
79 | | - console.log(problematicSubgraph); |
80 | | - |
81 | | - if (problematicSubgraph.numberOfNodes() == 0) { |
82 | | - // just return the indices of the distractors, I guess??? |
83 | | - } else { |
84 | | - let mvc = null; |
85 | | - let subsets = allSubsets(problematicSubgraph.nodes()); |
86 | | - for (let i = 0; i <= problematicSubgraph.numberOfNodes(); i++) { |
87 | | - for (let subset of subsets[i]) { |
88 | | - if (isVertexCover(problematicSubgraph, subset)) { |
89 | | - mvc = subset; |
90 | | - console.log(mvc) |
91 | | - break; |
92 | | - } |
93 | | - } |
94 | | - if (mvc != null) { |
| 78 | + let mvc = null; |
| 79 | + let subsets = allSubsets(problematicSubgraph.nodes()); |
| 80 | + for (let i = 0; i <= problematicSubgraph.numberOfNodes(); i++) { |
| 81 | + for (let subset of subsets[i]) { |
| 82 | + if (isVertexCover(problematicSubgraph, subset)) { |
| 83 | + mvc = subset; |
95 | 84 | break; |
96 | 85 | } |
97 | 86 | } |
| 87 | + if (mvc != null) { |
| 88 | + break; |
| 89 | + } |
98 | 90 | } |
99 | 91 |
|
100 | | - // TODO implement the algorithm properly for the DAG grader so that it is the shortest edit distance |
101 | | - // to ANY of the correct solutions instead of just to the model solution |
102 | | - return super.inverseLISIndices(arr) |
| 92 | + tagsToRemove = tagsToRemove.concat([...mvc]); |
| 93 | + let indices = tagsToRemove.map(tag => { |
| 94 | + for (let i = 0; i < answerLines.length; i++) { |
| 95 | + if (answerLines[i].tag === tag) return i; |
| 96 | + } |
| 97 | + }); |
| 98 | + |
| 99 | + return indices; |
103 | 100 | } |
104 | 101 |
|
105 | 102 | checkCorrectOrdering(solutionLines, answerLines) { |
| 103 | + if (!(isDirectedAcyclicGraph(graphToNX(solutionLines)))) { |
| 104 | + throw "Dependency between blocks does not form a Directed Acyclic Graph; Problem unsolvable." |
| 105 | + } |
| 106 | + |
106 | 107 | let seen = new Set(); |
107 | 108 | let isCorrectOrder = true; |
108 | 109 | this.correctLines = 0; |
|
0 commit comments