Pregunta

Tengo un programa que genera gráficos utilizando diferentes modelos de niveles múltiples. Cada modelo de niveles múltiples se compone de una generación de un gráfico de semilla más pequeña (por ejemplo, 50 nodos) que puede ser creado a partir de varios modelos (por ejemplo - para cada borde posible, elija incluirlo con probabilidad p).

Después de la generación del gráfico de la semilla, el gráfico se expande en una más grande (digamos 1000 nodos), usando uno de otro conjunto de modelos.

En cada una de las dos etapas, cada modelo requiere un número diferente de parámetros.

Me gustaría ser tener program_options analizar los diferentes parámetros posibles, de acuerdo con los nombres de los modelos.

Por ejemplo, decir que tengo dos modelos gráficos de semillas: SA, que tiene 1 parámetros, y SB, que tiene dos. También para la parte de expansión, tengo dos modelos: A y B, de nuevo con 1 y 2 parámetros, respectivamente. Me gustaría ser capaz de hacer algo como:

./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

y tener los parámetros analizados correctamente. ¿Es eso posible?

¿Fue útil?

Solución

Mediante el uso de un encargo validador y impulso :: program_options: : valor de la modalidad Multi :: , se puede lograr el resultado deseado:

#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 función validate probablemente necesita más rigor, pero se entiende la idea.

Esto compila y funciona para mí.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top