2010-05-29 15 views
16

Ho un programma che genera grafici utilizzando diversi modelli multilivello. Ogni modello multi-livello consiste in una generazione di un grafico seme più piccolo (ad esempio, 50 nodi) che può essere creato da diversi modelli (ad esempio - per ogni bordo possibile, scegliere di includerlo con probabilità p).Gestire le opzioni complesse con le opzioni_opzioni di Boost

Dopo la generazione del grafico seed, il grafico viene espanso in uno più grande (ad esempio 1000 nodi), utilizzando uno di un altro set di modelli.

In ciascuna delle due fasi, ciascun modello richiede un numero diverso di parametri.

Mi piacerebbe essere avere program_options analizzare i diversi parametri possibili, in base ai nomi dei modelli.

Ad esempio, supponiamo di disporre di due modelli di grafici seed: SA, che ha 1 parametro e SB, che ne ha due. Anche per la parte di espansione, ho due modelli: A e B, sempre con 1 e 2 parametri, rispettivamente. Vorrei poter fare qualcosa del tipo:

./graph_generator --seed=SA 0.1 --expansion=A 0.2 
./graph_generator --seed=SB 0.1 3 --expansion=A 0.2 
./graph_generator --seed=SA 0.1 --expansion=B 10 20 
./graph_generator --seed=SB 0.1 3 --expansion=B 10 20 

e avere i parametri analizzati correttamente. È possibile?

risposta

23

Utilizzando un custom validator e boost::program_options::value::multitoken, è possibile ottenere il risultato desiderato:

#include <iostream> 
#include <boost/lexical_cast.hpp> 
#include <boost/optional.hpp> 
#include <boost/program_options.hpp> 

// Holds parameters for seed/expansion model 
struct Model 
{ 
    std::string type; 
    boost::optional<float> param1; 
    boost::optional<float> param2; 
}; 

// Called by program_options to parse a set of Model arguments 
void validate(boost::any& v, const std::vector<std::string>& values, 
       Model*, int) 
{ 
    Model model; 
    // Extract tokens from values string vector and populate Model struct. 
    if (values.size() == 0) 
    { 
     throw boost::program_options::validation_error(
      "Invalid model specification"); 
    } 
    model.type = values.at(0); // Should validate for A/B 
    if (values.size() >= 2) 
     model.param1 = boost::lexical_cast<float>(values.at(1)); 
    if (values.size() >= 3) 
     model.param2 = boost::lexical_cast<float>(values.at(2)); 

    v = model; 
} 

int main(int argc, char* argv[]) 
{ 
    Model seedModel, expansionModel; 

    namespace po = boost::program_options; 
    po::options_description options("Generic options"); 
    options.add_options() 
     ("seed", 
      po::value<Model>(&seedModel)->multitoken(), 
      "seed graph model") 
     ("expansion", 
      po::value<Model>(&expansionModel)->multitoken(), 
      "expansion model") 
     ; 

    po::variables_map vm; 
    po::store(po::parse_command_line(argc, argv, options), vm); 
    po::notify(vm); 

    std::cout << "Seed type: " << seedModel.type << "\n"; 
    if (seedModel.param1) 
     std::cout << "Seed param1: " << *(seedModel.param1) << "\n"; 
    if (seedModel.param2) 
     std::cout << "Seed param2: " << *(seedModel.param2) << "\n"; 

    std::cout << "Expansion type: " << expansionModel.type << "\n"; 
    if (expansionModel.param1) 
     std::cout << "Expansion param1: " << *(expansionModel.param1) << "\n"; 
    if (expansionModel.param2) 
     std::cout << "Expansion param2: " << *(expansionModel.param2) << "\n"; 

    return 0; 
} 

La funzione validate probabilmente ha bisogno di più rigore, ma si ottiene l'idea.

Questo compila e funziona per me.

Problemi correlati