<commit_before>#include "../../SDP_Solver.hxx"
#include "../../../Timers.hxx"

// The main solver loop
// PROFILING : Using the somewhat weird convention to put timings outside the
//             function. Its just simpler to see this way what's timed and
//             what's not

void block_tensor_inv_transpose_congruence_with_cholesky(
  const Block_Diagonal_Matrix &L, const std::vector<Matrix> &Q,
  std::vector<Matrix> &Work, Block_Diagonal_Matrix &Result);

void block_tensor_transpose_congruence(const Block_Diagonal_Matrix &A,
                                       const std::vector<Matrix> &Q,
                                       std::vector<Matrix> &Work,
                                       Block_Diagonal_Matrix &Result);

void compute_dual_residues(const SDP &sdp, const Vector &y,
                           const Block_Diagonal_Matrix &bilinear_pairings_Y,
                           Vector &dual_residues);

void compute_primal_residues(const SDP &sdp, const Vector x,
                             const Block_Diagonal_Matrix &X,
                             Block_Diagonal_Matrix &primal_residues);

Real predictor_centering_parameter(const SDP_Solver_Parameters &parameters,
                                   const bool is_primal_dual_feasible);

Real corrector_centering_parameter(const SDP_Solver_Parameters &parameters,
                                   const Block_Diagonal_Matrix &X,
                                   const Block_Diagonal_Matrix &dX,
                                   const Block_Diagonal_Matrix &Y,
                                   const Block_Diagonal_Matrix &dY,
                                   const Real &mu,
                                   const bool is_primal_dual_feasible);

Real step_length(Block_Diagonal_Matrix &MCholesky, Block_Diagonal_Matrix &dM,
                 Block_Diagonal_Matrix &MInvDM,
                 std::vector<Vector> &eigenvalues,
                 std::vector<Vector> &workspace, const Real gamma);

SDP_Solver_Terminate_Reason
SDP_Solver::run(const boost::filesystem::path checkpoint_file)
{
  Real primal_step_length(0);
  Real dual_step_length(0);

  // the Cholesky decompositions of X and Y, each lower-triangular
  // BlockDiagonalMatrices with the same block sizes as X and Y
  Block_Diagonal_Matrix X_cholesky(X);
  Block_Diagonal_Matrix Y_cholesky(X);

  // Bilinear pairings needed for computing the Schur complement
  // matrix.  For example,
  //
  //   BilinearPairingsXInv.blocks[b].elt(
  //     (d_j+1) s + k1,
  //     (d_j+1) r + k2
  //   ) = v_{b,k1}^T (X.blocks[b]^{-1})^{(s,r)} v_{b,k2}
  //
  //     0 <= k1,k2 <= sdp.degrees[j] = d_j
  //     0 <= s,r < sdp.dimensions[j] = m_j
  //
  // where j corresponds to b and M^{(s,r)} denotes the (s,r)-th
  // (d_j+1)x(d_j+1) block of M.
  //
  // BilinearPairingsXInv has one block for each block of X.  The
  // dimension of BilinearPairingsXInv.block[b] is (d_j+1)*m_j.  See
  // SDP.h for more information on d_j and m_j.
  //
  Block_Diagonal_Matrix bilinear_pairings_X_Inv(
    sdp.bilinear_pairing_block_dims());
  //
  // BilinearPairingsY is analogous to BilinearPairingsXInv, with
  // X^{-1} -> Y.
  //
  Block_Diagonal_Matrix bilinear_pairings_Y(bilinear_pairings_X_Inv);

  // Additional workspace variables used in step_length()
  Block_Diagonal_Matrix step_matrix_workspace(X);
  std::vector<Matrix> bilinear_pairings_workspace;
  std::vector<Vector> eigenvalues_workspace;
  std::vector<Vector> QR_workspace;
  for(unsigned int b = 0; b < sdp.bilinear_bases.size(); b++)
    {
      bilinear_pairings_workspace.emplace_back(
        X.blocks[b].rows, bilinear_pairings_X_Inv.blocks[b].cols);
      eigenvalues_workspace.emplace_back(X.blocks[b].rows);
      QR_workspace.emplace_back(3 * X.blocks[b].rows - 1);
    }

  print_header();

  for(int iteration = 1;; iteration++)
    {
      if(timers["Last checkpoint"].elapsed().wall
         >= parameters.checkpoint_interval * 1000000000LL)
        {
          save_checkpoint(checkpoint_file);
        }
      if(timers["Solver runtime"].elapsed().wall
         >= parameters.max_runtime * 1000000000LL)
        {
          return SDP_Solver_Terminate_Reason::MaxRuntimeExceeded;
        }

      timers["run.objectives"].resume();
      primal_objective
        = sdp.objective_const + dot_product(sdp.primal_objective, x);
      dual_objective
        = sdp.objective_const + dot_product(sdp.dual_objective, y);
      duality_gap
        = abs(primal_objective - dual_objective)
          / max(Real(abs(primal_objective) + abs(dual_objective)), Real(1));
      timers["run.objectives"].stop();

      timers["run.choleskyDecomposition(X,XCholesky)"].resume();
      cholesky_decomposition(X, X_cholesky);
      timers["run.choleskyDecomposition(X,XCholesky)"].stop();

      timers["run.choleskyDecomposition(Y,YCholesky)"].resume();
      cholesky_decomposition(Y, Y_cholesky);
      timers["run.choleskyDecomposition(Y,YCholesky)"].stop();

      // Compute the bilinear pairings BilinearPairingsXInv and
      // BilinearPairingsY needed for the dualResidues and the Schur
      // complement matrix
      timers["run.blockTensorInvTransposeCongruenceWithCholesky"].resume();
      block_tensor_inv_transpose_congruence_with_cholesky(
        X_cholesky, sdp.bilinear_bases, bilinear_pairings_workspace,
        bilinear_pairings_X_Inv);
      timers["run.blockTensorInvTransposeCongruenceWithCholesky"].stop();

      timers["run.blockTensorTransposeCongruence"].resume();
      block_tensor_transpose_congruence(Y, sdp.bilinear_bases,
                                        bilinear_pairings_workspace,
                                        bilinear_pairings_Y);
      timers["run.blockTensorTransposeCongruence"].stop();

      // dualResidues[p] = primalObjective[p] - Tr(A_p Y) - (FreeVarMatrix y)_p,
      timers["run.computeDualResidues"].resume();
      compute_dual_residues(sdp, y, bilinear_pairings_Y, dual_residues);
      dual_error = max_abs_vector(dual_residues);
      timers["run.computeDualResidues"].stop();

      timers["run.computePrimalResidues"].resume();
      // PrimalResidues = \sum_p A_p x[p] - X
      compute_primal_residues(sdp, x, X, primal_residues);
      primal_error = primal_residues.max_abs();
      timers["run.computePrimalResidues"].stop();

      const bool is_primal_feasible
        = primal_error < parameters.primal_error_threshold;
      const bool is_dual_feasible
        = dual_error < parameters.dual_error_threshold;
      const bool is_optimal = duality_gap < parameters.duality_gap_threshold;

      if(is_primal_feasible && is_dual_feasible && is_optimal)
        return SDP_Solver_Terminate_Reason::PrimalDualOptimal;
      else if(is_primal_feasible && parameters.find_primal_feasible)
        return SDP_Solver_Terminate_Reason::PrimalFeasible;
      else if(is_dual_feasible && parameters.find_dual_feasible)
        return SDP_Solver_Terminate_Reason::DualFeasible;
      else if(primal_step_length == 1
              && parameters.detect_primal_feasible_jump)
        return SDP_Solver_Terminate_Reason::PrimalFeasibleJumpDetected;
      else if(dual_step_length == 1 && parameters.detect_dual_feasible_jump)
        return SDP_Solver_Terminate_Reason::DualFeasibleJumpDetected;
      else if(iteration > parameters.max_iterations)
        return SDP_Solver_Terminate_Reason::MaxIterationsExceeded;

      // Compute SchurComplement and prepare to solve the Schur
      // complement equation for dx, dy
      timers["run.initializeSchurComplementSolver"].resume();
      initialize_schur_complement_solver(bilinear_pairings_X_Inv,
                                         bilinear_pairings_Y);
      timers["run.initializeSchurComplementSolver"].stop();

      // Compute the complementarity mu = Tr(X Y)/X.dim
      Real mu = frobenius_product_symmetric(X, Y) / X.dim;
      if(mu > parameters.max_complementarity)
        return SDP_Solver_Terminate_Reason::MaxComplementarityExceeded;

      // Compute the predictor solution for (dx, dX, dy, dY)
      Real beta_predictor = predictor_centering_parameter(
        parameters, is_primal_feasible && is_dual_feasible);
      timers["run.computeSearchDirection(betaPredictor)"].resume();
      compute_search_direction(X_cholesky, beta_predictor, mu, false);
      timers["run.computeSearchDirection(betaPredictor)"].stop();

      // Compute the corrector solution for (dx, dX, dy, dY)
      Real beta_corrector = corrector_centering_parameter(
        parameters, X, dX, Y, dY, mu, is_primal_feasible && is_dual_feasible);
      timers["run.computeSearchDirection(betaCorrector)"].resume();
      compute_search_direction(X_cholesky, beta_corrector, mu, true);
      timers["run.computeSearchDirection(betaCorrector)"].stop();

      // Compute step-lengths that preserve positive definiteness of X, Y
      timers["run.stepLength(XCholesky)"].resume();
      primal_step_length = step_length(X_cholesky, dX, step_matrix_workspace,
                                       eigenvalues_workspace, QR_workspace,
                                       parameters.step_length_reduction);
      timers["run.stepLength(XCholesky)"].stop();
      timers["run.stepLength(YCholesky)"].resume();
      dual_step_length = step_length(Y_cholesky, dY, step_matrix_workspace,
                                     eigenvalues_workspace, QR_workspace,
                                     parameters.step_length_reduction);
      timers["run.stepLength(YCholesky)"].stop();

      // If our problem is both dual-feasible and primal-feasible,
      // ensure we're following the true Newton direction.
      if(is_primal_feasible && is_dual_feasible)
        {
          primal_step_length = min(primal_step_length, dual_step_length);
          dual_step_length = primal_step_length;
        }

      print_iteration(iteration, mu, primal_step_length, dual_step_length,
                      beta_corrector);

      // Update the primal point (x, X) += primalStepLength*(dx, dX)
      add_scaled_vector(x, primal_step_length, dx);
      dX *= primal_step_length;
      X += dX;

      // Update the dual point (y, Y) += dualStepLength*(dy, dY)
      add_scaled_vector(y, dual_step_length, dy);
      dY *= dual_step_length;
      Y += dY;
    }

  // Never reached
  return SDP_Solver_Terminate_Reason::MaxIterationsExceeded;
}
<commit_msg>Formatting<commit_after>#include "../../SDP_Solver.hxx"
#include "../../../Timers.hxx"

