001: /*
002: * <copyright>
003: *
004: * Copyright 1999-2004 Honeywell Inc
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.glm.packer;
028:
029: import java.io.Serializable;
030: import java.util.Enumeration;
031: import java.util.Vector;
032:
033: import org.cougaar.core.service.LoggingService;
034: import org.cougaar.planning.ldm.plan.AllocationResult;
035: import org.cougaar.planning.ldm.plan.AllocationResultDistributor;
036: import org.cougaar.planning.ldm.plan.AspectScorePoint;
037: import org.cougaar.planning.ldm.plan.AspectType;
038: import org.cougaar.planning.ldm.plan.AspectValue;
039: import org.cougaar.planning.ldm.plan.AuxiliaryQueryType;
040: import org.cougaar.planning.ldm.plan.Preference;
041: import org.cougaar.planning.ldm.plan.ScoringFunction;
042: import org.cougaar.planning.ldm.plan.Task;
043: import org.cougaar.planning.ldm.plan.TaskScoreTable;
044:
045: /**
046: * This class is similar to the DefaultDistributor, but allocates quantities
047: * proportionally, based on input task quantities, rather than just
048: * evenly. Code cribbed extensively from the definition of DefaultDistributor
049: * @see org.cougaar.planning.ldm.plan.AllocationResultDistributor.DefaultDistributor
050: */
051: public class ProportionalDistributor implements
052: AllocationResultDistributor, Serializable {
053: private transient LoggingService myLoggingService = null;
054: public static ProportionalDistributor DEFAULT_PROPORTIONAL_DISTRIBUTOR = new ProportionalDistributor();
055:
056: public ProportionalDistributor() {
057: }
058:
059: public void setLoggingService(LoggingService ls) {
060: myLoggingService = ls;
061: }
062:
063: public LoggingService getLoggingService() {
064: return myLoggingService;
065: }
066:
067: public TaskScoreTable calculate(Vector parents, AllocationResult ar) {
068: int l = parents.size();
069:
070: if (l == 0 || ar == null)
071: return null;
072:
073: if (!ar.isDefined(AspectType.QUANTITY)) {
074: // if there's no quantity in the Allocation result, then we
075: // can just use the Default Distributor
076: return AllocationResultDistributor.DEFAULT.calculate(
077: parents, ar);
078: } else {
079: double quantAchieved = ar.getValue(AspectType.QUANTITY);
080: AllocationResult results[] = new AllocationResult[l];
081: double quantProportions[] = new double[l];
082: // the following block serves to set the quantProportions array
083: {
084: // these variables are lexically scoped here --- just used
085: // to compute proportional share...
086: double totalRequestedQuant = 0.0;
087: double quantsRequested[] = new double[l];
088: for (int i = 0; i < l; i++) {
089: double this Quant = getTaskQuantity(((Task) parents
090: .get(i)));
091: if (this Quant == -1.0) {
092: // no quantity was requested, set to zero
093:
094: if (getLoggingService() == null) {
095: System.err
096: .println("ProportionalDistributor: attempting to allocate a proportional share of quantity to a Task which requests no quantity.");
097: } else {
098: getLoggingService()
099: .warn(
100: "ProportionalDistributor: attempting to allocate a proportional share of quantity to a Task which requests no quantity.");
101: }
102: this Quant = 0.0;
103: }
104: totalRequestedQuant += this Quant;
105: quantsRequested[i] = this Quant;
106: }
107: if (totalRequestedQuant == 0.0) {
108: // make sure we catch the boundary condition!
109: for (int i = 0; i < l; i++) {
110: quantProportions[i] = 0.0;
111: }
112: } else {
113: for (int i = 0; i < l; i++) {
114: quantProportions[i] = quantsRequested[i]
115: / totalRequestedQuant;
116: }
117: }
118: }
119:
120: // build a result for each parent task
121: for (int i = 0; i < l; i++) {
122:
123: // create a value vector and fill in the values for the
124: // defined aspects ONLY.
125: int[] types = ar.getAspectTypes();
126: double acc[] = new double[types.length];
127: for (int x = 0; x < types.length; x++) {
128: // if the aspect is COST divide evenly across parents
129: if (types[x] == AspectType.COST) {
130: acc[x] = ar.getValue(types[x]) / l;
131: } else if (types[x] == AspectType.QUANTITY) {
132: // if the aspect is QUANTITY, we'll have to divide
133: // proportionally across parents
134: acc[x] = ar.getValue(types[x])
135: * quantProportions[i];
136: } else {
137: acc[x] = ar.getValue(types[x]);
138: }
139: }
140:
141: results[i] = new AllocationResult(ar
142: .getConfidenceRating(), ar.isSuccess(), types,
143: acc);
144: // fill in the auxiliaryquery info
145: // each of the new allocationresults(for the parents)
146: // will have the SAME
147: // auxiliaryquery info that the allocationresult (of the child) has.
148: for (int aq = 0; aq < AuxiliaryQueryType.AQTYPE_COUNT; aq++) {
149: String info = ar.auxiliaryQuery(aq);
150: if (info != null) {
151: results[i].addAuxiliaryQueryInfo(aq, info);
152: }
153: }
154: }
155:
156: Task tasks[] = new Task[l];
157: parents.copyInto(tasks);
158:
159: return new TaskScoreTable(tasks, results);
160: }
161: }
162:
163: // the following cribbed from LCG/CGI
164: public double getTaskQuantity(Task task) {
165: return getTaskAspectValue(task, AspectType.QUANTITY);
166: } /* end method getTaskQuantity */
167:
168: /**
169: * @return value of the preference on the aspect of the task, or
170: * -1.0 if not defined.
171: * @param at The aspect type.
172: */
173: protected static double getTaskAspectValue(Task task, int at) {
174: //
175: // Grab the designated aspect value.
176: //
177: double value = -1.0d;
178: for (Enumeration preferences = task.getPreferences(); preferences
179: .hasMoreElements();) {
180: Preference preference = (Preference) preferences
181: .nextElement();
182: if (preference.getAspectType() == at) {
183: ScoringFunction sf = preference.getScoringFunction();
184: AspectScorePoint asp = sf.getBest();
185: AspectValue av = asp.getAspectValue();
186: value = av.getValue();
187: }
188: }
189: return (value);
190: }
191:
192: }
|