bool AffinityTask::staticStrongAnalysis(const TaskSet& taskSet, Time overhead)
{
	AffinityTask::Compare compare;
	std::unordered_map<AffinityTask*, Time> responseTime;
	Affinity allCPU;
	for(AffinityTask* task : taskSet)
	{
		responseTime.insert(std::pair<AffinityTask*, Time>(task, task->worstExecution));
		for(auto cpu : task->affinity)
			allCPU.insert(cpu);
	}

	while(true)
	{
		bool changed = false;
		bool overflow = false;
		std::unordered_map<AffinityTask*, Time> newResponseTime;

		for(auto current : responseTime)
		{
			AffinityTask* curTask = current.first;
			std::set<Affinity> powerSet = AffinityTask::powerSet(curTask->affinity);
			Time currentResponse = responseTime.find(curTask)->second;
			TaskSet ignoreTask;
			ignoreTask.insert(curTask);

			Time min_sumInterfere = std::numeric_limits<Time>::max();
			for(Affinity s : powerSet)
			{
				assert(s.size() != 0);
				Size s_Size = s.size();
				//Time sumInterference = 0;
				std::unordered_map<CPUID, std::list<TaskSet>> possibleReplacement;
				for(auto cpu : s)
				{
					possibleReplacement.insert(std::pair<CPUID, std::list<TaskSet>>
							(cpu, std::list<TaskSet>()));
				}

				for(CPUID selectedCPU : s)
				{
					Affinity ignoreCPU(s);
					ignoreCPU.erase(selectedCPU);
					for(auto alternative : allCPU)
					{
						if(ignoreCPU.find(alternative) != ignoreCPU.end())
							continue;
						auto allPaths = allPath(taskSet, selectedCPU, alternative, ignoreCPU, ignoreTask);
						for(auto path : allPaths)
						{
							if(path.size() > 0)
							{
								TaskSet ignoredTask;
								Affinity moreCheck;
								for(auto item : path)
								{
									if(item.isTask())
										ignoredTask.insert(item.getTask());
									else
										moreCheck.insert(item.getCPUID());
								}
								TaskSet highTaskSet;
								for(AffinityTask* highPriorityTask : taskSet)
								{
									//if(compare(curTask, highPriorityTask))
									//	continue;
									if(highPriorityTask == curTask)
										continue;
									if(ignoredTask.find(highPriorityTask) != ignoredTask.end())
										continue;

									bool intersect = false;
									for(auto cpu : highPriorityTask->affinity)
									{
										if(moreCheck.find(cpu) != moreCheck.end())
										{
											intersect = true;
											break;
										}
									}
									if(!intersect)
										continue;

									highTaskSet.insert(highPriorityTask);
								}
								possibleReplacement.find(selectedCPU)->second.push_back(highTaskSet);
							}
						}
					}
				}


				for(auto possibleSet : combinePossibleTaskSet(possibleReplacement))
				{
					Time sumInterference = 0;
					/*
					if(possibleSet.size() ==0)
						continue;

					assert(possibleSet.size() > 0);
					*/
					sumInterference += overhead;
					for(auto highPriorityTask : possibleSet)
					{

						Time interferenceCount = currentResponse/highPriorityTask->minPeriod;
						Time remaining = currentResponse % highPriorityTask->minPeriod;
						Time interference = interferenceCount * highPriorityTask->worstExecution
								+ std::min(remaining, highPriorityTask->worstExecution);

						Time contextSwitchCount = interferenceCount;
						if(remaining > 0)
							contextSwitchCount++;

						sumInterference += 2*(contextSwitchCount) * overhead;

						if(compare(curTask, highPriorityTask))
							continue;

						sumInterference += interference;
					}


					Time floorValue = floor((Real)sumInterference / (Real)s_Size);

					min_sumInterfere = std::min(min_sumInterfere, floorValue);
				}
			}
			assert(min_sumInterfere != std::numeric_limits<Time>::max());

			Time nextResponse = curTask->worstExecution + min_sumInterfere;
			newResponseTime.insert(std::pair<AffinityTask*, Time>(curTask, nextResponse));
			if(currentResponse != nextResponse)
				changed = true;
			if(currentResponse > curTask->minPeriod)
				overflow = true;
		}

		if(changed)
			responseTime = newResponseTime;
		else
			break;
		if(overflow)
			break;
	}

	bool possible = true;
	for(auto iter : responseTime)
	{
		if(iter.second > iter.first->minPeriod)
		{
			possible = false;
			iter.first->print_log(WARN, "Execution time: %lu, Period: %lu, Response time: %lu",
					iter.first->worstExecution, iter.first->minPeriod, iter.second);
		}
		else
		{
			iter.first->print_log(INFO, "Execution time: %lu, Period: %lu, Response time: %lu",
					iter.first->worstExecution, iter.first->minPeriod, iter.second);
		}
	}

	return possible;
}
void TrueTimeSourceVisitor::Visit_Node( const Semantics::Node & node ) {

	// Setup the node name
	std::string kernelName = node.name();
	std::string kernelInitName = kernelName + "_init";
	DEBUGOUT( "\tNode: " << kernelName << std::endl );

	// Must be the second pass
		_SchedHeaderLines.push_back( string( "// Define Schedule Offsets and Durations" ) );
		_SchedHeaderLines.push_back( string( "" ) );
	
		// Create the file name
		std::string filename = std::string( node.name() ) + "_init";

		// Create the hyperperiod symbol string for the node
		std::string hyp_str = kernelName + "_HYPERPERIOD";

		// Set some dictionary items for this node
		GetMainDictionary().SetValue( "FILENAME", filename );
		GetMainDictionary().SetValue( "KERNEL_SCHEDULE", "prioFP" );
		GetMainDictionary().SetFormattedValue( "KERNEL_HYPERPERIOD", "%f", (double) node.hyperperiodsecs() );
		GetMainDictionary().SetValue( "NODE_HYPERPERIOD_STR", hyp_str );

		DeviceSet devices = node.integrates();

		for ( DeviceSet::iterator devIter = devices.begin(); devIter != devices.end(); devIter++ )
		{
			if ( (*devIter).type() == Semantics::CommInterface::meta )
			{
				Semantics::CommInterface ci = Semantics::CommInterface::Cast( *devIter );
				Semantics::CommMedium cm = ci.commMedium();

				if ( cm != Udm::null ) {
					string busname = cm.name();
					AddSectionDictionary( "BUS_DEFINES" );
					GetTemplateDictionary().SetValue( "BUSNAME", busname );
					PopSectionDictionary();
				}
			}
		}
			

		if ( _SchedHeaderLines.size() < 4 )
		{
			ostringstream out;
			out << "#define " << hyp_str << " " << (double)node.hyperperiodsecs();
			_SchedHeaderLines.push_back( out.str() );
		}

		_already_included.clear();  // clear include list for each node

		// Visit all tasks assigned to this node
		TaskSet taskSet = node.executes();
		TaskVector taskVector( taskSet.begin(), taskSet.end() );
		TaskVector::iterator taskIter = taskVector.begin();
		for ( ; taskIter != taskVector.end(); taskIter++ ){
			// Visit the task
			taskIter->Accept( *this );
		}

		// Clear the analog in/out counters
		_analogIn = 1;
		_analogOut = 1;

		// Set up a sorted list of IChans and OChans
		SortedIChan_ByChanIndex_Set ichans;
		SortedOChan_ByChanIndex_Set ochans;

		// Visit all devices contained in this node
		DeviceSet deviceSet = node.integrates();
		DeviceSet::iterator deviceIter = deviceSet.begin();
		for ( ; deviceIter != deviceSet.end(); deviceIter++ ) {

			// Collect all of the IChans and OChans, and keep them in the proper sorted order
			// See if device is input
			if ( Semantics::InputDevice::meta == (*deviceIter).type() ) {

				// Cast to an InputDevice
				Semantics::InputDevice input = Semantics::InputDevice::Cast( *deviceIter );

				// Get the associated IChans
				SortedIChan_ByChanIndex_Set iChanSet = input.inputChannels_sorted( IChanIndexSorter() );
				ichans.insert( iChanSet.begin(), iChanSet.end() );
			}

			// See if device is output
			else if ( Semantics::OutputDevice::meta == (*deviceIter).type() ) {

				// Cast to an InputDevice
				Semantics::OutputDevice output = Semantics::OutputDevice::Cast( *deviceIter );

				// Get the associated OChans
				SortedOChan_ByChanIndex_Set oChanSet = output.outputChannels_sorted( OChanIndexSorter() );
				ochans.insert( oChanSet.begin(), oChanSet.end() );
			}
		}

		// Now process the IChans and OChans in order
		IChanVector iChanVector( ichans.begin(), ichans.end() );
		for ( IChanVector::iterator ichanIter = iChanVector.begin(); ichanIter != iChanVector.end(); ichanIter++ )
		{
			ichanIter->Accept( *this );
		}

		OChanVector oChanVector( ochans.begin(), ochans.end() );
		for ( OChanVector::iterator ochanIter = oChanVector.begin(); ochanIter != oChanVector.end(); ochanIter++ )
		{
			ochanIter->Accept( *this );
		}

		// Visit all local dependencies on this node
		LocalDependencySet dependencySet = node.nodeLocalDeps();
		LocalDependencyVector dependencyVector( dependencySet.begin(), dependencySet.end() );
		LocalDependencyVector::iterator dependencyIter = dependencyVector.begin();
		for ( ; dependencyIter != dependencyVector.end(); dependencyIter++ ) {

			// Visit the dependency
			dependencyIter->Accept( *this );
		}

		// Visit the dummy dependency message on this node (if we have one)
		Semantics::Msg dummyMsg = node.nodeDummyMsg();
		if ( dummyMsg != Udm::null )
			Visit_DummyMessage( dummyMsg );


		// Get the template file name
		std::string templateName = ConfigKeeper::inst().GetTemplatePath() + "\\truetime_src.tpl";
		// Initialize the template 
		ctemplate::Template* googleTemplate = ctemplate::Template::GetTemplate( templateName, ctemplate::DO_NOT_STRIP );
		std::string output;
		// Expand the output into a string
		googleTemplate->Expand( &output, &GetMainDictionary() );
		
		// Create the _init file for this TT kernel
		std::string directoryName = ConfigKeeper::inst().GetDirectoryName();
		string srcfilename = directoryName + "\\" + filename + ".cpp";
		ofstream initFile( srcfilename.c_str() );
		// Write the generated code out to the file and close
		initFile << output;
		// Close up the file
		initFile.close();
		// Clear out the dictionary
		ClearDictionary();

		// Write out the header file for the defines
		string hdrfilename = directoryName + "\\" + filename + "_defines.h";
		cout << "Writing header: " << hdrfilename << endl;
		ofstream headerFile( hdrfilename.c_str() );

		for ( std::vector< std::string >::iterator lineIter = _SchedHeaderLines.begin(); 
				lineIter != _SchedHeaderLines.end(); lineIter++ )
		{
			headerFile << *lineIter << endl;
		}
		headerFile.close();
		_SchedHeaderLines.clear(); // flush the list
}
std::list<GraphNode> AffinityTask::BFS(const TaskSet& taskSet, const GraphNode& start, const GraphNode& target, const Affinity& excludeID, const TaskSet& excludeTask)
{
	std::list<GraphNode> returnList;

	//prepare link map
	std::unordered_map<CPUID, TaskSet> cpuToTaskList;
	std::unordered_map<AffinityTask*, Affinity> taskToCPUList;
	for(auto task : taskSet)
	{
		if(excludeTask.find(task) != excludeTask.end())
			continue;
		Affinity affinityCopy(task->affinity);
		for(auto cpu : excludeID)
			affinityCopy.erase(cpu);
		taskToCPUList.insert(std::pair<AffinityTask*, Affinity>(task, affinityCopy));
		for(CPUID cpu : affinityCopy)
		{
			if(cpuToTaskList.find(cpu) == cpuToTaskList.end())
				cpuToTaskList.insert(std::pair<CPUID, TaskSet>(cpu, TaskSet()));

			cpuToTaskList.find(cpu)->second.insert(task);
		}
	}

	//procedure BFS(G,v) is
	std::unordered_map<CPUID, AffinityTask*> cpuToPrevTask;
	std::unordered_map<AffinityTask*, CPUID> taskToPrevCPU;
	bool reachable = false;

	std::queue<GraphNode> queue;//create a queue Q, true is Job, false is processor
	std::unordered_set<CPUID> visitedCPU; //create a set V
	std::unordered_set<AffinityTask*> visitedTask; //create a set V

	if(start.isTask())
		visitedTask.insert(start.getTask()); //add v to V
	else
		visitedCPU.insert(start.getCPUID());
	queue.push(start); //enqueue v onto Q

	while(!queue.empty())//while Q is not empty loop
	{
		auto currentItem = queue.front(); //t ← Q.dequeue()
		queue.pop();

		if(currentItem.isTask())
		{
			if(target.isTask())
				if(target.getTask() == currentItem.getTask()) //if t is what we are looking for then
				{
					//return t
					reachable = true;
					break;
				}
		}
		else
		{
			if(!target.isTask())
				if(target.getCPUID() == currentItem.getCPUID()) //if t is what we are looking for then
				{
					//return t
					reachable = true;
					break;
				}
		}

		//for all edges e in G.adjacentEdges(t) loop
		if(currentItem.isTask())
		{
			AffinityTask* curTask = currentItem.getTask();
			assert(curTask != nullptr);

			for(CPUID adjacentCPU : taskToCPUList.find(curTask)->second) //u ← G.adjacentVertex(t,e)
			{
				if(visitedCPU.find(adjacentCPU) == visitedCPU.end()) //if u is not in V then
				{
					visitedCPU.insert(adjacentCPU); //add u to V
					queue.push(GraphNode(adjacentCPU)); //enqueue u onto Q

					assert(cpuToPrevTask.find(adjacentCPU) == cpuToPrevTask.end());
					cpuToPrevTask.insert(std::pair<CPUID,AffinityTask*>(adjacentCPU, curTask));
				}
			}
		}
		else
		{
			CPUID curCPU = currentItem.getCPUID();
			auto iter = cpuToTaskList.find(curCPU);
			if(iter == cpuToTaskList.end())
			{
				continue;
			}
			assert(iter->second.size() > 0);
			for(AffinityTask* adjacentTask : iter->second) //u ← G.adjacentVertex(t,e)
			{
				if(visitedTask.find(adjacentTask) == visitedTask.end())
				{
					visitedTask.insert(adjacentTask);
					queue.push(GraphNode(adjacentTask));

					assert(taskToPrevCPU.find(adjacentTask) == taskToPrevCPU.end());
					taskToPrevCPU.insert(std::pair<AffinityTask*,CPUID>(adjacentTask, curCPU));
				}
			}
		}
	}

	if(reachable)
	{
		GraphNode current = target;
		while(true)
		{
			returnList.push_front(current);
			if(current.isTask())
			{
				auto cpu_iter = taskToPrevCPU.find(current.getTask());
				if(cpu_iter == taskToPrevCPU.end())
				{
					assert(start.isTask());
					assert(current.getTask() == start.getTask());
					break;
				}
				current = cpu_iter->second;
			}
			else
			{
				auto task_iter = cpuToPrevTask.find(current.getCPUID());
				if(task_iter == cpuToPrevTask.end())
				{
					assert(!start.isTask());
					assert(current.getCPUID() == start.getCPUID());
					break;
				}
				current = task_iter->second;
			}
		}
	}

	return returnList;
}