// The main solver loop
// PROFILING : Using the somewhat weird convention to put timings outside the
//             function. Its just simpler to see this way what's timed and
//             what's not

void block_tensor_inv_transpose_congruence_with_cholesky(
  const Block_Diagonal_Matrix &L, const std::vector<Matrix> &Q,
  std::vector<Matrix> &Work, Block_Diagonal_Matrix &Result);

void block_tensor_transpose_congruence(const Block_Diagonal_Matrix &A,
                                       const std::vector<Matrix> &Q,
                                       std::vector<Matrix> &Work,
                                       Block_Diagonal_Matrix &Result);

void compute_dual_residues(const SDP &sdp, const Vector &y,
                           const Block_Diagonal_Matrix &bilinear_pairings_Y,
                           Vector &dual_residues);

void compute_primal_residues(const SDP &sdp, const Vector x,
                             const Block_Diagonal_Matrix &X,
                             Block_Diagonal_Matrix &primal_residues);

Real predictor_centering_parameter(const SDP_Solver_Parameters &parameters,
                                   const bool is_primal_dual_feasible);

Real corrector_centering_parameter(const SDP_Solver_Parameters &parameters,
                                   const Block_Diagonal_Matrix &X,
                                   const Block_Diagonal_Matrix &dX,
                                   const Block_Diagonal_Matrix &Y,
                                   const Block_Diagonal_Matrix &dY,
                                   const Real &mu,
                                   const bool is_primal_dual_feasible);

Real step_length(Block_Diagonal_Matrix &MCholesky, Block_Diagonal_Matrix &dM,
                 Block_Diagonal_Matrix &MInvDM,
                 std::vector<Vector> &eigenvalues,
                 std::vector<Vector> &workspace, const Real gamma);

SDP_Solver_Terminate_Reason
SDP_Solver::run(const boost::filesystem::path checkpoint_file)
{
  Real primal_step_length(0);
  Real dual_step_length(0);

  // the Cholesky decompositions of X and Y, each lower-triangular
  // BlockDiagonalMatrices with the same block sizes as X and Y
  Block_Diagonal_Matrix X_cholesky(X);
  Block_Diagonal_Matrix Y_cholesky(X);

  // Bilinear pairings needed for computing the Schur complement
  // matrix.  For example,
  //
  //   BilinearPairingsXInv.blocks[b].elt(
  //     (d_j+1) s + k1,
  //     (d_j+1) r + k2
  //   ) = v_{b,k1}^T (X.blocks[b]^{-1})^{(s,r)} v_{b,k2}
  //
  //     0 <= k1,k2 <= sdp.degrees[j] = d_j
  //     0 <= s,r < sdp.dimensions[j] = m_j
  //
  // where j corresponds to b and M^{(s,r)} denotes the (s,r)-th
  // (d_j+1)x(d_j+1) block of M.
  //
  // BilinearPairingsXInv has one block for each block of X.  The
  // dimension of BilinearPairingsXInv.block[b] is (d_j+1)*m_j.  See
  // SDP.h for more information on d_j and m_j.

  Block_Diagonal_Matrix bilinear_pairings_X_Inv(
    sdp.bilinear_pairing_block_dims());

  // BilinearPairingsY is analogous to BilinearPairingsXInv, with
  // X^{-1} -> Y.

  Block_Diagonal_Matrix bilinear_pairings_Y(bilinear_pairings_X_Inv);

  // Additional workspace variables used in step_length()
  Block_Diagonal_Matrix step_matrix_workspace(X);
  std::vector<Matrix> bilinear_pairings_workspace;
  std::vector<Vector> eigenvalues_workspace;
  std::vector<Vector> QR_workspace;
  for(unsigned int b = 0; b < sdp.bilinear_bases.size(); b++)
    {
      bilinear_pairings_workspace.emplace_back(
        X.blocks[b].rows, bilinear_pairings_X_Inv.blocks[b].cols);
      eigenvalues_workspace.emplace_back(X.blocks[b].rows);
      QR_workspace.emplace_back(3 * X.blocks[b].rows - 1);
    }

  print_header();

  for(int iteration = 1;; iteration++)
    {
      if(timers["Last checkpoint"].elapsed().wall
         >= parameters.checkpoint_interval * 1000000000LL)
        {
          save_checkpoint(checkpoint_file);
        }
      if(timers["Solver runtime"].elapsed().wall
         >= parameters.max_runtime * 1000000000LL)
        {
          return SDP_Solver_Terminate_Reason::MaxRuntimeExceeded;
        }

      timers["run.objectives"].resume();
      primal_objective
        = sdp.objective_const + dot_product(sdp.primal_objective, x);
      dual_objective
        = sdp.objective_const + dot_product(sdp.dual_objective, y);
      duality_gap
        = abs(primal_objective - dual_objective)
          / max(Real(abs(primal_objective) + abs(dual_objective)), Real(1));
      timers["run.objectives"].stop();

      timers["run.choleskyDecomposition(X,XCholesky)"].resume();
      cholesky_decomposition(X, X_cholesky);
      timers["run.choleskyDecomposition(X,XCholesky)"].stop();

      timers["run.choleskyDecomposition(Y,YCholesky)"].resume();
      cholesky_decomposition(Y, Y_cholesky);
      timers["run.choleskyDecomposition(Y,YCholesky)"].stop();

      // Compute the bilinear pairings BilinearPairingsXInv and
      // BilinearPairingsY needed for the dualResidues and the Schur
      // complement matrix
      timers["run.blockTensorInvTransposeCongruenceWithCholesky"].resume();
      block_tensor_inv_transpose_congruence_with_cholesky(
        X_cholesky, sdp.bilinear_bases, bilinear_pairings_workspace,
        bilinear_pairings_X_Inv);
      timers["run.blockTensorInvTransposeCongruenceWithCholesky"].stop();

      timers["run.blockTensorTransposeCongruence"].resume();
      block_tensor_transpose_congruence(Y, sdp.bilinear_bases,
                                        bilinear_pairings_workspace,
                                        bilinear_pairings_Y);
      timers["run.blockTensorTransposeCongruence"].stop();

      // dualResidues[p] = primalObjective[p] - Tr(A_p Y) - (FreeVarMatrix y)_p,
      timers["run.computeDualResidues"].resume();
      compute_dual_residues(sdp, y, bilinear_pairings_Y, dual_residues);
      dual_error = max_abs_vector(dual_residues);
      timers["run.computeDualResidues"].stop();

      timers["run.computePrimalResidues"].resume();
      // PrimalResidues = \sum_p A_p x[p] - X
      compute_primal_residues(sdp, x, X, primal_residues);
      primal_error = primal_residues.max_abs();
      timers["run.computePrimalResidues"].stop();

      const bool is_primal_feasible
        = primal_error < parameters.primal_error_threshold;
      const bool is_dual_feasible
        = dual_error < parameters.dual_error_threshold;
      const bool is_optimal = duality_gap < parameters.duality_gap_threshold;

      if(is_primal_feasible && is_dual_feasible && is_optimal)
        return SDP_Solver_Terminate_Reason::PrimalDualOptimal;
      else if(is_primal_feasible && parameters.find_primal_feasible)
        return SDP_Solver_Terminate_Reason::PrimalFeasible;
      else if(is_dual_feasible && parameters.find_dual_feasible)
        return SDP_Solver_Terminate_Reason::DualFeasible;
      else if(primal_step_length == 1
              && parameters.detect_primal_feasible_jump)
        return SDP_Solver_Terminate_Reason::PrimalFeasibleJumpDetected;
      else if(dual_step_length == 1 && parameters.detect_dual_feasible_jump)
        return SDP_Solver_Terminate_Reason::DualFeasibleJumpDetected;
      else if(iteration > parameters.max_iterations)
        return SDP_Solver_Terminate_Reason::MaxIterationsExceeded;

      // Compute SchurComplement and prepare to solve the Schur
      // complement equation for dx, dy
      timers["run.initializeSchurComplementSolver"].resume();
      initialize_schur_complement_solver(bilinear_pairings_X_Inv,
                                         bilinear_pairings_Y);
      timers["run.initializeSchurComplementSolver"].stop();

      // Compute the complementarity mu = Tr(X Y)/X.dim
      Real mu = frobenius_product_symmetric(X, Y) / X.dim;
      if(mu > parameters.max_complementarity)
        return SDP_Solver_Terminate_Reason::MaxComplementarityExceeded;

      // Compute the predictor solution for (dx, dX, dy, dY)
      Real beta_predictor = predictor_centering_parameter(
        parameters, is_primal_feasible && is_dual_feasible);
      timers["run.computeSearchDirection(betaPredictor)"].resume();
      compute_search_direction(X_cholesky, beta_predictor, mu, false);
      timers["run.computeSearchDirection(betaPredictor)"].stop();

      // Compute the corrector solution for (dx, dX, dy, dY)
      Real beta_corrector = corrector_centering_parameter(
        parameters, X, dX, Y, dY, mu, is_primal_feasible && is_dual_feasible);
      timers["run.computeSearchDirection(betaCorrector)"].resume();
      compute_search_direction(X_cholesky, beta_corrector, mu, true);
      timers["run.computeSearchDirection(betaCorrector)"].stop();

      // Compute step-lengths that preserve positive definiteness of X, Y
      timers["run.stepLength(XCholesky)"].resume();
      primal_step_length = step_length(X_cholesky, dX, step_matrix_workspace,
                                       eigenvalues_workspace, QR_workspace,
                                       parameters.step_length_reduction);
      timers["run.stepLength(XCholesky)"].stop();
      timers["run.stepLength(YCholesky)"].resume();
      dual_step_length = step_length(Y_cholesky, dY, step_matrix_workspace,
                                     eigenvalues_workspace, QR_workspace,
                                     parameters.step_length_reduction);
      timers["run.stepLength(YCholesky)"].stop();

      // If our problem is both dual-feasible and primal-feasible,
      // ensure we're following the true Newton direction.
      if(is_primal_feasible && is_dual_feasible)
        {
          primal_step_length = min(primal_step_length, dual_step_length);
          dual_step_length = primal_step_length;
        }

      print_iteration(iteration, mu, primal_step_length, dual_step_length,
                      beta_corrector);

      // Update the primal point (x, X) += primalStepLength*(dx, dX)
      add_scaled_vector(x, primal_step_length, dx);
      dX *= primal_step_length;
      X += dX;

      // Update the dual point (y, Y) += dualStepLength*(dy, dY)
      add_scaled_vector(y, dual_step_length, dy);
      dY *= dual_step_length;
      Y += dY;
    }

  // Never reached
  return SDP_Solver_Terminate_Reason::MaxIterationsExceeded;
}
<|endoftext|>


