예제 #1
0
  void solve1( int M1, int L1,
               const Bipartite *m_to_l1,
               const double *P1, double *q1 )
  {
    M = M1;
    L = L1;
    P = P1;
    q = q1;
    m_to_l = m_to_l1;

    
    double *qp = q;
    for ( int l=0; l<L; l++ ) {
      auto &_to_m = m_to_l->getFromSet( l );
      memset( qp, 0, sizeof(double) * LabelSet::classes );
      for ( auto& ele : _to_m ) {
        int m = ele.first;
        double alpha = ele.second;
        addScaledTo( qp, P + m * LabelSet::classes, LabelSet::classes, alpha );
      }

      double s = sum_vec( qp, LabelSet::classes );
      
      scale( qp, LabelSet::classes, 1.0 / s );
      qp += LabelSet::classes;
    }
    
  }
예제 #2
0
  /*
   * Restricted Energy on q(l) is
   *     sum_m ( D(m) - alpha(l,m) * q(l) + alpha(l,m) * q'(l) )^2
   *   + sum_j w(i,j) * ( q'(l) - q(j) )^2
   */
  inline double restrict_energy( int l, double *q_l = nullptr )
  {

    auto& _to_m = m_to_l->getFromSet( l );
    auto& _to_j = forest->GetWeights( l );
    
    double energy = 0.0;
    double t0[LabelSet::classes];

    if ( nullptr == q_l ) {
      for ( auto& ele : _to_m ) {
        int m = ele.first;
        energy += norm2( D + m * LabelSet::classes, LabelSet::classes );
      }
      
      for ( auto& ele : _to_j ) {
        int j = ele.first;
        double wt = static_cast<double>( ele.second );

        minus( q + l * LabelSet::classes, q + j * LabelSet::classes, t0, LabelSet::classes );
        energy += options.beta * wt * norm2( t0, LabelSet::classes );
      }
    } else {

      double t0[LabelSet::classes];

      for ( auto& ele : _to_m ) {
        int m = ele.first;
        double alpha = ele.second;

        memcpy( t0, D + m * LabelSet::classes, sizeof(double) * LabelSet::classes );
        minusScaledFrom( t0, q + l * LabelSet::classes, LabelSet::classes, alpha );
        addScaledTo( t0, q_l, LabelSet::classes, alpha );
        energy += norm2( t0, LabelSet::classes );
      }

      
      for ( auto& ele : _to_j ) {
        int j = ele.first;
        double wt = static_cast<double>( ele.second );
        minus( q_l, q + j * LabelSet::classes, t0, LabelSet::classes );
        energy += options.beta * wt * norm2( t0, LabelSet::classes );
      }

    }

    return energy;

  }
예제 #3
0
  inline void update_q( int l )
  {

    auto& _to_m = m_to_l->getFromSet( l );
    auto& _to_j = forest->GetWeights( l );
    
    double t0[LabelSet::classes];
    memset( t0, 0, sizeof(double) * LabelSet::classes );
    double t1[LabelSet::classes];
        
    


    // t0 = sum_m alpha(l,m) * D(m) 
    for ( auto& ele : _to_m ) {
      int m = ele.first;
      double alpha = ele.second;
      addScaledTo( t0, D + m * LabelSet::classes, LabelSet::classes, alpha );
    }


    
    // t0 += sum_m wt(l,j) (q(l) - q(j) )
    for ( auto& ele : _to_j ) {
      int j = ele.first;
      double wt = static_cast<double>( ele.second );
      minus( q + l * LabelSet::classes, q + j * LabelSet::classes, t1, LabelSet::classes );
      addScaledTo( t0, t1, LabelSet::classes, wt );
    }

    // negate t0 to get negative gradient direction
    negate( t0, LabelSet::classes );
    
    // Line Search
    double energy_old = restrict_energy( l ) * options.wolf;

    bool updated = false;

    
    normalize_vec( t0, t0, LabelSet::classes );
    double energy_new = 0.0;
    for ( int i=0; i<40; i++ ) {
      scale( t0, LabelSet::classes, options.shrinkRatio );
      add( t0, q + l * LabelSet::classes, t1, LabelSet::classes );
      // Simplex Projection
      watershed( t1, t0, LabelSet::classes );

      energy_new = restrict_energy( l, t0 );
      if ( energy_new < energy_old ) {
        updated = true;
        break;
      }
    }

    if ( updated ) {
      for ( auto& ele : _to_m ) {
        int m = ele.first;
        double alpha = ele.second;
        update_D( m, l, t0, alpha );
      }
      memcpy( q + l * LabelSet::classes, t0, sizeof(double) * LabelSet::classes );
    }
  }