text:
/* Copyright (C) 2010-2019, The Regents of The University of Michigan.
 All rights reserved.

 This software was developed as part of the The Vulcan project in the Intelligent Robotics Lab
 under the direction of Benjamin Kuipers, kuipers@umich.edu. Use of this code is governed by an
 MIT-style License that can be found at "https://github.com/h2ssh/Vulcan".
*/

/**
 * \file     loops_and_trees.cpp
 * \author   Collin Johnson
 *
 * Definition of label_loops_and_trees function.
 */

#include "hssh/local_topological/area_detection/labeling/loops_and_trees.h"
#include "hssh/local_topological/area_detection/labeling/area_graph.h"
#include <boost/graph/breadth_first_search.hpp>
#include <boost/graph/exterior_property.hpp>
#include <boost/graph/johnson_all_pairs_shortest.hpp>
#include <boost/graph/visitors.hpp>
#include <boost/range/iterator_range.hpp>
#include <cassert>
#include <iostream>
#include <stack>

#define DEBUG_LOOPS
// #define DEBUG_CONNECTED

namespace vulcan
{
namespace hssh
{

using namespace boost;

using Vertex = graph_traits<LoopGraph>::vertex_descriptor;
using Edge = graph_traits<LoopGraph>::edge_descriptor;

// Define property map for storing the distances between nodes
using DistProperty = exterior_vertex_property<LoopGraph, double>;
using DistVec = DistProperty::container_type;
using DistMatrix = DistProperty::matrix_type;
using DistMap = DistProperty::matrix_map_type;

/*
 * LoopLabellingVisitor is a DFSVisitor for BGL.
 */
struct LoopLabellingVisitor : public default_bfs_visitor
{
    LoopLabellingVisitor(std::vector<Vertex>& pred, std::vector<Vertex>& source, std::vector<Vertex>& target)
    : predecessors(pred)
    , sourcePath(source)
    , targetPath(target)
    {
    }

    // DFSVisitor concept interface
    void initialize_vertex(Vertex v, const LoopGraph& graph);
    void tree_edge(Edge e, const LoopGraph& graph);
    void non_tree_edge(Edge e, const LoopGraph& graph);

    std::vector<Vertex>& predecessors;
    std::vector<Vertex>& sourcePath;
    std::vector<Vertex>& targetPath;
};

void construct_loop_graph(AreaGraph& areaGraph, LoopGraph& loopGraph)
{
    std::unordered_map<AreaNode*, Vertex> nodeToVertex;

    std::for_each(areaGraph.beginNodes(), areaGraph.endNodes(), [&](const auto& node) {
        auto v = add_vertex(loopGraph);
        nodeToVertex[node.get()] = v;
        loopGraph[v].node = node.get();
    });

    std::vector<std::pair<AreaNode*, AreaNode*>> addedEdges;

    std::for_each(areaGraph.beginEdges(), areaGraph.endEdges(), [&](const auto& edge) {
        auto endpoints = edge->getEndpoints();

        for (auto& added : addedEdges) {
            // Ignore previously added edges
            if ((added.first == endpoints[0].get()) && (added.second == endpoints[1].get())) {
                return;
            }
        }

        auto e = add_edge(nodeToVertex[endpoints[0].get()], nodeToVertex[endpoints[1].get()], loopGraph);
        loopGraph[e.first].length = edge->getLength();
        addedEdges.emplace_back(endpoints[0].get(), endpoints[1].get());
        addedEdges.emplace_back(endpoints[1].get(), endpoints[0].get());
    });
}

void label_loops_and_trees(AreaGraph& graph)
{
    LoopGraph loopGraph;
    construct_loop_graph(graph, loopGraph);
    label_loops_and_trees(loopGraph);
}

void label_loops_and_trees(LoopGraph& graph)
{
    std::vector<Vertex> predecessors(num_vertices(graph), num_vertices(graph));
    // storage for extracting the loops
    std::vector<Vertex> sourcePath;
    std::vector<Vertex> targetPath;
    LoopLabellingVisitor vis(predecessors, sourcePath, targetPath);
    predecessors[0] = 0;   // point root to itself

    breadth_first_search(graph, vertex(0, graph), visitor(vis));
    //     undirected_dfs(graph, visitor(vis).edge_color_map(get(&LoopGraphEdge::color, graph)));
}

void compute_node_distances(AreaGraph& graph, const LoopGraph& loopGraph)
{
    DistMatrix distances(graph.sizeNodes());
    DistMap distMap(distances, loopGraph);
    johnson_all_pairs_shortest_paths(loopGraph, distMap, weight_map(get(&LoopGraphEdge::length, loopGraph)));

    for (std::size_t n = 0, end = graph.sizeNodes(); n < end; ++n) {
        AreaNode* startNode = loopGraph[n].node;

        for (std::size_t m = n + 1; m < end; ++m) {
            AreaNode* endNode = loopGraph[m].node;
            graph.setNodeDistance(startNode, endNode, distances[n][m]);
        }
    }
}

void LoopLabellingVisitor::initialize_vertex(Vertex v, const LoopGraph& graph)
{
    // For each vertex, ensure it doesn't have any loops specified
    graph[v].node->setLoop(false);
}

void LoopLabellingVisitor::tree_edge(Edge e, const LoopGraph& graph)
{
    predecessors[target(e, graph)] = source(e, graph);
}

void LoopLabellingVisitor::non_tree_edge(Edge e, const LoopGraph& graph)
{
    // A back edge was found to the target of the edge
    // Go through the predecessors until target the is found.
    // Each node along the way back should be marked as part of a Loop

    auto targetVertex = target(e, graph);

    // Ignore this case. It arises from the BFS just looking at all outedges in the undirected graph, so it
    // sees back to the parent in the search tree when expanded.
    if (predecessors[source(e, graph)] == targetVertex) {
        return;
    }

    auto prevVertex = predecessors[targetVertex];
    auto vertex = targetVertex;

    // Extract the source and target paths
    targetPath.clear();
    while (prevVertex != vertex) {
        targetPath.push_back(vertex);
        prevVertex = vertex;
        vertex = predecessors[vertex];
    }

    vertex = source(e, graph);
    prevVertex = predecessors[vertex];
    sourcePath.clear();
    while (prevVertex != vertex) {
        sourcePath.push_back(vertex);
        prevVertex = vertex;
        vertex = predecessors[vertex];
    }

    // Find the first shared vertex between the two
    auto targetIt = std::find_first_of(targetPath.begin(), targetPath.end(), sourcePath.begin(), sourcePath.end());
    assert(targetIt != targetPath.end());
    auto sourceIt = std::find(sourcePath.begin(), sourcePath.end(), *targetIt);
    assert(sourceIt != sourcePath.end());

    // Turn begin, targetIt into a valid half-open range for a for-loop
    std::size_t targetEnd = std::distance(targetPath.begin(), targetIt) + 1;
    std::size_t sourceEnd = std::distance(sourcePath.begin(), sourceIt) + 1;

    double loopDist = 0.0;
    for (std::size_t n = 1; n < targetEnd; ++n) {
        loopDist += graph[edge(targetPath[n - 1], targetPath[n], graph).first].length;
    }

    for (std::size_t n = 1; n < sourceEnd; ++n) {
        loopDist += graph[edge(sourcePath[n - 1], sourcePath[n], graph).first].length;
    }

#ifdef DEBUG_LOOPS
    std::cout << "DEBUG:label_loops_and_trees: Found a loop with distance " << loopDist << " : \n";
#endif

    for (std::size_t n = 0; n < targetEnd; ++n) {
        graph[targetPath[n]].node->setLoop(true);
        graph[targetPath[n]].node->setLoopDistance(loopDist);

#ifdef DEBUG_LOOPS
        std::cout << graph[targetPath[n]].node->getPosition() << '\n';
#endif   // DEBUG_LOOPS
    }

    for (std::size_t n = 0; n < sourceEnd; ++n) {
        graph[sourcePath[n]].node->setLoop(true);
        graph[sourcePath[n]].node->setLoopDistance(loopDist);

#ifdef DEBUG_LOOPS
        std::cout << graph[sourcePath[n]].node->getPosition() << '\n';
#endif   // DEBUG_LOOPS
    }
}

}   // namespace hssh
}   // namespace vulcan

max_stars_repo_name: anuranbaka/Vulcan

max_issues_repo_name: anuranbaka/Vulcan

max_forks_repo_name: anuranbaka/Vulcan


text:
/*
 * Software License Agreement (BSD License)
 *
 *  Xin Wang
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of the copyright holder(s) nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * Author : Xin Wang
 * Email  : ericrussell@zju.edu.cn
 *
 */

#include <fstream>
#include <string>
#include <sstream>
#include <pcl/common/centroid.h>
#include <pcl/point_types.h>
#include <Eigen/src/Core/Matrix.h>
#include "openClustersWorker.h"
#include "globaldef.h"
#include "dataLibrary.h"

using namespace std;

bool openClustersWorker::is_para_satisfying(QString &message)
{
	this->setParaSize(1);
	if(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters.size()>=this->getParaSize())
	{
		this->setFileName(QString::fromUtf8(dataLibrary::Workflow[dataLibrary::current_workline_index].parameters[0].c_str()));
		this->setParaIndex(this->getParaSize());
		return true;
	}
	else
	{
		message = QString("openclusters: Location of Clusters (bin) File Not Provided.");
		return false;
	}
}
void openClustersWorker::prepare()
{
	this->setUnmute();
	this->setWriteLog();
	this->check_mute_nolog();
}