<commit_before>/*
  This is an example file shipped by 'Aleph - A Library for Exploring
  Persistent Homology'.

  This example demonstrates how to load a VTK structured grid from
  a file, convert it into a simplicial complex, and calculate its
  persistent homology.

  Demonstrated classes:

    - aleph::PersistenceDiagram
    - aleph::topology::Simplex
    - aleph::topology::SimplicialComplex
    - aleph::topology::VTKStructuredGridReader

  Demonstrated functions:

    - aleph::calculatePersistenceDiagrams
    - aleph::utilities::extension
    - Simplicial complex sorting (for filtrations)

  Original author: Bastian Rieck
*/

#include "persistenceDiagrams/PersistenceDiagram.hh"

#include "persistentHomology/Calculation.hh"

#include "topology/Simplex.hh"
#include "topology/SimplicialComplex.hh"

#include "topology/filtrations/Data.hh"

#include "topology/io/VTK.hh"

#include <functional>
#include <iostream>
#include <string>

#include <getopt.h>

void usage()
{
  std::cerr << "Usage: vtk [--superlevels] [--sublevels] FILE\n"
            << "\n"
            << "Calculates persistent homology of an input file. This program only\n"
            << "handles VTK files. The output is a persistence diagram and will be\n"
            << "written to STDOUT.\n\n"
            << "Flags:\n"
            << "  -S --superlevels: calculate superlevel sets\n"
            << "  -s --sublevels  : calculate sublevel sets\n"
            << "\n";
}

int main( int argc, char** argv )
{
  static option commandLineOptions[] =
  {
    { "superlevels", no_argument, nullptr, 'S' },
    { "sublevels"  , no_argument, nullptr, 's' },
    { nullptr      , 0          , nullptr,  0  }
  };

  bool calculateSuperlevelSets = false;

  int option = 0;
  while( ( option = getopt_long( argc, argv, "Ss", commandLineOptions, nullptr ) ) != -1 )
  {
    switch( option )
    {
    case 'S':
      calculateSuperlevelSets = true;
      break;
    case 's':
      calculateSuperlevelSets = false;
      break;
    default:
      break;
    }
  }

  if( ( argc - optind ) <= 0 )
  {
    usage();
    return -1;
  }

  std::string filename = argv[optind];

  // Since all data types in Aleph are templated, you need to decide
  // which types to use beforehand---or use more advanced constructs
  // like a type switch over a list of admissible types.
  using DataType           = double;
  using VertexType         = unsigned;
  using Simplex            = aleph::topology::Simplex<DataType, VertexType>;
  using SimplicialComplex  = aleph::topology::SimplicialComplex<Simplex>;

  // Select a functor for calculating the weights when reading
  // a simplicial complex.
  //
  // This is an optional argument for the main operator of the
  // structured grid reader class. It is used to determine the
  // weight of an edge.
  //
  // Since sublevel sets 'grow' from small to large weights, a
  // correct assignment uses the `max()` function. Analogously
  // the `min()` function is used for superlevel sets.
  //
  // If you do not specify this functor, sublevel sets will be
  // calculated by default.
  auto functor = calculateSuperlevelSets
               ? [] ( DataType a, DataType b ) { return std::min(a,b); }
               : [] ( DataType a, DataType b ) { return std::max(a,b); };

  std::cerr << "* Loading '" << filename << "'...";

  SimplicialComplex K;
  aleph::topology::io::VTKStructuredGridReader reader;

  reader( filename, K, functor );

  std::cerr << "finished\n";

  std::cerr << "* Calculating persistent homology...";

  // Sort superlevel sets from largest to smallest weight...
  if( calculateSuperlevelSets )
    K.sort( aleph::topology::filtrations::Data<Simplex, std::greater<DataType> >() );
  // ...and sublevel sets from smallest to largest.
  else
    K.sort( aleph::topology::filtrations::Data<Simplex, std::less<DataType> >() );

  auto persistenceDiagrams = aleph::calculatePersistenceDiagrams( K );

  std::cerr << "finished\n";

  for( auto&& D : persistenceDiagrams )
  {
    // Remove all features with a persistence of zero. This is not
    // strictly required but it helps unclutter the diagram.
    D.removeDiagonal();

    std::cout << D << "\n";
  }
}
<commit_msg>Fixed documentation of VTK processing example<commit_after>/*
  This is an example file shipped by 'Aleph - A Library for Exploring
  Persistent Homology'.

  This example demonstrates how to load a VTK structured grid from
  a file, convert it into a simplicial complex, and calculate its
  persistent homology.

  Demonstrated classes:

    - aleph::PersistenceDiagram
    - aleph::topology::Simplex
    - aleph::topology::SimplicialComplex
    - aleph::topology::io::VTKStructuredGridReader

  Demonstrated functions:

    - aleph::calculatePersistenceDiagrams
    - aleph::utilities::extension
    - Simplicial complex sorting (for filtrations)

  Original author: Bastian Rieck
*/

#include "persistenceDiagrams/PersistenceDiagram.hh"

#include "persistentHomology/Calculation.hh"

#include "topology/Simplex.hh"
#include "topology/SimplicialComplex.hh"

#include "topology/filtrations/Data.hh"

#include "topology/io/VTK.hh"

#include <functional>
#include <iostream>
#include <string>

#include <getopt.h>

void usage()
{
  std::cerr << "Usage: vtk [--superlevels] [--sublevels] FILE\n"
            << "\n"
            << "Calculates persistent homology of an input file. This program only\n"
            << "handles VTK files. The output is a persistence diagram and will be\n"
            << "written to STDOUT.\n\n"
            << "Flags:\n"
            << "  -S --superlevels: calculate superlevel sets\n"
            << "  -s --sublevels  : calculate sublevel sets\n"
            << "\n";
}

int main( int argc, char** argv )
{
  static option commandLineOptions[] =
  {
    { "superlevels", no_argument, nullptr, 'S' },
    { "sublevels"  , no_argument, nullptr, 's' },
    { nullptr      , 0          , nullptr,  0  }
  };

  bool calculateSuperlevelSets = false;

  int option = 0;
  while( ( option = getopt_long( argc, argv, "Ss", commandLineOptions, nullptr ) ) != -1 )
  {
    switch( option )
    {
    case 'S':
      calculateSuperlevelSets = true;
      break;
    case 's':
      calculateSuperlevelSets = false;
      break;
    default:
      break;
    }
  }

  if( ( argc - optind ) <= 0 )
  {
    usage();
    return -1;
  }

  std::string filename = argv[optind];

  // Since all data types in Aleph are templated, you need to decide
  // which types to use beforehand---or use more advanced constructs
  // like a type switch over a list of admissible types.
  using DataType           = double;
  using VertexType         = unsigned;
  using Simplex            = aleph::topology::Simplex<DataType, VertexType>;
  using SimplicialComplex  = aleph::topology::SimplicialComplex<Simplex>;

  // Select a functor for calculating the weights when reading
  // a simplicial complex.
  //
  // This is an optional argument for the main operator of the
  // structured grid reader class. It is used to determine the
  // weight of an edge.
  //
  // Since sublevel sets 'grow' from small to large weights, a
  // correct assignment uses the `max()` function. Analogously
  // the `min()` function is used for superlevel sets.
  //
  // If you do not specify this functor, sublevel sets will be
  // calculated by default.
  auto functor = calculateSuperlevelSets
               ? [] ( DataType a, DataType b ) { return std::min(a,b); }
               : [] ( DataType a, DataType b ) { return std::max(a,b); };

  std::cerr << "* Loading '" << filename << "'...";

  SimplicialComplex K;
  aleph::topology::io::VTKStructuredGridReader reader;

  reader( filename, K, functor );

  std::cerr << "finished\n";

  std::cerr << "* Calculating persistent homology...";

  // Sort superlevel sets from largest to smallest weight...
  if( calculateSuperlevelSets )
    K.sort( aleph::topology::filtrations::Data<Simplex, std::greater<DataType> >() );
  // ...and sublevel sets from smallest to largest.
  else
    K.sort( aleph::topology::filtrations::Data<Simplex, std::less<DataType> >() );

  auto persistenceDiagrams = aleph::calculatePersistenceDiagrams( K );

  std::cerr << "finished\n";

  for( auto&& D : persistenceDiagrams )
  {
    // Remove all features with a persistence of zero. This is not
    // strictly required but it helps unclutter the diagram.
    D.removeDiagonal();

    std::cout << D << "\n";
  }
}
<|endoftext|>


<commit_before>/*************************************************************************
 * Author: Mgumbo
 *
 * Date Completed: 24 February 2016
 *
 * Description: A driver program that creates a Calculator object
 *				and calls the object's start() method to begin
 *				user interaction with the program.
 **/

#include <iostream>
#include "Calculator.h"

/**
 * Runs the program.
 **/
int main()
{
	Calculator calc; //create the Calculator object
	calc.start(); //start the Calculator

	return 0;
} //end main<commit_msg>Updated file<commit_after>/*************************************************************************
 * Author: Mgumbo
 *
 * Date Completed: 24 February 2016
 *
 * Description: A driver program that creates a Calculator object
 *		and calls the object's start() method to begin
 *		user interaction with the program.
 **/

#include <iostream>
#include "Calculator.h"

/**
 * Runs the program.
 **/
int main()
{
	Calculator calc; //create the Calculator object
	calc.start(); //start the Calculator

	return 0;
} //end main
<|endoftext|>


<commit_before>// Ouzel by Elviss Strazdins

#ifndef OUZEL_SCENE_COMPONENT_HPP
#define OUZEL_SCENE_COMPONENT_HPP

#include <memory>
#include <vector>
#include "../math/Box.hpp"
#include "../math/Matrix.hpp"
#include "../math/Color.hpp"
#include "../math/Rect.hpp"
#include "../graphics/Texture.hpp"

namespace ouzel::scene
{
    class Actor;
    class Layer;

    class Component
    {
        friend Actor;
    public:
        Component() = default;
        virtual ~Component();

        Component(const Component&) = delete;
        Component& operator=(const Component&) = delete;

        Component(Component&&) = delete;
        Component& operator=(Component&&) = delete;

        virtual void draw(const math::Matrix<float, 4>& transformMatrix,
                          float opacity,
                          const math::Matrix<float, 4>& renderViewProjection,
                          bool wireframe);

        virtual const math::Box<float, 3>& getBoundingBox() const noexcept { return boundingBox; }
        virtual void setBoundingBox(const math::Box<float, 3>& newBoundingBox) { boundingBox = newBoundingBox; }

        virtual bool pointOn(const math::Vector<float, 2>& position) const;
        virtual bool shapeOverlaps(const std::vector<math::Vector<float, 2>>& edges) const;

        [[nodiscard]] auto isHidden() const noexcept { return hidden; }
        void setHidden(bool newHidden) { hidden = newHidden; }

        [[nodiscard]] auto getActor() const noexcept { return actor; }
        void removeFromActor();

