text:
// __BEGIN_LICENSE__
//  Copyright (c) 2009-2013, United States Government as represented by the
//  Administrator of the National Aeronautics and Space Administration. All
//  rights reserved.
//
//  The NGT platform is licensed under the Apache License, Version 2.0 (the
//  "License"); you may not use this file except in compliance with the
//  License. You may obtain a copy of the License at
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// __END_LICENSE__

/// \file StereoSessionDG.cc
///
#include <vw/Image/ImageMath.h>
#include <vw/Image/Manipulation.h>
#include <vw/Image/MaskViews.h>
#include <vw/Image/Transform.h>
#include <vw/Camera/Extrinsics.h>
#include <vw/Math/EulerAngles.h>
#include <vw/Math/Matrix.h>
#include <vw/Cartography/Datum.h>

#include <asp/Core/StereoSettings.h>
#include <asp/Core/InterestPointMatching.h>
#include <asp/Core/AffineEpipolar.h>
#include <asp/Sessions/DG/LinescanDGModel.h>
#include <asp/Sessions/DG/StereoSessionDG.h>
#include <asp/Sessions/RPC/RPCModel.h>
#include <asp/Sessions/DG/XML.h>

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

#include <boost/date_time/posix_time/posix_time.hpp>

#include <xercesc/util/PlatformUtils.hpp>

using namespace vw;
using namespace asp;
using namespace xercesc;

namespace pt = boost::posix_time;
namespace fs = boost::filesystem;

// Allows FileIO to correctly read/write these pixel types
namespace vw {
  template<> struct PixelFormatID<Vector3>   { static const PixelFormatEnum value = VW_PIXEL_GENERIC_3_CHANNEL; };
  template<> struct PixelFormatID<Vector2f>  { static const PixelFormatEnum value = VW_PIXEL_GENERIC_2_CHANNEL; };
}

// Helper class for converting to floating point seconds based on a
// given reference.
class SecondsFrom {
  pt::ptime m_reference;
public:
  SecondsFrom( pt::ptime const& time ) : m_reference(time) {}

  double operator()( pt::ptime const& time ) const {
    return double( (time - m_reference).total_microseconds() ) / 1e6;
  }
};

namespace asp {

  pt::ptime parse_time(std::string str){
    try{
      return pt::time_from_string(str);
    }catch(...){
      vw_throw(ArgumentErr() << "Failed to parse time from string: "
               << str << "\n");
    }
    return pt::time_from_string(str); // never reached
  }

  // These are initializers and closers for Xercesc since we use it to
  // read our RPC models.
  StereoSessionDG::StereoSessionDG() {
    XMLPlatformUtils::Initialize();
  }

  StereoSessionDG::~StereoSessionDG() {
    XMLPlatformUtils::Terminate();
  }

  // Provide our camera model
  boost::shared_ptr<camera::CameraModel>
  StereoSessionDG::camera_model( std::string const& /*image_file*/,
                                 std::string const& camera_file ) {

    GeometricXML geo;
    AttitudeXML att;
    EphemerisXML eph;
    ImageXML img;
    RPCXML rpc;
    read_xml( camera_file, geo, att, eph, img, rpc );

    // Convert measurements in millimeters to pixels.
    geo.principal_distance /= geo.detector_pixel_pitch;
    geo.detector_origin /= geo.detector_pixel_pitch;

    bool correct_velocity_aberration = !stereo_settings().disable_correct_velocity_aberration;

    // Convert all time measurements to something that boost::date_time can read.
    boost::replace_all( eph.start_time, "T", " " );
    boost::replace_all( img.tlc_start_time, "T", " " );
    boost::replace_all( img.first_line_start_time, "T", " " );
    boost::replace_all( att.start_time, "T", " " );

    // Convert UTC time measurements to line measurements. Ephemeris
    // start time will be our reference frame to calculate seconds
    // against.
    SecondsFrom convert( parse_time( eph.start_time ) );

    // I'm going make the assumption that EPH and ATT are sampled at the
    // same rate and time.
    VW_ASSERT( eph.position_vec.size() == att.quat_vec.size(),
               MathErr() << "Ephemeris and Attitude don't have the same number of samples." );
    VW_ASSERT( eph.start_time == att.start_time && eph.time_interval == att.time_interval,
               MathErr() << "Ephemeris and Attitude don't seem to sample with the same t0 or dt." );

    // Convert ephemeris to be position of camera. Change attitude to be
    // be the rotation from camera frame to world frame. We also add an
    // additional rotation to the camera frame so X is the horizontal
    // direction to the picture and +Y points down the image (in the
    // direction of flight).
    Quat sensor_coordinate = math::euler_xyz_to_quaternion(Vector3(0,0,geo.detector_rotation * M_PI/180.0 - M_PI/2));
    for ( size_t i = 0; i < eph.position_vec.size(); i++ ) {
      eph.position_vec[i] += att.quat_vec[i].rotate( geo.perspective_center );
      att.quat_vec[i] = att.quat_vec[i] * geo.camera_attitude * sensor_coordinate;
    }

    // Load up the time interpolation class. If the TLCList only has
    // one entry ... then we have to manually drop in the slope and
    // offset.
    if ( img.tlc_vec.size() == 1 ) {
      double direction = 1;
      if ( boost::to_lower_copy( img.scan_direction ) !=
           "forward" ) {
        direction = -1;
      }
      img.tlc_vec.push_back( std::make_pair(img.tlc_vec.front().first +
                                            img.avg_line_rate, direction) );
    }

    // Build the TLCTimeInterpolation object and do a quick sanity check.
    camera::TLCTimeInterpolation tlc_time_interpolation( img.tlc_vec,
                                                         convert( parse_time( img.tlc_start_time ) ) );
    VW_ASSERT( fabs( convert( parse_time( img.first_line_start_time ) ) -
                     tlc_time_interpolation( 0 ) ) < fabs( 1.0 / (10.0 * img.avg_line_rate ) ),
               MathErr() << "First Line Time and output from TLC lookup table do not agree of the ephemeris time for the first line of the image." );

    typedef LinescanDGModel<camera::PiecewiseAPositionInterpolation, camera::LinearPiecewisePositionInterpolation, camera::SLERPPoseInterpolation, camera::TLCTimeInterpolation> camera_type;
    typedef boost::shared_ptr<camera::CameraModel> result_type;
    double et0 = convert( parse_time( eph.start_time ) );
    double at0 = convert( parse_time( att.start_time ) );
    double edt = eph.time_interval;
    double adt = att.time_interval;
    return result_type(new camera_type(camera::PiecewiseAPositionInterpolation(eph.position_vec, eph.velocity_vec,
                                                                               et0, edt ),
                                       camera::LinearPiecewisePositionInterpolation(eph.velocity_vec, et0, edt),
                                       camera::SLERPPoseInterpolation(att.quat_vec, at0, adt),
                                       tlc_time_interpolation, img.image_size,
                                       subvector(inverse(sensor_coordinate).rotate(Vector3(geo.detector_origin[0],
                                                                                geo.detector_origin[1],
                                                                                0)), 0, 2),
                                       geo.principal_distance, correct_velocity_aberration)
                      );
  }

  bool StereoSessionDG::ip_matching( std::string const& match_filename,
                                     double left_nodata_value,
                                     double right_nodata_value ) {
    // Load the unmodified images
    DiskImageView<float> left_disk_image( m_left_image_file ),
      right_disk_image( m_right_image_file );

    boost::shared_ptr<camera::CameraModel> left_cam, right_cam;
    camera_models( left_cam, right_cam );

    return
      ip_matching_w_alignment( left_cam.get(), right_cam.get(),
                               left_disk_image, right_disk_image,
                               cartography::Datum("WGS84"), match_filename,
                               left_nodata_value,
                               right_nodata_value);
  }

  StereoSessionDG::left_tx_type
  StereoSessionDG::tx_left() const {
    Matrix<double> tx = math::identity_matrix<3>();
    if ( stereo_settings().alignment_method == "homography" ||
         stereo_settings().alignment_method == "affineepipolar" ) {
      read_matrix( tx, m_out_prefix + "-align-L.exr" );
    }
    return left_tx_type( tx );
  }

  StereoSessionDG::right_tx_type
  StereoSessionDG::tx_right() const {
    Matrix<double> tx = math::identity_matrix<3>();
    if ( stereo_settings().alignment_method == "homography" ||
         stereo_settings().alignment_method == "affineepipolar" ) {
      read_matrix( tx, m_out_prefix + "-align-R.exr" );
    }
    return right_tx_type( tx );
  }

  void StereoSessionDG::pre_preprocessing_hook(std::string const& left_input_file,
                                               std::string const& right_input_file,
                                               std::string &left_output_file,
                                               std::string &right_output_file) {

    boost::shared_ptr<DiskImageResource>
      left_rsrc( DiskImageResource::open(m_left_image_file) ),
      right_rsrc( DiskImageResource::open(m_right_image_file) );

    float left_nodata_value, right_nodata_value;
    get_nodata_values(left_rsrc, right_rsrc, left_nodata_value, right_nodata_value);

    // Load the unmodified images
    DiskImageView<float> left_disk_image( left_rsrc ), right_disk_image( right_rsrc );

    // Filenames of normalized images
    left_output_file = m_out_prefix + "-L.tif";
    right_output_file = m_out_prefix + "-R.tif";

    // If these files already exist, don't bother writting them again.
    bool rebuild = false;
    try {
      vw_log().console_log().rule_set().add_rule(-1,"fileio");
      DiskImageView<float> test_left(left_output_file);
      DiskImageView<float> test_right(right_output_file);
      vw_settings().reload_config();
    } catch (vw::IOErr const& e) {
      vw_settings().reload_config();
      rebuild = true;
    } catch (vw::ArgumentErr const& e ) {
      // Throws on a corrupted file.
      vw_settings().reload_config();
      rebuild = true;
    }

    if (!rebuild) {
      vw_out() << "\t--> Using cached L and R files.\n";
      return;
    }

    ImageViewRef< PixelMask<float> > left_masked_image
      = create_mask_less_or_equal(left_disk_image, left_nodata_value);
    ImageViewRef< PixelMask<float> > right_masked_image
      = create_mask_less_or_equal(right_disk_image, right_nodata_value);

    Vector4f left_stats  = gather_stats( left_masked_image,  "left" );
    Vector4f right_stats = gather_stats( right_masked_image, "right" );

    ImageViewRef< PixelMask<float> > Limg, Rimg;
    std::string lcase_file = boost::to_lower_copy(m_left_camera_file);

    if ( stereo_settings().alignment_method == "homography" ||
         stereo_settings().alignment_method == "affineepipolar" ) {
      std::string match_filename
        = ip::match_filename(m_out_prefix, left_input_file, right_input_file);

      if (!fs::exists(match_filename)) {
        // This is calling an internal virtualized method.
        bool inlier =
          ip_matching( match_filename,
                       left_nodata_value,
                       right_nodata_value );
        if ( !inlier ) {
          fs::remove( match_filename );
          vw_throw( IOErr() << "Unable to match left and right images." );
        }
      } else {
        vw_out() << "\t--> Using cached match file: " << match_filename << "\n";
      }

      std::vector<ip::InterestPoint> left_ip, right_ip;
      ip::read_binary_match_file( match_filename, left_ip, right_ip  );
      Matrix<double> align_left_matrix = math::identity_matrix<3>(),
        align_right_matrix = math::identity_matrix<3>();

      Vector2i left_size = file_image_size( left_input_file ),
        right_size = file_image_size( right_input_file );

      if ( stereo_settings().alignment_method == "homography" ) {
        left_size =
          homography_rectification( left_size, right_size, left_ip, right_ip,
                                    align_left_matrix, align_right_matrix );
        vw_out() << "\t--> Aligning right image to left using matrices:\n"
                 << "\t      " << align_left_matrix << "\n"
                 << "\t      " << align_right_matrix << "\n";
      } else {
        left_size =
          affine_epipolar_rectification( left_size, right_size,
                                         left_ip, right_ip,
                                         align_left_matrix,
                                         align_right_matrix );
        vw_out() << "\t--> Aligning left and right images using affine matrices:\n"
                 << "\t      " << submatrix(align_left_matrix,0,0,2,3) << "\n"
                 << "\t      " << submatrix(align_right_matrix,0,0,2,3) << "\n";
      }
      write_matrix( m_out_prefix + "-align-L.exr", align_left_matrix );
      write_matrix( m_out_prefix + "-align-R.exr", align_right_matrix );

      // Applying alignment transform
      Limg = transform(left_masked_image,
                       HomographyTransform(align_left_matrix),
                       left_size.x(), left_size.y() );
      Rimg = transform(right_masked_image,
                       HomographyTransform(align_right_matrix),
                       left_size.x(), left_size.y() );
    } else if ( stereo_settings().alignment_method == "epipolar" ) {
      vw_throw( NoImplErr() << "StereoSessionDG does not support epipolar rectification" );
    } else {
      // Do nothing just provide the original files.
      Limg = left_masked_image;
      Rimg = right_masked_image;
    }

    // Apply our normalization options.
    normalize_images(stereo_settings().force_use_entire_range,
                     stereo_settings().individually_normalize,
                     left_stats, right_stats, Limg, Rimg);

    // The output no-data value must be < 0 as we scale the images to [0, 1].
    float output_nodata = -32768.0;

    // Enforce no predictor in compression, it works badly with L.tif and R.tif.
    asp::BaseOptions options = m_options;
    options.gdal_options["PREDICTOR"] = "1";

    vw_out() << "\t--> Writing pre-aligned images.\n";
    block_write_gdal_image( left_output_file, apply_mask(Limg, output_nodata),
                            output_nodata, options,
                            TerminalProgressCallback("asp","\t  L:  ") );

    if ( stereo_settings().alignment_method == "none" )
      block_write_gdal_image( right_output_file, apply_mask(Rimg, output_nodata),
                              output_nodata, options,
                              TerminalProgressCallback("asp","\t  R:  ") );
    else
      block_write_gdal_image( right_output_file,
                              apply_mask(crop(edge_extend(Rimg, ConstantEdgeExtension()), bounding_box(Limg)), output_nodata),
                              output_nodata, options,
                              TerminalProgressCallback("asp","\t  R:  ") );
  }

}