void openClustersWorker::doWork()
{
	bool is_success(false);

    QByteArray ba = this->getFileName().toLocal8Bit();
	string* strfilename = new std::string(ba.data());

    dataLibrary::Status = STATUS_OPENCLUSTERS;

    this->timer_start();

	//begin of processing
    stringstream ss;

    ifstream fbinaryin(strfilename->c_str(), ios::in|ios::binary);
    if(fbinaryin.is_open())
    {
        if(!dataLibrary::cluster_patches.empty())
            dataLibrary::cluster_patches.clear();
        if(!dataLibrary::dips.empty())
            dataLibrary::dips.clear();
        if(!dataLibrary::dip_directions.empty())
            dataLibrary::dip_directions.clear();
        if(!dataLibrary::areas.empty())
            dataLibrary::areas.clear();
        if(!dataLibrary::patchIDs.empty())
            dataLibrary::patchIDs.clear();
        if(!dataLibrary::selectedPatches.empty())
            dataLibrary::selectedPatches.clear();

        int num_of_clusters, num_of_points;
        float x, y, z, rgb, dip, dip_direction, area;
        fbinaryin.read(reinterpret_cast<char*>(&num_of_clusters), sizeof(num_of_clusters));
        Eigen::Vector4f centroid;
        float centor_x = 0.0;
		float centor_y = 0.0;
		float centor_z = 0.0;
        for(int i=0; i<num_of_clusters; i++)
        {
            pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_patch (new pcl::PointCloud<pcl::PointXYZRGB>);
            fbinaryin.read(reinterpret_cast<char*>(&num_of_points), sizeof(num_of_points));
            fbinaryin.read(reinterpret_cast<char*>(&rgb), sizeof(rgb));
            for(int j=0; j<num_of_points; j++)
            {
                fbinaryin.read(reinterpret_cast<char*>(&x), sizeof(x));
                fbinaryin.read(reinterpret_cast<char*>(&y), sizeof(y));
                fbinaryin.read(reinterpret_cast<char*>(&z), sizeof(z));
                pcl::PointXYZRGB point;
                point.x = x;
                point.y = y;
                point.z = z;
                point.rgb = rgb;
                cloud_patch->push_back(point);
            }
            fbinaryin.read(reinterpret_cast<char*>(&dip), sizeof(dip));
            fbinaryin.read(reinterpret_cast<char*>(&dip_direction), sizeof(dip_direction));
            fbinaryin.read(reinterpret_cast<char*>(&area), sizeof(area));
            dataLibrary::cluster_patches.push_back(cloud_patch);
            dataLibrary::dips.push_back(dip);
            dataLibrary::dip_directions.push_back(dip_direction);
            dataLibrary::areas.push_back(area);

            ss << i;
            string patchID = *strfilename += ss.str();
            dataLibrary::patchIDs.push_back(patchID);
            pcl::compute3DCentroid(*cloud_patch, centroid);
            centor_x += centroid[0];
            centor_y += centroid[1];
            centor_z += centroid[2];
        }
        centor_x /= num_of_clusters;
        centor_y /= num_of_clusters;
        centor_z /= num_of_clusters;
        dataLibrary::cloud_centor.x=centor_x;
        dataLibrary::cloud_centor.y=centor_y;
        dataLibrary::cloud_centor.z=centor_z;
        fbinaryin.close();
        if(!this->getMuteMode())
        {
            emit show();
        }
        is_success = true;
    }
    else
    {
        emit showErrors("openclusters: Can Not Open the File!");
    }
	//end of processing

    this->timer_stop();

    if(this->getWriteLogMode()&&is_success)
    {
		std::string string_filename = this->getFileName().toUtf8().constData();
        std::string log_text = string_filename + "\n\tReading Clusters costs: ";
        std::ostringstream strs;
        strs << this->getTimer_sec();
        log_text += (strs.str() +" seconds.");
        dataLibrary::write_text_to_log_file(log_text);
    }

	dataLibrary::Status = STATUS_READY;
    emit showReadyStatus();
	delete strfilename;
	if(this->getWorkFlowMode()&&is_success)
	{
		this->Sleep(1000);
		emit GoWorkFlow();
	}
}

ext: cpp

max_stars_repo_name: EricAlex/structrock


text:
/**
 * @file symplectictimestepping.cc
 * @brief NPDE homework SymplecticTimestepping
 * @copyright Developed at ETH Zurich
 */

#include <Eigen/Dense>
#include <cmath>
#include <iostream>

constexpr double PI = 3.14159265358979323846;

namespace SymplecticTimestepping {

/* SAM_LISTING_BEGIN_0 */
void sympTimestep(double tau, Eigen::Vector2d &pq_j) {
  // Coefficients of the method
  const Eigen::Vector3d a{2. / 3., -2. / 3., 1.};
  const Eigen::Vector3d b{7. / 24., 3. / 4., -1. / 24.};
  // Single step
  //====================
  // Your code goes here
  //====================
}
/* SAM_LISTING_END_0 */

/* SAM_LISTING_BEGIN_1 */
void sympTimesteppingODETest() {
  int nIter = 7;   // total number of iterations
  unsigned int m;  // number of equidistant steps
  Eigen::Vector2d approx_sol;

  // Initial conditions
  Eigen::Vector2d init_cond;
  init_cond << 0.0, 1.0;  // initial conditions

  // Evaluating the error at the final step between the approx solutions as
  // given by the symplectic method and the exact solution computed from
  // the anlytic formula.
  double errors[nIter];  // errors vector for all approx. sols
  double tau;
  for (int k = 0; k < nIter; k++) {
    m = 10 * std::pow(2, k);
    //====================
    // Your code goes here
    //====================
  }
  // Printing results
  std::cout << "Convergence of Symplectic Time Stepping Method:\n";
  std::cout << "\tM\t\terr(M)\n";
  for (int k = 0; k < nIter; k++) {
    std::cout << "\t" << 10 * std::pow(2, k) << "\t\t" << errors[k]
              << std::endl;
  }
}
/* SAM_LISTING_END_1 */

/* SAM_LISTING_BEGIN_3 */
Eigen::MatrixXd simulateHamiltonianDynamics(const Eigen::VectorXd &p0,
                                            const Eigen::VectorXd &q0, double T,
                                            unsigned int M) {
  int n = p0.size();
  Eigen::MatrixXd PQ(2 * n, M + 1);

  // Coefficients of the method
  Eigen::VectorXd a(3);
  a << 2. / 3., -2. / 3., 1.;
  Eigen::VectorXd b(3);
  b << 7. / 24., 3. / 4., -1. / 24.;

  double tau = T / M;
  Eigen::VectorXd pj(p0), qj(q0);
  PQ.col(0) << pj, qj;
  //====================
  // Your code goes here
  //====================
  return PQ;
}
/* SAM_LISTING_END_3 */

}  // namespace SymplecticTimestepping

ext: cc


text:
#include "cmd_options.h"

#include "test_detail.h"

#include <boost/test/unit_test.hpp>

/**
  constraints test
 */

BOOST_AUTO_TEST_SUITE( constraints_test_suite )

namespace co = cmd_options;

typedef std::basic_string<detail::check_char_t> string_type;
typedef co::basic_option_pack<detail::check_char_t> option_pack_type;
typedef co::basic_option_description<detail::check_char_t>
  option_description_type;
typedef co::basic_options_group<detail::check_char_t> options_group_type;
typedef co::basic_variable_map<detail::check_char_t> variable_map_type;
typedef detail::std_stream_select<detail::check_char_t> stream_select;

/**
  ignore flagged options
 */
BOOST_AUTO_TEST_CASE( option_ignore_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--foo"),
    _LIT("--bar"),
    _LIT("--baz"),
    _LIT("arg"),
    _LIT("--buz"),
    _LIT("--foobar"),
  };

  options = options_group_type{
    co::make_option(_LIT("foo"),_LIT("ignored"),
      co::basic_constraint<detail::check_char_t>().ignore()),
    co::make_option(_LIT("bar"),_LIT("case 2")),
    co::make_option(_LIT("baz"),
      co::basic_value<string_type,detail::check_char_t>(),
      _LIT("ignored"),
      co::basic_constraint<detail::check_char_t>().ignore()),
    co::make_option(_LIT("buz"),_LIT("case 2")),
    co::make_option(_LIT("foobar"),_LIT("ignored"),
      co::basic_constraint<detail::check_char_t>().ignore()),
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("bar"),{}},
      {_LIT("buz"),{}}
    }));
}

/**
  ignore flagged operands
 */
BOOST_AUTO_TEST_CASE( operand_ignore_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("foo"),
    _LIT("bar"),
    _LIT("baz"),
    _LIT("buz"),
    _LIT("foobar"),
  };

  options = options_group_type{
    co::make_operand(_LIT("foo"),
      co::basic_constraint<detail::check_char_t>().at_position(0).ignore()),
    co::make_operand(_LIT("bar"),
      co::basic_constraint<detail::check_char_t>().at_position(1)),
    co::make_operand(_LIT("baz"),
      co::basic_constraint<detail::check_char_t>().at_position(2).ignore()),
    co::make_operand(_LIT("buz"),
      co::basic_constraint<detail::check_char_t>().at_position(3)),
    co::make_operand(_LIT("foobar"),
      co::basic_constraint<detail::check_char_t>().at_position(4).ignore()),
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

//    stream_select::cerr << detail::to_string(vm,co::basic_value<string_type,detail::check_char_t>());

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("bar"),{}},
      {_LIT("buz"),{}}
    }));
}

/**
  option no restriction given 0
 */
BOOST_AUTO_TEST_CASE( option_no_restrictions_given_0_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--bar"),
  };

  options = options_group_type{
    co::make_option(_LIT("foo,f"),_LIT("case 2")),
    co::make_option(_LIT("bar,b"),_LIT("case 2"))
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("bar"),{}}
    }));
}

/**
  option no restriction given 1
 */
BOOST_AUTO_TEST_CASE( option_no_restrictions_given_1_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--foo"),
  };

  options = options_group_type{
    co::make_option(_LIT("foo,f"),_LIT("case 2"))
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("foo"),{}}
    }));
}

/**
  option strict 0 given 0
 */
BOOST_AUTO_TEST_CASE( option_degenerate_occurrences_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--bar"),
  };

  options = options_group_type{
    co::make_option(_LIT("foo,f"),
      _LIT("case 2"),
      co::basic_constraint<detail::check_char_t>().occurrences(0)),
    co::make_option(_LIT("bar,b"),_LIT("case 2"))
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("bar"),{}}
    }));
}

/**
  option strict 0 given 1
 */
BOOST_AUTO_TEST_CASE( option_strict_0_given_1_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--foo"),
  };

  options = options_group_type{
    co::make_option(_LIT("foo,f"),_LIT("case 2"),
      co::basic_constraint<detail::check_char_t>().occurrences(0)),
  };

  BOOST_CHECK_EXCEPTION(
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options),
    co::occurrence_error, [](const co::occurrence_error &ex) {
      return (ex.mapped_key() == co::detail::asUTF8(string_type(_LIT("foo")))
        && ex.min() == 0 && ex.max() == 0 && ex.occurrences() == 1);
    }
  );
}

/**
  option Strictly 1 option given 0
 */
BOOST_AUTO_TEST_CASE( option_strict_1_given_0_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
  };

  options = options_group_type{
    co::make_option(_LIT("foo,f"),_LIT("case 2"),
      co::basic_constraint<detail::check_char_t>().occurrences(1))
  };

  BOOST_CHECK_EXCEPTION(
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options),
    co::occurrence_error, [](const co::occurrence_error &ex) {
      return (ex.mapped_key() == co::detail::asUTF8(string_type(_LIT("foo")))
        && ex.min() == 1 && ex.max() == 1 && ex.occurrences() == 0);
    }
  );
}

/**
  option Strictly 1 option given 1
 */
BOOST_AUTO_TEST_CASE( option_strict_1_given_1_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--foo"),
  };

  options = options_group_type{
    co::make_option(_LIT("foo,f"),_LIT("case 2"),
      co::basic_constraint<detail::check_char_t>().occurrences(1))
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("foo"),{}}
    }));
}

/**
  option Strictly 1 option given 2
 */
BOOST_AUTO_TEST_CASE( option_strict_1_given_2_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--foo"),
    _LIT("-f")
  };

  options = options_group_type{
    co::make_option(_LIT("foo,f"),_LIT("case 2"),
      co::basic_constraint<detail::check_char_t>().occurrences(1))
  };

  BOOST_CHECK_EXCEPTION(
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options),
    co::occurrence_error, [](const co::occurrence_error &ex) {
      return (ex.mapped_key() == co::detail::asUTF8(string_type(_LIT("foo")))
        && ex.min() == 1 && ex.max() == 1 && ex.occurrences() == 2);
    }
  );
}

