I'm trying to estimate ARMA(p,q) models with julia. I have a problem with the optimization of the log-likelihood function.
I have a function named "SsfLogLikConc" that estimates my concentrated log-likelihood and i would like to see it as function of vP, that is the value of my parameters phi and theta, and then optimize this function starting from the value vP0=zeros(cp+cq,1)where cp and cp represent the p and q orders of my ARMA(p,q) model. I tried to do it in this way:
vP0=zeros(cp+cq,1)
function f(vP)
SsfLogLikConc(vP, vy, cp, cq)
end
using Optim
res=optimize(f, vP0, BFGS())
But i keep getting errors from the optimize function even if change the method. Here is the full code:
function FisherInvTransform(Vp)
vt = (exp(2*vP)-1) ./ (exp(2*vP)+1)
end
function ReparAR(vr)
cp = length(vr)
vphi = zeros(cp,1);
vphi[1] = vr[1]
for k=2:cp
vphi[1:k-1] = vphi[1:k-1] - vr[k] * vphi[k-1:-1:1]
vphi[k] = vr[k]
end
end
function ReparMA(vr)
cq = length(vr)
vtheta = zeros(cq,1)
vtheta[1] = vr[1]
for k = 2:cq
vtheta[1:k-1] = vtheta[1:k-1] + vr[k] * vtheta[k-1:-1:1]
vtheta[k] = vr[k]
end
end
function SetStateSpaceModel(vP, cp, cq)
cm = max(cp,cq)
vphi = zeros(cm, 1)
vtheta = zeros(cm, 1)
if (cp > 0)
vphi[1:cp] = ReparAR(FisherInvTransform(vP[1:cp]))
end
if (cq > 0)
vtheta[1:cq] = ReparMA(FisherInvTransform(vP[cp+1:cp+cq]));
end
#Measurement equation: % y_{t} = Z_t \alpha_{t} + G_t \epsilon_t
mZ = [1, zeros(1, cm-1)]
mGG = 1 #G_t * G_t'
#Transition equation: % \alpha_{t+1} = T_t \alpha_{t} + H_t \epsilon_t
mT = [vphi, [eye(cm-1); zeros(1, cm-1)] ]
disp(mT)
disp( vphi)
mH = vtheta+vphi
mHH = mH*mH' #H_t * H_t'
mHG = mH
#initial conditions
va = zeros(cm,1)
mP = reshape(inv(eye(cm^2)-kron(mT,mT)) * reshape(mHH, cm^2,1) , cm, cm)
end
function KalmanFilter(vy, mZ, mGG, mT, mHH, mHG, va, mP)
cm = length(va) #n. of state elements and of diffuse elements
ck = 1
cn = length(vy)
#Initialisation of matrices and scalars
dLogf = 0
dSumSquares = 0
vInnovations = NaN(1, cn) #stores the KF innovations
vVarInnovations = NaN(1, cn)
mStatePred = NaN(cm, cn) #stores the states predictions
mCovStatePred = NaN(cm, cn)
for i = 1:cn
dv = vy[i] - mZ * va; dF = mZ * mP * mZ' + mGG;
vK = (mT * mP * mZ' + mHG) / dF;
va = mT * va + vK * dv; mP = mT * mP * mT' + mHH - vK * vK' * dF ;
if (i > ck)
vInnovations[i] = dv; vVarInnovations[i] = dF;
dLogf = dLogf + log(dF); dSumSquares = dSumSquares + dv^2 /dF;
end
mStatePred[:,i] = va; mCovStatePred[:,i] = diag(mP);
end
dSigma = dSumSquares/(cn-ck);
dLogLik = -0.5 * ((cn - ck) * log(2 * pi) + dLogf + dSumSquares );
dLogLikConc = -0.5*((cn - ck)* (log(2 * pi * dSigma)+1) + dLogf );
dPev = dSigma * dF ; # Final prediction error variance
end
function SsfLogLikConc(vP, vy, cp, cq)
SetStateSpaceModel(vP, cp, cq)
dLogF = 0; dSumSquares = 0;
cn = length(vy)
for i = 1:cn
dv = vy[i] - mZ * va; dF = mZ * mP * mZ' + mGG;
vK = (mT * mP * mZ' + mHG) / dF;
va = mT * va + vK * dv; mP = mT * mP * mT' + mHH - vK * dF * vK' ;
dLogF = dLogF + log(dF);
dSumSquares = dSumSquares + dv^2 /dF;
end
dSigma2 = dSumSquares/cn;
dLogLikConc = 0.5*( cn * (log(dSigma2)+1) + dLogF ); # concentrated LF (change of sign)
end
#Pkg.add("DataFrames")
using DataFrames;
cd("$(homedir())/Desktop")
pwd()
df=readtable("df.csv")
df
o=df[2]
mean(o)
vy=zeros(1000)
for i=1:length(o)
vy[i]=o[i]-mean(o)
end
cp = 1; cq =1;
vP0 = zeros(cp+cq,1)
function f(vP)
SsfLogLikConc(vP, vy, cp, cq)
end
#Pkg.add("Optim")
using Optim
res=optimize(f, vP0, BFGS())
Thank you for reading, I hope that someone will help me!
Related
My question is about the Linear Regression drawing.
The example in the documentation uses a fixed length (100), and is therefore :
shifting to the right on each new bar
of constant width (here 100 bars)
I'm trying to make it start from a custom point in time (x bars from now or bar_index or datetime...), so that :
it keeps extending on each new bar
but the starting point remains on the same location (until we change it in the settings).
That means that the length (input) would be dynamic and increase on each new bar.
I am getting the following error : Pine cannot determine the referencing length of a series. Try using max_bars_back in the study or strategy function.
Is it possible to do ?
Here is the code
//#version=4
study("Linear Regression", shorttitle="LinReg", overlay=true)
upperMult = input(title="Upper Deviation", defval=2)
lowerMult = input(title="Lower Deviation", defval=-2)
useUpperDev = input(title="Use Upper Deviation", defval=true)
useLowerDev = input(title="Use Lower Deviation", defval=true)
showPearson = input(title="Show Pearson's R", defval=true)
extendLines = input(title="Extend Lines", defval=false)
// ====================================================================
// ====================================================================
// Original parameter (the one that should increments)
// len = input(title="Count", defval=100)
// Unsuccessful attempt : "Starting from given bar_index"
barIndexOfStartingBar = 6392 - 80 // 6392 : Current bar_index, 80 : Offset to the starting bar
len = bar_index - barIndexOfStartingBar
len := nz(len[1]) + 1
// Unsuccessful attempt : "x bars from current bar"
startingPointFromCurrentBar = input(title="Count", defval=80)
len = (bar_index + startingPointFromCurrentBar) - bar_index
len := nz(len[1]) + 1
// ====================================================================
// ====================================================================
src = input(title="Source", defval=close)
extend = extendLines ? extend.right : extend.none
calcSlope(src, len) =>
if not barstate.islast or len <= 1
[float(na), float(na), float(na)]
else
sumX = 0.0
sumY = 0.0
sumXSqr = 0.0
sumXY = 0.0
for i = 0 to len - 1
val = src[i]
per = i + 1.0
sumX := sumX + per
sumY := sumY + val
sumXSqr := sumXSqr + per * per
sumXY := sumXY + val * per
slope = (len * sumXY - sumX * sumY) / (len * sumXSqr - sumX * sumX)
average = sumY / len
intercept = average - slope * sumX / len + slope
[slope, average, intercept]
[s, a, i] = calcSlope(src, len)
startPrice = i + s * (len - 1)
endPrice = i
var line baseLine = na
if na(baseLine) and not na(startPrice)
baseLine := line.new(bar_index - len + 1, startPrice, bar_index, endPrice, width=1, extend=extend, color=color.red)
else
line.set_xy1(baseLine, bar_index - len + 1, startPrice)
line.set_xy2(baseLine, bar_index, endPrice)
na
calcDev(src, len, slope, average, intercept) =>
upDev = 0.0
dnDev = 0.0
stdDevAcc = 0.0
dsxx = 0.0
dsyy = 0.0
dsxy = 0.0
periods = len - 1
daY = intercept + (slope * periods) / 2
val = intercept
for i = 0 to periods
price = high[i] - val
if (price > upDev)
upDev := price
price := val - low[i]
if (price > dnDev)
dnDev := price
price := src[i]
dxt = price - average
dyt = val - daY
price := price - val
stdDevAcc := stdDevAcc + price * price
dsxx := dsxx + dxt * dxt
dsyy := dsyy + dyt * dyt
dsxy := dsxy + dxt * dyt
val := val + slope
stdDev = sqrt(stdDevAcc / (periods == 0 ? 1 : periods))
pearsonR = dsxx == 0 or dsyy == 0 ? 0 : dsxy / sqrt(dsxx * dsyy)
[stdDev, pearsonR, upDev, dnDev]
[stdDev, pearsonR, upDev, dnDev] = calcDev(src, len, s, a, i)
upperStartPrice = startPrice + (useUpperDev ? upperMult * stdDev : upDev)
upperEndPrice = endPrice + (useUpperDev ? upperMult * stdDev : upDev)
var line upper = na
lowerStartPrice = startPrice + (useLowerDev ? lowerMult * stdDev : -dnDev)
lowerEndPrice = endPrice + (useLowerDev ? lowerMult * stdDev : -dnDev)
var line lower = na
if na(upper) and not na(upperStartPrice)
upper := line.new(bar_index - len + 1, upperStartPrice, bar_index, upperEndPrice, width=1, extend=extend, color=#0000ff)
else
line.set_xy1(upper, bar_index - len + 1, upperStartPrice)
line.set_xy2(upper, bar_index, upperEndPrice)
na
if na(lower) and not na(lowerStartPrice)
lower := line.new(bar_index - len + 1, lowerStartPrice, bar_index, lowerEndPrice, width=1, extend=extend, color=#0000ff)
else
line.set_xy1(lower, bar_index - len + 1, lowerStartPrice)
line.set_xy2(lower, bar_index, lowerEndPrice)
na
// Pearson's R
var label r = na
transparent = color.new(color.white, 100)
label.delete(r[1])
if showPearson and not na(pearsonR)
r := label.new(bar_index - len + 1, lowerStartPrice, tostring(pearsonR, "#.################"), color=transparent, textcolor=#0000ff, size=size.normal, style=label.style_labelup)
With these changes you should be able to go back a few thousand bars:
study("Linear Regression", shorttitle="LinReg", overlay=true, max_bars_back = 4999)
and either one of these:
// #1
offsetToStart = input(100, minval = 1, step = 100)
len = max(1, offsetToStart)
// #2
startingBar = input(10000, minval = 1, step = 100)
len = max(1, bar_index - startingBar)
What you are looking for is called anchoring. You can do this with a trick. What I usually do is the following:
p = input("D", title="Period", type=input.resolution)
offsetToStart = input(0, title="Begin Offset") // remove the minval
newbar(p) => change(time(p)) == 0?0:1
nb = newbar(p)
bars = barssince(nb) + offsetToStart
var line l1 = na
l1 := line.new(bar_index[bars], open, bar_index[bars], open + syminfo.mintick, extend=extend.both)
line.delete(l1[1])
Remember to remove the minval. Chose the period and you can now anchor beginning of your indicator. Playaround with p
I use some functions in my main code which they return some values (scalar).
These values will compare in main code.
But when I run the code it has this Error:
"ERROR: MethodError: no method matching isless(::Array{Float64,1}, ::Array{Float64,1})"
Please help me. This is the code:
using JuMP, CPLEX
ZT = [-36 ; -244.5 ];
ZB = [27.149 ; -288.747];
M = 5;
model = CreateModel();
WES = model[1];
f1 = model[2]; f2 = model[3];
rf1 = model[4]; rf2 = model[5];
lf1 = model[6]; lf2 = model[7];
x = WES[:x] ; y = WES[:y] ;
JuMP.setRHS( rf1, ZB[1] ); JuMP.setRHS( lf1, ZT[1] );
JuMP.setRHS( rf2, ZT[2] ); JuMP.setRHS( lf2, ZB[2] );
ZI, ofvInt = Intpoint( ZB, ZT );
Hgap, Vgap, ZG, ofvGap = Gappoint( ZB, ZT );
if ofvInt !== NaN
y = ZI[2];
elseif ofvGap !== NaN
if isless( Hgap, M + Vgap ) # "MethodError: no method matching
# isless(::Array{Float64,1}, ::Array{Float64,1})"
y = ZG[1]
end
y = ZG[2];
else
y = ( ZB[2] + ZT[2] ) / 2;
end
I want to know the length of a Path.
For example, if I have a straight line I can just compute the length with its start x,y and end x,y values. But it gets quickly very tricky if I use QuadCurves or CubicCurves.
Is there any way to get the length or an approximation of the length of a Path?
For example the following path:
Path path = new Path();
MoveTo moveTo = new MoveTo(start.getX(), start.getY());
double controlPointX = 50;
CubicCurveTo cubicCurveTo = new CubicCurveTo(start.getX() + controlPointX, start.getY(),
start.getX() + controlPointX, end.getY(), end.getX(), end.getY());
path.getElements().addAll(moveTo, cubicCurveTo);
I needed this recently as well. I couldn't find any solutions online, but it occurred to me PathTransition must be calculating it. It does, see PathTransition.recomputeSegment, where totalLength is calculated.
Unfortunately, it uses many internal APIs in Node and the PathElement to convert the Path to a java.awt.geom.Path2D. I extracted these methods out and replaced other usages of com.sun classes with java.awt ones, then pulled the parts relevant to calculating length out of PathTransition.recomputeSegments.
The resulting code is below. It is in Kotlin not Java, but it should be easy to convert it back to Java. I have not yet tested it extensively but it seems to be working on the fairly complex paths I have tested it against. I've compared my results to the length calculated by PathTransition and they are very close, I believe the discrepancies are due to my code using Path2D.Double where as Path2D.Float is used by PathElement.impl_addTo.
fun Transform.toAffineTransform(): AffineTransform {
if(!isType2D) throw UnsupportedOperationException("Conversion of 3D transforms is unsupported")
return AffineTransform(mxx, myx, mxy, myy, tx, ty)
}
val Path.totalLength: Double
get() {
var length = 0.0
val coords = DoubleArray(6)
var pt = 0 // Previous segment type
var px = 0.0 // Previous x-coordinate
var py = 0.0 // Previous y-coordinate
var mx = 0.0 // Last move to x-coordinate
var my = 0.0 // Last move to y-coordinate
val pit = toPath2D().getPathIterator(localToParentTransform.toAffineTransform(), 1.0)
while(!pit.isDone) {
val type = pit.currentSegment(coords)
val x = coords[0]
val y = coords[1]
when(type) {
PathIterator.SEG_MOVETO -> {
mx = x
my = y
}
PathIterator.SEG_LINETO -> {
val dx = x - px
val dy = y - py
val l = sqrt(dx * dx + dy * dy)
if(l >= 1 || pt == PathIterator.SEG_MOVETO) length += l
}
PathIterator.SEG_CLOSE -> {
val dx = x - mx
val dy = y - my
val l = sqrt(dx * dx + dy * dy)
if(l >= 1 || pt == PathIterator.SEG_MOVETO) length += l
}
}
pt = type
px = x
py = y
pit.next()
}
return length
}
fun Path.toPath2D(): Path2D {
val path: Path2D = Path2D.Double(if(fillRule == FillRule.EVEN_ODD) Path2D.WIND_EVEN_ODD else Path2D.WIND_NON_ZERO)
for(e in elements) {
when(e) {
is Arc2D -> append(e as ArcTo, path) // Why isn't this smart casted?
is ClosePath -> path.closePath()
is CubicCurveTo -> append(e, path)
is HLineTo -> append(e, path)
is LineTo -> append(e, path)
is MoveTo -> append(e, path)
is QuadCurveTo -> append(e, path)
is VLineTo -> append(e, path)
else -> throw UnsupportedOperationException("Path contains unknown PathElement type: " + e::class.qualifiedName)
}
}
return path
}
private fun append(arcTo: ArcTo, path: Path2D) {
val x0 = path.currentPoint.x
val y0 = path.currentPoint.y
val localX = arcTo.x
val localY = arcTo.y
val localSweepFlag = arcTo.isSweepFlag
val localLargeArcFlag = arcTo.isLargeArcFlag
// Determine target "to" position
val xto = if(arcTo.isAbsolute) localX else localX + x0
val yto = if(arcTo.isAbsolute) localY else localY + y0
// Compute the half distance between the current and the final point
val dx2 = (x0 - xto) / 2.0
val dy2 = (y0 - yto) / 2.0
// Convert angle from degrees to radians
val xAxisRotationR = Math.toRadians(arcTo.xAxisRotation)
val cosAngle = Math.cos(xAxisRotationR)
val sinAngle = Math.sin(xAxisRotationR)
//
// Step 1 : Compute (x1, y1)
//
val x1 = cosAngle * dx2 + sinAngle * dy2
val y1 = -sinAngle * dx2 + cosAngle * dy2
// Ensure radii are large enough
var rx = abs(arcTo.radiusX)
var ry = abs(arcTo.radiusY)
var Prx = rx * rx
var Pry = ry * ry
val Px1 = x1 * x1
val Py1 = y1 * y1
// check that radii are large enough
val radiiCheck = Px1 / Prx + Py1 / Pry
if (radiiCheck > 1.0) {
rx *= sqrt(radiiCheck)
ry *= sqrt(radiiCheck)
if(rx == rx && ry == ry) {/* not NANs */ }
else {
path.lineTo(xto, yto)
return
}
Prx = rx * rx
Pry = ry * ry
}
//
// Step 2 : Compute (cx1, cy1)
//
var sign = if (localLargeArcFlag == localSweepFlag) -1.0 else 1.0
var sq = (Prx * Pry - Prx * Py1 - Pry * Px1) / (Prx * Py1 + Pry * Px1)
sq = if (sq < 0.0) 0.0 else sq
val coef = sign * Math.sqrt(sq)
val cx1 = coef * (rx * y1 / ry)
val cy1 = coef * -(ry * x1 / rx)
//
// Step 3 : Compute (cx, cy) from (cx1, cy1)
//
val sx2 = (x0 + xto) / 2.0
val sy2 = (y0 + yto) / 2.0
val cx = sx2 + (cosAngle * cx1 - sinAngle * cy1)
val cy = sy2 + (sinAngle * cx1 + cosAngle * cy1)
//
// Step 4 : Compute the angleStart (angle1) and the angleExtent (dangle)
//
val ux = (x1 - cx1) / rx
val uy = (y1 - cy1) / ry
val vx = (-x1 - cx1) / rx
val vy = (-y1 - cy1) / ry
// Compute the angle start
var n = sqrt(ux * ux + uy * uy)
var p = ux // (1 * ux) + (0 * uy)
sign = if (uy < 0.0) -1.0 else 1.0
var angleStart = (sign * Math.acos(p / n)).toDegrees()
// Compute the angle extent
n = Math.sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy))
p = ux * vx + uy * vy
sign = if (ux * vy - uy * vx < 0.0) -1.0 else 1.0
var angleExtent = Math.toDegrees(sign * Math.acos(p / n))
if(!localSweepFlag && angleExtent > 0) angleExtent -= 360.0
else if(localSweepFlag && angleExtent < 0) angleExtent += 360.0
angleExtent %= 360
angleStart %= 360
//
// We can now build the resulting Arc2D
//
val arcX = cx - rx
val arcY = cy - ry
val arcW = rx * 2.0
val arcH = ry * 2.0
val arcStart = -angleStart
val arcExtent = -angleExtent
val arc = Arc2D.Double(OPEN).apply { setArc(arcX, arcY, arcW, arcH, arcStart, arcExtent, OPEN) }
val xform: AffineTransform? = when(xAxisRotationR) {
0.0 -> null
else -> AffineTransform().apply { setToRotation(xAxisRotationR, cx, cy) }
}
val pi = arc.getPathIterator(xform)
// RT-8926, append(true) converts the initial moveTo into a
// lineTo which can generate huge miter joins if the segment
// is small enough. So, we manually skip it here instead.
pi.next()
path.append(pi, true)
}
private fun append(cubicCurveTo: CubicCurveTo, path: Path2D) {
if(cubicCurveTo.isAbsolute) {
path.curveTo(cubicCurveTo.controlX1, cubicCurveTo.controlY1,
cubicCurveTo.controlX2, cubicCurveTo.controlY2,
cubicCurveTo.x, cubicCurveTo.y)
}
else {
val dx = path.currentPoint.x
val dy = path.currentPoint.y
path.curveTo(cubicCurveTo.controlX1 + dx, cubicCurveTo.controlY1 + dy,
cubicCurveTo.controlX2 + dx, cubicCurveTo.controlY2 + dy,
cubicCurveTo.x + dx, cubicCurveTo.y + dy)
}
}
private fun append(hLineTo: HLineTo, path: Path2D) {
if(hLineTo.isAbsolute) path.lineTo(hLineTo.x, path.currentPoint.y)
else path.lineTo(path.currentPoint.x + hLineTo.x, path.currentPoint.y)
}
private fun append(lineTo: LineTo, path: Path2D) {
if(lineTo.isAbsolute) path.lineTo(lineTo.x, lineTo.y)
else path.lineTo(path.currentPoint.x + lineTo.x, path.currentPoint.y + lineTo.y)
}
private fun append(moveTo: MoveTo, path: Path2D) {
if(moveTo.isAbsolute) path.moveTo(moveTo.x, moveTo.y)
else path.moveTo((path.currentPoint.x + moveTo.x), path.currentPoint.y + moveTo.y)
}
private fun append(quadCurveTo: QuadCurveTo, path: Path2D) {
if(quadCurveTo.isAbsolute) {
path.quadTo(quadCurveTo.controlX, quadCurveTo.controlY,
quadCurveTo.x, quadCurveTo.y)
}
else {
val dx = path.currentPoint.x
val dy = path.currentPoint.y
path.quadTo(quadCurveTo.controlX + dx, quadCurveTo.controlY + dy,
quadCurveTo.x + dx, quadCurveTo.y + dy)
}
}
private fun append(vLineTo: VLineTo, path: Path2D) {
if(vLineTo.isAbsolute) path.lineTo(path.currentPoint.x, vLineTo.y)
else path.lineTo(path.currentPoint.x, path.currentPoint.y + vLineTo.y)
}
Here is what I want to achieve.
The parameters are both circles radius, x - centers, and y - centers. The function to make line is line(x1, y1, x2, y2).
Here is what I have now using JavaScript.
var lineX1 = circleX1 + (circleRadius1 * Math.sin(Math.atan2(circleY2 - circleY1, circleX2 - circleX1)));
var lineY1 = circleY1 + (circleRadius1 * Math.cos(Math.atan2(circleY2 - circleY1, circleX2 - circleX1)));
var lineX2 = circleX2 - (circleRadius2 * Math.sin(Math.atan2(circleY1 - circleY2, circleX1 - circleX2)));
var lineY2 = circleY2 - (circleRadius2 * Math.cos(Math.atan2(circleY1 - circleY2, circleX1 - circleX2)));
line(lineX1, lineY1, lineX2, lineY2);
But it looks like this.
There is no need in trigonometric functions.
center difference vector
dx = cx2 - cx1
dy = cy2 - cy1
len = Math.Sqrt(dx*dx + dy*dy)
normalized
udx = dx / len
udy = dy / len
line ends
lx1 = cx1 + udx * r1
ly1 = cy1 + udy * r1
lx2 = cx2 - udx * r2
ly2 = cy2 - udy * r2
You are almost correct. As #welbog pointed out, you want to use Math.atan2. Also, you swapped your cos and sin for the x/y. Finally, you only need to calculate the angle once.
Here's a demonstration:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3#4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<script>
var svg = d3.select('body')
.append('svg')
.attr('width', 500)
.attr('height', 500);
draw();
function draw() {
svg.selectAll("*").remove();
var circleRadius1 = Math.random() * 100,
circleRadius2 = Math.random() * 100,
circleX1 = Math.random() * 500,
circleY1 = Math.random() * 500,
circleX2 = Math.random() * 500,
circleY2 = Math.random() * 500;
svg.append('circle')
.attr('r', circleRadius1)
.attr('cx', circleX1)
.attr('cy', circleY1)
.style('fill', 'none')
.style('stroke', 'steelblue');
svg.append('circle')
.attr('r', circleRadius2)
.attr('cx', circleX2)
.attr('cy', circleY2)
.style('fill', 'none')
.style('stroke', 'orange');
var angle = Math.atan2(circleY2 - circleY1, circleX2 - circleX1),
lineX1 = circleX1 + (circleRadius1 * Math.cos(angle)),
lineY1 = circleY1 + (circleRadius1 * Math.sin(angle)),
lineX2 = circleX2 - (circleRadius2 * Math.cos(angle)),
lineY2 = circleY2 - (circleRadius2 * Math.sin(angle));
svg.append('line')
.attr('x1', lineX1)
.attr('y1', lineY1)
.attr('x2', lineX2)
.attr('y2', lineY2)
.style('stroke','black')
setTimeout(draw, 1000);
}
</script>
</body>
</html>
I'm using Incanter and Parallel Colt for a project, and need to have a function that returns the modified Bessel function of an order n for a value v.
The Colt library has two methods for order 0 and order 1, but beyond that, only a method that return the Bessel function of order n for a value v (cern.jet.math.tdouble.Bessel/jn).
I'm trying to build the R function, dskellam(x,lambda1, lambda2) for the Skellam distribution, in Clojure/Java
Is there something I can do with the return value of the Bessel method to convert it to a modified Bessel?
No, the difference isn't a simple transformation, as these links make clear:
http://mathworld.wolfram.com/BesselFunctionoftheFirstKind.html
http://mathworld.wolfram.com/ModifiedBesselFunctionoftheFirstKind.html
I'd have a look at "Numerical Recipes" or Abramowitz & Stegun. It wouldn't be hard to implement your own in a short period of time.
Here's a Java implementation of the modified Bessel functions:
package math;
/**
* Functions that are not part of standard libraries
* User: Michael
* Date: 1/9/12
* Time: 9:22 PM
*/
public class Functions {
public static final double ACC = 4.0;
public static final double BIGNO = 1.0e10;
public static final double BIGNI = 1.0e-10;
public static void main(String[] args) {
double xmin = ((args.length > 0) ? Double.valueOf(args[0]) : 0.0);
double xmax = ((args.length > 1) ? Double.valueOf(args[1]) : 4.0);
double dx = ((args.length > 2) ? Double.valueOf(args[2]) : 0.1);
System.out.printf("%10s %10s %10s %10s\n", "x", "bessi0(x)", "bessi1(x)", "bessi2(x)");
for (double x = xmin; x < xmax; x += dx) {
System.out.printf("%10.6f %10.6f %10.6f %10.6f\n", x, bessi0(x), bessi1(x), bessi(2, x));
}
}
public static final double bessi0(double x) {
double answer;
double ax = Math.abs(x);
if (ax < 3.75) { // polynomial fit
double y = x / 3.75;
y *= y;
answer = 1.0 + y * (3.5156229 + y * (3.0899424 + y * (1.2067492 + y * (0.2659732 + y * (0.360768e-1 + y * 0.45813e-2)))));
} else {
double y = 3.75 / ax;
answer = 0.39894228 + y * (0.1328592e-1 + y * (0.225319e-2 + y * (-0.157565e-2 + y * (0.916281e-2 + y * (-0.2057706e-1 + y * (0.2635537e-1 + y * (-0.1647633e-1 + y * 0.392377e-2)))))));
answer *= (Math.exp(ax) / Math.sqrt(ax));
}
return answer;
}
public static final double bessi1(double x) {
double answer;
double ax = Math.abs(x);
if (ax < 3.75) { // polynomial fit
double y = x / 3.75;
y *= y;
answer = ax * (0.5 + y * (0.87890594 + y * (0.51498869 + y * (0.15084934 + y * (0.2658733e-1 + y * (0.301532e-2 + y * 0.32411e-3))))));
} else {
double y = 3.75 / ax;
answer = 0.2282967e-1 + y * (-0.2895312e-1 + y * (0.1787654e-1 - y * 0.420059e-2));
answer = 0.39894228 + y * (-0.3988024e-1 + y * (-0.362018e-2 + y * (0.163801e-2 + y * (-0.1031555e-1 + y * answer))));
answer *= (Math.exp(ax) / Math.sqrt(ax));
}
return answer;
}
public static final double bessi(int n, double x) {
if (n < 2)
throw new IllegalArgumentException("Function order must be greater than 1");
if (x == 0.0) {
return 0.0;
} else {
double tox = 2.0/Math.abs(x);
double ans = 0.0;
double bip = 0.0;
double bi = 1.0;
for (int j = 2*(n + (int)Math.sqrt(ACC*n)); j > 0; --j) {
double bim = bip + j*tox*bi;
bip = bi;
bi = bim;
if (Math.abs(bi) > BIGNO) {
ans *= BIGNI;
bi *= BIGNI;
bip *= BIGNI;
}
if (j == n) {
ans = bip;
}
}
ans *= bessi0(x)/bi;
return (((x < 0.0) && ((n % 2) == 0)) ? -ans : ans);
}
}
}