示例#1
0
    def testDuplicateAttrNames(self):
        schemaWithEntityA = Schema()
        schemaWithEntityA.addEntity('A')
        schemaWithEntityA.addAttribute('A', 'X', Attribute.INTEGER)
        TestUtil.assertRaisesMessage(
            self, Exception,
            "Schema already has attribute named 'X' for item 'A'",
            schemaWithEntityA.addAttribute, 'A', 'X', Attribute.INTEGER)

        schemaWithEntityA.addEntity('B')
        schemaWithEntityA.addRelationship('AB', ('A', Schema.ONE),
                                          ('B', Schema.ONE))
        schemaWithEntityA.addAttribute('AB', 'XY', Attribute.INTEGER)
        TestUtil.assertRaisesMessage(
            self, Exception,
            "Schema already has attribute named 'XY' for item 'AB'",
            schemaWithEntityA.addAttribute, 'AB', 'XY', Attribute.INTEGER)

        a = schemaWithEntityA.getEntity('A')
        TestUtil.assertRaisesMessage(
            self, Exception,
            "Schema already has attribute named 'X' for item 'A'",
            a.addAttribute, 'X', Attribute.INTEGER)

        ab = schemaWithEntityA.getRelationship('AB')
        TestUtil.assertRaisesMessage(
            self, Exception,
            "Schema already has attribute named 'XY' for item 'AB'",
            ab.addAttribute, 'XY', Attribute.INTEGER)
示例#2
0
    def testSetUndirectedSkeleton(self):
        schema = Schema()
        model = Model(schema, [])
        pc = PC(schema, Oracle(model))
        undirectedSkeleton = nx.DiGraph()
        pc.setUndirectedSkeleton(undirectedSkeleton)
        self.assertEqual(undirectedSkeleton, pc.undirectedSkeleton)

        TestUtil.assertRaisesMessage(self, Exception, "Undirected skeleton must be a networkx DiGraph: found None",
             pc.setUndirectedSkeleton, None)

        # nodes must match the attributes of the schema
        undirectedSkeleton = nx.DiGraph()
        undirectedSkeleton.add_node(ParserUtil.parseRelVar('[A].X'))
        TestUtil.assertRaisesMessage(self, Exception, "Undirected skeleton's nodes must match schema attributes",
             pc.setUndirectedSkeleton, undirectedSkeleton)

        schema = Schema()
        schema.addEntity('A')
        schema.addAttribute('A', 'X')
        model = Model(schema, [])
        pc = PC(schema, Oracle(model))
        undirectedSkeleton = nx.DiGraph()
        TestUtil.assertRaisesMessage(self, Exception, "Undirected skeleton's nodes must match schema attributes",
             pc.setUndirectedSkeleton, undirectedSkeleton)
    def testOneRelationship(self):
        schema = Schema()
        schema.addEntity('A')
        schema.addEntity('B')
        schema.addRelationship('AB', ('A', Schema.ONE), ('B', Schema.MANY))

        schema.addAttribute('A', 'X')
        schema.addAttribute('B', 'Y')
        schema.addAttribute('AB', 'XY')

        relDeps = RelationalSpace.getRelationalDependencies(
            schema, 0, includeExistence=True)
        hop0 = []
        self.assertTrue(
            all([
                isinstance(relDep, RelationalDependency) for relDep in relDeps
            ]))
        TestUtil.assertUnorderedListEqual(self, hop0,
                                          [str(relDep) for relDep in relDeps])

        relDeps = RelationalSpace.getRelationalDependencies(
            schema, 1, includeExistence=True)
        hop1 = [
            '[A, AB].XY -> [A].X', '[A, AB].exists -> [A].X',
            '[AB, A].X -> [AB].XY', '[AB, A].X -> [AB].exists',
            '[AB, B].Y -> [AB].XY', '[AB, B].Y -> [AB].exists',
            '[B, AB].XY -> [B].Y', '[B, AB].exists -> [B].Y'
        ]
        self.assertTrue(
            all([
                isinstance(relDep, RelationalDependency) for relDep in relDeps
            ]))
        TestUtil.assertUnorderedListEqual(self, hop0 + hop1,
                                          [str(relDep) for relDep in relDeps])

        relDeps = RelationalSpace.getRelationalDependencies(
            schema, 2, includeExistence=True)
        hop2 = [
            '[A, AB, B].Y -> [A].X', '[AB, B, AB].exists -> [AB].XY',
            '[B, AB, A].X -> [B].Y'
        ]
        self.assertTrue(
            all([
                isinstance(relDep, RelationalDependency) for relDep in relDeps
            ]))
        TestUtil.assertUnorderedListEqual(self, hop0 + hop1 + hop2,
                                          [str(relDep) for relDep in relDeps])

        relDeps = RelationalSpace.getRelationalDependencies(
            schema, 3, includeExistence=True)
        hop3 = [
            '[A, AB, B, AB].XY -> [A].X', '[A, AB, B, AB].exists -> [A].X',
            '[AB, B, AB, A].X -> [AB].XY'
        ]
        self.assertTrue(
            all([
                isinstance(relDep, RelationalDependency) for relDep in relDeps
            ]))
        TestUtil.assertUnorderedListEqual(self, hop0 + hop1 + hop2 + hop3,
                                          [str(relDep) for relDep in relDeps])