text:
#pragma once
#include "common.hpp"
#include <cstddef>
#include <boost/array.hpp>

namespace lite
{
    // boost::array
#ifndef APPLY_BOOST_GET
#  define APPLY_BOOST_GET(z, n, x) BOOST_PP_COMMA_IF(n) boost::get<n>(x)
#endif // !APPLY_BOOST_GET

    template<typename F, typename T, std::size_t N>
    inline typename boost::result_of<F(T)>::type apply(F f, boost::array<T, N>& array_)
    {
        return f(boost::get<0>(array_));
    }

    template<typename F, typename T, std::size_t N>
    inline typename boost::result_of<F(T)>::type apply(F f, const boost::array<T, N>& array_)
    {
        return f(boost::get<0>(array_));
    }

#ifndef ARRAY_BOOST_ARRAY
#  define ARRAY_BOOST_ARRAY(z, n, _) \
    template<typename F, typename T, std::size_t N> \
    inline typename boost::result_of<F(BOOST_PP_ENUM(n, APPLY_ARRAY_TYPE, T))>::type apply(F f, const boost::array<T, N>& array_) \
    { \
        return f(BOOST_PP_REPEAT_Z(z, n, APPLY_BOOST_GET, array_)); \
    }
    BOOST_PP_REPEAT_FROM_TO(2, 10, ARRAY_BOOST_ARRAY, _)
#endif
}

ext: hpp

max_stars_repo_name: gwankyun/apply

max_issues_repo_name: gwankyun/apply

max_forks_repo_name: gwankyun/apply


text:
#include <fstream>
#include <experimental/filesystem>
#include <boost/progress.hpp>
#include <boost/program_options.hpp>
#include <GraphMol/SmilesParse/SmilesParse.h>
#include <GraphMol/SmilesParse/SmilesWrite.h>
#include <GraphMol/FileParsers/MolSupplier.h>
#include "SAScore.hpp"

int main(int argc, const char* argv[]) {
  // Set up a command line argument parser and parse the command line arguments.
  std::string input_path, library_path, output_path;

  boost::program_options::options_description description("Options");
  description.add_options()
    ("help,h",
      "Display this help message.")
    ("input,i", boost::program_options::value<std::string>(&input_path)->required(),
      "Path to the input file containing molecules in SMILES or SDF format.")
    ("library,l", boost::program_options::value<std::string>(&library_path)->required(),
      "Path to the serialized feature library containing the feature scores.")
    ("output,o", boost::program_options::value<std::string>(&output_path)->required(),
      "Path to the output text file containing the SAScores.");

  boost::program_options::positional_options_description positionals_description;
  positionals_description.add("input", 1);
  positionals_description.add("library", 1);
  positionals_description.add("output", 1);
  boost::program_options::variables_map vm;
  boost::program_options::command_line_parser parser(argc, argv);
  parser.options(description);
  parser.positional(positionals_description);
  boost::program_options::parsed_options parsed_options = parser.run();
  boost::program_options::store(parsed_options, vm);
  if (vm.count("help")) {
    std::cout << description;
    return 1;
  };
  boost::program_options::notify(vm);

  // Deserialize the FeatureLibrary.
  FeatureLibrary feature_library;
  std::ifstream library_stream (library_path, std::ifstream::binary);
  boost::archive::binary_iarchive binary_archive (library_stream);
  binary_archive >> feature_library;

  // Create an output stream for the SAScores.
  std::ofstream output_stream (output_path);

  // Create a molecule input stream based on the extension of the input file.
  std::experimental::filesystem::path extension = std::experimental::filesystem::path(input_path).extension();

  // If the input file is a SMILES file:
  if (extension == ".smi" || extension == ".ism") {
    RDKit::SmilesMolSupplier supplier(input_path);

    // Initialize a progress bar.
    unsigned n_mols = supplier.length();
    supplier.reset();
    boost::progress_display progress(n_mols);

    // Loop over the input molecules.
    std::unique_ptr<RDKit::ROMol> mol;
    while (!supplier.atEnd()) {
      mol.reset(supplier.next());
      // Verify that the molecule was successfully read.
      if (mol) {
        // Calculate its SAScore and write it to the output file.
        double sascore = SAScore(*mol, feature_library);
        output_stream << RDKit::MolToSmiles(*mol) << " " << sascore << "\n";
      };
      ++progress;
    };

  // If the input file is a SDF file:
  } else if (extension == ".sdf") {
    RDKit::SDMolSupplier supplier(input_path);

    // Initialize a progress bar.
    unsigned n_mols = supplier.length();
    supplier.reset();
    boost::progress_display progress(n_mols);

    // Loop over the input molecules.
    std::unique_ptr<RDKit::ROMol> mol;
    while (!supplier.atEnd()) {
      mol.reset(supplier.next());
      // Verify that the molecule was successfully read.
      if (mol) {
        // Calculate its SAScore and write it to the output file.
        double sascore = SAScore(*mol, feature_library);
        output_stream << RDKit::MolToSmiles(*mol) << " " << sascore << "\n";
      };
      ++progress;
    };

  // If the molecule input format is something else, throw an error.
  } else {
    throw std::runtime_error("Unrecognized input format. Input should be either SMILES or SDF.");
  };

  // Close the output stream.
  output_stream.close();

  // Signal success.
  return 0;
};

ext: cpp

max_stars_repo_name: etijskens/LEADD

max_issues_repo_name: etijskens/LEADD

max_forks_repo_name: etijskens/LEADD


text:
/**
 * Copyright (c) 2016-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

#include <algorithm>
#include <boost/any.hpp>
#include <gtest/gtest.h>

#include "DexClass.h"
#include "DexInstruction.h"
#include "DexLoader.h"
#include "Resolver.h"
#include "Show.h"
#include "VerifyUtil.h"

struct StaticValueTestCase {
  const char* name;
  const char* type;
  const boost::any value;
};

void assert_class_clinit_exist(DexClasses& classes, const char* name) {
  auto cls = find_class_named(classes, name);
  ASSERT_NE(nullptr, cls);
  auto clinit = cls->get_clinit();
  ASSERT_NE(nullptr, clinit);
}

/*
 * Ensure that we are actually replacing encodable clinits by checking
 * that they exist in the pre-redexed binary.
 */

TEST_F(PreVerify, ReplaceEncodableClinit) {
  assert_class_clinit_exist(classes, "Lredex/Encodable;");
  assert_class_clinit_exist(classes, "Lredex/UnEncodable;");
  assert_class_clinit_exist(classes, "Lredex/HasWides;");
  assert_class_clinit_exist(classes, "Lredex/HasCharSequence;");
}

/*
 * Ensure that we've removed the appropriate clinit and that the corresponding
 * static values are still correct.
 *
 * TODO: Note that Encodable class in ReplaceEncodableClinitTest.java don't have
 * finals. It has just static fields. If you place finals, javac will do the
 * constant propagation and won't generate clinit. That's why our testing class
 * doesn't have final properties. Meanwhile, FinalInline's removing clinit logic
 * has been broken. It mistakely removed non-final fields. It should have
 * removed const-sput pairs with *final* and *static* fields. D5252471 fixes
 * this bug. Unfortunately this diff makes it harder to test with Java source.
 * Hence, we remove the testing for now. We need to write a new unit test
 * instead of instrumentation test.
 */
TEST_F(PostVerify, ReplaceEncodableClinit) {
  // The fixed FinalInline should not remove clinits with non-final fields.
  assert_class_clinit_exist(classes, "Lredex/Encodable;");

  assert_class_clinit_exist(classes, "Lredex/UnEncodable;");
  assert_class_clinit_exist(classes, "Lredex/HasCharSequence;");

  // "inline_wide_fields": false
  assert_class_clinit_exist(classes, "Lredex/HasWides;");
}

max_stars_repo_name: thezhangwei/redex

max_issues_repo_name: thezhangwei/redex

max_forks_repo_name: thezhangwei/redex


text:
//
// Created by Masahiro Tanaka on 2019-03-05.
//
#include <boost/graph/connected_components.hpp>
#include <boost/graph/strong_components.hpp>
#include <boost/graph/filtered_graph.hpp>
#include <boost/graph/copy.hpp>

#include <graph/ir.h>
#include <Common.h>
#include <Config.h>

#include "Decomposition.h"

namespace {
    const std::string LOGGER_NAME = "Decomposition";
}

namespace rannc {
    const std::string MASTER_NAME = "MASTER";

    typedef boost::filtered_graph<BGraph, std::function<bool(BGraph::edge_descriptor)>,
            std::function<bool(BGraph::vertex_descriptor)>> ComponentGraph;

    void setProperty(VertexInfo &v, const IRValue &value) {
        v.name = value.getName();
        v.value = value;
        v.type = VALUE;
        v.is_param = value.isParam();
        v.id = "v_" + value.getName();
        v.ranks = {};
        v.is_input = false;
        v.is_orig_input = false;
        v.is_output = false;
        v.is_orig_output = false;
        v.is_loss = value.isLoss();
    }

    void setProperty(VertexInfo &v, const IRNode &node) {
        v.name = node.getName();
        v.node = node;
        v.type = NODE;
        v.id = node.getId();
        v.ranks = {};
        v.is_input = false;
        v.is_orig_input = false;
        v.is_output = false;
        v.is_orig_output = false;
        v.is_criterion = node.isCriterion();
        v.fwd_time = 0;
        v.bwd_time = 0;
    }

