Using math in solr if expressions - java

I am trying to use math in an 'if' statement in solr. What I want to achieve is following, I have a trapeze function defined as:
There are 4 points on the x axis, left_minimum, left_optimum, right_optimum, right_maximum.
For every value of the field I want to have following outcome:
value v
score s
maxscore
if (v<left_minimum)
s = 0;
if (v>right_maximum)
s = 0;
if (v>=left_optimum AND v<=right_optimum)
s = maxScore;
if (v>=left_minimum AND v<left_optimum)
s = maxScore * (v - left_minimum) / (left_optimum - left_minimum)
if (v>right_optimum AND v<=right_maximum )
s = maxScore * (v - right_optimum) / (right_maximum - right_optimum)
The basic idea is to rank results which are "near" the ideal result higher than the results that are too far away.
to achieve this I tried to split my calculation for height in three parts (maxscore is 1.0):
heightWM=product(1.0, map(height,160,170,1,0))
&heightWL=if(height < 160 AND height > 150, product(1.0, div(sub(height,160),10)), 0)
&heightWR=if(height < 180 AND height > 170, product(1.0, div(sub(height,170),10)), 0)
&heightW=sum(heightWL, heightWM, heightWR)
problem is that solr doesn't like if with mathematical expression. Or at least I haven't find how.
Is there any other possibility to achieve this?

Ok, I actually found a solution or, better, a workaround.
heightWL=if(map(height,160,169,1,0),div(sub(height,160),10),0)
so I am basically mapping all values between x and y in a > x and a < y to 1, and all other values to 0. This way if can actually check, since it can work with 1 and 0, and in that case I calculate the subvalue for this area.

Related

How to get the same RSI as Tradingview in Java?

