[EDIT]
I am looking for the way to use the optim_lbfgs function in Rcppnumerical and RcppEigen with Rcpparmadillo. I follow the way in Rcpp Integration for Numerical Computing Libraries, but it was not working with the error, cannot declare variable 'obj' to be of abstract type 'scoreftn_mns'. But now, I fixed some codes to make it work. I define the beta as Eigen::VectorXd beta(p); as in the Rcppnumerical and convert it to arma::vec in the template(?).
Here's my code that I am trying to do.
// [[Rcpp::depends(RcppEigen)]]
// [[Rcpp::depends(RcppNumerical)]]
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
#include <RcppNumerical.h>
using namespace Numer;
using namespace arma;
using namespace Rcpp;
// Eigen::Ref<Eigen::VectorXd>
// Eigen::Ref<const Eigen::VectorXd>
class socreftn_mns: public MFuncGrad
{
private:
const arma::vec TIME;
const arma::vec DELTA;
const arma::mat COVARI;
const arma::vec TARGETVEC;
public:
socreftn_mns(const arma::vec Time, const arma::vec Delta, const arma::mat Covari,
const arma::vec targetvec) : TIME(Time), DELTA(Delta), COVARI(Covari), TARGETVEC(targetvec) {}
double f_grad(Constvec& beta, Refvec grad){
arma::vec b_s = arma::vec(beta.data(),beta.size());
int n = COVARI.n_rows;
int p = COVARI.n_cols;
arma::vec zero_vec_p = zeros(p);
arma::mat zero_mat_np = zeros(n,p);
arma::vec tempvec_p(p);
arma::mat tempmat_np(n,p);
arma::vec resid = log(TIME) + COVARI*b_s;
arma::uvec index_resid = sort_index(resid);
TIME(index_resid);
DELTA(index_resid);
COVARI.rows(index_resid);
resid(index_resid);
tempmat_np = zero_mat_np; arma::vec U_inf = zero_vec_p;
for(int it=0; it<n; it++){
tempmat_np = COVARI.row(it) - COVARI.each_row();
U_inf += sum(tempmat_np.each_col()%conv_to<vec>::from((resid>=resid(it))),0).t()*DELTA(it);
}
U_inf = U_inf/n - TARGETVEC;
double objvalue = conv_to<double>::from(sum(pow(U_inf,2)));
double h = 1e-4;
for(int itt=0; itt<p; itt++){
tempvec_p = b_s;
tempvec_p(itt) = tempvec_p(itt) + h;
arma::vec resid_g = log(TIME) + COVARI*tempvec_p;
arma::uvec index_resid_g = sort_index(resid_g);
TIME(index_resid_g);
DELTA(index_resid_g);
COVARI.rows(index_resid_g);
resid(index_resid_g);
tempmat_np = zero_mat_np; arma::vec score_grad = zero_vec_p;
for(int it=0; it<n; it++){
tempmat_np = COVARI.row(it) - COVARI.each_row();
score_grad += sum(tempmat_np.each_col()%conv_to<vec>::from((resid_g>=resid_g(it))),0).t()*DELTA(it);
}
score_grad = score_grad/n - TARGETVEC;
double score_objvalue = conv_to<double>::from(sum(pow(score_grad,2)));
grad(itt) = (score_objvalue-objvalue)/h;
}
// beta = Eigen::Ref(b_s);
return objvalue;
}
};
// [[Rcpp::export]]
Rcpp::NumericVector aftsrr_bfgs(arma::vec Time, arma::vec Delta, arma::mat Covari, arma::vec targetvec){
const arma::vec TIME = Time;
const arma::vec DELTA = Delta;
const arma::mat COVARI = Covari;
const arma::vec TARGETVEC = targetvec;
int p = COVARI.n_cols;
// Score Function
socreftn_mns obj(TIME, DELTA, COVARI, TARGETVEC);
// Initial Guess
Eigen::VectorXd beta(p);
beta.setOnes();
double fopt;
int status = optim_lbfgs(obj, beta, fopt);
if(status < 0)
Rcpp::stop("fail to converge");
return Rcpp::wrap(beta);
}
And, this is R code that is working.
library(Rcpp)
library(RcppArmadillo)
library(RcppEigen)
library(RcppNumerical)
library(survival)
library(aftgee)
sourceCpp("C:/Users/mattw/Documents/paper_wj/exercise/aftsrr_wj_cpp/aftsrr_wj/optim_bfgs.cpp")
U_beta_r_non = function(beta,Time,Delta,Covari) {
n=length(Time)
p=ncol(Covari)
e_i_beta = as.vector(log(Time) + Covari %*% beta)
order_resid = order(e_i_beta)
Time = Time[order_resid]
Covari = matrix(Covari[order_resid,],nrow = n)
Delta = Delta[order_resid]
e_i_beta = e_i_beta[order_resid]
U_beta = list(NA)
for (i in 1:n) {
U_beta[[i]] = colSums(Delta[i]*t(Covari[i,]-t(Covari))*(e_i_beta>=e_i_beta[i]))
}
U_beta = Reduce('+',U_beta)/n
U_beta = sum(U_beta^2)
# grad = c(); h = 1e-4;
# for (it in 1:p) {
# beta_g = beta;
# beta_g[it] = beta[it] + h
#
# e_i_beta = as.vector(log(Time) + Covari %*% beta_g)
#
# order_resid = order(e_i_beta)
#
# Time = Time[order_resid]
# Covari = matrix(Covari[order_resid,],nrow = n)
# Delta = Delta[order_resid]
# e_i_beta = e_i_beta[order_resid]
#
# grad_beta = list(NA);
# for (i in 1:n) {
# grad_beta[[i]] = colSums(Delta[i]*t(Covari[i,]-t(Covari))*(e_i_beta>=e_i_beta[i]))
# }
# grad_beta = Reduce('+',grad_beta)/n
# grad_beta = sum(grad_beta^2)
#
# grad[it] = (grad_beta-U_beta)/h
# }
# return(U_beta)
return(sum(U_beta^2))
# return(grad)
}
#------------------------DATA GENERATION----------------------
set.seed(1)
n=300
beta_0=1
gamma_0=0.5
Z1=matrix(rnorm(n,3,1),nrow=n)
Z2=matrix(rexp(n,5),nrow=n)
T_aft=as.vector(exp(-beta_0*Z1-gamma_0*Z2+rnorm(n,5,1)))
C_aft=as.vector(exp(-beta_0*Z1-gamma_0*Z2+rnorm(n,6,1)))
X_aft=C_aft*(T_aft>C_aft)+T_aft*(T_aft<=C_aft)
D_aft=0*(T_aft>C_aft)+1*(T_aft<=C_aft)
table(D_aft)
beta_aftsrr=-aftsrr(Surv(X_aft,D_aft)~Z1+Z2)$beta;beta_aftsrr
init_beta = rep(0,2)
cpp_bfgs_esti = aftsrr_bfgs(init_beta,X_aft,D_aft,cbind(Z1,Z2),rep(0,2));cpp_bfgs_esti
optim_lbfgsb = optim(init_beta,function(x){U_beta_r_non(x,X_aft,D_aft,cbind(Z1,Z2))},method = "L-BFGS-B")$par;optim_lbfgsb
Now, it is working, however, it seems that it just gives the init_beta without any calculation in the R example. As some people say that it is not possible to use the above armadillo codes, I am studying the Eigen library. However, I am not familiar with the computing it is hard to convert it. So, hopefully, there's a way to use it with some modification. Thanks!
Any comments will be helpful.
The rest of the error message that I am getting when compiling your code is of interest:
optim_num.cpp: In function ‘Rcpp::NumericVector aftsrr_bfgs(arma::vec, arma::vec, arma::mat, arma::vec)’:
optim_num.cpp:86:16: error: cannot declare variable ‘obj’ to be of abstract type ‘socreftn_mns’
socreftn_mns obj(TIME, DELTA, COVARI, TARGETVEC);
^~~
optim_num.cpp:11:7: note: because the following virtual functions are pure within ‘socreftn_mns’:
class socreftn_mns: public MFuncGrad
^~~~~~~~~~~~
In file included from /usr/local/lib/R/site-library/RcppNumerical/include/integration/wrapper.h:13:0,
from /usr/local/lib/R/site-library/RcppNumerical/include/RcppNumerical.h:16,
from optim_num.cpp:6:
/usr/local/lib/R/site-library/RcppNumerical/include/integration/../Func.h:52:20: note: virtual double Numer::MFuncGrad::f_grad(Numer::Constvec&, Numer::Refvec)
virtual double f_grad(Constvec& x, Refvec grad) = 0;
^~~~~~
In essence that means that your class socreftn_mns is derived from the abstract class MFuncGrad. This class is abstract since it does not contain a definition for the method f_grad(Constvec& x, Refvec grad). You try to define this by defining the method f_grad(arma::vec& b_s, arma::vec grad), but due to the different function signature, the virtual function is not overloaded. Hence your class is also abstract.
If you use the same signature, things should work out. The required types are defined in terms of Eigen objects:
// Reference to a vector
typedef Eigen::Ref<Eigen::VectorXd> Refvec;
typedef const Eigen::Ref<const Eigen::VectorXd> Constvec;
So you will have to convert back and forth between Aramdillo and Eigen constructs.
Related
The following Vulkan program attempts to create an instance and setup a VkDebugUtilsMessengerEXT - but when run it doesn't output anything:
#include <stdlib.h>
#include <stdio.h>
#include <vulkan/vulkan.h>
VkBool32 VKAPI_PTR debug_utils_messenger_callback(
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* pUserData) {
printf("%s", pCallbackData->pMessage);
return VK_FALSE;
}
int main() {
// create instance
VkInstanceCreateInfo instance_create_info = {};
instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
const char* layers[] = {"VK_LAYER_LUNARG_standard_validation"};
instance_create_info.ppEnabledLayerNames = layers;
instance_create_info.enabledLayerCount = 1;
const char* extensions[] = {VK_EXT_DEBUG_UTILS_EXTENSION_NAME};
instance_create_info.enabledExtensionCount = 1;
instance_create_info.ppEnabledExtensionNames = extensions;
VkInstance instance;
if (VK_SUCCESS != vkCreateInstance(&instance_create_info, NULL, &instance))
exit(EXIT_FAILURE);
// load kCreateDebugUtilsMessengerEXT
PFN_vkCreateDebugUtilsMessengerEXT pvkCreateDebugUtilsMessengerEXT =
(PFN_vkCreateDebugUtilsMessengerEXT)
vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
if (pvkCreateDebugUtilsMessengerEXT == NULL)
exit(EXIT_FAILURE);
// create debug utils messenger
VkDebugUtilsMessengerCreateInfoEXT debug_utils_messenger_create_info = {};
debug_utils_messenger_create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
debug_utils_messenger_create_info.messageSeverity =
VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
debug_utils_messenger_create_info.messageType =
VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
debug_utils_messenger_create_info.pfnUserCallback = debug_utils_messenger_callback;
VkDebugUtilsMessengerEXT debug_utils_messenger;
if (VK_SUCCESS != pvkCreateDebugUtilsMessengerEXT(instance, &debug_utils_messenger_create_info, NULL, &debug_utils_messenger))
exit(EXIT_FAILURE);
// destroy instance
vkDestroyInstance(instance, NULL);
}
Why not? I would expect that it outputs some debug messages from the debug_utils_messenger_callback?
Object Tracker does track debug utils objects, but it looks like the layer is only reporting objects belonging to undestroyed device objects at DestroyInstance-time, and debugutils shows up in that list. It should go in a separate Instance object list and get spit out at DestroyInstance time.
A github issue has been submitted: https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/658
I want to define a constant array of constants at every MPI node using C++03. M_chunk_sizes defines the size of matrix that will be passed to other nodes and won't be changed during the runtime.
int* define_chunk_sizes( int S, int world) {
int out[world];
double quotient = static_cast<double> (S) / world;
int maj = ceil(quotient);
for (int i =0; i < world - 1; i++)
out[i] = maj;
out[world-1] = maj + (S - maj*world);
return out;
}
int main() {
const int M = 999; // rows
int world_size = 4;
const int* const M_chunk_sizes = define_chunk_sizes(M, world_size);
}
But i get a warning: address of stack memory associated with local variable 'out' returned [-Wreturn-stack-address]
return out;.
What is the right way of doing this?
funciton local variables(stack varibales) will go out of scope and life once function returns.
you have use dynamic memory management operators, so allocate memory to out using
new
and relase memory using
delete
once you done with it.
I have a 6-DOF robot arm model:
robot arm structure
I want to calculate forward kinematics, so I uses the D-H matrix. the D-H parameters are:
static const std::vector<float> theta = {
0,0,90.0f,0,-90.0f,0};
// d
static const std::vector<float> d = {
380.948f,0,0,-560.18f,0,0};
// a
static const std::vector<float> a = {
-220.0f,522.331f,80.0f,0,0,94.77f};
// alpha
static const std::vector<float> alpha = {
90.0f,0,90.0f,-90.0f,-90.0f,0};
and the calculation :
glm::mat4 Robothand::armForKinematics() noexcept
{
glm::mat4 pose(1.0f);
float cos_theta, sin_theta, cos_alpha, sin_alpha;
for (auto i = 0; i < 6;i++)
{
cos_theta = cosf(glm::radians(theta[i]));
sin_theta = sinf(glm::radians(theta[i]));
cos_alpha = cosf(glm::radians(alpha[i]));
sin_alpha = sinf(glm::radians(alpha[i]));
glm::mat4 Ai = {
cos_theta, -sin_theta * cos_alpha,sin_theta * sin_alpha, a[i] * cos_theta,
sin_theta, cos_theta * cos_alpha, -cos_theta * sin_alpha,a[i] * sin_theta,
0, sin_alpha, cos_alpha, d[i],
0, 0, 0, 1 };
pose = pose * Ai;
}
return pose;
}
the problem I have is that, I can't get the correct result, for example, I want to calculate the transformation matrix from first joint to the 4th joint, I will change the for loop i < 3,then I can get the pose matrix, and I can the origin coordinate in 4th coordinate system by pose * (0,0,0,1).but the result (380.948,382.331,0) seems not correct because it should be move along x-axis not y-axis. I have read many books and materials about D-H matrix, but I can't figure out what's wrong with it.
I have figured it out by myself, the real problem behind is glm::mat, glm::mat is col-type which means columns will be initialized before rows,I changed the code and get the correct result:
for (int i = 0; i < joint_num; ++i)
{
pose = glm::rotate(pose, glm::radians(degrees[i]), glm::vec3(0, 0, 1));
pose = glm::translate(pose,glm::vec3(0,0,d[i]));
pose = glm::translate(pose, glm::vec3(a[i], 0, 0));
pose = glm::rotate(pose,glm::radians(alpha[i]),glm::vec3(1,0,0));
}
then I can get the position by:
auto pos = pose * glm::vec4(x,y,z,1);
My team is working on developing a new backend for TensorFlow. Generally, tensorflow opkernels are passed as arguments "Tensor" types which use memory allocated with our architecture:
void ComputeAsync(OpKernelContext* context, DoneCallback done) override {
// Grab the input tensors
const Tensor& A = context->input(0);
const Tensor& B = context->input(1);
// ...input validation...
const our::Memory_Type *bA = static_cast<const our::Memory_Type *>(DMAHelper::base(&A));
const our::Memory_Type *bB = static_cast<const our::Memory_Type *>(DMAHelper::base(&B));
// ...additional preconditioning...
// Create an output tensor
Tensor *C = NULL;
OP_REQUIRES_OK(context, context->allocate_output(0, out_shape, &C));
our::Memory_Type *bC = static_cast<kpi::KPI_RMR_Mem*>(DMAHelper::base(C));
//and run it
our_impl(bA, bB, bC, done);
}
However, we are having more trouble with porting the "CrossOp" type, because part of the preconditioning involves converting the datatype to Eigen types:
// in0, in1, and output are all tensorflow::Tensor types, but ConstTensor is an Eigen type
typename TTypes<Type, 2>::ConstTensor in0_data =
in0.flat_inner_dims<Type>();
typename TTypes<Type, 2>::ConstTensor in1_data =
in1.flat_inner_dims<Type>();
typename TTypes<Type, 2>::Tensor output_data =
output->flat_inner_dims<Type>();
DMAHelper::base() assumes it is run on a Tensor and not a ConstTensor. Is it safe to follow the above operations with the ones below, or is does the process of flat_inner_dims() change the contents of the underlying data such that the result would be invalid or not read by TensorFlow?
const our::Memory_Type *in0_arg = static_cast<const our::Memory_Type *>(DMAHelper::base(&in0));
const our::Memory_Type *in1_arg = static_cast<const our::Memory_Type *>(DMAHelper::base(&in1));
const our::Memory_Type *output_arg = static_cast<const our::Memory_Type *>(DMAHelper::base(&output));
our_cross_impl(in0_arg, in1_arg, output_arg);
I'm making a bidirectional path tracer and I have some troubles.
To be clear :
1) One point light
2) All objects are diffuse
3) All objects are spheres, even walls (they are very large)
4) NO MIS WEIGHTING
The light emission is a 3D vector. The BRDF of a sphere is a 3D vector. Hard coded.
In the main function below I generate EyePath and LightPath then I connect them. At least I try.
In this post I will talking about the main function then EyePath then LightPath. The talking about connecting function will appear once EyePath and Light are good.
First questions :
Does the generation of the first light point is good ?
Do I need to compute this point according to the emission of the light source? or is it just the emission ? The line is commented where i'm filling the Vertices structure.
Do I need to translate fromlight ? In order to put it on the sphere
The code below is sampled in the main function. Above it there is two for loops going through all pixels. Camera.o is the eye. CameraRayDir is the direction to the current pixel.
//The path light starting point is at the same position as the light
Ray fromLight(Vec(0, 24.3, 0), Vec());
Sphere light = spheres[7];
#define PDF 0.15915494309 // 1 / (2 * PI)
for(int i = 0; i < samps; ++i)
{
std::vector<Vertices> PathEye;
std::vector<Vertices> PathLight;
Vec cameraRayDir = cx * (double(x) / w - .5) + cy * (double(y) / h - .5) + camera.d;
Ray rayEye(camera.o, cameraRayDir.norm());
// Hemisphere oriented towards the top
fromLight.d = generateRayInHemisphere(fromLight.o,Vec(0,1,0)).d;
double f = clamp(n.dot(fromLight.d.norm()));
Vertices vert;
vert.d = fromLight.d;
vert.x = fromLight.o;
vert.id = 7;
vert.cos = f;
vert.n = Vec(0,1,0).norm();
// this one ?
//vert.couleur = spheres[7].e * f / PDF;
// Or this one ?
vert.couleur = spheres[7].e;
PathLight.push_back(vert);
int sizeEye = generateEyePath(PathEye, rayEye, maxDepth);
int sizeLight = generateLightPath(PathLight, fromLight, maxDepth);
for (int s = 0; s < sizeLight; ++s)
{
for (int t = 1; t < sizeEye; ++t)
{
int depth = t + s - 1;
if ((s == 0 && t == 0) || depth < 0 || depth > maxDepth)
continue;
pixelValue = pixelValue + connectPaths(PathEye, PathLight, s, t);
}
}
}
For the EyePath I intersect the geometry then I compute the illumination according to the distance with the light. The colour is black if the point is in the shadow.
Second question : For the eye path and the direct illumination, is the computation good ? I've seen in many code, people use the pdf even in direct illumination. But I'm only using point light and spheres.
int generateEyePath(std::vector<Vertices>& v, Ray eye, int maxDepth)
{
double t;
int id = 0;
Vertices vert;
int RussianRoulette;
while(v.size() <= maxDepth)
{
if(distribRREye(generatorRREye) < 10)
break;
// Intersect all the geometry
// id is the id of the intersected geometry in an array
intersect(eye, t, id);
const Sphere& obj = spheres[id];
// Intersection point
Vec x = eye.o + eye.d * t;
// normal
Vec n = (x - obj.p).norm();
Vec direction = light.p - x;
// Shadow ray
Ray RaytoLight = Ray(x, direction.norm());
const float distance = direction.length();
// shadow
const bool visibility = intersect(RaytoLight, t, id);
const Sphere &lumiere = spheres[id];
float degree = clamp(n.dot((lumiere.p - x).norm()));
// If the intersected geometry is not a light, then in shadow
if(lumiere.e.x == 0)
{
vert.couleur = Vec();
}
else // else we compute the colour
// obj.c is the brdf, lumiere.e is the emission
vert.couleur = (obj.c).mult(lumiere.e / (distance * distance)) * degree;
vert.x = x;
vert.id = id;
vert.n = n;
vert.d = eye.d.normn();
vert.cos = degree;
v.push_back(vert);
eye = generateRayInHemisphere(x,n);
}
return v.size();
}
For the LightPath, for a given point, I compute it according to the previous one and the values at this point. Like in a common path tracing.\n
Third question: Is the colour computation good ?
int generateLightPath(std::vector<Vertices>& v, Ray fromLight, int maxDepth)
{
double t;
int id = 0;
Vertices vert;
Vec previous;
while(v.size() <= maxDepth)
{
if(distribRRLight(generatorRRLight) < 10)
break;
previous = v.back().couleur;
intersect(fromLight, t, id);
// intersected geometry
const Sphere& obj = spheres[id];
// Intersection point
Vec x = fromLight.o + fromLight.d * t;
// normal
Vec n = (x - obj.p).norm();
double f = clamp(n.dot(fromLight.d.norm()));
// obj.c is the brdf
vert.couleur = previous.mult(((obj.c / M_PI) * f) / PDF);
vert.x = x;
vert.id = id;
vert.n = n;
vert.d = fromLight.d.norm();
vert.cos = f;
v.push_back(vert);
fromLight = generateRayInHemisphere(x,n);
}
return v.size();
}
For the moment I get this result.
enter image description here
The connecting function will come once EyePath and LightPath are good.
Thank you all
Try the spherical reference scene mentioned in this paper. I think then you can work out most of your questions by yourself since it has an analytical solution.
https://www.researchgate.net/publication/221546261_Testing_Monte-Carlo_Global_Illumination_Methods_with_Analytically_Computable_Scenes
It would save your time to implement and verify your understanding with path tracing and light tracing first, then try to combine them with weights.