    /**
     * Convert an IR graph to a BGL graph.
     *
     * @param ir_graph IR graph to convert
     * @return BGL graph
     */
    BGraph toBGL(const std::shared_ptr<IRGraph> &ir_graph) {
        BGraph b_graph;

        b_graph[boost::graph_bundle].id = ir_graph->getName();

        const auto logger = getLogger(LOGGER_NAME);
//        logger->trace("Converting graph:");

        std::unordered_map<std::string, Vertex> values;
        for (const std::string &input_name: ir_graph->getInputNames()) {
            const auto &value = ir_graph->getValue(input_name);
            Vertex v = boost::add_vertex(b_graph);
            setProperty(b_graph[v], value);
            values[input_name] = v;

            b_graph[v].is_input = true;
            b_graph[v].is_orig_input = true;

//            logger->trace("   Value name={} id={} param={} input={} output={}", b_graph[v].name, b_graph[v].id,
//                          b_graph[v].is_param, b_graph[v].is_input, b_graph[v].is_output);
        }

        // assume that nodes are topologically sorted
        for (const auto &in_node: ir_graph->getNodes()) {
            Vertex v = boost::add_vertex(b_graph);
            setProperty(b_graph[v], in_node);

//            logger->trace("Node name={} id={}", b_graph[v].name, b_graph[v].id);

            for (const auto &input_name: in_node.getInputNames()) {
                Vertex in_v = values[input_name];
                boost::add_edge(in_v, v, b_graph);
//                std::cout << "  Created edge: " << (*bGraph)[in_v].name << " -> " << (*bGraph)[v].name << std::endl;
            }

            for (const auto &output_name: in_node.getOutputNames()) {
                const auto &value = ir_graph->getValue(output_name);
                Vertex out_v = boost::add_vertex(b_graph);
                setProperty(b_graph[out_v], value);
                values[output_name] = out_v;
                boost::add_edge(v, out_v, b_graph);

                if (contains(ir_graph->getOutputNames(), output_name)) {
                    b_graph[out_v].is_output = true;
                    b_graph[out_v].is_orig_output = true;
                }

//                logger->trace("   Value name={} id={} param={} input={} output={}", b_graph[out_v].name,
//                              b_graph[out_v].id,
//                              b_graph[out_v].is_param, b_graph[out_v].is_input, b_graph[out_v].is_output);

                //                std::cout << "  Created edge: " << (*bGraph)[v].name << " -> " << (*bGraph)[out_v].name << std::endl;
            }
        }

        return b_graph;
    }

    bool containsVertex(const BGraph &g, const std::vector<Vertex> &vertices, const Vertex tgt) {
        for (const Vertex &v: vertices) {
            if (g[v].id == g[tgt].id) {
                return true;
            }
        }
        return false;
    }

    bool containsVertexById(const BGraph &g, const std::string &id) {
        for (const Vertex &v: all_nodes<Vertex, BGraph>(g)) {
            if (g[v].id == id) {
                return true;
            }
        }
        return false;
    }

    Vertex findVertexById(const BGraph &g, const std::string &id) {
        for (const Vertex &v: all_nodes<Vertex, BGraph>(g)) {
            if (g[v].id == id) {
                return v;
            }
        }
        throw std::invalid_argument("Vertex with id '" + id + "' is not found.");
    }

    BGraph createSubgraph(const BGraph &g, const std::vector<Vertex> &sub_vertices) {
        std::vector<Vertex> topo_vertices, rev_topo_vertices;
        boost::topological_sort(g, std::back_inserter(rev_topo_vertices));

        BGraph subgraph;
        std::unordered_map<std::string, Vertex> new_nodes;
        for (const Vertex &v: rev_topo_vertices) {
            if (containsVertex(g, sub_vertices, v)) {
                Vertex sv = boost::add_vertex(subgraph);
                subgraph[sv] = g[v];
                new_nodes[g[v].id] = sv;

                for (const auto &out: target_nodes(v, g)) {
                    if (contains(new_nodes, g[out].id)) {
                        boost::add_edge(sv, new_nodes[g[out].id], subgraph);
                    }
                }
            }
        }
        return subgraph;
    }

    BGraph createSubgraphByRank(const BGraph &g, int rank) {
        std::vector<Vertex> sub_vertices;

        for (const auto &v: all_nodes<Vertex, BGraph>(g)) {
            if (contains(g[v].ranks, rank)) {
                sub_vertices.push_back(v);
            }
        }
        return createSubgraph(g, sub_vertices);
    }

    std::unordered_map<int, BGraph> createSubgraphsByRank(const BGraph &g) {
        std::unordered_map<int, BGraph> subgraphs;
        std::unordered_set<int> ranks;

        for (const auto &v: all_nodes<Vertex, BGraph>(g)) {
            for (int r: g[v].ranks) {
                ranks.insert(r);
            }
        }
        for (int r: ranks) {
            subgraphs[r] = createSubgraphByRank(g, r);
        }

        return subgraphs;

    }

    int getRank(std::unordered_map<int, BGraph> &subgraphs, const std::string &id) {
        for (auto &sg: subgraphs) {
            if (containsVertexById(sg.second, id)) return sg.first;
        }
        throw std::invalid_argument("Node not found in a subgraph: " + id);
    }

    std::string createSubgraphId(const std::string &orig_name, int index) {
        std::stringstream ss;
        ss << orig_name << "_p" << index;
        return ss.str();
    }

    bool containsConnection(const std::vector<GraphConnection> &connections, const GraphConnection &con) {
        bool found = false;
        for (const auto &c: connections) {
            if (c.src == con.src
                && c.dest == con.dest
                && c.value == con.value) {
                return true;
            }
        }
        return found;
    }

    bool hasSameValueConnection(const std::vector<GraphConnection> &connections, const std::string &value_name,
                                const std::string &dest_sg) {
        for (const auto &c: connections) {
            if (c.value == value_name && c.dest == dest_sg) {
                return true;
            }
        }
        return false;
    }

    BDecomposition createSubGraphs(const BGraph &g) {

        std::unordered_map<int, std::string> subgraph_id_map;
        std::unordered_map<std::string, BGraph> subgraphs;
        std::vector<std::string> order;

        auto subgraphs_by_rank = createSubgraphsByRank(g);
        for (auto idx: keys(subgraphs_by_rank)) {
            auto &sg = subgraphs_by_rank.at(idx);
            const auto sg_id = createSubgraphId(g[boost::graph_bundle].id, idx);
            sg[boost::graph_bundle].id = sg_id;

            subgraph_id_map[idx] = sg_id;
            subgraphs[sg_id] = sg;

            order.push_back(sg_id);
        }

        typedef boost::graph_traits<BGraph>::edge_iterator edge_iterator;
        edge_iterator ei, ei_end;

        // Add inter-graph connections
        std::vector<GraphConnection> connections;
        std::vector<GraphConnection> param_connections;

        for (boost::tie(ei, ei_end) = boost::edges(g); ei != ei_end; ei++) {
            Vertex src = boost::source(*ei, g);
            Vertex tgt = boost::target(*ei, g);

            for (int tgt_rank: g[tgt].ranks) {
                if (!contains(g[src].ranks, tgt_rank)) {
                    assert(!g[src].ranks.empty());
                    int src_rank = *(g[src].ranks.begin());

//                    spdlog::info("Checking graph edge: {}@rank{}->{}@rank{}", g[src].name, src_rank, g[tgt].name, tgt_rank);
                    const auto &src_graph_id = subgraph_id_map[src_rank];
                    const auto &tgt_graph_id = subgraph_id_map[tgt_rank];

                    GraphConnection con{g[src].name, src_graph_id, tgt_graph_id, g[src].id, g[tgt].id};
                    if (g[src].is_param) {
                        if (!containsConnection(param_connections, con)) {
                            param_connections.emplace_back(con);
//                            spdlog::info("Found shared param connection: {} {}->{}", g[src].name, src_graph_id, tgt_graph_id);
                        }
                    } else {
                        if (!containsConnection(connections, con)) {
                            connections.emplace_back(con);
//                            spdlog::info("Created graph connection: {} {}->{}", g[src].name, src_graph_id, tgt_graph_id);
                        }
                    }
                }
            }
        }

        // Add vertices for receive buffer
        for (const auto &con: addAll(connections, param_connections)) {
            BGraph &src_graph = subgraphs[con.src];
            BGraph &tgt_graph = subgraphs[con.dest];
            Vertex src = findVertexById(g, con.id);

            Vertex tgt_src = boost::add_vertex(tgt_graph);
            tgt_graph[tgt_src] = g[src];
            Vertex tgt_tgt = findVertexById(tgt_graph, con.targetId);
            boost::add_edge(tgt_src, tgt_tgt, tgt_graph);

            if (!g[src].is_param) {
                Vertex v_src = findVertexById(src_graph, con.id);
                src_graph[v_src].is_output = true;
                Vertex v_tgt = findVertexById(tgt_graph, con.id);
                tgt_graph[v_tgt].is_input = true;
            }
        }

        // Add connections from/to master
        const auto logger = getLogger(LOGGER_NAME);
        for (const auto &it: subgraphs) {
            const auto &sg_id = it.first;
            const BGraph &subgraph = it.second;

            for (const Vertex &v: all_nodes<Vertex, BGraph>(subgraph)) {
                const VertexInfo &vi = subgraph[v];
                if (vi.type != VALUE) continue;

                if (vi.is_orig_input && !vi.is_param) {
                    if (!hasSameValueConnection(connections, vi.name, sg_id)) {
                        GraphConnection con{vi.name, MASTER_NAME, sg_id, "NA", vi.id};
                        connections.push_back(con);
//
//                        spdlog::info("Created graph connection: {} MASTER->{}", vi.name, sg_id);
                    }
                }
                if (vi.is_orig_output) {
                    GraphConnection con{vi.name, sg_id, MASTER_NAME, vi.id, "NA"};
                    connections.push_back(con);
//
//                    spdlog::info("Created graph connection: {} {}->MASTER", vi.name, sg_id);
                }
            }
        }

        return BDecomposition{subgraphs, connections, order};
    }

    std::vector<IRValue> searchGraphValuesByName(const std::shared_ptr<IRGraph> &ir_graph,
                                                 const std::string &val_name) {
        std::vector<IRValue> found;
        for (const auto &v: ir_graph->getValues()) {
            if (v.first == val_name) {
                found.push_back(v.second);
            }
        }
        return found;
    }

    std::vector<IRValue> searchGraphValuesByName(const std::vector<std::shared_ptr<IRGraph>> &ir_graphs,
                                                 const std::string &val_name) {
        std::vector<IRValue> found;

        for (const auto &g: ir_graphs) {
            for (const auto &v: searchGraphValuesByName(g, val_name)) {
                found.push_back(v);
            }
        }
        return found;
    }

    RouteTypeDP chooseRouteType(bool is_batch, bool is_loss, bool fwd) {

        if (is_batch) {
            return RouteTypeDP::REDIST;
        } else if (is_loss) {
            if (fwd) {
                return RouteTypeDP::BROADCAST;
            } else {
                return RouteTypeDP::WEIGHTED_REDUCE;
            }
        }
        std::stringstream ss;
        ss << "Failed to choose route type: is_batch=" << is_batch
           << " is_loss=" << is_loss
           << " fwd=" << fwd;
        throw std::invalid_argument(ss.str());
    }

    std::vector<int> getGraphRanks(const std::string &graph_id,
                                   const std::unordered_map<std::string, std::unordered_set<int>> &allocation) {
        if (graph_id == MASTER_NAME) {
            std::unordered_set<int> ranks;
            for (int i = 0; i < mpi::getSize(); i++) {
                ranks.insert(i);
            }
            return setToVector(ranks);
        }

        assert(contains(allocation, graph_id));
        return setToVector(allocation.at(graph_id));
    }

    bool isGraphInput(const GraphConnectionDP &con) {
        return con.src_graphs.size() == 1 && *con.src_graphs.begin() == MASTER_NAME;
    }

    bool isGraphOutput(const GraphConnectionDP &con) {
        return con.dest_graphs.size() == 1 && *con.dest_graphs.begin() == MASTER_NAME;
    }

    RGraph toRGraph(const std::unordered_map<std::string, std::shared_ptr<IRGraph>>& subgraphs,
            const std::vector<RouteDP> &routes) {
        RGraph rg;
        std::unordered_set<std::string> graph_ids;
        std::unordered_map<std::string, RVertex> v_map;

        for (const auto& it: subgraphs) {
            const auto& id = it.first;

            const auto v = boost::add_vertex(rg);
            v_map[id] = v;
            rg[v].name = id;
            rg[v].type = RVertexType::GRAPH;
            graph_ids.insert(id);
        }

        for (const auto& r: routes) {
            const auto& src_id = r.source_graph;
            const auto& tgt_id = r.dest_graph;

            if (!contains(graph_ids, src_id)) {
                const auto v = boost::add_vertex(rg);
                v_map[src_id] = v;
                rg[v].name = src_id;
                rg[v].type = RVertexType::GRAPH;
                graph_ids.insert(src_id);
            }

            if (!contains(graph_ids, tgt_id)) {
                const auto v = boost::add_vertex(rg);
                v_map[tgt_id] = v;
                rg[v].name = tgt_id;
                rg[v].type = RVertexType::GRAPH;
                graph_ids.insert(tgt_id);
            }

            const auto e = boost::add_vertex(rg);
            rg[e].name = r.ir_value.getName();
            rg[e].type = RVertexType::ROUTE;
            rg[e].route = r;

            boost::add_edge(v_map.at(src_id), e, rg);
            boost::add_edge(e, v_map.at(tgt_id), rg);
        }

        return rg;
    }