/**
  operand no restriction given 0
 */
BOOST_AUTO_TEST_CASE( operand_no_restrictions_given_0_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--foo"),
  };

  options = options_group_type{
    co::make_option(_LIT("foo,f"),_LIT("case 2")),
    co::make_operand(_LIT("case 14"),
      co::basic_value<string_type,detail::check_char_t>())
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("foo"),{}}
    }));
}

/**
  operand no restriction given 1
 */
BOOST_AUTO_TEST_CASE( operand_no_restrictions_given_1_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--bar"),
  };

  options = options_group_type{
    co::make_operand(_LIT("operand_key"),
      co::basic_value<string_type,detail::check_char_t>())
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("operand_key"),{string_type(_LIT("--bar"))}}
    }));
}

/**
  operand strict 0 given 0
 */
BOOST_AUTO_TEST_CASE( operand_strict_0_given_0_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--bar"),
  };

  options = options_group_type{
    co::make_operand(_LIT("case 14"),
      co::basic_value<string_type,detail::check_char_t>(),
      co::basic_constraint<detail::check_char_t>().occurrences(0)),
    co::make_option(_LIT("bar,b"),_LIT("case 2"))
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("bar"),{}}
    }));
}

/**
  operand strict 0 given 1
 */
BOOST_AUTO_TEST_CASE( operand_strict_0_given_1_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--bar"),
  };

  options = options_group_type{
    co::make_operand(_LIT("operand_key"),
      co::basic_value<string_type,detail::check_char_t>(),
      co::basic_constraint<detail::check_char_t>().occurrences(0))
  };

  BOOST_CHECK_EXCEPTION(
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options),
    co::occurrence_error, [](const co::occurrence_error &ex) {
      return (ex.mapped_key() == co::detail::asUTF8(_LIT("operand_key"))
        && ex.min() == 0 && ex.max() == 0 && ex.occurrences() == 1);
    }
  );
}

/**
  operand strict 1 given 0
 */
BOOST_AUTO_TEST_CASE( operand_strict_1_given_0_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
  };

  options = options_group_type{
    co::make_operand(_LIT("operand_key"),
      co::basic_value<string_type,detail::check_char_t>(),
      co::basic_constraint<detail::check_char_t>().occurrences(1))
  };

  BOOST_CHECK_EXCEPTION(
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options),
    co::occurrence_error, [](const co::occurrence_error &ex) {
      return (ex.mapped_key() == co::detail::asUTF8(_LIT("operand_key"))
        && ex.min() == 1 && ex.max() == 1 && ex.occurrences() == 0);
    }
  );
}

/**
  operand strict 1 given 1
 */
BOOST_AUTO_TEST_CASE( operand_strict_1_given_1_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--bar"),
  };

  options = options_group_type{
    co::make_operand(_LIT("operand_key"),
      co::basic_value<string_type,detail::check_char_t>(),
      co::basic_constraint<detail::check_char_t>().occurrences(1))
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("operand_key"),{string_type(_LIT("--bar"))}}
    }));
}

/**
  operand strict 1 given 2
 */
BOOST_AUTO_TEST_CASE( operand_strict_1_given_2_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--foo"),
    _LIT("-f")
  };

  options = options_group_type{
    co::make_operand(_LIT("operand_key"),
      co::basic_value<string_type,detail::check_char_t>(),
      co::basic_constraint<detail::check_char_t>().occurrences(1))
  };

  BOOST_CHECK_EXCEPTION(
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options),
    co::occurrence_error, [](const co::occurrence_error &ex) {
      return (ex.mapped_key() == co::detail::asUTF8(_LIT("operand_key"))
        && ex.min() == 1 && ex.max() == 1 && ex.occurrences() == 2);
    }
  );
}

/**
  operand 0 or 1 given 0
 */
BOOST_AUTO_TEST_CASE( operand_0_1_given_0_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--foo"),
    _LIT("-f")
  };

  options = options_group_type{
    co::make_operand(_LIT("case 14"),
      co::basic_value<string_type,detail::check_char_t>(),
      co::basic_constraint<detail::check_char_t>().occurrences(0,1)),
    co::make_option(_LIT("foo,f"),_LIT("case 2"))
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("foo"),{}},
      {_LIT("foo"),{}}
    }));
}

/**
  operand 0 or 1 given 1
 */
BOOST_AUTO_TEST_CASE( operand_0_1_given_1_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--foo"),
    _LIT("-f"),
    _LIT("bar")
  };

  options = options_group_type{
    co::make_operand(_LIT("operand_key"),
      co::basic_value<string_type,detail::check_char_t>(),
      co::basic_constraint<detail::check_char_t>().occurrences(0,1)),
    co::make_option(_LIT("foo,f"),_LIT("case 2"))
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("operand_key"),{string_type(_LIT("bar"))}},
      {_LIT("foo"),{}},
      {_LIT("foo"),{}}
    }));
}

/**
  operand 0 or 1 given 2
 */
BOOST_AUTO_TEST_CASE( operand_0_1_given_2_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--foo"),
    _LIT("-f"),
    _LIT("bar1"),
    _LIT("bar2")
  };

  options = options_group_type{
    co::make_operand(_LIT("operand_key"),
      co::basic_value<string_type,detail::check_char_t>(),
      co::basic_constraint<detail::check_char_t>().occurrences(0,1)),
    co::make_option(_LIT("foo,f"),_LIT("case 2"))
  };

  BOOST_CHECK_EXCEPTION(
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options),
    co::occurrence_error, [](const co::occurrence_error &ex) {
      return (ex.mapped_key() == co::detail::asUTF8(_LIT("operand_key"))
        && ex.min() == 0 && ex.max() == 1 && ex.occurrences() == 2);
    }
  );
}

/*
  Position and argument checks
*/

/**
  unconstrained operand argument
 */
BOOST_AUTO_TEST_CASE( operand_unconstrained_argument )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("bar1"),
    _LIT("--foo"),
    _LIT("bar2"),
    _LIT("-f"),
    _LIT("bar3")
  };

  options = options_group_type{
    co::make_operand(_LIT("operand_key"),
      co::basic_value<string_type,detail::check_char_t>(),
      co::basic_constraint<detail::check_char_t>().at_argument(-1)),
    co::make_option(_LIT("foo,f"),_LIT("case 2"))
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

//   stream_select::cerr << detail::to_string(vm,co::basic_value<string_type,detail::check_char_t>());

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("operand_key"),{string_type(_LIT("bar1"))}},
      {_LIT("operand_key"),{string_type(_LIT("bar2"))}},
      {_LIT("operand_key"),{string_type(_LIT("bar3"))}},
      {_LIT("foo"),{}},
      {_LIT("foo"),{}}
    }));
}

/**
  operand strictly at argument 0
 */
BOOST_AUTO_TEST_CASE( operand_argument_0_given_0 )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("bar"),
    _LIT("--foo")
  };

  options = options_group_type{
    co::make_operand(_LIT("operand_key"),
      co::basic_value<string_type,detail::check_char_t>(),
      co::basic_constraint<detail::check_char_t>().at_argument(0)),
    co::make_option(_LIT("foo,f"),_LIT("case 2"))
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("operand_key"),{string_type(_LIT("bar"))}},
      {_LIT("foo"),{}}
    }));
}

/**
  operand strictly at argument 0 given 1
 */
BOOST_AUTO_TEST_CASE( operand_argument_0_given_1 )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--foo"),
    _LIT("bar")
  };

  options = options_group_type{
    co::make_operand(_LIT("case 14"),
      co::basic_value<string_type,detail::check_char_t>(),
      co::basic_constraint<detail::check_char_t>().at_argument(0)),
    co::make_option(_LIT("foo,f"),_LIT("case 2"))
  };

  BOOST_CHECK_EXCEPTION(
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options),
    co::unexpected_operand_error, [](const co::unexpected_operand_error &ex) {
      return (ex.position() == 0 && ex.argument() == 1);
    }
  );
}

/**
  unconstrained operand position
 */
BOOST_AUTO_TEST_CASE( operand_unconstrained_position )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("bar1"),
    _LIT("--foo"),
    _LIT("bar2"),
    _LIT("-f"),
    _LIT("bar3")
  };

  options = options_group_type{
    co::make_operand(_LIT("operand_key"),
      co::basic_value<string_type,detail::check_char_t>(),
      co::basic_constraint<detail::check_char_t>().at_position(-1)),
    co::make_option(_LIT("foo,f"),_LIT("case 2"))
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

//   stream_select::cerr << detail::to_string(vm,co::basic_value<string_type,detail::check_char_t>());

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("operand_key"),{string_type(_LIT("bar1"))}},
      {_LIT("operand_key"),{string_type(_LIT("bar2"))}},
      {_LIT("operand_key"),{string_type(_LIT("bar3"))}},
      {_LIT("foo"),{}},
      {_LIT("foo"),{}}
    }));
}

/**
  operand strictly at position 0
 */
BOOST_AUTO_TEST_CASE( operand_position_0_given_0 )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--foo"),
    _LIT("bar")
  };

  options = options_group_type{
    co::make_operand(_LIT("operand_key"),
      co::basic_value<string_type,detail::check_char_t>(),
      co::basic_constraint<detail::check_char_t>().at_position(0)),
    co::make_option(_LIT("foo,f"),_LIT("case 2"))
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("operand_key"),{string_type(_LIT("bar"))}},
      {_LIT("foo"),{}}
    }));
}

/**
  operand strictly at position 0 given 1
 */
BOOST_AUTO_TEST_CASE( operand_position_0_given_1 )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--foo"),
    _LIT("bar0"),
    _LIT("bar1")
  };

  options = options_group_type{
    co::make_operand(_LIT("case 14"),
      co::basic_value<string_type,detail::check_char_t>(),
      co::basic_constraint<detail::check_char_t>().at_position(0)),
    co::make_option(_LIT("foo,f"),_LIT("case 2"))
  };

  BOOST_CHECK_EXCEPTION(
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options),
    co::unexpected_operand_error, [](const co::unexpected_operand_error &ex) {
      return (ex.position() == 1 && ex.argument() == 2);
    }
  );
}

/**
  option (empty) mutual exclusion
*/
BOOST_AUTO_TEST_CASE( option_empty_mutual_exclusion_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--bar")
  };

  options = options_group_type{
    co::make_option(_LIT("bar,b"),_LIT("case 2"),
      co::basic_constraint<detail::check_char_t>().occurrences(0,1)),
    co::make_option(_LIT("foo,f"),_LIT("case 2"),
      co::basic_constraint<detail::check_char_t>().mutually_exclusive(
        {_LIT("bar"),_LIT("baz"),_LIT("foobar")})),
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

//   stream_select::cerr << detail::to_string(vm,co::basic_value<string_type,detail::check_char_t>());

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("bar"),{}}
    }));
}