    protected:
        virtual void setActor(Actor* newActor);
        virtual void setLayer(Layer* newLayer);
        virtual void updateTransform();

        math::Box<float, 3> boundingBox;
        bool hidden = false;

        Layer* layer = nullptr;
        Actor* actor = nullptr;
    };
}

#endif // OUZEL_SCENE_COMPONENT_HPP
<commit_msg>Make bounding box getter and setter non-virtual<commit_after>// Ouzel by Elviss Strazdins

#ifndef OUZEL_SCENE_COMPONENT_HPP
#define OUZEL_SCENE_COMPONENT_HPP

#include <memory>
#include <vector>
#include "../math/Box.hpp"
#include "../math/Matrix.hpp"
#include "../math/Color.hpp"
#include "../math/Rect.hpp"
#include "../graphics/Texture.hpp"

namespace ouzel::scene
{
    class Actor;
    class Layer;

    class Component
    {
        friend Actor;
    public:
        Component() = default;
        virtual ~Component();

        Component(const Component&) = delete;
        Component& operator=(const Component&) = delete;

        Component(Component&&) = delete;
        Component& operator=(Component&&) = delete;

        virtual void draw(const math::Matrix<float, 4>& transformMatrix,
                          float opacity,
                          const math::Matrix<float, 4>& renderViewProjection,
                          bool wireframe);

        const auto& getBoundingBox() const noexcept { return boundingBox; }
        void setBoundingBox(const math::Box<float, 3>& newBoundingBox) noexcept
        {
            boundingBox = newBoundingBox;
        }

        virtual bool pointOn(const math::Vector<float, 2>& position) const;
        virtual bool shapeOverlaps(const std::vector<math::Vector<float, 2>>& edges) const;

        [[nodiscard]] auto isHidden() const noexcept { return hidden; }
        void setHidden(bool newHidden) { hidden = newHidden; }

        [[nodiscard]] auto getActor() const noexcept { return actor; }
        void removeFromActor();

    protected:
        virtual void setActor(Actor* newActor);
        virtual void setLayer(Layer* newLayer);
        virtual void updateTransform();

        math::Box<float, 3> boundingBox;
        bool hidden = false;

        Layer* layer = nullptr;
        Actor* actor = nullptr;
    };
}

#endif // OUZEL_SCENE_COMPONENT_HPP
<|endoftext|>


<commit_before><commit_msg>Fix a crasher in the GPU process caused by the DXVA code attempting to create an instance of the Video processor MFT<commit_after><|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/

#include "qmlprojectmanagerconstants.h"
#include "qmlproject.h"
#include "qmlprojectrunconfiguration.h"
#include "qmlprojectrunconfigurationfactory.h"

#include <projectexplorer/profileinformation.h>
#include <projectexplorer/projectconfiguration.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/target.h>
#include <qtsupport/qtprofileinformation.h>

namespace QmlProjectManager {
namespace Internal {

QmlProjectRunConfigurationFactory::QmlProjectRunConfigurationFactory(QObject *parent) :
    ProjectExplorer::IRunConfigurationFactory(parent)
{
    setObjectName(QLatin1String("QmlProjectRunConfigurationFactory"));
}

QmlProjectRunConfigurationFactory::~QmlProjectRunConfigurationFactory()
{
}

QList<Core::Id> QmlProjectRunConfigurationFactory::availableCreationIds(ProjectExplorer::Target *parent) const
{
    if (!canHandle(parent))
        return QList<Core::Id>();

    QtSupport::BaseQtVersion *version
            = QtSupport::QtProfileInformation::qtVersion(parent->profile());

    // put qmlscene first (so that it is the default) for Qt 5.0.0
    QList<Core::Id> list;
    if (version && version->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0))
        list << Core::Id(Constants::QML_SCENE_RC_ID);

    list << Core::Id(Constants::QML_VIEWER_RC_ID);

    return list;
}

QString QmlProjectRunConfigurationFactory::displayNameForId(const Core::Id id) const
{
    if (id == Constants::QML_VIEWER_RC_ID)
        return tr("QML Viewer");
    if (id == Constants::QML_SCENE_RC_ID)
        return tr("QML Scene");
    return QString();
}

bool QmlProjectRunConfigurationFactory::canCreate(ProjectExplorer::Target *parent,
                                                  const Core::Id id) const
{
    if (!canHandle(parent))
        return false;

    if (id == Constants::QML_VIEWER_RC_ID)
        return true;

    if (id == Constants::QML_SCENE_RC_ID) {
        // only support qmlscene if it's Qt5
        QtSupport::BaseQtVersion *version
                = QtSupport::QtProfileInformation::qtVersion(parent->profile());
        return version && version->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0);
    }
    return false;
}

ProjectExplorer::RunConfiguration *QmlProjectRunConfigurationFactory::create(ProjectExplorer::Target *parent, const Core::Id id)
{
    if (!canCreate(parent, id))
        return 0;
    return new QmlProjectRunConfiguration(parent, id);
}

bool QmlProjectRunConfigurationFactory::canRestore(ProjectExplorer::Target *parent, const QVariantMap &map) const
{
    return parent && canCreate(parent, ProjectExplorer::idFromMap(map));
}

ProjectExplorer::RunConfiguration *QmlProjectRunConfigurationFactory::restore(ProjectExplorer::Target *parent, const QVariantMap &map)
{
    if (!canRestore(parent, map))
        return 0;

    QmlProjectRunConfiguration *rc = new QmlProjectRunConfiguration(parent, id);
    if (rc->fromMap(map))
        return rc;
    delete rc;
    return 0;
}

bool QmlProjectRunConfigurationFactory::canClone(ProjectExplorer::Target *parent, ProjectExplorer::RunConfiguration *source) const
{
    return canCreate(parent, source->id());
}

ProjectExplorer::RunConfiguration *QmlProjectRunConfigurationFactory::clone(ProjectExplorer::Target *parent,
                                                                     ProjectExplorer::RunConfiguration *source)
{
    if (!canClone(parent, source))
        return 0;
    return new QmlProjectRunConfiguration(parent, qobject_cast<QmlProjectRunConfiguration *>(source));
}

bool QmlProjectRunConfigurationFactory::canHandle(ProjectExplorer::Target *parent) const
{
    if (!parent->project()->supportsProfile(parent->profile()))
        return false;
    if (!qobject_cast<QmlProject *>(parent->project()))
        return false;
    Core::Id deviceType = ProjectExplorer::DeviceTypeProfileInformation::deviceTypeId(parent->profile());
    return deviceType == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
}

} // namespace Internal
} // namespace QmlProjectManager

<commit_msg>QmlProject: Fix compilation failure<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/

#include "qmlprojectmanagerconstants.h"
#include "qmlproject.h"
#include "qmlprojectrunconfiguration.h"
#include "qmlprojectrunconfigurationfactory.h"

#include <projectexplorer/profileinformation.h>
#include <projectexplorer/projectconfiguration.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/target.h>
#include <qtsupport/qtprofileinformation.h>

namespace QmlProjectManager {
namespace Internal {

QmlProjectRunConfigurationFactory::QmlProjectRunConfigurationFactory(QObject *parent) :
    ProjectExplorer::IRunConfigurationFactory(parent)
{
    setObjectName(QLatin1String("QmlProjectRunConfigurationFactory"));
}

QmlProjectRunConfigurationFactory::~QmlProjectRunConfigurationFactory()
{
}

QList<Core::Id> QmlProjectRunConfigurationFactory::availableCreationIds(ProjectExplorer::Target *parent) const
{
    if (!canHandle(parent))
        return QList<Core::Id>();

    QtSupport::BaseQtVersion *version
            = QtSupport::QtProfileInformation::qtVersion(parent->profile());

    // put qmlscene first (so that it is the default) for Qt 5.0.0
    QList<Core::Id> list;
    if (version && version->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0))
        list << Core::Id(Constants::QML_SCENE_RC_ID);

    list << Core::Id(Constants::QML_VIEWER_RC_ID);

    return list;
}

QString QmlProjectRunConfigurationFactory::displayNameForId(const Core::Id id) const
{
    if (id == Constants::QML_VIEWER_RC_ID)
        return tr("QML Viewer");
    if (id == Constants::QML_SCENE_RC_ID)
        return tr("QML Scene");
    return QString();
}

bool QmlProjectRunConfigurationFactory::canCreate(ProjectExplorer::Target *parent,
                                                  const Core::Id id) const
{
    if (!canHandle(parent))
        return false;

    if (id == Constants::QML_VIEWER_RC_ID)
        return true;

    if (id == Constants::QML_SCENE_RC_ID) {
        // only support qmlscene if it's Qt5
        QtSupport::BaseQtVersion *version
                = QtSupport::QtProfileInformation::qtVersion(parent->profile());
        return version && version->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0);
    }
    return false;
}

ProjectExplorer::RunConfiguration *QmlProjectRunConfigurationFactory::create(ProjectExplorer::Target *parent, const Core::Id id)
{
    if (!canCreate(parent, id))
        return 0;
    return new QmlProjectRunConfiguration(parent, id);
}

bool QmlProjectRunConfigurationFactory::canRestore(ProjectExplorer::Target *parent, const QVariantMap &map) const
{
    return parent && canCreate(parent, ProjectExplorer::idFromMap(map));
}

ProjectExplorer::RunConfiguration *QmlProjectRunConfigurationFactory::restore(ProjectExplorer::Target *parent, const QVariantMap &map)
{
    if (!canRestore(parent, map))
        return 0;

    Core::Id id = ProjectExplorer::idFromMap(map);
    QmlProjectRunConfiguration *rc = new QmlProjectRunConfiguration(parent, id);
    if (rc->fromMap(map))
        return rc;
    delete rc;
    return 0;
}

bool QmlProjectRunConfigurationFactory::canClone(ProjectExplorer::Target *parent, ProjectExplorer::RunConfiguration *source) const
{
    return canCreate(parent, source->id());
}

ProjectExplorer::RunConfiguration *QmlProjectRunConfigurationFactory::clone(ProjectExplorer::Target *parent,
                                                                     ProjectExplorer::RunConfiguration *source)
{
    if (!canClone(parent, source))
        return 0;
    return new QmlProjectRunConfiguration(parent, qobject_cast<QmlProjectRunConfiguration *>(source));
}

bool QmlProjectRunConfigurationFactory::canHandle(ProjectExplorer::Target *parent) const
{
    if (!parent->project()->supportsProfile(parent->profile()))
        return false;
    if (!qobject_cast<QmlProject *>(parent->project()))
        return false;
    Core::Id deviceType = ProjectExplorer::DeviceTypeProfileInformation::deviceTypeId(parent->profile());
    return deviceType == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
}

} // namespace Internal
} // namespace QmlProjectManager

<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2018 The Apollo Authors. All Rights Reserved.
 *
 * 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.
 *****************************************************************************/

/**
 * @file
 **/