示例#4
0
    def testModelFileIO(self):
        schema = Schema()
        schema.addEntity('A')
        schema.addEntity('B')
        schema.addEntity('C')
        schema.addRelationship('AB', ('A', Schema.ONE), ('B', Schema.MANY))
        schema.addRelationship('BC', ('B', Schema.MANY), ('C', Schema.MANY))
        schema.addAttribute('A', 'X', Attribute.INTEGER)
        schema.addAttribute('B', 'Y', Attribute.INTEGER)
        schema.addAttribute('C', 'Z', Attribute.INTEGER)
        schema.addAttribute('AB', 'XY1', Attribute.INTEGER)
        schema.addAttribute('AB', 'XY2', Attribute.INTEGER)
        schema.addAttribute('BC', 'YZ', Attribute.INTEGER)

        schema.toFile('schema.json')

        model = Model(schema, [])
        model.toFile('model.json')
        loadedModel = Model.fromFile('schema.json', 'model.json')
        self.assertEqual(model, loadedModel)

        model = Model(schema, ['[A, AB, B].Y -> [A].X'])
        model.toFile('model.json')
        loadedModel = Model.fromFile('schema.json', 'model.json')
        self.assertEqual(model, loadedModel)

        model = Model(
            schema,
            ['[A, AB, B].Y -> [A].X', '[AB, B, BC, C].Z -> [AB].exists'])
        model.toFile('model.json')
        loadedModel = Model.fromFile('schema.json', 'model.json')
        self.assertEqual(model, loadedModel)
示例#5
0
    def testBadInput(self):
        schema = Schema()
        schema.addEntity('A')
        schema.addAttribute('A', 'X1')
        schema.addAttribute('A', 'X2')
        dataStore = InMemoryDataStore()
        linearCITest = LinearCITest(schema, dataStore)
        TestUtil.assertRaisesMessage(
            self, Exception,
            "relVar1Str must be a parseable RelationalVariable string",
            linearCITest.isConditionallyIndependent, None, '[A].X2', [])
        TestUtil.assertRaisesMessage(
            self, Exception,
            "relVar2Str must be a parseable RelationalVariable string",
            linearCITest.isConditionallyIndependent, '[A].X1', None, [])
        TestUtil.assertRaisesMessage(
            self, Exception,
            "condRelVarStrs must be a sequence of parseable RelationalVariable strings",
            linearCITest.isConditionallyIndependent, '[A].X1', '[A].X2', None)
        TestUtil.assertRaisesMessage(
            self, Exception,
            "condRelVarStrs must be a sequence of parseable RelationalVariable strings",
            linearCITest.isConditionallyIndependent, '[A].X1', '[A].X2',
            '[A].X2')

        # relVar2Str MUST be singleton
        schema.addEntity('B')
        schema.addAttribute('B', 'Y', Attribute.FLOAT)
        schema.addRelationship('AB', ('A', Schema.MANY), ('B', Schema.MANY))
        TestUtil.assertRaisesMessage(self, Exception,
                                     "relVar2Str must have a singleton path",
                                     linearCITest.isConditionallyIndependent,
                                     '[A].X1', '[A, AB, B].Y', [])
示例#6
0
    def testOneRelationshipOneToOne(self):
        schema = Schema()
        schema.addEntity('A')
        schema.addEntity('B')
        schema.addRelationship('AB', ('A', Schema.ONE), ('B', Schema.ONE))

        relPaths = RelationalSpace.getRelationalPaths(schema, 0)
        hop0 = [['A'], ['B'], ['AB']]
        TestUtil.assertUnorderedListEqual(self, hop0, relPaths)

        relPaths = RelationalSpace.getRelationalPaths(schema, 1)
        hop1 = [['A', 'AB'], ['AB', 'A'], ['AB', 'B'], ['B', 'AB']]
        TestUtil.assertUnorderedListEqual(self, hop0 + hop1, relPaths)

        schema = Schema()
        schema.addEntity('B')
        schema.addEntity('C')
        schema.addRelationship('BC', ('B', Schema.ONE), ('C', Schema.ONE))

        relPaths = RelationalSpace.getRelationalPaths(schema, 0)
        hop0 = [['B'], ['C'], ['BC']]
        TestUtil.assertUnorderedListEqual(self, hop0, relPaths)

        relPaths = RelationalSpace.getRelationalPaths(schema, 1)
        hop1 = [['B', 'BC'], ['BC', 'B'], ['BC', 'C'], ['C', 'BC']]
        TestUtil.assertUnorderedListEqual(self, hop0 + hop1, relPaths)

        relPaths = RelationalSpace.getRelationalPaths(schema, 2)
        hop2 = [['B', 'BC', 'C'], ['C', 'BC', 'B']]
        TestUtil.assertUnorderedListEqual(self, hop0 + hop1 + hop2, relPaths)

        relPaths = RelationalSpace.getRelationalPaths(schema, 3)
        hop3 = []
        TestUtil.assertUnorderedListEqual(self, hop0 + hop1 + hop2 + hop3,
                                          relPaths)
