Giter VIP home page Giter VIP logo

ypan1988 / roptim Goto Github PK

View Code? Open in Web Editor NEW
18.0 3.0 4.0 365 KB

General Purpose Optimization in R using C++: provides a unified C++ wrapper to call functions of the algorithms underlying the optim() solver

Home Page: https://cran.r-project.org/web/packages/roptim/index.html

R 11.68% Shell 1.97% C 6.48% C++ 79.87%
nelder-mead bfgs conjugate-gradient l-bfgs-b simulated-annealing cran optim armadillo rcpp

roptim's Introduction

roptim: General Purpose Optimization in R using C++.

Build Status cran version downloads total downloads

Features

  • Perform general purpose optimization in R using the Armadillo C++ library for numerical linear algebra.
  • A unified wrapper interface is used to call C code of the five optimization algorithms (namely Nelder-Mead, BFGS, CG, L-BFGS-B and SANN) underlying function optim() (package stats) provided by default R installation.

Installation

Get the development version from github:

install.packages("devtools")
library(devtools)
devtools::install_github("ypan1988/roptim", dependencies=TRUE)

Or the released version from CRAN:

install.packages("roptim")

A Quick Example

An example of using stats::optim() in R environment:

fr <- function(x) {   ## Rosenbrock Banana function
    x1 <- x[1]
    x2 <- x[2]
    100 * (x2 - x1 * x1)^2 + (1 - x1)^2
}
grr <- function(x) { ## Gradient of 'fr'
    x1 <- x[1]
    x2 <- x[2]
    c(-400 * x1 * (x2 - x1 * x1) - 2 * (1 - x1),
       200 *      (x2 - x1 * x1))
}
res <- optim(c(-1.2,1), fr, grr, method = "BFGS", control = list(trace=T), hessian = TRUE)
res

Corresponding code written in C++ using package roptim (file demo.cpp):

#include <cmath>  // std::pow

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]

#include <roptim.h>
// [[Rcpp::depends(roptim)]]

using namespace roptim;

class Rosen : public Functor {
public:
  double operator()(const arma::vec &x) override {
    double x1 = x(0);
    double x2 = x(1);
    return 100 * std::pow((x2 - x1 * x1), 2) + std::pow(1 - x1, 2);
  }
  
  void Gradient(const arma::vec &x, arma::vec &gr) override {
    gr = arma::zeros<arma::vec>(2);
    
    double x1 = x(0);
    double x2 = x(1);
    gr(0) = -400 * x1 * (x2 - x1 * x1) - 2 * (1 - x1);
    gr(1) = 200 * (x2 - x1 * x1);
  }
};


// [[Rcpp::export]]
void rosen_bfgs() {
  Rosen rb;
  Roptim<Rosen> opt("BFGS");
  opt.control.trace = 1;
  opt.set_hessian(true);
  
  arma::vec x = {-1.2, 1};
  opt.minimize(rb, x);
  
  Rcpp::Rcout << "-------------------------" << std::endl;
  opt.print();
}

Compile and run the function in R:

library(Rcpp)
sourceCpp("~/demo.cpp") # you may need to change the directory
rosen_bfgs()

Then you will get expected output as follows:

initial  value 24.200000 
iter  10 value 1.367383
iter  20 value 0.134560
iter  30 value 0.001978
iter  40 value 0.000000
final  value 0.000000 
converged
-------------------------
.par()
   1.0000   1.0000

.value()
9.59496e-018

.fncount()
110

.grcount()
43

.convergence()
0

.message()
NULL

.hessian()
  8.0200e+002 -4.0000e+002
 -4.0000e+002  2.0000e+002

Note: more examples are provided in src/roptim_examples.cpp.

roptim's People

Contributors

privefl avatar ypan1988 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

roptim's Issues

NOTE in R devel check

Hi Yi,

I am getting my package ready for CRAN and get the following note when running the check on R-devel:

File ‘psychonetrics/libs/psychonetrics.so’:
  Found ‘_ZSt4cout’, possibly from ‘std::cout’ (C++)
    Object: ‘04_generalfit_psychonetrics_BFGS.o’

Compiled code should not call entry points which might terminate R nor
write to stdout/stderr instead of to the console, nor use Fortran I/O
nor system RNGs.

I don't see any reference to cout or so in the corresponding code though. I was wondering if this NOTE is perhaps due to the roptim import here?

passing other arguments

Hi, I want to pass other arguments to the roptim in Rcpp but I don't know how to do that.
For example, I want to do the same thing in rcpp as the following in R's optim():

optim(par=r0, fn=fn, gr=gr, X=X, time=time, q=q, k=k, method = 'L-BFGS-B')

Do you know how could I do that? Thank you very much!

Use of numerical gradient

Hi,

I have a custom function for which there is no analytical gradient that I can find. Is it still possible to use this package to do optimization in Rcpp (without defining a gradient function)?

Thanks,
Teng

can't run the demo.cpp

