本文整理汇总了Python中pgmpy.models.BayesianModel.add_edges_from方法的典型用法代码示例。如果您正苦于以下问题:Python BayesianModel.add_edges_from方法的具体用法?Python BayesianModel.add_edges_from怎么用?Python BayesianModel.add_edges_from使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类pgmpy.models.BayesianModel
的用法示例。
在下文中一共展示了BayesianModel.add_edges_from方法的10个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Python代码示例。
示例1: estimate
# 需要导入模块: from pgmpy.models import BayesianModel [as 别名]
# 或者: from pgmpy.models.BayesianModel import add_edges_from [as 别名]
def estimate(self):
"""
Estimates the `BayesianModel` structure that fits best to the given data set,
according to the scoring method supplied in the constructor.
Exhaustively searches through all models. Only estimates network structure, no parametrization.
Returns
-------
model: `BayesianModel` instance
A `BayesianModel` with maximal score.
Examples
--------
>>> import pandas as pd
>>> import numpy as np
>>> from pgmpy.estimators import ExhaustiveSearch
>>> # create random data sample with 3 variables, where B and C are identical:
>>> data = pd.DataFrame(np.random.randint(0, 5, size=(5000, 2)), columns=list('AB'))
>>> data['C'] = data['B']
>>> est = ExhaustiveSearch(data)
>>> best_model = est.estimate()
>>> best_model
<pgmpy.models.BayesianModel.BayesianModel object at 0x7f695c535470>
>>> best_model.edges()
[('B', 'C')]
"""
best_dag = max(self.all_dags(), key=self.scoring_method.score)
best_model = BayesianModel()
best_model.add_nodes_from(sorted(best_dag.nodes()))
best_model.add_edges_from(sorted(best_dag.edges()))
return best_model
示例2: to_bayesian_model
# 需要导入模块: from pgmpy.models import BayesianModel [as 别名]
# 或者: from pgmpy.models.BayesianModel import add_edges_from [as 别名]
def to_bayesian_model(self):
"""
Creates a Bayesian Model which is a minimum I-Map for this markov model.
The ordering of parents may not remain constant. It would depend on the
ordering of variable in the junction tree (which is not constant) all the
time.
Examples
--------
>>> from pgmpy.models import MarkovModel
>>> from pgmpy.factors.discrete import DiscreteFactor
>>> mm = MarkovModel()
>>> mm.add_nodes_from(['x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7'])
>>> mm.add_edges_from([('x1', 'x3'), ('x1', 'x4'), ('x2', 'x4'),
... ('x2', 'x5'), ('x3', 'x6'), ('x4', 'x6'),
... ('x4', 'x7'), ('x5', 'x7')])
>>> phi = [DiscreteFactor(edge, [2, 2], np.random.rand(4)) for edge in mm.edges()]
>>> mm.add_factors(*phi)
>>> bm = mm.to_bayesian_model()
"""
from pgmpy.models import BayesianModel
bm = BayesianModel()
var_clique_dict = defaultdict(tuple)
var_order = []
# Create a junction tree from the markov model.
# Creation of clique tree involves triangulation, finding maximal cliques
# and creating a tree from these cliques
junction_tree = self.to_junction_tree()
# create an ordering of the nodes based on the ordering of the clique
# in which it appeared first
root_node = junction_tree.nodes()[0]
bfs_edges = nx.bfs_edges(junction_tree, root_node)
for node in root_node:
var_clique_dict[node] = root_node
var_order.append(node)
for edge in bfs_edges:
clique_node = edge[1]
for node in clique_node:
if not var_clique_dict[node]:
var_clique_dict[node] = clique_node
var_order.append(node)
# create a bayesian model by adding edges from parent of node to node as
# par(x_i) = (var(c_k) - x_i) \cap {x_1, ..., x_{i-1}}
for node_index in range(len(var_order)):
node = var_order[node_index]
node_parents = (set(var_clique_dict[node]) - set([node])).intersection(
set(var_order[:node_index]))
bm.add_edges_from([(parent, node) for parent in node_parents])
# TODO : Convert factor into CPDs
return bm
示例3: minimal_imap
# 需要导入模块: from pgmpy.models import BayesianModel [as 别名]
# 或者: from pgmpy.models.BayesianModel import add_edges_from [as 别名]
def minimal_imap(self, order):
"""
Returns a Bayesian Model which is minimal IMap of the Joint Probability Distribution
considering the order of the variables.
Parameters
----------
order: array-like
The order of the random variables.
Examples
--------
>>> import numpy as np
>>> from pgmpy.factors import JointProbabilityDistribution
>>> prob = JointProbabilityDistribution(['x1', 'x2', 'x3'], [2, 3, 2], np.ones(12)/12)
>>> bayesian_model = prob.minimal_imap(order=['x2', 'x1', 'x3'])
>>> bayesian_model
<pgmpy.models.models.models at 0x7fd7440a9320>
>>> bayesian_model.edges()
[('x1', 'x3'), ('x2', 'x3')]
"""
from pgmpy.models import BayesianModel
def get_subsets(u):
for r in range(len(u) + 1):
for i in itertools.combinations(u, r):
yield i
G = BayesianModel()
for variable_index in range(len(order)):
u = order[:variable_index]
for subset in get_subsets(u):
if (len(subset) < len(u) and
self.check_independence([order[variable_index]], set(u)-set(subset), subset, True)):
G.add_edges_from([(variable, order[variable_index]) for variable in subset])
return G
示例4: test_predict
# 需要导入模块: from pgmpy.models import BayesianModel [as 别名]
# 或者: from pgmpy.models.BayesianModel import add_edges_from [as 别名]
def test_predict(self):
titanic = BayesianModel()
titanic.add_edges_from([("Sex", "Survived"), ("Pclass", "Survived")])
titanic.fit(self.titanic_data2[500:])
p1 = titanic.predict(self.titanic_data2[["Sex", "Pclass"]][:30])
p2 = titanic.predict(self.titanic_data2[["Survived", "Pclass"]][:30])
p3 = titanic.predict(self.titanic_data2[["Survived", "Sex"]][:30])
p1_res = np.array(['0', '1', '0', '1', '0', '0', '0', '0', '0', '1', '0', '1', '0',
'0', '0', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
'0', '0', '0', '0'])
p2_res = np.array(['male', 'female', 'female', 'female', 'male', 'male', 'male',
'male', 'female', 'female', 'female', 'female', 'male', 'male',
'male', 'female', 'male', 'female', 'male', 'female', 'male',
'female', 'female', 'female', 'male', 'female', 'male', 'male',
'female', 'male'])
p3_res = np.array(['3', '1', '1', '1', '3', '3', '3', '3', '1', '1', '1', '1', '3',
'3', '3', '1', '3', '1', '3', '1', '3', '1', '1', '1', '3', '1',
'3', '3', '1', '3'])
np_test.assert_array_equal(p1.values.ravel(), p1_res)
np_test.assert_array_equal(p2.values.ravel(), p2_res)
np_test.assert_array_equal(p3.values.ravel(), p3_res)
示例5: TabularCPD
# 需要导入模块: from pgmpy.models import BayesianModel [as 别名]
# 或者: from pgmpy.models.BayesianModel import add_edges_from [as 别名]
cpd_rain = TabularCPD('Rain', 2, [[0.4], [0.6]])
cpd_accident = TabularCPD('Accident', 2, [[0.2], [0.8]])
cpd_traffic_jam = TabularCPD('TrafficJam', 2,
[[0.9, 0.6, 0.7, 0.1],
[0.1, 0.4, 0.3, 0.9]],
evidence=['Rain', 'Accident'],
evidence_card=[2, 2])
model.add_cpds(cpd_rain, cpd_accident, cpd_traffic_jam)
model.add_node('LongQueues')
model.add_edge('TrafficJam', 'LongQueues')
cpd_long_queues = TabularCPD('LongQueues', 2,
[[0.9, 0.2],
[0.1, 0.8]],
evidence=['TrafficJam'],
evidence_card=[2])
model.add_cpds(cpd_long_queues)
model.add_nodes_from(['GettingUpLate', 'LateForSchool'])
model.add_edges_from([('GettingUpLate', 'LateForSchool'),
('TrafficJam', 'LateForSchool')])
cpd_getting_up_late = TabularCPD('GettingUpLate', 2,
[[0.6], [0.4]])
cpd_late_for_school = TabularCPD('LateForSchool', 2,
[[0.9, 0.45, 0.8, 0.1],
[0.1, 0.55, 0.2, 0.9]],
evidence=['GettingUpLate', 'TrafficJam'],
evidence_card=[2, 2])
model.add_cpds(cpd_getting_up_late, cpd_late_for_school)
# Conversion from BayesianModel to MarkovModel is accomplished by
mm = model.to_markov_model()
mm.edges()
示例6: TestGibbsSampling
# 需要导入模块: from pgmpy.models import BayesianModel [as 别名]
# 或者: from pgmpy.models.BayesianModel import add_edges_from [as 别名]
class TestGibbsSampling(unittest.TestCase):
def setUp(self):
# A test Bayesian model
diff_cpd = TabularCPD('diff', 2, [[0.6], [0.4]])
intel_cpd = TabularCPD('intel', 2, [[0.7], [0.3]])
grade_cpd = TabularCPD('grade', 3, [[0.3, 0.05, 0.9, 0.5], [0.4, 0.25, 0.08, 0.3], [0.3, 0.7, 0.02, 0.2]],
evidence=['diff', 'intel'], evidence_card=[2, 2])
self.bayesian_model = BayesianModel()
self.bayesian_model.add_nodes_from(['diff', 'intel', 'grade'])
self.bayesian_model.add_edges_from([('diff', 'grade'), ('intel', 'grade')])
self.bayesian_model.add_cpds(diff_cpd, intel_cpd, grade_cpd)
# A test Markov model
self.markov_model = MarkovModel([('A', 'B'), ('C', 'B'), ('B', 'D')])
factor_ab = Factor(['A', 'B'], [2, 3], [1, 2, 3, 4, 5, 6])
factor_cb = Factor(['C', 'B'], [4, 3], [3, 1, 4, 5, 7, 8, 1, 3, 10, 4, 5, 6])
factor_bd = Factor(['B', 'D'], [3, 2], [5, 7, 2, 1, 9, 3])
self.markov_model.add_factors(factor_ab, factor_cb, factor_bd)
self.gibbs = GibbsSampling(self.bayesian_model)
def tearDown(self):
del self.bayesian_model
del self.markov_model
@patch('pgmpy.inference.Sampling.GibbsSampling._get_kernel_from_bayesian_model', autospec=True)
@patch('pgmpy.models.MarkovChain.__init__', autospec=True)
def test_init_bayesian_model(self, init, get_kernel):
model = MagicMock(spec_set=BayesianModel)
gibbs = GibbsSampling(model)
init.assert_called_once_with(gibbs)
get_kernel.assert_called_once_with(gibbs, model)
@patch('pgmpy.inference.Sampling.GibbsSampling._get_kernel_from_markov_model', autospec=True)
def test_init_markov_model(self, get_kernel):
model = MagicMock(spec_set=MarkovModel)
gibbs = GibbsSampling(model)
get_kernel.assert_called_once_with(gibbs, model)
def test_get_kernel_from_bayesian_model(self):
gibbs = GibbsSampling()
gibbs._get_kernel_from_bayesian_model(self.bayesian_model)
self.assertListEqual(list(gibbs.variables), self.bayesian_model.nodes())
self.assertDictEqual(gibbs.cardinalities, {'diff': 2, 'intel': 2, 'grade': 3})
def test_get_kernel_from_markov_model(self):
gibbs = GibbsSampling()
gibbs._get_kernel_from_markov_model(self.markov_model)
self.assertListEqual(list(gibbs.variables), self.markov_model.nodes())
self.assertDictEqual(gibbs.cardinalities, {'A': 2, 'B': 3, 'C': 4, 'D': 2})
def test_sample(self):
start_state = [State('diff', 0), State('intel', 0), State('grade', 0)]
sample = self.gibbs.sample(start_state, 2)
self.assertEquals(len(sample), 2)
self.assertEquals(len(sample.columns), 3)
self.assertIn('diff', sample.columns)
self.assertIn('intel', sample.columns)
self.assertIn('grade', sample.columns)
self.assertTrue(set(sample['diff']).issubset({0, 1}))
self.assertTrue(set(sample['intel']).issubset({0, 1}))
self.assertTrue(set(sample['grade']).issubset({0, 1, 2}))
@patch("pgmpy.inference.Sampling.GibbsSampling.random_state", autospec=True)
def test_sample_less_arg(self, random_state):
self.gibbs.state = None
random_state.return_value = [State('diff', 0), State('intel', 0), State('grade', 0)]
sample = self.gibbs.sample(size=2)
random_state.assert_called_once_with(self.gibbs)
self.assertEqual(len(sample), 2)
def test_generate_sample(self):
start_state = [State('diff', 0), State('intel', 0), State('grade', 0)]
gen = self.gibbs.generate_sample(start_state, 2)
samples = [sample for sample in gen]
self.assertEqual(len(samples), 2)
self.assertEqual({samples[0][0].var, samples[0][1].var, samples[0][2].var}, {'diff', 'intel', 'grade'})
self.assertEqual({samples[1][0].var, samples[1][1].var, samples[1][2].var}, {'diff', 'intel', 'grade'})
@patch("pgmpy.inference.Sampling.GibbsSampling.random_state", autospec=True)
def test_generate_sample_less_arg(self, random_state):
self.gibbs.state = None
gen = self.gibbs.generate_sample(size=2)
samples = [sample for sample in gen]
random_state.assert_called_once_with(self.gibbs)
self.assertEqual(len(samples), 2)
示例7: TestDirectedGraphCPDOperations
# 需要导入模块: from pgmpy.models import BayesianModel [as 别名]
# 或者: from pgmpy.models.BayesianModel import add_edges_from [as 别名]
class TestDirectedGraphCPDOperations(unittest.TestCase):
def setUp(self):
self.graph = BayesianModel()
def test_add_single_cpd(self):
cpd = TabularCPD('grade', 2, np.random.rand(2, 4),
['diff', 'intel'], [2, 2])
self.graph.add_edges_from([('diff', 'grade'), ('intel', 'grade')])
self.graph.add_cpds(cpd)
self.assertListEqual(self.graph.get_cpds(), [cpd])
def test_add_multiple_cpds(self):
cpd1 = TabularCPD('diff', 2, np.random.rand(2, 1))
cpd2 = TabularCPD('intel', 2, np.random.rand(2, 1))
cpd3 = TabularCPD('grade', 2, np.random.rand(2, 4),
['diff', 'intel'], [2, 2])
self.graph.add_edges_from([('diff', 'grade'), ('intel', 'grade')])
self.graph.add_cpds(cpd1, cpd2, cpd3)
self.assertListEqual(self.graph.get_cpds(), [cpd1, cpd2, cpd3])
def test_remove_single_cpd(self):
cpd1 = TabularCPD('diff', 2, np.random.rand(2, 1))
cpd2 = TabularCPD('intel', 2, np.random.rand(2, 1))
cpd3 = TabularCPD('grade', 2, np.random.rand(2, 4),
['diff', 'intel'], [2, 2])
self.graph.add_edges_from([('diff', 'grade'), ('intel', 'grade')])
self.graph.add_cpds(cpd1, cpd2, cpd3)
self.graph.remove_cpds(cpd1)
self.assertListEqual(self.graph.get_cpds(), [cpd2, cpd3])
def test_remove_multiple_cpds(self):
cpd1 = TabularCPD('diff', 2, np.random.rand(2, 1))
cpd2 = TabularCPD('intel', 2, np.random.rand(2, 1))
cpd3 = TabularCPD('grade', 2, np.random.rand(2, 4),
['diff', 'intel'], [2, 2])
self.graph.add_edges_from([('diff', 'grade'), ('intel', 'grade')])
self.graph.add_cpds(cpd1, cpd2, cpd3)
self.graph.remove_cpds(cpd1, cpd3)
self.assertListEqual(self.graph.get_cpds(), [cpd2])
def test_remove_single_cpd_string(self):
cpd1 = TabularCPD('diff', 2, np.random.rand(2, 1))
cpd2 = TabularCPD('intel', 2, np.random.rand(2, 1))
cpd3 = TabularCPD('grade', 2, np.random.rand(2, 4),
['diff', 'intel'], [2, 2])
self.graph.add_edges_from([('diff', 'grade'), ('intel', 'grade')])
self.graph.add_cpds(cpd1, cpd2, cpd3)
self.graph.remove_cpds('diff')
self.assertListEqual(self.graph.get_cpds(), [cpd2, cpd3])
def test_remove_multiple_cpds_string(self):
cpd1 = TabularCPD('diff', 2, np.random.rand(2, 1))
cpd2 = TabularCPD('intel', 2, np.random.rand(2, 1))
cpd3 = TabularCPD('grade', 2, np.random.rand(2, 4),
['diff', 'intel'], [2, 2])
self.graph.add_edges_from([('diff', 'grade'), ('intel', 'grade')])
self.graph.add_cpds(cpd1, cpd2, cpd3)
self.graph.remove_cpds('diff', 'grade')
self.assertListEqual(self.graph.get_cpds(), [cpd2])
def test_get_cpd_for_node(self):
cpd1 = TabularCPD('diff', 2, np.random.rand(2, 1))
cpd2 = TabularCPD('intel', 2, np.random.rand(2, 1))
cpd3 = TabularCPD('grade', 2, np.random.rand(2, 4),
['diff', 'intel'], [2, 2])
self.graph.add_edges_from([('diff', 'grade'), ('intel', 'grade')])
self.graph.add_cpds(cpd1, cpd2, cpd3)
self.assertEqual(self.graph.get_cpds('diff'), cpd1)
self.assertEqual(self.graph.get_cpds('intel'), cpd2)
self.assertEqual(self.graph.get_cpds('grade'), cpd3)
def test_get_cpd_raises_error(self):
cpd1 = TabularCPD('diff', 2, np.random.rand(2, 1))
cpd2 = TabularCPD('intel', 2, np.random.rand(2, 1))
cpd3 = TabularCPD('grade', 2, np.random.rand(2, 4),
['diff', 'intel'], [2, 2])
self.graph.add_edges_from([('diff', 'grade'), ('intel', 'grade')])
self.graph.add_cpds(cpd1, cpd2, cpd3)
self.assertRaises(ValueError, self.graph.get_cpds, 'sat')
def tearDown(self):
del self.graph
示例8: TestBaseModelCreation
# 需要导入模块: from pgmpy.models import BayesianModel [as 别名]
# 或者: from pgmpy.models.BayesianModel import add_edges_from [as 别名]
class TestBaseModelCreation(unittest.TestCase):
def setUp(self):
self.G = BayesianModel()
def test_class_init_without_data(self):
self.assertIsInstance(self.G, nx.DiGraph)
def test_class_init_with_data_string(self):
self.g = BayesianModel([('a', 'b'), ('b', 'c')])
self.assertListEqual(sorted(self.g.nodes()), ['a', 'b', 'c'])
self.assertListEqual(hf.recursive_sorted(self.g.edges()),
[['a', 'b'], ['b', 'c']])
def test_class_init_with_data_nonstring(self):
BayesianModel([(1, 2), (2, 3)])
def test_add_node_string(self):
self.G.add_node('a')
self.assertListEqual(self.G.nodes(), ['a'])
def test_add_node_nonstring(self):
self.G.add_node(1)
def test_add_nodes_from_string(self):
self.G.add_nodes_from(['a', 'b', 'c', 'd'])
self.assertListEqual(sorted(self.G.nodes()), ['a', 'b', 'c', 'd'])
def test_add_nodes_from_non_string(self):
self.G.add_nodes_from([1, 2, 3, 4])
def test_add_edge_string(self):
self.G.add_edge('d', 'e')
self.assertListEqual(sorted(self.G.nodes()), ['d', 'e'])
self.assertListEqual(self.G.edges(), [('d', 'e')])
self.G.add_nodes_from(['a', 'b', 'c'])
self.G.add_edge('a', 'b')
self.assertListEqual(hf.recursive_sorted(self.G.edges()),
[['a', 'b'], ['d', 'e']])
def test_add_edge_nonstring(self):
self.G.add_edge(1, 2)
def test_add_edge_selfloop(self):
self.assertRaises(ValueError, self.G.add_edge, 'a', 'a')
def test_add_edge_result_cycle(self):
self.G.add_edges_from([('a', 'b'), ('a', 'c')])
self.assertRaises(ValueError, self.G.add_edge, 'c', 'a')
def test_add_edges_from_string(self):
self.G.add_edges_from([('a', 'b'), ('b', 'c')])
self.assertListEqual(sorted(self.G.nodes()), ['a', 'b', 'c'])
self.assertListEqual(hf.recursive_sorted(self.G.edges()),
[['a', 'b'], ['b', 'c']])
self.G.add_nodes_from(['d', 'e', 'f'])
self.G.add_edges_from([('d', 'e'), ('e', 'f')])
self.assertListEqual(sorted(self.G.nodes()),
['a', 'b', 'c', 'd', 'e', 'f'])
self.assertListEqual(hf.recursive_sorted(self.G.edges()),
hf.recursive_sorted([('a', 'b'), ('b', 'c'),
('d', 'e'), ('e', 'f')]))
def test_add_edges_from_nonstring(self):
self.G.add_edges_from([(1, 2), (2, 3)])
def test_add_edges_from_self_loop(self):
self.assertRaises(ValueError, self.G.add_edges_from,
[('a', 'a')])
def test_add_edges_from_result_cycle(self):
self.assertRaises(ValueError, self.G.add_edges_from,
[('a', 'b'), ('b', 'c'), ('c', 'a')])
def test_update_node_parents_bm_constructor(self):
self.g = BayesianModel([('a', 'b'), ('b', 'c')])
self.assertListEqual(self.g.predecessors('a'), [])
self.assertListEqual(self.g.predecessors('b'), ['a'])
self.assertListEqual(self.g.predecessors('c'), ['b'])
def test_update_node_parents(self):
self.G.add_nodes_from(['a', 'b', 'c'])
self.G.add_edges_from([('a', 'b'), ('b', 'c')])
self.assertListEqual(self.G.predecessors('a'), [])
self.assertListEqual(self.G.predecessors('b'), ['a'])
self.assertListEqual(self.G.predecessors('c'), ['b'])
def tearDown(self):
del self.G
示例9: str
# 需要导入模块: from pgmpy.models import BayesianModel [as 别名]
# 或者: from pgmpy.models.BayesianModel import add_edges_from [as 别名]
ax_temp.bar(x, z, zs=y, zdir='y', alpha=0.6, color='r' * 4)
ax_temp.set_xlabel('X')
ax_temp.set_ylabel('Y')
ax_temp.set_zlabel('Z')
ax_temp.title.set_text(('Feature ' + str(mean_indices[counter])))
counter += 1
plt.show()
# Learning naive bayes model from various subsets of data
naive_bayes_with_some_features(all_city_data, all_city_label, feature_list=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
naive_bayes_with_some_features(all_city_data, all_city_label, feature_list=[0, 1, 2])
naive_bayes_with_some_features(all_city_data, all_city_label, feature_list=[0, 1, 2, 4])
naive_bayes_with_some_features(all_city_data, all_city_label, feature_list=[0, 1, 2, 3, 4, 5])
# Splitting train and test data for PGM model
temp_data = pd.concat([all_city_data, pd.DataFrame(all_city_label, columns=[13])], axis=1)
pgm_train_set = temp_data.loc[0:700]
pgm_test_set = temp_data.loc[700:]
print(pgm_train_set)
# Implementing PGM model on data
# Using these features: 0: (age) 1: (sex) 2: (cp)
pgm_model = BayesianModel()
pgm_model.add_nodes_from([0, 1, 2, 13])
pgm_model.add_edges_from([(1, 13)])
pgm_model.fit(pgm_train_set.loc[:, [0, 1, 2, 13]])
pgm_test_set = pgm_test_set.loc[:, [0, 1, 2, 13]].drop(13, axis=1)
print(pgm_test_set)
print(pgm_model.get_cpds(13))
示例10: BayesianModel
# 需要导入模块: from pgmpy.models import BayesianModel [as 别名]
# 或者: from pgmpy.models.BayesianModel import add_edges_from [as 别名]
# Bayesian network for students
from pgmpy.models import BayesianModel
model = BayesianModel()
# Add nodes
model.add_nodes_from(['difficulty', 'intelligence', 'grade', 'sat', 'letter'])
print(model.nodes())
# Add edges
model.add_edges_from([('difficulty', 'grade'), ('intelligence', 'grade'), ('intelligence', 'sat'), ('grade', 'letter')])
print(model.edges())