import unittest
import networkx
from grafon.measures import FixedGraphEditDistanceMeasure

class FixedGraphEditDistanceMeasureTest(unittest.TestCase):

  def test_init(self):
    """!
    Test whether init parameters are read correctly in the constructor.

    The options parameter should be a dictionary with four keys:
    'match_cost', 'substitute_cost', 'delete_cost', 'insert_cost'. The values
    may be float, int, str or unicode. However, they must be converted to float.
    If any of the keys is missing, then default values should be set.
    """
    # The correct case
    fged_options = {
      'match_cost': 0.5,
      'substitute_cost': 1.0,
      'delete_cost': 3.0,
      'insert_cost': 2.0
    }
    fged = FixedGraphEditDistanceMeasure(fged_options)
    self.assertEqual(fged.match_cost, 0.5)
    self.assertEqual(fged.substitute_cost, 1.0)
    self.assertEqual(fged.delete_cost, 3.0)
    self.assertEqual(fged.insert_cost, 2.0)

    # Mixed values in the options dictionary
    fged_options = {
      'match_cost': '0.5',
      'substitute_cost': u'1',
      'delete_cost': 3.0,
      'insert_cost': 2
    }
    fged = FixedGraphEditDistanceMeasure(fged_options)
    self.assertEqual(fged.match_cost, 0.5)
    self.assertEqual(fged.substitute_cost, 1.0)
    self.assertEqual(fged.delete_cost, 3.0)
    self.assertEqual(fged.insert_cost, 2.0)

    # Missing values
    fged_options = {}
    fged = FixedGraphEditDistanceMeasure(fged_options)
    self.assertEqual(fged.match_cost, 0)
    self.assertEqual(fged.substitute_cost, 1.0)
    self.assertEqual(fged.delete_cost, 2.5)
    self.assertEqual(fged.insert_cost, 2.0)

  def test_calculate(self):
    """Test the calculate method.

    The test calculate the similarity between 4 pairs of graphs:
    1) [4, 5, 6, 8, 10] -> [4, 5, 6, 8, 10] = 1
    2) [4, 5, 6, 8, 10] -> [4, 5, 10, 8, 6] = 1
    3) [4, 5, 6, 8, 10] -> [1, 2, 3] = 0
    4) [4, 5, 6, 8, 10] -> [4, 8, 6, 1] = 1 - 8/23.
    """
    fged_options = {
      'match_cost': 0.0,
      'substitute_cost': 1.0,
      'delete_cost': 3.0,
      'insert_cost': 2.0
    }
    fged = FixedGraphEditDistanceMeasure(fged_options)

    source = networkx.graph.Graph()
    source.add_nodes_from([4, 5, 6, 8, 10])

    target1 = networkx.graph.Graph()
    target1.add_nodes_from([4, 5, 6, 8, 10])
    target2 = networkx.graph.Graph()
    target2.add_nodes_from([4, 5, 10, 8, 6])
    target3 = networkx.graph.Graph()
    target3.add_nodes_from([1, 2, 3])
    target4 = networkx.graph.Graph()
    target4.add_nodes_from([4, 8, 6, 1])

    self.assertEqual(fged.calculate(source, target1), 1)
    self.assertEqual(fged.calculate(source, target2), 1)
    self.assertEqual(fged.calculate(source, target3), 0)
    self.assertEqual(fged.calculate(source, target4), (1 - 8/23.))


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