import unittest
import os
import networkx as nx
from Optimization.Order.ConstructionOrdering import ConstructionOrdering
 
class Test_level_marks(unittest.TestCase):
    def test_level_mark_basics(self):
        G = nx.DiGraph()
        G.add_nodes_from(range(8))
        G.add_edges_from([(0, 1), (0, 4), (1, 2), (2, 3), (4, 5), (5, 2), (5, 6), (6, 7), (7, 3)])
        ConstructionOrdering.markLevels(G)
        self.assertEqual(G.node[0][ConstructionOrdering.kAttrNameNodeLevel], 0)
        self.assertEqual(G.node[1][ConstructionOrdering.kAttrNameNodeLevel], 1)
        self.assertEqual(G.node[2][ConstructionOrdering.kAttrNameNodeLevel], 3)
        self.assertEqual(G.node[3][ConstructionOrdering.kAttrNameNodeLevel], 5)
        self.assertEqual(G.node[4][ConstructionOrdering.kAttrNameNodeLevel], 1)
        self.assertEqual(G.node[5][ConstructionOrdering.kAttrNameNodeLevel], 2)
        self.assertEqual(G.node[6][ConstructionOrdering.kAttrNameNodeLevel], 3)
        self.assertEqual(G.node[7][ConstructionOrdering.kAttrNameNodeLevel], 4)
        self.assertEqual(G.node[0][ConstructionOrdering.kAttrNameNodeAfterLength], 5)
        self.assertEqual(G.node[1][ConstructionOrdering.kAttrNameNodeAfterLength], 2)
        self.assertEqual(G.node[2][ConstructionOrdering.kAttrNameNodeAfterLength], 1)
        self.assertEqual(G.node[3][ConstructionOrdering.kAttrNameNodeAfterLength], 0)
        self.assertEqual(G.node[4][ConstructionOrdering.kAttrNameNodeAfterLength], 4)
        self.assertEqual(G.node[5][ConstructionOrdering.kAttrNameNodeAfterLength], 3)
        self.assertEqual(G.node[6][ConstructionOrdering.kAttrNameNodeAfterLength], 2)
        self.assertEqual(G.node[7][ConstructionOrdering.kAttrNameNodeAfterLength], 1)
        routes = ConstructionOrdering.getCriticalWays(G)
        self.assertEqual(routes, [[0, 4, 5, 6, 7, 3]])

    def test_two_critical_routes(self):
        G = nx.DiGraph()
        G.add_nodes_from(range(9))
        G.add_edges_from([(0, 1), (0, 4), (1, 2), (2, 3), (4, 5), (5, 2), (5, 6), (6, 7), (6, 8), (7, 3), (8, 3)])
        ConstructionOrdering.markLevels(G)
        self.assertEqual(G.node[0][ConstructionOrdering.kAttrNameNodeLevel], 0)
        self.assertEqual(G.node[1][ConstructionOrdering.kAttrNameNodeLevel], 1)
        self.assertEqual(G.node[2][ConstructionOrdering.kAttrNameNodeLevel], 3)
        self.assertEqual(G.node[3][ConstructionOrdering.kAttrNameNodeLevel], 5)
        self.assertEqual(G.node[4][ConstructionOrdering.kAttrNameNodeLevel], 1)
        self.assertEqual(G.node[5][ConstructionOrdering.kAttrNameNodeLevel], 2)
        self.assertEqual(G.node[6][ConstructionOrdering.kAttrNameNodeLevel], 3)
        self.assertEqual(G.node[7][ConstructionOrdering.kAttrNameNodeLevel], 4)
        self.assertEqual(G.node[8][ConstructionOrdering.kAttrNameNodeLevel], 4)

        self.assertEqual(G.node[0][ConstructionOrdering.kAttrNameNodeAfterLength], 5)
        self.assertEqual(G.node[1][ConstructionOrdering.kAttrNameNodeAfterLength], 2)
        self.assertEqual(G.node[2][ConstructionOrdering.kAttrNameNodeAfterLength], 1)
        self.assertEqual(G.node[3][ConstructionOrdering.kAttrNameNodeAfterLength], 0)
        self.assertEqual(G.node[4][ConstructionOrdering.kAttrNameNodeAfterLength], 4)
        self.assertEqual(G.node[5][ConstructionOrdering.kAttrNameNodeAfterLength], 3)
        self.assertEqual(G.node[6][ConstructionOrdering.kAttrNameNodeAfterLength], 2)
        self.assertEqual(G.node[7][ConstructionOrdering.kAttrNameNodeAfterLength], 1)
        self.assertEqual(G.node[8][ConstructionOrdering.kAttrNameNodeAfterLength], 1)
        routes = ConstructionOrdering.getCriticalWays(G)
        self.assertEqual(routes, [[0, 4, 5, 6, 8, 3], [0, 4, 5, 6, 7, 3]])

    def test_dependent_sets(self):
        G = nx.DiGraph()
        G.add_nodes_from(range(9))
        G.add_edges_from([(0, 1), (0, 4), (1, 2), (2, 3), (4, 5), (5, 2), (5, 6), (6, 7), (6, 8), (7, 3), (8, 3)])
        ConstructionOrdering.markChildrenCount(G)
        self.assertEqual(G.node[0][ConstructionOrdering.kAttrNameNodeNumOfChildren], 2)
        self.assertEqual(G.node[1][ConstructionOrdering.kAttrNameNodeNumOfChildren], 1)
        self.assertEqual(G.node[2][ConstructionOrdering.kAttrNameNodeNumOfChildren], 1)
        self.assertEqual(G.node[3][ConstructionOrdering.kAttrNameNodeNumOfChildren], 0)
        self.assertEqual(G.node[4][ConstructionOrdering.kAttrNameNodeNumOfChildren], 1)
        self.assertEqual(G.node[5][ConstructionOrdering.kAttrNameNodeNumOfChildren], 2)
        self.assertEqual(G.node[6][ConstructionOrdering.kAttrNameNodeNumOfChildren], 2)
        self.assertEqual(G.node[7][ConstructionOrdering.kAttrNameNodeNumOfChildren], 1)
        self.assertEqual(G.node[8][ConstructionOrdering.kAttrNameNodeNumOfChildren], 1)

        ConstructionOrdering.markDependentCount(G)
        self.assertEqual(G.node[0][ConstructionOrdering.kAttrNameNodeDependentSetSize], 8)
        self.assertEqual(G.node[1][ConstructionOrdering.kAttrNameNodeDependentSetSize], 2)
        self.assertEqual(G.node[2][ConstructionOrdering.kAttrNameNodeDependentSetSize], 1)
        self.assertEqual(G.node[3][ConstructionOrdering.kAttrNameNodeDependentSetSize], 0)
        self.assertEqual(G.node[4][ConstructionOrdering.kAttrNameNodeDependentSetSize], 6)
        self.assertEqual(G.node[5][ConstructionOrdering.kAttrNameNodeDependentSetSize], 5)
        self.assertEqual(G.node[6][ConstructionOrdering.kAttrNameNodeDependentSetSize], 3)
        self.assertEqual(G.node[7][ConstructionOrdering.kAttrNameNodeDependentSetSize], 1)
        self.assertEqual(G.node[8][ConstructionOrdering.kAttrNameNodeDependentSetSize], 1)

    def test_priorities(self):
        G = nx.DiGraph()
        G.add_nodes_from(range(12))
        G.add_edges_from([(0, 1), (0, 4), (1, 2), (2, 3), (4, 5), (5, 2), (5, 6), (6, 7), (6, 8), (7, 3), (8, 3), (9, 4), (3, 10)])
        ConstructionOrdering.setOrderPriorities(G)
        self.assertAlmostEqual(G.node[0][ConstructionOrdering.kAttrNameNodePriority], 1.0)
        self.assertAlmostEqual(G.node[1][ConstructionOrdering.kAttrNameNodePriority], 0.3)
        self.assertAlmostEqual(G.node[2][ConstructionOrdering.kAttrNameNodePriority], 0.135)
        self.assertAlmostEqual(G.node[3][ConstructionOrdering.kAttrNameNodePriority], 0.03333333333333333)
        self.assertAlmostEqual(G.node[4][ConstructionOrdering.kAttrNameNodePriority], 0.6666666666666667)
        self.assertAlmostEqual(G.node[5][ConstructionOrdering.kAttrNameNodePriority], 0.4666666666666666)
        self.assertAlmostEqual(G.node[6][ConstructionOrdering.kAttrNameNodePriority], 0.25)
        self.assertAlmostEqual(G.node[7][ConstructionOrdering.kAttrNameNodePriority], 0.09999999999999999)
        self.assertAlmostEqual(G.node[8][ConstructionOrdering.kAttrNameNodePriority], 0.09999999999999999)
        self.assertAlmostEqual(G.node[9][ConstructionOrdering.kAttrNameNodePriority], 0.9)
        self.assertAlmostEqual(G.node[10][ConstructionOrdering.kAttrNameNodePriority], 0.008333333333333333)
        self.assertAlmostEqual(G.node[11][ConstructionOrdering.kAttrNameNodePriority], 0.09)

    def test_construction_order(self):
        G = nx.DiGraph()
        G.add_nodes_from(range(12))
        G.add_edges_from([(0, 1), (0, 4), (1, 2), (2, 3), (4, 5), (5, 2), (5, 6), (6, 7), (6, 8), (7, 3), (8, 3), (9, 4), (3, 10)])
        order = ConstructionOrdering.getConstructionOrder(G, [])
        self.assertEqual(order, [0, 9, 4, 5, 1, 6, 2, 8, 7, 11, 3, 10])

    def test_relative_nodes(self):
        G = nx.DiGraph()
        G.add_nodes_from(range(12))
        G.add_edges_from([(0, 3), (0, 4), (1, 4), (1, 5), (2, 6), (2, 7), (3, 8), (4, 9), (5, 10), (6, 10), (7, 11)])
        relative1 = ConstructionOrdering.getRelativeNodes(G, 3)
        relative2 = ConstructionOrdering.getRelativeNodes(G, 4)
        self.assertTrue(len(relative1) == 4 and 0 in relative1 and 4 in relative1 and 8 in relative1 and 9 in relative1)
        self.assertTrue(len(relative2) == 7 and 0 in relative2 and 1 in relative2 and 3 in relative2 and 5 in relative2 and 8 in relative2 and 9 in relative2 and 10 in relative2)

if __name__ == "__main__":
    unittest.main()