示例#7
0
    def testCardinalities(self):
        schema = Schema()
        schema.addEntity('A')
        schema.addEntity('B')
        TestUtil.assertRaisesMessage(
            self, Exception,
            "Bad cardinality for entity1 or entity2: xxxx one. Should be either Schema.ONE or Schema.MANY",
            schema.addRelationship, 'AB', ('A', 'xxxx'), ('B', Schema.ONE))
        TestUtil.assertRaisesMessage(
            self, Exception,
            "Bad cardinality for entity1 or entity2: many xxxx. Should be either Schema.ONE or Schema.MANY",
            schema.addRelationship, 'AB', ('A', Schema.MANY), ('B', 'xxxx'))
        TestUtil.assertRaisesMessage(
            self, Exception,
            "Bad cardinality for entity1 or entity2: xxxx many. Should be either Schema.ONE or Schema.MANY",
            schema.addRelationship, 'AB', ('A', 'xxxx'), ('B', Schema.MANY))
        TestUtil.assertRaisesMessage(
            self, Exception,
            "Bad cardinality for entity1 or entity2: one xxxx. Should be either Schema.ONE or Schema.MANY",
            schema.addRelationship, 'AB', ('A', Schema.ONE), ('B', 'xxxx'))

        schema.addRelationship('AB', ('A', Schema.ONE), ('B', Schema.ONE))
        ab = schema.getRelationship('AB')
        self.assertEqual(Schema.ONE, ab.getCardinality('A'))
        self.assertEqual(Schema.ONE, ab.getCardinality('B'))

        schema.addEntity('C')
        schema.addRelationship('BC', ('B', Schema.ONE), ('C', Schema.MANY))
        bc = schema.getRelationship('BC')
        self.assertEqual(Schema.ONE, bc.getCardinality('B'))
        self.assertEqual(Schema.MANY, bc.getCardinality('C'))
        TestUtil.assertRaisesMessage(
            self, Exception, "Entity 'A' does not exist for relationship 'BC'",
            bc.getCardinality, 'A')
示例#8
0
    def testGenerateRelationshipAttributes(self):
        schema = SchemaGenerator.generateSchema(
            2,
            1,
            entityAttrDistribution=ConstantDistribution(0),
            relationshipAttrDistribution=ConstantDistribution(1),
            cardinalityDistribution=ConstantDistribution(Schema.ONE))
        expectedSchema = Schema()
        expectedSchema.addEntity('A')
        expectedSchema.addEntity('B')
        expectedSchema.addRelationship('AB', ('A', Schema.ONE),
                                       ('B', Schema.ONE))
        expectedSchema.addAttribute('AB', 'XY1')
        self.assertEqual(schema, expectedSchema)

        schema = SchemaGenerator.generateSchema(
            2,
            2,
            entityAttrDistribution=ConstantDistribution(0),
            relationshipAttrDistribution=ConstantDistribution(2),
            cardinalityDistribution=ConstantDistribution(Schema.ONE))
        expectedSchema.addRelationship('AB2', ('A', Schema.ONE),
                                       ('B', Schema.ONE))
        expectedSchema.addAttribute('AB', 'XY2')
        expectedSchema.addAttribute('AB2', 'XY2_1')
        expectedSchema.addAttribute('AB2', 'XY2_2')
        self.assertEqual(schema, expectedSchema)
示例#9
0
    def testCardinalities(self):
        schema = SchemaGenerator.generateSchema(
            2,
            1,
            entityAttrDistribution=ConstantDistribution(0),
            relationshipAttrDistribution=ConstantDistribution(0),
            cardinalityDistribution=ConstantDistribution(Schema.ONE))
        expectedSchema = Schema()
        expectedSchema.addEntity('A')
        expectedSchema.addEntity('B')
        expectedSchema.addRelationship('AB', ('A', Schema.ONE),
                                       ('B', Schema.ONE))
        self.assertEqual(schema, expectedSchema)

        schema = SchemaGenerator.generateSchema(
            2,
            1,
            entityAttrDistribution=ConstantDistribution(0),
            relationshipAttrDistribution=ConstantDistribution(0),
            cardinalityDistribution=ConstantDistribution(Schema.MANY))
        expectedSchema = Schema()
        expectedSchema.addEntity('A')
        expectedSchema.addEntity('B')
        expectedSchema.addRelationship('AB', ('A', Schema.MANY),
                                       ('B', Schema.MANY))
        self.assertEqual(schema, expectedSchema)
