bou*_*ful 10 java algorithm markov-chains
我有一组有序的数据点存储为TreeSet<DataPoint>.每个数据点具有一position和一Set的Event对象(HashSet<Event>).
有4个可能的Event对象A,B,C,和D.每个DataPoint具有这些,例如,2 A和C,除了第一个和最后DataPoint在对象集,其具有T尺寸1的.
我的算法是要找到一个新的可能性DataPoint Q的位置x有Event q在这个集合.
我这样做是通过计算S此数据集的值,然后添加Q到集合并S再次计算.然后我将第二个S除以第一个来隔离新概率DataPoint Q.
计算公式为S:
http://mathbin.net/equations/105225_0.png
哪里
http://mathbin.net/equations/105225_1.png
http://mathbin.net/equations/105225_2.png
对于 http://mathbin.net/equations/105225_3.png
和
http://mathbin.net/equations/105225_4.png
http://mathbin.net/equations/105225_5.png是一种昂贵的概率函数只取决于它的参数,并没有别的(和http://mathbin.net/equations/105225_6.png),HTTP:// mathbin.净/方程/ 105225_7.png是最后DataPoint在该组(右侧节点),http://mathbin.net/equations/105225_8.png是第一DataPoint(左侧节点),http://mathbin.net/equations/105225_9巴纽是最右边的DataPoint那个是不是节点,http://mathbin.net/equations/105225_10.png是DataPoint,http://mathbin.net/equations/105225_12.png是Set对这个事件DataPoint.
所以Qwith 的概率Event q是:
http://mathbin.net/equations/105225_11.png
我用Java实现了这个算法:
public class ProbabilityCalculator {
private Double p(DataPoint right, Event rightEvent, DataPoint left, Event leftEvent) {
// do some stuff
}
private Double f(DataPoint right, Event rightEvent, NavigableSet<DataPoint> points) {
DataPoint left = points.lower(right);
Double result = 0.0;
if(left.isLefthandNode()) {
result = 0.25 * p(right, rightEvent, left, null);
} else if(left.isQ()) {
result = p(right, rightEvent, left, left.getQEvent()) * f(left, left.getQEvent(), points);
} else { // if M_k
for(Event leftEvent : left.getEvents())
result += p(right, rightEvent, left, leftEvent) * f(left, leftEvent, points);
}
return result;
}
public Double S(NavigableSet<DataPoint> points) {
return f(points.last(), points.last().getRightNodeEvent(), points)
}
}
Run Code Online (Sandbox Code Playgroud)
因此,要找到的概率Q在x用q:
Double S1 = S(points);
points.add(Q);
Double S2 = S(points);
Double probability = S2/S1;
Run Code Online (Sandbox Code Playgroud)
由于实施立即紧跟数学算法.然而,这在实践中并不是一个特别好的主意,因为f每次调用本身两次DataPoint.因此,对于http://mathbin.net/equations/105225_9.png,f调用两次,然后为n-1 f每个先前的调用再次调用两次,依此类推.O(2^n)考虑DataPoints到每个可能超过1000 ,这导致复杂性非常糟糕Set.因为p()除了参数之外的所有内容都是独立的,我已经包含了一个缓存函数,其中if p()已经为这些参数计算过它只返回先前的结果,但这并不能解决固有的复杂性问题.我在这里遗漏了一些关于重复计算的东西,还是这个算法中的复杂性是不可避免的?
感谢您的所有建议。P我通过为和已计算的值创建新的嵌套类来实现我的解决方案F,然后使用 aHashMap来存储结果。HashMap然后在计算发生之前查询结果;如果存在,则仅返回结果,如果不存在,则计算结果并将其添加到HashMap.
最终产品看起来有点像这样:
public class ProbabilityCalculator {
private NavigableSet<DataPoint> points;
private ProbabilityCalculator(NavigableSet<DataPoint> points) {
this.points = points;
}
private static class P {
public final DataPoint left;
public final Event leftEvent;
public final DataPoint right;
public final Event rightEvent;
public P(DataPoint left, Event leftEvent, DataPoint right, Event rightEvent) {
this.left = left;
this.leftEvent = leftEvent;
this.right = right;
this.rightEvent = rightEvent;
}
public boolean equals(Object o) {
if(!(o instanceof P)) return false;
P p = (P) o;
if(!(this.leftEvent == null ? p.leftEvent == null : this.leftEvent.equals(p.leftEvent)))
return false;
if(!(this.rightEvent == null ? p.rightEvent == null : this.rightEvent.equals(p.rightEvent)))
return false;
return this.left.equals(p.left) && this.right.equals(p.right);
}
public int hashCode() {
int result = 93;
result = 31 * result + this.left.hashCode();
result = 31 * result + this.right.hashCode();
result = this.leftEvent != null ? 31 * result + this.leftEvent.hashCode() : 31 * result;
result = this.rightEvent != null ? 31 * result + this.rightEvent.hashCode() : 31 * result;
return result;
}
}
private Map<P, Double> usedPs = new HashMap<P, Double>();
private static class F {
public final DataPoint left;
public final Event leftEvent;
public final NavigableSet<DataPoint> dataPointsToLeft;
public F(DataPoint dataPoint, Event dataPointEvent, NavigableSet<DataPoint> dataPointsToLeft) {
this.dataPoint = dataPoint;
this.dataPointEvent = dataPointEvent;
this.dataPointsToLeft = dataPointsToLeft;
}
public boolean equals(Object o) {
if(!(o instanceof F)) return false;
F f = (F) o;
return this.dataPoint.equals(f.dataPoint) && this.dataPointEvent.equals(f.dataPointEvent) && this.dataPointsToLeft.equals(f.dataPointsToLeft);
}
public int hashCode() {
int result = 7;
result = 31 * result + this.dataPoint.hashCode();
result = 31 * result + this.dataPointEvent.hashCode();
result = 31 * result + this.dataPointsToLeft.hashCode();
return result;
}
}
private Map<F, Double> usedFs = new HashMap<F, Double>();
private Double p(DataPoint right, Event rightEvent, DataPoint left, Event leftEvent) {
P newP = new P(right, rightEvent, left, leftEvent);
if(this.usedPs.containsKey(newP)) return usedPs.get(newP);
// do some stuff
usedPs.put(newP, result);
return result;
}
private Double f(DataPoint right, Event rightEvent) {
NavigableSet<DataPoint> dataPointsToLeft = dataPoints.headSet(right, false);
F newF = new F(right, rightEvent, dataPointsToLeft);
if(usedFs.containsKey(newF)) return usedFs.get(newF);
DataPoint left = points.lower(right);
Double result = 0.0;
if(left.isLefthandNode()) {
result = 0.25 * p(right, rightEvent, left, null);
} else if(left.isQ()) {
result = p(right, rightEvent, left, left.getQEvent()) * f(left, left.getQEvent(), points);
} else { // if M_k
for(Event leftEvent : left.getEvents())
result += p(right, rightEvent, left, leftEvent) * f(left, leftEvent, points);
}
usedFs.put(newF, result)
return result;
}
public Double S() {
return f(points.last(), points.last().getRightNodeEvent(), points)
}
public static probabilityOfQ(DataPoint q, NavigableSet<DataPoint> points) {
ProbabilityCalculator pc = new ProbabilityCalculator(points);
Double S1 = S();
points.add(q);
Double S2 = S();
return S2/S1;
}
}
Run Code Online (Sandbox Code Playgroud)