Source Code Cross Referenced for ScoringFunction.java in  » Science » Cougaar12_4 » org » cougaar » planning » ldm » plan » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Science » Cougaar12_4 » org.cougaar.planning.ldm.plan 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * <copyright>
0003:         *  
0004:         *  Copyright 1997-2004 BBNT Solutions, LLC
0005:         *  under sponsorship of the Defense Advanced Research Projects
0006:         *  Agency (DARPA).
0007:         * 
0008:         *  You can redistribute this software and/or modify it under the
0009:         *  terms of the Cougaar Open Source License as published on the
0010:         *  Cougaar Open Source Website (www.cougaar.org).
0011:         * 
0012:         *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0013:         *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0014:         *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0015:         *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0016:         *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0017:         *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0018:         *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0019:         *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0020:         *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0021:         *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0022:         *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0023:         *  
0024:         * </copyright>
0025:         */
0026:
0027:        package org.cougaar.planning.ldm.plan;
0028:
0029:        import java.io.Serializable;
0030:        import java.util.Arrays;
0031:        import java.util.Enumeration;
0032:        import java.util.Vector;
0033:
0034:        import org.cougaar.util.Empty;
0035:        import org.cougaar.util.SingleElementEnumeration;
0036:        import org.cougaar.util.log.Logging;
0037:
0038:        /**
0039:         * Base class for functions which compute a Score value given an AspectValue.
0040:         * Score is a double where LOW_THRESHOLD (0.0) is "good"/"optimal" and
0041:         * HIGH_THRESHOLD (1.0) is "bad" (as bad as it gets).  ScoringFunction domains
0042:         * should be infinite and Range should be 0.0 to 1.0 inclusive.
0043:         *
0044:         * @note Instances are immutable.
0045:         **/
0046:        public abstract class ScoringFunction implements  Serializable,
0047:                Cloneable {
0048:
0049:            /** Minimum valid value **/
0050:            public static final double LOW_THRESHOLD = 0.0;
0051:            /** Maximum valid value **/
0052:            public static final double HIGH_THRESHOLD = 1.0;
0053:            /** "Best" Score **/
0054:            public final static double BEST = LOW_THRESHOLD;
0055:            /** "Worst" Score **/
0056:            public final static double WORST = HIGH_THRESHOLD;
0057:
0058:            /** Typical "Satisfactory" value **/
0059:            public final static double OK = 0.5;
0060:
0061:            /** A Value to be used when the Score is undefined, equivalent to Double.NaN.
0062:             * @note Should be compared via Double.isNaN() rather than with ==
0063:             **/
0064:            public final static double NOVALUE = Double.NaN;
0065:
0066:            protected int aspectType;
0067:
0068:            protected ScoringFunction(int type) {
0069:                this .aspectType = type;
0070:            }
0071:
0072:            public abstract Object clone();
0073:
0074:            /** Find the/a "Best" value of the function.
0075:             * Can be used as a starting point for an allocator.
0076:             * If not implemented, returns null.
0077:             * @return AspectScorePoint  May be null if uncomputable.
0078:             */
0079:            public abstract AspectScorePoint getBest();
0080:
0081:            /** Find the/a "Best" value within a range.
0082:             * Specify AspectValue boundaries within the function and get the
0083:             * minimum value within those boundaries.
0084:             * If not implemented, returns null.
0085:             * @param lowerbound
0086:             * @param upperbound
0087:             * @return AspectScorePoint May be null if uncomputable.
0088:             */
0089:            public abstract AspectScorePoint getMinInRange(
0090:                    AspectValue lowerbound, AspectValue upperbound);
0091:
0092:            /** Find the/a "Worst" value within a range.
0093:             * Specify AspectValue boundaries within the function and get the
0094:             * maximum value within those boundaries.
0095:             * If not implemented, returns null.
0096:             * @param lowerbound
0097:             * @param upperbound
0098:             * @return AspectScorePoint May be null if uncomputable.
0099:             */
0100:            public abstract AspectScorePoint getMaxInRange(
0101:                    AspectValue lowerbound, AspectValue upperbound);
0102:
0103:            /** Find all non-1.0 (worst) value ranges within boundaries.
0104:             * Specify AspectValue boundaries within the function and get the
0105:             * the valid ranges of values within those boundaries.
0106:             * If not implemented, returns null.
0107:             * @param lowerbound
0108:             * @param upperbound
0109:             * @return Enumeration{AspectScoreRange} may be null if uncomputable.
0110:             */
0111:            public abstract Enumeration getValidRanges(AspectValue lowerbound,
0112:                    AspectValue upperbound);
0113:
0114:            /** @return the range over which the scoring function is defined.
0115:             * Note that "undefined" == "undifferentiated WORST" score.
0116:             * Will always return a non-null value, but one or both values of
0117:             * the range may an AspectScorePoing infinity, indicating unbounded range.
0118:             * There may be any amount of score variation, including WORST points
0119:             * within this range.
0120:             **/
0121:            public AspectScoreRange getDefinedRange() {
0122:                return new AspectScoreRange(AspectScorePoint
0123:                        .getNEGATIVE_INFINITY(aspectType), AspectScorePoint
0124:                        .getPOSITIVE_INFINITY(aspectType));
0125:            }
0126:
0127:            /** Find the Score at a point.  1.0 is worst, 0.0 is best.
0128:             * @param value
0129:             * @return double  The score given an AspectValue.
0130:             * @see org.cougaar.planning.ldm.plan.AspectValue
0131:             */
0132:            public abstract double getScore(AspectValue value);
0133:
0134:            // methods that create basic Scoring Functions
0135:
0136:            /** Create a ScoringFunction from a set of AspectScorePoints
0137:             * @param points A set of AspectScorePoints which define the curve of the function.
0138:             */
0139:            public static final ScoringFunction createPiecewiseLinearScoringFunction(
0140:                    Enumeration points) {
0141:                return new PiecewiseLinearScoringFunction(points);
0142:            }
0143:
0144:            /** Create a ScoringFunction from a set of AspectScorePoints.  The parameter will not be
0145:             * copied, so the points must never be modified.
0146:             * @param points A set of AspectScorePoints which define the curve of the function.
0147:             */
0148:            public static final ScoringFunction createPiecewiseLinearScoringFunction(
0149:                    AspectScorePoint[] points) {
0150:                return new PiecewiseLinearScoringFunction(points);
0151:            }
0152:
0153:            /** A single point with straight sides in score space
0154:             * @param value  The single point.
0155:             * @return StrictValueScoringFunction
0156:             */
0157:            public static final ScoringFunction createStrictlyAtValue(
0158:                    AspectValue value) {
0159:                return new StrictValueScoringFunction(value);
0160:            }
0161:
0162:            /** A single point with slanted sides in score space
0163:             * @param value  The single point.
0164:             * @return PreferredValueScoringFunction
0165:             */
0166:            public static final ScoringFunction createPreferredAtValue(
0167:                    AspectValue value, double slope) {
0168:                return new PreferredValueScoringFunction(value, slope);
0169:            }
0170:
0171:            /** A flat basin with straight sides.
0172:             * BEST defaults to low point.
0173:             * @param low  The low point.
0174:             * @param high The high point.
0175:             * @return StrictBetweenScoringFunction
0176:             */
0177:            public static final ScoringFunction createStrictlyBetweenValues(
0178:                    AspectValue low, AspectValue high) {
0179:                return new StrictBetweenScoringFunction(low, high);
0180:            }
0181:
0182:            /** A flat basin with straight sides.
0183:             * Just like StrictBetweenScoringFunction, except
0184:             * that BEST point is specified, even though the
0185:             * Scores of low, best and high are all actually the same.
0186:             * @param low  The low point.
0187:             * @param best  The preferred point.
0188:             * @param high The high point.
0189:             * @return StrictBetweenWithBest
0190:             */
0191:            public static final ScoringFunction createStrictlyBetweenWithBestValues(
0192:                    AspectValue low, AspectValue best, AspectValue high) {
0193:                return new StrictBetweenWithBest(low, best, high);
0194:            }
0195:
0196:            /** A typical V-shaped scoring function.
0197:             * low and high values are OK, best is BEST,
0198:             * score is linear betwen low and best, best and high.
0199:             * anything outside the range is WORST.
0200:             * The best point need not be centered between low and high.
0201:             * @param low  The low point.
0202:             * @param best  The best point.
0203:             * @param high The high point.
0204:             * @return VScoringFunction
0205:             */
0206:            public static final ScoringFunction createVScoringFunction(
0207:                    AspectValue low, AspectValue best, AspectValue high) {
0208:                return new VScoringFunction(low, best, high);
0209:            }
0210:
0211:            /** like createVScoringFunction(low,best,high) except allows specification
0212:             * of value of OK value.
0213:             **/
0214:            public static final ScoringFunction createVScoringFunction(
0215:                    AspectValue low, AspectValue best, AspectValue high,
0216:                    double ok) {
0217:                return new VScoringFunction(low, best, high, ok);
0218:            }
0219:
0220:            /** A flat basin with slanted sides
0221:             * @param low The low point.
0222:             * @param high The high point.
0223:             * @return PreferredBetweenScoringFunction
0224:             */
0225:            public static final ScoringFunction createPreferredBetweenValues(
0226:                    AspectValue low, AspectValue high, double slope) {
0227:                return new PreferredBetweenScoringFunction(low, high, slope);
0228:            }
0229:
0230:            /** Prefer as close as possible to value from above
0231:             * The score at the inflection point is BEST
0232:             * @param value The point.
0233:             * @return AboveScoringFunction
0234:             */
0235:            public static final ScoringFunction createNearOrAbove(
0236:                    AspectValue value, double slope) {
0237:                return new AboveScoringFunction(value, slope);
0238:            }
0239:
0240:            /** Prefer as close as possible to value from below
0241:             * The score at the inflection point is BEST;
0242:             * @param value  The point.
0243:             * @return BelowScoringFunction
0244:             */
0245:            public static final ScoringFunction createNearOrBelow(
0246:                    AspectValue value, double slope) {
0247:                return new BelowScoringFunction(value, slope);
0248:            }
0249:
0250:            /** Select specific enumerated points where score is allowed :
0251:             * disallowed (above threshold) at all other points.
0252:             * Note : The implementation ignores range, as enumerations have
0253:             * no sense of comparison or continuity.
0254:             * @param points array of AspectScorePoints of allowable points
0255:             */
0256:            public static final ScoringFunction createEnumerated(
0257:                    AspectScorePoint[] points) {
0258:                return new EnumeratedScoringFunction(points);
0259:            }
0260:
0261:            /** Step function
0262:             * The score exactly at the inflection point is BEST
0263:             * @param changepoint
0264:             * @param prescore
0265:             * @param postscore
0266:             */
0267:            public static final ScoringFunction createStepScoringFunction(
0268:                    AspectValue changepoint, double prescore, double postscore) {
0269:                return new StepScoringFunction(changepoint, prescore, postscore);
0270:            }
0271:
0272:            /** Constant function
0273:             * always has same score
0274:             * @param score - the score for all values
0275:             */
0276:            public static final ScoringFunction createConstantScoringFunction(
0277:                    double score, int type) {
0278:                return new ConstantScoringFunction(score, type);
0279:            }
0280:
0281:            /** Constant function
0282:             * always has same score
0283:             * @param score - the score for all values
0284:             */
0285:            public static final ScoringFunction createConstantScoringFunction(
0286:                    AspectScorePoint score) {
0287:                return new ConstantScoringFunction(score.getScore(), score
0288:                        .getAspectType());
0289:            }
0290:
0291:            //
0292:            // helper functions for below
0293:            //
0294:
0295:            protected final static AspectScorePoint newASP(double value,
0296:                    double score, int type) {
0297:                return new AspectScorePoint(AspectValue.newAspectValue(type,
0298:                        value), score);
0299:            }
0300:
0301:            /** interpolate a Y given an X and a line segment.  px must be in
0302:             * the range.
0303:             **/
0304:            final static double _interpY(double px, double x1, double y1,
0305:                    double x2, double y2) {
0306:                if (x1 == x2)
0307:                    return y1; // eliminate div0
0308:                return y1 + ((px - x1) * ((y2 - y1) / (x2 - x1)));
0309:            }
0310:
0311:            /** return an AspectScorePoint for the minimum y of the segment
0312:             * ((x1,y1) (x2, y2)) in the range of minx-maxx.
0313:             * @return WORST if out of range.
0314:             **/
0315:            final AspectScorePoint _minY(double minx, double maxx, double x1,
0316:                    double y1, double x2, double y2) {
0317:                if (x1 > maxx || x2 < minx)
0318:                    return newASP(minx, WORST, aspectType);
0319:
0320:                if (x1 < minx) {
0321:                    y1 = _interpY(minx, x1, y1, x2, y2);
0322:                    x1 = minx;
0323:                }
0324:                if (x2 > maxx) {
0325:                    y2 = _interpY(maxx, x1, y1, x2, y2);
0326:                    x2 = maxx;
0327:                }
0328:
0329:                // return the lowest y
0330:                if (y2 < y1) {
0331:                    y1 = y2;
0332:                    x1 = x2;
0333:                }
0334:
0335:                return newASP(x1, y1, aspectType);
0336:            }
0337:
0338:            /** return an AspectScorePoint for the maximum y of the segment
0339:             * ((x1,y1) (x2, y2)) in the range of minx-maxx.
0340:             * @return BEST if out of range.
0341:             **/
0342:            final AspectScorePoint _maxY(double minx, double maxx, double x1,
0343:                    double y1, double x2, double y2) {
0344:                if (x1 > maxx || x2 < minx)
0345:                    return newASP(minx, BEST, aspectType);
0346:
0347:                if (x1 < minx) {
0348:                    y1 = _interpY(minx, x1, y1, x2, y2);
0349:                    x1 = minx;
0350:                }
0351:                if (x2 > maxx) {
0352:                    y2 = _interpY(maxx, x1, y1, x2, y2);
0353:                    x2 = maxx;
0354:                }
0355:
0356:                // return the highest y
0357:                // return the lowest y
0358:                if (y2 > y1) {
0359:                    y1 = y2;
0360:                    x1 = x2;
0361:                }
0362:
0363:                return newASP(x1, y1, aspectType);
0364:            }
0365:
0366:            /** Check a set of AspectScorePoints for validity as the "curve" of
0367:             * PiecewiseLinearScoringFunction.  Tests used are: must have at least 2 points,
0368:             * all points must have the AspectType, values must be strictly increasing, scores
0369:             * may not be negative.
0370:             * @throws IllegalArgumentException on illegal curve.
0371:             **/
0372:            public final static void checkValidCurve(AspectScorePoint[] curve) {
0373:                try {
0374:                    int l = curve.length;
0375:                    if (l == 0) {
0376:                        throw new IllegalArgumentException("Empty point set");
0377:                    }
0378:                    int at = curve[0].getAspectType();
0379:                    double lv = curve[0].getValue();
0380:                    double ls = curve[0].getScore();
0381:
0382:                    for (int i = 1; i < l; i++) {
0383:                        int t = curve[i].getAspectType();
0384:                        if (t != at) {
0385:                            throw new IllegalArgumentException("curve[" + i
0386:                                    + "].getAspectType() is inconsistent (" + t
0387:                                    + " != " + at + ")");
0388:                        }
0389:
0390:                        double v = curve[i].getValue();
0391:                        double s = curve[i].getScore();
0392:                        if (Double.isNaN(v)) {
0393:                            throw new IllegalArgumentException("curve[" + i
0394:                                    + "].getValue() is not a number");
0395:                        }
0396:                        if (v < lv) {
0397:                            throw new IllegalArgumentException("curve[" + i
0398:                                    + "].getValue() decreases (" + v + "<" + lv
0399:                                    + ")");
0400:                        }
0401:                        if (v == lv && s == ls) {
0402:                            throw new IllegalArgumentException("curve[" + i
0403:                                    + "] == curve[" + (i - 1) + "]");
0404:                        }
0405:                        lv = v;
0406:                        ls = s;
0407:
0408:                        if (Double.isNaN(s)) {
0409:                            throw new IllegalArgumentException("curve[" + i
0410:                                    + "].getScore() is not a number");
0411:                        }
0412:                        if (s < LOW_THRESHOLD || s > HIGH_THRESHOLD) {
0413:                            throw new IllegalArgumentException("curve[" + i
0414:                                    + "].getScore() out of range (" + s + ")");
0415:                        }
0416:                    }
0417:                } catch (IllegalArgumentException e) {
0418:                    Logging.getLogger(ScoringFunction.class).error(
0419:                            "Bad ScoringFunction curve", e);
0420:                }
0421:            }
0422:
0423:            //
0424:            // Implementations of the convenience ScoringFunctions above
0425:            //
0426:
0427:            public static class PiecewiseLinearScoringFunction extends
0428:                    ScoringFunction {
0429:                protected AspectScorePoint curve[];
0430:
0431:                public PiecewiseLinearScoringFunction(Enumeration points) {
0432:                    super (0);
0433:                    if (points == null || !points.hasMoreElements()) {
0434:                        throw new IllegalArgumentException(
0435:                                "Enumeration of points must be non-empty");
0436:                    }
0437:                    Vector v = new Vector();
0438:                    while (points.hasMoreElements()) {
0439:                        v.addElement(points.nextElement());
0440:                    }
0441:                    curve = (AspectScorePoint[]) v
0442:                            .toArray(new AspectScorePoint[v.size()]);
0443:                    checkValidCurve(curve);
0444:                    aspectType = curve[0].getAspectType();
0445:                }
0446:
0447:                public PiecewiseLinearScoringFunction(AspectScorePoint[] points) {
0448:                    super (0);
0449:                    curve = points;
0450:                    checkValidCurve(curve);
0451:                    aspectType = curve[0].getAspectType();
0452:                }
0453:
0454:                public boolean equals(Object o) {
0455:                    if (o instanceof  PiecewiseLinearScoringFunction) {
0456:                        PiecewiseLinearScoringFunction that = (PiecewiseLinearScoringFunction) o;
0457:                        return Arrays.equals(this .curve, that.curve);
0458:                    }
0459:                    return false;
0460:                }
0461:
0462:                public Object clone() {
0463:                    return new PiecewiseLinearScoringFunction(
0464:                            new Enumeration() {
0465:                                private int ix = 0;
0466:
0467:                                public boolean hasMoreElements() {
0468:                                    return ix < curve.length;
0469:                                }
0470:
0471:                                public Object nextElement() {
0472:                                    return curve[ix++].clone();
0473:                                }
0474:                            });
0475:                }
0476:
0477:                public double getScore(AspectValue value) {
0478:                    return getScore(value.getValue());
0479:                }
0480:
0481:                protected double getScore(double vp) {
0482:                    int l = curve.length;
0483:                    AspectScorePoint c1 = null;
0484:                    for (int i = 0; i < l; i++) {
0485:                        c1 = curve[i];
0486:                        double v1 = c1.getValue();
0487:                        double s1 = c1.getScore();
0488:
0489:                        if (vp < v1) {
0490:                            if (i > 0) {
0491:                                AspectScorePoint c0 = curve[i - 1];
0492:                                double v0 = c0.getValue();
0493:
0494:                                if (v1 <= v0)
0495:                                    return s1; // second point wins on undefined.
0496:
0497:                                double s0 = c0.getScore();
0498:                                double slope = (s1 - s0) / (v1 - v0);
0499:
0500:                                return s0 + (vp - v0) * slope;
0501:
0502:                            } else {
0503:                                return s1;
0504:                            }
0505:                        } // else continue
0506:                    }
0507:                    // drop through - flat after last point.
0508:                    return c1.getScore();
0509:                }
0510:
0511:                public AspectScorePoint getMinInRange(AspectValue lowerbound,
0512:                        AspectValue upperbound) {
0513:                    AspectScorePoint c0 = curve[0];
0514:                    AspectScorePoint c1;
0515:                    int l = curve.length;
0516:                    if (l == 1)
0517:                        return c0;
0518:                    double x0 = c0.getValue();
0519:                    double y0 = c0.getScore();
0520:
0521:                    double minx = lowerbound.getValue();
0522:                    double maxx = upperbound.getValue();
0523:
0524:                    AspectScorePoint bp = null;
0525:
0526:                    for (int i = 1; i < l; i++) {
0527:                        c1 = curve[i];
0528:                        double x1 = c1.getValue();
0529:                        double y1 = c1.getScore();
0530:                        AspectScorePoint pp = super ._minY(minx, maxx, x0, y0,
0531:                                x1, y1);
0532:                        if (bp == null || pp.getScore() < bp.getScore())
0533:                            bp = pp;
0534:                    }
0535:                    if (bp == null || bp.getScore() == WORST)
0536:                        return null;
0537:                    return bp;
0538:                }
0539:
0540:                public AspectScorePoint getMaxInRange(AspectValue lowerbound,
0541:                        AspectValue upperbound) {
0542:                    AspectScorePoint c0 = curve[0];
0543:                    AspectScorePoint c1;
0544:                    int l = curve.length;
0545:                    if (l == 1)
0546:                        return c0;
0547:                    double x0 = c0.getValue();
0548:                    double y0 = c0.getScore();
0549:
0550:                    double minx = lowerbound.getValue();
0551:                    double maxx = upperbound.getValue();
0552:
0553:                    AspectScorePoint bp = null;
0554:
0555:                    for (int i = 1; i < l; i++) {
0556:                        c1 = curve[i];
0557:                        double x1 = c1.getValue();
0558:                        double y1 = c1.getScore();
0559:                        AspectScorePoint pp = super ._maxY(minx, maxx, x0, y0,
0560:                                x1, y1);
0561:                        if (bp == null || pp.getScore() > bp.getScore())
0562:                            bp = pp;
0563:                    }
0564:                    if (bp == null || bp.getScore() == BEST)
0565:                        return null;
0566:                    return bp;
0567:                }
0568:
0569:                protected class DPair {
0570:                    public double x0, x1;
0571:
0572:                    public DPair(double x0, double x1) {
0573:                        this .x0 = x0;
0574:                        this .x1 = x1;
0575:                    }
0576:                }
0577:
0578:                /** return a vector of DPair instances, each one is a
0579:                 * range of valid x values.  Some may be points (x = x);
0580:                 * Will return an empty vector if no points are lower than then threshold.
0581:                 **/
0582:                protected Vector getAllValidValues(double thresh) {
0583:                    AspectScorePoint c0 = curve[0];
0584:                    double x0 = c0.getValue();
0585:                    double y0 = c0.getScore();
0586:                    boolean v0 = (y0 < thresh);
0587:                    AspectScorePoint c1;
0588:                    double x1, y1;
0589:                    boolean v1;
0590:
0591:                    Vector v = new Vector();
0592:
0593:                    int l = curve.length;
0594:
0595:                    if (l == 1) {
0596:                        if (v0) {
0597:                            v.addElement(new DPair(x0, x0));
0598:                        }
0599:                        return v;
0600:                    }
0601:
0602:                    DPair r = null;
0603:                    for (int i = 1; i < l; i++) {
0604:                        c1 = curve[i];
0605:                        x1 = c1.getValue();
0606:                        y1 = c1.getScore();
0607:                        v1 = (y1 < thresh);
0608:
0609:                        // is there a crossing?
0610:                        if (v0) {
0611:                            if (v1) { // both valid
0612:                                if (r == null) {
0613:                                    r = new DPair(x0, x1);
0614:                                } else {
0615:                                    r.x1 = x1;
0616:                                }
0617:                            } else { // v0 valid, v1 not
0618:                                // find the cross point
0619:                                double dx = x1 - x0;
0620:                                if (dx == 0) { // discontinuity
0621:                                    if (r == null) {
0622:                                        v.addElement(new DPair(x0, x0));
0623:                                    } else {
0624:                                        v.addElement(r);
0625:                                        r = null;
0626:                                    }
0627:                                } else {
0628:                                    double x = x0
0629:                                            + (((x1 - x0) * (thresh - y0)) / (y1 - y0));
0630:                                    if (r == null) {
0631:                                        v.addElement(new DPair(x0, x));
0632:                                    } else {
0633:                                        r.x1 = x;
0634:                                        v.addElement(r);
0635:                                        r = null;
0636:                                    }
0637:                                }
0638:                            }
0639:                        } else {
0640:                            if (v1) { // v0 not, v1 valid
0641:                                // find the cross point
0642:                                double dx = x1 - x0;
0643:                                if (dx == 0) { // discontinuity
0644:                                    if (r == null) {
0645:                                        r = new DPair(x1, x1);
0646:                                    } else {
0647:                                        // shouldn't actually happen, I think
0648:                                        v.addElement(r);
0649:                                        r = new DPair(x1, x1);
0650:                                    }
0651:                                } else {
0652:                                    double x = x0
0653:                                            + (((x1 - x0) * (thresh - y0)) / (y1 - y0));
0654:                                    if (r == null) {
0655:                                        r = new DPair(x, x1);
0656:                                    } else {
0657:                                        // again, shouldn't happen
0658:                                        r.x1 = x;
0659:                                        v.addElement(r);
0660:                                        r = null;
0661:                                    }
0662:                                }
0663:                            } else { // both invalid
0664:                                // just advance
0665:                            }
0666:                        }
0667:
0668:                        c0 = c1;
0669:                        x0 = x1;
0670:                        y0 = x1;
0671:                        v0 = v1;
0672:                    }
0673:
0674:                    if (r != null)
0675:                        v.addElement(r);
0676:                    return v;
0677:                }
0678:
0679:                public Enumeration getValidRanges(AspectValue lowerbound,
0680:                        AspectValue upperbound) {
0681:                    double minx = lowerbound.getValue();
0682:                    double maxx = upperbound.getValue();
0683:
0684:                    Vector all = getAllValidValues(WORST);
0685:
0686:                    Vector clipped = new Vector();
0687:
0688:                    int sz = all.size();
0689:                    for (int i = 0; i < sz; i++) {
0690:                        DPair dp = (DPair) all.elementAt(i);
0691:                        double x0 = dp.x0;
0692:                        double y0 = getScore(x0); // nasty
0693:                        double x1 = dp.x1;
0694:                        double y1 = getScore(x1); // evil
0695:                        if (x0 >= maxx)
0696:                            break; // seg is past range: stop
0697:
0698:                        if (x1 <= minx) // seg is before range: skip ahead
0699:                            continue;
0700:
0701:                        // cut by range start?
0702:                        if (x0 < minx) {
0703:                            x0 = minx;
0704:                            x0 = getScore(x0); //  horribly inefficient
0705:                        }
0706:                        // cut by range end?
0707:                        if (x1 > maxx) {
0708:                            x1 = maxx;
0709:                            y1 = getScore(x1); // noxious
0710:                        }
0711:
0712:                        // add a valid range to clipped vector
0713:                        clipped.addElement(new AspectScoreRange(newASP(x0, y0,
0714:                                aspectType), newASP(x1, y1, aspectType)));
0715:                    }
0716:
0717:                    return clipped.elements();
0718:                }
0719:
0720:                public AspectScoreRange getDefinedRange() {
0721:                    return new AspectScoreRange(curve[0],
0722:                            curve[curve.length - 1]);
0723:                }
0724:
0725:                public AspectScorePoint getBest() {
0726:                    AspectScorePoint best = curve[0];
0727:                    double bs = best.getScore();
0728:                    int l = curve.length;
0729:                    for (int i = 1; i < l; i++) {
0730:                        AspectScorePoint asp = curve[i];
0731:                        double s = asp.getScore();
0732:                        if (s < bs) {
0733:                            best = asp;
0734:                            bs = s;
0735:                        }
0736:                    }
0737:                    return best;
0738:                }
0739:
0740:                public String toString() {
0741:                    return "<PiecewiseLinear " + curve.length + ">";
0742:                }
0743:
0744:            }
0745:
0746:            /** utility base class for storing single-point SFs **/
0747:
0748:            public static abstract class SinglePointScoringFunction extends
0749:                    ScoringFunction {
0750:                protected AspectValue point;
0751:
0752:                protected SinglePointScoringFunction(AspectValue value) {
0753:                    super (value.getAspectType());
0754:                    point = value;
0755:                }
0756:
0757:                public AspectValue getPoint() {
0758:                    return point;
0759:                }
0760:
0761:                public boolean equals(Object o) {
0762:                    if (o instanceof  SinglePointScoringFunction) {
0763:                        SinglePointScoringFunction that = (SinglePointScoringFunction) o;
0764:                        return that.point.equals(this .point);
0765:                    }
0766:                    return false;
0767:                }
0768:            }
0769:
0770:            /* A single point with straight sides in score space
0771:             * @param value  The single point.
0772:             * @return StrictValueScoringFunction
0773:             */
0774:
0775:            public static class StrictValueScoringFunction extends
0776:                    SinglePointScoringFunction {
0777:                private transient AspectScorePoint basp = null;
0778:
0779:                private synchronized AspectScorePoint getB() {
0780:                    if (basp == null) {
0781:                        basp = new AspectScorePoint(point, BEST);
0782:                    }
0783:                    return basp;
0784:                }
0785:
0786:                public StrictValueScoringFunction(AspectValue value) {
0787:                    super (value);
0788:                }
0789:
0790:                public boolean equals(Object o) {
0791:                    if (o instanceof  StrictValueScoringFunction) {
0792:                        return super .equals(o);
0793:                    }
0794:                    return false;
0795:                }
0796:
0797:                public Object clone() {
0798:                    return new StrictValueScoringFunction(point);
0799:                }
0800:
0801:                public AspectScorePoint getBest() {
0802:                    return getB();
0803:                }
0804:
0805:                public AspectScorePoint getMinInRange(AspectValue lowerbound,
0806:                        AspectValue upperbound) {
0807:                    if (point.isBetween(lowerbound, upperbound)) {
0808:                        return getB();
0809:                    } else {
0810:                        return new AspectScorePoint(lowerbound, WORST);
0811:                    }
0812:                }
0813:
0814:                public AspectScorePoint getMaxInRange(AspectValue lowerbound,
0815:                        AspectValue upperbound) {
0816:                    if (point.equals(lowerbound) && point.equals(upperbound)) {
0817:                        return getB();
0818:                    } else {
0819:                        return new AspectScorePoint(lowerbound, WORST);
0820:                    }
0821:                }
0822:
0823:                public Enumeration getValidRanges(AspectValue lowerbound,
0824:                        AspectValue upperbound) {
0825:                    if (point.isBetween(lowerbound, upperbound)) {
0826:                        AspectScorePoint asp = getB();
0827:                        return new SingleElementEnumeration(
0828:                                new AspectScoreRange(asp, asp));
0829:                    } else {
0830:                        return Empty.enumeration;
0831:                    }
0832:                }
0833:
0834:                public double getScore(AspectValue value) {
0835:                    if (point.equals(value)) {
0836:                        return BEST;
0837:                    } else {
0838:                        return WORST;
0839:                    }
0840:                }
0841:
0842:                public String toString() {
0843:                    return "<StrictValue " + point + ">";
0844:                }
0845:            }
0846:
0847:            /** classic symmetric V curve.
0848:             *  Score = min(1.0, | value - point | * slope)
0849:             **/
0850:
0851:            public static class PreferredValueScoringFunction extends
0852:                    SinglePointScoringFunction {
0853:                protected double slope;
0854:
0855:                private transient AspectScorePoint basp = null;
0856:
0857:                private synchronized AspectScorePoint getB() {
0858:                    if (basp == null) {
0859:                        basp = new AspectScorePoint(point, BEST);
0860:                    }
0861:                    return basp;
0862:                }
0863:
0864:                public boolean equals(Object o) {
0865:                    if (o instanceof  PreferredValueScoringFunction) {
0866:                        PreferredValueScoringFunction that = (PreferredValueScoringFunction) o;
0867:                        if (that.slope != this .slope)
0868:                            return false;
0869:                        return super .equals(o);
0870:                    }
0871:                    return false;
0872:                }
0873:
0874:                public PreferredValueScoringFunction(AspectValue value,
0875:                        double slope) {
0876:                    super (value);
0877:                    this .slope = slope;
0878:                }
0879:
0880:                public Object clone() {
0881:                    return new PreferredValueScoringFunction(point, slope);
0882:                }
0883:
0884:                public AspectScorePoint getBest() {
0885:                    return getB();
0886:                }
0887:
0888:                public Enumeration getValidRanges(AspectValue lowerbound,
0889:                        AspectValue upperbound) {
0890:                    double v = point.getValue();
0891:                    int t = point.getAspectType();
0892:                    double delta = (slope == 0.0) ? (0.0) : (1 / slope);
0893:                    AspectValue v0 = AspectValue.newAspectValue(t, v - delta);
0894:                    AspectValue v1 = AspectValue.newAspectValue(t, v + delta);
0895:                    AspectScorePoint p0 = new AspectScorePoint(v0, WORST);
0896:                    AspectScorePoint p1 = new AspectScorePoint(v1, WORST);
0897:                    return new SingleElementEnumeration(new AspectScoreRange(
0898:                            p0, p1));
0899:                }
0900:
0901:                public double getScore(AspectValue value) {
0902:                    return Math
0903:                            .min(WORST, slope * Math.abs(point.minus(value)));
0904:                }
0905:
0906:                public AspectScorePoint getMinInRange(AspectValue lowerbound,
0907:                        AspectValue upperbound) {
0908:                    AspectScorePoint asp = null;
0909:                    if (point.isBetween(lowerbound, upperbound))
0910:                        asp = getB();
0911:                    else if (upperbound.isLessThan(point))
0912:                        asp = new AspectScorePoint(upperbound,
0913:                                getScore(upperbound));
0914:                    else
0915:                        asp = new AspectScorePoint(lowerbound,
0916:                                getScore(lowerbound));
0917:                    return asp;
0918:                }
0919:
0920:                public AspectScorePoint getMaxInRange(AspectValue lowerbound,
0921:                        AspectValue upperbound) {
0922:                    //AspectScorePoint asp = null;
0923:                    double ubScore = getScore(upperbound);
0924:                    double lbScore = getScore(lowerbound);
0925:
0926:                    if (lbScore > ubScore)
0927:                        return new AspectScorePoint(lowerbound, lbScore);
0928:                    else
0929:                        return new AspectScorePoint(upperbound, ubScore);
0930:                }
0931:
0932:                public String toString() {
0933:                    return "<PreferredValue " + point + " " + slope + ">";
0934:                }
0935:            }
0936:
0937:            public static abstract class TwoPointScoringFunction extends
0938:                    ScoringFunction {
0939:                protected AspectValue point1, point2;
0940:
0941:                protected TwoPointScoringFunction(AspectValue point1,
0942:                        AspectValue point2) {
0943:                    super (point1.getAspectType());
0944:                    this .point1 = point1;
0945:                    this .point2 = point2;
0946:                }
0947:
0948:                public boolean equals(Object o) {
0949:                    if (o instanceof  TwoPointScoringFunction) {
0950:                        TwoPointScoringFunction that = (TwoPointScoringFunction) o;
0951:                        return ((this .point1 == null ? that.point1 == null
0952:                                : this .point1.equals(that.point1)) && (this .point2 == null ? that.point2 == null
0953:                                : this .point2.equals(that.point2)));
0954:                    }
0955:                    return false;
0956:                }
0957:
0958:                public AspectValue getPoint1() {
0959:                    return point1;
0960:                }
0961:
0962:                public AspectValue getPoint2() {
0963:                    return point2;
0964:                }
0965:            }
0966:
0967:            public static class VScoringFunction extends
0968:                    TwoPointScoringFunction {
0969:                protected AspectValue best;
0970:                protected double ok;
0971:
0972:                public VScoringFunction(AspectValue low, AspectValue best,
0973:                        AspectValue high, double ok) {
0974:                    super (low, high);
0975:                    this .best = best;
0976:                    this .ok = ok;
0977:                }
0978:
0979:                public VScoringFunction(AspectValue low, AspectValue best,
0980:                        AspectValue high) {
0981:                    super (low, high);
0982:                    this .best = best;
0983:                    this .ok = OK;
0984:                }
0985:
0986:                public boolean equals(Object o) {
0987:                    if (o instanceof  VScoringFunction) {
0988:                        VScoringFunction that = (VScoringFunction) o;
0989:                        if (that.ok != this .ok)
0990:                            return false;
0991:                        if (!that.best.equals(this .best))
0992:                            return false;
0993:                        return super .equals(o);
0994:                    }
0995:                    return false;
0996:                }
0997:
0998:                public Object clone() { // clone is probably useless, since it is immutable
0999:                    return new VScoringFunction(point1, best, point2, ok);
1000:                }
1001:
1002:                // take the specified best as best
1003:                public AspectScorePoint getBest() {
1004:                    return new AspectScorePoint(best, BEST);
1005:                }
1006:
1007:                public Enumeration getValidRanges(AspectValue lowerbound,
1008:                        AspectValue upperbound) {
1009:                    AspectScorePoint p0 = new AspectScorePoint(point1, ok);
1010:                    AspectScorePoint p1 = new AspectScorePoint(point2, ok);
1011:                    return new SingleElementEnumeration(new AspectScoreRange(
1012:                            p0, p1));
1013:                }
1014:
1015:                // Although called VScoringFunction, the V hangs from an inverted pedestal
1016:                //----+      +----
1017:                //    |      |
1018:                //    |      |
1019:                //     \    /
1020:                //      \  /
1021:                //       \/
1022:
1023:                public double getScore(AspectValue value) {
1024:                    if (value.isBetween(point1, point2)) {
1025:                        double vp = value.getValue();
1026:                        double b = best.getValue();
1027:                        double p = ((vp < b) ? point1 : point2).getValue();
1028:                        // Value must be BEST at b and ok at p and linear between
1029:                        return ok + (vp - p) * (BEST - ok) / (b - p);
1030:                    } else {
1031:                        return WORST;
1032:                    }
1033:                }
1034:
1035:                public AspectScorePoint getMaxInRange(AspectValue lowerbound,
1036:                        AspectValue upperbound) {
1037:                    double ubScore = getScore(upperbound);
1038:                    double lbScore = getScore(lowerbound);
1039:
1040:                    if (ubScore < lbScore)
1041:                        return new AspectScorePoint(upperbound, ubScore);
1042:                    return new AspectScorePoint(lowerbound, lbScore);
1043:                }
1044:
1045:                public AspectScorePoint getMinInRange(AspectValue lowerbound,
1046:                        AspectValue upperbound) {
1047:
1048:                    // best is in range
1049:                    if (best.isBetween(lowerbound, upperbound))
1050:                        return getBest();
1051:
1052:                    // Out of range completely
1053:                    if (point1.isGreaterThan(upperbound))
1054:                        return new AspectScorePoint(upperbound, WORST);
1055:
1056:                    // Out of range completely
1057:                    if (point2.isLessThan(lowerbound))
1058:                        return new AspectScorePoint(lowerbound, WORST);
1059:
1060:                    // Ends on low
1061:                    if (point1.equals(upperbound))
1062:                        return new AspectScorePoint(upperbound, ok);
1063:
1064:                    // Starts on high
1065:                    if (point2.equals(lowerbound))
1066:                        return new AspectScorePoint(lowerbound, ok);
1067:
1068:                    // On the downslope
1069:                    if (upperbound.isLessThan(best))
1070:                        return new AspectScorePoint(upperbound,
1071:                                getScore(upperbound));
1072:
1073:                    // On the upslope
1074:                    return new AspectScorePoint(lowerbound,
1075:                            getScore(lowerbound));
1076:                }
1077:
1078:                public String toString() {
1079:                    return "<V " + point1 + "-" + point2 + " best=" + best
1080:                            + " ok=" + ok + ">";
1081:                }
1082:            }
1083:
1084:            public static class StrictBetweenScoringFunction extends
1085:                    TwoPointScoringFunction {
1086:                public StrictBetweenScoringFunction(AspectValue low,
1087:                        AspectValue high) {
1088:                    super (low, high);
1089:                }
1090:
1091:                public boolean equals(Object o) {
1092:                    if (o instanceof  StrictBetweenScoringFunction) {
1093:                        return super .equals(o);
1094:                    }
1095:                    return false;
1096:                }
1097:
1098:                public Object clone() {
1099:                    return new StrictBetweenScoringFunction(point1, point2);
1100:                }
1101:
1102:                //arbitrarily take the low value as best for now
1103:                public AspectScorePoint getBest() {
1104:                    return new AspectScorePoint(point1, BEST);
1105:                }
1106:
1107:                public Enumeration getValidRanges(AspectValue lowerbound,
1108:                        AspectValue upperbound) {
1109:                    AspectScorePoint p0 = new AspectScorePoint(point1, WORST);
1110:                    AspectScorePoint p1 = new AspectScorePoint(point2, WORST);
1111:                    return new SingleElementEnumeration(new AspectScoreRange(
1112:                            p0, p1));
1113:                }
1114:
1115:                public double getScore(AspectValue value) {
1116:                    if (value.isBetween(point1, point2))
1117:                        return BEST;
1118:                    else
1119:                        return WORST;
1120:                }
1121:
1122:                public AspectScorePoint getMaxInRange(AspectValue lowerbound,
1123:                        AspectValue upperbound) {
1124:
1125:                    // Begins out of range
1126:                    if (!lowerbound.isBetween(point1, point2))
1127:                        return new AspectScorePoint(lowerbound, WORST);
1128:
1129:                    // Ends out of range
1130:                    if (!upperbound.isBetween(point1, point2))
1131:                        return new AspectScorePoint(upperbound, WORST);
1132:
1133:                    // Arbitrarily send back lowerbound
1134:                    return new AspectScorePoint(lowerbound, BEST);
1135:                }
1136:
1137:                public AspectScorePoint getMinInRange(AspectValue lowerbound,
1138:                        AspectValue upperbound) {
1139:
1140:                    // starts between
1141:                    if (lowerbound.isBetween(point1, point2))
1142:                        return new AspectScorePoint(lowerbound, BEST);
1143:
1144:                    // ends between
1145:                    if (upperbound.isBetween(point1, point2))
1146:                        return new AspectScorePoint(upperbound, BEST);
1147:
1148:                    // surrounds
1149:                    if (point1.isBetween(lowerbound, upperbound)
1150:                            && point2.isBetween(lowerbound, upperbound))
1151:                        // return a point halfway between point1 and point2
1152:                        return new AspectScorePoint(AspectValue.newAspectValue(
1153:                                lowerbound.getAspectType(),
1154:                                (point1.getValue() + point2.getValue()) / 2),
1155:                                BEST);
1156:
1157:                    // Not in range at all, arbitrarily send back upperbound
1158:                    return new AspectScorePoint(upperbound, WORST);
1159:                }
1160:
1161:                public String toString() {
1162:                    return "<StrictBetween " + point1 + "-" + point2 + ">";
1163:                }
1164:            }
1165:
1166:            public static class StrictBetweenWithBest extends
1167:                    StrictBetweenScoringFunction {
1168:
1169:                protected AspectValue best;
1170:
1171:                public StrictBetweenWithBest(AspectValue low, AspectValue best,
1172:                        AspectValue high) {
1173:                    super (low, high);
1174:                    this .best = best;
1175:                }
1176:
1177:                public boolean equals(Object o) {
1178:                    if (o instanceof  StrictBetweenWithBest) {
1179:                        StrictBetweenWithBest that = (StrictBetweenWithBest) o;
1180:                        if (this .best.equals(that.best)) {
1181:                            return super .equals(o);
1182:                        }
1183:                    }
1184:                    return false;
1185:                }
1186:
1187:                public Object clone() {
1188:                    return new StrictBetweenWithBest(point1, best, point2);
1189:                }
1190:
1191:                // take the specified best as best
1192:                public AspectScorePoint getBest() {
1193:                    return new AspectScorePoint(best, BEST);
1194:                }
1195:
1196:                public AspectScorePoint getMinInRange(AspectValue lowerbound,
1197:                        AspectValue upperbound) {
1198:                    if (best.isBetween(lowerbound, upperbound))
1199:                        return getBest();
1200:
1201:                    return super .getMinInRange(lowerbound, upperbound);
1202:                }
1203:
1204:                public String toString() {
1205:                    return "<StrictBetween " + point1 + "-" + point2 + " best="
1206:                            + best + ">";
1207:                }
1208:            }
1209:
1210:            public static class PreferredBetweenScoringFunction extends
1211:                    TwoPointScoringFunction {
1212:                protected double slope;
1213:
1214:                public PreferredBetweenScoringFunction(AspectValue low,
1215:                        AspectValue high, double slope) {
1216:                    super (low, high);
1217:                    this .slope = slope;
1218:                }
1219:
1220:                public boolean equals(Object o) {
1221:                    if (o instanceof  PreferredBetweenScoringFunction) {
1222:                        PreferredBetweenScoringFunction that = (PreferredBetweenScoringFunction) o;
1223:                        if (that.slope != this .slope)
1224:                            return false;
1225:                        return super .equals(o);
1226:                    }
1227:                    return false;
1228:                }
1229:
1230:                public Object clone() {
1231:                    return new PreferredBetweenScoringFunction(point1, point2,
1232:                            slope);
1233:                }
1234:
1235:                //arbitrarily take the low value as best for now
1236:                public AspectScorePoint getBest() {
1237:                    return new AspectScorePoint(point1, BEST);
1238:                }
1239:
1240:                public Enumeration getValidRanges(AspectValue lowerbound,
1241:                        AspectValue upperbound) {
1242:                    int t = point1.getAspectType();
1243:                    double delta = (slope == 0.0) ? (0.0) : (1 / slope);
1244:                    AspectValue v0 = AspectValue.newAspectValue(t, point1
1245:                            .getValue()
1246:                            - delta);
1247:                    AspectValue v1 = AspectValue.newAspectValue(t, point1
1248:                            .getValue()
1249:                            + delta);
1250:                    AspectScorePoint p0 = new AspectScorePoint(v0, WORST);
1251:                    AspectScorePoint p1 = new AspectScorePoint(v1, WORST);
1252:                    return new SingleElementEnumeration(new AspectScoreRange(
1253:                            p0, p1));
1254:                }
1255:
1256:                public double getScore(AspectValue value) {
1257:                    if (value.isLessThan(point1)) {
1258:                        return Math.min(WORST, slope * point1.minus(value));
1259:                    } else if (value.isGreaterThan(point2)) {
1260:                        return Math.min(WORST, slope * value.minus(point2));
1261:                    } else {
1262:                        return BEST;
1263:                    }
1264:                }
1265:
1266:                public AspectScorePoint getMinInRange(AspectValue lowerbound,
1267:                        AspectValue upperbound) {
1268:                    // range spans basin
1269:                    if (point1.isBetween(lowerbound, upperbound)
1270:                            && point2.isBetween(lowerbound, upperbound)) {
1271:                        // pick halfway point in basin
1272:                        AspectValue halfpoint = AspectValue.newAspectValue(
1273:                                lowerbound.getAspectType(),
1274:                                (point1.getValue() + point2.getValue()) / 2);
1275:                        return new AspectScorePoint(halfpoint,
1276:                                getScore(halfpoint));
1277:                    }
1278:
1279:                    double ubScore = getScore(upperbound);
1280:                    double lbScore = getScore(lowerbound);
1281:
1282:                    // range begins or ends in basin
1283:                    if (lowerbound.isBetween(point1, point2))
1284:                        return new AspectScorePoint(lowerbound, lbScore);
1285:                    if (upperbound.isBetween(point1, point2))
1286:                        return new AspectScorePoint(upperbound, ubScore);
1287:
1288:                    // one of the end points is the min
1289:                    if (lbScore < ubScore)
1290:                        return new AspectScorePoint(lowerbound, lbScore);
1291:                    return new AspectScorePoint(upperbound, ubScore);
1292:
1293:                }
1294:
1295:                public AspectScorePoint getMaxInRange(AspectValue lowerbound,
1296:                        AspectValue upperbound) {
1297:                    double ubScore = getScore(upperbound);
1298:                    double lbScore = getScore(lowerbound);
1299:                    // max has to be one of the end points
1300:                    if (lbScore > ubScore)
1301:                        return new AspectScorePoint(lowerbound, lbScore);
1302:                    return new AspectScorePoint(upperbound, ubScore);
1303:
1304:                }
1305:
1306:                public String toString() {
1307:                    return "<PreferredBetween " + point1 + "-" + point2
1308:                            + " slope=" + slope + ">";
1309:                }
1310:            }
1311:
1312:            public static class AboveScoringFunction extends
1313:                    SinglePointScoringFunction {
1314:                private double slope;
1315:
1316:                public AboveScoringFunction(AspectValue value, double slope) {
1317:                    super (value);
1318:                    this .slope = slope;
1319:                }
1320:
1321:                public boolean equals(Object o) {
1322:                    if (o instanceof  AboveScoringFunction) {
1323:                        AboveScoringFunction that = (AboveScoringFunction) o;
1324:                        if (that.slope != this .slope)
1325:                            return false;
1326:                        return super .equals(o);
1327:                    }
1328:                    return false;
1329:                }
1330:
1331:                public Object clone() {
1332:                    return new AboveScoringFunction(point, slope);
1333:                }
1334:
1335:                public AspectScorePoint getBest() {
1336:                    return new AspectScorePoint(point, BEST);
1337:                }
1338:
1339:                public AspectScorePoint getMinInRange(AspectValue lowerbound,
1340:                        AspectValue upperbound) {
1341:                    AspectScorePoint asp = null;
1342:                    if (point.isBetween(lowerbound, upperbound))
1343:                        asp = new AspectScorePoint(point, BEST);
1344:                    else if (point.isGreaterThan(upperbound))
1345:                        asp = new AspectScorePoint(upperbound, WORST);
1346:                    else
1347:                        asp = new AspectScorePoint(lowerbound,
1348:                                getScore(lowerbound));
1349:                    return asp;
1350:                }
1351:
1352:                public AspectScorePoint getMaxInRange(AspectValue lowerbound,
1353:                        AspectValue upperbound) {
1354:                    AspectScorePoint asp = null;
1355:                    double ubScore = getScore(upperbound);
1356:                    double lbScore = getScore(lowerbound);
1357:                    // One of the endpoints is Max
1358:                    if (lbScore > ubScore)
1359:                        asp = new AspectScorePoint(lowerbound, lbScore);
1360:                    else
1361:                        asp = new AspectScorePoint(upperbound, ubScore);
1362:                    return asp;
1363:                }
1364:
1365:                public double getScore(AspectValue value) {
1366:                    if (!(value.isLessThan(point))) {
1367:                        return Math.min(WORST, slope * value.minus(point));
1368:                    } else {
1369:                        return WORST;
1370:                    }
1371:                }
1372:
1373:                public Enumeration getValidRanges(AspectValue lowerbound,
1374:                        AspectValue upperbound) {
1375:
1376:                    double lbScore = getScore(lowerbound);
1377:                    double ubScore = getScore(upperbound);
1378:
1379:                    // Whole range in safe area
1380:                    if ((lbScore < WORST) && (ubScore < WORST)) {
1381:                        // return range
1382:                        AspectScorePoint p0 = new AspectScorePoint(lowerbound,
1383:                                lbScore);
1384:                        AspectScorePoint p1 = new AspectScorePoint(upperbound,
1385:                                ubScore);
1386:                        return new SingleElementEnumeration(
1387:                                new AspectScoreRange(p0, p1));
1388:                    }
1389:
1390:                    // Whole range in WORST area
1391:                    if (!point.isBetween(lowerbound, upperbound)
1392:                            && (lbScore == WORST) && (ubScore == WORST)) {
1393:                        // return empty set
1394:                        return Empty.enumeration;
1395:                    }
1396:
1397:                    AspectScorePoint p0;
1398:                    AspectScorePoint p1;
1399:                    // Starts before point
1400:                    if (lowerbound.isLessThan(point))
1401:                        // use point
1402:                        p0 = new AspectScorePoint(point, getScore(point));
1403:                    else
1404:                        // use lb
1405:                        p0 = new AspectScorePoint(lowerbound, lbScore);
1406:
1407:                    if (ubScore < WORST)
1408:                        // use ub
1409:                        p1 = new AspectScorePoint(upperbound, ubScore);
1410:                    else {
1411:                        double delta = (slope == 0.0) ? (0.0) : (1 / slope);
1412:                        AspectValue v1 = AspectValue.newAspectValue(point
1413:                                .getAspectType(), point.getValue() + delta);
1414:                        p1 = new AspectScorePoint(v1, WORST);
1415:                    }
1416:                    return new SingleElementEnumeration(new AspectScoreRange(
1417:                            p0, p1));
1418:                }
1419:
1420:                public String toString() {
1421:                    return "<Above " + point + " " + slope + ">";
1422:                }
1423:            }
1424:
1425:            public static class BelowScoringFunction extends
1426:                    SinglePointScoringFunction {
1427:                private double slope;
1428:
1429:                public BelowScoringFunction(AspectValue value, double slope) {
1430:                    super (value);
1431:                    this .slope = slope;
1432:                }
1433:
1434:                public boolean equals(Object o) {
1435:                    if (o instanceof  BelowScoringFunction) {
1436:                        BelowScoringFunction that = (BelowScoringFunction) o;
1437:                        if (that.slope != this .slope)
1438:                            return false;
1439:                        return super .equals(o);
1440:                    }
1441:                    return false;
1442:                }
1443:
1444:                public Object clone() {
1445:                    return new BelowScoringFunction(point, slope);
1446:                }
1447:
1448:                public AspectScorePoint getBest() {
1449:                    return new AspectScorePoint(point, BEST);
1450:                }
1451:
1452:                public AspectScorePoint getMinInRange(AspectValue lowerbound,
1453:                        AspectValue upperbound) {
1454:                    AspectScorePoint asp = null;
1455:                    if (point.isBetween(lowerbound, upperbound))
1456:                        asp = new AspectScorePoint(point, BEST);
1457:                    else if (point.isGreaterThan(upperbound))
1458:                        asp = new AspectScorePoint(upperbound,
1459:                                getScore(upperbound));
1460:                    else
1461:                        asp = new AspectScorePoint(lowerbound,
1462:                                getScore(lowerbound));
1463:                    return asp;
1464:                }
1465:
1466:                public AspectScorePoint getMaxInRange(AspectValue lowerbound,
1467:                        AspectValue upperbound) {
1468:                    AspectScorePoint asp = null;
1469:                    double ubScore = getScore(upperbound);
1470:                    double lbScore = getScore(lowerbound);
1471:                    // One of the endpoints is Max
1472:                    if (lbScore > ubScore)
1473:                        asp = new AspectScorePoint(lowerbound, lbScore);
1474:                    else
1475:                        asp = new AspectScorePoint(upperbound, ubScore);
1476:                    return asp;
1477:                }
1478:
1479:                public double getScore(AspectValue value) {
1480:                    if (!(value.isGreaterThan(point))) {
1481:                        return Math.min(WORST, slope * point.minus(value));
1482:                    } else {
1483:                        return WORST;
1484:                    }
1485:                }
1486:
1487:                public Enumeration getValidRanges(AspectValue lowerbound,
1488:                        AspectValue upperbound) {
1489:                    double lbScore = getScore(lowerbound);
1490:                    double ubScore = getScore(upperbound);
1491:
1492:                    // Whole range in safe area
1493:                    if ((lbScore < WORST) && (ubScore < WORST)) {
1494:                        // return range
1495:                        AspectScorePoint p0 = new AspectScorePoint(lowerbound,
1496:                                lbScore);
1497:                        AspectScorePoint p1 = new AspectScorePoint(upperbound,
1498:                                ubScore);
1499:                        return new SingleElementEnumeration(
1500:                                new AspectScoreRange(p0, p1));
1501:                    }
1502:
1503:                    // Whole range in WORST area
1504:                    if (!point.isBetween(lowerbound, upperbound)
1505:                            && (lbScore == WORST) && (ubScore == WORST)) {
1506:                        // return empty set
1507:                        return Empty.enumeration;
1508:                    }
1509:
1510:                    AspectScorePoint p0;
1511:                    if (lbScore < WORST) {
1512:                        // lowerbound in good range
1513:                        p0 = new AspectScorePoint(lowerbound, lbScore);
1514:                    } else {
1515:                        double delta = (slope == 0.0) ? (0.0) : (1 / slope);
1516:                        AspectValue v0 = AspectValue.newAspectValue(point
1517:                                .getAspectType(), point.getValue() - delta);
1518:                        p0 = new AspectScorePoint(v0, WORST);
1519:                    }
1520:
1521:                    AspectScorePoint p1;
1522:                    if (ubScore < WORST)
1523:                        // use upperbound
1524:                        p1 = new AspectScorePoint(upperbound, ubScore);
1525:                    else
1526:                        // use point
1527:                        p1 = new AspectScorePoint(point, getScore(point));
1528:
1529:                    return new SingleElementEnumeration(new AspectScoreRange(
1530:                            p0, p1));
1531:
1532:                }
1533:
1534:                public String toString() {
1535:                    return "<Below " + point + " " + slope + ">";
1536:                }
1537:            }
1538:
1539:            public static class StepScoringFunction extends
1540:                    SinglePointScoringFunction {
1541:                double v0;
1542:                double v1;
1543:
1544:                public StepScoringFunction(AspectValue changepoint,
1545:                        double prescore, double postscore) {
1546:                    super (changepoint);
1547:                    v0 = prescore;
1548:                    v1 = postscore;
1549:                }
1550:
1551:                public boolean equals(Object o) {
1552:                    if (o instanceof  StepScoringFunction) {
1553:                        StepScoringFunction that = (StepScoringFunction) o;
1554:                        if (that.v0 != this .v0)
1555:                            return false;
1556:                        if (that.v1 != this .v1)
1557:                            return false;
1558:                        return super .equals(o);
1559:                    }
1560:                    return false;
1561:                }
1562:
1563:                public Object clone() {
1564:                    return new StepScoringFunction(point, v0, v1);
1565:                }
1566:
1567:                public double getScore(AspectValue value) {
1568:                    if (value.isLessThan(point))
1569:                        return v0;
1570:                    else
1571:                        return v1;
1572:                }
1573:
1574:                public AspectScorePoint getMinInRange(AspectValue lowerbound,
1575:                        AspectValue upperbound) {
1576:
1577:                    double lbScore = getScore(lowerbound);
1578:                    double ubScore = getScore(upperbound);
1579:
1580:                    if (lbScore < ubScore)
1581:                        return new AspectScorePoint(lowerbound, lbScore);
1582:                    return new AspectScorePoint(upperbound, ubScore);
1583:                }
1584:
1585:                public AspectScorePoint getMaxInRange(AspectValue lowerbound,
1586:                        AspectValue upperbound) {
1587:                    double lbScore = getScore(lowerbound);
1588:                    double ubScore = getScore(upperbound);
1589:                    if (lbScore > ubScore)
1590:                        return new AspectScorePoint(lowerbound, lbScore);
1591:                    return new AspectScorePoint(upperbound, ubScore);
1592:                }
1593:
1594:                /**
1595:                 * return changepoint if its score is lower,
1596:                 * otherwise return a point -x away from changepoint
1597:                 **/
1598:                public AspectScorePoint getBest() {
1599:                    // which is lower?
1600:                    double lowscore = (v0 < v1) ? v0 : v1;
1601:
1602:                    // _____
1603:                    //      |
1604:                    //      |
1605:                    //      |____
1606:                    //
1607:                    if (getScore(point) == lowscore)
1608:                        return new AspectScorePoint(point, lowscore);
1609:
1610:                    // v1 < v0, but point is at zero
1611:                    //______
1612:                    //
1613:                    //
1614:                    if (point.getValue() == 0)
1615:                        return new AspectScorePoint(point, getScore(point));
1616:
1617:                    //      ______
1618:                    //      |
1619:                    //      |
1620:                    // _____|
1621:                    // arbitrary value in the range between 0 and point
1622:                    // what if point<0 ?
1623:                    double away = 1.0;
1624:                    double pointValue = point.getValue();
1625:                    while (pointValue - away <= 0)
1626:                        away = away * 0.1;
1627:
1628:                    return new AspectScorePoint(AspectValue.newAspectValue(
1629:                            point.getAspectType(), pointValue - away), lowscore);
1630:
1631:                }
1632:
1633:                public Enumeration getValidRanges(AspectValue lowerbound,
1634:                        AspectValue upperbound) {
1635:
1636:                    double lbScore = getScore(lowerbound);
1637:                    double ubScore = getScore(upperbound);
1638:
1639:                    // Either the "bad" score is less than 1.0
1640:                    // -or-
1641:                    // The range is on the "good" side of the point
1642:                    if (((v0 < WORST) && (v1 < WORST))
1643:                            || ((lbScore < WORST) && (ubScore < WORST))) {
1644:                        // send back the whole range
1645:                        AspectScorePoint p0 = new AspectScorePoint(lowerbound,
1646:                                lbScore);
1647:                        AspectScorePoint p1 = new AspectScorePoint(upperbound,
1648:                                ubScore);
1649:                        return new SingleElementEnumeration(
1650:                                new AspectScoreRange(p0, p1));
1651:                    }
1652:
1653:                    if (point.isBetween(lowerbound, upperbound)) {
1654:                        if (v0 == WORST) {
1655:                            // return from point to upperbound
1656:                            AspectScorePoint p0 = new AspectScorePoint(point,
1657:                                    v1);
1658:                            AspectScorePoint p1 = new AspectScorePoint(
1659:                                    upperbound, v1);
1660:                            return new SingleElementEnumeration(
1661:                                    new AspectScoreRange(p0, p1));
1662:                        } else {
1663:                            // return from lowerbound to point
1664:                            AspectScorePoint p0 = new AspectScorePoint(
1665:                                    lowerbound, v0);
1666:                            AspectScorePoint p1 = new AspectScorePoint(point,
1667:                                    v1);
1668:                            return new SingleElementEnumeration(
1669:                                    new AspectScoreRange(p0, p1));
1670:                        }
1671:                    }
1672:
1673:                    // Entire range WORST
1674:                    return Empty.enumeration;
1675:                }
1676:
1677:                public String toString() {
1678:                    return "<Step " + point + " " + v0 + " " + v1 + ">";
1679:                }
1680:            }
1681:
1682:            /* A scoring function for an enumerated set of AspectScorePoints
1683:             * Ranges are ignored, since enumerations have no sense of comparison or
1684:             * continuity. All values not in enumeration give a value of WORST.
1685:             */
1686:            public static class EnumeratedScoringFunction extends
1687:                    ScoringFunction {
1688:
1689:                // Maintain list of all provided points
1690:                // NOTE : Could implement this as a hash table if lists get long
1691:                private AspectScorePoint[] my_points;
1692:
1693:                /**
1694:                 * Constructor for EnumeratedScoringFunction
1695:                 **/
1696:                public EnumeratedScoringFunction(AspectScorePoint[] points) {
1697:                    super (points[0].getAspectType());
1698:                    my_points = points;
1699:                }
1700:
1701:                public boolean equals(Object o) {
1702:                    if (o instanceof  EnumeratedScoringFunction) {
1703:                        EnumeratedScoringFunction that = (EnumeratedScoringFunction) o;
1704:                        return Arrays.equals(this .my_points, that.my_points);
1705:                    }
1706:                    return false;
1707:                }
1708:
1709:                public Object clone() {
1710:                    AspectScorePoint[] newPoints = new AspectScorePoint[my_points.length];
1711:                    for (int i = 0; i < newPoints.length; i++) {
1712:                        newPoints[i] = my_points[i];
1713:                    }
1714:                    return new EnumeratedScoringFunction(newPoints);
1715:                }
1716:
1717:                // Find aspectscore point with max/min based on flag
1718:                private AspectScorePoint findExtreme(boolean find_max) {
1719:                    AspectScorePoint current = null;
1720:                    for (int i = 0; i < my_points.length; i++) {
1721:                        if ((current == null)
1722:                                || ((find_max == false) && (current.getScore() > my_points[i]
1723:                                        .getScore()))
1724:                                || ((find_max == true) && (current.getScore() < my_points[i]
1725:                                        .getScore()))) {
1726:                            current = my_points[i];
1727:                        }
1728:                    }
1729:                    return current;
1730:                }
1731:
1732:                /**
1733:                 * getBest AspectScorePoint - iterate over all and find lowest score
1734:                 */
1735:                public AspectScorePoint getBest() {
1736:                    return findExtreme(false);
1737:                }
1738:
1739:                /**
1740:                 * Find minimum value - ignore range information
1741:                 **/
1742:                public AspectScorePoint getMinInRange(AspectValue lowerbound,
1743:                        AspectValue upperbound) {
1744:                    return findExtreme(true);
1745:                }
1746:
1747:                public AspectScorePoint getMaxInRange(AspectValue lowerbound,
1748:                        AspectValue upperbound) {
1749:                    return getBest();
1750:                }
1751:
1752:                /**
1753:                 * Enumeration of all valid ranges : in this case, all points
1754:                 * represent a discrete range in and of themselves
1755:                 **/
1756:                public Enumeration getValidRanges(AspectValue lowerbound,
1757:                        AspectValue upperbound) {
1758:                    Vector v = new Vector();
1759:                    for (int i = 0; i < my_points.length; i++) {
1760:                        v.addElement(new AspectScoreRange(my_points[i],
1761:                                my_points[i]));
1762:                    }
1763:                    return v.elements();
1764:                }
1765:
1766:                /**
1767:                 * Iterate over all points and find if there is a point for this
1768:                 * value. If not, return WORST.
1769:                 **/
1770:                public double getScore(AspectValue value) {
1771:                    for (int i = 0; i < my_points.length; i++) {
1772:                        if (my_points[i].getValue() == value.getValue()) {
1773:                            return my_points[i].getScore();
1774:                        }
1775:                    }
1776:                    return WORST;
1777:                }
1778:
1779:                public String toString() {
1780:                    return "<Enumerated " + my_points.length + ">";
1781:                }
1782:            }
1783:
1784:            public static class ConstantScoringFunction extends ScoringFunction {
1785:                double score = BEST;
1786:
1787:                public ConstantScoringFunction(double score, int aspectType) {
1788:                    super (aspectType);
1789:                    this .score = score;
1790:                }
1791:
1792:                public ConstantScoringFunction(int aspectType) {
1793:                    super (aspectType);
1794:                }
1795:
1796:                public boolean equals(Object o) {
1797:                    if (o instanceof  ConstantScoringFunction) {
1798:                        ConstantScoringFunction that = (ConstantScoringFunction) o;
1799:                        if (this .aspectType == that.aspectType) {
1800:                            return this .score == that.score;
1801:                        }
1802:                    }
1803:                    return false;
1804:                }
1805:
1806:                public Object clone() {
1807:                    return new ConstantScoringFunction(score, aspectType);
1808:                }
1809:
1810:                public AspectScorePoint getBest() {
1811:                    return newASP(0, score, aspectType);
1812:                }
1813:
1814:                public AspectScorePoint getMinInRange(AspectValue lowerbound,
1815:                        AspectValue upperbound) {
1816:                    return newASP(lowerbound.getValue(), score, aspectType);
1817:                }
1818:
1819:                public AspectScorePoint getMaxInRange(AspectValue lowerbound,
1820:                        AspectValue upperbound) {
1821:                    return newASP(upperbound.getValue(), score, aspectType);
1822:                }
1823:
1824:                public Enumeration getValidRanges(AspectValue lowerbound,
1825:                        AspectValue upperbound) {
1826:                    AspectScorePoint low = new AspectScorePoint(lowerbound,
1827:                            score);
1828:                    AspectScorePoint high = new AspectScorePoint(upperbound,
1829:                            score);
1830:                    return new SingleElementEnumeration(new AspectScoreRange(
1831:                            low, high));
1832:                }
1833:
1834:                public double getScore(AspectValue value) {
1835:                    return score;
1836:                }
1837:
1838:                public String toString() {
1839:                    return "<Constant " + score + ">";
1840:                }
1841:            }
1842:
1843:            // Test fix for bug 2536. Eventually turn this into a regression test
1844:            public static void main(String[] args) {
1845:                long p1 = Long.parseLong(args[0]);
1846:                long b = Long.parseLong(args[1]);
1847:                long p2 = Long.parseLong(args[2]);
1848:                ScoringFunction sf = createVScoringFunction(AspectValue
1849:                        .newAspectValue(AspectType.START_TIME, p1), AspectValue
1850:                        .newAspectValue(AspectType.START_TIME, b), AspectValue
1851:                        .newAspectValue(AspectType.START_TIME, p2));
1852:                for (int i = 3; i < args.length; i++) {
1853:                    long p = Long.parseLong(args[i]);
1854:                    AspectValue av = AspectValue.newAspectValue(
1855:                            AspectType.START_TIME, p);
1856:                    double score = sf.getScore(av);
1857:                    System.out.println(p + ": " + score);
1858:                }
1859:            }
1860:        }
1861:
1862:        /*
1863:         public AspectScorePoint getMinInRange(AspectValue lowerbound, AspectValue upperbound) {
1864:         }
1865:         public AspectScorePoint getMaxInRange(AspectValue lowerbound, AspectValue upperbound) {
1866:         }
1867:         public Enumeration getValidRanges(AspectValue lowerbound, AspectValue upperbound) {
1868:         }
1869:         public AspectScoreRange getDefinedRange() {
1870:         }
1871:
1872:         */
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.