#include "modules/planning/toolkits/deciders/side_pass_path_decider.h"

#include <algorithm>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

#include "modules/common/proto/pnc_point.pb.h"
#include "modules/planning/common/frame.h"

namespace apollo {
namespace planning {

using ::apollo::common::ErrorCode;
using ::apollo::common::Status;
using ::apollo::hdmap::PathOverlap;

double ROAD_BUFFER = 0.2;
double OBSTACLE_BUFFER = 0.2;
double PLANNING_DIST_AFTER_OBSTACLE = 3.0;

SidePassPathDecider::SidePassPathDecider(const TaskConfig &config)
    : Decider(config) {
  SetName("SidePassPathDecider");
  fem_qp_.reset(new Fem1dExpandedJerkQpProblem());
  // TODO(lianglia-apollo):
  // Put numbers into config when refactor is finished.
  const int n = 400;
  std::array<double, 3> l_init = {0.0, 0.0, 0.0};
  const double delta_s = 0.5;
  std::array<double, 5> w = {1.0, 2.0, 3.0, 4.0, 5.0};
  constexpr double kMaxLThirdOrderDerivative = 10.0;
  CHECK(fem_qp_->Init(n, l_init, delta_s, w, kMaxLThirdOrderDerivative));
}

Status SidePassPathDecider::Process(Frame *frame,
                                    ReferenceLineInfo *reference_line_info) {
  return Status::OK();
}

Status SidePassPathDecider::BuildSidePathDecision(
    Frame *frame, ReferenceLineInfo *const reference_line_info) {
  // TODO(All): decide side pass from left or right.
  // For now, just go left at all times.
  decided_direction_ = LEFT;
  return Status().OK();
}

// TODO(All): currently it's the 1st version, and only consider one
// vehicular obstacle ahead. It side-passes that obstacle and move
// back to original reference_line immediately. (without considering
// subsequent obstacles)
bool SidePassPathDecider::GeneratePath(Frame *frame,
                                       ReferenceLineInfo *reference_line_info) {
  // Sanity checks.
  CHECK_NOTNULL(frame);
  CHECK_NOTNULL(reference_line_info);

  // Check if ADC has fully stopped.
  // TODO(All)

  // Decide whether to side-pass from left or right.
  if (BuildSidePathDecision(frame, reference_line_info) != Status().OK()) {
    AERROR << "Failed to decide on a side-pass direction.";
    return false;
  }

  // Generate the boundary conditions for the selected direction
  // based on the obstacle ahead and road conditions.
  std::vector<std::pair<double, double>> bound_cond;
  const ReferenceLine& reference_line = reference_line_info->reference_line();
  double adc_end_s = reference_line_info->AdcSlBoundary().end_s();
  // Get obstacle info.
  bool no_obs_selected = true;
  double nearest_obs_start_s, nearest_obs_end_s,
         nearest_obs_start_l, nearest_obs_end_l;
  for (const auto* path_obstacle :
       reference_line_info->path_decision()->path_obstacles().Items()) {
    // Filter out obstacles that are behind ADC.
    double obs_start_s = path_obstacle->PerceptionSLBoundary().start_s();
    double obs_end_s = path_obstacle->PerceptionSLBoundary().end_s();
    if (obs_end_s < adc_end_s) {
      continue;
    }
    // TODO(All): currently, it also ignores obstacles that are
    // partially ahead of ADC, meaning (obs_end_s > adc_end_s) but
    // (obs_start_s < adc_end_s). It treats such obstacles as
    // those that have been considered already in the last cycle.
    if (obs_start_s < adc_end_s) {
      continue;
    }
    // Filter out those out-of-lane obstacles.
    double lane_left_width_at_start_s, lane_left_width_at_end_s,
           lane_right_width_at_start_s, lane_right_width_at_end_s;
    reference_line.GetLaneWidth(obs_start_s,
        &lane_left_width_at_start_s, &lane_right_width_at_start_s);
    reference_line.GetLaneWidth(obs_end_s,
        &lane_left_width_at_end_s, &lane_right_width_at_end_s);
    double lane_left_width = std::min(std::abs(lane_left_width_at_start_s),
                                      std::abs(lane_left_width_at_end_s));
    double lane_right_width = std::min(std::abs(lane_right_width_at_start_s),
                                      std::abs(lane_right_width_at_end_s));
    double obs_start_l = path_obstacle->PerceptionSLBoundary().start_l();
    double obs_end_l = path_obstacle->PerceptionSLBoundary().end_l();
    if (obs_start_l > lane_left_width || -obs_end_l > lane_right_width) {
      continue;
    }
    // Only select vehicle obstacles.
    if (path_obstacle->obstacle()->Perception().type() !=
        perception::PerceptionObstacle::VEHICLE) {
      continue;
    }
    // For obstacles of interests, select the nearest one.
    // TODO(All): currently, regardless of the orientation
    // of the obstacle, it treats the obstacle as a rectangle
    // with two edges parallel to the reference line and the
    // other two perpendicular to that.
    if (no_obs_selected) {
      nearest_obs_start_s = obs_start_s;
      nearest_obs_end_s = obs_end_s;
      nearest_obs_start_l = obs_start_l;
      nearest_obs_end_l = obs_end_l;
      no_obs_selected = false;
    }
    if (nearest_obs_start_s > obs_start_s) {
      nearest_obs_start_s = obs_start_s;
      nearest_obs_end_s = obs_end_s;
      nearest_obs_start_l = obs_start_l;
      nearest_obs_end_l = obs_end_l;
    }
  }
  // Get road info at every point and fill in the boundary condition vector.
  common::PathPoint start_path_point = frame->PlanningStartPoint().path_point();
  common::math::Vec2d start_path_point_vec2d(start_path_point.x(),
                                             start_path_point.y());
  common::SLPoint start_path_point_SL;
  if (!reference_line.XYToSL(start_path_point_vec2d, &start_path_point_SL)) {
    AERROR << "Failed to get the projection from TrajectoryPoint onto "
              "reference_line";
    return false;
  }
  double s_increment = 1.0;
  double curr_s = start_path_point_SL.s();
  bool bound_cond_gen_finished = false;
  bool is_blocked_by_obs = false;
  std::vector<std::vector<double>> list_s_leftbound_rightbound;
  // Currently, it only considers one obstacle.
  // For future scaling so that multiple obstacles can be considered,
  // a sweep-line method can be used. The code here leaves some room
  // for the sweep-line method.
  while (!bound_cond_gen_finished) {
    std::vector<double> s_leftbound_rightbound;
    s_leftbound_rightbound.push_back(curr_s);
    // Check if boundary should be dictated by obstacle or road
    if (curr_s >= nearest_obs_start_s && curr_s <= nearest_obs_end_s) {
      is_blocked_by_obs = true;
    } else {
      is_blocked_by_obs = false;
    }
    // Get the road info at the current s.
    double road_left_width_at_curr_s, road_right_width_at_curr_s;
    reference_line.GetRoadWidth(curr_s,
        &road_left_width_at_curr_s, &road_right_width_at_curr_s);
    if (!is_blocked_by_obs) {
      s_leftbound_rightbound.push_back
          (-std::abs(road_left_width_at_curr_s-ROAD_BUFFER));
      s_leftbound_rightbound.push_back
          (std::abs(road_right_width_at_curr_s-ROAD_BUFFER));
    } else {
      if (decided_direction_ == LEFT) {
        s_leftbound_rightbound.push_back
            (-std::abs(road_left_width_at_curr_s-ROAD_BUFFER));
        s_leftbound_rightbound.push_back
            (-nearest_obs_end_l);
      } else if (decided_direction_ == RIGHT) {
        s_leftbound_rightbound.push_back
            (-nearest_obs_start_l);
        s_leftbound_rightbound.push_back
            (std::abs(road_right_width_at_curr_s-ROAD_BUFFER));
      } else {
        AERROR << "Side-pass direction undefined.";
        return false;
      }
    }
    // Move to next s
    curr_s += s_increment;
    if (curr_s > PLANNING_DIST_AFTER_OBSTACLE + nearest_obs_end_s) {
      bound_cond_gen_finished = true;
    }
  }
  // Call optimizer: (name to be filled) to generate smooth path.

  // Update Reference_Line_Info with this newly generated path.

  // TODO(All): generate path here

  std::vector<std::tuple<double, double, double>> l_bounds;

  // TODO(All): set up l_bounds here.
  fem_qp_->SetVariableBounds(l_bounds);
  fem_qp_->Optimize();
  // TODO(All): put optimized results into ReferenceLineInfo.

  return true;
}

}  // namespace planning
}  // namespace apollo
<commit_msg>Planning: minor changes.<commit_after>/******************************************************************************
 * Copyright 2018 The Apollo Authors. All Rights Reserved.
 *
 * 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.
 *****************************************************************************/

/**
 * @file
 **/

#include "modules/planning/toolkits/deciders/side_pass_path_decider.h"

#include <algorithm>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

#include "modules/common/proto/pnc_point.pb.h"
#include "modules/planning/common/frame.h"

