Optim.jl does many redundant function calls. For a function of 6 variables and method LBFGS() (with no supplied gradient - my function is the solution to a fixed point problem with no easy to compute gradient and ForwardDiff and ReverseDiff, for some reason, don't work with my code).
It calls the function 39 times in the first iteration. What is more, many of these function calls are evaluated at exactly the same inputs. This seems very inefficient - am I doing something wrong? If not, what are some things I could do to increase efficiency?
My code is currently the following - let me know if you need more to give an answer.
function f(x::Vector{Float64})
modelPar.ρ = x[1]
modelPar.χI = x[2]
modelPar.χS = x[3]
modelPar.χE = x[4] * x[3]
modelPar.λ = x[5]
modelPar.ν = x[6]
f = open("figures/log.txt","a")
write(f,"Iteration: ρ = $(x[1]); χI = $(x[2]); χS = $(x[3]);
χE = $(x[3] * x[4]); λ = $(x[5]); ν = $(x[6])\n")
close(f)
output = computeScore(algoPar,modelPar,guess,targets,weights)
end
initial_x = [ modelPar.ρ;
modelPar.χI;
modelPar.χS;
modelPar.χE / modelPar.χS;
modelPar.λ;
modelPar.ν ]
lower = [0.01, 0.1, 0.1, 0.01, 1.001, 0.01]
upper = [0.1, 6, 6, 0.99, 1.5, 0.5]
inner_optimizer = LBFGS()
results = optimize(f,lower,upper,initial_x,Fminbox(inner_optimizer),
Optim.Options(iterations = 0, store_trace = true, show_trace = true))
The trace is the following
Results of Optimization Algorithm
* Algorithm: Fminbox with L-BFGS
* Starting Point: [0.04,4.0,2.0,0.5,1.05,0.05]
* Minimizer: [0.04,4.0,2.0,0.5,1.05,0.05]
* Minimum: 2.069848e-02
* Iterations: 1
* Convergence: true
* |x - x'| ≤ 0.0e+00: true
|x - x'| = 0.00e+00
* |f(x) - f(x')| ≤ 0.0e+00 |f(x)|: true
|f(x) - f(x')| = 0.00e+00 |f(x)|
* |g(x)| ≤ 1.0e-08: false
|g(x)| = 1.63e-01
* Stopped by an increasing objective: false
* Reached Maximum Number of Iterations: true
* Objective Calls: 1
* Gradient Calls: 1
However, the file log.txt is 39 lines long and has the following contents:
Iteration: ρ = 0.04000605545445239; χI = 4.0; χS = 2.0; χE = 1.0; λ = 1.05; ν = 0.05
Iteration: ρ = 0.03999394454554761; χI = 4.0; χS = 2.0; χE = 1.0; λ = 1.05; ν = 0.05
Iteration: ρ = 0.04; χI = 4.000024221817809; χS = 2.0; χE = 1.0; λ = 1.05; ν = 0.05
Iteration: ρ = 0.04; χI = 3.9999757781821903; χS = 2.0; χE = 1.0; λ = 1.05; ν = 0.05
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0000121109089046; χE = 1.0000060554544523; λ = 1.05; ν = 0.05
Iteration: ρ = 0.04; χI = 4.0; χS = 1.9999878890910952; χE = 0.9999939445455476; λ = 1.05; ν = 0.05
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0; χE = 1.0000121109089048; λ = 1.05; ν = 0.05
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0; χE = 0.9999878890910953; λ = 1.05; ν = 0.05
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0; χE = 1.0; λ = 1.050006358227175; ν = 0.05
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0; χE = 1.0; λ = 1.049993641772825; ν = 0.05
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0; χE = 1.0; λ = 1.05; ν = 0.05000605545445239
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0; χE = 1.0; λ = 1.05; ν = 0.04999394454554761
Iteration: ρ = 0.04000605545445239; χI = 4.0; χS = 2.0; χE = 1.0; λ = 1.05; ν = 0.05
Iteration: ρ = 0.03999394454554761; χI = 4.0; χS = 2.0; χE = 1.0; λ = 1.05; ν = 0.05
Iteration: ρ = 0.04; χI = 4.000024221817809; χS = 2.0; χE = 1.0; λ = 1.05; ν = 0.05
Iteration: ρ = 0.04; χI = 3.9999757781821903; χS = 2.0; χE = 1.0; λ = 1.05; ν = 0.05
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0000121109089046; χE = 1.0000060554544523; λ = 1.05; ν = 0.05
Iteration: ρ = 0.04; χI = 4.0; χS = 1.9999878890910952; χE = 0.9999939445455476; λ = 1.05; ν = 0.05
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0; χE = 1.0000121109089048; λ = 1.05; ν = 0.05
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0; χE = 0.9999878890910953; λ = 1.05; ν = 0.05
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0; χE = 1.0; λ = 1.050006358227175; ν = 0.05
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0; χE = 1.0; λ = 1.049993641772825; ν = 0.05
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0; χE = 1.0; λ = 1.05; ν = 0.05000605545445239
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0; χE = 1.0; λ = 1.05; ν = 0.04999394454554761
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0; χE = 1.0; λ = 1.05; ν = 0.05
Iteration: ρ = 0.04000605545445239; χI = 4.0; χS = 2.0; χE = 1.0; λ = 1.05; ν = 0.05
Iteration: ρ = 0.03999394454554761; χI = 4.0; χS = 2.0; χE = 1.0; λ = 1.05; ν = 0.05
Iteration: ρ = 0.04; χI = 4.000024221817809; χS = 2.0; χE = 1.0; λ = 1.05; ν = 0.05
Iteration: ρ = 0.04; χI = 3.9999757781821903; χS = 2.0; χE = 1.0; λ = 1.05; ν = 0.05
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0000121109089046; χE = 1.0000060554544523; λ = 1.05; ν = 0.05
Iteration: ρ = 0.04; χI = 4.0; χS = 1.9999878890910952; χE = 0.9999939445455476; λ = 1.05; ν = 0.05
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0; χE = 1.0000121109089048; λ = 1.05; ν = 0.05
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0; χE = 0.9999878890910953; λ = 1.05; ν = 0.05
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0; χE = 1.0; λ = 1.050006358227175; ν = 0.05
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0; χE = 1.0; λ = 1.049993641772825; ν = 0.05
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0; χE = 1.0; λ = 1.05; ν = 0.05000605545445239
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0; χE = 1.0; λ = 1.05; ν = 0.04999394454554761
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0; χE = 1.0; λ = 1.05; ν = 0.05
Iteration: ρ = 0.04; χI = 4.0; χS = 2.0; χE = 1.0; λ = 1.05; ν = 0.05
What is going on here?
1.0e-08 is quite low. Could you try with g_tol=1.0e-6 to see it it converges?
results = optimize(f, lower, upper, initial_x, Fminbox(inner_optimizer), Optim.Options(iterations=0, store_trace=true, show_trace=true, g_tol=1.0e-6))
Related
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!
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)
}
The collision is not working
According to that post Collision detection between 2 "linearly" moving objects in WGS84,
I have the following data
EDIT:
I have updated the data for a collision that should occur in 10 seconds.
m_sPosAV = {North=48.276111971715515 East=17.921031349301817 Altitude=6000.0000000000000 }
Poi_Position = {North=48.806113707277042 East=17.977161602106488 Altitude=5656.0000000000000 }
velocity.x = -189.80000000000001 // m/s
velocity.y = -39.800000000000004 // m/s
velocity.z = 9 // m/s
m_sVelAV = {x=1.0000000000000000 y=1.0000000000000000 z=0.00000000000000000 } // m/s
void WGS84toXYZ(double &x, double &y, double &z, double lon, double lat, double alt)
{
const double _earth_a = 6378141.4; // [m] equator radius
const double _earth_b = 6356755.0; // [m] polar radius
double a, b, h, l, c, s;
a = lon;
b = lat;
h = alt;
c = cos(b);
s = sin(b);
h = h + sqrt((_earth_a*_earth_a*c*c) + (_earth_b*_earth_b*s*s));
z = h*s;
l = h*c;
x = l*cos(a);
y = l*sin(a);
}
bool CPoiFilterCollision::collisionDetection(const CPoiItem& poi)
{
const double _min_t = 10; // min_time
const double _max_d = 500; // max_distance
const double _max_t = 0.001; // max_time
double dt;
double d0, d1;
double xAv, yAv, zAv;
double xPoi, yPoi, zPoi;
double x, y, z;
double Ux, Uy, Uz; // [m]
double Vx, Vy, Vz; // [m]
double Wx, Wy, Wz; // [m]
double da = 1.567e-7; // [rad] angular step ~ 1.0 m in lon direction
double dl = 1.0;
const double deg = pi / 180.0;
// [m] altitide step 1.0 m
WGS84toXYZ(xAv, yAv, zAv, m_sPosAV.GetLongitude(), m_sPosAV.GetLatitude(), m_sPosAV.GetAltitude()); // actual position
WGS84toXYZ(xPoi, yPoi, zPoi, poi.Position().GetLongitude(), poi.Position().GetLatitude(), poi.Position().GetAltitude()); // actual position
WGS84toXYZ(Ux, Uy, Uz, m_sPosAV.GetLongitude() + da, m_sPosAV.GetLatitude(), m_sPosAV.GetAltitude()); // lon direction Nort
WGS84toXYZ(Vx, Vy, Vz, m_sPosAV.GetLongitude(), m_sPosAV.GetLatitude() + da, m_sPosAV.GetAltitude()); // lat direction East
WGS84toXYZ(Wx, Wy, Wz, m_sPosAV.GetLongitude(), m_sPosAV.GetLatitude(), m_sPosAV.GetAltitude() + dl); // alt direction High/Up
Ux -= xAv; Uy -= yAv; Uz -= zAv;
Vx -= xAv; Vy -= yAv; Vz -= zAv;
Wx -= xAv; Wy -= yAv; Wz -= zAv;
normalize(Ux, Uy, Uz);
normalize(Vx, Vy, Vz);
normalize(Wx, Wy, Wz);
double vx = m_sVelAV.x*Ux + m_sVelAV.y*Vx + m_sVelAV.z*Wx;
double vy = m_sVelAV.x*Uy + m_sVelAV.y*Vy + m_sVelAV.z*Wy;
double vz = m_sVelAV.x*Uz + m_sVelAV.y*Vz + m_sVelAV.z*Wz;
const QList<QVariant> velocity = poi.Property(QLatin1String("VELOCITY")).toList();
if (velocity.size() == 3)
{
dt = _max_t;
x = xAv - xPoi;
y = yAv - yPoi;
z = zAv - zPoi;
d0 = sqrt((x*x) + (y*y) + (z*z));
x = xAv - xPoi + (vx - velocity.at(0).toDouble())*dt;
y = yAv - yPoi + (vy - velocity.at(1).toDouble())*dt;
z = zAv - zPoi + (vz - velocity.at(2).toDouble())*dt;
d1 = sqrt((x*x) + (y*y) + (z*z));
if (d0 <= _max_d)
{
return true;
}
if (d0 <= d1)
{
return false;
}
double t = (_max_d - d0)*dt / (d1 - d0);
if (t < _min_t)
{
qDebug() << "Collision at time " << t;
return true;
}
}
return false;
}
I have black color png with transparent background.
I am trying to change color using hue-rotate(180deg) and invert(100%) CSS but failed.
In the case of other color png, all is good.
.huerotate{-webkit-filter: hue-rotate(180deg); filter: hue-rotate(180deg);}
<img src="blackXXX.png" class="huerotate"/>
Is it possible or impossible?
Yes, you can do it... the black is tricky.
Here's how:
background: url(black.png);
filter: brightness(0.9) invert(.7) sepia(.5) hue-rotate(100deg) saturate(200%);
This makes black -> blue.
This website can help you generate the FILTER from a HEX color:
https://isotropic.co/tool/hex-color-to-css-filter/
If you need a custom color, just try
this fiddle
The javascript:
'use strict';
class Color {
constructor(r, g, b) {
this.set(r, g, b);
}
toString() {
return `rgb(${Math.round(this.r)}, ${Math.round(this.g)}, ${Math.round(this.b)})`;
}
set(r, g, b) {
this.r = this.clamp(r);
this.g = this.clamp(g);
this.b = this.clamp(b);
}
hueRotate(angle = 0) {
angle = angle / 180 * Math.PI;
const sin = Math.sin(angle);
const cos = Math.cos(angle);
this.multiply([
0.213 + cos * 0.787 - sin * 0.213,
0.715 - cos * 0.715 - sin * 0.715,
0.072 - cos * 0.072 + sin * 0.928,
0.213 - cos * 0.213 + sin * 0.143,
0.715 + cos * 0.285 + sin * 0.140,
0.072 - cos * 0.072 - sin * 0.283,
0.213 - cos * 0.213 - sin * 0.787,
0.715 - cos * 0.715 + sin * 0.715,
0.072 + cos * 0.928 + sin * 0.072,
]);
}
grayscale(value = 1) {
this.multiply([
0.2126 + 0.7874 * (1 - value),
0.7152 - 0.7152 * (1 - value),
0.0722 - 0.0722 * (1 - value),
0.2126 - 0.2126 * (1 - value),
0.7152 + 0.2848 * (1 - value),
0.0722 - 0.0722 * (1 - value),
0.2126 - 0.2126 * (1 - value),
0.7152 - 0.7152 * (1 - value),
0.0722 + 0.9278 * (1 - value),
]);
}
sepia(value = 1) {
this.multiply([
0.393 + 0.607 * (1 - value),
0.769 - 0.769 * (1 - value),
0.189 - 0.189 * (1 - value),
0.349 - 0.349 * (1 - value),
0.686 + 0.314 * (1 - value),
0.168 - 0.168 * (1 - value),
0.272 - 0.272 * (1 - value),
0.534 - 0.534 * (1 - value),
0.131 + 0.869 * (1 - value),
]);
}
saturate(value = 1) {
this.multiply([
0.213 + 0.787 * value,
0.715 - 0.715 * value,
0.072 - 0.072 * value,
0.213 - 0.213 * value,
0.715 + 0.285 * value,
0.072 - 0.072 * value,
0.213 - 0.213 * value,
0.715 - 0.715 * value,
0.072 + 0.928 * value,
]);
}
multiply(matrix) {
const newR = this.clamp(this.r * matrix[0] + this.g * matrix[1] + this.b * matrix[2]);
const newG = this.clamp(this.r * matrix[3] + this.g * matrix[4] + this.b * matrix[5]);
const newB = this.clamp(this.r * matrix[6] + this.g * matrix[7] + this.b * matrix[8]);
this.r = newR;
this.g = newG;
this.b = newB;
}
brightness(value = 1) {
this.linear(value);
}
contrast(value = 1) {
this.linear(value, -(0.5 * value) + 0.5);
}
linear(slope = 1, intercept = 0) {
this.r = this.clamp(this.r * slope + intercept * 255);
this.g = this.clamp(this.g * slope + intercept * 255);
this.b = this.clamp(this.b * slope + intercept * 255);
}
invert(value = 1) {
this.r = this.clamp((value + this.r / 255 * (1 - 2 * value)) * 255);
this.g = this.clamp((value + this.g / 255 * (1 - 2 * value)) * 255);
this.b = this.clamp((value + this.b / 255 * (1 - 2 * value)) * 255);
}
hsl() {
// Code taken from https://stackoverflow.com/a/9493060/2688027, licensed under CC BY-SA.
const r = this.r / 255;
const g = this.g / 255;
const b = this.b / 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
let h, s, l = (max + min) / 2;
if (max === min) {
h = s = 0;
} else {
const d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0);
break;
case g:
h = (b - r) / d + 2;
break;
case b:
h = (r - g) / d + 4;
break;
}
h /= 6;
}
return {
h: h * 100,
s: s * 100,
l: l * 100,
};
}
clamp(value) {
if (value > 255) {
value = 255;
} else if (value < 0) {
value = 0;
}
return value;
}
}
class Solver {
constructor(target, baseColor) {
this.target = target;
this.targetHSL = target.hsl();
this.reusedColor = new Color(0, 0, 0);
}
solve() {
const result = this.solveNarrow(this.solveWide());
return {
values: result.values,
loss: result.loss,
filter: this.css(result.values),
};
}
solveWide() {
const A = 5;
const c = 15;
const a = [60, 180, 18000, 600, 1.2, 1.2];
let best = { loss: Infinity };
for (let i = 0; best.loss > 25 && i < 3; i++) {
const initial = [50, 20, 3750, 50, 100, 100];
const result = this.spsa(A, a, c, initial, 1000);
if (result.loss < best.loss) {
best = result;
}
}
return best;
}
solveNarrow(wide) {
const A = wide.loss;
const c = 2;
const A1 = A + 1;
const a = [0.25 * A1, 0.25 * A1, A1, 0.25 * A1, 0.2 * A1, 0.2 * A1];
return this.spsa(A, a, c, wide.values, 500);
}
spsa(A, a, c, values, iters) {
const alpha = 1;
const gamma = 0.16666666666666666;
let best = null;
let bestLoss = Infinity;
const deltas = new Array(6);
const highArgs = new Array(6);
const lowArgs = new Array(6);
for (let k = 0; k < iters; k++) {
const ck = c / Math.pow(k + 1, gamma);
for (let i = 0; i < 6; i++) {
deltas[i] = Math.random() > 0.5 ? 1 : -1;
highArgs[i] = values[i] + ck * deltas[i];
lowArgs[i] = values[i] - ck * deltas[i];
}
const lossDiff = this.loss(highArgs) - this.loss(lowArgs);
for (let i = 0; i < 6; i++) {
const g = lossDiff / (2 * ck) * deltas[i];
const ak = a[i] / Math.pow(A + k + 1, alpha);
values[i] = fix(values[i] - ak * g, i);
}
const loss = this.loss(values);
if (loss < bestLoss) {
best = values.slice(0);
bestLoss = loss;
}
}
return { values: best, loss: bestLoss };
function fix(value, idx) {
let max = 100;
if (idx === 2 /* saturate */) {
max = 7500;
} else if (idx === 4 /* brightness */ || idx === 5 /* contrast */) {
max = 200;
}
if (idx === 3 /* hue-rotate */) {
if (value > max) {
value %= max;
} else if (value < 0) {
value = max + value % max;
}
} else if (value < 0) {
value = 0;
} else if (value > max) {
value = max;
}
return value;
}
}
loss(filters) {
// Argument is array of percentages.
const color = this.reusedColor;
color.set(0, 0, 0);
color.invert(filters[0] / 100);
color.sepia(filters[1] / 100);
color.saturate(filters[2] / 100);
color.hueRotate(filters[3] * 3.6);
color.brightness(filters[4] / 100);
color.contrast(filters[5] / 100);
const colorHSL = color.hsl();
return (
Math.abs(color.r - this.target.r) +
Math.abs(color.g - this.target.g) +
Math.abs(color.b - this.target.b) +
Math.abs(colorHSL.h - this.targetHSL.h) +
Math.abs(colorHSL.s - this.targetHSL.s) +
Math.abs(colorHSL.l - this.targetHSL.l)
);
}
css(filters) {
function fmt(idx, multiplier = 1) {
return Math.round(filters[idx] * multiplier);
}
return `filter: invert(${fmt(0)}%) sepia(${fmt(1)}%) saturate(${fmt(2)}%) hue-rotate(${fmt(3, 3.6)}deg) brightness(${fmt(4)}%) contrast(${fmt(5)}%);`;
}
}
function hexToRgb(hex) {
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, (m, r, g, b) => {
return r + r + g + g + b + b;
});
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result
? [
parseInt(result[1], 16),
parseInt(result[2], 16),
parseInt(result[3], 16),
]
: null;
}
$(document).ready(() => {
$('button.execute').click(() => {
const rgb = hexToRgb($('input.target').val());
if (rgb.length !== 3) {
alert('Invalid format!');
return;
}
const color = new Color(rgb[0], rgb[1], rgb[2]);
const solver = new Solver(color);
const result = solver.solve();
let lossMsg;
if (result.loss < 1) {
lossMsg = 'This is a perfect result.';
} else if (result.loss < 5) {
lossMsg = 'The is close enough.';
} else if (result.loss < 15) {
lossMsg = 'The color is somewhat off. Consider running it again.';
} else {
lossMsg = 'The color is extremely off. Run it again!';
}
$('.realPixel').css('background-color', color.toString());
$('.filterPixel').attr('style', result.filter);
$('.filterDetail').text(result.filter);
$('.lossDetail').html(`Loss: ${result.loss.toFixed(1)}. <b>${lossMsg}</b>`);
});
});
I am trying to solve a differential equation numerically but I need to vary y0 for my plot and view result for constant x. I can solve my equation normally as I expected:but I can't get result when I try for my real purpose as you can see
`\[Sigma] = 1;
n = 23.04;
Rop = y[x];
R = 0.5;
sz = R/(Rop + R);
F = -n*\[Sigma]*y[x]*(1 - 2*sz);
s = NDSolve[{y'[x] == F, y[0] == 0.8}, y, {x, 0, 0.07}]
Plot[Evaluate[y[x] /. s], {x, 0, 0.07}, PlotRange -> All,]`
`[Sigma] = 1;
n = 23.04;
Rop = y[x];
R = 0.5;
sz = R/(Rop + R);
F = -n*\[Sigma]*y[x]*(1 - 2*sz);
y0 = 0.8;
\!\(\*
ButtonBox["Array",
BaseStyle->"Link",
ButtonData->"paclet:ref/Array"]\)[s, 140]
i = 1;
For[i < 140,
s = NDSolve[{y'[x] == F, y[0] == y0}, y, {x, 0, 0.07}]
Plot[Evaluate[y[] /. s], x = 0.07, {y0, 0.8, 2.2}] // print
y0 == y0 + i*0.01];`
A variety of typos or misunderstandings
\[Sigma] = 1;
n = 23.04;
Rop = y[x];
R = 0.5;
sz = R/(Rop + R);
F = -n*\[Sigma]*y[x]*(1 - 2*sz);
y0 = 0.8;
For[i = 1, i < 140, i++,
s = NDSolve[{y'[x] == F, y[0] == y0}, y, {x, 0, 0.07}];
Plot[Evaluate[y[x] /. s], {x, 0, 0.07}] // Print;
y0 = y0 + i*0.01
];
Go through that and compare it a character at a time against your original.
After you have figured out why each of the changes were made then you can try to decide whether to put your Button back in that or not.