001    
002    package algo;
003    
004    import java.io.Serializable;
005    
006    /**
007     * A Path in a graph implementd as arrays of bytes. 
008     * @author Heinz Kredel.
009     */
010    public final class PathByteArray implements Path, Serializable {
011    
012        public final Graph graph;
013        public final byte[] used;   // points in the path
014        public final byte[] unused; // points not in the path
015        public final double cost;
016        public final int maxsize;
017        public final int length;
018    
019    
020    /**
021     * @param g the graph.
022     * @param u used points.
023     * @param uu unused points.
024     * @param c cost of this path.
025     */
026        public PathByteArray(Graph g, byte[] u, byte[] uu, double c) {
027            this(g, u, u.length, uu, c);
028        }
029    
030    
031    /**
032     * @param g the graph.
033     * @param u used points.
034     * @param pos position of last used point in path, e.g. length.
035     * @param uu unused points.
036     * @param c cost of this path.
037     */
038        public PathByteArray(Graph g, byte[] u, int pos, byte[] uu, double c) {
039            graph = g;
040            used = u;
041            unused = uu;
042            cost = c;
043            length = pos;
044            maxsize = graph.size();
045        }
046    
047    
048        /** Clone / copy this path.
049         * @see java.lang.Object#clone()
050         */
051        public Object clone() {
052            byte[] u = new byte[ length ]; 
053            System.arraycopy( used, 0, u, 0, length );
054            return new PathByteArray( graph, u, length, unused, cost );
055        }
056    
057    
058    /**
059     * @return cost of this path.
060     */
061        public double cost() {
062            return cost;
063        }
064    
065    
066    /**
067     * @return length of this path.
068     */
069        public int length() {
070            return length;
071        }
072    
073    
074    /**
075     * @return maxsize of this path.
076     */
077        public int maxsize() {
078            return maxsize;
079        }
080    
081    
082    /**
083     * Empty path, all n points unused.
084     * @param g the graph.
085     * @return a new empty path.
086     */
087        public static PathByteArray emptyPath(Graph g) { 
088            byte[] u  = new byte[ 0 ];
089            byte[] uu = new byte[ g.size() ];
090            for (byte i = 0; i < g.size(); i++ ){
091                uu[i] = i;
092            }
093            return new PathByteArray(g, u, uu, Double.POSITIVE_INFINITY);
094        }
095    
096    
097    /**
098     * One path. One point used and other n-1 points unused.
099     * @param g the graph.
100     * @return a new path of one point.
101     */
102        public static PathByteArray onePath(Graph g) { 
103            byte[] u  = new byte[ 1 ];
104            u[0] = (byte)0;
105            byte[] uu = new byte[ g.size()-1 ];
106            for (byte i = 0; i < g.size()-1; i++ ){
107                uu[i] = (byte)(i+1);
108            }
109            return new PathByteArray(g, u, uu, Double.POSITIVE_INFINITY);
110        }
111    
112    
113    /**
114     * Standard path from point 0 to point n-1 to 0.
115     * @param g the graph.
116     * @return a new closed path.
117     */
118        public static PathByteArray standardPath(Graph g) {
119            byte[] u  = new byte[ g.size() ];
120            byte[] uu = new byte[0];
121            double c = 0.0;
122            u[0] = (byte)0;
123            for (byte i = 1; i < g.size(); i++ ){
124                u[i] = i;
125                c += cost( g.distance(i-1,i) );
126            }
127            // u[ g.size() ] = (byte)0;
128            c += cost( g.distance(g.size()-1,0) ); //for circle
129            PathByteArray p = new PathByteArray(g, u, uu, c);
130            System.out.println("initial  = " + p);
131            return p;
132        }
133    
134    
135    /**
136     * Clone / copy this path, but allocate full length used array.
137     * @return a copy of this with maximal used array.
138     */
139        public Path copyMax() {
140            byte[] u = new byte[ maxsize ]; 
141            System.arraycopy( used, 0, u, 0, length );
142            return new PathByteArray( graph, u, length, unused, cost );
143        }
144    
145    
146    /**
147     * Get next possible path reusing used array.
148     * New path shares used array, so do not use in threads.
149     * @param pos position of last valid point in used array.
150     * @return next path.
151     */
152        public Path nextPath(int pos) {
153            //System.out.print("pos = " + pos + " this = " + this);
154            byte[] uu = new byte[ unused.length-1 ];
155            byte m = 0;
156            byte j = -1;
157            for ( byte k = 0; k < unused.length; k++ ) {
158                if ( k == pos ) { 
159                     j = unused[k];
160                } else {
161                     uu[ m ] = unused[k]; 
162                     m++;
163                }
164            }
165            // j != -1
166            used[ length ] = j;
167            // compute new cost
168            double c = 0.0;
169            if ( cost < Double.POSITIVE_INFINITY ) {
170               c = cost;
171            }
172            if ( length > 0 ) {
173               int n1 = used[ length-1 ];
174               c += cost( graph.distance(n1,j) );
175            }
176            // add circle cost
177            if ( length+1 == maxsize ) {
178               //System.out.print("#");
179               int n0 = used[ 0 ];
180               c += cost( graph.distance(j,n0) );
181            }
182            // new path shares used array, so do not use in threads
183            return new PathByteArray( graph, used, length+1, uu, c ); 
184        }
185    
186    
187     /**
188      * Get array of next possible paths.
189      * @return all possible path starting with this.
190      */
191        public Path[] nextPaths() {
192            PathByteArray[] pr = new PathByteArray[ unused.length ];
193            for ( byte i = 0; i < unused.length; i++ ) {
194                byte[] uu = new byte[ unused.length-1 ];
195                byte m = 0;
196                byte j = -1;
197                for ( byte k = 0; k < unused.length; k++ ) {
198                    if ( k == i ) { 
199                        j = unused[k];
200                    } else {
201                        uu[ m ] = unused[k]; m++;
202                    }
203                }
204                // j != -1
205                byte[] u = new byte[ used.length+1 ];
206                System.arraycopy( used, 0, u, 0, used.length );
207                u[ used.length ] = j;
208                // compute new cost
209                double c = 0.0;
210                if ( cost < Double.POSITIVE_INFINITY ) {
211                   c = cost;
212                }
213                if ( length > 0 ) {
214                   int l = used[ length-1 ];
215                   int k = j;
216                   c += cost( graph.distance(l,k) );
217                }
218                // add circle cost
219                if ( length+1 == maxsize ) {
220                    //System.out.print("#");
221                   int n = used[ 0 ];
222                   int k = j;
223                   c += cost( graph.distance(k,n) );
224                }
225                pr[i] = new PathByteArray( graph, u, uu, c ); 
226            }
227            return pr;
228        }
229    
230    
231        /* (non-Javadoc)
232         * @see java.lang.Object#toString()
233         */
234        public String toString() {
235            StringBuffer s = new StringBuffer();
236            s.append("[ ");
237            for ( int i = 0; i < length; i++ ) {
238                s.append( used[i] );
239                if ( i+1 < length ) {
240                   s.append(",");
241                }
242            }
243            s.append(" | cost="+cost);
244            if ( unused.length > 0 ) {
245               s.append(" | ");
246               for ( int i = 0; i < unused.length; i++ ) {
247                   s.append( unused[i] );
248                   if ( i+1 < unused.length ) {
249                      s.append(",");
250                   }
251               }
252            }
253            s.append(" ]");
254            return s.toString();
255        }
256    
257    
258    /**
259     * Dummy function. 
260     * Used to increase computing load or to define different traveling costs.
261     * @param c actual cost.
262     * @return new cost (most likely equal to c).
263     */
264        protected static double cost(double c) {
265            if ( c >= 0.0 ) {
266                return c;
267            }
268            double r = Math.log( c );
269            for (int i = 0; i < 100; i++ ) {
270                r *= c;
271            }
272            r = r/2.0;
273            for (int i = 0; i < 100; i++ ) {
274                r /= c;
275            }
276            r = r/2.0;
277            return Math.exp( r );
278        }
279    
280    }