/**
  option (non) mutual exclusion
*/
BOOST_AUTO_TEST_CASE( option_non_mutual_exclusion_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--foo")
  };

  options = options_group_type{
    co::make_option(_LIT("foo,f"),_LIT("case 2"),
      co::basic_constraint<detail::check_char_t>().mutually_exclusive(
        {_LIT("bar"),_LIT("baz"),_LIT("foobar")})),
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

//   stream_select::cerr << detail::to_string(vm,co::basic_value<string_type,detail::check_char_t>());

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("foo"),{}}
    }));
}

/**
  option mutual exclusion
*/
BOOST_AUTO_TEST_CASE( option_mutual_exclusion_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--foo"),
    _LIT("--bar")
  };

  options = options_group_type{
    co::make_option(_LIT("bar,b"),_LIT("case 2")),
    co::make_option(_LIT("foo,f"),_LIT("case 2"),
      co::basic_constraint<detail::check_char_t>().mutually_exclusive(
        {_LIT("bar")})),
  };

  BOOST_CHECK_EXCEPTION(
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options),
    co::mutually_exclusive_error, [](const co::mutually_exclusive_error &ex) {
      return (ex.mapped_key() == co::detail::asUTF8(string_type(_LIT("foo")))
        && ex.exclusive_mapped_key() ==
          co::detail::asUTF8(string_type(_LIT("bar"))));
    }
  );
}

/**
  option (empty) mutual exclusion any
*/
BOOST_AUTO_TEST_CASE( option_empty_mutual_exclusion_any_test1 )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--bar")
  };

  options = options_group_type{
    co::make_option(_LIT("bar,b"),_LIT("case 2"),
      co::basic_constraint<detail::check_char_t>().occurrences(0,1)),
    co::make_option(_LIT("foo,f"),_LIT("case 2"),
      co::basic_constraint<detail::check_char_t>().mutually_exclusive_any(
        {_LIT("bar"),_LIT("baz"),_LIT("foobar")})),
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

//   stream_select::cerr << detail::to_string(vm,co::basic_value<string_type,detail::check_char_t>());

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("bar"),{}}
    }));
}

/**
  option (empty) mutual exclusion any
*/
BOOST_AUTO_TEST_CASE( option_empty_mutual_exclusion_any_test2 )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--bar")
  };

  options = options_group_type{
    co::make_option(_LIT("bar,b"),_LIT("case 2"),
      co::basic_constraint<detail::check_char_t>().occurrences(0,1)),
    co::make_option(_LIT("foo,f"),_LIT("case 2"),
      co::basic_constraint<detail::check_char_t>().mutually_exclusive_any(
        {_LIT("baz"),_LIT("foobar"),_LIT("bar")})),
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

//   stream_select::cerr << detail::to_string(vm,co::basic_value<string_type,detail::check_char_t>());

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("bar"),{}}
    }));
}

/**
  option (non) mutual exclusion any
*/
BOOST_AUTO_TEST_CASE( option_non_mutual_exclusion_any_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--foo")
  };

  options = options_group_type{
    co::make_option(_LIT("foo,f"),_LIT("case 2"),
      co::basic_constraint<detail::check_char_t>().mutually_exclusive(
        {_LIT("bar"),_LIT("baz"),_LIT("foobar")})),
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

//   stream_select::cerr << detail::to_string(vm,co::basic_value<string_type,detail::check_char_t>());

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("foo"),{}}
    }));
}

/**
  option mutual exclusion any
*/
BOOST_AUTO_TEST_CASE( option_mutual_exclusion_any_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--foo"),
  };

  options = options_group_type{
    co::make_option(_LIT("foo,f"),_LIT("case 2")),
    co::make_option(_LIT("bar,b"),_LIT("case 2"),
      co::basic_constraint<detail::check_char_t>().mutually_exclusive_any(
        {_LIT("baz"),_LIT("foobar")})),
  };

  std::vector<std::string> exclusive_any_keys{
    co::detail::asUTF8(string_type(_LIT("baz"))),
    co::detail::asUTF8(string_type(_LIT("foobar")))};

  BOOST_CHECK_EXCEPTION(
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options),
    co::mutually_exclusive_any_error,
      [&](const co::mutually_exclusive_any_error &ex)
      {
        return (ex.mapped_key() == co::detail::asUTF8(string_type(_LIT("bar")))
          && ex.exclusive_any_keys() == exclusive_any_keys);
      }
  );
}

/**
  option (empty) mutual inclusion
*/
BOOST_AUTO_TEST_CASE( option_empty_mutual_inclusion_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
  };

  options = options_group_type{
    co::make_option(_LIT("foo,f"),_LIT("case 2"),
      co::basic_constraint<detail::check_char_t>().mutually_inclusive(
        {_LIT("bar")})),
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

//   stream_select::cerr << detail::to_string(vm,co::basic_value<string_type,detail::check_char_t>());

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
    }));
}

/**
  option (non) mutual inclusion
*/
BOOST_AUTO_TEST_CASE( option_non_mutual_inclusion_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--foo"),
    _LIT("--bar")
  };

  options = options_group_type{
    co::make_option(_LIT("bar,b"),_LIT("case 2")),
    co::make_option(_LIT("foo,f"),_LIT("case 2"),
      co::basic_constraint<detail::check_char_t>().mutually_inclusive(
        {_LIT("bar")})),
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

//   stream_select::cerr << detail::to_string(vm,co::basic_value<string_type,detail::check_char_t>());

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("bar"),{}},
      {_LIT("foo"),{}}
    }));
}

/**
  option mutual inclusion (actual)
*/
BOOST_AUTO_TEST_CASE( option_mutual_inclusion_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--foo")
  };

  options = options_group_type{
    co::make_option(_LIT("bar,b"),_LIT("case 2")),
    co::make_option(_LIT("foo,f"),_LIT("case 2"),
      co::basic_constraint<detail::check_char_t>().mutually_inclusive(
        {_LIT("bar")})),
  };

  BOOST_CHECK_EXCEPTION(
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options),
    co::mutually_inclusive_error, [](const co::mutually_inclusive_error &ex) {
      return (ex.mapped_key() == co::detail::asUTF8(string_type(_LIT("foo")))
        && ex.inclusive_mapped_key() ==
          co::detail::asUTF8(string_type(_LIT("bar"))));
    }
  );
}

/**
  option (empty) mutual inclusion any
*/
BOOST_AUTO_TEST_CASE( option_empty_mutual_inclusion_any_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
  };

  options = options_group_type{
    co::make_option(_LIT("foo,f"),_LIT("case 2"),
      co::basic_constraint<detail::check_char_t>().mutually_inclusive_any(
        {_LIT("bar")})),
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

//   stream_select::cerr << detail::to_string(vm,co::basic_value<string_type,detail::check_char_t>());

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
    }));
}

/**
  option (non) mutual inclusion any
*/
BOOST_AUTO_TEST_CASE( option_non_mutual_inclusion_any_test1 )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--foo"),
    _LIT("--bar")
  };

  options = options_group_type{
    co::make_option(_LIT("bar,b"),_LIT("case 2")),
    co::make_option(_LIT("foo,f"),_LIT("case 2"),
      co::basic_constraint<detail::check_char_t>().mutually_inclusive_any(
        {_LIT("bar")})),
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

//   stream_select::cerr << detail::to_string(vm,co::basic_value<string_type,detail::check_char_t>());

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("bar"),{}},
      {_LIT("foo"),{}}
    }));
}

/**
  option (non) mutual inclusion any
*/
BOOST_AUTO_TEST_CASE( option_non_mutual_inclusion_any_test2 )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--foo"),
    _LIT("--bar")
  };

  options = options_group_type{
    co::make_option(_LIT("bar,b"),_LIT("case 2")),
    co::make_option(_LIT("foo,f"),_LIT("case 2"),
      co::basic_constraint<detail::check_char_t>().mutually_inclusive_any(
        {_LIT("bar"),_LIT("foobar")})),
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

//   stream_select::cerr << detail::to_string(vm,co::basic_value<string_type,detail::check_char_t>());

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("bar"),{}},
      {_LIT("foo"),{}}
    }));
}

/**
  option (non) mutual inclusion any
*/
BOOST_AUTO_TEST_CASE( option_non_mutual_inclusion_any_test3 )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--foo"),
    _LIT("--bar")
  };

  options = options_group_type{
    co::make_option(_LIT("bar,b"),_LIT("case 2")),
    co::make_option(_LIT("foo,f"),_LIT("case 2"),
      co::basic_constraint<detail::check_char_t>().mutually_inclusive_any(
        {_LIT("foobar"),_LIT("bar")})),
  };

  std::tie(std::ignore,vm) =
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options);

//   stream_select::cerr << detail::to_string(vm,co::basic_value<string_type,detail::check_char_t>());

  BOOST_REQUIRE(detail::contents_equal<string_type>(vm,
    variable_map_type{
      {_LIT("bar"),{}},
      {_LIT("foo"),{}}
    }));
}

/**
  option mutual inclusion (actual) any
*/
BOOST_AUTO_TEST_CASE( option_mutual_inclusion_any_test )
{
  variable_map_type vm;
  options_group_type options;
  std::vector<const detail::check_char_t *> argv{
    _LIT("--foo")
  };

  options = options_group_type{
    co::make_option(_LIT("bar,b"),_LIT("case 2")),
    co::make_option(_LIT("foo,f"),_LIT("case 2"),
      co::basic_constraint<detail::check_char_t>().mutually_inclusive_any(
        {_LIT("bar"),_LIT("foobar")})),
  };

  std::vector<std::string> inclusive_any_keys{
    co::detail::asUTF8(string_type(_LIT("bar"))),
    co::detail::asUTF8(string_type(_LIT("foobar")))};

  BOOST_CHECK_EXCEPTION(
    co::parse_arguments(argv.data(),argv.data()+argv.size(),options),
    co::mutually_inclusive_any_error,
      [&](const co::mutually_inclusive_any_error &ex)
      {
        return (ex.mapped_key() == co::detail::asUTF8(string_type(_LIT("foo")))
          && ex.inclusive_any_keys() == inclusive_any_keys);
      }
  );
}

BOOST_AUTO_TEST_SUITE_END()


text:
/// @file
/// @copyright The code is licensed under the BSD License
///            <http://opensource.org/licenses/BSD-2-Clause>,
///            Copyright (c) 2013-2015 Alexandre Hamez.
/// @author Alexandre Hamez

#include <algorithm> // search
#include <array>
#include <cassert>
#include <deque>
#include <iostream>
#include <limits>
#include <regex>
#include <sstream>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>

#include <boost/algorithm/string/join.hpp>
#include <boost/optional.hpp>

#include "support/parsers/parse_error.hh"
#include "support/parsers/net.hh"
#include "support/parsers/token.hh"