    std::vector<std::string> sortGraphs(const std::unordered_map<std::string, std::shared_ptr<IRGraph>>& subgraphs,
            const std::vector<RouteDP> &routes) {
        RGraph rg = toRGraph(subgraphs, routes);

        std::vector<std::string> sorted_graph_id;
        for (const auto &v: all_nodes_topo<RVertex, RGraph>(rg)) {
            if (rg[v].type == RVertexType::GRAPH) {
                sorted_graph_id.push_back(rg[v].name);
            }
        }

        return sorted_graph_id;
    }

    Deployment createDeployment(const PartitionDP &partition, const std::unordered_map<std::string, std::unordered_set<int>> &allocation) {

        const auto logger = getLogger(LOGGER_NAME);
        logger->trace("createDeployment starting. id={} #connections={}", partition.id,
                      partition.connections.size());

        Deployment deployment;

        deployment.id = partition.id;
        deployment.graph = partition.graph;
        deployment.subgraphs = partition.subgraphs;
        deployment.allocation = allocation;

        std::vector<RouteDP> fwd_routes, fwd_in_routes, fwd_out_routes;
        std::vector<RouteDP> bwd_routes, bwd_in_routes, bwd_out_routes;

        TagMap &tag_map = TagMap::get();
        for (const auto &con: partition.connections) {
            logger->trace("createDeployment converting connection: {}", toString(con));

            std::vector<IRValue> ir_values;
            for (const auto &sg: values(partition.subgraphs)) {
                for (const auto &v: searchGraphValuesByName(sg, con.value)) {
                    ir_values.push_back(v);
                }
            }
            assert(!ir_values.empty());
            const IRValue &val = ir_values.at(0);

            RouteDP fwd_route;
            fwd_route.location = con.value;
            fwd_route.sources = getGraphRanks(con.src, allocation);
            fwd_route.source_graph = con.src;
            fwd_route.dests = getGraphRanks(con.dest, allocation);
            fwd_route.dest_graph = con.dest;
            fwd_route.type = chooseRouteType(val.isBatch(), val.isLoss(), true);
            fwd_route.ir_value = val;

            int tag = tag_map.getRouteTag(fwd_route);
            fwd_route.tag = tag;
            fwd_route.source_tag = tag_map.getRouteSourceTag(fwd_route);

            if (isGraphInput(con)) {
                fwd_in_routes.push_back(fwd_route);
            } else if (isGraphOutput(con)) {
                fwd_out_routes.push_back(fwd_route);
            } else {
                fwd_routes.push_back(fwd_route);
            }

            logger->trace("Created route for forwarding: {} (batch={} loss={} con={})", toString(fwd_route),
                          val.isBatch(), val.isLoss(), toString(con));

            if (passedForBackward(val.getType())) {
                RouteDP bwd_route;
                bwd_route.location = con.value;
                bwd_route.sources = getGraphRanks(con.dest, allocation);
                bwd_route.source_graph = con.dest;
                bwd_route.dests = getGraphRanks(con.src, allocation);
                bwd_route.dest_graph = con.src;
                bwd_route.tag = tag;
                bwd_route.source_tag = tag_map.getRouteSourceTag(bwd_route);
                bwd_route.type = chooseRouteType(val.isBatch(), val.isLoss(), false);
                bwd_route.ir_value = val;

                if (isGraphInput(con)) {
                    bwd_out_routes.push_back(bwd_route);
                } else if (isGraphOutput(con)) {
                    bwd_in_routes.push_back(bwd_route);
                } else {
                    bwd_routes.push_back(bwd_route);
                }

                logger->trace("Created route for backwarding: {}", toString(bwd_route));
            }
        }

        // Order values for communication
        // Hopefully this ordering allows blocking communication among graphs
        deployment.fwd_routes = fwd_routes;
        deployment.fwd_in_routes = fwd_in_routes;
        deployment.fwd_out_routes = fwd_out_routes;
        deployment.fwd_graph_order = sortGraphs(deployment.subgraphs, fwd_routes);
        deployment.bwd_routes = bwd_routes;
        deployment.bwd_in_routes = bwd_in_routes;
        deployment.bwd_out_routes = bwd_out_routes;
        deployment.bwd_graph_order = sortGraphs(deployment.subgraphs, bwd_routes);
        deployment.pipeline_num = config::Config::get().getVal<int>(config::PIPELINE_NUM);

        for (const auto& r: deployment.fwd_in_routes) {
            logger->debug("fwd_in_routes: {}", toString(r));
        }
        for (const auto& r: deployment.fwd_routes) {
            logger->debug("fwd_routes: {}", toString(r));
        }
        for (const auto& r: deployment.fwd_out_routes) {
            logger->debug("fwd_out_routes: {}", toString(r));
        }
        logger->debug("fwd_graph_order: {}", join_as_str(deployment.fwd_graph_order));
        for (const auto& r: deployment.bwd_in_routes) {
            logger->debug("bwd_in_routes: {}", toString(r));
        }
        for (const auto& r: deployment.bwd_routes) {
            logger->debug("bwd_routes: {}", toString(r));
        }
        for (const auto& r: deployment.bwd_out_routes) {
            logger->debug("bwd_out_routes: {}", toString(r));
        }
        logger->debug("bwd_graph_order: {}", join_as_str(deployment.bwd_graph_order));

        logger->trace("createDeployment finished");

        return deployment;
    }

    template<typename F>
    std::unordered_map<std::string, std::unordered_map<std::string, std::unordered_set<int>>> getGraphValueRanks(const Deployment &deployment, F f) {
        std::unordered_map<std::string, std::unordered_map<std::string, std::unordered_set<int>>> results;

        for (const auto &it: deployment.subgraphs) {
            const auto &sg_name = it.first;
            const auto &subgraph = it.second;

            for (const auto &val: f(subgraph)) {
                auto &ranks = results[sg_name][val.getName()];
                for (const int r: deployment.allocation.at(sg_name)) {
                    ranks.insert(r);
                }
            }
        }
        return results;
    }

    std::unordered_map<std::string, std::unordered_map<std::string, std::unordered_set<int>>> getParamRanks(const Deployment &deployment) {
        return getGraphValueRanks(deployment, graphParamValues);
    }

    std::unordered_map<std::string, std::unordered_map<std::string, std::unordered_set<int>>> getConstantRanks(const Deployment &deployment) {
        return getGraphValueRanks(deployment, graphConstantValues);
    }

    std::vector<RouteDP> filterRoutes(const std::vector<RouteDP> &routes, int rank,
                                      std::function<std::vector<int>(const RouteDP &r)> &f) {
        std::vector<RouteDP> results;
        std::copy_if(routes.begin(), routes.end(), std::back_inserter(results),
                     [rank, &f](const RouteDP &r) {
                         return contains(f(r), rank);
                     });
        return results;
    }

    std::vector<RouteDP> filterRecvRoutes(const std::vector<RouteDP> &routes, int rank) {
        std::function<std::vector<int>(const RouteDP &r)> f = [](const RouteDP &r) { return r.dests; };
        return filterRoutes(routes, rank, f);
    }

    std::vector<RouteDP> filterSendRoutes(const std::vector<RouteDP> &routes, int rank) {
        std::function<std::vector<int>(const RouteDP &r)> f = [](const RouteDP &r) { return r.sources; };
        return filterRoutes(routes, rank, f);
    }

    std::vector<RouteDP> filterRoutesByGraph(const std::vector<RouteDP> &routes,
                                             const std::vector<std::string> &val_names) {

        std::vector<RouteDP> results;
        for (const auto &route: routes) {
            if (contains(val_names, route.location.value_name)) {
                results.push_back(route);
            }
        }
        return results;
    }

    std::vector<RouteDP> filterRoutesByGraphInputs(const std::vector<RouteDP> &routes,
                                                   const std::shared_ptr<IRGraph> &graph) {
        return filterRoutesByGraph(routes, graph->getInputNames());
    }

    std::vector<RouteDP> filterRoutesByGraphOutputs(const std::vector<RouteDP> &routes,
                                                    const std::shared_ptr<IRGraph> &graph) {
        return filterRoutesByGraph(routes, graph->getOutputNames());
    }

    std::unordered_map<std::string, GraphRoutes> getRoutesByGraph(
            const Deployment &deployment,
            const std::vector<std::shared_ptr<IRGraph>> &subgraphs,
            int rank) {

        std::unordered_map<std::string, GraphRoutes> results;

        for (const auto &subgraph: subgraphs) {
            GraphRoutes graph_routes;
            graph_routes.fwd_recv_routes = filterRoutesByGraphInputs(filterRecvRoutes(deployment.fwd_routes, rank), subgraph);
            graph_routes.fwd_send_routes = filterRoutesByGraphOutputs(filterSendRoutes(deployment.fwd_routes, rank), subgraph);
            graph_routes.bwd_recv_routes = filterRoutesByGraphOutputs(filterRecvRoutes(deployment.bwd_routes, rank), subgraph);
            graph_routes.bwd_send_routes = filterRoutesByGraphInputs(filterSendRoutes(deployment.bwd_routes, rank), subgraph);

            results[subgraph->getName()] = graph_routes;
        }

        return results;
    }

    UndirectedBGraph toUndirected(const BGraph &g) {
        UndirectedBGraph udg;
        copy_graph(g, udg);
        return udg;
    }

    std::string createComponentGraphId(const std::string &orig_name, int index) {
        std::stringstream ss;
        ss << orig_name << "_c" << index;
        return ss.str();
    }

    std::vector<BGraph> getConnectedComponents(const BGraph &g) {
        std::shared_ptr<std::vector<unsigned long>> mapping = std::make_shared<std::vector<unsigned long>>(
                num_vertices(g));
        UndirectedBGraph udg = toUndirected(g);
        size_t num = boost::connected_components(udg, mapping->data());

        std::vector<BGraph> component_graphs;

        for (size_t i = 0; i < num; i++) {
            ComponentGraph comp = {g,
                                   [mapping, i, &g](BGraph::edge_descriptor e) {
                                       return mapping->at(source(e, g)) == i || mapping->at(target(e, g)) == i;
                                   },
                                   [mapping, i](BGraph::vertex_descriptor v) {
                                       return mapping->at(v) == i;
                                   }};
            BGraph comp_g;
            copy_graph(comp, comp_g);
            comp_g[boost::graph_bundle].id = createComponentGraphId(g[boost::graph_bundle].id, i);
            component_graphs.emplace_back(comp_g);
        }

        return component_graphs;
    }

    std::string searchGraphWithValue(const std::unordered_map<std::string, std::shared_ptr<IRGraph>> &ir_graphs,
            const std::string &val_name) {
        for (const auto& it: ir_graphs) {
            const std::string& sg_id = it.first;
            const auto& g = it.second;
            if (g->hasValue(val_name)) {
                return sg_id;
            }
        }
        throw std::invalid_argument("No value found in graphs: " + val_name);
    }