示例#10
0
    def testInvalidRelationalDependencies(self):
        schema = Schema()
        schema.addEntity('A')
        schema.addEntity('B')
        schema.addRelationship('AB', ('A', Schema.ONE), ('B', Schema.ONE))
        schema.addAttribute('A', 'X')
        schema.addAttribute('B', 'Y')

        # Check that entire dependency is canonical (relVar2 has a singleton path)
        TestUtil.assertRaisesMessage(
            self, Exception,
            "Dependency '[B].Y -> [B, AB, A].X' is not canonical",
            RelationalValidity.checkRelationalDependencyValidity, schema,
            ParserUtil.parseRelDep('[B].Y -> [B, AB, A].X'))

        # Check that base items are the same in both paths
        TestUtil.assertRaisesMessage(
            self, Exception,
            "Dependency '[B].Y -> [A].X' has inconsistent base items",
            RelationalValidity.checkRelationalDependencyValidity, schema,
            ParserUtil.parseRelDep('[B].Y -> [A].X'))

        # enforce that the relational variables are checked for consistency against the schema
        # using RelationalValidity.checkRelationalVariableValidity
        mockRelVarChecker = MagicMock(
            wraps=RelationalValidity.checkRelationalVariableValidity)
        RelationalValidity.checkRelationalDependencyValidity(
            schema,
            ParserUtil.parseRelDep('[A, AB, B].Y -> [A].X'),
            relationalVariableChecker=mockRelVarChecker)
        self.assertEqual(2, mockRelVarChecker.call_count)
示例#11
0
    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)
示例#12
0
    def testBadRelVarInput(self):
        schema = Schema()
        schema.addEntity('A')
        schema.addAttribute('A', 'X1')
        schema.addAttribute('A', 'X2')
        model = Model(schema, [])
        dsep = DSeparation(model)
        TestUtil.assertRaisesMessage(
            self, Exception,
            "relVars1 must be a non-empty sequence of parseable RelationalVariable strings",
            dsep.dSeparated, 0, None, ['[A].X2'], [])
        TestUtil.assertRaisesMessage(
            self, Exception,
            "relVars2 must be a non-empty sequence of parseable RelationalVariable strings",
            dsep.dSeparated, 0, ['[A].X1'], None, [])
        TestUtil.assertRaisesMessage(
            self, Exception,
            "condRelVars must be a sequence of parseable RelationalVariable strings",
            dsep.dSeparated, 0, ['[A].X1'], ['[A].X2'], None)

        TestUtil.assertRaisesMessage(
            self, Exception,
            "relVars1 must be a non-empty sequence of parseable RelationalVariable strings",
            dsep.dSeparated, 0, [], ['[A].X2'], [])

        TestUtil.assertRaisesMessage(
            self, Exception,
            "relVars2 must be a non-empty sequence of parseable RelationalVariable strings",
            DSeparation.dSeparated, model, 0, ['[A].X1'], [], [])
示例#13
0
    def testGetSchemaItems(self):
        schema = Schema()
        schema.addEntity('A')
        actualItems = schema.getSchemaItems()
        TestUtil.assertUnorderedListEqual(self, ['A'],
                                          [item.name for item in actualItems])
        actualItem = schema.getSchemaItem('A')
        self.assertEqual('A', actualItem.name)
        self.assertTrue(schema.hasSchemaItem('A'))

        schema.addEntity('B')
        actualItems = schema.getSchemaItems()
        TestUtil.assertUnorderedListEqual(self, ['A', 'B'],
                                          [item.name for item in actualItems])
        actualItem = schema.getSchemaItem('B')
        self.assertEqual('B', actualItem.name)
        self.assertTrue(schema.hasSchemaItem('B'))

        schema.addRelationship('AB', ('A', Schema.ONE), ('B', Schema.ONE))
        actualItems = schema.getSchemaItems()
        TestUtil.assertUnorderedListEqual(self, ['A', 'B', 'AB'],
                                          [item.name for item in actualItems])
        actualItem = schema.getSchemaItem('AB')
        self.assertEqual('AB', actualItem.name)
        self.assertTrue(schema.hasSchemaItem('AB'))

        TestUtil.assertRaisesMessage(self, Exception,
                                     "Schema item 'XX' does not exist",
                                     schema.getSchemaItem, 'XX')
        self.assertFalse(schema.hasSchemaItem('XX'))
示例#14
0
    def testNoExistenceVariables(self):
        schema = Schema()
        schema.addEntity('A')
        schema.addEntity('B')
        schema.addEntity('C')
        schema.addRelationship('AB', ('A', Schema.MANY), ('B', Schema.ONE))
        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')

        hop0 = ['[A].X', '[B].Y', '[C].Z', '[AB].XY', '[BC].YZ']

        hop1 = ['[A, AB].XY', '[B, AB].XY', '[B, BC].YZ', '[C, BC].YZ', '[AB, A].X',
                '[AB, B].Y', '[BC, C].Z', '[BC, B].Y']

        hop2 = ['[A, AB, B].Y', '[B, AB, A].X', '[B, BC, C].Z', '[C, BC, B].Y', '[AB, A, AB].XY',
                '[AB, B, BC].YZ', '[BC, C, BC].YZ', '[BC, B, AB].XY']

        hop3 = ['[A, AB, B, BC].YZ', '[B, AB, A, AB].XY', '[B, BC, C, BC].YZ', '[C, BC, B, AB].XY',
                '[AB, A, AB, B].Y', '[AB, B, BC, C].Z', '[BC, C, BC, B].Y', '[BC, B, AB, A].X']

        relVars = RelationalSpace.getRelationalVariables(schema, 3)
        self.assertTrue(all([isinstance(relVar, RelationalVariable) for relVar in relVars]))
        TestUtil.assertUnorderedListEqual(self, hop0 + hop1 + hop2 + hop3, [str(relVar) for relVar in relVars])