namespace apollo {
namespace planning {

using ::apollo::common::ErrorCode;
using ::apollo::common::Status;
using ::apollo::hdmap::PathOverlap;

double ROAD_BUFFER = 0.2;
double OBSTACLE_BUFFER = 0.2;
double PLANNING_DIST_AFTER_OBSTACLE = 3.0;

SidePassPathDecider::SidePassPathDecider(const TaskConfig &config)
    : Decider(config) {
  SetName("SidePassPathDecider");
  fem_qp_.reset(new Fem1dExpandedJerkQpProblem());
  // TODO(lianglia-apollo):
  // Put numbers into config when refactor is finished.
  const int n = 400;
  std::array<double, 3> l_init = {0.0, 0.0, 0.0};
  const double delta_s = 0.5;
  std::array<double, 5> w = {1.0, 2.0, 3.0, 4.0, 5.0};
  constexpr double kMaxLThirdOrderDerivative = 10.0;
  CHECK(fem_qp_->Init(n, l_init, delta_s, w, kMaxLThirdOrderDerivative));
}

Status SidePassPathDecider::Process(Frame *frame,
                                    ReferenceLineInfo *reference_line_info) {
  return Status::OK();
}

Status SidePassPathDecider::BuildSidePathDecision(
    Frame *frame, ReferenceLineInfo *const reference_line_info) {
  // TODO(All): decide side pass from left or right.
  // For now, just go left at all times.
  decided_direction_ = LEFT;
  return Status().OK();
}

// TODO(All): currently it's the 1st version, and only consider one
// vehicular obstacle ahead. It side-passes that obstacle and move
// back to original reference_line immediately. (without considering
// subsequent obstacles)
bool SidePassPathDecider::GeneratePath(Frame *frame,
                                       ReferenceLineInfo *reference_line_info) {
  // Sanity checks.
  CHECK_NOTNULL(frame);
  CHECK_NOTNULL(reference_line_info);

  // Check if ADC has fully stopped.
  // TODO(All)

  // Decide whether to side-pass from left or right.
  if (BuildSidePathDecision(frame, reference_line_info) != Status().OK()) {
    AERROR << "Failed to decide on a side-pass direction.";
    return false;
  }

  // Generate the boundary conditions for the selected direction
  // based on the obstacle ahead and road conditions.
  std::vector<std::pair<double, double>> bound_cond;
  const ReferenceLine& reference_line = reference_line_info->reference_line();
  double adc_end_s = reference_line_info->AdcSlBoundary().end_s();
  // Get obstacle info.
  bool no_obs_selected = true;
  double nearest_obs_start_s, nearest_obs_end_s,
         nearest_obs_start_l, nearest_obs_end_l;
  for (const auto* path_obstacle :
       reference_line_info->path_decision()->path_obstacles().Items()) {
    // Filter out obstacles that are behind ADC.
    double obs_start_s = path_obstacle->PerceptionSLBoundary().start_s();
    double obs_end_s = path_obstacle->PerceptionSLBoundary().end_s();
    if (obs_end_s < adc_end_s) {
      continue;
    }
    // TODO(All): currently, it also ignores obstacles that are
    // partially ahead of ADC, meaning (obs_end_s > adc_end_s) but
    // (obs_start_s < adc_end_s). It treats such obstacles as
    // those that have been considered already in the last cycle.
    if (obs_start_s < adc_end_s) {
      continue;
    }
    // Filter out those out-of-lane obstacles.
    double lane_left_width_at_start_s, lane_left_width_at_end_s,
           lane_right_width_at_start_s, lane_right_width_at_end_s;
    reference_line.GetLaneWidth(obs_start_s,
        &lane_left_width_at_start_s, &lane_right_width_at_start_s);
    reference_line.GetLaneWidth(obs_end_s,
        &lane_left_width_at_end_s, &lane_right_width_at_end_s);
    double lane_left_width = std::min(std::abs(lane_left_width_at_start_s),
                                      std::abs(lane_left_width_at_end_s));
    double lane_right_width = std::min(std::abs(lane_right_width_at_start_s),
                                      std::abs(lane_right_width_at_end_s));
    double obs_start_l = path_obstacle->PerceptionSLBoundary().start_l();
    double obs_end_l = path_obstacle->PerceptionSLBoundary().end_l();
    if (obs_start_l > lane_left_width || -obs_end_l > lane_right_width) {
      continue;
    }
    // Only select vehicle obstacles.
    if (path_obstacle->obstacle()->Perception().type() !=
        perception::PerceptionObstacle::VEHICLE) {
      continue;
    }
    // For obstacles of interests, select the nearest one.
    // TODO(All): currently, regardless of the orientation
    // of the obstacle, it treats the obstacle as a rectangle
    // with two edges parallel to the reference line and the
    // other two perpendicular to that.
    if (no_obs_selected) {
      nearest_obs_start_s = obs_start_s;
      nearest_obs_end_s = obs_end_s;
      nearest_obs_start_l = obs_start_l;
      nearest_obs_end_l = obs_end_l;
      no_obs_selected = false;
    }
    if (nearest_obs_start_s > obs_start_s) {
      nearest_obs_start_s = obs_start_s;
      nearest_obs_end_s = obs_end_s;
      nearest_obs_start_l = obs_start_l;
      nearest_obs_end_l = obs_end_l;
    }
  }
  // Get road info at every point and fill in the boundary condition vector.
  common::PathPoint start_path_point = frame->PlanningStartPoint().path_point();
  common::math::Vec2d start_path_point_vec2d(start_path_point.x(),
                                             start_path_point.y());
  common::SLPoint start_path_point_SL;
  if (!reference_line.XYToSL(start_path_point_vec2d, &start_path_point_SL)) {
    AERROR << "Failed to get the projection from TrajectoryPoint onto "
              "reference_line";
    return false;
  }
  double s_increment = 1.0;
  double curr_s = start_path_point_SL.s();
  bool bound_cond_gen_finished = false;
  bool is_blocked_by_obs = false;
  std::vector<std::tuple<double, double, double>> list_s_leftbound_rightbound;
  // Currently, it only considers one obstacle.
  // For future scaling so that multiple obstacles can be considered,
  // a sweep-line method can be used. The code here leaves some room
  // for the sweep-line method.
  while (!bound_cond_gen_finished) {
    std::tuple<double, double, double> s_leftbound_rightbound;
    std::get<0>(s_leftbound_rightbound) = curr_s;
    // Check if boundary should be dictated by obstacle or road
    if (curr_s >= nearest_obs_start_s && curr_s <= nearest_obs_end_s) {
      is_blocked_by_obs = true;
    } else {
      is_blocked_by_obs = false;
    }
    // Get the road info at the current s.
    double road_left_width_at_curr_s, road_right_width_at_curr_s;
    reference_line.GetRoadWidth(curr_s,
        &road_left_width_at_curr_s, &road_right_width_at_curr_s);
    if (!is_blocked_by_obs) {
      std::get<1>(s_leftbound_rightbound) =
          -std::abs(road_left_width_at_curr_s-ROAD_BUFFER);
      std::get<2>(s_leftbound_rightbound) =
          std::abs(road_right_width_at_curr_s-ROAD_BUFFER);
    } else {
      if (decided_direction_ == LEFT) {
        std::get<1>(s_leftbound_rightbound) =
            -std::abs(road_left_width_at_curr_s-ROAD_BUFFER);
        std::get<2>(s_leftbound_rightbound) =
            -nearest_obs_end_l;
      } else if (decided_direction_ == RIGHT) {
        std::get<1>(s_leftbound_rightbound) =
            -nearest_obs_start_l;
        std::get<2>(s_leftbound_rightbound) =
            std::abs(road_right_width_at_curr_s-ROAD_BUFFER);
      } else {
        AERROR << "Side-pass direction undefined.";
        return false;
      }
    }
    list_s_leftbound_rightbound.push_back(s_leftbound_rightbound);
    // Move to next s
    curr_s += s_increment;
    if (curr_s > PLANNING_DIST_AFTER_OBSTACLE + nearest_obs_end_s) {
      bound_cond_gen_finished = true;
    }
  }
  // Call optimizer to generate smooth path.
  fem_qp_->SetVariableBounds(list_s_leftbound_rightbound);
  fem_qp_->Optimize();

  // TODO(All): put optimized results into ReferenceLineInfo.
  // Update Reference_Line_Info with this newly generated path.

  return true;
}

}  // namespace planning
}  // namespace apollo
<|endoftext|>


