Explore possible futures (cpp)

Commit and checkout

Move through the alternatives

Create a main file and paste the following inside it:

#include <iostream>

#include <ros/ros.h>

#include "ontologenius/OntologiesManipulator.h"

int main(int argc, char** argv)
{
ros::init(argc, argv, "explore_futures");

onto::OntologiesManipulator onto;
onto.waitInit();

onto.add("bob");
onto["bob"]->close();

onto.copy("cpy", "bob");

onto["cpy"]->feeder.waitConnected();

onto["cpy"]->feeder.addConcept("bob");
onto["cpy"]->feeder.addInheritage("bob", "human");
std::string first_commit = onto["cpy"]->feeder.commit();

onto["cpy"]->feeder.addRelation("bob", "eat", "pasta");
onto["cpy"]->feeder.addRelation("pasta", "isIn", "bob");
onto["cpy"]->feeder.commit("after_pasta");

onto["cpy"]->feeder.checkout(first_commit);

onto["cpy"]->feeder.addRelation("bob", "eat", "burger");
onto["cpy"]->feeder.addRelation("burger", "isIn", "bob");
onto["cpy"]->feeder.commit("after_burger");

onto["cpy"]->feeder.checkout("after_pasta");
onto["cpy"]->feeder.addRelation("bob", "isHungry", "bool", "true");
std::string hungry_commit = onto["cpy"]->feeder.commit();

onto["cpy"]->feeder.checkout("after_pasta");
onto["cpy"]->feeder.addRelation("bob", "isHungry", "bool", "false");
onto["cpy"]->feeder.commit();

onto["cpy"]->feeder.checkout(hungry_commit);
std::vector<std::string> hungry_state = onto["cpy"]->individuals.getOn("bob", "isHungry");
std::cout << "-> test hungry on cpy" << std::endl;
for(auto& state : hungry_state)
std::cout << "bob isHungry " << state << std::endl;

hungry_state = onto["bob"]->individuals.getOn("bob", "isHungry");
std::cout << "-> test hungry on bob" << std::endl;
for(auto& state : hungry_state)
std::cout << "bob isHungry " << state << std::endl;

onto.del("cpy");

return 0;
}

Now, let's break the code down.

#include "ontologenius/OntologiesManipulator.h"

Since we need to manipulate multiple instances, we have to include the OntologiesManipulator header.

onto.add("bob");
onto["bob"]->close();

Once we have an OntologiesManipulator object, we can use it to create an instance for our bob agent. This instance is the one that represents his knowledge base at present.

onto.copy("cpy", "bob");

To create the instance that represents the possible futures, we use the copy function of the OntologiesManipulator object. This function creates a deep copy of an existing instance which becomes independent.

std::string first_commit = onto["cpy"]->feeder.commit();

After making changes in our new instance, we can now commit these changes with the commit function. It then returns the identifier of the commit that we must keep so that we can return to it later.

onto["cpy"]->feeder.commit("after_pasta");

The commit function can also be used with a personalized commit identifier. The advantage is that you no longer need to store it or that you can use an identifier already existing in your program.

onto["cpy"]->feeder.checkout(first_commit);

If we now want to return to the state of our first commit, nothing more simple, just do a checkout with the identifier of the first commit. After this line, it's as if Bob hadn't eaten the pasta.

In the following lines of the program, we simply go from one commit to another by making some modifications.

onto["cpy"]->feeder.commit();

onto["cpy"]->feeder.checkout(hungry_commit);

In the lines above, we execute a commit in a state where bob is not hungry. We then checkout the commit where he is hungry.

std::vector<std::string> hungry_state = onto["cpy"]->individuals.getOn("bob", "isHungry");
std::cout << "-> test hungry on cpy" << std::endl;
for(auto& state : hungry_state)
std::cout << "bob isHungry " << state << std::endl;

hungry_state = onto["bob"]->individuals.getOn("bob", "isHungry");
std::cout << "-> test hungry on bob" << std::endl;
for(auto& state : hungry_state)
std::cout << "bob isHungry " << state << std::endl;

With these displays, we should see the fact that bob is hungry regarding the copied instance since we checked this state.

Regarding the bob instance, we should have no results for the getOn request since the copied instance is independent of the original instance.

onto.del("cpy");

We can finally delete our copied instance because we no longer need it. By doing so, even if we had set an internal file to Ontologenius, this instance will not be saved.

Compile this, start the program and verify if you have the expected results.