[jboss-jira] [JBoss JIRA] (DROOLS-1422) Make AccumulateFunction interface simpler and more powerful
Geoffrey De Smet (JIRA)
issues at jboss.org
Tue Jan 31 09:11:00 EST 2017
[ https://issues.jboss.org/browse/DROOLS-1422?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Geoffrey De Smet updated DROOLS-1422:
-------------------------------------
Description:
* Replace the AccumulateFunction interface with the AccumulateFunction2 interface:
** All core runtime code uses the AccumulateFunction2 interface.
** Deprecate AccumulateFunction and use a bridge class at DRL compilation time so old implementations still work because they are bridged into the new interface
* Changes of the AccumulateFunction2:
** Methods no longer throw checked exceptions (no "throws Exception"), so drools doesn't have to catch them. This might improve performance.
** Remove "Serializable context". The class itself contains the state.
*** Remove method createContext()
*** Replace method init(Serializeble) with constructor call (no-args normally)
*** Remove parameter Serializable from accumulate(value), reserve(value) and getResult() methods
*** Instead of making 1 AccFunction instance and n context instances, make n AccFunction instances. This uses less memory.
*** This might improve performance (data locality).
** It should Serializable, but doesn't have to Externalizable. Removes methods writeExternal() and readExternal() in the user implementation.
* Interface ReversableAccumulateFunction2 extends AccumulateFunction2
** Only ReversableAccumulateFunction2 has method reverse(value)
** Remove method supportsReverse(): the custom accumulate is reverseable if it also implements this interface
* Opportunities
** construction parameters. For example: fixed average for standard deviation (very useful for OptaPlanner)
** Multi-argument accumulates, for example in DRL: `$total : standardDeviation($groupBy, $weight)`
Notice how clean the user implementation would become.
{code}
// NEW
public class SumAccumulateFunction
implements ReversableAccumulateFunction2<Integer, Integer> {
public int total;
public SumAccumulateFunction() {
total = 0;
}
public void accumulate(Integer value) {
total += value;
}
public void reverse(Integer value) {
total -= value;
}
public Integer getResult() {
return total;
}
}
{code}
*Compare that with the old way:*
{code}
// OLD
public class SumAccumulateFunction implements AccumulateFunction {
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { }
public void writeExternal(ObjectOutput out) throws IOException { }
protected static class SumData implements Externalizable {
public double total = 0;
public SumData() {}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
total = in.readDouble();
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeDouble(total);
}
}
public Serializable createContext() {
return new SumData();
}
public void init(Serializable context) {
SumData data = (SumData) context;
data.total = 0;
}
public void accumulate(Serializable context,
Object value) {
SumData data = (SumData) context;
data.total += ((Number) value).doubleValue();
}
public void reverse(Serializable context,
Object value) {
SumData data = (SumData) context;
data.total -= ((Number) value).doubleValue();
}
public Object getResult(Serializable context) {
return ((SumData) context).total;
}
public boolean supportsReverse() {
return true;
}
public Class<?> getResultType() {
return Double.class;
}
}
{code}
Some other cases:
Different result type than value type:
{code}
public class AverageAccumulateFunction
implements ReversableAccumulateFunction2<Integer, Double> {
public int total;
public int count;
public AverageAccumulateFunction() {
total = 0;
count = 0;
}
public void accumulate(Integer value) {
total += value;
count++;
}
public void reverse(Integer value) {
total -= value;
count--;
}
public Double getResult() {
return (double) total / count;
}
}
{code}
Construction parameter:
{code}
public class StdDeviationAccumulateFunction
implements ReversableAccumulateFunction2<Integer, Double> {
public final double average;
public double variance;
public StdDeviationAccumulateFunction(double average) {
this.average = average;
variance = 0;
}
public void accumulate(double value) {
variance += (value - average)²; // TODO
}
public void reverse(double value) {
variance -= (value - average)²; // TODO
}
public Double getResult() {
return Math.sqrt(variance);
}
}
{code}
TODO multi-argument accumulate:
...
was:
* Replace the AccumulateFunction interface with the AccumulateFunction2 interface:
** All core runtime code uses the AccumulateFunction2 interface.
** Deprecate AccumulateFunction and use a bridge class at DRL compilation time so old implementations still work because they are bridged into the new interface
* Changes of the AccumulateFunction2:
** Methods no longer throw checked exceptions (no "throws Exception"), so drools doesn't have to catch them. This might improve performance.
** Remove "Serializable context". The class itself contains the state.
*** Remove method createContext()
*** Replace method init(Serializeble) with constructor call (no-args normally)
*** Remove parameter Serializable from accumulate(value), reserve(value) and getResult() methods
*** Instead of making 1 AccFunction instance and n context instances, make n AccFunction instances. This uses less memory.
*** This might improve performance.
** It should Serializable, but doesn't have to Externalizable. Removes methods writeExternal() and readExternal() in the user implementation.
* Interface ReversableAccumulateFunction2 extends AccumulateFunction2
** Only ReversableAccumulateFunction2 has method reverse(value)
** Remove method supportsReverse(): the custom accumulate is reverseable if it also implements this interface
* Opportunities
** construction parameters. For example: fixed average for standard deviation (very useful for OptaPlanner)
** Multi-argument accumulates, for example in DRL: `$total : standardDeviation($groupBy, $weight)`
Notice how clean the user implementation would become.
{code}
// NEW
public class SumAccumulateFunction
implements ReversableAccumulateFunction2<Integer, Integer> {
public int total;
public SumAccumulateFunction() {
total = 0;
}
public void accumulate(Integer value) {
total += value;
}
public void reverse(Integer value) {
total -= value;
}
public Integer getResult() {
return total;
}
}
{code}
*Compare that with the old way:*
{code}
// OLD
public class SumAccumulateFunction implements AccumulateFunction {
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { }
public void writeExternal(ObjectOutput out) throws IOException { }
protected static class SumData implements Externalizable {
public double total = 0;
public SumData() {}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
total = in.readDouble();
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeDouble(total);
}
}
public Serializable createContext() {
return new SumData();
}
public void init(Serializable context) {
SumData data = (SumData) context;
data.total = 0;
}
public void accumulate(Serializable context,
Object value) {
SumData data = (SumData) context;
data.total += ((Number) value).doubleValue();
}
public void reverse(Serializable context,
Object value) {
SumData data = (SumData) context;
data.total -= ((Number) value).doubleValue();
}
public Object getResult(Serializable context) {
return ((SumData) context).total;
}
public boolean supportsReverse() {
return true;
}
public Class<?> getResultType() {
return Double.class;
}
}
{code}
Some other cases:
Different result type than value type:
{code}
public class AverageAccumulateFunction
implements ReversableAccumulateFunction2<Integer, Double> {
public int total;
public int count;
public AverageAccumulateFunction() {
total = 0;
count = 0;
}
public void accumulate(Integer value) {
total += value;
count++;
}
public void reverse(Integer value) {
total -= value;
count--;
}
public Double getResult() {
return (double) total / count;
}
}
{code}
Construction parameter:
{code}
public class StdDeviationAccumulateFunction
implements ReversableAccumulateFunction2<Integer, Double> {
public final double average;
public double variance;
public StdDeviationAccumulateFunction(double average) {
this.average = average;
variance = 0;
}
public void accumulate(double value) {
variance += (value - average)²; // TODO
}
public void reverse(double value) {
variance -= (value - average)²; // TODO
}
public Double getResult() {
return Math.sqrt(variance);
}
}
{code}
TODO multi-argument accumulate:
...
> Make AccumulateFunction interface simpler and more powerful
> -----------------------------------------------------------
>
> Key: DROOLS-1422
> URL: https://issues.jboss.org/browse/DROOLS-1422
> Project: Drools
> Issue Type: Feature Request
> Components: core engine
> Reporter: Geoffrey De Smet
> Assignee: Mario Fusco
>
> * Replace the AccumulateFunction interface with the AccumulateFunction2 interface:
> ** All core runtime code uses the AccumulateFunction2 interface.
> ** Deprecate AccumulateFunction and use a bridge class at DRL compilation time so old implementations still work because they are bridged into the new interface
> * Changes of the AccumulateFunction2:
> ** Methods no longer throw checked exceptions (no "throws Exception"), so drools doesn't have to catch them. This might improve performance.
> ** Remove "Serializable context". The class itself contains the state.
> *** Remove method createContext()
> *** Replace method init(Serializeble) with constructor call (no-args normally)
> *** Remove parameter Serializable from accumulate(value), reserve(value) and getResult() methods
> *** Instead of making 1 AccFunction instance and n context instances, make n AccFunction instances. This uses less memory.
> *** This might improve performance (data locality).
> ** It should Serializable, but doesn't have to Externalizable. Removes methods writeExternal() and readExternal() in the user implementation.
> * Interface ReversableAccumulateFunction2 extends AccumulateFunction2
> ** Only ReversableAccumulateFunction2 has method reverse(value)
> ** Remove method supportsReverse(): the custom accumulate is reverseable if it also implements this interface
> * Opportunities
> ** construction parameters. For example: fixed average for standard deviation (very useful for OptaPlanner)
> ** Multi-argument accumulates, for example in DRL: `$total : standardDeviation($groupBy, $weight)`
> Notice how clean the user implementation would become.
> {code}
> // NEW
> public class SumAccumulateFunction
> implements ReversableAccumulateFunction2<Integer, Integer> {
> public int total;
> public SumAccumulateFunction() {
> total = 0;
> }
> public void accumulate(Integer value) {
> total += value;
> }
> public void reverse(Integer value) {
> total -= value;
> }
> public Integer getResult() {
> return total;
> }
> }
> {code}
> *Compare that with the old way:*
> {code}
> // OLD
> public class SumAccumulateFunction implements AccumulateFunction {
> public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { }
> public void writeExternal(ObjectOutput out) throws IOException { }
> protected static class SumData implements Externalizable {
> public double total = 0;
> public SumData() {}
> public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
> total = in.readDouble();
> }
> public void writeExternal(ObjectOutput out) throws IOException {
> out.writeDouble(total);
> }
> }
> public Serializable createContext() {
> return new SumData();
> }
> public void init(Serializable context) {
> SumData data = (SumData) context;
> data.total = 0;
> }
> public void accumulate(Serializable context,
> Object value) {
> SumData data = (SumData) context;
> data.total += ((Number) value).doubleValue();
> }
> public void reverse(Serializable context,
> Object value) {
> SumData data = (SumData) context;
> data.total -= ((Number) value).doubleValue();
> }
> public Object getResult(Serializable context) {
> return ((SumData) context).total;
> }
> public boolean supportsReverse() {
> return true;
> }
> public Class<?> getResultType() {
> return Double.class;
> }
> }
> {code}
> Some other cases:
> Different result type than value type:
> {code}
> public class AverageAccumulateFunction
> implements ReversableAccumulateFunction2<Integer, Double> {
> public int total;
> public int count;
> public AverageAccumulateFunction() {
> total = 0;
> count = 0;
> }
> public void accumulate(Integer value) {
> total += value;
> count++;
> }
> public void reverse(Integer value) {
> total -= value;
> count--;
> }
> public Double getResult() {
> return (double) total / count;
> }
> }
> {code}
> Construction parameter:
> {code}
> public class StdDeviationAccumulateFunction
> implements ReversableAccumulateFunction2<Integer, Double> {
> public final double average;
> public double variance;
> public StdDeviationAccumulateFunction(double average) {
> this.average = average;
> variance = 0;
> }
> public void accumulate(double value) {
> variance += (value - average)²; // TODO
> }
> public void reverse(double value) {
> variance -= (value - average)²; // TODO
> }
> public Double getResult() {
> return Math.sqrt(variance);
> }
> }
> {code}
> TODO multi-argument accumulate:
> ...
--
This message was sent by Atlassian JIRA
(v7.2.3#72005)
More information about the jboss-jira
mailing list