Exemplo n.º 1
0
   Example(IloEnv env)
      : nblocks(0), model(env), vars(env), ranges(env)
   {
      // Model data.
      // fixed[] is the fixed cost for opening a facility,
      // cost[i,j] is the cost for serving customer i from facility j.
      static double const fixed[] = { 2.0, 3.0, 3.0 };
      static double const cost[] = { 2.0, 3.0, 4.0, 5.0, 7.0,
                                     4.0, 3.0, 1.0, 2.0, 6.0,
                                     5.0, 4.0, 2.0, 1.0, 3.0 };
#define NFACTORY ((CPXDIM)(sizeof(fixed) / sizeof(fixed[0])))
#define NCUSTOMER ((CPXDIM)((sizeof(cost) / sizeof(cost[0])) / NFACTORY))
      nblocks = NCUSTOMER;

      IloExpr obj(env);
      // Create integer y  variables.
      IloNumVarArray y(env);
      for (IloInt f = 0; f < NFACTORY; ++f) {
         std::stringstream s;
         s << "y" << f;
         IloIntVar v(env, 0, 1, s.str().c_str());
         obj += fixed[f] * v;
         objMap[v] = fixed[f];
         y.add(v);
         blockMap.insert(BlockMap::value_type(v, -1));
         intersectMap.insert(IntersectMap::value_type(v, RowSet()));
      }

      // Create continuous x variables.
      IloNumVarArray x(env);
      for (IloInt f = 0; f < NFACTORY; ++f) {
         for (IloInt c = 0; c < NCUSTOMER; ++c) {
            std::stringstream s;
            s << "x" << f << "#" << c;
            IloNumVar v(env, 0.0, IloInfinity, s.str().c_str());
            obj += v * cost[f * NCUSTOMER + c];
            objMap[v] = cost[f * NCUSTOMER + c];
            x.add(v);
            blockMap.insert(BlockMap::value_type(v, c));
            intersectMap.insert(IntersectMap::value_type(v, RowSet()));
         }
      }
      vars.add(y);
      vars.add(x);
      model.add(vars);

      // Add objective function.
      model.add(IloMinimize(env, obj, "obj"));
      objSense = IloObjective::Minimize;
      obj.end();

      // Satisfy each customer's demand.
      for (IloInt c = 0; c < NCUSTOMER; ++c) {
         std::stringstream s;
         s << "c1_" << c;
         IloRange r(env, 1.0, IloInfinity, s.str().c_str());
         IloExpr lhs(env);
         for (IloInt f = 0; f < NFACTORY; ++f) {
            lhs += x[f * NCUSTOMER + c];
            intersectMap[x[f * NCUSTOMER + c]].insert(r);
         }
         r.setExpr(lhs);
         ranges.add(r);
         lhs.end();
      }

      // A factory must be open if we service from it.
      for (IloInt c = 0; c < NCUSTOMER; ++c) {
         for (IloInt f = 0; f < NFACTORY; ++f) {
            std::stringstream s;
            s << "c2_" << c << "#" << f;
            IloRange r(env, 0.0, IloInfinity, s.str().c_str());
            intersectMap[x[f * NCUSTOMER + c]].insert(r);
            intersectMap[y[f]].insert(r);
            r.setExpr(-x[f * NCUSTOMER + c] + y[f]);
            ranges.add(r);
         }
      }

      // Capacity constraint.
      IloRange r(env, -IloInfinity, NFACTORY - 1, "c3");
      IloExpr lhs(env);
      for (IloInt f = 0; f < NFACTORY; ++f) {
         lhs += y[f];
         intersectMap[y[f]].insert(r);
      }
      r.setExpr(lhs);
      ranges.add(r);
      lhs.end();

      model.add(ranges);

#undef NFACTORY
#undef NCUSTOMER
   }
bool SimplifyControlFlowGraphPass::_mergeExitBlocks(ir::IRKernel& k)
{
	typedef std::unordered_map<ir::ControlFlowGraph::iterator,
		ir::ControlFlowGraph::instruction_iterator> BlockMap;
	
	report(" Merging exit blocks...");
	
	BlockMap exitBlocks;
	
	// Find all blocks with exit instructions
	for(ir::ControlFlowGraph::iterator block = k.cfg()->begin();
		block != k.cfg()->end(); ++block)
	{
		for(ir::ControlFlowGraph::instruction_iterator
			instruction = block->instructions.begin();
			instruction != block->instructions.end(); ++instruction)
		{
			ir::PTXInstruction& ptx =
				static_cast<ir::PTXInstruction&>(**instruction);
			
			if(ptx.isExit() && ptx.opcode != ir::PTXInstruction::Trap)
			{
				// There should be an edge to the exit block
				assertM(block->find_out_edge(k.cfg()->get_exit_block()) !=
					block->out_edges.end(), "No edge from " << block->label()
					<< " to exit node.");
			
				exitBlocks.insert(std::make_pair(block, instruction));
				break;
			}
		}
	}
	
	// If there is only one/zero blocks, then don't change anything
	if(exitBlocks.size() < 2)
	{
		if(exitBlocks.size() == 1)
		{
			ir::PTXInstruction& ptx =
				static_cast<ir::PTXInstruction&>(**exitBlocks.begin()->second);
			
			if(k.function())
			{
				ptx.opcode = ir::PTXInstruction::Ret;
			}
			else
			{
				ptx.opcode = ir::PTXInstruction::Exit;
			}
		}
		
		return false;
	}
	// Otherwise...
	
	// 1) create a new exit block
	ir::ControlFlowGraph::iterator newExit = k.cfg()->insert_block(
		ir::BasicBlock(k.cfg()->newId()));
	
	ir::BasicBlock::EdgePointerVector deletedEdges =
		k.cfg()->get_exit_block()->in_edges;
	
	// 1a) Create edges targetting the new block
	for(ir::ControlFlowGraph::edge_pointer_iterator edge = deletedEdges.begin();
		edge != deletedEdges.end(); ++edge)
	{
		k.cfg()->insert_edge(ir::Edge((*edge)->head, newExit, (*edge)->type));
		k.cfg()->remove_edge(*edge);
	}
	
	k.cfg()->insert_edge(ir::Edge(newExit, k.cfg()->get_exit_block(),
		ir::Edge::FallThrough));
	
	// 2) Delete the instructions from their blocks
	for(BlockMap::iterator block = exitBlocks.begin();
		block != exitBlocks.end(); ++block)
	{
		report("  merging block " << block->first->label());
		
		// 2a) Insert a branch from blocks with branch edges
		ir::ControlFlowGraph::edge_pointer_iterator edge =
			newExit->find_in_edge(block->first);
		
		if((*edge)->type == ir::Edge::Branch)
		{
			ir::PTXInstruction* newBranch = new ir::PTXInstruction(
				ir::PTXInstruction::Bra, ir::PTXOperand(newExit->label()));
				
			newBranch->uni = true;
		
			block->first->instructions.push_back(newBranch);
		}
		
		delete *block->second;
		block->first->instructions.erase(block->second);
	}
	
	// 3 Add an appropriate exit instruction to the new exit block
	if(k.function())
	{
		newExit->instructions.push_back(
			new ir::PTXInstruction(ir::PTXInstruction::Ret));
	}
	else
	{
		newExit->instructions.push_back(
			new ir::PTXInstruction(ir::PTXInstruction::Exit));
	}
	
	return true;
}