namespace pnmc { namespace parsers {

namespace {

/*------------------------------------------------------------------------------------------------*/

// @brief Used to start keywords in token_t at indexes higher than other regular tokens matched by
// the regular expression.
static constexpr auto keywords_gap = 1000u;

// @brief Start at 1 because the relative position in the enum is used to compute the type of the
// token and because submatches of regular expressions start at 1 (0 is the whole match).
enum class tk { skip = 1u, newline, number, qname, name, colon, comma
              , lbracket, rbracket, arrow, lparen, rparen, question, exclamation, minus, mult
              , lt, gt
              , net = keywords_gap, transition, place, prio, module};

/*------------------------------------------------------------------------------------------------*/

using token = token_holder<tk>;
using parse_cxt = parse_context<tk>;

/*------------------------------------------------------------------------------------------------*/

/// @brief Returns the tokens of a Tina model.
template <typename InputIterator>
auto
tokens(InputIterator&& begin, InputIterator&& end)
{
  static constexpr std::array<const char*, 5> keywords = {{"net", "tr", "pl", "pr", "md"}};
  // Order must match enum token_t
  static const std::regex regex
  {
    "([ \\t]+)|"                  // skip spaces and tabs
    "(\\r\\n|\\n|\\r)|"           // newline (to keep track of line numbers)
    "(\\d+[KM]?)|"                // numbers can have a suffix
    "(\\{)|"                      // only search for opening brace for qualified names
    "([a-zA-Z'_][a-zA-Z0-9'_]*)|" // don't begin by a number, we add it if necessary in the parser
    "(:)|"                        // colon
    "(,)|"                        // comma
    "(\\[)|"                      // left bracket
    "(\\])|"                      // right bracket
    "(->)|"                       // arrow
    "(\\()|"                      // left parenthesis
    "(\\))|"                      // right parenthesis
    "(\\?)|"                      // question mark
    "(!)|"                        // exclamation mark
    "(-)|"                        // minus
    "(\\*)|"                      // multiplication
    "(<)|"                        // less than
    "(>)"                         // upper than
  };

  // To report error location, if any.
  auto line = 1ul;
  auto column = 1ul;
  std::smatch match;
  std::deque<token> tokens;

  while (true)
  {
    if (begin == end) {break;}

    std::regex_search(begin, end, match, regex);

    if (match.position() != 0)
    {
      throw parse_error( "Unexpected '" + match.prefix().str() + "' at " + std::to_string(line)
                       + ':' + std::to_string(column - match.prefix().str().size()));
    }

    column += match.length();
    begin += match.length();

    if (match[pos(tk::skip)].matched)    {continue;}
    if (match[pos(tk::newline)].matched) {column = 1; ++line; continue;}

    // Get the type of token by looking for the first successful submatch.
    const auto ty = [&match]
    {
      auto t = pos(tk::number);
      for (; t < match.size(); ++t)
      {
        if (match[t].matched) {break;}
      }
      return t;
    }();
    assert(ty < match.size());

    // Check if name is a keyword.
    if (ty == pos(tk::name))
    {
      const auto search = std::find(keywords.cbegin(), keywords.cend(), match[ty].str());
      if (search != keywords.cend())
      {
        const auto kw_ty = std::distance(keywords.cbegin(), search) + keywords_gap;
        tokens.emplace_back(token {tk(kw_ty), "", line, column});
        continue;
      }
    }
    // Process qualified names manually (to handle despecialization).
    else if (ty == pos(tk::qname))
    {
      std::string qname;
      qname.reserve(32);
      bool despecialization = false;
      while (true)
      {
        if (despecialization)
        {
          qname.push_back(*begin);
          despecialization = false;
        }
        else
        {
          if      (*begin == '}')  {++begin; ++column; break;}
          else if (*begin == '\\') {despecialization = true;}
          else                     {qname.push_back(*begin);}
        }
        ++begin;
        ++column;
      }
      tokens.emplace_back(token {tk::qname, qname, line, column});
      continue;
    }
    // All other tokens.
    tokens.emplace_back(token {tk(ty), match[ty].str(), line, column});
  }

  return tokens;
}

/*------------------------------------------------------------------------------------------------*/

boost::optional<std::string>
accept_name(parse_cxt& cxt)
{
  if (accept(cxt, tk::number)) // identifiers may start with a number
  {
    const auto name = cxt.val();
    accept(cxt, tk::name);
    return name + cxt.val();
  }
  else if (accept(cxt, tk::name))
  {
    return cxt.val();
  }
  return {};
}

/*------------------------------------------------------------------------------------------------*/

std::string
id(parse_cxt& cxt)
{
  if (const auto maybe_name = accept_name(cxt))
  {
    return *maybe_name;
  }
  else
  {
    expect(cxt, tk::qname);
    return cxt.val();
  }
}

/*------------------------------------------------------------------------------------------------*/

boost::optional<std::string>
accept_id(parse_cxt& cxt)
{
  if      (const auto n = accept_name(cxt)) {return *n;}
  else if (accept(cxt, tk::qname))          {return cxt.val();}
  else                                      {return {};}
}

/*------------------------------------------------------------------------------------------------*/

unsigned int
number(parse_cxt& cxt)
{
  expect(cxt, tk::number);
  const auto res = std::stoi(cxt.val());
  switch (cxt.val().back())
  {
    case 'K': return res * 1'000;
    case 'M': return res * 1'000'000;
    default : return res;
  }
}

/*------------------------------------------------------------------------------------------------*/

template <typename Fun>
void
input_arcs(parse_cxt& cxt, Fun&& add_arc)
{
  while (true)
  {
    const auto maybe_target = accept_id(cxt);
    if (not maybe_target) {break;} // no more arcs

    auto arc_ty = pn::arc::type::normal;
    auto valuation = 1u;

    if (accept(cxt, tk::mult))
    {
      if (accept(cxt, tk::mult))
      {
        arc_ty = pn::arc::type::reset;
      }
      else
      {
        valuation = number(cxt);
      }
    }
    else if (accept(cxt, tk::question))
    {
      if   (accept(cxt, tk::minus)) {arc_ty = pn::arc::type::inhibitor;}
      else                          {arc_ty = pn::arc::type::read;}
      valuation = number(cxt);
    }
    else if (accept(cxt, tk::exclamation))
    {
      throw parse_error("Unsupported stopwatch inhibitor arc");
    }
    add_arc(*maybe_target, valuation, arc_ty);
  }
}

/*------------------------------------------------------------------------------------------------*/

template <typename Fun>
void
output_arcs(parse_cxt& cxt, Fun&& add_arc)
{
  while (true)
  {
    const auto maybe_target = accept_id(cxt);
    if (not maybe_target)
    {
      break; // no more arcs
    }
    auto valuation = 1u;
    if (accept(cxt, tk::mult))
    {
      valuation = number(cxt);
    }
    add_arc(*maybe_target, valuation, pn::arc::type::normal);
  }
}

/*------------------------------------------------------------------------------------------------*/

void
transition(parse_cxt& cxt, pn::net& n)
{
  const auto tid = id(cxt);
  n.add_transition(tid);

  if (accept(cxt, tk::colon)) // label
  {
    id(cxt);
  }

  if (accept(cxt, tk::lbracket) or accept(cxt, tk::rbracket)) // time interval
  {
    static constexpr auto inf = std::numeric_limits<unsigned int>::max();

    // To report error location.
    const auto line = cxt.previous().line;
    const auto column = cxt.previous().column - 1;

    const bool open_lower_endpoint = cxt.val() == "]";
    bool open_upper_endpoint = false;

    auto low = number(cxt);

    expect(cxt, tk::comma);

    auto high = 0u;
    if (accept(cxt, tk::name))
    {
      if (cxt.val() != "w") {error(cxt);}
      high = inf;
    }
    else
    {
      high = number(cxt);
    }

    if (not accept(cxt, tk::rbracket))
    {
      expect(cxt, tk::lbracket);
      open_upper_endpoint = cxt.val() == "[";
    }

    if (open_lower_endpoint)                 {low += 1;}
    if (open_upper_endpoint and high != inf) {high -= 1;}

    if (high < low)
    {
      throw parse_error( "Time interval at " + std::to_string(line) + ":" + std::to_string(column));
    }

    n.add_time_interval(tid, low, high);
  }

  input_arcs(cxt, [&](const auto& pre, unsigned int weight, pn::arc::type ty)
                     {
                       n.add_pre_place(tid, pre, weight, ty);
                     });
  if (accept(cxt, tk::arrow))
  {
    output_arcs(cxt, [&](const auto& post, unsigned int weight, pn::arc::type ty)
                        {
                          n.add_post_place(tid, post, weight, ty);
                        });
  }
}

/*------------------------------------------------------------------------------------------------*/

void
place(parse_cxt& cxt, pn::net& n)
{
  const auto name = id(cxt);
  auto marking = 0u;
  if (accept(cxt, tk::colon)) // label
  {
    id(cxt);
  }
  if (accept(cxt, tk::lparen)) // initial marking
  {
    marking = number(cxt);
    expect(cxt, tk::rparen);
  }
  n.add_place(name, marking);
}

/*------------------------------------------------------------------------------------------------*/

void
priority(parse_cxt& cxt, pn::net&)
{
  id(cxt);
  while (accept_id(cxt)) {}
  if (not accept(cxt, tk::lt))
  {
    expect(cxt, tk::gt);
  }
  id(cxt);
  while (accept_id(cxt)) {}
}

/*------------------------------------------------------------------------------------------------*/

void
module(parse_cxt& cxt, std::unordered_map<std::string, std::vector<std::string>>& modules_id)
{
  const auto insertion = modules_id.emplace(id(cxt), std::vector<std::string>{});
  while (const auto pl = accept_id(cxt))
  {
    insertion.first->second.emplace_back(*pl);
  }
}

/*------------------------------------------------------------------------------------------------*/

/// @brief Remove commented lines and uncomment '#!' pragmas.
std::string
preprocess(std::istream& in)
{
  std::stringstream ss;
  auto comment = false;
  auto new_line = true;
  while (true)
  {
    const char c = in.get();
    if (in.eof())
    {
      break;
    }
    if (comment)
    {
      if (c == '!')
      {
        comment = false; // a comment is terminated by a line
        new_line = false;
        ss << ' '; // remove pragma ! indicator, the parser will directly read the associated token
      }
      else if (c == '\n' or c == '\r')
      {
        comment = false; // a comment is terminated by a line
        ss << c;
        if (c == '\r' and in.peek() == '\n')
        {
          ss << static_cast<char>(in.get());
          new_line = true;
        }
      }
      // else Comments are not copied
    }
    else if (new_line and not comment and c == '#' and in.peek())
    {
      comment = true;
      ss << ' ';
      new_line = false;
    }
    else if (new_line and not comment and c == 'n' and in.peek() == 't')
    // process notes as comments
    {
      comment = true;
    }
    else if (c == '\n')
    {
      ss << '\n';
      new_line = true;
    }
    else if (not comment)
    {
      ss << c;
      new_line = false;
    }
  }
  return ss.str();
}

/*------------------------------------------------------------------------------------------------*/

pn::module
make_module( const std::string& id, std::unordered_map<std::string, std::vector<std::string>>& graph
           , pn::net& net, const std::string& container, std::unordered_set<std::string>& places)
{
  const auto place_search = net.places().find(id);
  if (place_search != end(net.places()))
  {
    places.insert(place_search->name);
    return pn::make_module(*place_search);
  }
  else
  {
    pn::module_node m{id};
    const auto submodule_search = graph.find(id);
    if (submodule_search == end(graph))
    {
      throw parse_error("Undefined module or place " + id + " in module " + container);
    }
    for (const auto& sub : submodule_search->second)
    {
      m.add_submodule(make_module(sub, graph, net, id, places));
    }
    const auto insertion = net.modules.emplace(id, pn::make_module(m));
    if (not insertion.second)
    {
      throw parse_error("Module or place " + id + " is present in another module");
    }
    return insertion.first->second;
  }
}

/*------------------------------------------------------------------------------------------------*/

} // namespace anonymous

/*------------------------------------------------------------------------------------------------*/

std::shared_ptr<pn::net>
net(std::istream& in)
{
  auto net_ptr = std::make_shared<pn::net>();

  const auto text = preprocess(in);
  const auto tks = tokens(begin(text), end(text));
  auto cxt = parse_cxt{tks.cbegin(), tks.cend()};

  auto modules_id = std::unordered_map<std::string, std::vector<std::string>>{};

  while (not cxt.eof())
  {
    if      (accept(cxt, tk::net))        {net_ptr->name = id(cxt);}
    else if (accept(cxt, tk::transition)) {transition(cxt, *net_ptr);}
    else if (accept(cxt, tk::place))      {place(cxt, *net_ptr);}
    else if (accept(cxt, tk::prio))       {priority(cxt, *net_ptr);}
    else if (accept(cxt, tk::module))     {module(cxt, modules_id);}
    else                                  {error(cxt);}
  };

  if (modules_id.size() > 0)
  {
    const auto& net_name = net_ptr->name;
    const auto& root_search = modules_id.find(net_name);
    auto places_encountered = std::unordered_set<std::string>{};

    if (root_search == end(modules_id))
    {
      throw parse_error("No root module(s).");
    }
    for (const auto& submodule : root_search->second)
    {
      net_ptr->root_modules.emplace_back(make_module( submodule, modules_id, *net_ptr, net_name
                                                    , places_encountered));
    }
    auto invalid = std::vector<std::string>{};
    std::for_each( begin(net_ptr->places()), end(net_ptr->places())
                 , [&](const auto& p)
                      {
                        if (not places_encountered.count(p.name)) {invalid.push_back(p.name);}
                      });
    std::for_each( begin(modules_id), end(modules_id)
                 , [&](const auto& kv)
                      {
                        if (kv.first != net_ptr->name and not net_ptr->modules.count(kv.first))
                        {
                          invalid.push_back(kv.first);
                        }
                      });
    if (not invalid.empty())
    {
      const auto msg = boost::algorithm::join(invalid, ", ");
      throw parse_error("The following modules or places do not belong to any module: " + msg);
    }
  }

  net_ptr->format = conf::pn_format::net;
  return net_ptr;
}

/*------------------------------------------------------------------------------------------------*/

}} // namespace pnmc::parsers

