annotate lib/Graph/PathGraph.pm @ 0:4816e4a8ae95 draft default tip

Uploaded
author deepakjadmin
date Wed, 20 Jan 2016 09:23:18 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
1 package Graph::PathGraph;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
2 #
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
3 # $RCSfile: PathGraph.pm,v $
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
4 # $Date: 2015/02/28 20:49:06 $
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
5 # $Revision: 1.24 $
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
6 #
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
7 # Author: Manish Sud <msud@san.rr.com>
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
8 #
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
9 # Copyright (C) 2015 Manish Sud. All rights reserved.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
10 #
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
11 # This file is part of MayaChemTools.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
12 #
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
13 # MayaChemTools is free software; you can redistribute it and/or modify it under
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
14 # the terms of the GNU Lesser General Public License as published by the Free
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
15 # Software Foundation; either version 3 of the License, or (at your option) any
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
16 # later version.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
17 #
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
18 # MayaChemTools is distributed in the hope that it will be useful, but without
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
19 # any warranty; without even the implied warranty of merchantability of fitness
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
20 # for a particular purpose. See the GNU Lesser General Public License for more
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
21 # details.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
22 #
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
23 # You should have received a copy of the GNU Lesser General Public License
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
24 # along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
25 # write to the Free Software Foundation Inc., 59 Temple Place, Suite 330,
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
26 # Boston, MA, 02111-1307, USA.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
27 #
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
28
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
29 use strict;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
30 use Carp;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
31 use Exporter;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
32 use Storable ();
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
33 use Scalar::Util ();
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
34 use Graph;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
35 use Graph::Path;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
36
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
37 use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
38
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
39 @ISA = qw(Graph Exporter);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
40 @EXPORT = qw(IsPathGraph);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
41 @EXPORT_OK = qw();
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
42
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
43 %EXPORT_TAGS = (all => [@EXPORT, @EXPORT_OK]);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
44
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
45 # Setup class variables...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
46 my($ClassName, $PathsPropertyName, $CyclicPathsPropertyName);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
47 _InitializeClass();
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
48
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
49 # Overload Perl functions...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
50 use overload '""' => 'StringifyPathGraph';
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
51
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
52 # Class constructor...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
53 sub new {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
54 my($Class, $Graph) = @_;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
55
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
56 # Initialize object...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
57 my $This = $Class->SUPER::new();
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
58 bless $This, ref($Class) || $Class;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
59 $This->_InitializePathGraph($Graph);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
60
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
61 $This->_ConvertGraphIntoPathGraph($Graph);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
62
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
63 return $This;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
64 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
65
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
66 # Initialize object data...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
67 sub _InitializePathGraph {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
68 my($This, $Graph) = @_;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
69
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
70 if (!(defined($Graph) && Graph::IsGraph($Graph))) {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
71 croak "Error: ${ClassName}->new: PathGraph object can't be instantiated without a Graph object...";
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
72 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
73
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
74 $This->{Graph} = $Graph;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
75
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
76 # Maximum time allowed for cycles detection during collapse vertex cycles detection
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
77 # methodology in seconds...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
78 $This->{MaxAllowedTime} = 30;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
79
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
80 # Starting time for cycles detection during collapse vertex cycles detection
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
81 # methodology...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
82 $This->{StartTime} = time;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
83
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
84 return $This;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
85 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
86
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
87 # Initialize class ...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
88 sub _InitializeClass {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
89 #Class name...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
90 $ClassName = __PACKAGE__;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
91
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
92 # Path edge property name...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
93 $PathsPropertyName = 'Paths';
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
94
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
95 # Cyclic path vertex property name...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
96 $CyclicPathsPropertyName = 'CyclicPaths';
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
97 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
98
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
99 # Convert graph into a path graph...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
100 #
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
101 sub _ConvertGraphIntoPathGraph {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
102 my($This, $Graph) = @_;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
103
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
104 # Copy graph vertices and edges without any associated properties data
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
105 # from Graph to This: Graph properties data is available using Graph object reference
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
106 # store in This object...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
107 #
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
108 $Graph->CopyVerticesAndEdges($This);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
109
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
110 # . Attach Path property to each edge...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
111 #
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
112 my($Index, $VertexID1, $VertexID2, $Path, @EdgesVertexIDs);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
113
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
114 @EdgesVertexIDs = ();
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
115 @EdgesVertexIDs = $This->GetEdges();
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
116 for ($Index = 0; $Index < $#EdgesVertexIDs; $Index += 2) {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
117 $VertexID1 = $EdgesVertexIDs[$Index]; $VertexID2 = $EdgesVertexIDs[$Index + 1];
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
118 $Path = new Graph::Path($VertexID1, $VertexID2);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
119 my(@Paths) = ();
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
120 push @Paths, $Path;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
121 $This->SetEdgeProperty($PathsPropertyName, \@Paths, $VertexID1, $VertexID2);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
122 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
123 return $This;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
124 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
125
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
126 # Collapse paths around a specified vertex by updating paths around the vertex
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
127 # and adding any resulting cyclic paths to vertices attached to specified vertex.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
128 #
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
129 # Notes:
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
130 # . Path object references are stored as a list attached to Paths property on edges.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
131 # Usage of list allows multiple paths attached to the egde between a pair of vertices;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
132 # Graph doesn't support multiple egdes between a pair of vertices.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
133 #
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
134 # . Cyclic path object references are stored as list on vertices as CyclicPaths graph property.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
135 # List allows multiple Loop properties attached to a vertex.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
136 #
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
137 # . For topologically complex graphs containing large number of cycles, cycles detection algorithm
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
138 # [ Ref 31 ] as implemented implemented in CollapseVertexAndCollectCyclicPathsDetectCycles
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
139 # might not be able to find all the cycles in a reasonable amount of time and is designed to
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
140 # abandon cycles detection after MaxAllowedTime. Consequently, no cycles are detected
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
141 # or assigned.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
142 #
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
143 sub CollapseVertexAndCollectCyclicPaths {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
144 my($This, $VertexID) = @_;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
145
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
146 if (!$This->HasVertex($VertexID)) {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
147 carp "Warning: ${ClassName}->CollapseVertexAndCollectCyclicPaths: Didn't collapse vertex $VertexID: Vertex $VertexID doesn't exist...";
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
148 return undef;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
149 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
150 # Collect all paths around specified VertexID by going over paths associated with its edges...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
151 my($Index, $EdgePathsRef, $EdgeVertexID1, $EdgeVertexID2, @Paths, @EdgesVertexIDs);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
152
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
153 @EdgesVertexIDs = ();
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
154 @EdgesVertexIDs = $This->GetEdges($VertexID);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
155
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
156 @Paths = ();
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
157 for ($Index = 0; $Index < $#EdgesVertexIDs; $Index += 2) {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
158 ($EdgeVertexID1, $EdgeVertexID2) = ($EdgesVertexIDs[$Index], $EdgesVertexIDs[$Index + 1]);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
159 $EdgePathsRef = $This->GetEdgeProperty($PathsPropertyName, $EdgeVertexID1, $EdgeVertexID2);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
160 push @Paths, @{$EdgePathsRef};
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
161 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
162
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
163 # Go over each pair of paths around the specified vertex, join paths and associate
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
164 # joined path to appropriate edge...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
165 my($Index1, $Index2, $Path1, $Path2, $JoinedPath, $JoinedPathStartVertexID, $JoinedPathEndVertexID, @CommonVertices);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
166
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
167 for ($Index1 = 0; $Index1 < $#Paths; $Index1 +=1 ) {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
168 $Path1 = $Paths[$Index1];
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
169
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
170 PATH2: for ($Index2 = $Index1 + 1; $Index2 <= $#Paths; $Index2 +=1 ) {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
171 $Path2 = $Paths[$Index2];
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
172
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
173 # For JoinedPath to be valid cycle, Path1 and Path2 must have exactly two vertices in common.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
174 # Otherwise, joined path contains duplicate vertices besides the terminal vertices and
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
175 # indicates a path from a different direction.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
176 #
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
177 # For paths leading to cycles, it only makes sense to join paths with only one common vertex;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
178 # otherwise, it wouldn't lead to a cycle and can be ignored.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
179 #
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
180 @CommonVertices = $Path1->GetCommonVertices($Path2);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
181 if (!(@CommonVertices <= 2 && ($CommonVertices[0] == $VertexID || $CommonVertices[1] == $VertexID))) {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
182 next PATH2;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
183 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
184
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
185 $JoinedPath = $Path1->JoinAtVertex($Path2, $VertexID);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
186 ($JoinedPathStartVertexID, $JoinedPathEndVertexID) = $JoinedPath->GetTerminalVertices();
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
187
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
188 if (!$JoinedPath->IsIndependentPath()) {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
189 next PATH2;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
190 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
191
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
192 # Decide whether to give up or keep going...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
193 if ($This->_IsTimeToGiveUpCyclesDetection()) {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
194 warn "Warning: ${ClassName}->CollapseVertexAndCollectCyclicPaths: Cycles detection algorithm [ Ref 31 ] as implemented in the current release of MayaChemTools didn't finish with in the maximum allowed time of $This->{MaxAllowedTime} seconds; Cycles detection has been abandoned...";
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
195 return undef;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
196 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
197
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
198 if ($JoinedPathStartVertexID == $JoinedPathEndVertexID) {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
199 # It's a cycle. Attach it to the graph as CylicPaths property...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
200 if ($This->HasGraphProperty($CyclicPathsPropertyName)) {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
201 my($ExistingCyclicPathsRef);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
202 $ExistingCyclicPathsRef = $This->GetGraphProperty($CyclicPathsPropertyName);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
203 push @{$ExistingCyclicPathsRef}, $JoinedPath;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
204 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
205 else {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
206 my(@NewCyclicPaths) = ();
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
207 push @NewCyclicPaths, $JoinedPath;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
208 $This->SetGraphProperty($CyclicPathsPropertyName, \@NewCyclicPaths, $JoinedPathStartVertexID);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
209 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
210 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
211 else {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
212 if ($This->HasEdge($JoinedPathStartVertexID, $JoinedPathEndVertexID)) {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
213 # Append to the list of exisiting paths property of the edge...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
214 my($ExistingPathsRef);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
215 $ExistingPathsRef = $This->GetEdgeProperty($PathsPropertyName, $JoinedPathStartVertexID, $JoinedPathEndVertexID);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
216 push @{$ExistingPathsRef}, $JoinedPath;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
217 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
218 else {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
219 # Create a new edge and associate path property...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
220 my(@NewPaths) = ();
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
221 push @NewPaths, $JoinedPath;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
222 $This->AddEdge($JoinedPathStartVertexID, $JoinedPathEndVertexID);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
223 $This->SetEdgeProperty($PathsPropertyName, \@NewPaths, $JoinedPathStartVertexID, $JoinedPathEndVertexID);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
224 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
225 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
226 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
227 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
228 $This->DeleteVertex($VertexID);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
229
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
230 return $This;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
231 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
232
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
233 # Decide whether to give up cycles detection using collapse vertex methodology...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
234 #
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
235 sub _IsTimeToGiveUpCyclesDetection {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
236 my($This) = @_;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
237
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
238 return ((time - $This->{StartTime}) > $This->{MaxAllowedTime}) ? 1 : 0;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
239 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
240
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
241 # Delete vertices with degree less than a specifed degree...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
242 #
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
243 sub DeleteVerticesWithDegreeLessThan {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
244 my($This, $Degree) = @_;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
245 my($VertexID, @VertexIDs);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
246
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
247 while (@VertexIDs = $This->GetVerticesWithDegreeLessThan($Degree)) {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
248 for $VertexID (@VertexIDs) {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
249 $This->DeleteVertex($VertexID);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
250 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
251 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
252 return $This;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
253 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
254
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
255 # Get paths associated with edges...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
256 #
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
257 sub GetPaths {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
258 my($This) = @_;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
259 my($PathsRef, @Paths, @PathsList);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
260
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
261 @Paths = (); @PathsList = ();
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
262 @PathsList = $This->GetEdgesProperty($PathsPropertyName);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
263 for $PathsRef (@PathsList) {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
264 push @Paths, @{$PathsRef};
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
265 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
266 return wantarray ? @Paths : scalar @Paths;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
267 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
268
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
269 # Get paths associated with edges which make a cylce...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
270 #
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
271 sub GetCyclicPaths {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
272 my($This) = @_;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
273 my($PathsRef, @Paths, @PathsList);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
274
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
275 @Paths = (); @PathsList = ();
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
276 @PathsList = $This->GetGraphProperty($CyclicPathsPropertyName);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
277 PATHS: for $PathsRef (@PathsList) {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
278 if (!(defined($PathsRef) && @{$PathsRef})) {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
279 next PATHS;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
280 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
281 push @Paths, @{$PathsRef};
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
282 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
283 return wantarray ? @Paths : scalar @Paths;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
284 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
285
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
286 # Is it a path graph object?
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
287 sub IsPathGraph ($) {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
288 my($Object) = @_;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
289
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
290 return _IsPathGraph($Object);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
291 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
292
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
293 # Return a string containg data for PathGraph object...
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
294 sub StringifyPathGraph {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
295 my($This) = @_;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
296 my($PathGraphString);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
297
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
298 $PathGraphString = 'PathGraph:' . $This->StringifyVerticesAndEdges() . '; ' . $This->StringifyProperties();
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
299
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
300 return $PathGraphString;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
301 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
302
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
303 # Is it a PathGraph object?
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
304 sub _IsPathGraph {
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
305 my($Object) = @_;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
306
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
307 return (Scalar::Util::blessed($Object) && $Object->isa($ClassName)) ? 1 : 0;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
308 }
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
309
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
310 1;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
311
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
312 __END__
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
313
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
314 =head1 NAME
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
315
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
316 PathGraph
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
317
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
318 =head1 SYNOPSIS
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
319
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
320 use Graph::PathGraph;
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
321
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
322 use Graph::PathGraph qw(:all);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
323
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
324 =head1 DESCRIPTION
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
325
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
326 B<PathGraph> class provides the following methods:
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
327
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
328 new, CollapseVertexAndCollectCyclicPaths, DeleteVerticesWithDegreeLessThan,
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
329 GetCyclicPaths, GetPaths, IsPathGraph, StringifyPathGraph
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
330
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
331 B<PathGraph> class is derived from I<Graph> class.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
332
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
333 =head2 METHODS
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
334
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
335 =over 4
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
336
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
337 =item B<new>
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
338
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
339 $NewPathGraph = new Graph::PathGraph($Graph);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
340
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
341 Using specified I<Graph>, B<new> method creates a new B<PathGraph> object and returns
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
342 newly created B<PathGraph> object.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
343
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
344 I<Graph> is converted into a B<PathGraph> by copying all its vertices and edges without any
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
345 associated properties data and associating a I<Path> object to each edge containing edge
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
346 vertex IDs as intial path.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
347
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
348 =item B<CollapseVertexAndCollectCyclicPaths>
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
349
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
350 $PathGraph->CollapseVertexAndCollectCyclicPaths($VertexID);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
351
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
352 Collapses paths around a I<VertexID> by updating paths around the vertex [Ref 31] and associating any
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
353 resulting cyclic paths to graph as B<CyclicPaths> property name. And returns I<PathGraph>.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
354
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
355 =item B<DeleteVerticesWithDegreeLessThan>
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
356
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
357 $Return = $PathGraph->DeleteVerticesWithDegreeLessThan($Degree);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
358
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
359 Deletes vertices with degree less than I<Degree> from I<PathGraph> and returns I<PathGraph>.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
360
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
361 =item B<GetCyclicPaths>
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
362
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
363 @CyclicPaths = $PathGraph->GetCyclicPaths();
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
364 $NumOfPaths = $PathGraph->GetCyclicPaths();
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
365
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
366 Returns an array of cyclic I<Paths> associated with edges in I<PathGraph>. In scalar context, number
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
367 of cyclic paths is returned.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
368
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
369 =item B<GetPaths>
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
370
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
371 @Paths = $PathGraph->GetPaths();
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
372 $NumOfPaths = $PathGraph->GetPaths();
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
373
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
374 Returns an array of I<Paths> associated with edges in I<PathGraph>. In scalar context, number
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
375 of paths is returned.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
376
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
377 =item B<IsPathGraph>
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
378
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
379 $Status = Graph::PathGraph::IsPathGraph($Object);
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
380
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
381 Returns 1 or 0 based on whether I<Object> is a B<PathGraph> object.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
382
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
383 =item B<StringifyPathGraph>
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
384
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
385 $String = $PathGraph->StringifyPathGraph();
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
386
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
387 Returns a string containing information about traversed paths in I<PathGraph> object.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
388
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
389 =back
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
390
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
391 =head1 AUTHOR
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
392
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
393 Manish Sud <msud@san.rr.com>
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
394
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
395 =head1 SEE ALSO
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
396
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
397 Graph.pm, Path.pm
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
398
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
399 =head1 COPYRIGHT
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
400
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
401 Copyright (C) 2015 Manish Sud. All rights reserved.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
402
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
403 This file is part of MayaChemTools.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
404
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
405 MayaChemTools is free software; you can redistribute it and/or modify it under
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
406 the terms of the GNU Lesser General Public License as published by the Free
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
407 Software Foundation; either version 3 of the License, or (at your option)
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
408 any later version.
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
409
4816e4a8ae95 Uploaded
deepakjadmin
parents:
diff changeset
410 =cut