I don't understand why, but my RSI is always different as Tradingview's RSI.
Is use the same period (14 candles of 15min each), I use the same type of value (closes price), I tried to add the last non closed candle, but I never get the same RSI.
Tradingview RSI code :
//#version=4
study(title="Relative Strength Index", shorttitle="RSI",
format=format.price, precision=2, resolution="")
len = input(14, minval=1, title="Length")
src = input(close, "Source", type = input.source)
up = rma(max(change(src), 0), len)
down = rma(-min(change(src), 0), len)
rsi = down == 0 ? 100 : up == 0 ? 0 : 100 - (100 / (1 + up / down))
plot(rsi, "RSI", color=#7E57C2)
band1 = hline(70, "Upper Band", color=#787B86)
bandm = hline(50, "Middle Band", color=color.new(#787B86, 50))
band0 = hline(30, "Lower Band", color=#787B86)
fill(band1, band0, color=color.rgb(126, 87, 194, 90), title="Background")
MY code with TA-Lib
MInteger outBegIdx = new MInteger();
MInteger outNbElement = new MInteger();
double[] outReal = new double[array.length-1];
int startIdx = 0;
int endIdx = array.length - 1;
Core core = new Core();
core.rsi(startIdx, endIdx, array, length-1, outBegIdx, outNbElement, outReal);
System.out.println(Arrays.toString(outReal));
return outReal[0];
my custom code without plugin
double av_gain_up_periods = 0;
double av_loss_down_periods = 0;
int gain_count = 0;
int loss_count = 0;
double previous_observation = array[0];
for (int i = 1; i < array.length; i++) {
if (previous_observation <= array[i]) { // if gain
double gain = array[i] - previous_observation;
gain_count++;
av_gain_up_periods += gain;
}
else { // if loss
double loss = previous_observation - array[i];
loss_count++;
av_loss_down_periods += loss;
}
previous_observation = array[i];
}
av_gain_up_periods = av_gain_up_periods/gain_count;
av_loss_down_periods = av_loss_down_periods/loss_count;
// CALCULATE RSI
double relative_strength = av_gain_up_periods/av_loss_down_periods;
double relative_strength_index = 100-(100/(1+relative_strength));
// PRINT RESULT
return relative_strength_index;
I can garantee you that I have 14 closes price and they are the same as Tradingview's. The difference is in the calculation.
Related to this issue
Thanks
I think the problem is in RMA (relative moving average) calculation.it happens because of the unmutual starting point for getting RMA. Different starting point for getting RMA will cause big difference in calculated RSI oppose to tradingview RSI. Tradingview is using Realtime data, hence older data. My suggestion is to start with 1000 klines.
Here is the tradingview formula :
len = input(14, minval=1, title="Length")
src = input(close, "Source", type = input.source)
up = rma(max(change(src), 0), len)
down = rma(-min(change(src), 0), len)
rsi = down == 0 ? 100 : up == 0 ? 0 : 100 - (100 / (1 + up / down))
according to this formula, first you need to get prices and store them somewhere. Closed candles are either gain or loss. After that you have to calculate the change for gain and loss.
Notice : for a closer result get more klines. you need the older data to have a more accurate calculation.( for example 1000 klines)
Now is the time to calculate RMA.
The RMA formula is :
Alpha*source(or as we know, change) + (1-alpha) * previous RMA
Alpha : 1/period(for example 1/14)
At this point we are at the tricky part of calculation. As you can see in the RMA formula, we need the previous RMA to calculate the current one. Assume that we are using 1 hour timeframe and store the klines lets say in an array. Each and every one off array elements has a previous element, hence previous RMA ; But what about the element stored in array[0] ?
It would also be needing previous RMA. Here you will need to calculate SMA(simple moving average).
SMA : the number of prices within a time period is divided by the number of total periods.
The calculated SMA is equal the arrays first member RMA.
Now is the time to calculate RSI. With this method I was able to calculate RSI almost exactly same as tradingview.
Personally, I wrote a bot with C++ to calculate RSI according to tradingview, using Binance API. You can see my code here :
https://github.com/Mina-Jahan/RSIgnal_bot
And I would be appreciated to hear your opinion in order to make my code better if there is a way to reform it.
Thank you.

Java-Algorithm for Polygon-Collision (Point-in-Polygon): Problems with Degenerated # Boundary

I need for my java-program a function that checks for polygon-collision, but the algorithms (for point-in-polygon) I tried were not correct for my needs, the degenerative cases are a problem for me.
This is what i try to reach with my program: I have 2 polygons and want to put them nearest possible together. I want to place them on their vertices and rotate them along the edge to fit optimal. Therefor I need a collision-detection, if they intersect or not.
My biggest problem is that those polygon-edges could be on the same point. The researched algorithms decide if it is in polygon a or b (mostly with y-value).
What I use
Polygon with double coordinates for x and y
standard java
no external librarys
My required rules:
polygons can have same edge and same vertices (can be on same boundary, but not complete polygon overlay)
the edges should not be allowed to intersect
it is not allowed, that one polygon is completly surrounded by another polygon (a hole).
(an optional very small epsilon in algorithm would be good, because rotating with double is not very exact)
I tried too the internal classes like Path2D.Double() with contains too without success to this problem.
The last algorithm (of about minimum of 8) i tried was this:
wiki.cizmar.org/doku.php?id=physics:point-in-polygon_problem_with_simulation_of_simplicity
This is C Code of the linked algorithm (last one I tried)
int i, j, c = 0;
for (i = 0, j = number_of_vertices-1; i < number_of_vertices; j = i++) {
if ( ((vertices[i].y>p.y) != (vertices[j].y>p.y)) &&
(p.x < (vertices[j].x-vertices[i].x) * (p.y-vertices[i].y) / (vertices[j].y-vertices[i].y) + vertices[i].x) )
c = !c;
}
return c;
My adapted JAVA code (Punkt=Point, Form.getCoords = List of Coordinates with x,y)
private boolean testPointInsidePolygon3c(Punkt p, Form f){
int number_of_vertices = f.getCoords().size();
int i, j = 0;
boolean odd = false;
for (i = 0, j = number_of_vertices-1; i < number_of_vertices; j = i++) {
if ( ((f.getCoords().get(i).getY() >p.getY()) != (f.getCoords().get(j).getY() >p.getY())) &&
( p.getX() < (f.getCoords().get(j).getX() -f.getCoords().get(i).getX())
* (p.getY() -f.getCoords().get(i).getY())
/ (f.getCoords().get(j).getY() -f.getCoords().get(i).getY())
+ f.getCoords().get(i).getX())
){
odd = !odd;
}
}
return odd;
}
To show that problem: here are pictures with 2 polygons. the blue vertices are the troublesomes.
Problem Example #1 example from another source
I hope you got some ideas, links, algorithm or anything for me. i got stucked too long with that problem ;-)
What a pity - i could not do a complete correct algorithm, that solves my problem.
That is why I now use the JTS-Library!
With overlaps and covers/within i got everything correct in my test-cases.

Compare graph values or structure

I have an android application which is getting gesture coordinates (3 axis - x,y,z). I need to compare them with coordinates which I have in my DB and determine whether they are the same or not.
I also need to add some tolerance, since accelerometer (device which captures gestures) is very sensitive. It would be easy, but I also want to consider e.g. "big circle" drawn in the air, same as "small circle" drawn in the air. meaning that there would be different values, but structure of the graph would be the same, right?
I have heard about translating graph values into bits and then compare. Is that the right approach? Is there any library for such comparison?
So far I just hard coded it, covering all my requirements except the last one (big circle vs small circle).
My code now:
private int checkWhetherGestureMatches(byte[] values, String[] refValues) throws IOException {
int valuesSize = 32;
int ignorePositions = 4;
byte[] valuesX = new byte[valuesSize];
byte[] valuesY = new byte[valuesSize];
byte[] valuesZ = new byte[valuesSize];
for (int i = 0; i < valuesSize; i++) {
int position = i * 3 + ignorePositions;
valuesX[i] = values[position];
valuesY[i] = values[position + 1];
valuesZ[i] = values[position + 2];
}
Double[] valuesXprevious = new Double[valuesSize];
Double[] valuesYprevious = new Double[valuesSize];
Double[] valuesZprevious = new Double[valuesSize];
for (int i = 0; i < valuesSize; i++) {
int position = i * 3 + ignorePositions;
valuesXprevious[i] = Double.parseDouble(refValues[position]);
valuesYprevious[i] = Double.parseDouble(refValues[position + 1]);
valuesZprevious[i] = Double.parseDouble(refValues[position + 2]);
}
int incorrectPoints = 0;
for (int j = 0; j < valuesSize; j++) {
if (valuesX[j] < valuesXprevious[j] + 20 && valuesX[j] > valuesXprevious[j] - 20
&& valuesY[j] < valuesYprevious[j] + 20 && valuesY[j] > valuesYprevious[j] - 20
&& valuesZ[j] < valuesZprevious[j] + 20 && valuesZ[j] > valuesZprevious[j] - 20) {
} else {
incorrectPoints++;
}
}
return incorrectPoints;
}
EDIT:
I found JGraphT, it might work. If you know anything about that already, let me know.
EDIT2:
See these images, they are the same gesture but one is done in a slower motion than another.
Faster one:
Slower one:
I haven't captured images of the same gesture where one would be smaller than another, might add that later.
If your list of gestures is complex, I would suggest training a neural network which can classify the gestures based on the graph value bits you mentioned. The task is very similar to classification of handwritten numerical digits, for which lots of resources are there on the net.
The other approach would be to mathematically guess the shape of the gesture, but I doubt it will be useful considering the tolerance of the accelerometer and the fact that users won't draw accurate shapes.
(a) convert your 3D coordinates into 2D plain figure. Use matrix transformations.
(b) normalize your gesture scale - again with matrix transformations
(c) normalize the number of points or use interpolation on the next step.
(d) calculate the difference between your stored (s) gesture and current (c) gesture as
Sum((Xs[i] - Xc[i])^2 + (Ys[i] - Yc[i])^2) where i = 0 .. num of points
If the difference is below your predefined precision - gestures are equal.
I have used a Java implementation of Dynamic Time Wrapping algorithm. The library is called fastDTW.
Unfortunately from what I undersood they don't support it anymore, though I found a use for it.
https://code.google.com/p/fastdtw/
I can't recall now, but I think I used this one and compiled it myself:
https://github.com/cscotta/fastdtw/tree/master/src/main/java/com/fastdtw/dtw

Java: calculating velocity of a skydiver

In Java, I am trying to implement the following equation for calculating the current velocity of a skydiver not neglecting air resistance.
v(t) = v(t-∆t) + (g - [(drag x crossArea x airDensity) / (2*mass)] *
v[(t-∆t)^2] ) * (∆t)
My problem is that I am not sure how to translate "v(t - ∆t)" into a code. Right now I have this method below, where as you can see I am using the method within itself to find the previous velocity. This has continued to result in a stack overflow error message, understandably.
(timeStep = ∆t)
public double calculateVelocity(double time){
double velocity;
velocity = calculateVelocity(time - timeStep)
+ (acceleration - ((drag * crossArea * airDensity)
/ (2 * massOfPerson))
* (calculateVelocity(time - timeStep)*(time * timeStep)))
* timeStep;
}
return velocity;
}
I am calling the above method in the method below. Assuming that the ending time = an int, will be the user input but written this way to be dynamic.
public void assignVelocitytoArrays(){
double currentTime = 0;
while(currentTime <= endingTime){
this.vFinal = calculateVelocity(currentTime);
currentTime += timeStep;
}
}
I would like to figure this out on my own, could someone give me a general direction? Is using a method within itself the right idea or am I completely off track?
The formula you want to implement is the recursive representation of a sequence, mathematiacally speaking.
Recursive sequences need a starting point, e.g.
v(0) = 0 (because a negative time does not make sense)
and a rule to calculate the next elements, e.g.
v(t) = v(t-∆t) + (g - [(drag x crossArea x airDensity) / (2*mass)] * v[(t-∆t)^2] ) * (∆t)
(btw: are you sure it has to be v([t-∆t]^2) instead of v([t-∆t])^2?)
So your approach to use recursion (calling a function within itself) to calculate a recursive sequence is correct.
In your implementation, you only forgot one detail: the starting point. How should your program know that v(0) is not defined be the rule, but by a definite value? So you must include it:
if(input value == starting point){
return starting point
}
else{
follow the rule
}
On a side note: you seem to be creating an ascending array of velocities. It would make sense to use the already calculated values in the array instead of recursion, so you don't have to calculate every step again and again.
This only works if you did indeed make a mistake in the rule.
double[] v = new double[maxTime/timeStep];
v[0] = 0; //starting point
for(int t = 1; t < maxSteps; t++){
v[t] = v[t-1] + (g - [(drag x crossArea x airDensity) / (2*mass)] * v[t-1]^2 ) * (∆t)
}

Lines Intersect method not working correctly

I'm working on some vector math, and I need to calculate the normal vector of a polygon.
My code:
//p is a parameter, is a Vec2, second point on first line
double[][] vert = getVerticies(); //[any length, # of verticies][2]
for(int i = 0; i < vert.length; i++) {
Vec2 cm = Vec2.ZERO_VEC;//first point on first line, always is <0, 0> as it is the origin
Vec2 rcm = getCM(); // just used to get relative positions.
Vec2 v1 = cm.sub(new Vec2(vert[i])); //the first point in one of all edges of the shape, second line
Vec2 v2 = cm.sub(new Vec2(i == vert.length - 1 ? vert[0] : vert[i + 1])); // the second point on the second line.
double den = (v2.getY() - v1.getY()) * (p.getX() - cm.getX()) - (v2.getX() - v1.getX()) * (p.getY() - cm.getY());
if(den == 0D) {
continue;
}
double a = ((v2.getX() - v1.getX()) * (cm.getY() - v1.getY()) - (v2.getY() - v1.getY()) * (cm.getX() - v1.getX())) / den;
double b = ((p.getX() - cm.getX()) * (cm.getY() - v1.getY()) - (p.getY() - cm.getY()) * (cm.getX() - v1.getX())) / den;
if(a >= 0D && a <= 1D && b >= 0D && b <= 1D) {
Vec2 mid = v2.add(v2.sub(v1).scale(0.5D)); //this is just normal vector calculation stuff, I know the error isn't here, as if it was, it would return a non-unit-scale vector.
return mid.uscale(); //hats the vector, returns
}
}
return p; // return the parameter, second point on first line, used as a contingency, should never actually run, as the first line is fully contained in the lines were testing against
I've done some debugging, and I just don't see what's happening. Can anyone tell me what's wrong with my math? It just seems to flow absolutely fine, but the math just doesn't seem right. My goal with this code is to determine the index of the two verticies that my line intersects.
Oops, figured it out by virtue of attempted to explain it. I need to be ray tracing, or use ray intersection testing.
If you are trying to calculate the normal of a polygon, it looks like you are trying to do something overly complicated. You can simply use cross product of two adjacent edges to get it. Even better, with a simple math explained here, you don't even need to calculate the edge vectors. Just take the cross product of each adjacent vertex pair and sum them up:

Categories

Resources