S-PLUS中使用CONNECT/C++模块与C++进行交互

来源:互联网 发布:c语言中圆的面积 编辑:程序博客网 时间:2024/04/27 13:48

 

介绍

CONNECT/C++是一个使用S语言和C++交互的接口工具。它为使用C++的程序员提供了把SPLUS引擎集成在其中的便利,同时,它也可以整合C++代码到SPLUS环境中去。

 

为了容许在GUISPLUS间通讯,在SPLUS7中,CONNECT/C++被开发用来提供了这样一个框架(基于S语句版本4)。事实上,SPLUS7 GUI提供了使用CONNECT/C++集成SPLUS引擎和C++应用更全面的例子。同样的,C++开发者也可以使用同样的技术来和SPLUS交互

 

CONNECT/C++是一个C++类库,使用这些类和它们的成员可以创建和处理大多数的本地S对象

 

为在C++程序和模块中计算S表达式,CONNECT/C++提供了一个灵活多变的机制,在SPLUS7.X中提供了许多使用这些类库的例子,其中有些例子提供了执行相同任务的等价的SC++函数,其中C++函数大多数运行时间都要快于S代码,当然这也依赖于代码的复杂度和数据的尺寸。这些例子你可以在SHOME/sconnect目录中找到,其中SHOME为你的SPLUS的安装目录。

 

资源                 

更多关于CONNECT/C++的信息,请参见SPLUS7.0 CONNECT/C++库帮助,如果你再UNIX上,请查看SHOME/connect/help/ConnectC++ .Class.library.htm文件。这个HTML文件是一个CONNECT/C++类库的C++开发者指南。它仔细讨论了如何连接到SPLUS引擎,如何建立数据对象、调用SPLUS函数和执行SPLUS语法

 

 

 

 

 

简单的例子:一个简单应用的执行流程

 

 

 

CONNECT/C++主要用于实现这2个目标:建立一个能访问SPLUS功能的C++应用;建立一个能被SPLUS调用的C++函数,下面我们开始一个简单的应用

 

 


建立一个简单的应用


这个例子是一个控制台程序,用来在应用中建立2SPLUS向量,然后使用SPLUS来建立关于这2个向量的线性模型。

 

这个代码开始行包含了一个sconnect.h文件,这是必须的,所有CONECT/C++代码必须引用这个文件。然后定义一个全局的SPLUS连接对象,这个类的名字为CSPengineConnect, 它必须在主调函数之前定义,这个CSPengineConnect类会在客户应用和SPLUS间生成一个连接,这将允许你建立SPLUS对象,并且当数据库被附加或者被卸载到客户的时候发出通知,而且还可以执行S语言表达式等。代码看起来像下面所示:

 

#include  "sconnect.h"

 

 

//  A  global  connection  object

CSPengineConnect  g_engineConnect;

 

 

int  main(int  argc,  char*  argv[])

{

 

主函数的第一步是建立一个实际的连接对象(连接到SPLUS

 

//  Create  the  connection  to  S-PLUS

g_engineConnect.Create(  argc,  argv);

 

然后我们建立变量X,Y,这个CSPnumeric用于存储数字型向量。这个类是CONNECT/C++中的一个类,被使用在C++中用来表示SPLUS中的对象,同样,也还有很多C++类对应了SPLUS中的原子对象(见表71);接下来通过使用create方法建立这个类的一个实例,通过Assign方法赋值这个类到SPLUS数据库,如下


 

 

//  Create  S  object  with  name  "x"  in  the  current  database.

//  Same  as  x<-1:10  at  the  command  line. CSPnumeric  sx;

sx.Create("1:10","x");

 

 

//  Squaring  sx,  which  is  the  same  as  S  expression

//  sy  <-  x*x  in  a  local  frame,  but  here  we  set  it  to  local

//  C++  variable  sy. CSPnumeric  sy  =  sx  *  sx;

//  Assign  the  result  as  S  object  with  name  "y"  in  the

//  current  database. sy.Assign("y");

 

最后,我们准备合适的线性模型,通过CONNECT/C++方法在适当的时候调用SPLUS执行,如下

 

//  Evaluate  z<-lm(y~x)

g_engineConnect.SyncParseEval("z<-lm(y~x)");

 

 

return  1;

}

 

这个例子的完整代码在SHOME/samples/spllmWIN下),UNIX下这个目录在SHOM E/sconnect/samples/splm.

 