<commit_before>/*
	Flexisip, a flexible SIP proxy server with media capabilities.
	Copyright (C) 2010-2018  Belledonne Communications SARL, All rights reserved.

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU Affero General Public License as
	published by the Free Software Foundation, either version 3 of the
	License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Affero General Public License for more details.

	You should have received a copy of the GNU Affero General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <dlfcn.h>
#include <unordered_map>

#include "plugin-loader.hh"
#include "plugin.hh"

// =============================================================================

using namespace std;

// -----------------------------------------------------------------------------
// Low API to open library.
// -----------------------------------------------------------------------------

static string getDlerror () {
	const char *dlError = dlerror();
	return dlError ? dlError : "Unknown";
}

static void *openLibrary(const string &filename, string &error) {
	void *library = dlopen(filename.c_str(), RTLD_LAZY);
	if (!library) {
		error = getDlerror();
		return nullptr;
	}

	PluginInfo *info = static_cast<PluginInfo *>(dlsym(library, "__flexisipPluginInfo"));
	if (!info) {
		error = getDlerror();
		dlclose(library);
		return nullptr;
	}

	if (strcmp(info->apiVersion, FLEXISIP_PLUGIN_API_VERSION)) {
		error = "Incompatible plugin API. Expected `" FLEXISIP_PLUGIN_API_VERSION "`, got `";
		error.append(info->apiVersion);
		error.append("`.");
		dlclose(library);
		return nullptr;
	}

	error.clear();
	return library;
}

// -----------------------------------------------------------------------------
// SharedLibrary between each PluginLoader.
// -----------------------------------------------------------------------------

class SharedLibrary {
public:
	SharedLibrary(const string &filename, void *library) : mFilename(filename), mLibrary(library) {}

	SharedLibrary(SharedLibrary &&other) : mFilename(move(other.mFilename)), mLibrary(other.mLibrary) {
		other.mLibrary = nullptr;
	}

	~SharedLibrary() {
		if (module)
			delete module;
		if (mLibrary)
			dlclose(mLibrary);
	}

	void ref() {
		++mRefCounter;
	}

	void unref() {
		--mRefCounter;
	}

	bool unload();

	void *get() const { return mLibrary; }

	Module *module = nullptr;

private:
	string mFilename;
	void *mLibrary;

	int mRefCounter = 1;
};

namespace {
	unordered_map<string, SharedLibrary> LoadedLibraries;
}

bool SharedLibrary::unload() {
	if (--mRefCounter == 1) {
		LoadedLibraries.erase(mFilename);
		return true;
	}
	return false;
}

static SharedLibrary *getOrCreateSharedLibrary(const string &filename, string &error) {
	SharedLibrary *sharedLibrary;

	auto it = LoadedLibraries.find(filename);
	if (it != LoadedLibraries.end()) {
		sharedLibrary = &it->second;
		error.clear();
	} else {
		void *library = openLibrary(filename, error);
		if (library)
			sharedLibrary = &LoadedLibraries.insert({ filename, SharedLibrary(filename, library) }).first->second;
		else
			return nullptr;
	}

	return sharedLibrary;
}

// -----------------------------------------------------------------------------
// PluginLoader.
// -----------------------------------------------------------------------------

class PluginLoaderPrivate {
public:
	Agent *agent = nullptr;
	string filename;

	SharedLibrary *sharedLibrary = nullptr;

	string error;

	int libraryRefCounter = 0;
};

namespace Private {
	Plugin::Plugin(SharedLibrary &sharedLibrary) : mSharedLibrary(&sharedLibrary) {}

	Plugin::~Plugin() {
		mSharedLibrary->module = nullptr;
	}
}

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

PluginLoader::PluginLoader(Agent *agent) : mPrivate(new PluginLoaderPrivate) {
	mPrivate->agent = agent;
}

PluginLoader::PluginLoader(Agent *agent, const string &filename) : PluginLoader(agent) {
	mPrivate->filename = filename;
}

PluginLoader::~PluginLoader() {
	SharedLibrary *sharedLibrary = mPrivate->sharedLibrary;
	if (sharedLibrary)
		sharedLibrary->unref();

	delete mPrivate;
}

const string &PluginLoader::getFilename() const {
	return mPrivate->filename;
}

void PluginLoader::setFilename(const string &filename) {
	if (mPrivate->sharedLibrary) {
		mPrivate->sharedLibrary->unref();
		mPrivate->sharedLibrary = nullptr;
	}
	mPrivate->filename = filename;
}

bool PluginLoader::isLoaded() const {
	return mPrivate->sharedLibrary;
}

bool PluginLoader::load() {
	if (!mPrivate->sharedLibrary)
		mPrivate->sharedLibrary = getOrCreateSharedLibrary(mPrivate->filename, mPrivate->error);

	if (mPrivate->sharedLibrary) {
		++mPrivate->libraryRefCounter;
		mPrivate->sharedLibrary->ref();
		return true;
	}

	return false;
}

bool PluginLoader::unload() {
	if (!mPrivate->sharedLibrary)
		return false;

	--mPrivate->libraryRefCounter;
	bool unloaded = mPrivate->sharedLibrary->unload();
	if (!mPrivate->libraryRefCounter)
		mPrivate->sharedLibrary = nullptr;

	return unloaded;
}

Module *PluginLoader::get() {
	if (!mPrivate->sharedLibrary && !load())
		return nullptr;

	SharedLibrary *sharedLibrary = mPrivate->sharedLibrary;
	if (sharedLibrary->module)
		return sharedLibrary->module;

	Module *(*createPlugin)(Agent *agent, SharedLibrary *sharedLibrary);
	*reinterpret_cast<void **>(&createPlugin) = dlsym(mPrivate->sharedLibrary->get(), "__flexisipCreatePlugin");
	if (!createPlugin)
		mPrivate->error = "Unable to get plugin. CreatePlugin symbol not found.";
	else
		sharedLibrary->module = createPlugin(mPrivate->agent, sharedLibrary);

	return sharedLibrary->module;
}

const ModuleInfoBase *PluginLoader::getModuleInfo() {
	if (load()) {
		const ModuleInfoBase *(*getPluginModuleInfo)();
		*reinterpret_cast<void **>(&getPluginModuleInfo) = dlsym(mPrivate->sharedLibrary->get(), "__flexisipGetPluginModuleInfo");
		if (!getPluginModuleInfo)
			mPrivate->error = "Unable to get plugin. GetPluginModuleInfo symbol not found.";
		else
			return getPluginModuleInfo();
	}
	return nullptr;
}

const string &PluginLoader::getError() const {
	return mPrivate->error;
}
<commit_msg>fix(PluginLoader): deal with older versions of gcc<commit_after>/*
	Flexisip, a flexible SIP proxy server with media capabilities.
	Copyright (C) 2010-2018  Belledonne Communications SARL, All rights reserved.

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU Affero General Public License as
	published by the Free Software Foundation, either version 3 of the
	License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Affero General Public License for more details.

	You should have received a copy of the GNU Affero General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <dlfcn.h>
#include <unordered_map>

#include "plugin-loader.hh"
#include "plugin.hh"

// =============================================================================

using namespace std;

// -----------------------------------------------------------------------------
// Low API to open library.
// -----------------------------------------------------------------------------

static string getDlerror () {
	const char *dlError = dlerror();
	return dlError ? dlError : "Unknown";
}

static void *openLibrary(const string &filename, string &error) {
	void *library = dlopen(filename.c_str(), RTLD_LAZY);
	if (!library) {
		error = getDlerror();
		return nullptr;
	}

	PluginInfo *info = static_cast<PluginInfo *>(dlsym(library, "__flexisipPluginInfo"));
	if (!info) {
		error = getDlerror();
		dlclose(library);
		return nullptr;
	}

	if (strcmp(info->apiVersion, FLEXISIP_PLUGIN_API_VERSION)) {
		error = "Incompatible plugin API. Expected `" FLEXISIP_PLUGIN_API_VERSION "`, got `";
		error.append(info->apiVersion);
		error.append("`.");
		dlclose(library);
		return nullptr;
	}

	error.clear();
	return library;
}

// -----------------------------------------------------------------------------
// SharedLibrary between each PluginLoader.
// -----------------------------------------------------------------------------

class SharedLibrary {
public:
	SharedLibrary(const string &filename, void *library) : mFilename(filename), mLibrary(library) {}

	// Workaround for older gcc versions.
	// Move ctor is not correctly supported with std::pair on older versions of gcc.
	#if __GNUC__ < 5
	SharedLibrary(
		const SharedLibrary &other
	) : module(other.module), mFilename(move(other.mFilename)), mLibrary(other.mLibrary), mRefCounter(other.mRefCounter) {
		SharedLibrary &self = const_cast<SharedLibrary &>(other);
		self.module = nullptr;
		self.mLibrary = nullptr;
	}
	#else
	SharedLibrary(
		SharedLibrary &&other
	) : module(other.module), mFilename(move(other.mFilename)), mLibrary(other.mLibrary), mRefCounter(other.mRefCounter) {
		other.module = nullptr;
		other.mLibrary = nullptr;
	}
	#endif // if __GNUC__ < 5

	~SharedLibrary() {
		if (module)
			delete module;
		if (mLibrary)
			dlclose(mLibrary);
	}

	void ref() {
		++mRefCounter;
	}

	void unref() {
		--mRefCounter;
	}

	bool unload();

	void *get() const { return mLibrary; }

	Module *module = nullptr;

private:
	string mFilename;
	void *mLibrary;

	int mRefCounter;
};

namespace {
	unordered_map<string, SharedLibrary> LoadedLibraries;
}

bool SharedLibrary::unload() {
	if (--mRefCounter == 1) {
		LoadedLibraries.erase(mFilename);
		return true;
	}
	return false;
}

static SharedLibrary *getOrCreateSharedLibrary(const string &filename, string &error) {
	SharedLibrary *sharedLibrary;

	auto it = LoadedLibraries.find(filename);
	if (it != LoadedLibraries.end()) {
		sharedLibrary = &it->second;
		error.clear();
	} else {
		void *library = openLibrary(filename, error);
		if (library)
			sharedLibrary = &LoadedLibraries.insert({ filename, SharedLibrary(filename, library) }).first->second;
		else
			return nullptr;
	}

	return sharedLibrary;
}

// -----------------------------------------------------------------------------
// PluginLoader.
// -----------------------------------------------------------------------------

class PluginLoaderPrivate {
public:
	Agent *agent = nullptr;
	string filename;

	SharedLibrary *sharedLibrary = nullptr;

	string error;

	int libraryRefCounter = 0;
};

namespace Private {
	Plugin::Plugin(SharedLibrary &sharedLibrary) : mSharedLibrary(&sharedLibrary) {}

	Plugin::~Plugin() {
		mSharedLibrary->module = nullptr;
	}
}

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

PluginLoader::PluginLoader(Agent *agent) : mPrivate(new PluginLoaderPrivate) {
	mPrivate->agent = agent;
}

PluginLoader::PluginLoader(Agent *agent, const string &filename) : PluginLoader(agent) {
	mPrivate->filename = filename;
}

PluginLoader::~PluginLoader() {
	SharedLibrary *sharedLibrary = mPrivate->sharedLibrary;
	if (sharedLibrary)
		sharedLibrary->unref();

	delete mPrivate;
}

const string &PluginLoader::getFilename() const {
	return mPrivate->filename;
}

void PluginLoader::setFilename(const string &filename) {
	if (mPrivate->sharedLibrary) {
		mPrivate->sharedLibrary->unref();
		mPrivate->sharedLibrary = nullptr;
	}
	mPrivate->filename = filename;
}

bool PluginLoader::isLoaded() const {
	return mPrivate->sharedLibrary;
}

bool PluginLoader::load() {
	if (!mPrivate->sharedLibrary)
		mPrivate->sharedLibrary = getOrCreateSharedLibrary(mPrivate->filename, mPrivate->error);

	if (mPrivate->sharedLibrary) {
		++mPrivate->libraryRefCounter;
		mPrivate->sharedLibrary->ref();
		return true;
	}

	return false;
}

bool PluginLoader::unload() {
	if (!mPrivate->sharedLibrary)
		return false;

	--mPrivate->libraryRefCounter;
	bool unloaded = mPrivate->sharedLibrary->unload();
	if (!mPrivate->libraryRefCounter)
		mPrivate->sharedLibrary = nullptr;

	return unloaded;
}

Module *PluginLoader::get() {
	if (!mPrivate->sharedLibrary && !load())
		return nullptr;

	SharedLibrary *sharedLibrary = mPrivate->sharedLibrary;
	if (sharedLibrary->module)
		return sharedLibrary->module;

	Module *(*createPlugin)(Agent *agent, SharedLibrary *sharedLibrary);
	*reinterpret_cast<void **>(&createPlugin) = dlsym(mPrivate->sharedLibrary->get(), "__flexisipCreatePlugin");
	if (!createPlugin)
		mPrivate->error = "Unable to get plugin. CreatePlugin symbol not found.";
	else
		sharedLibrary->module = createPlugin(mPrivate->agent, sharedLibrary);

	return sharedLibrary->module;
}

const ModuleInfoBase *PluginLoader::getModuleInfo() {
	if (load()) {
		const ModuleInfoBase *(*getPluginModuleInfo)();
		*reinterpret_cast<void **>(&getPluginModuleInfo) = dlsym(mPrivate->sharedLibrary->get(), "__flexisipGetPluginModuleInfo");
		if (!getPluginModuleInfo)
			mPrivate->error = "Unable to get plugin. GetPluginModuleInfo symbol not found.";
		else
			return getPluginModuleInfo();
	}
	return nullptr;
}

const string &PluginLoader::getError() const {
	return mPrivate->error;
}
<|endoftext|>


<commit_before>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id:

#include <BALL/STRUCTURE/geometricProperties.h>
#include <qcolordialog.h>
#include <qpopupmenu.h>
#include <qmenubar.h>
#include <BALL/VIEW/DIALOGS/labelDialog.h>
#include <BALL/VIEW/PRIMITIVES/label.h>
#include <BALL/VIEW/KERNEL/mainControl.h>
#include <BALL/FORMAT/INIFile.h>

#include <qlabel.h>
#include <qpushbutton.h>
#include <qlineedit.h>

namespace BALL
{
	namespace VIEW
	{

LabelDialog::LabelDialog(QWidget* parent, const char* name)
	throw()
	:	LabelDialogData( parent, name ),
		ModularWidget(name),
		id_(-1),
		selection_()
{
#ifdef BALL_VIEW_DEBUG
	Log.error() << "new LabelDialog " << this << std::endl;
#endif
	setCaption("Add Label");

	// register the widget with the MainControl
	ModularWidget::registerWidget(this);

	hide();
}

LabelDialog::~LabelDialog()
	throw()
{
#ifdef BALL_VIEW_DEBUG
	Log.error() << "deleting LabelDialog " << this << std::endl;
#endif
}

void LabelDialog::fetchPreferences(INIFile& inifile)
	throw()
{
	//
	// the geometry of the main window
	//
	int x_pos = x();
	int y_pos = y();

	if (inifile.hasEntry("WINDOWS", "Label::x"))
	{
		x_pos = inifile.getValue("WINDOWS", "Label::x").toInt();
	}
	if (inifile.hasEntry("WINDOWS", "Label::y"))
	{
		y_pos = inifile.getValue("WINDOWS", "Label::y").toInt();
	}

	move(x_pos, y_pos);

	//
	// the color value
	//

	if (inifile.hasEntry("WINDOWS", "Label::customcolor"))
	{
		custom_color_.set(inifile.getValue("WINDOWS", "Label::customcolor"));

		QColor qcolor(custom_color_.getRed(),
									custom_color_.getGreen(),
									custom_color_.getBlue());

		color_sample_->setBackgroundColor(qcolor);
	}
	else
	{
		custom_color_.set(ColorRGBA(1.,1.,0.,1.));
		QColor qcolor(custom_color_.getRed(),
									custom_color_.getGreen(),
									custom_color_.getBlue());

		color_sample_->setBackgroundColor(qcolor);
	}
}

void LabelDialog::writePreferences(INIFile& inifile)
	throw()
{
	// the label window position
	inifile.insertValue("WINDOWS", "Label::x", String(x()));
	inifile.insertValue("WINDOWS", "Label::y", String(y()));

	// the color value
	inifile.insertValue("WINDOWS", "Label::customcolor", custom_color_);
}

void LabelDialog::onNotify(Message *message)
	throw()
{
#ifdef BALL_VIEW_DEBUG
	Log.error() << "LabelDialog " << this << " onNotify " << message << std::endl;
#endif
	// selection => store last selection for later processing
	if (RTTI::isKindOf<ControlSelectionMessage>(*message))
	{
		ControlSelectionMessage* selection = RTTI::castTo<ControlSelectionMessage>(*message);
		selection_ = selection->getSelection();
	}
	else
	{
		// no molecular selection => clear the selection
		selection_.clear();
	}

	// disabled apply button, if selection is empty
	apply_button_->setEnabled(!selection_.empty());
}

void LabelDialog::initializeWidget(MainControl& main_control)
	throw()
{
	main_control.initPopupMenu(MainControl::DISPLAY)->setCheckable(true);

	id_ = main_control.insertMenuEntry(MainControl::DISPLAY, "Add &Label", this,
																		 SLOT(openDialog()), CTRL+Key_L);
}

void LabelDialog::finalizeWidget(MainControl& main_control)
	throw()
{
	main_control.removeMenuEntry(MainControl::DISPLAY, "Add &Label", this,
															 SLOT(openDialog()), CTRL+Key_L);
}

void LabelDialog::checkMenu(MainControl& main_control)
	throw()
{
	bool selected = (selection_.empty() ? false : true);

	main_control.menuBar()->setItemEnabled(id_, selected);
	main_control.menuBar()->setItemChecked(id_, isVisible());
}

void LabelDialog::openDialog()
{
	show();
	raise();
}

void LabelDialog::accept()
{
	// no selection present => return
	if (selection_.empty())
	{
		return;
	}

	// number of objects
	unsigned long number_of_objects = 0;

	// center processor
	GeometricCenterProcessor center_processor;

	// center to which the label will be attached
	Vector3 center(0,0,0);

	// process all objects in the selection list
	List<Composite*>::Iterator list_it = selection_.begin();
	for (; list_it != selection_.end(); ++list_it)
	{
		(*list_it)->apply(center_processor);

		center += center_processor.getCenter();
		++number_of_objects;
	}

	if (number_of_objects != 0)
	{
		center /= number_of_objects;
	}

	// create Label and Representation

	Label* label = new Label;

	label->setText(label_edit_->text().ascii());
	label->setColor(custom_color_);
	label->setVertex(center);

	Representation* rep = getMainControl()->getPrimitiveManager().createRepresentation();
	rep->insert(*label);
	rep->setProperty(Representation::PROPERTY__ALWAYS_FRONT);
	rep->setModelType(6);
	RepresentationMessage* arm = new RepresentationMessage;
	arm->setRepresentation(rep);
	arm->setType(RepresentationMessage::ADD);
	notify_(arm);

	// update scene
	SceneMessage* scene_message = new SceneMessage;
	scene_message->setType(SceneMessage::REDRAW);
	notify_(scene_message);

	// clear status bar
	setStatusbarText("");
}

void LabelDialog::editColor()
{
	color_sample_->setBackgroundColor(QColorDialog::getColor(color_sample_->backgroundColor()));
	QColor qcolor = color_sample_->backgroundColor();

	custom_color_.set((float)qcolor.red() / 255.0,
										(float)qcolor.green() / 255.0,
										(float)qcolor.blue() / 255.0);

	update();
}

} } // namespaces
<commit_msg>now setting the right representation type<commit_after>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id:

#include <BALL/STRUCTURE/geometricProperties.h>
#include <BALL/FORMAT/INIFile.h>
#include <BALL/VIEW/DIALOGS/labelDialog.h>
#include <BALL/VIEW/PRIMITIVES/label.h>
#include <BALL/VIEW/KERNEL/mainControl.h>
#include <BALL/VIEW/KERNEL/common.h>

#include <qcolordialog.h>
#include <qpopupmenu.h>
#include <qmenubar.h>
#include <qlabel.h>
#include <qpushbutton.h>
#include <qlineedit.h>

namespace BALL
{
	namespace VIEW
	{

LabelDialog::LabelDialog(QWidget* parent, const char* name)
	throw()
	:	LabelDialogData( parent, name ),
		ModularWidget(name),
		id_(-1),
		selection_()
{
#ifdef BALL_VIEW_DEBUG
	Log.error() << "new LabelDialog " << this << std::endl;
#endif
	setCaption("Add Label");

	// register the widget with the MainControl
	ModularWidget::registerWidget(this);

	hide();
}

LabelDialog::~LabelDialog()
	throw()
{
#ifdef BALL_VIEW_DEBUG
	Log.error() << "deleting LabelDialog " << this << std::endl;
#endif
}

void LabelDialog::fetchPreferences(INIFile& inifile)
	throw()
{
	//
	// the geometry of the main window
	//
	int x_pos = x();
	int y_pos = y();

	if (inifile.hasEntry("WINDOWS", "Label::x"))
	{
		x_pos = inifile.getValue("WINDOWS", "Label::x").toInt();
	}
	if (inifile.hasEntry("WINDOWS", "Label::y"))
	{
		y_pos = inifile.getValue("WINDOWS", "Label::y").toInt();
	}

	move(x_pos, y_pos);

	//
	// the color value
	//

	if (inifile.hasEntry("WINDOWS", "Label::customcolor"))
	{
		custom_color_.set(inifile.getValue("WINDOWS", "Label::customcolor"));

		QColor qcolor(custom_color_.getRed(),
									custom_color_.getGreen(),
									custom_color_.getBlue());

		color_sample_->setBackgroundColor(qcolor);
	}
	else
	{
		custom_color_.set(ColorRGBA(1.,1.,0.,1.));
		QColor qcolor(custom_color_.getRed(),
									custom_color_.getGreen(),
									custom_color_.getBlue());

		color_sample_->setBackgroundColor(qcolor);
	}
}

void LabelDialog::writePreferences(INIFile& inifile)
	throw()
{
	// the label window position
	inifile.insertValue("WINDOWS", "Label::x", String(x()));
	inifile.insertValue("WINDOWS", "Label::y", String(y()));

	// the color value
	inifile.insertValue("WINDOWS", "Label::customcolor", custom_color_);
}

void LabelDialog::onNotify(Message *message)
	throw()
{
#ifdef BALL_VIEW_DEBUG
	Log.error() << "LabelDialog " << this << " onNotify " << message << std::endl;
#endif
	// selection => store last selection for later processing
	if (RTTI::isKindOf<ControlSelectionMessage>(*message))
	{
		ControlSelectionMessage* selection = RTTI::castTo<ControlSelectionMessage>(*message);
		selection_ = selection->getSelection();
	}
	else
	{
		// no molecular selection => clear the selection
		selection_.clear();
	}

	// disabled apply button, if selection is empty
	apply_button_->setEnabled(!selection_.empty());
}

void LabelDialog::initializeWidget(MainControl& main_control)
	throw()
{
	main_control.initPopupMenu(MainControl::DISPLAY)->setCheckable(true);

	id_ = main_control.insertMenuEntry(MainControl::DISPLAY, "Add &Label", this,
																		 SLOT(openDialog()), CTRL+Key_L);
}

void LabelDialog::finalizeWidget(MainControl& main_control)
	throw()
{
	main_control.removeMenuEntry(MainControl::DISPLAY, "Add &Label", this,
															 SLOT(openDialog()), CTRL+Key_L);
}

void LabelDialog::checkMenu(MainControl& main_control)
	throw()
{
	bool selected = (selection_.empty() ? false : true);

	main_control.menuBar()->setItemEnabled(id_, selected);
	main_control.menuBar()->setItemChecked(id_, isVisible());
}

void LabelDialog::openDialog()
{
	show();
	raise();
}

void LabelDialog::accept()
{
	// no selection present => return
	if (selection_.empty())
	{
		return;
	}

	// number of objects
	unsigned long number_of_objects = 0;

	// center processor
	GeometricCenterProcessor center_processor;

	// center to which the label will be attached
	Vector3 center(0,0,0);

	// process all objects in the selection list
	List<Composite*>::Iterator list_it = selection_.begin();
	for (; list_it != selection_.end(); ++list_it)
	{
		(*list_it)->apply(center_processor);

		center += center_processor.getCenter();
		++number_of_objects;
	}

	if (number_of_objects != 0)
	{
		center /= number_of_objects;
	}

	// create Label and Representation
	Label* label = new Label;
	label->setText(label_edit_->text().ascii());
	label->setColor(custom_color_);
	label->setVertex(center);

	Representation* rep = getMainControl()->getPrimitiveManager().createRepresentation();
	rep->insert(*label);
	rep->setProperty(Representation::PROPERTY__ALWAYS_FRONT);
	rep->setModelType(MODEL_LABEL);
	RepresentationMessage* arm = new RepresentationMessage;
	arm->setRepresentation(rep);
	arm->setType(RepresentationMessage::ADD);
	notify_(arm);

	// update scene
	SceneMessage* scene_message = new SceneMessage;
	scene_message->setType(SceneMessage::REDRAW);
	notify_(scene_message);

	// clear status bar
	setStatusbarText("");
}

void LabelDialog::editColor()
{
	color_sample_->setBackgroundColor(QColorDialog::getColor(color_sample_->backgroundColor()));
	QColor qcolor = color_sample_->backgroundColor();

	custom_color_.set((float)qcolor.red() / 255.0,
										(float)qcolor.green() / 255.0,
										(float)qcolor.blue() / 255.0);

	update();
}

} } // namespaces
<|endoftext|>