Hi, thank you for making this package which might potentially facilitate one of the projects that I am working on. There is one thing that I couldn't follow, which is to reproduce the example described in the README.md. I downloaded the demo.cpp and try to run the following R code. However, it gave me lots of error messages, which do not fit here.

library(Rcpp)
sourceCpp("~/demo.cpp") # you may need to change the directory
rosen_bfgs()

Please let me know if this is the right way to execute the rcpp code. Thank you!

Specify intolerable parameter set in fit function

Hi Yi Pan,

Thank you very much for your earlier help! I was encountering one more problem I hope you could help me with. In optimization, I require parameters to form positive definite matrices. However, sometimes the optimizer would go to a parameter value that would lead to non positive definite matrices. I was wondering if there is some way to specify when the parameters are in a non tolerable space? I tried building in a simple if statement in the fit function that returns NA_REAL or a very large number, but the first solution gives the message:

 L-BFGS-B needs finite values of 'fn'

And the second solution seems to work but leads to poor parameter estimates.

Best, Sacha

Help with implementation

I think your package could be very handy for my problem; thanks for developing it.

I prototyped some R code, which works fine:

library(bigsnpr)
bigsnp <- snp_attachExtdata()
G <- bigsnp$genotypes

simu <- snp_simuPheno(G, 0.2, 500, alpha = 0.5)

log_var <- log(big_colstats(G, ind.col = simu$set)$var)
beta2 <- simu$effects^2

FUN <- function(x, log_var, beta2) {
  S <- 1 + x[[1]]; sigma2 <- x[[2]]
  S * sum(log_var) + length(log_var) * log(sigma2) + sum(beta2 / exp(S * log_var)) / sigma2
}

DER <- function(x, log_var, beta2) {
  S <- 1 + x[[1]]; sigma2 <- x[[2]]
  res1 <- sum(log_var) - sum(log_var * beta2 / exp(S * log_var)) / sigma2
  res2 <- length(log_var) / sigma2 - sum(beta2 / exp(S * log_var)) / sigma2^2
  c(res1, res2)
}

optim(par = c(-0.5, 0.2 / 500), fn = FUN, method = "L-BFGS-B", gr = DER,
      lower = c(-2, 0.2 / 5000), upper = c(1, 0.2 / 50),
      log_var = log_var, beta2 = beta2)

Then I tried implementing it in C++ using your package:

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]

#include <roptim.h>
// [[Rcpp::depends(roptim)]]

using namespace roptim;

class MLE : public Functor {
public:
  MLE(const arma::vec& a_, const arma::vec& b_) : a(a_), b(b_) {}

  double operator()(const arma::vec& par) override {

    double S = par[0] + 1;
    double sigma2 = par[1];

    int m = a.size();
    double sum_a = 0, sum_c = 0;
    for (int j = 0; j < m; j++) {
      sum_a += a[j];
      sum_c += b[j] / ::exp(S * a[j]);
    }

    return S * sum_a + m * ::log(sigma2) + sum_c / sigma2;
  }

  void Gradient(const arma::vec& par, arma::vec& gr) override {

    double S = par[0] + 1;
    double sigma2 = par[1];

    int m = a.size();
    double sum_a = 0, sum_c = 0, sum_ac = 0;
    for (int j = 0; j < m; j++) {
      double c_j = b[j] / ::exp(S * a[j]);
      sum_a += a[j];
      sum_c += c_j;
      sum_ac += a[j] * c_j;
    }

    gr[0] = sum_a - sum_ac / sigma2;
    gr[1] = (m - sum_c / sigma2) / sigma2;
  }

private:
  arma::vec a;
  arma::vec b;
};


// [[Rcpp::export]]
arma::vec test_MLE(const arma::vec& a_, const arma::vec& b_,
                   arma::vec par, const arma::vec& lower, const arma::vec& upper) {

  MLE mle(a_, b_);
  Roptim<MLE> opt("L-BFGS-B");
  opt.set_lower(lower);
  opt.set_upper(upper);
  opt.set_hessian(false);
  opt.control.maxit = 100;

  opt.minimize(mle, par);

  Rcpp::Rcout << "-------------------------" << std::endl;
  opt.print();

  return par;
}

Then in R:

Rcpp::sourceCpp('tmp-tests/proto-MLE-optim-C++.cpp')
x <- c(0.5, 0.2 / 500)
test_MLE(log_var, beta2, x,
         lower = c(-2, 0.2 / 5000), upper = c(1, 0.2 / 50))

but it crashes..

I have been trying to debug it, but I am not sure if it comes from a silly mistake on my part, or something I didn't understand about how to use your package.
Any idea?

Cannot compile package using roptim on Windows

Dear Yi Pan,

Thank you for the roptim package! It works very well and seems to be exactly what I was looking for. I am working on a developmental version of my R package psychonetrics which uses roptim in this c++ code. The package works well on Linux, but when trying to compile the package on Windows I get the following errors:

image

I am entirely at a loss what this error could be, which seems not to be related to the source code of my package at all. I tried commenting out lines 82 - 85 of the code that uses roptim, but this did not solve the problem.

Thank you very much for your time!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.