Extract own IR inside IRTools dynamo - compilation

I'm trying to write an IRTools dynamo which will internally use the IR of the method it is called on. As a simplified example, keep_ir(f, args...) should return (f(args...), IR(f, args...)).
I tried the following:
IRTools.#dynamo function keep_ir(f, args...)
old_ir = IRTools.IR(f, args...)
new_ir = IRTools.empty(old_ir)
foreach(arg -> IRTools.argument!(new_ir), IRTools.arguments(old_ir))
foreach(((v, stmt),) -> push!(new_ir, stmt.expr), old_ir)
arg_types = [IRTools.xcall(Core, :Typeof, arg) for arg in IRTools.arguments(old_ir)]
original_ir = push!(new_ir, IRTools.xcall(IRTools, :IR,
IRTools.xcall(IRTools, :meta,
IRTools.xcall(Core, :apply_type,
:(Base.Tuple),
arg_types...))))
old_rv = IRTools.branches(IRTools.block(old_ir, 1))[end]
new_rv = push!(new_ir, IRTools.xcall(:tuple, old_rv.args[1], original_ir))
IRTools.return!(new_ir, new_rv)
#show new_ir # for debugging
return new_ir
end
but it fails with an obcure error:
julia> ff(x, y) = 4x + y^2, x
ff (generic function with 1 method)
julia> keep_ir(ff, 1, 20)
new_ir = 1: (%1, %2, %3)
%4 = 4 * %2
%5 = Core.apply_type(Base.Val, 2)
%6 = (%5)()
%7 = Base.literal_pow(Main.:^, %3, %6)
%8 = %4 + %7
%9 = Core.tuple(%8, %2)
%10 = Base.Tuple
%11 = Core.Typeof(%1)
%12 = Core.Typeof(%2)
%13 = Core.Typeof(%3)
%14 = Core.apply_type(%10, %11, %12, %13)
%15 = IRTools.meta(%14)
%16 = IRTools.IR(%15)
%17 = Base.tuple(%9, %16)
return %17
ERROR: error compiling keep_ir: unsupported or misplaced expression "." in function keep_ir
Stacktrace:
[1] top-level scope at REPL[76]:1
caused by [exception 1]
unsupported or misplaced expression "." in function keep_ir
Stacktrace:
[1] top-level scope at REPL[76]:1
The IR it constructed looks good to me, though...

Rather than trying to reconstruct the IR at run time, you can just splice it in as a value at compile time:
using IRTools
using IRTools: #dynamo, IR, returnvalue, block, xcall, return!
#dynamo function keepir(args...)
ir = IR(args...)
ir2 = copy(ir)
ret = push!(ir, xcall(:tuple, returnvalue(block(ir, 1)), ir2))
return!(ir, ret)
return ir
end
ff(x, y) = 4x + y^2, x
keepir(ff, 2, 3) # => ((17, 2), IR(...))
FWIW, the error you see is probably coming from the expression :(Base.Tuple) that you put in the IR. It should work if you use GlobalRef(Base, :Tuple) instead.

Related

How can I factor multiples function that gets their result process by another function?

