Przeglądaj źródła

deprecated strange nchoosek interface

Former-commit-id: d63fcdb3082533d547f836c0d0760c8af806a6ed
Alec Jacobson 10 lat temu
rodzic
commit
8d88dd275c
2 zmienionych plików z 113 dodań i 38 usunięć
  1. 74 32
      include/igl/nchoosek.cpp
  2. 39 6
      include/igl/nchoosek.h

+ 74 - 32
include/igl/nchoosek.cpp

@@ -1,54 +1,96 @@
 // This file is part of libigl, a simple c++ geometry processing library.
 //
-// Copyright (C) 2014 Olga Diamanti <olga.diam@gmail.com>
+// Copyright (C) 2015 Olga Diamanti, Alec Jacobson
 //
 // This Source Code Form is subject to the terms of the Mozilla Public License
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // obtain one at http://mozilla.org/MPL/2.0/.
-
 #include "nchoosek.h"
+#include <cmath>
+#include <cassert>
 
-namespace igl {
-  class CombinationFinder
+IGL_INLINE double igl::nchoosek(const int n, const int k)
+{
+  if(k>n/2)
+  {
+    return nchoosek(n,n-k);
+  }else if(k==1)
   {
-  private:
-    std::vector<int> combinations;
-    void add(const std::vector<int>& v,
-             std::vector<std::vector<int> > &allCombs)
+    return n;
+  }else
+  {
+    double c = 1;
+    for(int i = 1;i<=k;i++)
     {
-      allCombs.push_back(v);
+      c *= (((double)n-k+i)/((double)i));
     }
+    return std::round(c);
+  }
+}
 
-  public:
-    void doCombs(int offset,
-                 int k,
-                 int N,
-                 std::vector<std::vector<int> > &allCombs)
+template < typename DerivedV, typename DerivedU>
+IGL_INLINE void igl::nchoosek(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const int k,
+  Eigen::PlainObjectBase<DerivedU> & U)
+{
+  using namespace Eigen;
+  if(V.size() == 0)
+  {
+    U.resize(0,k);
+    return;
+  }
+  assert((V.cols() == 1 || V.rows() == 1) && "V must be a vector");
+  U.resize(nchoosek(V.size(),k),k);
+  int running_i  = 0;
+  int running_j = 0;
+  Matrix<typename DerivedU::Scalar,1,Dynamic> running(1,k);
+  int N = V.size();
+  const std::function<void(int,int)> doCombs = 
+    [&running,&N,&doCombs,&running_i,&running_j,&U,&V](int offset, int k)
+  {
+    if(k==0)
     {
-      if (k == 0) {
-        add(combinations,allCombs);
-        return;
-      }
-      for (int i = offset; i <= N - k; ++i) {
-        combinations.push_back(i);
-        doCombs(i+1, k-1, N,allCombs);
-        combinations.pop_back();
-      }
+      U.row(running_i) = running;
+      running_i++;
+      return;
+    }
+    for (int i = offset; i <= N - k; ++i) 
+    {
+      running(running_j) = V(i);
+      running_j++;
+      doCombs(i+1,k-1);
+      running_j--;
     }
-
   };
-
-
+  doCombs(0,k);
 }
 
-IGL_INLINE void igl::nchoosek(int offset,
-                              int k,
-                              int N,
-                              std::vector<std::vector<int> > &allCombs)
+IGL_INLINE void igl::nchoosek(
+  int offset,
+  int k,
+  int N,
+  std::vector<std::vector<int> > &allCombs)
 {
-  CombinationFinder cmbf;
   allCombs.clear();
-  cmbf.doCombs(offset,k,N,allCombs);
+  std::vector<int> running;
+  const std::function<void(int,int)> doCombs = 
+    [&allCombs,&running,&N,&doCombs](int offset, int k)
+  {
+    if(k==0)
+    {
+      allCombs.push_back(running);
+      return;
+    }
+    for (int i = offset; i <= N - k; ++i) 
+    {
+      running.push_back(i);
+      doCombs(i+1,k-1);
+      running.pop_back();
+    }
+  };
+  doCombs(offset,k);
+
 }
 
 

+ 39 - 6
include/igl/nchoosek.h

@@ -1,6 +1,6 @@
 // This file is part of libigl, a simple c++ geometry processing library.
 //
-// Copyright (C) 2014 Olga Diamanti <olga.diam@gmail.com>
+// Copyright (C) 2015 Olga Diamanti, Alec Jacobson
 //
 // This Source Code Form is subject to the terms of the Mozilla Public License
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
@@ -9,15 +9,48 @@
 #ifndef IGL_NCHOOSEK
 #define IGL_NCHOOSEK
 #include "igl_inline.h"
+#include "deprecated.h"
 #include <vector>
 
 #include <Eigen/Core>
 
-namespace igl {
-  IGL_INLINE void nchoosek(int offset,
-                           int k,
-                           int N,
-                           std::vector<std::vector<int> > &allCombs);
+namespace igl 
+{
+  // NCHOOSEK  Like matlab's nchoosek.
+  //
+  // Inputs:
+  //   n  total number elements
+  //   k  size of sub-set to consider
+  // Returns number of k-size combinations out of the set [1,...,n]
+  IGL_INLINE double nchoosek(const int n, const int k);
+  // 
+  // Inputs:
+  //   V  n-long vector of elements
+  //   k  size of sub-set to consider
+  // Outputs:
+  //   U  nchoosek by k long matrix where each row is a unique k-size
+  //     combination
+  template < typename DerivedV, typename DerivedU>
+  IGL_INLINE void nchoosek(
+    const Eigen::PlainObjectBase<DerivedV> & V,
+    const int k,
+    Eigen::PlainObjectBase<DerivedU> & U);
+  // This version has a strange interface and confusing parameters. It seems to
+  // reproduce matlab's 
+  //
+  //     nchoosek(3:5,2) 
+  //
+  // Then one should use
+  //
+  //     igl::nchoosek(3,2,6,res);
+  //
+  IGL_INLINE 
+  IGL_DEPRECATED(
+  void nchoosek(
+    int offset,
+    int k,
+    int N,
+    std::vector<std::vector<int> > &allCombs));
 }