示例#15
0
    def testInvalidSetOfRelationalVariables(self):
        # all relvars must have the same perspective
        schema = Schema()
        schema.addEntity('A')
        schema.addEntity('B')
        schema.addRelationship('AB', ('A', Schema.ONE), ('B', Schema.ONE))
        schema.addAttribute('A', 'X')
        schema.addAttribute('B', 'Y')

        TestUtil.assertRaisesMessage(
            self, Exception,
            "Perspective is not consistent across all relational variables",
            RelationalValidity.checkValidityOfRelationalVariableSet, schema, 0,
            [
                ParserUtil.parseRelVar(relVarStr)
                for relVarStr in ['[A].X', '[B].Y']
            ])

        TestUtil.assertRaisesMessage(
            self, Exception,
            "Perspective is not consistent across all relational variables",
            RelationalValidity.checkValidityOfRelationalVariableSet, schema, 0,
            [
                ParserUtil.parseRelVar(relVarStr)
                for relVarStr in ['[B].Y', '[A].X']
            ])

        # all relvars must be consistent with hop threshold
        TestUtil.assertRaisesMessage(
            self, Exception,
            "Relational variable '[A, AB, B].Y' is longer than the hop threshold",
            RelationalValidity.checkValidityOfRelationalVariableSet, schema, 0,
            [
                ParserUtil.parseRelVar(relVarStr)
                for relVarStr in ['[A].X', '[A, AB, B].Y']
            ])

        TestUtil.assertRaisesMessage(
            self, Exception,
            "Relational variable '[A, AB, B].Y' is longer than the hop threshold",
            RelationalValidity.checkValidityOfRelationalVariableSet, schema, 1,
            [
                ParserUtil.parseRelVar(relVarStr)
                for relVarStr in ['[A, AB, B].Y', '[A].X']
            ])

        # enforce that the relational variables are checked for consistency against the schema
        # using RelationalValidity.checkRelationalVariableValidity
        mockRelVarChecker = MagicMock(
            wraps=RelationalValidity.checkRelationalVariableValidity)
        RelationalValidity.checkValidityOfRelationalVariableSet(
            schema,
            2, [
                ParserUtil.parseRelVar(relVarStr)
                for relVarStr in ['[A, AB, B].Y', '[A].X']
            ],
            relationalVariableChecker=mockRelVarChecker)
        self.assertEqual(2, mockRelVarChecker.call_count)