    /**
     * Partition a graph according to VertexInfo::rank.
     *
     * @param g Graph to partition
     * @return Partition
     */
    Partition createPartition(const BGraph &g) {

        const auto logger = getLogger(LOGGER_NAME);
        logger->trace("createPartition started. id={}", g[boost::graph_bundle].id);

        std::vector<Vertex> topo_vertices = all_nodes_topo<Vertex, BGraph>(g);
        BDecomposition b_decomp = createSubGraphs(g);

        bool dump_graph = config::Config::get().getVal<bool>(config::DUMP_GRAPH);
        std::string dump_graph_prefix = config::Config::get().getVal<std::string>(config::DUMP_GRAPH_PREFIX);

        if (dump_graph) {
            std::ofstream file(dump_graph_prefix + "_r0.dot");
            boost::write_graphviz(file, g, vertex_rank_label_writer<BGraph>(g));
        }

        std::unordered_map<std::string, std::shared_ptr<IRGraph>> comp_graphs;
        std::unordered_map<std::string, std::unordered_map<std::string, std::shared_ptr<IRGraph>>> comp_graph_groups;

        for (const auto &it: b_decomp.graphs) {
            const std::string &subg_id = it.first;
            const BGraph &subg = it.second;

            if (dump_graph) {
                std::ofstream file1(subg_id + ".dot");
                boost::write_graphviz(file1, subg, vertex_rank_label_writer<BGraph>(subg));
            }

            comp_graphs[subg_id] = fromBGL(subg);
            comp_graph_groups[subg_id][subg_id] = fromBGL(subg);
        }
        // fix connections
//        spdlog::info("b_decomp.connections={}", b_decomp.connections.size());

        std::vector<GraphConnection> comp_connection;
        for (const auto& con: b_decomp.connections) {
//            spdlog::info("  con={}", toString(con));
            std::string comp_src = con.src;
            if (con.src != MASTER_NAME) {
                comp_src = searchGraphWithValue(comp_graph_groups[con.src], con.value);
            }
            std::string comp_dest = con.dest;
            if (con.dest != MASTER_NAME) {
                comp_dest = searchGraphWithValue(comp_graph_groups[con.dest], con.value);
            }

            GraphConnection comp_con = {con.value, comp_src, comp_dest, con.id, con.targetId};
            comp_connection.push_back(comp_con);
        }

        size_t cut_size = 0;
        for (const auto &con: b_decomp.connections) {
            const auto &n = find_value_node<Vertex, BGraph>(con.value, g);
            cut_size += g[n].value.getSizeInByte();
        }
        logger->trace("Cut size: {} (cut count={})", cut_size, b_decomp.connections.size());

        auto ret = Partition{g[boost::graph_bundle].id, fromBGL(g), comp_graphs, comp_connection, b_decomp.order};
        logger->trace("createPartition finished");

        return ret;
    }

    size_t getSizeInByte(const std::shared_ptr<IRGraph> &ir_graph) {
        size_t size = 0;

        for (const auto &v: ir_graph->getValues()) {
            size += v.second.getSizeInByte();
        }
        return size;
    }

    std::string toString(const GraphRoutes& routes) {
        std::stringstream ss;

        const auto& fwd_recv_routes = routes.fwd_recv_routes;
        ss << "Fwd recv routes (num=" << fwd_recv_routes.size() << ")" << std::endl;
        for (const auto &r: fwd_recv_routes) {
            ss << "  " << r << std::endl;
        }
        const auto& fwd_send_routes = routes.fwd_send_routes;
        ss << "Fwd send routes (num=" << fwd_send_routes.size() << ")" << std::endl;
        for (const auto &r: fwd_send_routes) {
            ss << "  " << r << std::endl;
        }

        const auto& bwd_recv_routes = routes.bwd_recv_routes;
        ss << "Bwd recv routes (num=" << bwd_recv_routes.size() << ")" << std::endl;
        for (const auto &r: bwd_recv_routes) {
            ss << "  " << r << std::endl;
        }

        const auto& bwd_send_routes = routes.bwd_send_routes;
        ss << "Bwd send routes (num=" << bwd_send_routes.size() << ")" << std::endl;
        for (const auto &r: bwd_send_routes) {
            ss << "  " << r << std::endl;
        }
        return ss.str();
    }

    std::unordered_map<int, IRType> getDistTensorType(const IRType& type, const std::unordered_set<int>& ranks,
                                                      int64_t batch_size) {
        const auto dp_dim = calcDistBatchDims(batch_size, type.getTensorDim(), ranks);

        std::unordered_map<int, IRType> ret;
        for (int r: ranks) {
            const auto dp_type = IRType::createTensorType(type.getTensorElemType(), dp_dim.at(r), type.requiresGrad());
            ret[r] = dp_type;
        }
        return ret;
    }

    IRType getDistType(const IRType& type, const std::unordered_set<int>& ranks, int64_t batch_size, int rank) {
        auto base_type = type.getBaseType();
        switch (base_type) {
            case IRBaseType::SCALAR: return type;
            case IRBaseType::TENSOR: {
                const auto& dim = type.getTensorDim();
                if (dim.empty()) { // maybe loss
                    return type;
                }
                return getDistTensorType(type, ranks, batch_size).at(rank);
            }
            case IRBaseType::LIST: {
                const auto list_type = type.getListType();
                if (list_type == IRListType::TENSOR) {
                    std::vector<IRType> tensor_types;
                    for (size_t i=0; i<type.getListSize(); i++) {
                        const auto dist_types = getDistTensorType(type.getCompoundTypes().at(i), ranks, batch_size);
                        tensor_types.push_back(dist_types.at(rank));
                    }
                    return IRType::createTensorListType(tensor_types);
                } else if (list_type == IRListType::GENERIC) {
                    std::vector<IRType> elem_types;
                    for (const auto& et: type.getCompoundTypes()) {
                        const auto dist_type = getDistType(et, ranks, batch_size, rank);
                        elem_types.push_back(dist_type);
                    }
                    return IRType::createListType(elem_types);
                }
                return type;
            }
            case IRBaseType::TUPLE: {
                std::vector<IRType> elem_types;
                for (const auto& et: type.getCompoundTypes()) {
                    const auto dist_type = getDistType(et, ranks, batch_size, rank);
                    elem_types.push_back(dist_type);
                }
                return IRType::createTupleType(elem_types);
            }
            case IRBaseType::STRING:
            case IRBaseType::NONE:
            case IRBaseType::OPTIONAL: {
                return type;
            }
        }
    }

    std::shared_ptr<IRGraph> scaleGraph(const std::shared_ptr<IRGraph>& graph, const std::string& name,
            int num, int index, int64_t batch_size) {
        std::vector<IRNode> nodes = graph->getNodes();

        std::unordered_set<int> dummy_ranks;
        for (int i=0; i<num; i++) {
            dummy_ranks.insert(i);
        }

        std::unordered_map<std::string, IRValue> values;
        for (auto& v: graph->getValues()) {
            const auto ir_val = v.second;
            if (ir_val.isBatch()) {
                const auto& type = ir_val.getType();
                const auto dp_type = getDistType(type, dummy_ranks, batch_size, index);

                IRValue batch_val(ir_val.getName(), dp_type);
                batch_val.setBatch(true);
                values[v.first] = batch_val;
            } else {
                values[v.first] = ir_val;
            }
        }

        return std::make_shared<IRGraph>(name, graph->getNodes(), values,
                                                 graph->getInputNames(), graph->getOutputNames());
    }

    std::shared_ptr<IRGraph> scaleGraph(const std::shared_ptr<IRGraph>& graph, int num, int64_t batch_size) {
        std::stringstream ss;
        ss << graph->getName() << "_dev_" << num;
        return scaleGraph(graph, ss.str(), num, 0, batch_size);
    }

    std::vector<std::shared_ptr<IRGraph>> replicateGraph(const std::shared_ptr<IRGraph>& graph, int num, int64_t batch_size) {
        std::vector<std::shared_ptr<IRGraph>> replicas;

        for (int i = 0; i < num; i++) {
            std::stringstream ss;
            ss << graph->getName() << "_dp" << i;
            auto replica = scaleGraph(graph, ss.str(), num, i, batch_size);
            replica->setReplicable(graph->isReplicable());

            replicas.push_back(replica);
        }
        return replicas;
    }

    PartitionDP replicate(const PartitionDP &partition, const std::unordered_map<std::string, int>& repl_nums,
            int64_t batch_size) {
        const auto logger = getLogger(LOGGER_NAME);

        PartitionDP rep_partition = partition;
        for (const auto& it: repl_nums) {
            assert(contains(rep_partition.subgraphs, it.first));
            const auto& g = rep_partition.subgraphs.at(it.first);
            int num = it.second;
            if (num > 1 && !g->isReplicable()) {
                logger->info("Graph {} is not replicable. Replication num {} is ignored.", it.first, it.second);
                num = 1;
            }

            auto replica = scaleGraph(g, g->getName(), num, 0, batch_size);
            replica->setReplicable(g->isReplicable());
            rep_partition.subgraphs[it.first] = replica;
        }
        rep_partition.replica_nums = repl_nums;
        return rep_partition;
    }

    bool isAllocFeasible(const std::unordered_map<int, size_t>& alloc_mem, size_t dev_mem) {

        for (const auto& it: alloc_mem) {
            if (dev_mem < it.second) {
                return false;
            }
        }
        return true;
    }

    struct AllocState {
        int dev;
        std::unordered_map<std::string, int> alloc;
        std::unordered_map<int, size_t> alloc_mem;

        size_t getMaxAllocMem() const {
            size_t max = 0;
            for (const auto& it: alloc_mem) {
                if (it.second > max) {
                    max = it.second;
                }
            }
            return max;
        }
    };