I would like to factorize this code :
(* This function is applied to the result of functions below *)
let manage_result r s =
match r with
| Error ( `Msg e ) -> Tsdl.Sdl.log s e;exit 1
| Ok a -> a
(* Examples of function I want to factorize, let's call them f_functions, f for factorize *)
let init () =
let flag = Tsdl.Sdl.Init.everything in
let result = Tsdl.Sdl.init flag in
manage_result result "Init error : %s"
let create_window title w h =
let flag = Tsdl.Sdl.Window.windowed in
let result = Tsdl.Sdl.create_window title ~w:w ~h:h flag in
manage_result result "Create window error : %s"
let get_window_surface window =
let result = Tsdl.Sdl.get_window_surface window in
manage_result result "Get window surface error : %s"
As you can see, the two last lines of all of these f_functions are very similar. I would like to make a function that takes as argument a function ( for example, if I wanted to factorize init, the function passed as a parameter would be Tsdl.Sdl.init) and return a function that return the return value of function passed as an argument AND processed through manage_result.
The difficulty is that I don't know how many argument can the f_functions take.
Any other recommendations is appreciated!
Thank you.
A potential solution might be to use the pipe operator rather than naming the intermediary result
let on_error s r = manage_result r s
let create_window title w h =
let flag = Tsdl.Sdl.Window.windowed in
Tsdl.Sdl.create_window title ~w:w ~h:h flag
|> on_error "Create window error : %s"
Going one step further, we could define a custom operator for the error handling
let ( <!> ) = manage_result
which may make your definition lightweight enough
let create_window title w h =
let flag = Tsdl.Sdl.Window.windowed in
Tsdl.Sdl.create_window title ~w:w ~h:h flag
<!> "Create window error : %s"

OpenMP parameter sweep parallel

I am new to OpenMP. I want to solve a stiff ODE system for a range of parameter values using parallel do loops. I use the following code in Fortran given below. However, I do not know whether calling a stiff solver(as a subroutine) inside a parallel do loop is allowed or not? Also, I want to write the time series data into files with filenames such as "r_value_s__value.txt" in the subroutine before the return to the main program. Can anyone help. Below is the code and the error. I used gfortran with flags -fopenmp to compile.
PROGRAM OPENMP_PARALLEL_STIFF
USE omp_lib
IMPLICIT NONE
INTEGER :: I, J
INTEGER, PARAMETER :: RTOT=10, STOT=15
INTEGER :: TID
INTEGER, PARAMETER :: NUM_THREADS=8
DOUBLE PRECISION :: T_INITIAL, T_FINAL
CALL OMP_SET_NUM_THREADS(NUM_THREADS)
CALL CPU_TIME(T_INITIAL)
PRINT*, "TIME INITIAL ",T_INITIAL
!$OMP PARALLEL DO PRIVATE(I,J,TID)
DO I=1,RTOT
DO J=1,STOT
TID=OMP_GET_THREAD_NUM()
CALL STIFF_DRIVER(TID,I,J,RTOT,STOT)
END DO
END DO
!$OMP END PARALLEL DO
CALL CPU_TIME(T_FINAL)
PRINT*, "TIME FINAL ",T_FINAL
PRINT*, "TIME ELAPSED ",(T_FINAL-T_INITIAL)/NUM_THREADS
END PROGRAM OPENMP_PARALLEL_STIFF
SUBROUTINE STIFF_DRIVER(TID,II,JJ,RTOT,STOT)
USE USEFUL_PARAMETERS_N_FUNC
USE DVODE_F90_M
! Type declarations:
IMPLICIT NONE
! Number of odes for the problem:
INTEGER :: SERIAL_NUMBER, TID
INTEGER :: II, JJ, RTOT, STOT, IND
INTEGER :: J, NTOUT
INTEGER :: ITASK, ISTATE, ISTATS, I
! parameters : declaration
DOUBLE PRECISION, PARAMETER :: s0=0.450D0, dr=1.0D-4, ds=1.0D-2
DOUBLE PRECISION, DIMENSION(NEQ) :: Y, YOUT
DOUBLE PRECISION :: ATOL, RTOL, RSTATS, T, TOUT, EPS, TFINAL, DELTAT
DIMENSION :: RSTATS(22), ISTATS(31)
DOUBLE PRECISION :: bb, cc, ba, ba1, eta
CHARACTER(len=45) :: filename
TYPE (VODE_OPTS) :: OPTIONS
SERIAL_NUMBER=3011+II+(JJ-1)*RTOT
IND=TID+3011+II+(JJ-1)*RTOT
WRITE (*,12)SERIAL_NUMBER,TID
12 FORMAT ("SL. NO. ",I5," THREAD NO.",I3)
r=(II-1)*dr
s=s0+JJ*ds
EPS = 1.0D-9
! Open the output file:
WRITE (filename,93)r,s
93 FORMAT ("r_",f6.4,"_s_",f4.2,".txt")
OPEN (UNIT=IND,FILE=filename,STATUS='UNKNOWN',ACTION='WRITE')
! Parameters for the stiff ODE system
q0 = 0.60D0; v = 3.0D0
Va = 20.0D-4; Vs = 1.0D-1
e1 = 1.0D-1; e2 = 1.10D-5; e3 = 2.3D-3; e4=3.0D-4
del = 1.7D-4; mu = 5.9D-4
al = 1.70D-4; be = 8.9D-4; ga = 2.5D-1
! S and r dependent parameters
e1s = e1/s; e2s = e2/(s**2); e3s = e3/s; e4s = e4/s
dels = del*s; rs = r*s
e1v = e1/v; e2v = e2/(v**2); e3v = e3/v; e4v = e4/v
delv = del*v; rv = r*v
! SET INITIAL PARAMETERS for INTEGRATION ROUTINES
T = 0.0D0
TFINAL = 200.0D0
DELTAT = 0.10D0
NTOUT = INT(TFINAL/DELTAT)
RTOL = EPS
ATOL = EPS
ITASK = 1
ISTATE = 1
! Set the initial conditions: USING MODULE USEFUL_PARAMETERS_N_FUNC
CALL Y_INITIAL(NEQ,Y)
! Set the VODE_F90 options:
OPTIONS = SET_OPTS(DENSE_J=.TRUE.,USER_SUPPLIED_JACOBIAN=.FALSE., &
RELERR=RTOL,ABSERR=ATOL,MXSTEP=100000)
! Integration:
DO I=1,NTOUT
TOUT = (I-1)*DELTAT
CALL DVODE_F90(F_FUNC,NEQ,Y,T,TOUT,ITASK,ISTATE,OPTIONS)
! Stop the integration in case of an error
IF (ISTATE<0) THEN
WRITE (*,*)"ISTATE ", ISTATE
STOP
END IF
! WRITE DATA TO FILE
WRITE (IND,*) TOUT,T, Y(NEQ-2)
END DO
CLOSE(UNIT=IND)
RETURN
END SUBROUTINE STIFF_DRIVER
At line ** of file openmp_parallel_stiff.f90 (unit = 3013)
Fortran runtime error: File already opened in another unit
The issue is the format that you chose: f6.4 for r will overflow for r>=10. Then, the output will be six asterisks ****** (depending on the compiler) for all values of r>=10 on all threads. The same holds true for s.
I would suggest to either limit/check the range of these values or extend the format to honor more digits.
As #francescalus mentioned, another possibility is hit a combination of II and JJ where r and s are identical.
Just for the fun of it - let's do the math:
r=(II-1)*dr
s=s0+JJ*ds
From r=s follows
(II-1)*dr = s0+JJ*ds
or
II = 1 + s0/dr + JJ*ds/dr
Using the constants s0=0.450D0, dr=1.0D-4, ds=1.0D-2 yields
II = 4501 + JJ*10
So, whenever this combination is true for two (or more) threads at a time, you run into the observed issue.
Simple solution for this case: add the thread number to the file name.

quantstrat::apply.paramset error: attempt to select less than one element

I modified quantstrat demo bee and tried to run optimization on indicator parameters. However, I have tried to simplify optimization as much as I can, but I still got the same error as following:
error calling combine function:
<simpleError in fun(result.1, result.2, result.3, result.4, result.5, result.6, result.7, result.8, result.9, result.10): attempt to select less than one element>
Error in .subset2(x, i, exact = exact) : subscript out of bounds
my sessionInfo output:
R version 3.2.4 (2016-03-10)
Platform: x86_64-apple-darwin13.4.0 (64-bit)
Running under: OS X 10.11.4 (El Capitan)
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] parallel stats graphics grDevices utils
[6] datasets methods base
other attached packages:
[1] doMC_1.3.4
[2] iterators_1.0.8
[3] lubridate_1.5.0
[4] dplyr_0.4.3
[5] quantstrat_0.9.1739
[6] foreach_1.4.3
[7] blotter_0.9.1741
[8] PerformanceAnalytics_1.4.4000
[9] FinancialInstrument_1.2.0
[10] quantmod_0.4-5
[11] TTR_0.23-1
[12] xts_0.9-7
[13] zoo_1.7-12
loaded via a namespace (and not attached):
[1] Rcpp_0.12.3 magrittr_1.5
[3] lattice_0.20-33 R6_2.1.2
[5] stringr_1.0.0 tools_3.2.4
[7] grid_3.2.4 DBI_0.3.1
[9] htmltools_0.3 yaml_2.1.13
[11] lazyeval_0.1.10 assertthat_0.1
[13] digest_0.6.9 codetools_0.2-14
[15] rsconnect_0.4.1.4 rmarkdown_0.9.5
[17] stringi_1.0-1 compiler_3.2.4
Here is my code and data is to be download from here. Could anyone help me to figure out where goes wrong? thanks
####################################################################
#### Load packages
#####################################################################
library(dplyr)
suppressMessages(require(quantstrat))
####################################################################
#### remove objects
########################################################################
rm(list = ls(all.names = T))
if(!exists(".instrument")) .instrument <<- new.env()
if(!exists(".blotter")) .blotter <<- new.env()
if(!exists(".strategy")) .strategy <- new.env()
########################################################################
#### DEFINE VARIABLES or parameters
########################################################################
initDate = "2000-01-01"
symbol.st = 'CYB_DAY'
portf.st = 'bug'
acct.st = 'colony'
strat.st = 'bee'
initEq = 100000
nFast = 10
nSlow = 30
nSd = 1
########################################################################
#### GET DATA
###############################################################
# set your working directory where the data is stored
setwd("/Users/Natsume/Documents/data_exploration_r/data")
currency('USD') # initiate currency
stock(symbol.st ,currency='USD', multiplier=1) # initiate stock
getSymbols(Symbols = symbol.st, src = "csv")
initPortf(
portf.st,
symbol.st,
initDate=initDate) # initiate portfolio
initAcct(
acct.st,
portf.st,
initEq=initEq,
initDate=initDate) # initiate account
initOrders(
portf.st,
initDate=initDate ) # initiate order_book
bee = strategy(strat.st) # create strategy object
addPosLimit(
portfolio=portf.st,
symbol=symbol.st,
timestamp=initDate,
maxpos=300, longlevels = 3) # only trade in one direction once
bee <- add.indicator(
strategy = strat.st,
name = 'BBands', # TA name
arguments = list(HLC=quote(HLC(mktdata)),
n=nSlow,
sd=nSd),
label = 'BBand')
#### SMA column
bee <- add.indicator(
strategy = strat.st,
name = 'SMA', # TA name
arguments = list(x=quote(Cl(mktdata)),
n=nFast),
label = 'MA' )
bee <- add.signal(
strategy = strat.st,
name = 'sigCrossover',
arguments = list(columns=c('MA','dn'),
relationship='lt'),
label = 'MA.lt.dn')
#### SMA cross over upperBand
bee <- add.signal(
strategy = strat.st,
name = 'sigCrossover',
arguments = list(columns=c('MA','up'),
relationship='gt'),
label = 'MA.gt.up')
bee <- add.rule(
strategy = strat.st,
name = 'ruleSignal',
arguments = list(sigcol = 'MA.gt.up',
sigval = TRUE,
replace = F,
orderqty = 100,
ordertype = 'market',
# one of "market","limit","stoplimit", "stoptrailing", or "iceberg"
orderside = 'long',
osFUN = 'osMaxPos'),
type = 'enter',
label = 'EnterLONG')
#### exitLong when SMA cross under LowerBand
bee <- add.rule(
strategy = strat.st,
name = 'ruleSignal',
arguments = list(sigcol = 'MA.lt.dn',
sigval = TRUE,
replace = F,
orderqty = 'all',
ordertype = 'market',
orderside = 'long'),
type = 'exit',
label = 'ExitLONG')
#### enterShort when SMA cross under LowerBand
bee <- add.rule(
strategy = strat.st,
name = 'ruleSignal',
arguments = list(sigcol = 'MA.lt.dn',
sigval = TRUE,
replace = F,
orderqty = -100,
ordertype = 'market',
orderside = 'short',
osFUN = 'osMaxPos'),
type = 'enter',
label = 'EnterSHORT')
#### exitShort when SMA cross over upperBand
bee <- add.rule(
strategy = strat.st,
name = 'ruleSignal',
arguments = list(sigcol = 'MA.gt.up',
sigval = TRUE,
replace = F,
orderqty = 'all',
ordertype = 'market',
orderside = 'short'),
type = 'exit',
label = 'ExitSHORT')
applyStrategy(
strat.st,
portf.st,
prefer='Open', # why prefer='Open'
verbose=T)
updatePortf(
portf.st) #,
updateAcct(
acct.st) # ,
updateEndEq(
Account = acct.st)#,
### User Set up pf parameter ranges to test
.nFastList = 5:13
.nSlowList = 10:40
.nSdList = 1:3
# number of random samples of the parameter distribution to use for random run
.nsamples = 10
add.distribution(strat.st,
paramset.label = 'SMA_BBparams',
component.type = 'indicator',
component.label = 'BBand', #this is the label given to the indicator in the strat
variable = list(n = .nSlowList),
label = 'BBandMA'
)
add.distribution(strat.st,
paramset.label = 'SMA_BBparams',
component.type = 'indicator',
component.label = 'BBand', #this is the label given to the indicator in the strat
variable = list(sd = .nSdList),
label = 'BBandSD'
)
add.distribution(strat.st,
paramset.label = 'SMA_BBparams',
component.type = 'indicator',
component.label = 'MA', #this is the label given to the indicator in the strat
variable = list(n = .nFastList),
label = 'MAn'
)
add.distribution.constraint(strat.st,
paramset.label = 'SMA_BBparams',
distribution.label.1 = 'BBandMA',
distribution.label.2 = 'MAn',
operator = '>',
label = 'BBandMA>MAn'
)
### parallel computing to speed up
if( Sys.info()['sysname'] == "Windows" )
{
library(doParallel)
# registerDoParallel(cores=detectCores())
registerDoSEQ()
} else {
library(doMC)
registerDoMC(cores=detectCores())
}
results <- apply.paramset(strat.st,
paramset.label='SMA_BBparams',
portfolio.st=portf.st,
account.st=acct.st,
nsamples= .nsamples, # take all options
#.nsamples, only take 10 samples
verbose=TRUE)
results$tradeStats %>% View()

How to make a function with two strings as arguments

I'm not entirely sure what I'm doing wrong here. I have tested the code by input and output and it functions as desired no pun intended. :'P
I'm just not setting up this function correctly and I believe it's because my arguments happen to be desirably a string. Where if done correctly "CD" will be inserted into the middle of "ABEF". So, how do I go about doing this?
Thanks!
insertstr(ABEF, CD)
Function insertstr(string1, string2)
nostrmsg = "No string"
fullng = len(string1)
half = len(string1)/2
if half>0 then hfstr1 = mid(string1, 1, half)
str2lng = len(string2)
if str2lng>0 then paste = hfstr1+string2
lshalf = mid(string1, half+1, fullng)
if str2lng+half=str2lng+half then insert = paste+lshalf
End Function
Start with the knowledge that a functions returns a value, a tentative specification of what the function should do, and a basic testing skeleton:
Option Explicit
' returns the string build by inserting m(iddle) into f(ull) at half position
Function insertInto(f, m)
insertInto = "?"
End Function
Dim t, r
For Each t In Array( _
Array("ABEF", "CD", "ABCDEF") _
)
r = insertInto(t(0), t(1))
WScript.Echo t(0), t(1), r, CStr(r = t(2))
Next
output:
cscript 26873276.vbs
ABEF CD ? False
Then learn about Left, Mid, Len, and \ (integer division).
At last, re-write insertInto() so that the result starts with
cscript 26873276.vbs
ABEF CD ABCDEF True

Compile errors with Fortran90

All, I've been fighting these errors for hours, here's my code:
program hello
implicit none
integer :: k, n, iterator
integer, dimension(18) :: objectArray
call SetVariablesFromFile()
do iterator = 1, 18
write(*,*) objectArray(iterator)
end do
contains
subroutine SetVariablesFromFile()
IMPLICIT NONE
integer :: status, ierror, i, x
open(UNIT = 1, FILE = 'input.txt', &
ACTION = 'READ',STATUS = 'old', IOSTAT = ierror)
if(ierror /= 0) THEN
write(*, *) "Failed to open input.txt!"
stop
end if
do i = 1, 18
objectArray(i) = read(1, *, IOSTAT = status) x
if (status > 0) then
write(*,*) "Error reading input file"
exit
else if (status < 0) then
write(*,*) "EOF"
exit
end if
end do
close(1)
END subroutine SetVariablesFromFile
end program hello
I'm getting compile errors:
make: * [hello.o] Error1
Syntax error in argument list at (1)
I read online that the latter error could be due to a long line of code exceeding 132 characters, which doesn't appear to be the problem.I have no where to begin on the first error... any help would be much appreciated!
This,
objectArray(i) = read(1, *, IOSTAT = status) x
is not valid Fortran. You need to write it as,
read(1,*,iostat=status) objectArray(i)
Setting it in this correct form, I received no compiler errors with ifort 12.1, nor with gfortran 4.4.3

Resources