max_stars_repo_name: ahamez/pnmc

max_issues_repo_name: ahamez/pnmc

max_forks_repo_name: ahamez/pnmc


text:
// Autogenerated from KST: please remove this line if doing any edits by hand!

#include <boost/test/unit_test.hpp>
#include "nav_parent_vs_value_inst.h"
#include <iostream>
#include <fstream>
#include <vector>

BOOST_AUTO_TEST_CASE(test_nav_parent_vs_value_inst) {
    std::ifstream ifs("src/term_strz.bin", std::ifstream::binary);
    kaitai::kstream ks(&ifs);
    nav_parent_vs_value_inst_t* r = new nav_parent_vs_value_inst_t(&ks);

    BOOST_CHECK_EQUAL(r->s1(), std::string("foo"));

    delete r;
}


text:
/*******************************************************************************
 *
 * Forward fixpoint iterators of varying complexity and precision.
 *
 * The interleaved fixpoint iterator is described in G. Amato and F. Scozzari's
 * paper: Localizing widening and narrowing. In Proceedings of SAS 2013,
 * pages 25-42. LNCS 7935, 2013.
 *
 * Author: Arnaud J. Venet (arnaud.j.venet@nasa.gov)
 *
 * Notices:
 *
 * Copyright (c) 2011 United States Government as represented by the
 * Administrator of the National Aeronautics and Space Administration.
 * All Rights Reserved.
 *
 * Disclaimers:
 *
 * No Warranty: THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF
 * ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED
 * TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO SPECIFICATIONS,
 * ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
 * OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL BE
 * ERROR FREE, OR ANY WARRANTY THAT DOCUMENTATION, IF PROVIDED, WILL CONFORM TO
 * THE SUBJECT SOFTWARE. THIS AGREEMENT DOES NOT, IN ANY MANNER, CONSTITUTE AN
 * ENDORSEMENT BY GOVERNMENT AGENCY OR ANY PRIOR RECIPIENT OF ANY RESULTS,
 * RESULTING DESIGNS, HARDWARE, SOFTWARE PRODUCTS OR ANY OTHER APPLICATIONS
 * RESULTING FROM USE OF THE SUBJECT SOFTWARE.  FURTHER, GOVERNMENT AGENCY
 * DISCLAIMS ALL WARRANTIES AND LIABILITIES REGARDING THIRD-PARTY SOFTWARE,
 * IF PRESENT IN THE ORIGINAL SOFTWARE, AND DISTRIBUTES IT "AS IS."
 *
 * Waiver and Indemnity:  RECIPIENT AGREES TO WAIVE ANY AND ALL CLAIMS AGAINST
 * THE UNITED STATES GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, AS WELL
 * AS ANY PRIOR RECIPIENT.  IF RECIPIENT'S USE OF THE SUBJECT SOFTWARE RESULTS
 * IN ANY LIABILITIES, DEMANDS, DAMAGES, EXPENSES OR LOSSES ARISING FROM SUCH
 * USE, INCLUDING ANY DAMAGES FROM PRODUCTS BASED ON, OR RESULTING FROM,
 * RECIPIENT'S USE OF THE SUBJECT SOFTWARE, RECIPIENT SHALL INDEMNIFY AND HOLD
 * HARMLESS THE UNITED STATES GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS,
 * AS WELL AS ANY PRIOR RECIPIENT, TO THE EXTENT PERMITTED BY LAW.
 * RECIPIENT'S SOLE REMEDY FOR ANY SUCH MATTER SHALL BE THE IMMEDIATE,
 * UNILATERAL TERMINATION OF THIS AGREEMENT.
 *
 ******************************************************************************/

#ifndef IKOS_FWD_FIXPOINT_ITERATORS_HPP
#define IKOS_FWD_FIXPOINT_ITERATORS_HPP

#include <map>
#include <boost/shared_ptr.hpp>
#include <crab/common/types.hpp>
#include <crab/common/debug.hpp>
#include <crab/common/stats.hpp>
#include <crab/iterators/wto.hpp>
#include <crab/iterators/fixpoint_iterators_api.hpp>
#include <crab/iterators/thresholds.hpp>

namespace ikos {

  namespace interleaved_fwd_fixpoint_iterator_impl {

    template< typename NodeName, typename CFG, typename AbstractValue >
    class wto_iterator;

    template< typename NodeName, typename CFG, typename AbstractValue >
    class wto_processor;

  } // namespace interleaved_fwd_fixpoint_iterator_impl

  template< typename NodeName, typename CFG, typename AbstractValue >
  class interleaved_fwd_fixpoint_iterator:
      public forward_fixpoint_iterator< NodeName, CFG, AbstractValue > {

    friend class interleaved_fwd_fixpoint_iterator_impl::wto_iterator< NodeName, CFG, AbstractValue >;

  private:
    typedef std::map< NodeName, AbstractValue > invariant_table_t;
    typedef boost::shared_ptr< invariant_table_t > invariant_table_ptr;
    typedef wto< NodeName, CFG > wto_t;
    typedef interleaved_fwd_fixpoint_iterator_impl::wto_iterator< NodeName, CFG, AbstractValue > wto_iterator_t;
    typedef interleaved_fwd_fixpoint_iterator_impl::wto_processor< NodeName, CFG, AbstractValue > wto_processor_t;
    typedef crab::iterators::thresholds<z_number> thresholds_t;

  private:
    CFG _cfg;
    wto_t _wto;
    invariant_table_ptr _pre, _post;
    // number of iterations until triggering widening
    unsigned int _widening_delay;
    // number of narrowing iterations. If the narrowing operator is
    // indeed a narrowing operator this parameter is not
    // needed. However, there are abstract domains for which a sound
    // narrowing operation is not available so we must enforce
    // termination.
    unsigned int _descending_iterations;
    // whether jump set is used for widening
    bool _use_widening_jump_set;
    // set of thresholds to jump during widening
    thresholds_t _jump_set;

  private:
    void set(invariant_table_ptr table, NodeName node, const AbstractValue& v) {
      std::pair< typename invariant_table_t::iterator, bool > res =
          table->insert(std::make_pair(node, v));
      if (!res.second) {
        (res.first)->second = v;
      }
    }

    void set_pre(NodeName node, const AbstractValue& v) {
      this->set(this->_pre, node, v);
    }

    void set_post(NodeName node, const AbstractValue& v) {
      this->set(this->_post, node, v);
    }

    AbstractValue get(invariant_table_ptr table, NodeName n) {
      typename invariant_table_t::iterator it = table->find(n);
      if (it != table->end()) {
        return it->second;
      } else {
        return AbstractValue::bottom();
      }
    }

  public:
    interleaved_fwd_fixpoint_iterator(CFG cfg,
                                      unsigned int widening_delay,
                                      unsigned int descending_iterations,
                                      size_t jump_set_size):
        _cfg(cfg),
        _wto(cfg),
        _pre(boost::make_shared<invariant_table_t>()),
        _post(boost::make_shared<invariant_table_t>()),
        _widening_delay(widening_delay),
        _descending_iterations(descending_iterations),
        _use_widening_jump_set (jump_set_size > 0) {

      if (_use_widening_jump_set) {
        crab::CrabStats::resume ("Fixpo");
        // select statically some widening points to jump to.
        _jump_set = _cfg.initialize_thresholds_for_widening(jump_set_size);
        crab::CrabStats::stop ("Fixpo");
      }
    }

    CFG get_cfg() const {
      return this->_cfg;
    }

    const wto_t& get_wto() const {
      return this->_wto;
    }

    AbstractValue get_pre(NodeName node) {
      return this->get(this->_pre, node);
    }

    AbstractValue get_post(NodeName node) {
      return this->get(this->_post, node);
    }

   private:

    AbstractValue extrapolate(NodeName /* node */, unsigned int iteration,
                              AbstractValue before, AbstractValue after) {

      CRAB_LOG("fixpo", crab::outs() << "Increasing iteration=" << iteration << "\n";);

      if (iteration <= _widening_delay) {
        CRAB_LOG("fixpo",
                 crab::outs() << "Widening \n";
                 auto widen_res = before | after;
                 crab::outs() << "Prev   : " << before << "\n"
                           << "Current: " << after << "\n"
                           << "Res    : " << widen_res << "\n");
        //crab::CrabStats::count (AbstractValue::getDomainName() + ".count.join");
        //crab::ScopedCrabStats __st__(AbstractValue::getDomainName() + ".join");
        return before | after;
      } else {
        CRAB_LOG("fixpo",
                 crab::outs() << "Widening \n";
                 crab::outs() << "Prev   : " << before << "\n"
                           << "Current: " << after << "\n");

        if (_use_widening_jump_set) {
          CRAB_LOG("fixpo",
                   auto widen_res = before.widening_thresholds (after, _jump_set);
                   crab::outs() << "Res    : " << widen_res << "\n");
          //crab::CrabStats::count (AbstractValue::getDomainName() + ".count.widening");
          //crab::ScopedCrabStats __st__(AbstractValue::getDomainName() + ".widening");
          return before.widening_thresholds (after, _jump_set);
        } else {
          CRAB_LOG("fixpo",
                   auto widen_res = before || after;
                   crab::outs() << "Res    : " << widen_res << "\n");
          //crab::CrabStats::count (AbstractValue::getDomainName() + ".count.widening");
          //crab::ScopedCrabStats __st__(AbstractValue::getDomainName() + ".widening");
          return before || after;
        }
      }
    }

    AbstractValue refine(NodeName /* node */, unsigned int iteration,
                         AbstractValue before, AbstractValue after) {

      CRAB_LOG("fixpo",
               crab::outs() << "Decreasing iteration=" << iteration << "\n";);

      if (iteration == 1) {
        CRAB_LOG("fixpo",
                 crab::outs() << "Narrowing \n";
                 auto narrow_res = before && after;
                 crab::outs() << "Prev   : " << before << "\n"
                           << "Current: " << after << "\n"
                           << "Res    : " << narrow_res << "\n");
        //crab::CrabStats::count (AbstractValue::getDomainName() + ".count.meet");
        //crab::ScopedCrabStats __st__(AbstractValue::getDomainName() + ".meet");
        return before & after;
      } else {
        CRAB_LOG("fixpo",
                 crab::outs() << "Narrowing \n";
                 auto narrow_res = before && after;
                 crab::outs() << "Prev   : " << before << "\n"
                 << "Current: " << after << "\n"
                           << "Res    : " << narrow_res << "\n");
        //crab::CrabStats::count (AbstractValue::getDomainName() + ".count.narrowing");
        //crab::ScopedCrabStats __st__(AbstractValue::getDomainName() + ".narrowing");
        return before && after;
      }
    }

   public:

    void run(AbstractValue init) {
      crab::ScopedCrabStats __st__("Fixpo");
      this->set_pre(this->_cfg.entry(), init);
      wto_iterator_t iterator(this);
      this->_wto.accept(&iterator);
      wto_processor_t processor(this);
      this->_wto.accept(&processor);
      this->_pre.reset();
      this->_post.reset();
    }

    virtual ~interleaved_fwd_fixpoint_iterator() { }

  }; // class interleaved_fwd_fixpoint_iterator

