001/*
002 * Copyright (c) 2003-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: welker $'
006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 
007 * '$Revision: 24234 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030package org.kepler.sms.actors;
031
032import java.util.Iterator;
033import java.util.Vector;
034
035import org.kepler.sms.SMSServices;
036import org.kepler.sms.SemanticType;
037
038import ptolemy.actor.IOPort;
039import ptolemy.actor.TypedIOPort;
040import ptolemy.kernel.util.NamedObj;
041
042/**
043 * SIMPLE MERGE ALGORITHM:
044 * 
045 * ComputeMerge() 1. Let Matches = {} 2. Let Conflicts = {} 3. foreach A in
046 * MergeActors 4. foreach output port P of A involved in merge 5.
047 * ComputeMatches(A, P, Matches, Conflicts) 6. ComputeMappings(Matches) 7.
048 * ComputeTargetSemTypes(matches);
049 * 
050 * ComputeMatches(A, P, Matches, Conflicts) 1. Let Actors = MergeActors - {A} 2.
051 * foreach A' in Actors and !HasConflict(P, A', Conflicts) 3. foreach output
052 * port P' of A' involved in merge 4. if( semType(P) subtypeof semType(P') ) 5.
053 * if( HasMatch(P', A, Matches) ) 6. AddConflict(P, A', Matches, Conflicts) 7.
054 * else 8. AddMatch(P, P', Matches) ... here we can add a condition for
055 * conversion functions ...
056 * 
057 * ComputeMappings(Matches) 1. Let MergeSets = PartitionMatches(Matches) 2.
058 * foreach S in MergeSets 3. Let P' = CreateNewOutputPort() 4. foreach P in S 5.
059 * AddMapping(P, P') 6. foreach A in MergeActors 7. foreach otuput port P of A
060 * involved in merge 8. if( !InMatch(P, Matches) ) 9. Let P' =
061 * CreateNewOutputPort() 10. AddMapping(P, P')
062 */
063
064public class SimpleComputeMergeAlgorithm {
065
066        /**
067     *
068     */
069        public SimpleComputeMergeAlgorithm(MergeActor mergeActor) {
070                _mergeActor = mergeActor;
071        }
072
073        /**
074     *
075     */
076        public void computeMerge() {
077                Vector matches = new Vector();
078                Vector conflicts = new Vector();
079                Iterator actors = _mergeActor.getActors().iterator();
080                while (actors.hasNext()) {
081                        NamedObj a = (NamedObj) actors.next();
082                        Iterator ports = _mergeActor.getActorPorts(a).iterator();
083                        while (ports.hasNext()) {
084                                IOPort p = (IOPort) ports.next();
085                                _computeMatches(a, p, matches, conflicts);
086                        }
087                }
088
089                System.out.print("COMPUTE MATCHES: ");
090                _printMatches(matches);
091
092                _computeMappings(matches);
093                _computeTargetSemTypes(matches);
094        }
095
096        /**
097     *
098     */
099        private void _computeMatches(NamedObj a, IOPort p, Vector matches,
100                        Vector conflicts) {
101                Vector actors = new Vector();
102                Iterator iter = _mergeActor.getActors().iterator();
103                while (iter.hasNext()) {
104                        NamedObj actor = (NamedObj) iter.next();
105                        if (!actor.equals(a))
106                                actors.add(actor);
107                }
108                iter = actors.iterator();
109                while (iter.hasNext()) {
110                        NamedObj ap = (NamedObj) iter.next();
111                        if (!_hasConflict(p, ap, conflicts)) {
112                                Iterator ports = _mergeActor.getActorPorts(ap).iterator();
113                                while (ports.hasNext()) {
114                                        IOPort pp = (IOPort) ports.next();
115                                        Vector<SemanticType> p_semtypes = SMSServices.getPortSemanticTypes(p);
116                                        Vector<SemanticType> pp_semtypes = SMSServices.getPortSemanticTypes(pp);
117                                        if (SMSServices.compatible(p_semtypes, pp_semtypes)) {
118                                                System.out.println(p.getContainer().getName() + "."
119                                                                + p.getName() + " is compatible with "
120                                                                + pp.getContainer().getName() + "."
121                                                                + pp.getName());
122                                                if (_hasMatch(pp, a, matches))
123                                                        _addConflict(p, ap, matches, conflicts);
124                                                else
125                                                        _addMatch(p, pp, matches);
126                                        }
127                                        // else if(SMSServices.compatible(pp_semtypes, p_semtypes))
128                                        // {
129                                        // System.out.println(pp.getContainer().getName() + "." +
130                                        // pp.getName() +
131                                        // " is compatible with " +
132                                        // p.getContainer().getName() + "." + p.getName());
133                                        // if(_hasMatch(pp, a, matches))
134                                        // _addConflict(p, ap, matches, conflicts);
135                                        // else
136                                        // _addMatch(pp, p, matches);
137                                        // }
138                                }
139                        }
140                }
141        }
142
143        /**
144     *
145     */
146        private void _computeMappings(Vector matches) {
147                Vector mergeSets = _partitionMatches(matches);
148                Iterator iter = mergeSets.iterator();
149                while (iter.hasNext()) {
150                        Vector s = (Vector) iter.next();
151                        System.out.println("ADDING PARTITION");
152                        TypedIOPort pp = _createNewOutputPort();
153                        Iterator ports = s.iterator();
154                        while (ports.hasNext()) {
155                                IOPort p = (IOPort) ports.next();
156                                System.out.println("... ADDING PORT: "
157                                                + p.getContainer().getName() + "." + p.getName());
158                                _addMapping(p, pp);
159                        }
160                }
161                iter = _mergeActor.getActors().iterator();
162                while (iter.hasNext()) {
163                        NamedObj a = (NamedObj) iter.next();
164                        Iterator ports = _mergeActor.getActorPorts(a).iterator();
165                        while (ports.hasNext()) {
166                                IOPort p = (IOPort) ports.next();
167                                // System.out.println("CHECKING a = " + a.getName() +
168                                // " and p = " + p.getName());
169                                if (!_inMatch(p, matches)) {
170                                        TypedIOPort pp = _createNewOutputPort();
171                                        _addMapping(p, pp);
172                                }
173                        }
174                }
175        }
176
177        /**
178     *
179     */
180        private void _addMapping(IOPort p, IOPort pp) {
181                String name = _mergeActor.uniqueName("_merge");
182                String actor = p.getContainer().getName();
183                String port = p.getName();
184                String target = pp.getName();
185                try {
186                        SimpleMergeMapping m = new SimpleMergeMapping(_mergeActor, name,
187                                        actor, port, target);
188                } catch (Exception e) {
189                        e.printStackTrace();
190                }
191        }
192
193        /**
194     *
195     */
196        private boolean _inMatch(IOPort p, Vector matches) {
197                Iterator iter = matches.iterator();
198                while (iter.hasNext()) {
199                        IOPort[] match = (IOPort[]) iter.next();
200                        if (p.equals(match[0]) || p.equals(match[1]))
201                                return true;
202                }
203                return false;
204        }
205
206        /**
207     *
208     */
209        private TypedIOPort _createNewOutputPort() {
210                TypedIOPort p = null;
211                try {
212                        p = new TypedIOPort(_mergeActor, _mergeActor.uniqueName("target"),
213                                        false, true);
214                } catch (Exception e) {
215                        e.printStackTrace();
216                }
217                return p;
218        }
219
220        /**
221     *
222     */
223        private Vector _partitionMatches(Vector matches) {
224                Vector matches_copy = new Vector();
225                Iterator iter = matches.iterator();
226                while (iter.hasNext())
227                        matches_copy.add(iter.next());
228                Vector partitions = new Vector();
229                _partitionMatches(matches_copy, partitions);
230                return partitions;
231        }
232
233        /**
234     *
235     */
236        private void _partitionMatches(Vector matches, Vector partitions) {
237                if (matches.isEmpty())
238                        return;
239                IOPort[] match = (IOPort[]) matches.elementAt(0);
240                boolean found = false;
241                Iterator iter = partitions.iterator();
242                while (!found && iter.hasNext()) {
243                        Vector partition = (Vector) iter.next();
244                        if (partition.contains(match[0]) || partition.contains(match[1])) {
245                                // add both to be sure
246                                if (!partition.contains(match[0]))
247                                        partition.add(match[0]);
248                                if (!partition.contains(match[1]))
249                                        partition.add(match[1]);
250                                found = true;
251                        }
252                }
253                matches.remove(match);
254                if (!found) {
255                        Vector partition = new Vector();
256                        partition.add(match[0]);
257                        partition.add(match[1]);
258                        partitions.add(partition);
259                }
260                _partitionMatches(matches, partitions);
261        }
262
263        /**
264     *
265     */
266        private void _computeTargetSemTypes(Vector matches) {
267
268        }
269
270        /**
271     *
272     */
273        private boolean _hasConflict(IOPort p, NamedObj ap, Vector conflicts) {
274                Iterator iter = conflicts.iterator();
275                while (iter.hasNext()) {
276                        Object[] conflict = (Object[]) iter.next();
277                        if (p.equals(conflict[0]) && ap.equals(conflict[1]))
278                                return true;
279                }
280                return false;
281        }
282
283        /**
284     *
285     */
286        private boolean _hasMatch(IOPort pp, NamedObj a, Vector matches) {
287                Iterator iter = matches.iterator();
288                while (iter.hasNext()) {
289                        IOPort[] match = (IOPort[]) iter.next();
290                        if (pp.equals(match[0]) && a.equals(match[1]))
291                                return true;
292                }
293                return false;
294        }
295
296        /**
297     *
298     */
299        private void _addConflict(IOPort p, NamedObj ap, Vector matches,
300                        Vector conflicts) {
301                Object[] conflict = { p, ap };
302                if (!conflicts.contains(conflict))
303                        conflicts.add(conflict);
304                // remove all <p,pp> or <pp,p> matches
305                Iterator iter = matches.iterator();
306                while (iter.hasNext()) {
307                        IOPort[] match = (IOPort[]) iter.next();
308                        if (p.equals(match[0])) {
309                                Iterator ports = _mergeActor.getActorPorts(ap).iterator();
310                                while (ports.hasNext()) {
311                                        IOPort pp = (IOPort) ports.next();
312                                        if (pp.equals(match[1]))
313                                                matches.remove(match);
314                                }
315                        }
316                        if (p.equals(match[1])) {
317                                Iterator ports = _mergeActor.getActorPorts(ap).iterator();
318                                while (ports.hasNext()) {
319                                        IOPort pp = (IOPort) ports.next();
320                                        if (pp.equals(match[0]))
321                                                matches.remove(match);
322                                }
323                        }
324                }
325        }
326
327        /**
328     *
329     */
330        private void _addMatch(IOPort p, IOPort pp, Vector matches) {
331                IOPort[] match = { p, pp };
332                Iterator iter = matches.iterator();
333                while (iter.hasNext()) {
334                        IOPort[] m = (IOPort[]) iter.next();
335                        if (m[0].equals(p) && m[1].equals(pp))
336                                return;
337                }
338                matches.add(match);
339        }
340
341        /**
342         * Helper function for printing out a set of matches
343         */
344        private void _printMatches(Vector matches) {
345                Iterator iter = matches.iterator();
346                System.out.print("{");
347                while (iter.hasNext()) {
348                        IOPort[] match = (IOPort[]) iter.next();
349                        System.out.print("<" + match[0].getName() + ", "
350                                        + match[1].getName() + ">");
351                        if (iter.hasNext())
352                                System.out.print(", ");
353                }
354                System.out.println("}");
355        }
356
357        // //////////////////////////////////////////////////////////////////////////
358        // PRIVATE MEMBERS
359
360        private MergeActor _mergeActor;
361
362}// SimpleComputeMergeAlgorithm