001: /*
002: * <copyright>
003: *
004: * Copyright 1997-2004 BBNT Solutions, LLC
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.mlm.plugin.strategictransport;
028:
029: // Simple scheduler to generate multileg expansions for transporation tasks
030: // To be used as a TOPS stub in conjunction with GSS for AIR, GROUND, SEA
031:
032: import java.util.Date;
033: import java.util.Enumeration;
034: import java.util.Vector;
035:
036: import org.cougaar.core.blackboard.IncrementalSubscription;
037: import org.cougaar.glm.ldm.Constants;
038: import org.cougaar.glm.ldm.asset.Person;
039: import org.cougaar.glm.ldm.plan.GeolocLocation;
040: import org.cougaar.glm.ldm.plan.GeolocLocationImpl;
041: import org.cougaar.glm.ldm.plan.NewGeolocLocation;
042: import org.cougaar.planning.ldm.asset.AggregateAsset;
043: import org.cougaar.planning.ldm.asset.Asset;
044: import org.cougaar.planning.ldm.measure.Latitude;
045: import org.cougaar.planning.ldm.measure.Longitude;
046: import org.cougaar.planning.ldm.plan.AllocationResult;
047: import org.cougaar.planning.ldm.plan.AspectType;
048: import org.cougaar.planning.ldm.plan.AspectValue;
049: import org.cougaar.planning.ldm.plan.Expansion;
050: import org.cougaar.planning.ldm.plan.Location;
051: import org.cougaar.planning.ldm.plan.NewPrepositionalPhrase;
052: import org.cougaar.planning.ldm.plan.NewTask;
053: import org.cougaar.planning.ldm.plan.NewWorkflow;
054: import org.cougaar.planning.ldm.plan.PlanElement;
055: import org.cougaar.planning.ldm.plan.Preference;
056: import org.cougaar.planning.ldm.plan.PrepositionalPhrase;
057: import org.cougaar.planning.ldm.plan.ScoringFunction;
058: import org.cougaar.planning.ldm.plan.Task;
059: import org.cougaar.planning.ldm.plan.Verb;
060: import org.cougaar.util.UnaryPredicate;
061:
062: public class SimpleMultilegExpanderPlugin extends
063: org.cougaar.planning.plugin.legacy.SimplePlugin {
064:
065: // Subscription for all 'Transport' tasks
066: private IncrementalSubscription allTransportTasks;
067: private UnaryPredicate allTransportTasksPredicate = new UnaryPredicate() {
068: public boolean execute(Object o) {
069: return (o instanceof Task)
070: && (((Task) o).getVerb()
071: .equals(Constants.Verb.Transport));
072: }
073: };
074:
075: // Subscription for all 'Transport' expansions
076: private IncrementalSubscription allTransportExpansions;
077: private UnaryPredicate allTransportExpansionsPredicate = new UnaryPredicate() {
078: public boolean execute(Object o) {
079: return (o instanceof Expansion)
080: && (((Expansion) o).getTask().getVerb()
081: .equals(Constants.Verb.Transport));
082: }
083: };
084:
085: public void setupSubscriptions() {
086: // Subscribe to all 'Transport' tasks
087: allTransportTasks = (IncrementalSubscription) subscribe(allTransportTasksPredicate);
088:
089: // Subscribe to all 'Transport' expansions
090: allTransportExpansions = (IncrementalSubscription) subscribe(allTransportExpansionsPredicate);
091: }
092:
093: public void execute() {
094: //Handle new transport tasks
095: for (Enumeration t_added = allTransportTasks.getAddedList(); t_added
096: .hasMoreElements();) {
097: Task task = (Task) t_added.nextElement();
098: handleTask(task);
099: }
100:
101: // Handle modified transport tasks by unallocating them and reallocating them
102: for (Enumeration t_changed = allTransportTasks.getChangedList(); t_changed
103: .hasMoreElements();) {
104: Task task = (Task) t_changed.nextElement();
105: reHandleTask(task);
106: }
107:
108: // Copy reported results to expected results on expansions
109: for (Enumeration e_changed = allTransportExpansions
110: .getChangedList(); e_changed.hasMoreElements();) {
111: Expansion exp = (Expansion) e_changed.nextElement();
112: exp.setEstimatedResult(exp.getReportedResult());
113: }
114:
115: }
116:
117: // Generate multi-leg schedule for task, storing schedule information
118: protected void handleTask(Task task) {
119: AllocationResult estAR = null;
120: NewWorkflow new_wf = theLDMF.newWorkflow();
121: new_wf.setParentTask(task);
122:
123: // Hard code some POD/POD locations/duration for Sea travel
124: long travel_days = 16l;
125: GeolocLocation POE = createGeolocLocation("UZXJ", 32.0836,
126: -81.1167);
127: GeolocLocation POD = createGeolocLocation("LWEV", 27, 49.6667);
128: String mode_verb = "TransportBySea";
129:
130: // If we're going by air (passengers), then use different locations/duration
131: if (goesByAirMode(task.getDirectObject())) {
132: mode_verb = "TransportByAir";
133: POE = createGeolocLocation("LEXG", 32.0097, -81.1461);
134: POD = createGeolocLocation("FFTJ", 26.26389, 50.15833);
135: travel_days = 3l;
136: }
137:
138: double to_date_double = task.getPreference(AspectType.END_TIME)
139: .getScoringFunction().getBest().getValue();
140: Date to_date = new Date((long) to_date_double);
141: Date from_date = new Date(to_date.getTime()
142: - (travel_days * ONE_DAY));
143: Location from_loc = (Location) task.getPrepositionalPhrase(
144: Constants.Preposition.FROM).getIndirectObject();
145: Location to_loc = (Location) task.getPrepositionalPhrase(
146: Constants.Preposition.TO).getIndirectObject();
147:
148: // Assume one day for ground transportation on either side
149: Date poe_date = new Date(from_date.getTime() + ONE_DAY);
150: Date pod_date = new Date(to_date.getTime() - ONE_DAY);
151:
152: // GROUND leg FORT TO POE
153: Task leg1 = createSubTask(task, "TransportByGround", from_loc,
154: POE, from_date, poe_date);
155: new_wf.addTask(leg1);
156: ((NewTask) leg1).setWorkflow(new_wf);
157:
158: // SEA/AIR leg POE TO POD
159: Task leg2 = createSubTask(task, mode_verb, POE, POD, poe_date,
160: pod_date);
161: new_wf.addTask(leg2);
162: ((NewTask) leg2).setWorkflow(new_wf);
163:
164: // GROUND leg POD to TAA
165: Task leg3 = createSubTask(task, "TransportByGround", POD,
166: to_loc, pod_date, to_date);
167: new_wf.addTask(leg3);
168: ((NewTask) leg3).setWorkflow(new_wf);
169:
170: Expansion new_exp = theLDMF.createExpansion(task.getPlan(),
171: task, new_wf, estAR);
172:
173: publishAdd(leg1);
174: publishAdd(leg2);
175: publishAdd(leg3);
176: publishAdd(new_wf);
177: publishAdd(new_exp);
178: System.out.println("Publishing expansion (3 legs) of task : "
179: + task);
180:
181: }
182:
183: // Remove task from any expansion PE and re-handle
184: protected void reHandleTask(Task task) {
185: PlanElement plan_element = task.getPlanElement();
186: if (plan_element != null) {
187: publishRemove(plan_element);
188: }
189: System.out.println("Rescheduling changed task : " + task);
190: handleTask(task);
191: }
192:
193: // Create a subtask for given parent and verb, start/end locations and dates
194: // Copy other information from parent task
195: protected Task createSubTask(Task parent, String verb,
196: Location from_loc, Location to_loc, Date earliest_start,
197: Date latest_end) {
198: // Set up a new task
199: NewTask new_task = theLDMF.newTask();
200:
201: // Set up parent relationship of subtask
202: new_task.setParentTask(parent);
203:
204: // Set up Direct object for task from parent
205: new_task.setDirectObject(parent.getDirectObject());
206:
207: // Set up prepositions for task
208: Vector prepositions = new Vector();
209:
210: // Set up the FROM and TO Prepositional Phrases
211: NewPrepositionalPhrase npp = theLDMF.newPrepositionalPhrase();
212: npp.setPreposition(Constants.Preposition.FROM);
213: npp.setIndirectObject(from_loc);
214: prepositions.add(npp);
215:
216: npp = theLDMF.newPrepositionalPhrase();
217: npp.setPreposition(Constants.Preposition.TO);
218: npp.setIndirectObject(to_loc);
219: prepositions.add(npp);
220:
221: // Copy all prepositions that aren't FROM and TO from the parent task
222: for (Enumeration preps = parent.getPrepositionalPhrases(); preps
223: .hasMoreElements();) {
224: PrepositionalPhrase pp = (PrepositionalPhrase) preps
225: .nextElement();
226: if ((!pp.getPreposition().equals(Constants.Preposition.TO))
227: && (!pp.getPreposition().equals(
228: Constants.Preposition.FROM))) {
229: prepositions.add(pp);
230: }
231: }
232:
233: new_task.setPrepositionalPhrases(prepositions.elements());
234:
235: // Set the verb as given
236: new_task.setVerb(Verb.get(verb));
237:
238: // Set the plan for the task
239: new_task.setPlan(parent.getPlan());
240:
241: // Establish preferences for task
242: Vector preferences = new Vector();
243:
244: // Set up START_TIME preference
245: ScoringFunction start_scorefcn = ScoringFunction
246: .createNearOrAbove(AspectValue.newAspectValue(
247: AspectType.START_TIME, (double) earliest_start
248: .getTime()), 0.0d);
249:
250: Preference start_pref = theLDMF.newPreference(
251: AspectType.START_TIME, start_scorefcn);
252: preferences.addElement(start_pref);
253:
254: // Set up preference for END_TIME
255: ScoringFunction end_scorefcn = ScoringFunction
256: .createStrictlyBetweenWithBestValues(
257: AspectValue
258: .newAspectValue(
259: AspectType.END_TIME,
260: (double) (latest_end.getTime() - (0l * ONE_DAY))),
261: AspectValue
262: .newAspectValue(
263: AspectType.END_TIME,
264: (double) (latest_end.getTime() + (2l * ONE_DAY))),
265: AspectValue
266: .newAspectValue(
267: AspectType.END_TIME,
268: (double) (latest_end.getTime() + (7l * ONE_DAY))));
269:
270: Preference end_pref = theLDMF.newPreference(
271: AspectType.END_TIME, end_scorefcn);
272: preferences.addElement(end_pref);
273:
274: // Copy all preferences that aren't START_TIME and END_TIME
275: for (Enumeration prefs = parent.getPreferences(); prefs
276: .hasMoreElements();) {
277: Preference pref = (Preference) prefs.nextElement();
278: if ((pref.getAspectType() != AspectType.START_TIME)
279: && (pref.getAspectType() != AspectType.END_TIME)) {
280: preferences.addElement(pref);
281: }
282: }
283:
284: new_task.setPreferences(preferences.elements());
285:
286: return new_task;
287: }
288:
289: // Create a simple geoloc code for a code and lat/logn
290: protected GeolocLocation createGeolocLocation(String code,
291: double latitude, double longitude) {
292: NewGeolocLocation loc = new GeolocLocationImpl();
293: loc.setGeolocCode(code);
294: loc.setLatitude(Latitude.newLatitude(latitude));
295: loc.setLongitude(Longitude.newLongitude(longitude));
296: return loc;
297: }
298:
299: // People go by air, all others go by sea...
300: private boolean goesByAirMode(Asset asset) {
301: if (asset instanceof AggregateAsset) {
302: return goesByAirMode(((AggregateAsset) asset).getAsset());
303: } else
304: return (asset instanceof Person);
305: }
306:
307: // Constants
308:
309: private final static long ONE_DAY = 86400000;
310:
311: }
|