#! /usr/bin/env python

#
# STEP 1: IMPORT LIBs
#
# This part should be the same for every complexity evaluation script
# except "../../src" should point to directory of decisiondiagram.py 
#
import sys
sys.path.append("../../src")
import decisiondiagram
import functools

#
# STEP 2 (OPTIONAL): SOME SHORTCUTS
#
ite       = decisiondiagram.ite
evaluate  = decisiondiagram.evaluate
combine   = decisiondiagram.combine
reorder   = decisiondiagram.reorder
merge     = decisiondiagram.merge
produceDD = decisiondiagram.produceDD

#
# STEP 3: IMPORT THE TARGET MODEl
#
model_name = "models/power_control"
model = __import__( model_name )

#
# STEP 4: PRODUCE THE DECISION DIAGRAM OF FUNCTIONS BY BRUTE-FORCE SEARCH
#

# decision diagrams of functions for power source allocations
left_df  = produceDD({0:2, 1:2, 2:2, 3:2, 4:2, 5:2, 6:2, 7:2, 8:2, 9:2}, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], model.left_df)
right_df = produceDD({0:2, 1:2, 2:2, 3:2, 4:2, 5:2, 6:2, 7:2, 8:2, 10:2}, [0, 1, 2, 3, 4, 5, 6, 7, 8, 10], model.right_df)

# decision diagrams of FSM functions producing the intermediate states for power control
left_fsm_df  = produceDD({11:4, 12:4, 9:2, 13:2}, [11, 12, 9, 13], model.left_fsm_df)
right_fsm_df = produceDD({14:4, 15:4, 10:2, 16:2}, [14, 15, 10, 16], model.right_fsm_df)

# decision diagrams of functions producing the control signals for engines, APU, and switches 1-6
control_functions = []
for i in range(9):
	fun = functools.partial(model.control_df, output_bit=i)
	control_df = produceDD({18:4, 19:4, 13:2, 16:2}, [18, 19, 13, 16], fun)
	control_functions.append(control_df)

#
# STEP 5 (OPTIONAL): REORDER VARIABLES
#
left_df  = reorder(left_df, [9, 0, 1, 2, 3, 4, 5, 6, 7, 8])
right_df = reorder(right_df, [10, 0, 1, 2, 3, 4, 5, 6, 7, 8])

#
# STEP 6: COMPOSE DECISION DIAGRAMS
#
stage1_power_allocations = merge([left_df, right_df])
stage2_power_switchings  = merge([left_fsm_df, right_fsm_df])
stage3_control_signals   = merge(control_functions)
complexity               = merge([stage1_power_allocations, stage2_power_switchings, stage3_control_signals])

#
# STEP 7: OUTPUT COMPLEXITY
#
print "Complexity of the functional models: "
print "Complexity of left power source allocations:       ", left_df.countPath()
print "Complexity of right power source allocations:      ", right_df.countPath()
print "Complexity of left power switchings:               ", left_fsm_df.countPath()
print "Complexity of right power switchings:              ", right_fsm_df.countPath()
print "Complexity of the system:                          ", complexity.countPath()
print "Complexity of the 3-stage partitions and mappings: "
print "Complexity of stage 1 (power source allocations):  ", stage1_power_allocations.countPath()
print "Complexity of stage 2 (power switchings):          ", stage2_power_switchings.countPath()
print "Complexity of stage 3 (control signals producing): ", stage3_control_signals.countPath()

#
# STEP 8 (OPTIONAL): VISUALIZE THE RESULTING DECISION DIAGRAMS
#
complexity.visualize("complexity")

print "Done."