  namespace interleaved_fwd_fixpoint_iterator_impl {

    template< typename NodeName, typename CFG, typename AbstractValue >
    class wto_iterator: public wto_component_visitor< NodeName, CFG > {

    public:
      typedef interleaved_fwd_fixpoint_iterator< NodeName, CFG, AbstractValue > interleaved_iterator_t;
      typedef wto_vertex< NodeName, CFG > wto_vertex_t;
      typedef wto_cycle< NodeName, CFG > wto_cycle_t;
      typedef wto< NodeName, CFG > wto_t;
      typedef typename wto_t::wto_nesting_t wto_nesting_t;

    private:
      interleaved_iterator_t *_iterator;

    public:
      wto_iterator(interleaved_iterator_t *iterator): _iterator(iterator) { }

      void visit(wto_vertex_t& vertex) {
        AbstractValue pre;
        NodeName node = vertex.node();
        if (node == this->_iterator->get_cfg().entry()) {
          pre = this->_iterator->get_pre(node);
        } else {
          auto prev_nodes = this->_iterator->_cfg.prev_nodes(node);
          pre = AbstractValue::bottom();
          CRAB_LOG ("fixpo", crab::outs() << "Joining predecessors ...\n");
          for (NodeName prev : prev_nodes) {
            //crab::CrabStats::count (AbstractValue::getDomainName() + ".count.join");
            //crab::ScopedCrabStats __st__(AbstractValue::getDomainName() + ".join");
            pre |= this->_iterator->get_post(prev);
          }
          this->_iterator->set_pre(node, pre);
        }
        CRAB_LOG ("fixpo", crab::outs() << "Analyzing node ...\n");
        this->_iterator->analyze(node, pre);
        this->_iterator->set_post(node, pre);
      }

      void visit(wto_cycle_t& cycle) {
        NodeName head = cycle.head();
        wto_nesting_t cycle_nesting = this->_iterator->_wto.nesting(head);
        auto prev_nodes = this->_iterator->_cfg.prev_nodes(head);
        AbstractValue pre = AbstractValue::bottom();
        CRAB_LOG ("fixpo", crab::outs() << "Merging predecessors at widening point ...\n");
        for (NodeName prev : prev_nodes) {
          if (!(this->_iterator->_wto.nesting(prev) > cycle_nesting)) {
            //crab::CrabStats::count (AbstractValue::getDomainName() + ".count.join");
            //crab::ScopedCrabStats __st__(AbstractValue::getDomainName() + ".join");
            pre |= this->_iterator->get_post(prev);
          }
        }
        for(unsigned int iteration = 1; ; ++iteration) {
          // Increasing iteration sequence with widening
          this->_iterator->set_pre(head, pre);
          AbstractValue post(pre);
          CRAB_LOG ("fixpo", crab::outs() << "Analyzing node ...\n");
          this->_iterator->analyze(head, post);
          this->_iterator->set_post(head, post);
          for (typename wto_cycle_t::iterator it = cycle.begin(); it != cycle.end(); ++it) {
            it->accept(this);
          }
          AbstractValue new_pre = AbstractValue::bottom();
          for (NodeName prev : prev_nodes) {
            //crab::CrabStats::count (AbstractValue::getDomainName() + ".count.join");
            //crab::ScopedCrabStats __st__(AbstractValue::getDomainName() + ".join");
            new_pre |= this->_iterator->get_post(prev);
          }
          //crab::CrabStats::count (AbstractValue::getDomainName() + ".count.leq");
          //crab::CrabStats::resume (AbstractValue::getDomainName() + ".leq");
          if (new_pre <= pre) {
            //crab::CrabStats::stop (AbstractValue::getDomainName() + ".leq");
            // Post-fixpoint reached
            CRAB_LOG ("fixpo", crab::outs() << "post-fixpoint reached\n");
            this->_iterator->set_pre(head, new_pre);
            pre = new_pre;
            break;
          } else {
            //crab::CrabStats::stop (AbstractValue::getDomainName() + ".leq");
            pre = this->_iterator->extrapolate(head, iteration, pre, new_pre);
          }
        }
        for(unsigned int iteration = 1; ; ++iteration) {
          // Decreasing iteration sequence with narrowing
          AbstractValue post(pre);
          CRAB_LOG ("fixpo", crab::outs() << "Analyzing node ...\n");
          this->_iterator->analyze(head, post);
          this->_iterator->set_post(head, post);
          for (typename wto_cycle_t::iterator it = cycle.begin(); it != cycle.end(); ++it) {
            it->accept(this);
          }
          AbstractValue new_pre = AbstractValue::bottom();
          for (NodeName prev : prev_nodes) {
            //crab::CrabStats::count (AbstractValue::getDomainName() + ".count.join");
            //crab::ScopedCrabStats __st__(AbstractValue::getDomainName() + ".join");
            new_pre |= this->_iterator->get_post(prev);
          }
          //crab::CrabStats::count (AbstractValue::getDomainName() + ".count.leq");
          //crab::CrabStats::resume (AbstractValue::getDomainName() + ".leq");
          if (pre <= new_pre) {
            //crab::CrabStats::stop (AbstractValue::getDomainName() + ".leq");
            CRAB_LOG ("fixpo", crab::outs() << "No more refinement possible.\n");
            // No more refinement possible (pre == new_pre)
            break;
          } else {
            //crab::CrabStats::stop (AbstractValue::getDomainName() + ".leq");
            if (iteration > this->_iterator->_descending_iterations) break;
            pre = this->_iterator->refine(head, iteration, pre, new_pre);
            this->_iterator->set_pre(head, pre);
          }
        }
      }

    }; // class wto_iterator

    template< typename NodeName, typename CFG, typename AbstractValue >
    class wto_processor: public wto_component_visitor< NodeName, CFG > {

    public:
      typedef interleaved_fwd_fixpoint_iterator< NodeName, CFG, AbstractValue > interleaved_iterator_t;
      typedef wto_vertex< NodeName, CFG > wto_vertex_t;
      typedef wto_cycle< NodeName, CFG > wto_cycle_t;

    private:
      interleaved_iterator_t *_iterator;

    public:
      wto_processor(interleaved_iterator_t *iterator): _iterator(iterator) { }

      void visit(wto_vertex_t& vertex) {
        NodeName node = vertex.node();
        this->_iterator->process_pre(node, this->_iterator->get_pre(node));
        this->_iterator->process_post(node, this->_iterator->get_post(node));
      }

      void visit(wto_cycle_t& cycle) {
        NodeName head = cycle.head();
        this->_iterator->process_pre(head, this->_iterator->get_pre(head));
        this->_iterator->process_post(head, this->_iterator->get_post(head));
        for (typename wto_cycle_t::iterator it = cycle.begin(); it != cycle.end(); ++it) {
          it->accept(this);
        }
      }

    }; // class wto_processor

  } // interleaved_fwd_fixpoint_iterator_impl
} // namespace ikos
#endif // IKOS_FWD_FIXPOINT_ITERATORS

ext: hpp

max_stars_repo_name: satbekmyrza/crab

max_issues_repo_name: satbekmyrza/crab

max_forks_repo_name: satbekmyrza/crab


text:
#include <string>
#include <random>
#include <set>
#include <sstream>
#include <vector>
#include <array>
#include <algorithm>
#include <util/cityhash_gl.hpp>
#include <cxxtest/TestSuite.h>

// Eigen
#include <Eigen/Core>
#include <Eigen/SparseCore>

// SFrame and Flex type
#include <unity/lib/flex_dict_view.hpp>
#include <random/random.hpp>

// ML-Data Utils
#include <ml_data/ml_data.hpp>
#include <ml_data/ml_data_entry.hpp>
#include <ml_data/metadata.hpp>

// Testing utils common to all of ml_data_iterator
#include <util/testing_utils.hpp>
#include <ml_data/testing_utils.hpp>
#include <unity/toolkits/ml_data_2/testing_utils.hpp>

#include <globals/globals.hpp>

using namespace turi;

typedef Eigen::Matrix<double, Eigen::Dynamic,1>  DenseVector;
typedef Eigen::SparseVector<double> SparseVector;

class test_basic_version_compat : public CxxTest::TestSuite {
 public:

  // Test the block iterator by stress-testing a large number of
  // combinations of bounds, threads, sizes, and types