    bool hasReplica(const std::string& sg_name, int dev,
            const std::unordered_map<std::string, std::unordered_set<std::string>>& replications,
            const std::unordered_map<std::string, int>& alloc) {

        for (const auto& it: replications) {
            const auto& repl_set = it.second;
            if (contains(repl_set, sg_name)) {
                for (const auto& repl_id: repl_set) {
                    if (contains(alloc,repl_id)) {
                        if (alloc.at(repl_id) == dev) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

    std::unordered_map<std::string, int> doSearchAllocation(
            std::vector<std::string> sg_names,
            const std::unordered_map<std::string, std::unordered_set<std::string>>& replications,
            const std::unordered_map<std::string, int>& alloc,
            const std::unordered_map<int, size_t>& alloc_mem,
            const std::unordered_map<std::string, size_t>& graph_sizes,
            const std::vector<int>& devices, size_t dev_mem) {
        const auto logger = getLogger(LOGGER_NAME);

        if (!isAllocFeasible(alloc_mem, dev_mem)) {
            return std::unordered_map<std::string, int>();
        }
        if (sg_names.empty()) {
            return alloc;
        }

        const std::string sg_name = sg_names.back();
        sg_names.pop_back();

        std::vector<AllocState> alloc_states;
        for (int dev: devices) {
            if (hasReplica(sg_name, dev, replications, alloc)) {
                continue;
            }

            auto _alloc = alloc;
            auto _alloc_mem = alloc_mem;

            _alloc[sg_name] = dev;
            _alloc_mem[dev] += graph_sizes.at(sg_name);
            AllocState state = {dev, _alloc, _alloc_mem};
            alloc_states.push_back(state);
        }

        std::sort(alloc_states.begin(), alloc_states.end(), [](const AllocState& s1, const AllocState& s2) {
            return s1.getMaxAllocMem() < s2.getMaxAllocMem();
        });

        for (const auto& st: alloc_states) {
            const auto ret_alloc = doSearchAllocation(sg_names, replications, st.alloc, st.alloc_mem, graph_sizes, devices, dev_mem);
            if (!ret_alloc.empty()) {
                return ret_alloc;
            }
        }

        return std::unordered_map<std::string, int>();
    }

    std::unordered_map<std::string, std::unordered_set<int>> searchAllocation(
            const PartitionDP& partition,
            size_t dev_count, size_t dev_mem) {

        int repl_num = -1;
        for (const auto& it: partition.replica_nums) {
            repl_num = it.second;
        }

        std::unordered_map<std::string, std::unordered_set<int>> ret;
        int i=0;
        for (size_t repl_idx=0; repl_idx<repl_num; repl_idx++) {
            for (const auto& it: partition.subgraphs) {
                ret[it.first].insert(i%dev_count);
                i++;
            }
        }
        return ret;

//        std::unordered_map<std::string, int> alloc;
//        std::vector<std::string> sg_names = keys(partition.subgraphs);
//
//        std::unordered_map<int, size_t> alloc_mem;
//        for (size_t i=1; i<=dev_count; i++) {
//            alloc_mem[i] = 0;
//        }
//        std::unordered_map<std::string, size_t> graph_sizes;
//        for (const auto& sg: partition.subgraphs) {
//            graph_sizes[sg.first] = getSizeInByte(sg.second);
//        }
//
//        std::vector<int> devices;
//        for (size_t i=1; i<=dev_count; i++) {
//            devices.push_back(i);
//        }
//
//        return doSearchAllocation(sg_names, partition.replications, alloc, alloc_mem, graph_sizes, devices, dev_mem);
    }

    std::unordered_map<std::string, std::unordered_set<int>> searchAllocationFlat(
            const PartitionDP& partition,
            size_t dev_count, size_t dev_mem) {

        const auto repl_nums= values(partition.replica_nums);
        int common_repl_num = gcd(repl_nums);

        int dev_idx = 0;
        std::unordered_map<std::string, std::unordered_set<int>> ret;
        for (int i=0; i<common_repl_num; i++) {
            for (const auto &it: partition.replica_nums) {
                for (int j=0; j<(it.second/common_repl_num); j++) {
                    ret[it.first].insert(dev_idx);
                    dev_idx++;
                }
            }
        }

        return ret;
    }

    std::unordered_map<std::string, std::unordered_set<int>> searchAllocationSimple(
            const PartitionDP& partition,
            size_t dev_count, size_t dev_mem) {

        std::vector<std::string> sorted_gid = keys(partition.subgraphs);
        std::sort(sorted_gid.begin(), sorted_gid.end(), [&partition](const std::string& g1, const std::string& g2) {
            assert(contains(partition.replica_nums, g1));
            assert(contains(partition.replica_nums, g2));
            return partition.replica_nums.at(g1) > partition.replica_nums.at(g2);
        });

        std::unordered_map<std::string, std::unordered_set<int>> ret;
        int dev_idx = 0;
        for (const auto &gid: sorted_gid) {
            for (int i=0; i<partition.replica_nums.at(gid); i++) {
                ret[gid].insert(dev_idx);
                dev_idx++;
            }
        }

        return ret;
    }

        HGraph toHGraph(const PartitionDP& partition) {
        HGraph hg;
        std::unordered_map<std::string, HVertex> node_map;

        for (const auto& it: partition.subgraphs) {
            auto v = boost::add_vertex(hg);
            hg[v] = it.second;
            node_map[it.second->getName()] = v;
        }

        for (const auto& con: partition.connections) {
            assert(contains(node_map, con.src));
            assert(contains(node_map, con.dest));
            boost::add_edge(node_map.at(con.src), node_map.at(con.dest), hg);
        }

        return hg;
    }

    std::unordered_map<std::string, std::unordered_set<int>> searchAllocationFitToDevice(
            const PartitionDP& partition) {

        HGraph hg = toHGraph(partition);
        std::unordered_map<std::string, std::unordered_set<int>> ret;

        int graph_idx = 0;
        for (const auto& v: all_nodes_topo<HVertex, HGraph>(hg)) {
            const auto& sg = hg[v];
            assert(contains(partition.replica_nums, sg->getName()));
            int repl_num = partition.replica_nums.at(sg->getName());

            for (int i=0; i<repl_num; i++) {
                ret[sg->getName()].insert(i*partition.subgraphs.size() + graph_idx);
            }
            graph_idx++;
        }
        return ret;
    }

    // Fix ranks of nodes and values.
    // If a value is NOT a batch, replicates the value on the ranks of following ops.
    void fixNonBatchRanks(BGraph &g) {
        std::vector<Vertex> rev_topo_vertices;
        boost::topological_sort(g, std::back_inserter(rev_topo_vertices));

        // check nodes and values in a reversed topological sorted order
        for (auto &v: rev_topo_vertices) {
            if (g[v].type == VALUE) {
                if (g[v].value.isBatch()) {
//                    spdlog::info("Value {} {} is batch. ranks: {}", g[v].name, g[v].id,
//                                 join_as_str(g[v].ranks));
                    continue;
                }

                std::unordered_set<int> fixed_ranks;
                std::vector<Vertex> out_ops = target_nodes(v, g);
                for (auto &op: out_ops) {
                    for (int op_rank: g[op].ranks) {
                        fixed_ranks.insert(op_rank);
                    }
                }

//                spdlog::info("Value {} {} changed ranks: {} to {}", g[v].name, g[v].id,
//                        join_as_str(g[v].ranks),
//                             join_as_str(fixed_ranks));
                if (!fixed_ranks.empty()) {
                    g[v].ranks = fixed_ranks;
                }
            } else {
                if (g[v].node.isBatch()) {
//                    spdlog::info("Node {} {} is batch. ranks: {}", g[v].name, g[v].id,
//                                 join_as_str(g[v].ranks));
                    continue;
                }

                std::unordered_set<int> fixed_ranks;
                std::vector<Vertex> out_vals = target_nodes(v, g);
                std::vector<std::string> output_names;
                for (auto &val: out_vals) {
                    for (int val_rank: g[val].ranks) {
                        fixed_ranks.insert(val_rank);
                    }
                    output_names.push_back(g[val].name);
                }

//                spdlog::info("Node {} {} (out={}) changed ranks: {} to {}",
//                             g[v].name, g[v].id, join_as_str(output_names), join_as_str(g[v].ranks),
//                             join_as_str(fixed_ranks));

                if (!fixed_ranks.empty()) {
                    g[v].ranks = fixed_ranks;
                }
            }
        }
    }

    std::vector<size_t> splitByValueSizes(const BGraph& g, int n_partition) {

        std::vector<Vertex> topo_vertices, rev_topo_vertices;
        boost::topological_sort(g, std::back_inserter(rev_topo_vertices));

        boost::for_each(rev_topo_vertices | boost::adaptors::reversed, [&topo_vertices](Vertex v) {
            topo_vertices.push_back(v);
        });
        size_t total_size = 0;
        for (const auto& v: topo_vertices) {
            if (g[v].type == VALUE) {
                total_size += g[v].value.getSizeInByte();
            }
        }

        // initial decomposition
        size_t current_size = 0;
        size_t index = 0;
        std::vector<size_t> split_indices;
        for (const auto& v: topo_vertices) {
            if (g[v].type == VALUE) {
                current_size += g[v].value.getSizeInByte();
            }
            if (current_size > (total_size/n_partition)) {
                split_indices.push_back(index);
                current_size = 0;
            }
            index++;
        }
        split_indices.push_back(index);

        return split_indices;
    }

    void setRanksOnGraph(BGraph& g, const std::vector<size_t>& split) {
        std::vector<Vertex> topo_vertices, rev_topo_vertices;
        boost::topological_sort(g, std::back_inserter(rev_topo_vertices));

        boost::for_each(rev_topo_vertices | boost::adaptors::reversed, [&topo_vertices](Vertex v) {
            topo_vertices.push_back(v);
        });

        for (const auto& v: topo_vertices) {
            g[v].ranks.clear();
        }

        int rank = 0;
        size_t index = 0;
        for (const auto& v: topo_vertices) {
            if (split.size() > rank && index >= split.at(rank) && g[v].type == NODE) {
                rank++;
            }
            g[v].ranks.insert(rank);
            index++;

//            spdlog::info("@setRanksOnGraph {} ranks={}", g[v].name, join_as_str(g[v].ranks));
        }
    }

    BGraph copyGraphWithBatch(const BGraph& g) {
        BGraph copy_graph;
        std::unordered_map<std::string, Vertex> desc_map;

        copy_graph[boost::graph_bundle].id = g[boost::graph_bundle].id;
        for (const auto& v: all_nodes_topo<Vertex, BGraph>(g)) {
            if (g[v].type == VALUE) {
                if (g[v].value.isBatch() || g[v].value.isLoss()) {
                    const auto new_v = add_vertex(copy_graph);
                    desc_map[g[v].id] = new_v;
                    copy_graph[new_v] = g[v];
                }
            } else {
                if (g[v].node.isBatch() || g[v].node.isCriterion()) {
                    const auto new_v = add_vertex(copy_graph);
                    desc_map[g[v].id] = new_v;
                    copy_graph[new_v] = g[v];
                }
            }
        }

        typedef typename boost::graph_traits<BGraph>::out_edge_iterator out_edge_iterator;
        typedef typename boost::adjacency_iterator_generator<BGraph, Vertex, out_edge_iterator>::type adjacency_iterator;

        for (const auto& src: all_nodes_topo<Vertex, BGraph>(g)) {
            std::pair<adjacency_iterator, adjacency_iterator> iter_pair = boost::adjacent_vertices(src, g);
            for (auto first = iter_pair.first, last = iter_pair.second; first != last; ++first) {
                Vertex tgt = *first;
                if (contains(desc_map, g[src].id) && contains(desc_map, g[tgt].id)) {
                    boost::add_edge(desc_map.at(g[src].id), desc_map.at(g[tgt].id), copy_graph);
                }
            }
        }

        return copy_graph;
    }

    void verifyDeployment(const Deployment& deployment) {
        std::vector<RouteDP> fwd_routes;
        fwd_routes = addAll(fwd_routes, deployment.fwd_in_routes);
        fwd_routes = addAll(fwd_routes, deployment.fwd_routes);
        fwd_routes = addAll(fwd_routes, deployment.fwd_out_routes);
        std::vector<RouteDP> bwd_routes;
        bwd_routes = addAll(bwd_routes, deployment.bwd_in_routes);
        bwd_routes = addAll(bwd_routes, deployment.bwd_routes);
        bwd_routes = addAll(bwd_routes, deployment.bwd_out_routes);

        for (const auto& it: deployment.subgraphs) {
            const auto& graph_name = it.first;
            const auto& ir_graph = it.second;

            for (const auto& in_name: ir_graph->getInputNames()) {
                const auto& in_val = ir_graph->getValue(in_name);
                if (in_val.isParam()) {
                    continue;
                }

                bool used_fwd = false;
                for (const auto& r: fwd_routes) {
                    if (graph_name == r.dest_graph && r.ir_value.getName() == in_val.getName()) {
                        used_fwd = true;
                    }
                }
                if (!used_fwd) {
                    std::stringstream ss;
                    ss << "No fwd route for input: " << in_name << " in " << graph_name;
                    throw std::runtime_error(ss.str());
                }

                if (passedForBackward(in_val.getType())) {
                    bool used_bwd = false;
                    for (const auto &r: bwd_routes) {
                        if (graph_name == r.source_graph && r.ir_value.getName() == in_val.getName()) {
                            used_bwd = true;
                        }
                    }
                    if (!used_bwd) {
                        std::stringstream ss;
                        ss << "No bwd route for input: " << in_name << " in " << graph_name;
                        throw std::runtime_error(ss.str());
                    }
                }
            }

            for (const auto& out_name: ir_graph->getOutputNames()) {
                const auto& out_val = ir_graph->getValue(out_name);

                bool used_fwd = false;
                for (const auto& r: fwd_routes) {
                    if (graph_name == r.source_graph && r.ir_value.getName() == out_val.getName()) {
                        used_fwd = true;
                    }
                }
                if (!used_fwd) {
                    std::stringstream ss;
                    ss << "No fwd route for output: " << out_name << " in " << graph_name;
                    throw std::runtime_error(ss.str());
                }

                if (passedForBackward(out_val.getType())) {
                    bool used_bwd = false;
                    for (const auto &r: bwd_routes) {
                        if (graph_name == r.dest_graph && r.ir_value.getName() == out_val.getName()) {
                            used_bwd = true;
                        }
                    }
                    if (!used_bwd) {
                        std::stringstream ss;
                        ss << "No bwd route for output: " << out_name << " in " << graph_name;
                        throw std::runtime_error(ss.str());
                    }
                }
            }
        }
    }

}

max_stars_repo_name: lazykyama/rannc

max_issues_repo_name: lazykyama/rannc

max_forks_repo_name: lazykyama/rannc


text:
/*
Copyright 2010 KS Rajan, Mohammed Rashad KM

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

#include <boost/lexical_cast.hpp>
#include <iostream>
#include "drawshape.h"
#include <Wt/WCssDecorationStyle>
#include <Wt/WPainter>
#include<Wt/WPaintDevice>
#include <Wt/WPainterPath>
#include <Wt/WPointF>
#include <Wt/WRectF>
#include <Wt/WFont>
#include <Wt/WEvent>
#include<Wt/WSvgImage>
#include <Wt/WText>
#include <Wt/WApplication>
#include <cmath>
#include <iostream>
#include <fstream>
#include <Wt/WFileUpload>
#include <boost/lexical_cast.hpp>
#include <Wt/WRandom>
#include<string>
#include "attribute_table.h"
#include <vector>

using namespace std;
using namespace Wt;

using namespace boost;

#define MIN_POINT(x,y) (x < y ? x : y)
#define MAX_POINT(x,y) (x > y ? x : y)
#define INSIDE 0
#define OUTSIDE 1

struct LABELS
{
	double x;
	double y;
	string label;
};
void DrawShape::updatePaint(string clientfile,string spoolfile){
	cfile = clientfile;
	sfile = spoolfile;

	update();
}

DrawShape::DrawShape(int width, int height, WContainerWidget *parent): WPaintedWidget(parent)
{
	setSelectable(false);
	iwidth = 0.0015;
	x_pos_shift=0;
	y_pos_shift=0;
	increase_width=0;
	increase_height=0;
	labelpercentage=1;
	resize(WLength(width), WLength(height));
	select=false;

}
DrawShape::~DrawShape()
{

//	delete font;
//	delete text;
	if(!svgFile.empty()){
			string delfile="rm "+svgFile;
			int ret=system(delfile.c_str());}
}
void DrawShape::reset()
{
	x_pos_shift=0;
	y_pos_shift=0;
	increase_width=0;
	increase_height=0;
	labelindex=0;
}
void DrawShape::setPenWidth(int w)  {
	double cwidth = pen.width().value();
	//cout << cwidth << "VCCC" << w << "DDD" << endl;
	if(w > cwidth)
		iwidth = iwidth*3;
	else
		iwidth = iwidth/3;

	update();
}
void DrawShape::incrWidth() {
	iwidth = iwidth*3;

	update();
}
void DrawShape::decrWidth() {
	iwidth = iwidth/3;

	update();
}

void DrawShape::incrLabelWidth() {
	labelpercentage*=1.2;
	update();
}
void DrawShape::decrLabelWidth() {
	labelpercentage/=1.2;
	update();
}

void DrawShape::changeBorderColor(WColor color) {
	bordercolor= color;
	update();
}

void DrawShape::changeFillColor(WColor color) {
	fillcolor= color;
	update();
}
void DrawShape::paintondevice(WPaintDevice *p) {
	paintEvent(p);
}
void DrawShape::mouseMove(const WMouseEvent& e) {
	//cout << e.screen().x << ":::" << e.screen().y << endl;
	//string coords = boost::lexical_cast<string>(e.document().x) + "::" + boost::lexical_cast<string>(e.document().y);
	//text->setText(coords);
}

void DrawShape::paintEvent(WPaintDevice *paintDevice)
{
	if(!sfile.empty()) {
		paintMap(paintDevice);
	}

}
void DrawShape::paintMap(WPaintDevice *paintDevice)
{
	WPainter painter(paintDevice);
	painter.setRenderHint(WPainter::LowQualityShadows);
	painter.save();
	if(!sfile.empty()) {

		vector<LABELS> label_list;
		OGRDataSource       *poDS,*PointDS;
		string dfile = sfile  + ".shp";
		string shp = "g_4326/" + sfile + ".shp";
		poDS = OGRSFDriverRegistrar::Open(shp.c_str(), FALSE );  //comment till here

		if(poDS==NULL)
		{
			printf( "Open failed.\n" );
			exit( 1 );
		}
		OGRLayer  *poLayer;
		poLayer = poDS->GetLayerByName( sfile.c_str() ); // comment here
		OGRFeature *poFeature;
		OGREnvelope *   	 psExtent = new OGREnvelope();

		poLayer->GetExtent(psExtent);
		double xMin = psExtent->MinX;
		double yMin = psExtent->MinY;
		double xMax = psExtent->MaxX;
		double yMax = psExtent->MaxY;

		stringstream strm;
		strm << xMin;
		string exp;
		double scaleFactor;
		string bound_string = strm.str();
		int size = bound_string.size();
		size_t found=bound_string.find("+");
		if (found!=string::npos) {
			exp =  bound_string.substr(found+1,size);
		}

		if(exp.empty()) {

			stringstream strExtent;
			strExtent << yMin;
			bound_string = strExtent.str();
			size = bound_string.size();
			found = bound_string.find("+");
			if(found!=string::npos) {
				exp = bound_string.substr(found+1,size);
			}
		}
		if(exp.empty()) {
			stringstream strExtent;
			strExtent << xMax;
			bound_string = strExtent.str();
			size = bound_string.size();
			found = bound_string.find("+");
			if(found!=string::npos) {
				exp = bound_string.substr(found+1,size);
			}
		}
		if(exp.empty()) {
			stringstream strExtent;
			strExtent << yMax;
			bound_string = strExtent.str();
			size = bound_string.size();
			found = bound_string.find("+");
			if(found!=string::npos) {
				exp = bound_string.substr(found+1,size);
			}
		}
		//cout << "EXXP: " << exp << endl;
		if(!exp.empty()) {
			int exponent  = boost::lexical_cast<int>(exp);

			exponent-=3;
			scaleFactor = pow (10,exponent);
		}
		else
		{
			//cout << "EXXP is empty " << exp << endl;
			scaleFactor = 1;
		}

		xMin/=scaleFactor;
		xMax/=scaleFactor;
		yMin/=scaleFactor;
		yMax/=scaleFactor;

		double gWidth = xMax - xMin;
		double gHeight = yMax - yMin;
		double widthFactor = 1;
		double pwidth = abs(gWidth-gHeight);
		double s = gWidth - gHeight;
		if(s<0.16)
			gWidth = gHeight + 0.16;

		double ratio=gWidth/gHeight;
		//for zoom n pan
		if(increase_width<100 && increase_height<100){
			painter.setWindow(xMin +(-x_pos_shift+increase_width/2)/100*gWidth* widthFactor, yMax+(y_pos_shift-increase_height/2)/100*gHeight * widthFactor, gWidth* widthFactor*(100-increase_width)/100, gHeight * widthFactor*(-1+increase_height/100));

			brush.setStyle(SolidPattern);
			brush.setColor(backcolor);
			painter.setBrush(brush);
			painter.drawRect(xMin +(-x_pos_shift+increase_width/2)/100*gWidth* widthFactor, yMax+(y_pos_shift-increase_height/2)/100*gHeight * widthFactor, gWidth* widthFactor*(100-increase_width)/100, gHeight * widthFactor*(-1+increase_height/100));
}
		else{
			painter.setWindow(xMin +x_pos_shift, yMax-y_pos_shift, 0, 0);
}

		// for normal picture

		//painter.setWindow(xMin , yMax, gWidth* widthFactor, -gHeight * widthFactor);
		pwidth/=480;
		pwidth*=4;
		//if(iwidth<0.06)
		//		iwidth=0.06;
		if(iwidth == 0.0015){
			pen.setWidth(pwidth);
		}
		else
		{
			pen.setWidth(iwidth);
		}

		//std::cerr<<pwidth<<" "<<iwidth<<"\n";
		pen.setColor(bordercolor);
		brush.setStyle(SolidPattern);
		brush.setColor(fillcolor);
		font= new WFont();
		font->setSize(WLength(labelpercentage*gWidth*widthFactor));
		painter.setFont(*font);
		painter.setPen(pen);
		painter.setBrush(brush);
		WPainterPath path;
		poLayer->ResetReading();

		OGRPoint *centroid = new OGRPoint();
		char label[100];
		while( (poFeature = poLayer->GetNextFeature()) != NULL )
		{
			centroid->empty();
			label[0]=0;
			if(labelindex>0)
			{
				OGRFeatureDefn *PointFDefn = poLayer->GetLayerDefn();
				OGRFieldDefn *PointFieldDefn = PointFDefn->GetFieldDefn(labelindex-1);
				if( PointFieldDefn->GetType() == OFTInteger )
					sprintf(label, "%d", poFeature->GetFieldAsInteger(labelindex-1) );
				else if( PointFieldDefn->GetType() == OFTReal )
					sprintf(label, "%.3f", poFeature->GetFieldAsDouble(labelindex-1) );
				else if( PointFieldDefn->GetType() == OFTString )
					sprintf(label, "%s", poFeature->GetFieldAsString(labelindex-1) );
				else
					sprintf(label, "%s", poFeature->GetFieldAsString(labelindex-1) );
			}
			OGRGeometry *poGeometry;

			poGeometry = poFeature->GetGeometryRef();

			if( poGeometry != NULL && wkbFlatten(poGeometry->getGeometryType()) == wkbPoint )
			{
				OGRPoint *poPoint = (OGRPoint *) poGeometry;
				double x = poPoint->getX();
				double y = poPoint->getY();
				//painter.drawPoint(x/scaleFactor,y/scaleFactor);
				painter.drawEllipse(x/scaleFactor-0.005*gWidth*widthFactor,y/scaleFactor-0.005*gWidth*widthFactor,0.01*gWidth*widthFactor,0.01*gWidth*widthFactor);
				poGeometry->Centroid(centroid);

			} //end wkbpoint

			else if( poGeometry != NULL  && wkbFlatten(poGeometry->getGeometryType()) == wkbLineString  )
			{
				OGRLineString *poPoint = (OGRLineString *) poGeometry;

				for(int i=0;i<poPoint->getNumPoints();i++)
				{
					double x=poPoint->getX(i) ;
					double y = poPoint->getY(i);
					x/=scaleFactor; y/=scaleFactor;

					if(i==0)
						path = WPainterPath( WPointF(x, y));
					else
						path.lineTo( x , y);
				}

				painter.drawPath(path);
				poGeometry->Centroid(centroid);
			}

			else if( (poGeometry != NULL)  &&  wkbFlatten(poGeometry->getGeometryType()) == wkbPolygon)
			{
				OGRPolygon *poPoint = (OGRPolygon *) poGeometry;
				OGRLinearRing *extring = poPoint->getExteriorRing();

				int n = extring->getNumPoints();
				double x, y;
				for(int i=0;i<n;i++)
				{
					x = extring->getX(i);   y = extring->getY(i);
					x/=scaleFactor; y/=scaleFactor;
					if(i==0)
						path = WPainterPath( WPointF(x , y));

					else
						path.lineTo( x , y);
				}
				painter.drawPath(path);
				poGeometry->Centroid(centroid);

			}
			else if( (poGeometry != NULL)  &&  wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon)
			{
				double x, y;
				OGRMultiPolygon *poPoint = (OGRMultiPolygon *) poGeometry;
				int p = poPoint->getNumGeometries();
				for(int k=0;k<p;k++) {
					OGRGeometry* geom = poPoint->getGeometryRef(k);
					OGRPolygon *poly = (OGRPolygon *) geom;
					OGRLinearRing  *ring = poly->getExteriorRing();

					for(int i=0;i<ring->getNumPoints();i++)
					{
						x = ring->getX(i);   y = ring->getY(i);
						x/=scaleFactor; y/=scaleFactor;
						if(i==0)
							path = WPainterPath( WPointF(x , y));
						else
							path.lineTo( x , y);

					}
					painter.drawPath(path);
					poGeometry->Centroid(centroid);

				}

			}
			if(labelindex>0 && !centroid->IsEmpty()){
				LABELS l={centroid->getX(),centroid->getY(),label};
				label_list.push_back(l);
			}
		}
		painter.restore();

		//labelling the contents
if(increase_width<100 && increase_height<100){
		painter.setWindow(0.0, 0.0, (paintDevice->width()).value(),(paintDevice->height()).value());
		font= new WFont(WFont::SansSerif);
		font->setSize(WLength(10*labelpercentage));
		painter.setFont(*font);
		pen.setColor(labelcolor);
		painter.setPen(pen);
		std::vector<LABELS>::iterator the_iterator = label_list.begin();
		double x, y, minx=(xMin+(-x_pos_shift+increase_width/2)/100*gWidth* widthFactor),miny=(yMax+(y_pos_shift-increase_height/2)/100*gHeight*widthFactor);

		double multx=(paintDevice->width().value())/(gWidth* widthFactor*(100-increase_width)/100);
		double multy=(paintDevice->height().value())/(gHeight*widthFactor*(-1+increase_height/100));

		while( the_iterator != label_list.end() ) {

		x=((*the_iterator).x/scaleFactor-minx)*multx;
		y=((*the_iterator).y/scaleFactor-miny)*multy;

		painter.drawText(WRectF( x-(*the_iterator).label.size()*5*labelpercentage, y-5*labelpercentage, (*the_iterator).label.size()	*10*labelpercentage,10*labelpercentage),AlignCenter,(*the_iterator).label);
			++the_iterator;
		}
		pen.setColor(red);
		painter.setPen(pen);
		painter.setFont(*font);
		//painter.drawText(WRectF(paintDevice->width().value()-dfile.size()*10*labelpercentage,paintDevice->height().value()-10*labelpercentage*(paintDevice->height()).value(), dfile.size()*10*labelpercentage,10*labelpercentage ),AlignCenter,dfile); //this text is not seen in the picture when painted.
}
	}

}

void DrawShape::featuredetect(int XPoint,int YPoint)
{
	if(!sfile.empty() && XPoint>=(x_pos_shift-increase_width/2)*6.40 && XPoint<=(x_pos_shift-increase_width/2)*6.40+(100+increase_width)*6.4 && YPoint>=(y_pos_shift-increase_height/2)*4.8 && YPoint<=(y_pos_shift-increase_height/2)*4.8+(100+increase_height)*4.8 )//check if point is inside the view area
	{

		OGRDataSource       *poDS;
		string dfile = sfile  + ".shp";
		string shp = "g_4326/" + sfile + ".shp";
		poDS = OGRSFDriverRegistrar::Open(shp.c_str(), FALSE );  //comment till here
		if( poDS == NULL )
		{
			WApplication::instance()->doJavaScript("alert('Open failed')");
			cout << "Open failed";
		}
		OGRLayer  *poLayer;
		poLayer = poDS->GetLayerByName( sfile.c_str() ); // comment here
		OGRFeature *poFeature;
		OGREnvelope *   	 psExtent = new OGREnvelope();
		poLayer->GetExtent(psExtent);

		double xMin = psExtent->MinX;
		double yMin = psExtent->MinY;
		double xMax = psExtent->MaxX;
		double yMax = psExtent->MaxY;

		stringstream strm;
		strm << xMin;
		string exp;
		double scaleFactor;
		string bound_string = strm.str();
		int size = bound_string.size();
		size_t found=bound_string.find("+");
		if (found!=string::npos) {
			exp =  bound_string.substr(found+1,size);
		}

		if(exp.empty()) {

			stringstream strExtent;
			strExtent << yMin;
			bound_string = strExtent.str();
			size = bound_string.size();
			found = bound_string.find("+");
			if(found!=string::npos) {
				exp = bound_string.substr(found+1,size);
			}
		}
		if(exp.empty()) {
			stringstream strExtent;
			strExtent << xMax;
			bound_string = strExtent.str();
			size = bound_string.size();
			found = bound_string.find("+");
			if(found!=string::npos) {
				exp = bound_string.substr(found+1,size);
			}
		}
		if(exp.empty()) {
			stringstream strExtent;
			strExtent << yMax;
			bound_string = strExtent.str();
			size = bound_string.size();
			found = bound_string.find("+");
			if(found!=string::npos) {
				exp = bound_string.substr(found+1,size);
			}
		}
		if(!exp.empty()) {
			int exponent  = boost::lexical_cast<int>(exp);

			exponent-=3;
			scaleFactor = pow (10,exponent);
		}
		else
		{
			scaleFactor = 1;
		}

		xMin/=scaleFactor;
		xMax/=scaleFactor;
		yMin/=scaleFactor;
		yMax/=scaleFactor;

		double gWidth = xMax - xMin;
		double gHeight = yMax - yMin;
		double widthFactor = 1;
		double pwidth = abs(gWidth-gHeight);
		double s = gWidth - gHeight;
		if(s<0.16)
			gWidth = gHeight + 0.16;

		double scaledX=(XPoint*(gWidth* widthFactor*(100-increase_width)/100)/640 + (xMin+(-x_pos_shift+increase_width/2)/100*gWidth* widthFactor))*scaleFactor;
		double scaledY=(YPoint*(gHeight*widthFactor*(-1+increase_height/100))/480 + (yMax+(y_pos_shift-increase_height/2)/100*gHeight*widthFactor))*scaleFactor;
		OGRPoint *poPoint =new OGRPoint();
		poPoint->setX(scaledX);
		poPoint->setY(scaledY);

		poLayer->ResetReading();

		int index=0;bool flagFeature=false;

		while( (poFeature = poLayer->GetNextFeature()) != NULL )
		{

			OGRGeometry *poGeometry;
			poGeometry = poFeature->GetGeometryRef();
			if(poGeometry->Distance(poPoint)/scaleFactor<=0.01*gWidth*widthFactor)
				{
					flagFeature=true;
					//std::cerr<<index<<" " <<flagFeature<<" "<<poGeometry->Distance(poPoint);
					break;
				}
			index++;
		}
		if(flagFeature)
			DBFDialog *attrtable =new DBFDialog(cfile,sfile,flagFeature,index);

	}
}

max_stars_repo_name: LSI-IIIT/lsiviewer

max_issues_repo_name: LSI-IIIT/lsiviewer

max_forks_repo_name: LSI-IIIT/lsiviewer


text:
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/beast
//

#ifndef BOOST_BEAST_CORE_IMPL_FLAT_STREAM_HPP
#define BOOST_BEAST_CORE_IMPL_FLAT_STREAM_HPP

#include <boost/asio/buffer.hpp>
#include <boost/beast/core/async_base.hpp>
#include <boost/beast/core/buffers_prefix.hpp>
#include <boost/beast/core/static_buffer.hpp>
#include <boost/beast/core/stream_traits.hpp>
#include <boost/beast/websocket/teardown.hpp>
#include <memory>

namespace boost {
namespace beast {

template <class NextLayer> struct flat_stream<NextLayer>::ops {

  template <class Handler>
  class write_op
      : public async_base<Handler, beast::executor_type<flat_stream>> {
  public:
    template <class ConstBufferSequence, class Handler_>
    write_op(Handler_ &&h, flat_stream<NextLayer> &s,
             ConstBufferSequence const &b)
        : async_base<Handler, beast::executor_type<flat_stream>>(
              std::forward<Handler_>(h), s.get_executor()) {
      auto const result = flatten(b, max_size);
      if (result.flatten) {
        s.buffer_.clear();
        s.buffer_.commit(
            net::buffer_copy(s.buffer_.prepare(result.size), b, result.size));
        s.stream_.async_write_some(s.buffer_.data(), std::move(*this));
      } else {
        s.buffer_.clear();
        s.buffer_.shrink_to_fit();
        s.stream_.async_write_some(beast::buffers_prefix(result.size, b),
                                   std::move(*this));
      }
    }

    void operator()(boost::system::error_code ec,
                    std::size_t bytes_transferred) {
      this->complete_now(ec, bytes_transferred);
    }
  };

  struct run_write_op {
    template <class WriteHandler, class Buffers>
    void operator()(WriteHandler &&h, flat_stream *s, Buffers const &b) {
      // If you get an error on the following line it means
      // that your handler does not meet the documented type
      // requirements for the handler.

      static_assert(
          beast::detail::is_invocable<WriteHandler,
                                      void(error_code, std::size_t)>::value,
          "WriteHandler type requirements not met");

      write_op<typename std::decay<WriteHandler>::type>(
          std::forward<WriteHandler>(h), *s, b);
    }
  };
};

//------------------------------------------------------------------------------

template <class NextLayer>
template <class... Args>
flat_stream<NextLayer>::flat_stream(Args &&... args)
    : stream_(std::forward<Args>(args)...) {}

template <class NextLayer>
template <class MutableBufferSequence>
std::size_t
flat_stream<NextLayer>::read_some(MutableBufferSequence const &buffers) {
  static_assert(boost::beast::is_sync_read_stream<next_layer_type>::value,
                "SyncReadStream type requirements not met");
  static_assert(net::is_mutable_buffer_sequence<MutableBufferSequence>::value,
                "MutableBufferSequence type requirements not met");
  error_code ec;
  auto n = read_some(buffers, ec);
  if (ec)
    BOOST_THROW_EXCEPTION(boost::system::system_error{ec});
  return n;
}

template <class NextLayer>
template <class MutableBufferSequence>
std::size_t
flat_stream<NextLayer>::read_some(MutableBufferSequence const &buffers,
                                  error_code &ec) {
  static_assert(boost::beast::is_sync_read_stream<next_layer_type>::value,
                "SyncReadStream type requirements not met");
  static_assert(net::is_mutable_buffer_sequence<MutableBufferSequence>::value,
                "MutableBufferSequence type requirements not met");
  return stream_.read_some(buffers, ec);
}

template <class NextLayer>
template <class MutableBufferSequence, class ReadHandler>
BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
flat_stream<NextLayer>::async_read_some(MutableBufferSequence const &buffers,
                                        ReadHandler &&handler) {
  static_assert(boost::beast::is_async_read_stream<next_layer_type>::value,
                "AsyncReadStream type requirements not met");
  static_assert(net::is_mutable_buffer_sequence<MutableBufferSequence>::value,
                "MutableBufferSequence type requirements not met");
  return stream_.async_read_some(buffers, std::forward<ReadHandler>(handler));
}

template <class NextLayer>
template <class ConstBufferSequence>
std::size_t
flat_stream<NextLayer>::write_some(ConstBufferSequence const &buffers) {
  static_assert(boost::beast::is_sync_write_stream<next_layer_type>::value,
                "SyncWriteStream type requirements not met");
  static_assert(net::is_const_buffer_sequence<ConstBufferSequence>::value,
                "ConstBufferSequence type requirements not met");
  error_code ec;
  auto n = write_some(buffers, ec);
  if (ec)
    BOOST_THROW_EXCEPTION(boost::system::system_error{ec});
  return n;
}

template <class NextLayer>
template <class ConstBufferSequence>
std::size_t flat_stream<NextLayer>::stack_write_some(
    std::size_t size, ConstBufferSequence const &buffers, error_code &ec) {
  static_buffer<max_stack> b;
  b.commit(net::buffer_copy(b.prepare(size), buffers));
  return stream_.write_some(b.data(), ec);
}

template <class NextLayer>
template <class ConstBufferSequence>
std::size_t
flat_stream<NextLayer>::write_some(ConstBufferSequence const &buffers,
                                   error_code &ec) {
  static_assert(boost::beast::is_sync_write_stream<next_layer_type>::value,
                "SyncWriteStream type requirements not met");
  static_assert(net::is_const_buffer_sequence<ConstBufferSequence>::value,
                "ConstBufferSequence type requirements not met");
  auto const result = flatten(buffers, max_size);
  if (result.flatten) {
    if (result.size <= max_stack)
      return stack_write_some(result.size, buffers, ec);

    buffer_.clear();
    buffer_.commit(net::buffer_copy(buffer_.prepare(result.size), buffers));
    return stream_.write_some(buffer_.data(), ec);
  }
  buffer_.clear();
  buffer_.shrink_to_fit();
  return stream_.write_some(boost::beast::buffers_prefix(result.size, buffers),
                            ec);
}

template <class NextLayer>
template <class ConstBufferSequence, class WriteHandler>
BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
flat_stream<NextLayer>::async_write_some(ConstBufferSequence const &buffers,
                                         WriteHandler &&handler) {
  static_assert(boost::beast::is_async_write_stream<next_layer_type>::value,
                "AsyncWriteStream type requirements not met");
  static_assert(net::is_const_buffer_sequence<ConstBufferSequence>::value,
                "ConstBufferSequence type requirements not met");
  return net::async_initiate<WriteHandler, void(error_code, std::size_t)>(
      typename ops::run_write_op{}, handler, this, buffers);
}

template <class NextLayer>
void teardown(boost::beast::role_type role, flat_stream<NextLayer> &s,
              error_code &ec) {
  using boost::beast::websocket::teardown;
  teardown(role, s.next_layer(), ec);
}

template <class NextLayer, class TeardownHandler>
void async_teardown(boost::beast::role_type role, flat_stream<NextLayer> &s,
                    TeardownHandler &&handler) {
  using boost::beast::websocket::async_teardown;
  async_teardown(role, s.next_layer(), std::move(handler));
}

} // namespace beast
} // namespace boost

#endif

max_stars_repo_name: henrywarhurst/matrix

max_issues_repo_name: henrywarhurst/matrix

max_forks_repo_name: henrywarhurst/matrix