要运行这个应用,打开一个命令提示或者MS-DOS窗口(WIN)或者编译(UNIX

1.   改变当前目录到包含代码的目录

 

cd  SHOME/samples/spllm

 

(WIN)

 

cd  /sconnect/samples/splm

 

(UNIX,假设当前路径为SHOME)

 

 

 

2.   编译程序

 

msdev  spllm.dsp  /make

 

(WIN)

 

Splus7  CHAPTER  -sconnectapp  *.cxx

Splus7  make

 

(UNIX)

 

3.   如果你在WIN下,检查环境变量PATH确认它包含了%SHOM E%/cmd,如果没有,你应该在运行下面的步骤前把它加上去。

 

4.   运行程序

 

spllm.exe  S_PROJ=.

 

WIN

 

Splus7  EXEC  S.app

 

UNIX

 

要验证运行结果,在相同目录下启动SPLUS控制台(WIN)或者启动SPLUSUNIX

 

sqpe.exe  S_PROJ=.

 

WIN平台上,SPLUS将返回下面信息

 

S-PLUS  :  Copyright  (c)  1988,  2005  Insightful  Corp. Version  7.0  Release  1  for  Microsoft  Windows  :  2005

Working  data  will  be  in  E:/programs/splus7.0/users/rich

 

或者输入

 

Splus7

 

UNXI上,将返回下面信息:

 

S-PLUS  :  Copyright  (c)  1988,  2005  Insightful  Corp. Version  7.0  Release  1  for  Sun  SPARC,  SunOS  5.8  :  2005

Working  data  will  be  in  .Data

 

然后查看对象X,YZ

 

[1]

1

2

3

4

>  y

 

 

 

 

[1]

1

4

9

16

 

>  x

5     6     7     8     9     10

 

 

25    36     49     64     81     100

 

 

 

>  z

Call:

lm(formula  =  y  ~  x)

 

 

Coefficients:

(Intercept)     x

-22  11

 

 

Degrees  of  freedom:  10  total;  8  residual

Residual  standard  error:  8.124038

 

 


通过CALL调用C函数的例子


 Gauss-Seidel是一个熟悉的技术,主用于线性回归系统的解决。这个算法在SPLUS中是很容易简单明了的实现,如下

 

gaussSeidel<-

#  gaussSeidel  solves  a  linear  system  using  Gauss-Seidel

#  iterative  method.

#  REQUIRED  ARGUMENTS:

#              A  and  b  are  numeric  matrix  and  vector  respectively.

#  VALUE:

#              a  vector  x,  solution  of  A  x  =  b

#

#  Usage:

#     A<-matrix(rnorm(100),nrow=10)

#     diag(A)<-seq(ncol(A),ncol(A))  #Make  it  diagonally

#                                                                             #  dominant

#     b<-rnorm(ncol(A))

#     sys.time({x1<-gaussSeidel(A,b)})

function(A,b)

{


#  Hard-coded  relative  tolerance  and  max  iterations tol<-1.0e-4

maxItr<-1e4

 

 

#  Validating

A  <-  as.matrix(A)

b  <-  as.numeric(b)

if(nrow(A)!=ncol(A)  ||  ncol(A)!=length(b))

stop("nrow(A)!=ncol(A)  ||  ncol(A)!=length(b)")

 

 

 

 

 

 

#  Begin  Gauss-Seidel  step

x<-b

for(k  in  1:maxItr)

{

xOld<-x

for(i  in  1:nrow(A))

{

s<-  A[i,i]*x[i]

for(j  in  1:ncol(A))

s  <-  s  -  A[i,j]*x[j]

x[i]  <-  (b[i]+s)/A[i,i]

}

#  Check  convergence;  continue  if  necessary if(max(abs((x-xOld)/x))  <  tol)

return(x);

}

warning("Solution  does  not  converge/n")

return(x)

}

 

这个代码中,包含了一个嵌套的循环,也许可以写成更加有效率的代码,但我们这只是一个演示。通过使用CONNECT/C++的类和方法,下面的这些代码实现了上面类似的功能

 

这些代码开始处包含了sconnect.h头文件,这样我们就可以访问SCONNECT/C++库,下一步,它包含了一个实现Gauss-Seidel的头文件

 

#  include  "sconnect.h"

#  include  "gausssdl.h"

当我们定义gaussSeidel对象作为s_object类的一个对象时,它请求通过CALL交互

 

s_object*  gaussSeidel(s_object*  ps_A,  s_object*  ps_b)

 

作为一个典型的代码,我们定义了S_EVALUATOR.然后嵌入了我们的实现代码在try-catch块中,try 块里,可能发生的错误是可以捕抓的。如下代码

 

 

 

{

S_EVALUATOR

try

{

//  Hard-coded  relative  tolerance  and  max  iterations double  tol  =1e-4;

long  maxItr  =  1000;

 

 

//  Constructing  and  validating  C++  objects

CSPnumericMatrix  A(ps_A); CSPnumeric  b(ps_b);

if(A.nrow()!=A.ncol()  ||  A.ncol()!=b.length())

PROBLEM  "A.nrow()!=A.ncol()  ||  A.ncol()!=b.length()" ERROR;

 

实际的Gauss-Seidel步骤如下:

 

//  Begin  Gauss-Seidel  step

CSPnumeric  x=b;

for(long  k  =1;  k<=  maxItr;  k++)

{

CSPnumeric  xOld  =  x;

for(long  i=  1;  i  <=  A.nrow();  i++)

{

double  s  =  A(i,i)  *  x(i);

for(long  j  =  1;  j  <=  A.ncol();  j++)

s     =  s  -  A(i,j)  *  x(j);

x(i)  =  (b(i)+s)/A(i,i);

}

//  Check  convergence;  continue  if  necessary if(Max(abs((x-xOld)/x))  <  tol)

return(x);

}

PROBLEM  "Solution  does  not  converge"  WARN;

return(x);

}

catch(...)

{

}

return(blt_in_NULL);  //  return  the  built-in  NULL  object

}

 

 

 


UNXI上编译和执行C++


这个例子代码在SHOM E/ sconnect/samples/gausssdl下,C++代码在gausssdl.cxx

 

编译和执行C++代码

 

1.   改变当前目录到包含代码的目录

 

cd  SHOME/sconnect/samples/gausssdl

 

2.   编译共享库

 

Splus7  CHAPTER  -sconnectlib  *.cxx

Splus7  make

 

3.   运行SPLUS

 

Splus7

 

通过CHAPTER生成makefile,编译的代码只是需要在SPLUS后加上MAKE命令,如步骤2

 

MAKE前可以适当的设置环境变量

 

make工具执行了必要的命令编译和连接C++代码到共享对象S.so

.注意:-sconnectlib是被请求包含CONNECT/C++

 

通过CALL调用CONNECT/C++要比SPLUS代码快,下面是一个比较,运行在奔腾3 512内存,WIN平台,矩阵A100100

 

>  A<-matrix(rnorm(10000),nrow=100);  diag(A)<-seq(ncol(A),

+  ncol(A))  #  Make  it  diagonally  dominant

>  b<-rnorm(100);

>  sys.time({x1<-gaussSeidel(A,b)})

[1]  19.328  19.354

 

下面是一个运行在Solaris机器上的一个比较,矩阵也是100100

 

[1]  37.00  39.35

 

 

>  sys.time({x2<-.Call('gaussSeidel',A,b)})


我们比较(通过sys.time 在不同平台的输出的时间:

 

 

 

[1]  0.07  0.07

 

WIN

 

[1]  0.04  0.04

 

UNIXt.

 

可以看出,相同的CONNECT/C++版本比WIN上快250次,比纯SPLUS版本快大约1000

 

 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 裤子穿着往上跑怎么办 伤囗发炎了怎么办 玩派派背包食物不足怎么办 80岁老人植物人怎么办 steam账户创不起怎么办 小孩读书没有居住证怎么办 小孩上学没有准生证怎么办 小学在外地初中怎么办 小孩上学没准生证怎么办 没结婚出生证明怎么办 异地上高中高考怎么办 高中去外地上学怎么办 农村在城里上学怎么办? 父母没钱不工作怎么办 qq被家长偷看怎么办 孩子考差了怎么办 父母翻看qq记录怎么办 孩子qq屏蔽父母怎么办 杜鹃花老叶脱落怎么办 父母对孩子不好怎么办 家长看孩子手机怎么办 六年级打四年级学生怎么办 儿童被家长打怎么办 老师打孩子耳光怎么办 孩子动手打母亲怎么办 小孩被老师体罚怎么办 儿子跟父母对打怎么办 两个孩子争东西怎么办 大人吵架小孩该怎么办 小孩老爱顶嘴怎么办 孩子老爱顶嘴怎么办 孩子不愿分房睡怎么办 孩子不愿意去补课怎么办 高中孩子不愿意补课怎么办 孩子协调性不好怎么办 孩子暑假不愿意补课怎么办 话唠的孩子怎么办 孩孑不做作业怎么办 孩子有消极情绪怎么办 孩子太依赖奶奶怎么办 缺少母爱的孩子怎么办