示例#16
0
    def testPhaseI(self):
        schema = Schema()
        schema.addEntity('A')
        schema.addAttribute('A', 'X')
        model = Model(schema, [])
        mockOracle = MagicMock(wraps=Oracle(model))
        mockModelProperty = PropertyMock()
        type(mockOracle).model = mockModelProperty
        pc = PC(schema, mockOracle)
        pc.pcPhaseI()
        self.assertEqual(0, mockModelProperty.call_count)   # forces us not to cheat by simply returning the model
        self.assertPCOutputEqual(['[A].X'], [], {}, 0, pc.undirectedSkeleton, pc.sepsets, mockOracle)

        schema.addAttribute('A', 'Y')
        model = Model(schema, [])
        mockOracle = MagicMock(wraps=Oracle(model))
        mockModelProperty = PropertyMock()
        type(mockOracle).model = mockModelProperty
        pc = PC(schema, mockOracle)
        pc.pcPhaseI()
        self.assertEqual(0, mockModelProperty.call_count)   # forces us not to cheat by simply returning the model
        expectedSepset = {('[A].X', '[A].Y'): set(), ('[A].Y', '[A].X'): set()}
        self.assertPCOutputEqual(['[A].X', '[A].Y'], [], expectedSepset, 1, pc.undirectedSkeleton,
                                 pc.sepsets, mockOracle)

        model = Model(schema, ['[A].X -> [A].Y'])
        mockOracle = MagicMock(wraps=Oracle(model))
        pc = PC(schema, mockOracle)
        pc.pcPhaseI()
        expectedNodes = ['[A].X', '[A].Y']
        expectedEdges = [('[A].X', '[A].Y'), ('[A].Y', '[A].X')]
        self.assertPCOutputEqual(expectedNodes, expectedEdges, {}, 2, pc.undirectedSkeleton,
                                 pc.sepsets, mockOracle)

        schema.addAttribute('A', 'Z')
        model = Model(schema, ['[A].X -> [A].Y'])
        mockOracle = MagicMock(wraps=Oracle(model))
        pc = PC(schema, mockOracle)
        pc.pcPhaseI()
        expectedNodes = ['[A].X', '[A].Y', '[A].Z']
        expectedEdges = [('[A].X', '[A].Y'), ('[A].Y', '[A].X')]
        expectedSepset = {('[A].X', '[A].Z'): set(), ('[A].Z', '[A].X'): set(), ('[A].Y', '[A].Z'): set(),
                          ('[A].Z', '[A].Y'): set()}
        self.assertPCOutputEqual(expectedNodes, expectedEdges, expectedSepset, 4, pc.undirectedSkeleton,
                                 pc.sepsets, mockOracle)

        model = Model(schema, ['[A].X -> [A].Z', '[A].Z -> [A].Y'])
        mockOracle = MagicMock(wraps=Oracle(model))
        pc = PC(schema, mockOracle)
        pc.pcPhaseI()
        expectedNodes = ['[A].X', '[A].Y', '[A].Z']
        expectedEdges = [('[A].X', '[A].Z'), ('[A].Z', '[A].X'), ('[A].Z', '[A].Y'), ('[A].Y', '[A].Z')]
        expectedSepset = {('[A].X', '[A].Y'): {'[A].Z'}, ('[A].Y', '[A].X'): {'[A].Z'}}
        expectedDSepCount = 9

        self.assertPCOutputEqual(expectedNodes, expectedEdges, expectedSepset, expectedDSepCount, pc.undirectedSkeleton,
                                 pc.sepsets, mockOracle)
    def testTwoRelationships(self):
        schema = Schema()
        schema.addEntity('A')
        schema.addEntity('B')
        schema.addEntity('C')
        schema.addRelationship('AB', ('A', Schema.MANY), ('B', Schema.ONE))
        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')

        hop0 = []

        hop1 = [
            '[A, AB].exists -> [A].X', '[B, AB].exists -> [B].Y',
            '[B, BC].exists -> [B].Y', '[C, BC].exists -> [C].Z',
            '[A, AB].XY -> [A].X', '[B, AB].XY -> [B].Y',
            '[B, BC].YZ -> [B].Y', '[C, BC].YZ -> [C].Z',
            '[AB, A].X -> [AB].exists', '[AB, A].X -> [AB].XY',
            '[AB, B].Y -> [AB].exists', '[AB, B].Y -> [AB].XY',
            '[BC, C].Z -> [BC].exists', '[BC, C].Z -> [BC].YZ',
            '[BC, B].Y -> [BC].exists', '[BC, B].Y -> [BC].YZ'
        ]

        hop2 = [
            '[AB, A, AB].exists -> [AB].XY',
            '[AB, B, BC].exists -> [AB].exists',
            '[AB, B, BC].exists -> [AB].XY', '[BC, C, BC].exists -> [BC].YZ',
            '[BC, B, AB].exists -> [BC].exists',
            '[BC, B, AB].exists -> [BC].YZ', '[A, AB, B].Y -> [A].X',
            '[B, AB, A].X -> [B].Y', '[B, BC, C].Z -> [B].Y',
            '[C, BC, B].Y -> [C].Z', '[AB, B, BC].YZ -> [AB].exists',
            '[AB, B, BC].YZ -> [AB].XY', '[BC, B, AB].XY -> [BC].exists',
            '[BC, B, AB].XY -> [BC].YZ'
        ]

        hop3 = [
            '[A, AB, B, BC].exists -> [A].X', '[B, AB, A, AB].exists -> [B].Y',
            '[B, BC, C, BC].exists -> [B].Y', '[C, BC, B, AB].exists -> [C].Z',
            '[A, AB, B, BC].YZ -> [A].X', '[B, AB, A, AB].XY -> [B].Y',
            '[B, BC, C, BC].YZ -> [B].Y', '[C, BC, B, AB].XY -> [C].Z',
            '[AB, A, AB, B].Y -> [AB].XY', '[AB, B, BC, C].Z -> [AB].exists',
            '[AB, B, BC, C].Z -> [AB].XY', '[BC, C, BC, B].Y -> [BC].YZ',
            '[BC, B, AB, A].X -> [BC].exists', '[BC, B, AB, A].X -> [BC].YZ'
        ]

        relDeps = RelationalSpace.getRelationalDependencies(
            schema, 3, includeExistence=True)
        self.assertTrue(
            all([
                isinstance(relDep, RelationalDependency) for relDep in relDeps
            ]))
        TestUtil.assertUnorderedListEqual(self, hop0 + hop1 + hop2 + hop3,
                                          [str(relDep) for relDep in relDeps])
示例#18
0
    def testSchemaEntities(self):
        schemaWithEntityA = Schema()
        schemaWithEntityA.addEntity('A')
        actualEntities = schemaWithEntityA.getEntities()
        TestUtil.assertUnorderedListEqual(self, ['A'],
                                          [ent.name for ent in actualEntities])

        schemaWithEntityA.addEntity('B')
        actualEntities = schemaWithEntityA.getEntities()
        TestUtil.assertUnorderedListEqual(self, ['A', 'B'],
                                          [ent.name for ent in actualEntities])