  enum class target_column_type {NONE, NUMERICAL, CATEGORICAL};

  void run_version_compat_check_test(size_t n, std::string run_string, target_column_type target_type) {

    globals::set_global("TURI_ML_DATA_TARGET_ROW_BYTE_MINIMUM", 29);
    globals::set_global("TURI_ML_DATA_STATS_PARALLEL_ACCESS_THRESHOLD", 7);

    random::seed(0);

    ml_data data_1;
    v2::ml_data data_2;

    bool target_column;

    std::map<std::string, ml_column_mode> data_1_modes;
    std::map<std::string, v2::ml_column_mode> data_2_modes;

    if(target_type == target_column_type::CATEGORICAL) {
      target_column = true;
      run_string = std::string("Z") + run_string;
      data_1_modes["target"] = ml_column_mode::CATEGORICAL;
      data_2_modes["target"] = v2::ml_column_mode::CATEGORICAL;
    } else if(target_type == target_column_type::NUMERICAL) {
      run_string = std::string("Z") + run_string;
      data_1_modes["target"] = ml_column_mode::NUMERIC;
      data_2_modes["target"] = v2::ml_column_mode::NUMERIC;
      target_column = true;
    } else {
      target_column = false;
    }

    sframe raw_data = make_random_sframe(n, run_string);

    if(target_column)
      raw_data.set_column_name(0, "target");

    for(size_t i = 0; i < raw_data.num_columns(); ++i) {
      if(raw_data.column_type(i) == flex_type_enum::INTEGER) {
        data_1_modes[raw_data.column_name(i)] = ml_column_mode::CATEGORICAL;
        data_2_modes[raw_data.column_name(i)] = v2::ml_column_mode::CATEGORICAL;
      }
    }

    std::string print_str = run_string;

    if(target_column)
      print_str += ":target";

    if(target_column) {
      data_1.fill(raw_data, "target", data_1_modes);
      data_2.set_data(raw_data, "target", {}, data_2_modes);
      data_2.fill();
    } else {
      data_1.fill(raw_data, "", data_1_modes);
      data_2.set_data(raw_data, "", {}, data_2_modes);
      data_2.fill();
    }

    // Now, go through and verify that the metadata loaded between
    std::shared_ptr<ml_metadata> loaded_metadata;

    // Save v2 metadata, load as current.
    save_and_load_object(loaded_metadata, data_2.metadata());

    data_1.metadata()->_debug_is_equal(loaded_metadata);
  }

  ////////////////////////////////////////////////////////////////////////////////

  void test_version_compat_0n() {
    // All unique
    run_version_compat_check_test(50, "n", target_column_type::NONE);
  }

  void test_version_compat_0b() {
    run_version_compat_check_test(50, "b", target_column_type::NONE);
  }

  void test_version_compat_0c() {
    // All unique
    run_version_compat_check_test(50, "c", target_column_type::NONE);
  }

  void test_version_compat_0C() {
    // All unique
    run_version_compat_check_test(50, "C", target_column_type::NONE);
  }

  void test_version_compat_1b_unsorted() {
    run_version_compat_check_test(130, "b", target_column_type::NONE);
  }

  void test_version_compat_1() {
    run_version_compat_check_test(130, "bc", target_column_type::NONE);
  }

  void test_version_compat_2() {
    run_version_compat_check_test(130, "zc", target_column_type::NONE);
  }

  void test_version_compat_3() {
    run_version_compat_check_test(1000, "Zc", target_column_type::NONE);
  }

  void test_version_compat_4() {
    // Pretty much gonna be unique
    run_version_compat_check_test(1000, "Cc", target_column_type::NONE);
  }

  void test_version_compat_5() {
    // 10 blocks of values.
    run_version_compat_check_test(1000, "Zc", target_column_type::NONE);
  }

  void test_version_compat_6() {
    // two large blocks of values
    run_version_compat_check_test(1000, "bc", target_column_type::NONE);
  }

  void test_version_compat_10() {
    // Yeah, a corner case
    run_version_compat_check_test(10, "bc", target_column_type::NONE);
  }

  void test_version_compat_11() {
    // One with just a lot of stuff
    run_version_compat_check_test(2000, "u", target_column_type::NONE);
  }

  void test_version_compat_12() {
    // One with just a lot of stuff
    run_version_compat_check_test(2000, "d", target_column_type::NONE);
  }

  void test_version_compat_13() {
    // One with just a lot of stuff
    run_version_compat_check_test(1000, "cnv", target_column_type::NONE);
  }

  void test_version_compat_14() {
    // One with just a lot of stuff
    run_version_compat_check_test(1000, "du", target_column_type::NONE);
  }

  void test_version_compat_15() {
    // One with just a lot of stuff
    run_version_compat_check_test(30, "UDccccV", target_column_type::NONE);
  }

  void test_version_compat_100() {
    // One with just a lot of stuff
    run_version_compat_check_test(100, "Zcuvd", target_column_type::NONE);
  }

  ////////////////////////////////////////////////////////////////////////////////
  // All the ones with targets

  void test_version_compat_0n_tn() {
    // All unique
    run_version_compat_check_test(500, "n", target_column_type::NUMERICAL);
  }

  void test_version_compat_0C_tn() {
    // All unique
    run_version_compat_check_test(500, "c", target_column_type::NUMERICAL);
  }

  void test_version_compat_1_unsorted_tn() {
    run_version_compat_check_test(500, "b", target_column_type::NUMERICAL);
  }

  void test_version_compat_0b_tn() {
    // All unique
    run_version_compat_check_test(130, "C", target_column_type::NUMERICAL);
  }

  void test_version_compat_1b_unsorted_tn() {
    run_version_compat_check_test(130, "b", target_column_type::NUMERICAL);
  }

  void test_version_compat_1_tn() {
    run_version_compat_check_test(130, "bc", target_column_type::NUMERICAL);
  }

  void test_version_compat_2_tn() {
    run_version_compat_check_test(130, "zc", target_column_type::NUMERICAL);
  }

  void test_version_compat_3_tn() {
    run_version_compat_check_test(1000, "Zc", target_column_type::NUMERICAL);
  }

  void test_version_compat_4_tn() {
    // Pretty much gonna be unique
    run_version_compat_check_test(1000, "Cc", target_column_type::NUMERICAL);
  }

  void test_version_compat_5_tn() {
    // 10 blocks of values.
    run_version_compat_check_test(1000, "Zc", target_column_type::NUMERICAL);
  }

  void test_version_compat_6_tn() {
    // two large blocks of values
    run_version_compat_check_test(1000, "bc", target_column_type::NUMERICAL);
  }

  void test_version_compat_10_tn() {
    // Yeah, a corner case
    run_version_compat_check_test(10, "bc", target_column_type::NUMERICAL);
  }

  void test_version_compat_11_tn() {
    // One with just a lot of stuff
    run_version_compat_check_test(2000, "u", target_column_type::NUMERICAL);
  }

  void test_version_compat_12_tn() {
    // One with just a lot of stuff
    run_version_compat_check_test(2000, "d", target_column_type::NUMERICAL);
  }

  void test_version_compat_13_tn() {
    // One with just a lot of stuff
    run_version_compat_check_test(1000, "cnv", target_column_type::NUMERICAL);
  }

  void test_version_compat_14_tn() {
    // One with just a lot of stuff
    run_version_compat_check_test(1000, "du", target_column_type::NUMERICAL);
  }

  void test_version_compat_15_tn() {
    // One with just a lot of stuff
    run_version_compat_check_test(30, "UDccccV", target_column_type::NUMERICAL);
  }

  void test_version_compat_100_tn() {
    // One with just a lot of stuff
    run_version_compat_check_test(100, "Zcuvd", target_column_type::NUMERICAL);
  }

  void test_version_compat_16_null_tn() {
    // two large blocks of values
    run_version_compat_check_test(1000, "", target_column_type::NUMERICAL);
  }

  ////////////////////////////////////////////////////////////////////////////////
  // All the ones with targets

  void test_version_compat_0n_tc() {
    // All unique
    run_version_compat_check_test(50, "n", target_column_type::CATEGORICAL);
  }

  void test_version_compat_0C_tc() {
    // All unique
    run_version_compat_check_test(50, "c", target_column_type::CATEGORICAL);
  }

  void test_version_compat_1_unsorted_tc() {
    run_version_compat_check_test(50, "b", target_column_type::CATEGORICAL);
  }

  void test_version_compat_0b_tc() {
    // All unique
    run_version_compat_check_test(130, "C", target_column_type::CATEGORICAL);
  }

  void test_version_compat_1b_unsorted_tc() {
    run_version_compat_check_test(130, "b", target_column_type::CATEGORICAL);
  }

  void test_version_compat_1_tc() {
    run_version_compat_check_test(130, "bc", target_column_type::CATEGORICAL);
  }

  void test_version_compat_2_tc() {
    run_version_compat_check_test(130, "zc", target_column_type::CATEGORICAL);
  }

  void test_version_compat_3_tc() {
    run_version_compat_check_test(1000, "Zc", target_column_type::CATEGORICAL);
  }

  void test_version_compat_4_tc() {
    // Pretty much gonna be unique
    run_version_compat_check_test(1000, "Cc", target_column_type::CATEGORICAL);
  }

  void test_version_compat_5_tc() {
    // 10 blocks of values.
    run_version_compat_check_test(1000, "Zc", target_column_type::CATEGORICAL);
  }

  void test_version_compat_6_tc() {
    // two large blocks of values
    run_version_compat_check_test(1000, "bc", target_column_type::CATEGORICAL);
  }

  void test_version_compat_10_tc() {
    // Yeah, a corner case
    run_version_compat_check_test(10, "bc", target_column_type::CATEGORICAL);
  }

  void test_version_compat_11_tc() {
    // One with just a lot of stuff
    run_version_compat_check_test(2000, "u", target_column_type::CATEGORICAL);
  }

  void test_version_compat_12_tc() {
    // One with just a lot of stuff
    run_version_compat_check_test(2000, "d", target_column_type::CATEGORICAL);
  }

  void test_version_compat_13_tc() {
    // One with just a lot of stuff
    run_version_compat_check_test(1000, "cnv", target_column_type::CATEGORICAL);
  }

  void test_version_compat_14_tc() {
    // One with just a lot of stuff
    run_version_compat_check_test(1000, "du", target_column_type::CATEGORICAL);
  }

  void test_version_compat_15_tc() {
    // One with just a lot of stuff
    run_version_compat_check_test(30, "UDccccV", target_column_type::CATEGORICAL);
  }

  void test_version_compat_100_tc() {
    // One with just a lot of stuff
    run_version_compat_check_test(100, "Zcuvd", target_column_type::CATEGORICAL);
  }

  void test_version_compat_16_null_tc() {
    // two large blocks of values
    run_version_compat_check_test(1000, "", target_column_type::CATEGORICAL);
  }

};

ext: cxx

max_stars_repo_name: LeeCenY/turicreate

max_issues_repo_name: LeeCenY/turicreate

max_forks_repo_name: ZeroInfinite/turicreate