def testPropositionalAGG(self): schema = Schema() schema.addEntity('A') model = Model(schema, []) agg = AbstractGroundGraph(model, 'A', 0) self.assertAGGEqualNoIntersection(schema, agg, []) schema.addAttribute('A', 'A') schema.addAttribute('A', 'B') schema.addAttribute('A', 'C') model = Model(schema, []) agg = AbstractGroundGraph(model, 'A', 0) self.assertAGGEqualNoIntersection(schema, agg, []) schema.addAttribute('A', 'D') schema.addAttribute('A', 'E') schema.addAttribute('A', 'F') schema.addAttribute('A', 'G') schema.addAttribute('A', 'H') dependencies = [ '[A].A -> [A].B', '[A].A -> [A].C', '[A].B -> [A].D', '[A].C -> [A].D', '[A].E -> [A].F', '[A].E -> [A].G', '[A].F -> [A].H', '[A].G -> [A].H' ] model = Model(schema, dependencies) agg = AbstractGroundGraph(model, 'A', 0) self.assertAGGEqualNoIntersection(schema, agg, dependencies)
def testGetAncestors(self): schema = Schema() schema.addEntity('A') schema.addAttribute('A', 'X') model = Model(schema, []) agg = AbstractGroundGraph(model, 'A', 0) self.assertGetAncestorsEquals(['[A].X'], agg, '[A].X') schema = Schema() schema.addEntity('A') schema.addAttribute('A', 'A') schema.addAttribute('A', 'B') schema.addAttribute('A', 'C') schema.addAttribute('A', 'D') schema.addAttribute('A', 'E') schema.addAttribute('A', 'F') schema.addAttribute('A', 'G') schema.addAttribute('A', 'H') dependencies = [ '[A].A -> [A].C', '[A].A -> [A].D', '[A].B -> [A].D', '[A].C -> [A].E', '[A].D -> [A].E', '[A].E -> [A].G', '[A].E -> [A].H', '[A].F -> [A].H' ] model = Model(schema, dependencies) agg = AbstractGroundGraph(model, 'A', 0) self.assertGetAncestorsEquals( ['[A].G', '[A].A', '[A].B', '[A].C', '[A].D', '[A].E'], agg, '[A].G') self.assertGetAncestorsEquals( ['[A].F', '[A].A', '[A].B', '[A].C', '[A].D', '[A].E', '[A].H'], agg, '[A].H') schema = Schema() schema.addEntity('A') schema.addEntity('B') schema.addEntity('C') schema.addRelationship('AB', ('A', Schema.MANY), ('B', Schema.MANY)) schema.addRelationship('BC', ('B', Schema.ONE), ('C', Schema.MANY)) schema.addAttribute('A', 'X') schema.addAttribute('B', 'Y') schema.addAttribute('C', 'Z') schema.addAttribute('AB', 'XY') schema.addAttribute('BC', 'YZ') model = Model(schema, [ '[BC, B, AB, A].X -> [BC].YZ', '[AB, B, BC, C].Z -> [AB].XY', '[AB, B, AB, A, AB, B].Y -> [AB].XY' ]) agg = AbstractGroundGraph(model, 'A', 6) self.assertGetAncestorsEquals([ '[A, AB].XY', '[A, AB, B, BC, C].Z', '[A, AB, B, AB, A, AB, B].Y', ('[A, AB, B, AB, A, AB, B].Y', '[A, AB, B, BC, C, BC, B].Y') ], agg, '[A, AB].XY') self.assertGetAncestorsEquals( [('[A, AB, B, AB, A, AB, B].Y', '[A, AB, B, BC, C, BC, B].Y')], agg, ('[A, AB, B, AB, A, AB, B].Y', '[A, AB, B, BC, C, BC, B].Y'))
def testGetSubsumedRelVarInts(self): schema = Schema() schema.addEntity('A') schema.addEntity('B') schema.addRelationship('AB', ('A', Schema.MANY), ('B', Schema.ONE)) schema.addAttribute('A', 'X') schema.addAttribute('B', 'Y') model = Model(schema, []) abAGG = AbstractGroundGraph(model, 'AB', 3) self.assertSameSubsumedVariables(['[AB, A].X'], abAGG, '[AB, A].X') self.assertSameSubsumedVariables( ['[AB, B].Y', ('[AB, B].Y', '[AB, A, AB, B].Y')], abAGG, '[AB, B].Y') self.assertSameSubsumedVariables( ['[AB, A, AB, B].Y', ('[AB, B].Y', '[AB, A, AB, B].Y')], abAGG, '[AB, A, AB, B].Y') schema = Schema() schema.addEntity('A') schema.addEntity('B') schema.addRelationship('AB1', ('A', Schema.MANY), ('B', Schema.MANY)) schema.addRelationship('AB2', ('A', Schema.MANY), ('B', Schema.MANY)) schema.addAttribute('A', 'X') schema.addAttribute('B', 'Y') schema.addAttribute('AB1', 'XY1') schema.addAttribute('AB2', 'XY2') model = Model(schema, []) aAGG = AbstractGroundGraph(model, 'A', 4) self.assertSameSubsumedVariables([ '[A, AB1, B, AB1, A].X', ('[A, AB1, B, AB1, A].X', '[A, AB1, B, AB2, A].X'), ('[A, AB1, B, AB1, A].X', '[A, AB2, B, AB1, A].X'), ('[A, AB1, B, AB1, A].X', '[A, AB2, B, AB2, A].X') ], aAGG, '[A, AB1, B, AB1, A].X') # test bad relVar input to getSubsumedVariables schema = Schema() schema.addEntity('A') model = Model(schema, []) agg = AbstractGroundGraph(model, 'A', 0) TestUtil.assertRaisesMessage( self, Exception, "relVar must be a RelationalVariable: found 'None'", agg.getSubsumedVariables, None) schema = Schema() schema.addEntity('A') schema.addAttribute('A', 'X1') model = Model(schema, []) agg = AbstractGroundGraph(model, 'A', 0) TestUtil.assertRaisesMessage( self, Exception, "relVar '[A].X2' is not a node in the abstract ground graph", agg.getSubsumedVariables, RelationalVariable(['A'], 'X2'))
def dSeparated(self, hopThreshold, relVar1Strs, relVar2Strs, condRelVarStrs, relationalVariableSetChecker=RelationalValidity.checkValidityOfRelationalVariableSet): """ relVar1Strs, relVar2Strs, and condRelVarStrs are sequences of parseable RelationalVariable strings Method checks if, in model, are relVars1 and relVars2 d-separated? Constructs the abstract ground graph (AGG) for the model, and checks to see if all paths are d-separated. """ if not isinstance(relVar1Strs, collections.Iterable) or not relVar1Strs: raise Exception("relVars1 must be a non-empty sequence of parseable RelationalVariable strings") relVars1 = {ParserUtil.parseRelVar(relVarStr) for relVarStr in relVar1Strs} if not isinstance(relVar2Strs, collections.Iterable) or not relVar2Strs: raise Exception("relVars2 must be a non-empty sequence of parseable RelationalVariable strings") relVars2 = {ParserUtil.parseRelVar(relVarStr) for relVarStr in relVar2Strs} if not isinstance(condRelVarStrs, collections.Iterable): raise Exception("condRelVars must be a sequence of parseable RelationalVariable strings") condRelVars = {ParserUtil.parseRelVar(condRelVar) for condRelVar in condRelVarStrs} # check consistency of all three relational variable sets (perspectives, hop threshold, against schema) relationalVariableSetChecker(self.model.schema, hopThreshold, relVars1 | relVars2 | condRelVars) perspective = list(relVars1)[0].getBaseItemName() if (perspective, hopThreshold) not in self.perspectiveHopThresholdToAgg: agg = AbstractGroundGraph(self.model, perspective, hopThreshold) ug = agg2ug(agg) self.perspectiveHopThresholdToAgg[(perspective, hopThreshold)] = agg self.ugs[(perspective, hopThreshold)] = ug else: agg = self.perspectiveHopThresholdToAgg[(perspective, hopThreshold)] ug = self.ugs[(perspective, hopThreshold)] # expand relVars1, relVars2, condRelVars with all intersection variables they subsume relVars1 = {relVar for relVar1 in relVars1 for relVar in agg.getSubsumedVariables(relVar1)} relVars2 = {relVar for relVar2 in relVars2 for relVar in agg.getSubsumedVariables(relVar2)} condRelVars = {relVar for condRelVar in condRelVars for relVar in agg.getSubsumedVariables(condRelVar)} relVars1 -= condRelVars relVars2 -= condRelVars if relVars1 & relVars2 != set(): return False if not relVars1 or not relVars2: return True return bfsReachability(relVars1, relVars2, condRelVars, agg, ug)
def testLongRangeDependencyIsIgnored(self): # Build AGG with model with a dependency that is longer than hop threshold # the long-range dependence is not (B,h)-reachable for the AGG from perspective B schema = Schema() schema.addEntity('A') schema.addEntity('B') schema.addRelationship('AB', ('A', Schema.MANY), ('B', Schema.ONE)) schema.addAttribute('B', 'Y1') schema.addAttribute('B', 'Y2') model = Model(schema, ['[B, AB, A, AB, B].Y1 -> [B].Y2']) self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'B', 2), [])
def testRemoveEdgesForDependency(self): schema = Schema() schema.addEntity('A') schema.addAttribute('A', 'A') schema.addAttribute('A', 'B') schema.addAttribute('A', 'C') schema.addAttribute('A', 'D') schema.addAttribute('A', 'E') schema.addAttribute('A', 'F') schema.addAttribute('A', 'G') schema.addAttribute('A', 'H') dependencies = [ '[A].A -> [A].B', '[A].A -> [A].C', '[A].B -> [A].D', '[A].C -> [A].D', '[A].E -> [A].F', '[A].E -> [A].G', '[A].F -> [A].H', '[A].G -> [A].H' ] model = Model(schema, dependencies) agg = AbstractGroundGraph(model, 'A', 0) agg.removeEdgesForDependency(ParserUtil.parseRelDep('[A].B -> [A].A')) self.assertEqual(8, len(agg.edges())) agg.removeEdgesForDependency(ParserUtil.parseRelDep('[A].A -> [A].B')) self.assertEqual(7, len(agg.edges())) self.assertNotIn( (ParserUtil.parseRelVar('[A].A'), ParserUtil.parseRelVar('[A].B')), agg.edges()) agg.removeEdgesForDependency(ParserUtil.parseRelDep('[A].F -> [A].H')) self.assertEqual(6, len(agg.edges())) self.assertNotIn( (ParserUtil.parseRelVar('[A].F'), ParserUtil.parseRelVar('[A].H')), agg.edges()) schema = Schema() schema.addEntity('A') schema.addEntity('B') schema.addEntity('C') schema.addRelationship('AB', ('A', Schema.MANY), ('B', Schema.MANY)) schema.addRelationship('BC', ('B', Schema.ONE), ('C', Schema.MANY)) schema.addAttribute('A', 'X') schema.addAttribute('B', 'Y') schema.addAttribute('C', 'Z') schema.addAttribute('AB', 'XY') schema.addAttribute('BC', 'YZ') model = Model(schema, [ '[BC, B, AB, A].X -> [BC].YZ', '[AB, B, BC, C].Z -> [AB].XY', '[AB, B, AB, A, AB, B].Y -> [AB].XY' ]) aAGG = AbstractGroundGraph(model, 'A', 6) self.assertEqual(9, len(aAGG.edges())) aAGG.removeEdgesForDependency( ParserUtil.parseRelDep('[BC, B, AB, A].X -> [BC].YZ')) self.assertEqual(7, len(aAGG.edges())) aAGG.removeEdgesForDependency( ParserUtil.parseRelDep('[AB, B, AB, A, AB, B].Y -> [AB].XY')) self.assertEqual(2, len(aAGG.edges()))
def testOneToOneTwoEntityAGG(self): schema = Schema() schema.addEntity('A') schema.addEntity('B') schema.addRelationship('AB', ('A', Schema.ONE), ('B', Schema.ONE)) model = Model(schema, []) self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'A', 0), []) self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'B', 0), []) self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'AB', 0), []) schema.addAttribute('A', 'X') model = Model(schema, []) self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'A', 0), []) self.assertAGGEqualNoIntersection( schema, AbstractGroundGraph(model, 'B', 1), []) # insufficient hop threshold to give it nodes self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'B', 2), []) self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'AB', 1), []) schema.addAttribute('B', 'Y') model = Model(schema, []) self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'A', 2), []) self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'B', 2), []) self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'AB', 1), []) schema.addAttribute('AB', 'XY') model = Model(schema, []) self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'A', 2), []) self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'B', 2), []) self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'AB', 1), []) model = Model(schema, ['[B, AB, A].X -> [B].Y']) self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'A', 2), ['[A].X -> [A, AB, B].Y']) self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'B', 2), ['[B, AB, A].X -> [B].Y']) self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'AB', 1), ['[AB, A].X -> [AB, B].Y'])
def testThreeEntityTwoRelationshipsAGG(self): schema = Schema() schema.addEntity('A') schema.addEntity('B') schema.addEntity('C') schema.addRelationship('AB', ('A', Schema.MANY), ('B', Schema.MANY)) schema.addRelationship('BC', ('B', Schema.ONE), ('C', Schema.MANY)) schema.addAttribute('A', 'X') schema.addAttribute('B', 'Y') schema.addAttribute('C', 'Z') schema.addAttribute('AB', 'XY') schema.addAttribute('BC', 'YZ') model = Model(schema, []) aAGG = AbstractGroundGraph(model, 'A', 6) expectedRelVarNodes = [ ParserUtil.parseRelVar(relVarStr) for relVarStr in [ '[A].X', '[A, AB].XY', '[A, AB, B].Y', '[A, AB, B, AB].XY', '[A, AB, B, BC].YZ', '[A, AB, B, AB, A].X', '[A, AB, B, BC, C].Z', '[A, AB, B, AB, A, AB].XY', '[A, AB, B, BC, C, BC].YZ', '[A, AB, B, AB, A, AB, B].Y', '[A, AB, B, BC, C, BC, B].Y' ] ] TestUtil.assertUnorderedListEqual(self, expectedRelVarNodes, aAGG.getRelationalVariableNodes()) expectedRelVarIntNodes = self.relVarStrPairsToRelVarInts([ ('[A, AB, B, AB, A, AB, B].Y', '[A, AB, B, BC, C, BC, B].Y') ]) TestUtil.assertUnorderedListEqual( self, expectedRelVarIntNodes, aAGG.getRelationalVariableIntersectionNodes()) self.assertAGGEdgesEqual([], aAGG) bcAGG = AbstractGroundGraph(model, 'BC', 4) expectedRelVarNodes = [ ParserUtil.parseRelVar(relVarStr) for relVarStr in [ '[BC].YZ', '[BC, B].Y', '[BC, C].Z', '[BC, B, AB].XY', '[BC, C, BC].YZ', '[BC, B, AB, A].X', '[BC, C, BC, B].Y', '[BC, B, AB, A, AB].XY', '[BC, C, BC, B, AB].XY' ] ] TestUtil.assertUnorderedListEqual(self, expectedRelVarNodes, bcAGG.getRelationalVariableNodes()) expectedRelVarIntNodes = self.relVarStrPairsToRelVarInts([ ('[BC, B].Y', '[BC, C, BC, B].Y'), ('[BC, B, AB].XY', '[BC, C, BC, B, AB].XY'), ('[BC, B, AB, A, AB].XY', '[BC, C, BC, B, AB].XY') ]) TestUtil.assertUnorderedListEqual( self, expectedRelVarIntNodes, bcAGG.getRelationalVariableIntersectionNodes()) self.assertAGGEdgesEqual([], bcAGG) model = Model(schema, [ '[BC, B, AB, A].X -> [BC].YZ', '[AB, B, BC, C].Z -> [AB].XY', '[AB, B, AB, A, AB, B].Y -> [AB].XY' ]) aAGG = AbstractGroundGraph(model, 'A', 6) expectedEdges = self.relVarStrPairsToRelVarPairs([ ('[A].X', '[A, AB, B, BC].YZ'), ('[A, AB, B, AB, A].X', '[A, AB, B, BC].YZ'), ('[A, AB, B, BC, C].Z', '[A, AB].XY'), ('[A, AB, B, BC, C].Z', '[A, AB, B, AB].XY'), ('[A, AB, B, AB, A, AB, B].Y', '[A, AB].XY'), ('[A, AB, B].Y', '[A, AB, B, AB].XY'), ('[A, AB, B, AB, A, AB, B].Y', '[A, AB, B, AB].XY'), (('[A, AB, B, AB, A, AB, B].Y', '[A, AB, B, BC, C, BC, B].Y'), '[A, AB].XY'), (('[A, AB, B, AB, A, AB, B].Y', '[A, AB, B, BC, C, BC, B].Y'), '[A, AB, B, AB].XY') ]) self.assertAGGEdgesEqual(expectedEdges, aAGG)
def testManyToManyTwoEntityTwoRelationshipsAGGNodes(self): schema = Schema() schema.addEntity('A') schema.addEntity('B') schema.addRelationship('AB1', ('A', Schema.MANY), ('B', Schema.MANY)) schema.addRelationship('AB2', ('A', Schema.MANY), ('B', Schema.MANY)) schema.addAttribute('A', 'X') schema.addAttribute('B', 'Y') schema.addAttribute('AB1', 'XY1') schema.addAttribute('AB2', 'XY2') model = Model(schema, []) aAGG = AbstractGroundGraph(model, 'A', 4) expectedRelVarNodes = [ ParserUtil.parseRelVar(relVarStr) for relVarStr in [ '[A].X', '[A, AB1].XY1', '[A, AB2].XY2', '[A, AB1, B].Y', '[A, AB2, B].Y', '[A, AB1, B, AB1].XY1', '[A, AB1, B, AB2].XY2', '[A, AB2, B, AB1].XY1', '[A, AB2, B, AB2].XY2', '[A, AB1, B, AB1, A].X', '[A, AB1, B, AB2, A].X', '[A, AB2, B, AB1, A].X', '[A, AB2, B, AB2, A].X' ] ] expectedRelVarIntNodes = self.relVarStrPairsToRelVarInts([ ('[A, AB1].XY1', '[A, AB2, B, AB1].XY1'), ('[A, AB2].XY2', '[A, AB1, B, AB2].XY2'), ('[A, AB1, B].Y', '[A, AB2, B].Y'), ('[A, AB1, B, AB1].XY1', '[A, AB2, B, AB1].XY1'), ('[A, AB2, B, AB2].XY2', '[A, AB1, B, AB2].XY2'), ('[A, AB1, B, AB1, A].X', '[A, AB1, B, AB2, A].X'), ('[A, AB1, B, AB1, A].X', '[A, AB2, B, AB1, A].X'), ('[A, AB1, B, AB1, A].X', '[A, AB2, B, AB2, A].X'), ('[A, AB2, B, AB2, A].X', '[A, AB1, B, AB2, A].X'), ('[A, AB2, B, AB2, A].X', '[A, AB2, B, AB1, A].X'), ('[A, AB1, B, AB2, A].X', '[A, AB2, B, AB1, A].X') ]) TestUtil.assertUnorderedListEqual(self, expectedRelVarNodes, aAGG.getRelationalVariableNodes()) TestUtil.assertUnorderedListEqual( self, expectedRelVarIntNodes, aAGG.getRelationalVariableIntersectionNodes()) self.assertAGGEdgesEqual([], aAGG) ab1AGG = AbstractGroundGraph(model, 'AB1', 4) expectedRelVarNodes = [ ParserUtil.parseRelVar(relVarStr) for relVarStr in [ '[AB1].XY1', '[AB1, A].X', '[AB1, B].Y', '[AB1, A, AB1].XY1', '[AB1, A, AB2].XY2', '[AB1, B, AB1].XY1', '[AB1, B, AB2].XY2', '[AB1, A, AB1, B].Y', '[AB1, A, AB2, B].Y', '[AB1, B, AB1, A].X', '[AB1, B, AB2, A].X', '[AB1, A, AB1, B, AB1].XY1', '[AB1, A, AB2, B, AB1].XY1', '[AB1, B, AB1, A, AB1].XY1', '[AB1, B, AB2, A, AB1].XY1', '[AB1, A, AB1, B, AB2].XY2', '[AB1, A, AB2, B, AB2].XY2', '[AB1, B, AB1, A, AB2].XY2', '[AB1, B, AB2, A, AB2].XY2' ] ] TestUtil.assertUnorderedListEqual(self, expectedRelVarNodes, ab1AGG.getRelationalVariableNodes()) expectedRelVarIntNodes = self.relVarStrPairsToRelVarInts([ ('[AB1, A].X', '[AB1, B, AB1, A].X'), ('[AB1, A].X', '[AB1, B, AB2, A].X'), ('[AB1, B].Y', '[AB1, A, AB1, B].Y'), ('[AB1, B].Y', '[AB1, A, AB2, B].Y'), ('[AB1, A, AB1].XY1', '[AB1, B, AB1].XY1'), ('[AB1, A, AB1].XY1', '[AB1, A, AB2, B, AB1].XY1'), ('[AB1, A, AB1].XY1', '[AB1, B, AB1, A, AB1].XY1'), ('[AB1, A, AB1].XY1', '[AB1, B, AB2, A, AB1].XY1'), ('[AB1, A, AB2].XY2', '[AB1, B, AB2].XY2'), ('[AB1, A, AB2].XY2', '[AB1, B, AB2, A, AB2].XY2'), ('[AB1, A, AB2].XY2', '[AB1, B, AB1, A, AB2].XY2'), ('[AB1, A, AB2].XY2', '[AB1, A, AB1, B, AB2].XY2'), ('[AB1, B, AB1].XY1', '[AB1, B, AB2, A, AB1].XY1'), ('[AB1, B, AB1].XY1', '[AB1, A, AB1, B, AB1].XY1'), ('[AB1, B, AB1].XY1', '[AB1, A, AB2, B, AB1].XY1'), ('[AB1, B, AB2].XY2', '[AB1, A, AB2, B, AB2].XY2'), ('[AB1, B, AB2].XY2', '[AB1, A, AB1, B, AB2].XY2'), ('[AB1, B, AB2].XY2', '[AB1, B, AB1, A, AB2].XY2'), ('[AB1, A, AB1, B].Y', '[AB1, A, AB2, B].Y'), ('[AB1, B, AB1, A].X', '[AB1, B, AB2, A].X'), ('[AB1, A, AB1, B, AB1].XY1', '[AB1, A, AB2, B, AB1].XY1'), ('[AB1, A, AB1, B, AB1].XY1', '[AB1, B, AB1, A, AB1].XY1'), ('[AB1, A, AB1, B, AB1].XY1', '[AB1, B, AB2, A, AB1].XY1'), ('[AB1, A, AB2, B, AB1].XY1', '[AB1, B, AB1, A, AB1].XY1'), ('[AB1, A, AB2, B, AB1].XY1', '[AB1, B, AB2, A, AB1].XY1'), ('[AB1, B, AB1, A, AB1].XY1', '[AB1, B, AB2, A, AB1].XY1'), ('[AB1, A, AB1, B, AB2].XY2', '[AB1, A, AB2, B, AB2].XY2'), ('[AB1, A, AB1, B, AB2].XY2', '[AB1, B, AB1, A, AB2].XY2'), ('[AB1, A, AB1, B, AB2].XY2', '[AB1, B, AB2, A, AB2].XY2'), ('[AB1, A, AB2, B, AB2].XY2', '[AB1, B, AB1, A, AB2].XY2'), ('[AB1, A, AB2, B, AB2].XY2', '[AB1, B, AB2, A, AB2].XY2'), ('[AB1, B, AB1, A, AB2].XY2', '[AB1, B, AB2, A, AB2].XY2') ]) TestUtil.assertUnorderedListEqual( self, expectedRelVarIntNodes, ab1AGG.getRelationalVariableIntersectionNodes()) self.assertAGGEdgesEqual([], aAGG) # test multiple relationships with two dependencies model = Model(schema, [ '[AB2, B, AB1, A].X -> [AB2].XY2', '[AB1, B, AB2].XY2 -> [AB1].XY1' ]) ab1AGG = AbstractGroundGraph(model, 'AB1', 3) expectedRelVarNodes = [ ParserUtil.parseRelVar(relVarStr) for relVarStr in [ '[AB1].XY1', '[AB1, A].X', '[AB1, B].Y', '[AB1, A, AB1].XY1', '[AB1, A, AB2].XY2', '[AB1, B, AB1].XY1', '[AB1, B, AB2].XY2', '[AB1, A, AB1, B].Y', '[AB1, A, AB2, B].Y', '[AB1, B, AB1, A].X', '[AB1, B, AB2, A].X' ] ] TestUtil.assertUnorderedListEqual(self, expectedRelVarNodes, ab1AGG.getRelationalVariableNodes()) expectedRelVarIntNodes = self.relVarStrPairsToRelVarInts([ ('[AB1, A].X', '[AB1, B, AB1, A].X'), ('[AB1, A].X', '[AB1, B, AB2, A].X'), ('[AB1, B].Y', '[AB1, A, AB1, B].Y'), ('[AB1, B].Y', '[AB1, A, AB2, B].Y'), ('[AB1, A, AB1].XY1', '[AB1, B, AB1].XY1'), ('[AB1, A, AB2].XY2', '[AB1, B, AB2].XY2'), ('[AB1, A, AB1, B].Y', '[AB1, A, AB2, B].Y'), ('[AB1, B, AB1, A].X', '[AB1, B, AB2, A].X') ]) TestUtil.assertUnorderedListEqual( self, expectedRelVarIntNodes, ab1AGG.getRelationalVariableIntersectionNodes()) expectedEdges = self.relVarStrPairsToRelVarPairs([ ('[AB1, B, AB2].XY2', '[AB1].XY1'), ('[AB1, B, AB2].XY2', '[AB1, B, AB1].XY1'), ('[AB1, A].X', '[AB1, B, AB2].XY2'), ('[AB1, B, AB1, A].X', '[AB1, B, AB2].XY2'), (('[AB1, A].X', '[AB1, B, AB1, A].X'), '[AB1, B, AB2].XY2'), (('[AB1, A].X', '[AB1, B, AB2, A].X'), '[AB1, B, AB2].XY2'), ('[AB1, B, AB2].XY2', ('[AB1, A, AB1].XY1', '[AB1, B, AB1].XY1')), ('[AB1, A].X', ('[AB1, A, AB2].XY2', '[AB1, B, AB2].XY2')), ('[AB1, B, AB1, A].X', ('[AB1, A, AB2].XY2', '[AB1, B, AB2].XY2')), (('[AB1, A, AB2].XY2', '[AB1, B, AB2].XY2'), '[AB1].XY1'), (('[AB1, A, AB2].XY2', '[AB1, B, AB2].XY2'), '[AB1, B, AB1].XY1'), (('[AB1, B, AB1, A].X', '[AB1, B, AB2, A].X'), '[AB1, B, AB2].XY2') ]) self.assertAGGEdgesEqual(expectedEdges, ab1AGG)
def testOneToManyTwoEntityAGG(self): schema = Schema() schema.addEntity('A') schema.addEntity('B') schema.addRelationship('AB', ('A', Schema.MANY), ('B', Schema.ONE)) model = Model(schema, []) self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'A', 0), []) self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'B', 0), []) self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'AB', 0), []) schema.addAttribute('A', 'X') model = Model(schema, []) self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'A', 2), []) self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'B', 2), []) self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'AB', 2), []) schema.addAttribute('B', 'Y') model = Model(schema, []) self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'A', 2), []) # putting in max hop threshold self.assertAGGEqualNoIntersection(schema, AbstractGroundGraph(model, 'B', 4), []) abAGG = AbstractGroundGraph(model, 'AB', 3) expectedRelVarNodes = [ ParserUtil.parseRelVar(relVarStr) for relVarStr in ['[AB, A].X', '[AB, B].Y', '[AB, A, AB, B].Y'] ] expectedRelVarIntNodes = self.relVarStrPairsToRelVarInts([ ('[AB, B].Y', '[AB, A, AB, B].Y') ]) TestUtil.assertUnorderedListEqual(self, expectedRelVarNodes, abAGG.getRelationalVariableNodes()) TestUtil.assertUnorderedListEqual( self, expectedRelVarIntNodes, abAGG.getRelationalVariableIntersectionNodes()) self.assertAGGEdgesEqual([], abAGG) # test that order of relVar1, relVar2 for RelationalVariableIntersection doesn't matter expectedRelVarIntNodes = self.relVarStrPairsToRelVarInts([ ('[AB, A, AB, B].Y', '[AB, B].Y') ]) TestUtil.assertUnorderedListEqual( self, expectedRelVarIntNodes, abAGG.getRelationalVariableIntersectionNodes()) model = Model(schema, ['[A, AB, B].Y -> [A].X']) aAGG = AbstractGroundGraph(model, 'A', 2) expectedEdges = self.relVarStrPairsToRelVarPairs([('[A, AB, B].Y', '[A].X')]) self.assertAGGEdgesEqual(expectedEdges, aAGG) # test that extended dependencies are only added among nodes that exist in the AGG (have an appropriate number of hops) bAGG = AbstractGroundGraph(model, 'B', 2) expectedEdges = self.relVarStrPairsToRelVarPairs([('[B].Y', '[B, AB, A].X')]) self.assertAGGEdgesEqual(expectedEdges, bAGG) bAGG = AbstractGroundGraph(model, 'B', 4) expectedEdges = self.relVarStrPairsToRelVarPairs([ ('[B].Y', '[B, AB, A].X'), ('[B, AB, A, AB, B].Y', '[B, AB, A].X') ]) self.assertAGGEdgesEqual(expectedEdges, bAGG) # test dependencies get inherited for intersection nodes abAGG = AbstractGroundGraph(model, 'AB', 3) expectedEdges = self.relVarStrPairsToRelVarPairs([ ('[AB, B].Y', '[AB, A].X'), ('[AB, A, AB, B].Y', '[AB, A].X'), (('[AB, A, AB, B].Y', '[AB, B].Y'), '[AB, A].X') ]) self.assertAGGEdgesEqual(expectedEdges, abAGG) schema.addAttribute('B', 'Z') model = Model(schema, []) abAGG = AbstractGroundGraph(model, 'AB', 3) expectedRelVarNodes = [ ParserUtil.parseRelVar(relVarStr) for relVarStr in [ '[AB, A].X', '[AB, B].Y', '[AB, A, AB, B].Y', '[AB, B].Z', '[AB, A, AB, B].Z' ] ] expectedRelVarIntNodes = self.relVarStrPairsToRelVarInts([ ('[AB, B].Y', '[AB, A, AB, B].Y'), ('[AB, B].Z', '[AB, A, AB, B].Z') ]) TestUtil.assertUnorderedListEqual(self, expectedRelVarNodes, abAGG.getRelationalVariableNodes()) TestUtil.assertUnorderedListEqual( self, expectedRelVarIntNodes, abAGG.getRelationalVariableIntersectionNodes()) self.assertAGGEdgesEqual([], abAGG) model = Model(schema, [ '[A, AB, B].Y -> [A].X', '[A, AB, B].Z -> [A].X', '[B].Y -> [B].Z' ]) aAGG = AbstractGroundGraph(model, 'A', 2) expectedEdges = self.relVarStrPairsToRelVarPairs([ ('[A, AB, B].Y', '[A].X'), ('[A, AB, B].Z', '[A].X'), ('[A, AB, B].Y', '[A, AB, B].Z') ]) self.assertAGGEdgesEqual(expectedEdges, aAGG) abAGG = AbstractGroundGraph(model, 'AB', 3) expectedEdges = self.relVarStrPairsToRelVarPairs([ ('[AB, A, AB, B].Y', '[AB, A, AB, B].Z'), ('[AB, A, AB, B].Y', '[AB, A].X'), ('[AB, B].Y', '[AB, B].Z'), ('[AB, A, AB, B].Z', '[AB, A].X'), ('[AB, B].Y', '[AB, A].X'), ('[AB, B].Z', '[AB, A].X'), (('[AB, B].Y', '[AB, A, AB, B].Y'), '[AB, A].X'), (('[AB, B].Y', '[AB, A, AB, B].Y'), '[AB, B].Z'), (('[AB, B].Y', '[AB, A, AB, B].Y'), '[AB, A, AB, B].Z'), (('[AB, B].Z', '[AB, A, AB, B].Z'), '[AB, A].X'), ('[AB, A, AB, B].Y', ('[AB, B].Z', '[AB, A, AB, B].Z')), ('[AB, B].Y', ('[AB, B].Z', '[AB, A, AB, B].Z')) ]) self.assertAGGEdgesEqual(expectedEdges, abAGG)
def constructAggsFromDependencies(self, dependencies, times=2): schemaDepWrapper = SchemaDependencyWrapper(self.schema, dependencies) perspectives = [si.name for si in self.schema.getSchemaItems()] self.perspectiveToAgg = {perspective: AbstractGroundGraph(schemaDepWrapper, perspective, times*self.hopThreshold) for perspective in perspectives}
print('Oriented recall:', ModelEvaluation.orientedRecall(model, rcdl.orientedDependencies)) assert ModelEvaluation.orientedRecall(model, rcdl.orientedDependencies) == \ ModelEvaluation.orientedRecall(model, rcd.orientedDependencies) == \ 0.0 # Demonstrate that there is no 'unshielded triple' in AGGs for the counter-example. schema, model = shlee.RCDLight.incompleteness_example() hopThreshold = max(len(d.relVar1.path) + 1 for d in model.dependencies) oracle = Oracle(model, 3 * hopThreshold) schemaDepWrapper = SchemaDependencyWrapper(schema, model.dependencies) perspectives = [si.name for si in schema.getSchemaItems()] perspectiveToAgg = { perspective: AbstractGroundGraph(schemaDepWrapper, perspective, 3 * hopThreshold) for perspective in perspectives } for agg in perspectiveToAgg.values(): for node1 in agg.nodes(): neighbors1 = set(agg.predecessors(node1) + agg.successors(node1)) for node2 in neighbors1: neighbors2 = set(agg.predecessors(node2) + agg.successors(node2)) - {node1} for node3 in neighbors2: if node3 not in neighbors1: if not isinstance(node1, RelationalVariable) or not isinstance(node2, RelationalVariable) or \ not isinstance(node3, RelationalVariable): continue print(node1, node2, node3)