示例#19
0
 def testChoseTooFewDependencies(self):
     schema = Schema()
     schema.addEntity('A')
     schema.addAttribute('A', 'X1')
     schema.addAttribute('A', 'X2')
     schema.addAttribute('A', 'X3')
     dependencies = ['[A].X3 -> [A].X1', '[A].X1 -> [A].X2', '[A].X2 -> [A].X3', '[A].X2 -> [A].X1',
                     '[A].X1 -> [A].X3', '[A].X3 -> [A].X2']
     TestUtil.assertRaisesMessage(self, Exception, "Could not generate a model: failed to find a model with 4 dependenc[y|ies]",
                 ModelGenerator.generateModel, schema, 0, 4, dependencies=dependencies,
                 randomPicker=lambda depsList, _: [depsList[0]])
示例#20
0
 def testRemoveCommonCondRelVarOnlyFromRelVars(self):
     schema = Schema()
     schema.addEntity('A')
     schema.addAttribute('A', 'X1')
     schema.addAttribute('A', 'X2')
     schema.addAttribute('A', 'X3')
     model = Model(schema, ['[A].X1 -> [A].X2', '[A].X2 -> [A].X3'])
     dsep = DSeparation(model)
     self.assertTrue(
         dsep.dSeparated(0, ['[A].X1', '[A].X2'], ['[A].X3'], ['[A].X2']))
     self.assertTrue(
         dsep.dSeparated(0, ['[A].X1', '[A].X2'], ['[A].X2', '[A].X3'],
                         ['[A].X2']))
示例#21
0
    def testExtendPaths(self):
        schema = Schema()
        schema.addEntity('A')
        schema.addEntity('B')
        schema.addRelationship('AB', ('A', Schema.MANY), ('B', Schema.MANY))
        schema.addAttribute('AB', 'XY1')
        schema.addAttribute('AB', 'XY2')
        schema.addAttribute('AB', 'XY3')

        from causality.dseparation import AbstractGroundGraph as AGG_module
        self.assertEqual([['AB', 'B', 'AB', 'A', 'AB', 'B', 'AB']],
                         AGG_module.extendPath(schema, ['AB', 'B', 'AB'],
                                               ['AB', 'A', 'AB', 'B', 'AB']))
示例#22
0
 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),
                                       [])
示例#23
0
    def testOneRelationshipManyToOne(self):
        schema = Schema()
        schema.addEntity('A')
        schema.addEntity('B')
        schema.addRelationship('AB', ('A', Schema.ONE), ('B', Schema.MANY))

        relPaths = RelationalSpace.getRelationalPaths(schema, 3)
        hopUpTo3 = [['A'], ['B'], ['AB'], ['A', 'AB'], ['AB',
                                                        'A'], ['AB', 'B'],
                    ['B', 'AB'], ['A', 'AB', 'B'], ['AB', 'B', 'AB'],
                    ['B', 'AB', 'A'], ['A', 'AB', 'B', 'AB'],
                    ['AB', 'B', 'AB', 'A']]
        TestUtil.assertUnorderedListEqual(self, hopUpTo3, relPaths)
示例#24
0
 def testPCLearnModel(self):
     schema = Schema()
     schema.addEntity('A')
     schema.addAttribute('A', 'X')
     schema.addAttribute('A', 'Y')
     schema.addAttribute('A', 'Z')
     schema.addAttribute('A', 'W')
     model = Model(schema, ['[A].X -> [A].Y', '[A].X -> [A].W', '[A].X -> [A].Z', '[A].Y -> [A].Z', '[A].W -> [A].Z'])
     pc = PC(schema, Oracle(model))
     pc.learnModel()
     expectedNodes = ['[A].X', '[A].Y', '[A].Z', '[A].W']
     expectedEdges = [('[A].X', '[A].Z'), ('[A].Y', '[A].Z'), ('[A].W', '[A].Z'), ('[A].X', '[A].Y'),
                      ('[A].Y', '[A].X'), ('[A].W', '[A].X'), ('[A].X', '[A].W')]
     self.assertPCOutputEqual(expectedNodes, expectedEdges, None, None, pc.partiallyDirectedGraph, None, None)
示例#25
0
 def testBadHopThresholdInput(self):
     # hop thresholds must be non-negative integers
     schema = Schema()
     schema.addEntity('A')
     model = Model(schema, [])
     TestUtil.assertRaisesMessage(
         self, Exception, "hopThreshold must be a non-negative integer",
         AbstractGroundGraph, model, 'A', None)
     TestUtil.assertRaisesMessage(
         self, Exception, "hopThreshold must be a non-negative integer",
         AbstractGroundGraph, model, 'A', 1.5)
     TestUtil.assertRaisesMessage(
         self, Exception, "hopThreshold must be a non-negative integer",
         AbstractGroundGraph, model, 'A', -1)
