1

I'm getting started using YAML, and the yaml-cpp library to intepret my file. I extended the "monsters" example with some information from my own project. The code and yaml file are below, but here's my question first:

Is it necessary to place all the data that I'll be getting out of the project into one massive structure? In the monsters example, reading the values in from the document doc[i] was easy because it was a list of monsters. In my example, I'll have some lists, but also scalars, etc. The only way that I found to do this, is to make a list that technically only has one entry (i.e., there's a single '-' at the top of the file, and everything is indented into a block). I think the answer is to take some of the content of the 'problemformulation' version of the overloaded >> operator, but I couldn't get it to work properly without having that content inside that function. Any help or advice is appreciated.

ea_test.cpp:

#include <fstream>
#include <iostream>
#include <string>
#include <vector>

#include "yaml-cpp/yaml.h"

struct Vec2 {
  double x, y;
};

struct DecVar {
  std::string name;
  std::string tag;
  Vec2 range;
  std::string description;
};

struct ProblemFormulation {
  std::vector<DecVar> decvars;
  int numrealizations;
};

void operator>>(const YAML::Node& node, Vec2& v) {
  node[0] >> v.x;
  node[1] >> v.y;
}

void operator>>(const YAML::Node& node, DecVar& decvar) {
  node["name"] >> decvar.name;
  node["tag"] >> decvar.tag;
  node["range"] >> decvar.range;
  node["description"] >> decvar.description;
}

void operator>>(const YAML::Node& node,
                ProblemFormulation& problemformulation) {
  node["realizations"] >> problemformulation.numrealizations;
  std::cout << " read realizations!" << std::endl;
  const YAML::Node& decvarNode = node["decisions"];
  for (unsigned int i = 0; i < decvarNode.size(); i++) {
    DecVar decvar;
    decvarNode[i] >> decvar;
    problemformulation.decvars.push_back(decvar);
  }
}

int main() {
  std::ifstream fin("./ea.yaml");
  YAML::Parser parser(fin);
  YAML::Node doc;
  parser.GetNextDocument(doc);
  std::cout << "entering loop" << std::endl;

  ProblemFormulation problemformulation;

  for (unsigned int i = 0; i < doc.size(); i++) {
    doc[i] >> problemformulation;
  }
  return 0;
}

And, ea.yaml:

- realizations: 10
  decisions:
    - name: reservoir
      tag: res_tag
      range:
        - 0
        - 1
      description: |
        This is a description.
    - name: flow
      tag: flow_tag
      range:
        - 0
        - 2
      description: |
        This is how much flow is in the system.

Thanks in advance for your help and tips!

Edit: I will probably only be running one yaml document, and there's only one problemformulation object that will ever be created. My code adapts what you'd do for a list, but only does it once. I would like to know the proper way to, "just do it once", since I think that would be cleaner and make a better looking YAML file (without all the things indented one block for no reason).

1 Answer 1

1

When you write

for (unsigned int i = 0; i < doc.size(); i++)
{
    doc[i] >> problemformulation;
}

this loops through all entries in the [assumed-to-be-sequence] document and reads each one. If your top-level node isn't a sequence node, but instead a "problem formulation", then just write

doc >> problemformulation;
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the help. I will probably have more questions but will write them as full, separate posts later.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.