示例#26
0
    def testIntersectingInputRelVars(self):
        schema = Schema()
        schema.addEntity('A')
        schema.addAttribute('A', 'X1')
        schema.addAttribute('A', 'X2')
        model = Model(schema, [])
        dsep = DSeparation(model)
        self.assertFalse(dsep.dSeparated(0, ['[A].X1'], ['[A].X1'], []))
        self.assertFalse(
            dsep.dSeparated(0, ['[A].X2', '[A].X1'], ['[A].X1', '[A].X2'], []))
        self.assertFalse(
            dsep.dSeparated(0, ['[A].X2', '[A].X1'], ['[A].X1'], []))

        schema = Schema()
        schema.addEntity('A')
        schema.addAttribute('A', 'X')
        schema.addEntity('B')
        schema.addAttribute('B', 'Y')
        schema.addRelationship('AB', ('A', Schema.MANY), ('B', Schema.MANY))
        schema.addEntity('C')
        schema.addAttribute('C', 'Z')
        schema.addRelationship('BC', ('B', Schema.ONE), ('C', Schema.MANY))
        model = Model(schema, [])
        dsep = DSeparation(model)
        self.assertFalse(
            dsep.dSeparated(6, ['[A, AB, B, AB, A, AB, B].Y'],
                            ['[A, AB, B, BC, C, BC, B].Y'], []))
示例#27
0
    def testGenerateEntities(self):
        schema = SchemaGenerator.generateSchema(0, 0)
        expectedSchema = Schema()
        self.assertEqual(schema, expectedSchema)

        schema = SchemaGenerator.generateSchema(
            1, 0, entityAttrDistribution=ConstantDistribution(0))
        expectedSchema.addEntity('A')
        self.assertEqual(schema, expectedSchema)

        schema = SchemaGenerator.generateSchema(
            2, 0, entityAttrDistribution=ConstantDistribution(0))
        expectedSchema.addEntity('B')
        self.assertEqual(schema, expectedSchema)
示例#28
0
    def testMaximumNumParentsArgument(self):
        schema = Schema()
        schema.addEntity('A')
        schema.addAttribute('A', 'X1')
        schema.addAttribute('A', 'X2')
        schema.addAttribute('A', 'X3')
        dependencies = ['[A].X1 -> [A].X3', '[A].X2 -> [A].X3']
        TestUtil.assertRaisesMessage(self, Exception, "Could not generate a model: failed to find a model with 2 dependenc[y|ies]",
                                     ModelGenerator.generateModel, schema, 0, 2, maxNumParents=1, dependencies=dependencies)

        schema.addAttribute('A', 'X4')
        dependencies = ['[A].X1 -> [A].X3', '[A].X2 -> [A].X3', '[A].X4 -> [A].X3']
        TestUtil.assertRaisesMessage(self, Exception, "Could not generate a model: failed to find a model with 3 dependenc[y|ies]",
                                     ModelGenerator.generateModel, schema, 0, 3, maxNumParents=2, dependencies=dependencies)
示例#29
0
    def testTwoVariableModels(self):
        schema = Schema()
        schema.addEntity('A')
        schema.addAttribute('A', 'X1')
        schema.addAttribute('A', 'X2')
        model = Model(schema, [])
        dsep = DSeparation(model)
        self.assertTrue(dsep.dSeparated(0, ['[A].X1'], ['[A].X2'], []))
        self.assertTrue(dsep.dSeparated(0, ['[A].X2'], ['[A].X1'], []))

        model = Model(schema, ['[A].X1 -> [A].X2'])
        dsep = DSeparation(model)
        self.assertFalse(dsep.dSeparated(0, ['[A].X1'], ['[A].X2'], []))
        self.assertFalse(dsep.dSeparated(0, ['[A].X2'], ['[A].X1'], []))
示例#30
0
    def testGenerateEntityAttributes(self):
        schema = SchemaGenerator.generateSchema(
            1, 0, entityAttrDistribution=ConstantDistribution(1))
        expectedSchema = Schema()
        expectedSchema.addEntity('A')
        expectedSchema.addAttribute('A', 'X1')
        self.assertEqual(schema, expectedSchema)

        schema = SchemaGenerator.generateSchema(
            2, 0, entityAttrDistribution=ConstantDistribution(2))
        expectedSchema.addEntity('B')
        expectedSchema.addAttribute('A', 'X2')
        expectedSchema.addAttribute('B', 'Y1')
        expectedSchema.addAttribute('B', 'Y2')
        self.assertEqual(schema, expectedSchema)
示例#31
0
def incompleteness_example():
    schema = Schema()
    schema.addEntity("E1")
    schema.addEntity("E2")
    schema.addEntity("E3")
    schema.addRelationship("R1", ("E1", Schema.ONE), ("E2", Schema.ONE))
    schema.addRelationship("R2", ("E2", Schema.ONE), ("E3", Schema.ONE))
    schema.addRelationship("R3", ("E2", Schema.ONE), ("E3", Schema.ONE))
    schema.addAttribute("R1", "X")
    schema.addAttribute("R2", "Y")
    schema.addAttribute("E2", "Z")

    d1 = RelationalDependency(RelationalVariable(["R2", "E2", "R1"], "X"), RelationalVariable(["R2"], "Y"))
    d2 = RelationalDependency(RelationalVariable(["R2", "E3", "R3", "E2"], "Z"), RelationalVariable(["R2"], "Y"))
    d3 = RelationalDependency(RelationalVariable(["R1", "E2", "R2", "E3", "R3", "E2"], "Z"),
                              RelationalVariable(["R1"], "X"))
    model = Model(schema, [d1, d2, d3])
    return schema, model