├── python-graph
├── tests
│ ├── __init__.py
│ ├── test_data.py
│ ├── testlib.py
│ ├── testrunner.py
│ ├── unittests-critical.py
│ ├── unittests-sorting.py
│ ├── unittests-heuristics.py
│ ├── unittests-cycles.py
│ ├── unittests-pagerank.py
│ ├── unittests-readwrite.py
│ ├── unittests-searching.py
│ └── unittests-filters.py
├── dot
│ ├── python_graph_dot.egg-info
│ │ ├── dependency_links.txt
│ │ ├── namespace_packages.txt
│ │ ├── requires.txt
│ │ ├── top_level.txt
│ │ ├── SOURCES.txt
│ │ └── PKG-INFO
│ ├── pygraph
│ │ ├── __init__.py
│ │ ├── readwrite
│ │ │ └── __init__.py
│ │ └── __init__.pyc
│ ├── build
│ │ └── lib.linux-i686-2.6
│ │ │ └── pygraph
│ │ │ ├── __init__.py
│ │ │ └── readwrite
│ │ │ └── __init__.py
│ ├── distribute_setup.pyc
│ ├── distribute-0.6.24.tar.gz
│ ├── distribute-0.6.24-py2.6.egg
│ ├── dist
│ │ └── python_graph_dot-1.8.2-py2.6.egg
│ └── setup.py
├── core
│ ├── python_graph_core.egg-info
│ │ ├── dependency_links.txt
│ │ ├── namespace_packages.txt
│ │ ├── top_level.txt
│ │ ├── PKG-INFO
│ │ └── SOURCES.txt
│ ├── distribute_setup.pyc
│ ├── pygraph
│ │ ├── __init__.pyc
│ │ ├── classes
│ │ │ ├── __init__.py
│ │ │ └── exceptions.py
│ │ ├── algorithms
│ │ │ ├── filters
│ │ │ │ ├── __init__.py
│ │ │ │ ├── null.py
│ │ │ │ ├── find.py
│ │ │ │ └── radius.py
│ │ │ ├── __init__.py
│ │ │ ├── heuristics
│ │ │ │ ├── __init__.py
│ │ │ │ ├── chow.py
│ │ │ │ └── euclidean.py
│ │ │ ├── sorting.py
│ │ │ ├── traversal.py
│ │ │ ├── pagerank.py
│ │ │ ├── utils.py
│ │ │ ├── cycles.py
│ │ │ ├── generators.py
│ │ │ ├── searching.py
│ │ │ └── critical.py
│ │ ├── readwrite
│ │ │ └── __init__.py
│ │ ├── mixins
│ │ │ ├── __init__.py
│ │ │ └── basegraph.py
│ │ └── __init__.py
│ ├── distribute-0.6.24.tar.gz
│ ├── distribute-0.6.24-py2.6.egg
│ ├── dist
│ │ └── python_graph_core-1.8.2-py2.6.egg
│ ├── setup.py
│ └── build
│ │ └── lib.linux-i686-2.6
│ │ └── pygraph
│ │ ├── classes
│ │ ├── __init__.py
│ │ └── exceptions.py
│ │ ├── algorithms
│ │ ├── filters
│ │ │ ├── __init__.py
│ │ │ ├── null.py
│ │ │ ├── find.py
│ │ │ └── radius.py
│ │ ├── __init__.py
│ │ ├── heuristics
│ │ │ ├── __init__.py
│ │ │ ├── chow.py
│ │ │ └── euclidean.py
│ │ ├── sorting.py
│ │ ├── traversal.py
│ │ ├── pagerank.py
│ │ ├── utils.py
│ │ ├── cycles.py
│ │ ├── generators.py
│ │ └── searching.py
│ │ ├── readwrite
│ │ └── __init__.py
│ │ ├── mixins
│ │ ├── __init__.py
│ │ └── basegraph.py
│ │ └── __init__.py
├── .DS_Store
├── misc
│ ├── logo.png
│ └── logo.txt
├── COPYING
├── Makefile
└── README
├── src
├── wcbg.png
├── cluster.png
├── hotpath.png
├── malware1.png
├── malware2.png
├── wcbg.dot
├── hotpath.dot
├── ismalware.py
├── malware1.xml
├── mincs.py
├── malware2.xml
├── mcs.py
└── wcbg.py
├── README.md
└── malwaresamples
└── Test
├── mal3.xml
├── mal4.xml
├── mal1.xml
└── mal2.xml
/python-graph/tests/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/python-graph/dot/python_graph_dot.egg-info/dependency_links.txt:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/python-graph/core/python_graph_core.egg-info/dependency_links.txt:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/python-graph/dot/python_graph_dot.egg-info/namespace_packages.txt:
--------------------------------------------------------------------------------
1 | pygraph
2 |
--------------------------------------------------------------------------------
/python-graph/core/python_graph_core.egg-info/namespace_packages.txt:
--------------------------------------------------------------------------------
1 | pygraph
2 |
--------------------------------------------------------------------------------
/python-graph/dot/python_graph_dot.egg-info/requires.txt:
--------------------------------------------------------------------------------
1 | python-graph-core==1.8.2
2 | pydot
--------------------------------------------------------------------------------
/python-graph/dot/python_graph_dot.egg-info/top_level.txt:
--------------------------------------------------------------------------------
1 | pygraph
2 | pygraph/readwrite
3 |
--------------------------------------------------------------------------------
/src/wcbg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahulp0491/Malware-Classifier/HEAD/src/wcbg.png
--------------------------------------------------------------------------------
/python-graph/dot/pygraph/__init__.py:
--------------------------------------------------------------------------------
1 | __import__('pkg_resources').declare_namespace(__name__)
2 |
--------------------------------------------------------------------------------
/src/cluster.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahulp0491/Malware-Classifier/HEAD/src/cluster.png
--------------------------------------------------------------------------------
/src/hotpath.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahulp0491/Malware-Classifier/HEAD/src/hotpath.png
--------------------------------------------------------------------------------
/src/malware1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahulp0491/Malware-Classifier/HEAD/src/malware1.png
--------------------------------------------------------------------------------
/src/malware2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahulp0491/Malware-Classifier/HEAD/src/malware2.png
--------------------------------------------------------------------------------
/python-graph/dot/pygraph/readwrite/__init__.py:
--------------------------------------------------------------------------------
1 | __import__('pkg_resources').declare_namespace(__name__)
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Malware-Classifier
2 | ==================
3 |
4 | Malware Classification using Graph Clustering
--------------------------------------------------------------------------------
/python-graph/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahulp0491/Malware-Classifier/HEAD/python-graph/.DS_Store
--------------------------------------------------------------------------------
/python-graph/misc/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahulp0491/Malware-Classifier/HEAD/python-graph/misc/logo.png
--------------------------------------------------------------------------------
/python-graph/dot/build/lib.linux-i686-2.6/pygraph/__init__.py:
--------------------------------------------------------------------------------
1 | __import__('pkg_resources').declare_namespace(__name__)
2 |
--------------------------------------------------------------------------------
/python-graph/dot/build/lib.linux-i686-2.6/pygraph/readwrite/__init__.py:
--------------------------------------------------------------------------------
1 | __import__('pkg_resources').declare_namespace(__name__)
--------------------------------------------------------------------------------
/python-graph/core/distribute_setup.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahulp0491/Malware-Classifier/HEAD/python-graph/core/distribute_setup.pyc
--------------------------------------------------------------------------------
/python-graph/core/pygraph/__init__.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahulp0491/Malware-Classifier/HEAD/python-graph/core/pygraph/__init__.pyc
--------------------------------------------------------------------------------
/python-graph/dot/distribute_setup.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahulp0491/Malware-Classifier/HEAD/python-graph/dot/distribute_setup.pyc
--------------------------------------------------------------------------------
/python-graph/dot/pygraph/__init__.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahulp0491/Malware-Classifier/HEAD/python-graph/dot/pygraph/__init__.pyc
--------------------------------------------------------------------------------
/python-graph/dot/distribute-0.6.24.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahulp0491/Malware-Classifier/HEAD/python-graph/dot/distribute-0.6.24.tar.gz
--------------------------------------------------------------------------------
/python-graph/core/distribute-0.6.24.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahulp0491/Malware-Classifier/HEAD/python-graph/core/distribute-0.6.24.tar.gz
--------------------------------------------------------------------------------
/python-graph/dot/distribute-0.6.24-py2.6.egg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahulp0491/Malware-Classifier/HEAD/python-graph/dot/distribute-0.6.24-py2.6.egg
--------------------------------------------------------------------------------
/python-graph/core/distribute-0.6.24-py2.6.egg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahulp0491/Malware-Classifier/HEAD/python-graph/core/distribute-0.6.24-py2.6.egg
--------------------------------------------------------------------------------
/python-graph/core/python_graph_core.egg-info/top_level.txt:
--------------------------------------------------------------------------------
1 | pygraph/classes
2 | pygraph/readwrite
3 | pygraph
4 | pygraph/mixins
5 | pygraph/algorithms
6 |
--------------------------------------------------------------------------------
/python-graph/dot/dist/python_graph_dot-1.8.2-py2.6.egg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahulp0491/Malware-Classifier/HEAD/python-graph/dot/dist/python_graph_dot-1.8.2-py2.6.egg
--------------------------------------------------------------------------------
/python-graph/core/dist/python_graph_core-1.8.2-py2.6.egg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahulp0491/Malware-Classifier/HEAD/python-graph/core/dist/python_graph_core-1.8.2-py2.6.egg
--------------------------------------------------------------------------------
/python-graph/misc/logo.txt:
--------------------------------------------------------------------------------
1 | LICENCE
2 |
3 | The image is provided under Creative Commons Attribution-Share Alike 3.0
4 | license. Check http://creativecommons.org/licenses/by-sa/3.0/ for more
5 | information.
6 |
7 | ATTRIBUTION:
8 | The artwork for the official logo of python-graph
9 | was designed by Tomaž Kovačič
10 | .
11 |
12 |
13 |
--------------------------------------------------------------------------------
/python-graph/dot/python_graph_dot.egg-info/SOURCES.txt:
--------------------------------------------------------------------------------
1 | setup.py
2 | pygraph/__init__.py
3 | pygraph/readwrite/__init__.py
4 | pygraph/readwrite/dot.py
5 | python_graph_dot.egg-info/PKG-INFO
6 | python_graph_dot.egg-info/SOURCES.txt
7 | python_graph_dot.egg-info/dependency_links.txt
8 | python_graph_dot.egg-info/namespace_packages.txt
9 | python_graph_dot.egg-info/requires.txt
10 | python_graph_dot.egg-info/top_level.txt
--------------------------------------------------------------------------------
/src/wcbg.dot:
--------------------------------------------------------------------------------
1 | digraph graphname {
2 | 1 [nodename=analysis];
3 | 2 [nodename=process_call];
4 | 3 [nodename=process_call];
5 | 5 [nodename=process];
6 | 6 [nodename=load_image];
7 | 7 [nodename=load_dll];
8 | 8 [nodename=load_dll];
9 | 1 -> 2 [weight="0.5", label="0.5"];
10 | 1 -> 3 [weight="0.5", label="0.5"];
11 | 2 -> 5 [weight="0.5", label="0.5"];
12 | 5 -> 6 [weight="0.5", label="0.5"];
13 | 5 -> 7 [weight="0.5", label="0.5"];
14 | 5 -> 8 [weight="0.5", label="0.5"];
15 | }
16 |
--------------------------------------------------------------------------------
/src/hotpath.dot:
--------------------------------------------------------------------------------
1 | digraph graphname {
2 | "(6, 40)" [nodename=load_image];
3 | "(5, 39)" [nodename=process];
4 | "(8, 42)" [nodename=load_dll];
5 | "(1, 36)" [nodename=analysis];
6 | "(3, 38)" [nodename=process_call];
7 | "(2, 37)" [nodename=process_call];
8 | "(7, 41)" [nodename=load_dll];
9 | "(5, 39)" -> "(6, 40)" [weight=2, label=2];
10 | "(5, 39)" -> "(7, 41)" [weight=2, label=2];
11 | "(5, 39)" -> "(8, 42)" [weight=2, label=2];
12 | "(1, 36)" -> "(2, 37)" [weight=2, label=2];
13 | "(1, 36)" -> "(3, 38)" [weight=2, label=2];
14 | "(2, 37)" -> "(5, 39)" [weight=2, label=2];
15 | }
16 |
--------------------------------------------------------------------------------
/python-graph/dot/python_graph_dot.egg-info/PKG-INFO:
--------------------------------------------------------------------------------
1 | Metadata-Version: 1.0
2 | Name: python-graph-dot
3 | Version: 1.8.2
4 | Summary: DOT support for python-graph
5 | Home-page: http://code.google.com/p/python-graph/
6 | Author: Pedro Matiello
7 | Author-email: pmatiello@gmail.com
8 | License: MIT
9 | Description: python-graph is a library for working with graphs in Python. This software provides a suitable data structure for representing graphs and a whole set of important algorithms.
10 | Keywords: python graphs hypergraphs networks library algorithms
11 | Platform: UNKNOWN
12 | Classifier: License :: OSI Approved :: MIT License
13 | Classifier: Topic :: Software Development :: Libraries :: Python Modules
14 |
--------------------------------------------------------------------------------
/python-graph/core/python_graph_core.egg-info/PKG-INFO:
--------------------------------------------------------------------------------
1 | Metadata-Version: 1.0
2 | Name: python-graph-core
3 | Version: 1.8.2
4 | Summary: A library for working with graphs in Python
5 | Home-page: http://code.google.com/p/python-graph/
6 | Author: Pedro Matiello
7 | Author-email: pmatiello@gmail.com
8 | License: MIT
9 | Description: python-graph is a library for working with graphs in Python. This software provides a suitable data structure for representing graphs and a whole set of important algorithms.
10 | Keywords: python graphs hypergraphs networks library algorithms
11 | Platform: UNKNOWN
12 | Classifier: License :: OSI Approved :: MIT License
13 | Classifier: Topic :: Software Development :: Libraries :: Python Modules
14 |
--------------------------------------------------------------------------------
/python-graph/core/pygraph/classes/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Data structure classes.
27 | """
--------------------------------------------------------------------------------
/python-graph/core/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import os
5 |
6 | try:
7 | from setuptools import setup, find_packages
8 | except ImportError as ie:
9 | import distribute_setup
10 | distribute_setup.use_setuptools()
11 | from setuptools import setup, find_packages
12 |
13 | # Startup
14 | appname = "python-graph-core"
15 | appversion = "1.8.2"
16 |
17 | setup(
18 | name = appname,
19 | version = appversion,
20 | author = "Pedro Matiello",
21 | namespace_packages = ["pygraph"],
22 | packages = ["pygraph"] + [ os.path.join("pygraph", a) for a in find_packages("pygraph") ],
23 | author_email = "pmatiello@gmail.com",
24 | description = "A library for working with graphs in Python",
25 | license = "MIT",
26 | keywords = "python graphs hypergraphs networks library algorithms",
27 | url = "http://code.google.com/p/python-graph/",
28 | classifiers = ["License :: OSI Approved :: MIT License","Topic :: Software Development :: Libraries :: Python Modules"],
29 | long_description = "python-graph is a library for working with graphs in Python. This software provides a suitable data structure for representing graphs and a whole set of important algorithms.",
30 | )
31 |
--------------------------------------------------------------------------------
/python-graph/core/build/lib.linux-i686-2.6/pygraph/classes/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Data structure classes.
27 | """
--------------------------------------------------------------------------------
/python-graph/core/python_graph_core.egg-info/SOURCES.txt:
--------------------------------------------------------------------------------
1 | setup.py
2 | pygraph/__init__.py
3 | pygraph/algorithms/__init__.py
4 | pygraph/algorithms/accessibility.py
5 | pygraph/algorithms/critical.py
6 | pygraph/algorithms/cycles.py
7 | pygraph/algorithms/generators.py
8 | pygraph/algorithms/minmax.py
9 | pygraph/algorithms/pagerank.py
10 | pygraph/algorithms/searching.py
11 | pygraph/algorithms/sorting.py
12 | pygraph/algorithms/traversal.py
13 | pygraph/algorithms/utils.py
14 | pygraph/algorithms/filters/__init__.py
15 | pygraph/algorithms/filters/find.py
16 | pygraph/algorithms/filters/null.py
17 | pygraph/algorithms/filters/radius.py
18 | pygraph/algorithms/heuristics/__init__.py
19 | pygraph/algorithms/heuristics/chow.py
20 | pygraph/algorithms/heuristics/euclidean.py
21 | pygraph/classes/__init__.py
22 | pygraph/classes/digraph.py
23 | pygraph/classes/exceptions.py
24 | pygraph/classes/graph.py
25 | pygraph/classes/hypergraph.py
26 | pygraph/mixins/__init__.py
27 | pygraph/mixins/basegraph.py
28 | pygraph/mixins/common.py
29 | pygraph/mixins/labeling.py
30 | pygraph/readwrite/__init__.py
31 | pygraph/readwrite/markup.py
32 | python_graph_core.egg-info/PKG-INFO
33 | python_graph_core.egg-info/SOURCES.txt
34 | python_graph_core.egg-info/dependency_links.txt
35 | python_graph_core.egg-info/namespace_packages.txt
36 | python_graph_core.egg-info/top_level.txt
--------------------------------------------------------------------------------
/python-graph/dot/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import os
5 |
6 |
7 | try:
8 | from setuptools import setup, find_packages
9 | except ImportError as ie:
10 | import distribute_setup
11 | distribute_setup.use_setuptools()
12 | from setuptools import setup, find_packages
13 |
14 | # Startup
15 | appname = "python-graph-dot"
16 | appversion = "1.8.2"
17 |
18 | setup(
19 | name = appname,
20 | version = appversion,
21 | namespace_packages = ["pygraph"],
22 | packages = ["pygraph"] + [ os.path.join("pygraph", a) for a in find_packages("pygraph") ],
23 | install_requires = [ 'python-graph-core==%s' % appversion, 'pydot' ],
24 | author = "Pedro Matiello",
25 | author_email = "pmatiello@gmail.com",
26 | description = "DOT support for python-graph",
27 | license = "MIT",
28 | keywords = "python graphs hypergraphs networks library algorithms",
29 | url = "http://code.google.com/p/python-graph/",
30 | classifiers = ["License :: OSI Approved :: MIT License","Topic :: Software Development :: Libraries :: Python Modules"],
31 | long_description = "python-graph is a library for working with graphs in Python. This software provides a suitable data structure for representing graphs and a whole set of important algorithms.",
32 | )
33 |
--------------------------------------------------------------------------------
/python-graph/core/pygraph/algorithms/filters/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Set of searching filters.
27 | """
28 |
29 | __import__('pkg_resources').declare_namespace(__name__)
30 |
--------------------------------------------------------------------------------
/python-graph/core/build/lib.linux-i686-2.6/pygraph/algorithms/filters/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Set of searching filters.
27 | """
28 |
29 | __import__('pkg_resources').declare_namespace(__name__)
30 |
--------------------------------------------------------------------------------
/python-graph/core/pygraph/readwrite/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Readwrite algorithms.
27 |
28 | Algorithms for reading and writing graphs.
29 | """
30 |
31 | __import__('pkg_resources').declare_namespace(__name__)
--------------------------------------------------------------------------------
/python-graph/core/build/lib.linux-i686-2.6/pygraph/readwrite/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Readwrite algorithms.
27 |
28 | Algorithms for reading and writing graphs.
29 | """
30 |
31 | __import__('pkg_resources').declare_namespace(__name__)
--------------------------------------------------------------------------------
/python-graph/core/pygraph/algorithms/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Algorithms
27 |
28 | This subpackage contains a set of modules, each one of them containing some algorithms.
29 | """
30 |
31 | __import__('pkg_resources').declare_namespace(__name__)
32 |
--------------------------------------------------------------------------------
/python-graph/core/build/lib.linux-i686-2.6/pygraph/algorithms/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Algorithms
27 |
28 | This subpackage contains a set of modules, each one of them containing some algorithms.
29 | """
30 |
31 | __import__('pkg_resources').declare_namespace(__name__)
32 |
--------------------------------------------------------------------------------
/python-graph/core/pygraph/mixins/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Mixins.
27 |
28 | Base classes used to compose the the graph classes.
29 |
30 | The classes in this namespace should not be used directly.
31 | """
32 |
33 | __import__('pkg_resources').declare_namespace(__name__)
34 |
--------------------------------------------------------------------------------
/python-graph/core/build/lib.linux-i686-2.6/pygraph/mixins/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Mixins.
27 |
28 | Base classes used to compose the the graph classes.
29 |
30 | The classes in this namespace should not be used directly.
31 | """
32 |
33 | __import__('pkg_resources').declare_namespace(__name__)
34 |
--------------------------------------------------------------------------------
/python-graph/core/pygraph/algorithms/heuristics/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | # Salim Fadhley
3 | #
4 | # Permission is hereby granted, free of charge, to any person
5 | # obtaining a copy of this software and associated documentation
6 | # files (the "Software"), to deal in the Software without
7 | # restriction, including without limitation the rights to use,
8 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | # copies of the Software, and to permit persons to whom the
10 | # Software is furnished to do so, subject to the following
11 | # conditions:
12 |
13 | # The above copyright notice and this permission notice shall be
14 | # included in all copies or substantial portions of the Software.
15 |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 | # OTHER DEALINGS IN THE SOFTWARE.
24 |
25 |
26 | """
27 | Set of search heuristics.
28 |
29 | These are to be used with the C{heuristic_search()} function.
30 | """
31 |
32 | __import__('pkg_resources').declare_namespace(__name__)
33 |
--------------------------------------------------------------------------------
/python-graph/core/build/lib.linux-i686-2.6/pygraph/algorithms/heuristics/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | # Salim Fadhley
3 | #
4 | # Permission is hereby granted, free of charge, to any person
5 | # obtaining a copy of this software and associated documentation
6 | # files (the "Software"), to deal in the Software without
7 | # restriction, including without limitation the rights to use,
8 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | # copies of the Software, and to permit persons to whom the
10 | # Software is furnished to do so, subject to the following
11 | # conditions:
12 |
13 | # The above copyright notice and this permission notice shall be
14 | # included in all copies or substantial portions of the Software.
15 |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 | # OTHER DEALINGS IN THE SOFTWARE.
24 |
25 |
26 | """
27 | Set of search heuristics.
28 |
29 | These are to be used with the C{heuristic_search()} function.
30 | """
31 |
32 | __import__('pkg_resources').declare_namespace(__name__)
33 |
--------------------------------------------------------------------------------
/python-graph/core/pygraph/mixins/basegraph.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | # Salim Fadhley
3 | #
4 | # Permission is hereby granted, free of charge, to any person
5 | # obtaining a copy of this software and associated documentation
6 | # files (the "Software"), to deal in the Software without
7 | # restriction, including without limitation the rights to use,
8 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | # copies of the Software, and to permit persons to whom the
10 | # Software is furnished to do so, subject to the following
11 | # conditions:
12 |
13 | # The above copyright notice and this permission notice shall be
14 | # included in all copies or substantial portions of the Software.
15 |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 | # OTHER DEALINGS IN THE SOFTWARE.
24 |
25 |
26 | class basegraph( object ):
27 | """
28 | An abstract class intended as a common ancestor to all graph classes. This allows the user
29 | to test isinstance(X, basegraph) to determine if the object is one of any of the python-graph
30 | main classes.
31 | """
32 |
--------------------------------------------------------------------------------
/python-graph/core/build/lib.linux-i686-2.6/pygraph/mixins/basegraph.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | # Salim Fadhley
3 | #
4 | # Permission is hereby granted, free of charge, to any person
5 | # obtaining a copy of this software and associated documentation
6 | # files (the "Software"), to deal in the Software without
7 | # restriction, including without limitation the rights to use,
8 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | # copies of the Software, and to permit persons to whom the
10 | # Software is furnished to do so, subject to the following
11 | # conditions:
12 |
13 | # The above copyright notice and this permission notice shall be
14 | # included in all copies or substantial portions of the Software.
15 |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 | # OTHER DEALINGS IN THE SOFTWARE.
24 |
25 |
26 | class basegraph( object ):
27 | """
28 | An abstract class intended as a common ancestor to all graph classes. This allows the user
29 | to test isinstance(X, basegraph) to determine if the object is one of any of the python-graph
30 | main classes.
31 | """
32 |
--------------------------------------------------------------------------------
/python-graph/COPYING:
--------------------------------------------------------------------------------
1 | Copyright (c) 2007-2012 Pedro Matiello
2 | Christian Muise
3 | Eugen Zagorodniy
4 | Johannes Reinhardt
5 | Nathan Davis
6 | Paul Harrison
7 | Rhys Ulerich
8 | Roy Smith
9 | Salim Fadhley
10 | Tomaz Kovacic
11 | Zsolt Haraszti
12 |
13 | Permission is hereby granted, free of charge, to any person
14 | obtaining a copy of this software and associated documentation
15 | files (the "Software"), to deal in the Software without
16 | restriction, including without limitation the rights to use,
17 | copy, modify, merge, publish, distribute, sublicense, and/or sell
18 | copies of the Software, and to permit persons to whom the
19 | Software is furnished to do so, subject to the following
20 | conditions:
21 |
22 | The above copyright notice and this permission notice shall be
23 | included in all copies or substantial portions of the Software.
24 |
25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
27 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
29 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
30 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
31 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
32 | OTHER DEALINGS IN THE SOFTWARE.
33 |
--------------------------------------------------------------------------------
/python-graph/core/pygraph/algorithms/sorting.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2007-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Sorting algorithms.
27 |
28 | @sort: topological_sorting
29 | """
30 |
31 |
32 | # Imports
33 | from pygraph.algorithms.searching import depth_first_search
34 |
35 | # Topological sorting
36 | def topological_sorting(graph):
37 | """
38 | Topological sorting.
39 |
40 | @attention: Topological sorting is meaningful only for directed acyclic graphs.
41 |
42 | @type graph: digraph
43 | @param graph: Graph.
44 |
45 | @rtype: list
46 | @return: Topological sorting for the graph.
47 | """
48 | # The topological sorting of a DAG is equivalent to its reverse postordering.
49 | order = depth_first_search(graph)[2]
50 | order.reverse()
51 | return order
52 |
--------------------------------------------------------------------------------
/python-graph/core/build/lib.linux-i686-2.6/pygraph/algorithms/sorting.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2007-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Sorting algorithms.
27 |
28 | @sort: topological_sorting
29 | """
30 |
31 |
32 | # Imports
33 | from pygraph.algorithms.searching import depth_first_search
34 |
35 | # Topological sorting
36 | def topological_sorting(graph):
37 | """
38 | Topological sorting.
39 |
40 | @attention: Topological sorting is meaningful only for directed acyclic graphs.
41 |
42 | @type graph: digraph
43 | @param graph: Graph.
44 |
45 | @rtype: list
46 | @return: Topological sorting for the graph.
47 | """
48 | # The topological sorting of a DAG is equivalent to its reverse postordering.
49 | order = depth_first_search(graph)[2]
50 | order.reverse()
51 | return order
52 |
--------------------------------------------------------------------------------
/python-graph/tests/test_data.py:
--------------------------------------------------------------------------------
1 | """
2 | Misc functions used for testing, including the generation of test-data.
3 | """
4 |
5 | EDGES = [
6 | ("China", "Russia"),
7 | ("Afghanistan", "Iran"),
8 | ("China", "Russia"),
9 | ("China", "Mongolia"),
10 | ("Mongolia", "Russia"),
11 | ("Mongolia", "China"),
12 | ("Nepal", "China"),
13 | ("India", "Pakistan"),
14 | ("India", "Nepal"),
15 | ("Afghanistan", "Pakistan"),
16 | ("North Korea", "China"),
17 | ("Romania", "Bulgaria"),
18 | ("Romania", "Moldova"),
19 | ("Romania", "Ukraine"),
20 | ("Romania", "Hungary"),
21 | ("North Korea", "South Korea"),
22 | ("Portugal", "Spain"),
23 | ("Spain","France"),
24 | ("France","Belgium"),
25 | ("France","Germany"),
26 | ("France","Italy",),
27 | ("Belgium","Netherlands"),
28 | ("Germany","Belgium"),
29 | ("Germany","Netherlands"),
30 | ("Germany","Denmark"),
31 | ("Germany","Luxembourg"),
32 | ("Germany","Czech Republic"),
33 | ("Belgium","Luxembourg"),
34 | ("France","Luxembourg"),
35 | ("England","Wales"),
36 | ("England","Scotland"),
37 | ("England","France"),
38 | ("Scotland","Wales"),
39 | ("Scotland","Ireland"),
40 | ("England","Ireland"),
41 | ("Switzerland","Austria"),
42 | ("Switzerland","Germany"),
43 | ("Switzerland","France"),
44 | ("Switzerland","Italy"),
45 | ("Austria","Germany"),
46 | ("Austria","Italy"),
47 | ("Austria","Czech Republic"),
48 | ("Austria","Slovakia"),
49 | ("Austria","Hungary"),
50 | ("Austria","Slovenia"),
51 | ("Denmark","Germany"),
52 | ("Poland","Czech Republic"),
53 | ("Poland","Slovakia"),
54 | ("Poland","Germany"),
55 | ("Poland","Russia"),
56 | ("Poland","Ukraine"),
57 | ("Poland","Belarus"),
58 | ("Poland","Lithuania"),
59 | ("Czech Republic","Slovakia"),
60 | ("Czech Republic","Germany"),
61 | ("Slovakia","Hungary")]
62 |
63 |
64 | def nations_of_the_world( G ):
65 | """
66 | This is intended to simplify the unit-tests. Given a graph add the nations of the world to it.
67 | """
68 | for a,b in EDGES:
69 |
70 | for n in [a,b,]:
71 | if not n in G.nodes():
72 | G.add_node(n)
73 |
74 | if (not G.has_edge((a,b))):
75 | G.add_edge( (a,b) )
76 |
77 | return G
78 |
79 |
80 |
--------------------------------------------------------------------------------
/python-graph/core/pygraph/algorithms/filters/null.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Null searching filter.
27 | """
28 |
29 |
30 | class null(object):
31 | """
32 | Null search filter.
33 | """
34 |
35 | def __init__(self):
36 | """
37 | Initialize the filter.
38 | """
39 | self.graph = None
40 | self.spanning_tree = None
41 |
42 | def configure(self, graph, spanning_tree):
43 | """
44 | Configure the filter.
45 |
46 | @type graph: graph
47 | @param graph: Graph.
48 |
49 | @type spanning_tree: dictionary
50 | @param spanning_tree: Spanning tree.
51 | """
52 | self.graph = graph
53 | self.spanning_tree = spanning_tree
54 |
55 | def __call__(self, node, parent):
56 | """
57 | Decide if the given node should be included in the search process.
58 |
59 | @type node: node
60 | @param node: Given node.
61 |
62 | @type parent: node
63 | @param parent: Given node's parent in the spanning tree.
64 |
65 | @rtype: boolean
66 | @return: Whether the given node should be included in the search process.
67 | """
68 | return True
--------------------------------------------------------------------------------
/python-graph/core/build/lib.linux-i686-2.6/pygraph/algorithms/filters/null.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Null searching filter.
27 | """
28 |
29 |
30 | class null(object):
31 | """
32 | Null search filter.
33 | """
34 |
35 | def __init__(self):
36 | """
37 | Initialize the filter.
38 | """
39 | self.graph = None
40 | self.spanning_tree = None
41 |
42 | def configure(self, graph, spanning_tree):
43 | """
44 | Configure the filter.
45 |
46 | @type graph: graph
47 | @param graph: Graph.
48 |
49 | @type spanning_tree: dictionary
50 | @param spanning_tree: Spanning tree.
51 | """
52 | self.graph = graph
53 | self.spanning_tree = spanning_tree
54 |
55 | def __call__(self, node, parent):
56 | """
57 | Decide if the given node should be included in the search process.
58 |
59 | @type node: node
60 | @param node: Given node.
61 |
62 | @type parent: node
63 | @param parent: Given node's parent in the spanning tree.
64 |
65 | @rtype: boolean
66 | @return: Whether the given node should be included in the search process.
67 | """
68 | return True
--------------------------------------------------------------------------------
/python-graph/core/pygraph/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2007-2012 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | B{python-graph}
27 |
28 | A library for working with graphs in Python.
29 |
30 | @version: 1.8.2
31 |
32 | L{Data structure} classes are located at C{pygraph.classes}.
33 |
34 | L{Exception} classes are located at C{pygraph.classes.exceptions}.
35 |
36 | L{Search filters} are located at C{pygraph.algorithms.filters}.
37 |
38 | L{Heuristics} for the A* algorithm are exposed in
39 | C{pygraph.algorithms.heuristics}.
40 |
41 | A quick introductory example:
42 |
43 | >>> # Import the module and instantiate a graph object
44 | >>> from pygraph.classes.graph import graph
45 | >>> from pygraph.algorithms.searching import depth_first_search
46 | >>> gr = graph()
47 | >>> # Add nodes
48 | >>> gr.add_nodes(['X','Y','Z'])
49 | >>> gr.add_nodes(['A','B','C'])
50 | >>> # Add edges
51 | >>> gr.add_edge(('X','Y'))
52 | >>> gr.add_edge(('X','Z'))
53 | >>> gr.add_edge(('A','B'))
54 | >>> gr.add_edge(('A','C'))
55 | >>> gr.add_edge(('Y','B'))
56 | >>> # Depth first search rooted on node X
57 | >>> st, pre, post = depth_first_search(gr, root='X')
58 | >>> # Print the spanning tree
59 | >>> print st
60 | {'A': 'B', 'C': 'A', 'B': 'Y', 'Y': 'X', 'X': None, 'Z': 'X'}
61 | """
62 |
63 | __import__('pkg_resources').declare_namespace(__name__)
64 |
--------------------------------------------------------------------------------
/python-graph/core/build/lib.linux-i686-2.6/pygraph/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2007-2012 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | B{python-graph}
27 |
28 | A library for working with graphs in Python.
29 |
30 | @version: 1.8.2
31 |
32 | L{Data structure} classes are located at C{pygraph.classes}.
33 |
34 | L{Exception} classes are located at C{pygraph.classes.exceptions}.
35 |
36 | L{Search filters} are located at C{pygraph.algorithms.filters}.
37 |
38 | L{Heuristics} for the A* algorithm are exposed in
39 | C{pygraph.algorithms.heuristics}.
40 |
41 | A quick introductory example:
42 |
43 | >>> # Import the module and instantiate a graph object
44 | >>> from pygraph.classes.graph import graph
45 | >>> from pygraph.algorithms.searching import depth_first_search
46 | >>> gr = graph()
47 | >>> # Add nodes
48 | >>> gr.add_nodes(['X','Y','Z'])
49 | >>> gr.add_nodes(['A','B','C'])
50 | >>> # Add edges
51 | >>> gr.add_edge(('X','Y'))
52 | >>> gr.add_edge(('X','Z'))
53 | >>> gr.add_edge(('A','B'))
54 | >>> gr.add_edge(('A','C'))
55 | >>> gr.add_edge(('Y','B'))
56 | >>> # Depth first search rooted on node X
57 | >>> st, pre, post = depth_first_search(gr, root='X')
58 | >>> # Print the spanning tree
59 | >>> print st
60 | {'A': 'B', 'C': 'A', 'B': 'Y', 'Y': 'X', 'X': None, 'Z': 'X'}
61 | """
62 |
63 | __import__('pkg_resources').declare_namespace(__name__)
64 |
--------------------------------------------------------------------------------
/python-graph/tests/testlib.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2007-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Helper functions for unit-tests.
27 | """
28 |
29 |
30 | # Imports
31 | from pygraph.algorithms.generators import generate, generate_hypergraph
32 | from random import seed
33 | from time import time
34 | from sys import argv
35 |
36 | # Configuration
37 | random_seed = int(time())
38 | num_nodes = { 'small': 10,
39 | 'medium': 25,
40 | 'sparse': 40
41 | }
42 | num_edges = { 'small': 18,
43 | 'medium': 120,
44 | 'sparse': 200
45 | }
46 | sizes = ['small', 'medium', 'sparse']
47 | use_size = 'medium'
48 |
49 | # Init
50 | try:
51 | if (argv[0] != 'testrunner.py'):
52 | print
53 | print ("Random seed: %s" % random_seed)
54 | except:
55 | pass
56 |
57 |
58 | def new_graph(wt_range=(1, 1)):
59 | seed(random_seed)
60 | return generate(num_nodes[use_size], num_edges[use_size], directed=False, weight_range=wt_range)
61 |
62 | def new_digraph(wt_range=(1, 1)):
63 | seed(random_seed)
64 | return generate(num_nodes[use_size], num_edges[use_size], directed=True, weight_range=wt_range)
65 |
66 | def new_hypergraph():
67 | seed(random_seed)
68 | return generate_hypergraph(num_nodes[use_size], num_edges[use_size])
69 |
70 | def new_uniform_hypergraph(_r):
71 | seed(random_seed)
72 | return generate_hypergraph(num_nodes[use_size], num_edges[use_size], r = _r)
73 |
--------------------------------------------------------------------------------
/python-graph/core/pygraph/classes/exceptions.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | # Salim Fadhley
3 | #
4 | # Permission is hereby granted, free of charge, to any person
5 | # obtaining a copy of this software and associated documentation
6 | # files (the "Software"), to deal in the Software without
7 | # restriction, including without limitation the rights to use,
8 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | # copies of the Software, and to permit persons to whom the
10 | # Software is furnished to do so, subject to the following
11 | # conditions:
12 |
13 | # The above copyright notice and this permission notice shall be
14 | # included in all copies or substantial portions of the Software.
15 |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 | # OTHER DEALINGS IN THE SOFTWARE.
24 |
25 |
26 | """
27 | Exceptions.
28 | """
29 |
30 | # Graph errors
31 |
32 | class GraphError(RuntimeError):
33 | """
34 | A base-class for the various kinds of errors that occur in the the python-graph class.
35 | """
36 | pass
37 |
38 | class AdditionError(GraphError):
39 | """
40 | This error is raised when trying to add a node or edge already added to the graph or digraph.
41 | """
42 | pass
43 |
44 | class NodeUnreachable(GraphError):
45 | """
46 | Goal could not be reached from start.
47 | """
48 | def __init__(self, start, goal):
49 | msg = "Node %s could not be reached from node %s" % ( repr(goal), repr(start) )
50 | InvalidGraphType.__init__(self, msg)
51 | self.start = start
52 | self.goal = goal
53 |
54 | class InvalidGraphType(GraphError):
55 | """
56 | Invalid graph type.
57 | """
58 | pass
59 |
60 | # Algorithm errors
61 |
62 | class AlgorithmError(RuntimeError):
63 | """
64 | A base-class for the various kinds of errors that occur in the the
65 | algorithms package.
66 | """
67 | pass
68 |
69 | class NegativeWeightCycleError(AlgorithmError):
70 | """
71 | Algorithms like the Bellman-Ford algorithm can detect and raise an exception
72 | when they encounter a negative weight cycle.
73 |
74 | @see: pygraph.algorithms.shortest_path_bellman_ford
75 | """
76 | pass
77 |
--------------------------------------------------------------------------------
/python-graph/core/build/lib.linux-i686-2.6/pygraph/classes/exceptions.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | # Salim Fadhley
3 | #
4 | # Permission is hereby granted, free of charge, to any person
5 | # obtaining a copy of this software and associated documentation
6 | # files (the "Software"), to deal in the Software without
7 | # restriction, including without limitation the rights to use,
8 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | # copies of the Software, and to permit persons to whom the
10 | # Software is furnished to do so, subject to the following
11 | # conditions:
12 |
13 | # The above copyright notice and this permission notice shall be
14 | # included in all copies or substantial portions of the Software.
15 |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 | # OTHER DEALINGS IN THE SOFTWARE.
24 |
25 |
26 | """
27 | Exceptions.
28 | """
29 |
30 | # Graph errors
31 |
32 | class GraphError(RuntimeError):
33 | """
34 | A base-class for the various kinds of errors that occur in the the python-graph class.
35 | """
36 | pass
37 |
38 | class AdditionError(GraphError):
39 | """
40 | This error is raised when trying to add a node or edge already added to the graph or digraph.
41 | """
42 | pass
43 |
44 | class NodeUnreachable(GraphError):
45 | """
46 | Goal could not be reached from start.
47 | """
48 | def __init__(self, start, goal):
49 | msg = "Node %s could not be reached from node %s" % ( repr(goal), repr(start) )
50 | InvalidGraphType.__init__(self, msg)
51 | self.start = start
52 | self.goal = goal
53 |
54 | class InvalidGraphType(GraphError):
55 | """
56 | Invalid graph type.
57 | """
58 | pass
59 |
60 | # Algorithm errors
61 |
62 | class AlgorithmError(RuntimeError):
63 | """
64 | A base-class for the various kinds of errors that occur in the the
65 | algorithms package.
66 | """
67 | pass
68 |
69 | class NegativeWeightCycleError(AlgorithmError):
70 | """
71 | Algorithms like the Bellman-Ford algorithm can detect and raise an exception
72 | when they encounter a negative weight cycle.
73 |
74 | @see: pygraph.algorithms.shortest_path_bellman_ford
75 | """
76 | pass
77 |
--------------------------------------------------------------------------------
/python-graph/tests/testrunner.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2007-2009 Pedro Matiello
2 | # Salim Fadhley
3 | #
4 | # Permission is hereby granted, free of charge, to any person
5 | # obtaining a copy of this software and associated documentation
6 | # files (the "Software"), to deal in the Software without
7 | # restriction, including without limitation the rights to use,
8 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | # copies of the Software, and to permit persons to whom the
10 | # Software is furnished to do so, subject to the following
11 | # conditions:
12 |
13 | # The above copyright notice and this permission notice shall be
14 | # included in all copies or substantial portions of the Software.
15 |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 | # OTHER DEALINGS IN THE SOFTWARE.
24 |
25 | import sys
26 | sys.path.append('..')
27 | import pygraph
28 | import unittest
29 | import testlib
30 | import logging
31 | from os import listdir
32 |
33 | log = logging.getLogger(__name__)
34 |
35 | def test_modules():
36 | modlist = []
37 | for each in listdir('.'):
38 | if (each[0:9] == "unittests" and each[-3:] == ".py"):
39 | modlist.append(each[0:-3])
40 | return modlist
41 |
42 | def run_tests():
43 | for each_size in testlib.sizes:
44 | print ("Testing with %s graphs" % each_size)
45 |
46 | suite = unittest.TestSuite()
47 | testlib.use_size = each_size
48 |
49 | for each_module in test_modules():
50 | try:
51 | suite.addTests(unittest.TestLoader().loadTestsFromName(each_module))
52 | except ImportError as ie:
53 | log.exception(ie)
54 | continue
55 |
56 | tr = unittest.TextTestRunner(verbosity=2)
57 | result = tr.run(suite)
58 | del suite
59 |
60 | def main():
61 | try:
62 | rseed = sys.argv[1]
63 | testlib.random_seed = int(rseed)
64 | except:
65 | pass
66 | print ("")
67 | print ("--------------------------------------------------")
68 | print ("python-graph unit-tests")
69 | print ("Random seed: %s" % testlib.random_seed)
70 | print ("--------------------------------------------------")
71 | print ("")
72 | run_tests()
73 |
74 | if __name__ == "__main__":
75 | main()
76 |
--------------------------------------------------------------------------------
/python-graph/core/pygraph/algorithms/filters/find.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Search filter for finding a specific node.
27 | """
28 |
29 |
30 | class find(object):
31 | """
32 | Search filter for finding a specific node.
33 | """
34 |
35 | def __init__(self, target):
36 | """
37 | Initialize the filter.
38 |
39 | @type target: node
40 | @param target: Target node.
41 | """
42 | self.graph = None
43 | self.spanning_tree = None
44 | self.target = target
45 | self.done = False
46 |
47 | def configure(self, graph, spanning_tree):
48 | """
49 | Configure the filter.
50 |
51 | @type graph: graph
52 | @param graph: Graph.
53 |
54 | @type spanning_tree: dictionary
55 | @param spanning_tree: Spanning tree.
56 | """
57 | self.graph = graph
58 | self.spanning_tree = spanning_tree
59 |
60 | def __call__(self, node, parent):
61 | """
62 | Decide if the given node should be included in the search process.
63 |
64 | @type node: node
65 | @param node: Given node.
66 |
67 | @type parent: node
68 | @param parent: Given node's parent in the spanning tree.
69 |
70 | @rtype: boolean
71 | @return: Whether the given node should be included in the search process.
72 | """
73 | if (not self.done):
74 | if (node == self.target):
75 | self.done = True
76 | return True
77 | else:
78 | return False
--------------------------------------------------------------------------------
/python-graph/core/pygraph/algorithms/traversal.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Traversal algorithms.
27 |
28 | @sort: traversal
29 | """
30 |
31 |
32 | # Minimal spanning tree
33 |
34 | def traversal(graph, node, order):
35 | """
36 | Graph traversal iterator.
37 |
38 | @type graph: graph, digraph
39 | @param graph: Graph.
40 |
41 | @type node: node
42 | @param node: Node.
43 |
44 | @type order: string
45 | @param order: traversal ordering. Possible values are:
46 | 2. 'pre' - Preordering (default)
47 | 1. 'post' - Postordering
48 |
49 | @rtype: iterator
50 | @return: Traversal iterator.
51 | """
52 | visited = {}
53 | if (order == 'pre'):
54 | pre = 1
55 | post = 0
56 | elif (order == 'post'):
57 | pre = 0
58 | post = 1
59 |
60 | for each in _dfs(graph, visited, node, pre, post):
61 | yield each
62 |
63 |
64 | def _dfs(graph, visited, node, pre, post):
65 | """
66 | Depth-first search subfunction for traversals.
67 |
68 | @type graph: graph, digraph
69 | @param graph: Graph.
70 |
71 | @type visited: dictionary
72 | @param visited: List of nodes (visited nodes are marked non-zero).
73 |
74 | @type node: node
75 | @param node: Node to be explored by DFS.
76 | """
77 | visited[node] = 1
78 | if (pre): yield node
79 | # Explore recursively the connected component
80 | for each in graph[node]:
81 | if (each not in visited):
82 | for other in _dfs(graph, visited, each, pre, post):
83 | yield other
84 | if (post): yield node
85 |
--------------------------------------------------------------------------------
/python-graph/core/build/lib.linux-i686-2.6/pygraph/algorithms/filters/find.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Search filter for finding a specific node.
27 | """
28 |
29 |
30 | class find(object):
31 | """
32 | Search filter for finding a specific node.
33 | """
34 |
35 | def __init__(self, target):
36 | """
37 | Initialize the filter.
38 |
39 | @type target: node
40 | @param target: Target node.
41 | """
42 | self.graph = None
43 | self.spanning_tree = None
44 | self.target = target
45 | self.done = False
46 |
47 | def configure(self, graph, spanning_tree):
48 | """
49 | Configure the filter.
50 |
51 | @type graph: graph
52 | @param graph: Graph.
53 |
54 | @type spanning_tree: dictionary
55 | @param spanning_tree: Spanning tree.
56 | """
57 | self.graph = graph
58 | self.spanning_tree = spanning_tree
59 |
60 | def __call__(self, node, parent):
61 | """
62 | Decide if the given node should be included in the search process.
63 |
64 | @type node: node
65 | @param node: Given node.
66 |
67 | @type parent: node
68 | @param parent: Given node's parent in the spanning tree.
69 |
70 | @rtype: boolean
71 | @return: Whether the given node should be included in the search process.
72 | """
73 | if (not self.done):
74 | if (node == self.target):
75 | self.done = True
76 | return True
77 | else:
78 | return False
--------------------------------------------------------------------------------
/python-graph/Makefile:
--------------------------------------------------------------------------------
1 | # python-graph
2 | # Makefile
3 |
4 |
5 | # Module directories -------------------------------------------------
6 |
7 | CORE_DIR="core/"
8 | DOT_DIR="dot/"
9 | TESTS_DIR="tests/"
10 | DOCS_DIR="docs/"
11 | TEMP="temp/"
12 | PYTHONPATH="`pwd`/core:`pwd`/dot"
13 |
14 |
15 | # General ------------------------------------------------------------
16 |
17 | nothing:
18 |
19 | sdist: clean sdist-core sdist-dot
20 | rm -rf dist
21 | mkdir dist
22 | cp */dist/* dist
23 |
24 |
25 | # Core ---------------------------------------------------------------
26 |
27 | install-core:
28 | cd ${CORE_DIR} && ./setup.py install
29 |
30 | sdist-core: clean
31 | cd ${CORE_DIR} && ./setup.py sdist
32 |
33 |
34 | # Dot ----------------------------------------------------------------
35 |
36 | install-dot:
37 | cd ${DOT_DIR} && ./setup.py install
38 |
39 | sdist-dot: clean
40 | cd ${DOT_DIR} && ./setup.py sdist
41 |
42 |
43 | # Docs ---------------------------------------------------------------
44 |
45 | docs: cleanpyc
46 | rm -rf ${DOCS_DIR} ${TEMP}
47 | mkdir -p ${TEMP}
48 | cp -R ${CORE_DIR}/pygraph ${TEMP}
49 | cp -Rn ${DOT_DIR}/pygraph ${TEMP}/pygraph/
50 | epydoc -v --no-frames --no-sourcecode --name="python-graph" \
51 | --url="http://code.google.com/p/python-graph/" \
52 | --inheritance listed --no-private --html \
53 | --graph classtree \
54 | --css misc/epydoc.css -o docs ${TEMP}/pygraph/*.py \
55 | ${TEMP}/pygraph/algorithms/*py \
56 | ${TEMP}/pygraph/algorithms/heuristics/*.py \
57 | ${TEMP}/pygraph/algorithms/filters/* \
58 | ${TEMP}/pygraph/readwrite/* \
59 | ${TEMP}/pygraph/classes/*.py \
60 | ${TEMP}/pygraph/mixins/*.py
61 | rm -rf ${TEMP}
62 |
63 |
64 | # Tests --------------------------------------------------------------
65 |
66 | test-pre:
67 | reset
68 |
69 | test: test-pre
70 | export PYTHONPATH=${PYTHONPATH} && cd ${TESTS_DIR} && python testrunner.py
71 |
72 | test3: test-pre
73 | export PYTHONPATH=${PYTHONPATH} && cd ${TESTS_DIR} && python3 testrunner.py
74 |
75 | tests: test
76 |
77 |
78 | # Tests --------------------------------------------------------------
79 |
80 | console:
81 | export PYTHONPATH=${PYTHONPATH} && cd ${TESTS_DIR} && python
82 |
83 | console3:
84 | export PYTHONPATH=${PYTHONPATH} && cd ${TESTS_DIR} && python3
85 |
86 |
87 | # Cleaning -----------------------------------------------------------
88 |
89 | cleanpyc:
90 | find . -name *.pyc -exec rm {} \;
91 | find . -name __pycache__ -exec rm -rf {} \;
92 |
93 | clean: cleanpyc
94 | rm -rf ${DOCS_DIR}
95 | rm -rf */dist
96 | rm -rf */build
97 | rm -rf */*.egg-info
98 | rm -rf dist
99 |
100 |
101 | # Phony rules --------------------------------------------------------
102 |
103 | .PHONY: clean cleanpyc docs-core
104 |
--------------------------------------------------------------------------------
/python-graph/core/build/lib.linux-i686-2.6/pygraph/algorithms/traversal.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Traversal algorithms.
27 |
28 | @sort: traversal
29 | """
30 |
31 |
32 | # Minimal spanning tree
33 |
34 | def traversal(graph, node, order):
35 | """
36 | Graph traversal iterator.
37 |
38 | @type graph: graph, digraph
39 | @param graph: Graph.
40 |
41 | @type node: node
42 | @param node: Node.
43 |
44 | @type order: string
45 | @param order: traversal ordering. Possible values are:
46 | 2. 'pre' - Preordering (default)
47 | 1. 'post' - Postordering
48 |
49 | @rtype: iterator
50 | @return: Traversal iterator.
51 | """
52 | visited = {}
53 | if (order == 'pre'):
54 | pre = 1
55 | post = 0
56 | elif (order == 'post'):
57 | pre = 0
58 | post = 1
59 |
60 | for each in _dfs(graph, visited, node, pre, post):
61 | yield each
62 |
63 |
64 | def _dfs(graph, visited, node, pre, post):
65 | """
66 | Depth-first search subfunction for traversals.
67 |
68 | @type graph: graph, digraph
69 | @param graph: Graph.
70 |
71 | @type visited: dictionary
72 | @param visited: List of nodes (visited nodes are marked non-zero).
73 |
74 | @type node: node
75 | @param node: Node to be explored by DFS.
76 | """
77 | visited[node] = 1
78 | if (pre): yield node
79 | # Explore recursively the connected component
80 | for each in graph[node]:
81 | if (each not in visited):
82 | for other in _dfs(graph, visited, each, pre, post):
83 | yield other
84 | if (post): yield node
85 |
--------------------------------------------------------------------------------
/src/ismalware.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | import xml.etree.ElementTree as et
3 | from pygraph.classes.digraph import digraph
4 | from pygraph.readwrite.dot import *
5 | from mcs import *
6 | from mincs import *
7 | from wcbg import *
8 |
9 | # Delta function which ckecks the similarity between wcbg and guest malware kobg
10 | def similarity (wcbg, gnew):
11 | wcbg_edges = wcbg.edges ()
12 | gnew_edges = gnew.edges ()
13 |
14 | sum = 0
15 | for e1 in wcbg_edges:
16 | for e2 in gnew_edges:
17 | w_node1, w_node2 = e1
18 | g_node1, g_node2 = e2
19 | w_node1_attr = wcbg.node_attributes (w_node1)
20 | w_node2_attr = wcbg.node_attributes (w_node2)
21 | w_node1_label = w_node1_attr [0][1]
22 | w_node2_label = w_node2_attr [0][1]
23 | g_node1_attr = gnew.node_attributes (g_node1)
24 | g_node2_attr = gnew.node_attributes (g_node2)
25 | g_node1_label = g_node1_attr [0][1]
26 | g_node2_label = g_node2_attr [0][1]
27 | if g_node1_label == w_node1_label and g_node2_label == w_node2_label:
28 | sum = sum + gnew.edge_weight (e2)
29 | break
30 |
31 | sum = float (sum)
32 | n = min (len (gnew), len (wcbg))
33 | if n > 0:
34 | return sum/n
35 | else:
36 | return -1
37 |
38 | # Checks if a graph is the subset of other graph
39 | def issubset (hotpath, malware_kobg):
40 | mcs = mcsinit (hotpath, malware_kobg)
41 | if len (mcs.nodes ()) == len (hotpath.nodes ()) and len (mcs.edges ()) == len (hotpath.edges ()):
42 | return True
43 | else:
44 | return False
45 |
46 | # Final check if malware is of the same family
47 | def isMalware (wcbg, hotpath, malware_kobg, gamma):
48 | similarity_index = similarity (wcbg, malware_kobg)
49 | issubset (hotpath, malware_kobg)
50 | if similarity_index > gamma and issubset (hotpath, malware_kobg):
51 | return True
52 | else:
53 | return False
54 |
55 | # Initializes operations on guest malware`
56 | def init_check (hotpath, wcbg, family):
57 | global nodeid
58 | nodeid = 1
59 | malware = sys.argv [3]
60 | malware_kobg = makeMalGraph (malware)
61 | malware = malware.split ('.')[0]
62 | generate_graph_image (malware_kobg, malware)
63 | decision = isMalware (wcbg, hotpath, malware_kobg, GAMMA)
64 | if decision:
65 | print malware + ' is a Malware of the family ' + family
66 | else:
67 | print malware + ' is not a Malware of the family ' + family
68 |
69 | # Init function
70 | if __name__ == '__main__':
71 | wcbg_file = sys.argv [1]
72 | if os.path.isfile (wcbg_file):
73 | pass
74 | else:
75 | raise IOError ('File does not exists')
76 |
77 | f_wcbg = open (wcbg_file, 'r')
78 | dot_wcbg = f_wcbg.read ()
79 | f_wcbg.close ()
80 | wcbg = read (dot_wcbg)
81 | # print wcbg
82 | hotpath_file = sys.argv [2]
83 | if os.path.isfile (hotpath_file):
84 | pass
85 | else:
86 | raise IOError ('File does not exists')
87 |
88 | f_hotpath = open (hotpath_file, 'r')
89 | dot_hotpath = f_hotpath.read ()
90 | f_hotpath.close ()
91 | hotpath = read (dot_hotpath)
92 | family = wcbg_file.split ('.')[0]
93 | init_check (hotpath, wcbg, family)
94 |
--------------------------------------------------------------------------------
/python-graph/core/pygraph/algorithms/pagerank.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2010 Pedro Matiello
2 | # Juarez Bochi
3 | #
4 | # Permission is hereby granted, free of charge, to any person
5 | # obtaining a copy of this software and associated documentation
6 | # files (the "Software"), to deal in the Software without
7 | # restriction, including without limitation the rights to use,
8 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | # copies of the Software, and to permit persons to whom the
10 | # Software is furnished to do so, subject to the following
11 | # conditions:
12 |
13 | # The above copyright notice and this permission notice shall be
14 | # included in all copies or substantial portions of the Software.
15 |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 | # OTHER DEALINGS IN THE SOFTWARE.
24 |
25 |
26 | """
27 | PageRank algoritm
28 |
29 | @sort: pagerank
30 | """
31 |
32 | def pagerank(graph, damping_factor=0.85, max_iterations=100, min_delta=0.00001):
33 | """
34 | Compute and return the PageRank in an directed graph.
35 |
36 | @type graph: digraph
37 | @param graph: Digraph.
38 |
39 | @type damping_factor: number
40 | @param damping_factor: PageRank dumping factor.
41 |
42 | @type max_iterations: number
43 | @param max_iterations: Maximum number of iterations.
44 |
45 | @type min_delta: number
46 | @param min_delta: Smallest variation required to have a new iteration.
47 |
48 | @rtype: Dict
49 | @return: Dict containing all the nodes PageRank.
50 | """
51 |
52 | nodes = graph.nodes()
53 | graph_size = len(nodes)
54 | if graph_size == 0:
55 | return {}
56 | min_value = (1.0-damping_factor)/graph_size #value for nodes without inbound links
57 |
58 | # itialize the page rank dict with 1/N for all nodes
59 | pagerank = dict.fromkeys(nodes, 1.0/graph_size)
60 |
61 | for i in range(max_iterations):
62 | diff = 0 #total difference compared to last iteraction
63 | # computes each node PageRank based on inbound links
64 | for node in nodes:
65 | rank = min_value
66 | for referring_page in graph.incidents(node):
67 | rank += damping_factor * pagerank[referring_page] / len(graph.neighbors(referring_page))
68 |
69 | diff += abs(pagerank[node] - rank)
70 | pagerank[node] = rank
71 |
72 | #stop if PageRank has converged
73 | if diff < min_delta:
74 | break
75 |
76 | return pagerank
77 |
--------------------------------------------------------------------------------
/python-graph/core/build/lib.linux-i686-2.6/pygraph/algorithms/pagerank.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2010 Pedro Matiello
2 | # Juarez Bochi
3 | #
4 | # Permission is hereby granted, free of charge, to any person
5 | # obtaining a copy of this software and associated documentation
6 | # files (the "Software"), to deal in the Software without
7 | # restriction, including without limitation the rights to use,
8 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | # copies of the Software, and to permit persons to whom the
10 | # Software is furnished to do so, subject to the following
11 | # conditions:
12 |
13 | # The above copyright notice and this permission notice shall be
14 | # included in all copies or substantial portions of the Software.
15 |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 | # OTHER DEALINGS IN THE SOFTWARE.
24 |
25 |
26 | """
27 | PageRank algoritm
28 |
29 | @sort: pagerank
30 | """
31 |
32 | def pagerank(graph, damping_factor=0.85, max_iterations=100, min_delta=0.00001):
33 | """
34 | Compute and return the PageRank in an directed graph.
35 |
36 | @type graph: digraph
37 | @param graph: Digraph.
38 |
39 | @type damping_factor: number
40 | @param damping_factor: PageRank dumping factor.
41 |
42 | @type max_iterations: number
43 | @param max_iterations: Maximum number of iterations.
44 |
45 | @type min_delta: number
46 | @param min_delta: Smallest variation required to have a new iteration.
47 |
48 | @rtype: Dict
49 | @return: Dict containing all the nodes PageRank.
50 | """
51 |
52 | nodes = graph.nodes()
53 | graph_size = len(nodes)
54 | if graph_size == 0:
55 | return {}
56 | min_value = (1.0-damping_factor)/graph_size #value for nodes without inbound links
57 |
58 | # itialize the page rank dict with 1/N for all nodes
59 | pagerank = dict.fromkeys(nodes, 1.0/graph_size)
60 |
61 | for i in range(max_iterations):
62 | diff = 0 #total difference compared to last iteraction
63 | # computes each node PageRank based on inbound links
64 | for node in nodes:
65 | rank = min_value
66 | for referring_page in graph.incidents(node):
67 | rank += damping_factor * pagerank[referring_page] / len(graph.neighbors(referring_page))
68 |
69 | diff += abs(pagerank[node] - rank)
70 | pagerank[node] = rank
71 |
72 | #stop if PageRank has converged
73 | if diff < min_delta:
74 | break
75 |
76 | return pagerank
77 |
--------------------------------------------------------------------------------
/python-graph/core/pygraph/algorithms/heuristics/chow.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | # Salim Fadhley
3 | #
4 | # Permission is hereby granted, free of charge, to any person
5 | # obtaining a copy of this software and associated documentation
6 | # files (the "Software"), to deal in the Software without
7 | # restriction, including without limitation the rights to use,
8 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | # copies of the Software, and to permit persons to whom the
10 | # Software is furnished to do so, subject to the following
11 | # conditions:
12 |
13 | # The above copyright notice and this permission notice shall be
14 | # included in all copies or substantial portions of the Software.
15 |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 | # OTHER DEALINGS IN THE SOFTWARE.
24 |
25 |
26 | """
27 | Edmond Chow's heuristic for A*.
28 | """
29 |
30 |
31 | # Imports
32 | from pygraph.algorithms.minmax import shortest_path
33 |
34 |
35 | class chow(object):
36 | """
37 | An implementation of the graph searching heuristic proposed by Edmond Chow.
38 |
39 | Remember to call the C{optimize()} method before the heuristic search.
40 |
41 | For details, check: U{http://www.edmondchow.com/pubs/levdiff-aaai.pdf}.
42 | """
43 |
44 | def __init__(self, *centers):
45 | """
46 | Initialize a Chow heuristic object.
47 | """
48 | self.centers = centers
49 | self.nodes = {}
50 |
51 | def optimize(self, graph):
52 | """
53 | Build a dictionary mapping each pair of nodes to a number (the distance between them).
54 |
55 | @type graph: graph
56 | @param graph: Graph.
57 | """
58 | for center in self.centers:
59 | shortest_routes = shortest_path(graph, center)[1]
60 | for node, weight in list(shortest_routes.items()):
61 | self.nodes.setdefault(node, []).append(weight)
62 |
63 | def __call__(self, start, end):
64 | """
65 | Estimate how far start is from end.
66 |
67 | @type start: node
68 | @param start: Start node.
69 |
70 | @type end: node
71 | @param end: End node.
72 | """
73 | assert len( list(self.nodes.keys()) ) > 0, "You need to optimize this heuristic for your graph before it can be used to estimate."
74 |
75 | cmp_sequence = list(zip( self.nodes[start], self.nodes[end] ))
76 | chow_number = max( abs( a-b ) for a,b in cmp_sequence )
77 | return chow_number
78 |
--------------------------------------------------------------------------------
/python-graph/core/pygraph/algorithms/utils.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | # Roy Smith
3 | # Salim Fadhley
4 | #
5 | # Permission is hereby granted, free of charge, to any person
6 | # obtaining a copy of this software and associated documentation
7 | # files (the "Software"), to deal in the Software without
8 | # restriction, including without limitation the rights to use,
9 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | # copies of the Software, and to permit persons to whom the
11 | # Software is furnished to do so, subject to the following
12 | # conditions:
13 |
14 | # The above copyright notice and this permission notice shall be
15 | # included in all copies or substantial portions of the Software.
16 |
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 | # OTHER DEALINGS IN THE SOFTWARE.
25 |
26 |
27 | """
28 | Miscellaneous useful stuff.
29 | """
30 |
31 | # Imports
32 | from heapq import heappush, heappop, heapify
33 |
34 |
35 | # Priority Queue
36 | class priority_queue:
37 | """
38 | Priority queue.
39 | """
40 |
41 | def __init__(self, list=[]):
42 | self.heap = [HeapItem(i, 0) for i in list]
43 | heapify(self.heap)
44 |
45 | def __contains__(self, item):
46 | for heap_item in self.heap:
47 | if item == heap_item.item:
48 | return True
49 | return False
50 |
51 | def __len__(self):
52 | return len(self.heap)
53 |
54 | def empty(self):
55 | return len(self.heap) == 0
56 |
57 | def insert(self, item, priority):
58 | """
59 | Insert item into the queue, with the given priority.
60 | """
61 | heappush(self.heap, HeapItem(item, priority))
62 |
63 | def pop(self):
64 | """
65 | Return the item with the lowest priority, and remove it from the queue.
66 | """
67 | return heappop(self.heap).item
68 |
69 | def peek(self):
70 | """
71 | Return the item with the lowest priority. The queue is unchanged.
72 | """
73 | return self.heap[0].item
74 |
75 | def discard(self, item):
76 | new_heap = []
77 | for heap_item in self.heap:
78 | if item != heap_item.item:
79 | new_heap.append(heap_item)
80 | self.heap = new_heap
81 | heapify(self.heap)
82 |
83 | class HeapItem:
84 | def __init__(self, item, priority):
85 | self.item = item
86 | self.priority = priority
87 |
88 | def __cmp__(self, other):
89 | return cmp(self.priority, other.priority)
90 |
--------------------------------------------------------------------------------
/python-graph/core/build/lib.linux-i686-2.6/pygraph/algorithms/heuristics/chow.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | # Salim Fadhley
3 | #
4 | # Permission is hereby granted, free of charge, to any person
5 | # obtaining a copy of this software and associated documentation
6 | # files (the "Software"), to deal in the Software without
7 | # restriction, including without limitation the rights to use,
8 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | # copies of the Software, and to permit persons to whom the
10 | # Software is furnished to do so, subject to the following
11 | # conditions:
12 |
13 | # The above copyright notice and this permission notice shall be
14 | # included in all copies or substantial portions of the Software.
15 |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 | # OTHER DEALINGS IN THE SOFTWARE.
24 |
25 |
26 | """
27 | Edmond Chow's heuristic for A*.
28 | """
29 |
30 |
31 | # Imports
32 | from pygraph.algorithms.minmax import shortest_path
33 |
34 |
35 | class chow(object):
36 | """
37 | An implementation of the graph searching heuristic proposed by Edmond Chow.
38 |
39 | Remember to call the C{optimize()} method before the heuristic search.
40 |
41 | For details, check: U{http://www.edmondchow.com/pubs/levdiff-aaai.pdf}.
42 | """
43 |
44 | def __init__(self, *centers):
45 | """
46 | Initialize a Chow heuristic object.
47 | """
48 | self.centers = centers
49 | self.nodes = {}
50 |
51 | def optimize(self, graph):
52 | """
53 | Build a dictionary mapping each pair of nodes to a number (the distance between them).
54 |
55 | @type graph: graph
56 | @param graph: Graph.
57 | """
58 | for center in self.centers:
59 | shortest_routes = shortest_path(graph, center)[1]
60 | for node, weight in list(shortest_routes.items()):
61 | self.nodes.setdefault(node, []).append(weight)
62 |
63 | def __call__(self, start, end):
64 | """
65 | Estimate how far start is from end.
66 |
67 | @type start: node
68 | @param start: Start node.
69 |
70 | @type end: node
71 | @param end: End node.
72 | """
73 | assert len( list(self.nodes.keys()) ) > 0, "You need to optimize this heuristic for your graph before it can be used to estimate."
74 |
75 | cmp_sequence = list(zip( self.nodes[start], self.nodes[end] ))
76 | chow_number = max( abs( a-b ) for a,b in cmp_sequence )
77 | return chow_number
78 |
--------------------------------------------------------------------------------
/python-graph/core/build/lib.linux-i686-2.6/pygraph/algorithms/utils.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | # Roy Smith
3 | # Salim Fadhley
4 | #
5 | # Permission is hereby granted, free of charge, to any person
6 | # obtaining a copy of this software and associated documentation
7 | # files (the "Software"), to deal in the Software without
8 | # restriction, including without limitation the rights to use,
9 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | # copies of the Software, and to permit persons to whom the
11 | # Software is furnished to do so, subject to the following
12 | # conditions:
13 |
14 | # The above copyright notice and this permission notice shall be
15 | # included in all copies or substantial portions of the Software.
16 |
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 | # OTHER DEALINGS IN THE SOFTWARE.
25 |
26 |
27 | """
28 | Miscellaneous useful stuff.
29 | """
30 |
31 | # Imports
32 | from heapq import heappush, heappop, heapify
33 |
34 |
35 | # Priority Queue
36 | class priority_queue:
37 | """
38 | Priority queue.
39 | """
40 |
41 | def __init__(self, list=[]):
42 | self.heap = [HeapItem(i, 0) for i in list]
43 | heapify(self.heap)
44 |
45 | def __contains__(self, item):
46 | for heap_item in self.heap:
47 | if item == heap_item.item:
48 | return True
49 | return False
50 |
51 | def __len__(self):
52 | return len(self.heap)
53 |
54 | def empty(self):
55 | return len(self.heap) == 0
56 |
57 | def insert(self, item, priority):
58 | """
59 | Insert item into the queue, with the given priority.
60 | """
61 | heappush(self.heap, HeapItem(item, priority))
62 |
63 | def pop(self):
64 | """
65 | Return the item with the lowest priority, and remove it from the queue.
66 | """
67 | return heappop(self.heap).item
68 |
69 | def peek(self):
70 | """
71 | Return the item with the lowest priority. The queue is unchanged.
72 | """
73 | return self.heap[0].item
74 |
75 | def discard(self, item):
76 | new_heap = []
77 | for heap_item in self.heap:
78 | if item != heap_item.item:
79 | new_heap.append(heap_item)
80 | self.heap = new_heap
81 | heapify(self.heap)
82 |
83 | class HeapItem:
84 | def __init__(self, item, priority):
85 | self.item = item
86 | self.priority = priority
87 |
88 | def __cmp__(self, other):
89 | return cmp(self.priority, other.priority)
90 |
--------------------------------------------------------------------------------
/python-graph/core/pygraph/algorithms/filters/radius.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Radial search filter.
27 | """
28 |
29 |
30 | class radius(object):
31 | """
32 | Radial search filter.
33 |
34 | This will keep searching contained inside a specified limit.
35 | """
36 |
37 | def __init__(self, radius):
38 | """
39 | Initialize the filter.
40 |
41 | @type radius: number
42 | @param radius: Search radius.
43 | """
44 | self.graph = None
45 | self.spanning_tree = None
46 | self.radius = radius
47 | self.done = False
48 |
49 | def configure(self, graph, spanning_tree):
50 | """
51 | Configure the filter.
52 |
53 | @type graph: graph
54 | @param graph: Graph.
55 |
56 | @type spanning_tree: dictionary
57 | @param spanning_tree: Spanning tree.
58 | """
59 | self.graph = graph
60 | self.spanning_tree = spanning_tree
61 |
62 | def __call__(self, node, parent):
63 | """
64 | Decide if the given node should be included in the search process.
65 |
66 | @type node: node
67 | @param node: Given node.
68 |
69 | @type parent: node
70 | @param parent: Given node's parent in the spanning tree.
71 |
72 | @rtype: boolean
73 | @return: Whether the given node should be included in the search process.
74 | """
75 |
76 | def cost_to_root(node):
77 | if (node is not None):
78 | return cost_to_parent(node, st[node]) + cost_to_root(st[node])
79 | else:
80 | return 0
81 |
82 | def cost_to_parent(node, parent):
83 | if (parent is not None):
84 | return gr.edge_weight((parent, node))
85 | else:
86 | return 0
87 |
88 | gr = self.graph
89 | st = self.spanning_tree
90 |
91 | cost = cost_to_parent(node, parent) + cost_to_root(parent)
92 |
93 | if (cost <= self.radius):
94 | return True
95 | else:
96 | return False
--------------------------------------------------------------------------------
/python-graph/core/build/lib.linux-i686-2.6/pygraph/algorithms/filters/radius.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Radial search filter.
27 | """
28 |
29 |
30 | class radius(object):
31 | """
32 | Radial search filter.
33 |
34 | This will keep searching contained inside a specified limit.
35 | """
36 |
37 | def __init__(self, radius):
38 | """
39 | Initialize the filter.
40 |
41 | @type radius: number
42 | @param radius: Search radius.
43 | """
44 | self.graph = None
45 | self.spanning_tree = None
46 | self.radius = radius
47 | self.done = False
48 |
49 | def configure(self, graph, spanning_tree):
50 | """
51 | Configure the filter.
52 |
53 | @type graph: graph
54 | @param graph: Graph.
55 |
56 | @type spanning_tree: dictionary
57 | @param spanning_tree: Spanning tree.
58 | """
59 | self.graph = graph
60 | self.spanning_tree = spanning_tree
61 |
62 | def __call__(self, node, parent):
63 | """
64 | Decide if the given node should be included in the search process.
65 |
66 | @type node: node
67 | @param node: Given node.
68 |
69 | @type parent: node
70 | @param parent: Given node's parent in the spanning tree.
71 |
72 | @rtype: boolean
73 | @return: Whether the given node should be included in the search process.
74 | """
75 |
76 | def cost_to_root(node):
77 | if (node is not None):
78 | return cost_to_parent(node, st[node]) + cost_to_root(st[node])
79 | else:
80 | return 0
81 |
82 | def cost_to_parent(node, parent):
83 | if (parent is not None):
84 | return gr.edge_weight((parent, node))
85 | else:
86 | return 0
87 |
88 | gr = self.graph
89 | st = self.spanning_tree
90 |
91 | cost = cost_to_parent(node, parent) + cost_to_root(parent)
92 |
93 | if (cost <= self.radius):
94 | return True
95 | else:
96 | return False
--------------------------------------------------------------------------------
/python-graph/tests/unittests-critical.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Pedro Matiello
2 | # Tomaz Kovacic
3 | #
4 | # Permission is hereby granted, free of charge, to any person
5 | # obtaining a copy of this software and associated documentation
6 | # files (the "Software"), to deal in the Software without
7 | # restriction, including without limitation the rights to use,
8 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | # copies of the Software, and to permit persons to whom the
10 | # Software is furnished to do so, subject to the following
11 | # conditions:
12 |
13 | # The above copyright notice and this permission notice shall be
14 | # included in all copies or substantial portions of the Software.
15 |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 | # OTHER DEALINGS IN THE SOFTWARE.
24 |
25 |
26 | """
27 | Unittests for pygraph.algorithms.critical
28 | """
29 |
30 | import unittest
31 | from pygraph.algorithms.critical import critical_path
32 | from pygraph.algorithms.critical import transitive_edges,_intersection
33 | from pygraph.classes.digraph import digraph
34 |
35 | def generate_test_graph():
36 | '''
37 | Generates & returns a weighted digraph with
38 | one transitive edge and no cycles.
39 | '''
40 | G = digraph()
41 | G.add_nodes([1,2,3,4,5,6])
42 | G.add_edge((1,2), 1)
43 | G.add_edge((2,4), 4)
44 | G.add_edge((1,3), 1)#transitive edge
45 | G.add_edge((2,3), 20)
46 | G.add_edge((3,5), 3)
47 | G.add_edge((4,6), 5)
48 | G.add_edge((5,6), 4)
49 | return G
50 |
51 | class test_critical_path_and_transitive_edges(unittest.TestCase):
52 |
53 | # critical path algorithm
54 |
55 | def test_critical_path_with_cycle(self):
56 | G = generate_test_graph()
57 | G.add_edge((5,2),3)#add cycle
58 | assert critical_path(G) == []
59 |
60 | def test_critical_path(self):
61 | G = generate_test_graph()
62 | assert critical_path(G) == [1,2,3,5,6]
63 |
64 | # transitive edge detection algorithm
65 |
66 | def test_transitivity_with_cycle(self):
67 | G = generate_test_graph()
68 | G.add_edge((5,2),3)#add cycle
69 | assert transitive_edges(G) == []
70 |
71 | def test_transitivity(self):
72 | G = generate_test_graph()
73 | G.add_edge((2,5),1)#add another transitive edge
74 | assert transitive_edges(G) == [(1,3),(2,5)]
75 |
76 | # intersection testing (used internally)
77 |
78 | def test_partial_intersection(self):
79 | list1 = [1,2,3,4]
80 | list2 = [3,4,5,6]
81 | assert _intersection(list1, list2) == [3,4]
82 |
83 | def test_empty_intersection(self):
84 | list1 = [1,2,3,4]
85 | list2 = [5,6]
86 | assert _intersection(list1, list2) == []
87 |
88 |
89 | if __name__ == "__main__":
90 | unittest.main()
--------------------------------------------------------------------------------
/python-graph/tests/unittests-sorting.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Unittests for graph.algorithms.sorting
27 | """
28 |
29 |
30 | import unittest
31 | import pygraph.classes
32 | from pygraph.algorithms.sorting import topological_sorting
33 | from pygraph.algorithms.searching import depth_first_search
34 | from sys import getrecursionlimit
35 | import testlib
36 |
37 |
38 | class test_topological_sorting(unittest.TestCase):
39 |
40 | def test_topological_sorting_on_tree(self):
41 | gr = testlib.new_graph()
42 | st, pre, post = depth_first_search(gr)
43 | tree = pygraph.classes.digraph.digraph()
44 |
45 |
46 | for each in st:
47 | if st[each]:
48 | if (each not in tree.nodes()):
49 | tree.add_node(each)
50 | if (st[each] not in tree.nodes()):
51 | tree.add_node(st[each])
52 | tree.add_edge((st[each], each))
53 |
54 | ts = topological_sorting(tree)
55 | for each in ts:
56 | if (st[each]):
57 | assert ts.index(each) > ts.index(st[each])
58 |
59 | def test_topological_sorting_on_digraph(self):
60 |
61 | def is_ordered(node, list):
62 | # Has parent on list
63 | for each in list:
64 | if gr.has_edge((each, node)):
65 | return True
66 | # Has no possible ancestors on list
67 | st, pre, post = depth_first_search(gr, node)
68 | for each in list:
69 | if (each in st):
70 | return False
71 | return True
72 |
73 | gr = testlib.new_digraph()
74 | ts = topological_sorting(gr)
75 |
76 | while (ts):
77 | x = ts.pop()
78 | assert is_ordered(x, ts)
79 |
80 | def test_topological_sort_on_very_deep_graph(self):
81 | gr = pygraph.classes.graph.graph()
82 | gr.add_nodes(range(0,20001))
83 | for i in range(0,20000):
84 | gr.add_edge((i,i+1))
85 | recursionlimit = getrecursionlimit()
86 | topological_sorting(gr)
87 | assert getrecursionlimit() == recursionlimit
88 |
89 | if __name__ == "__main__":
90 | unittest.main()
--------------------------------------------------------------------------------
/malwaresamples/Test/mal3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/src/malware1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/src/mincs.py:
--------------------------------------------------------------------------------
1 | from mcs import *
2 |
3 | # Checks if the edge is in g_subgraph
4 | def notin (edge, g_subgraph_edges, gid):
5 | for e in g_subgraph_edges:
6 | if (e[0][gid-1], e[1][gid-1]) == edge:
7 | return False
8 | return True
9 |
10 | # Returns embedding between a graph and its subgraph
11 | def embedding (subgraph, g, gid):
12 | g_subgraph_edges = subgraph.edges ()
13 | g_edges = g.edges ()
14 | E = []
15 | for edge in g_edges:
16 | if notin(edge, g_subgraph_edges, gid):
17 | E.append (edge)
18 | return E
19 |
20 | # Returns diff of two graphs
21 | def diff (g, g_subgraph, gid):
22 | g_subgraph_nodes = g_subgraph.nodes ()
23 | g_nodes = g.nodes ()
24 | delnodes = []
25 | for node in g_subgraph_nodes:
26 | if node[gid-1] in g_nodes:
27 | for node_adj in g.incidents (node[gid-1]):
28 | g.del_edge ((node_adj, node[gid-1]))
29 | if node_adj not in delnodes:
30 | delnodes.append (node_adj)
31 | if node[gid-1] not in delnodes:
32 | delnodes.append (node[gid-1])
33 | for node in delnodes:
34 | g.del_node (node)
35 | return g
36 |
37 | # Get a node in second graph, given a node in the first graph, from the subgraph
38 | def getendpoint (node2, subgraph):
39 | subgraph_nodes = subgraph.nodes ()
40 |
41 | for n1, n2 in subgraph_nodes:
42 | if n2 == node2:
43 | return n1
44 |
45 | return None
46 |
47 | # Returns the union of two graphs
48 | def union (g, g_diff, E, subgraph):
49 | g_diff_nodes = g_diff.nodes ()
50 | for node in g_diff_nodes:
51 | g.add_node (node, g_diff.node_attributes (node))
52 |
53 | for n1, n2 in E:
54 | if not (n1 in g_diff and n2 in g_diff):
55 | if n1 in g_diff:
56 | node1 = getendpoint (n2, subgraph)
57 | g.add_edge ((n1, node1))
58 | elif n2 in g_diff:
59 | node2 = getendpoint (n1, subgraph)
60 | g.add_edge ((node2, n2))
61 | return g
62 |
63 | # Sets appropriate weights of edges
64 | def setweight (graph, subgraph):
65 | subgraph_edges = subgraph.edges ()
66 | for e1, e2 in subgraph_edges:
67 | wt = subgraph.edge_weight ((e1[0], e2[0]))
68 | graph.set_edge_weight ((e1[0], e2[0]), wt + 1)
69 |
70 | # Returns isolated nodes in a graph
71 | def getisolatednodes (graph):
72 | g_nodes = graph.nodes ()
73 | nodelist = []
74 | for e1, e2 in graph.edges ():
75 | if e1 not in nodelist:
76 | nodelist.append (e1)
77 | if e2 not in nodelist:
78 | nodelist.append (e2)
79 | isolatednodes = []
80 | for node in g_nodes:
81 | if node not in nodelist:
82 | isolatednodes.append (node)
83 |
84 | return isolatednodes
85 |
86 | # Prunes the graph given a threshold
87 | def prunegraph (graph, theta):
88 | g_edges = graph.edges ()
89 | for e1, e2 in g_edges:
90 | if graph.edge_weight ((e1, e2)) < theta:
91 | graph.del_edge ((e1, e2))
92 |
93 | for node in getisolatednodes (graph):
94 | graph.del_node (node)
95 |
96 | return graph
97 |
98 | # Save a graph
99 | def save_graph (g):
100 | g_nodes = g.nodes ()
101 | graph = digraph ()
102 |
103 | for node in g_nodes:
104 | graph.add_node (node, g.node_attributes (node))
105 | g_edges = g.edges ()
106 | for edge in g_edges:
107 | graph.add_edge (edge)
108 | return graph
109 |
110 | # Return MinCS of two graphs
111 | def mincs (g1, g2):
112 | graph = save_graph (g1)
113 | subgraph = mcsinit (g1, g2)
114 | E1 = embedding (subgraph, g1, 1)
115 | E2 = embedding (subgraph, g2, 2)
116 | U1 = subgraph
117 | U2 = diff (g1, U1, 1)
118 | U3 = diff (g2, U1, 2)
119 | wmincs = union (graph, U3, E2, subgraph)
120 | return wmincs, subgraph
121 |
--------------------------------------------------------------------------------
/malwaresamples/Test/mal4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/python-graph/README:
--------------------------------------------------------------------------------
1 | python-graph
2 | A library for working with graphs in Python
3 | --------------------------------------------------------------------------------
4 |
5 |
6 | SUMMARY
7 |
8 | python-graph is a library for working with graphs in Python.
9 |
10 | This software provides a suitable data structure for representing graphs and a
11 | whole set of important algorithms.
12 |
13 |
14 | INSTALLING
15 |
16 | To install the core module, run:
17 |
18 | make install-core
19 |
20 | To install the dot language support, run:
21 |
22 | make install-dot
23 |
24 | Alternatively, if you don't have make, you can install the modules by running:
25 |
26 | ./setup.py install
27 |
28 | inside the module directory.
29 |
30 |
31 | DOCUMENTATION
32 |
33 | To generate the API documentation for this package, run:
34 |
35 | make docs
36 |
37 | You'll need epydoc installed in your system.
38 |
39 |
40 | WEBSITE
41 |
42 | The latest version of this package can be found at:
43 |
44 | http://code.google.com/p/python-graph/
45 |
46 | Please report bugs at:
47 |
48 | http://code.google.com/p/python-graph/issues/list
49 |
50 |
51 | PROJECT COMMITTERS
52 |
53 | Pedro Matiello
54 | * Project maintainer/leader;
55 | * Graph, Digraph and Hipergraph classes;
56 | * Accessibility algorithms;
57 | * Cut-node and cut-edge detection;
58 | * Cycle detection;
59 | * Depth-first and Breadth-first searching;
60 | * Minimal Spanning Tree (Prim's algorithm);
61 | * Random graph generation;
62 | * Topological sorting;
63 | * Traversals;
64 | * XML reading/writing;
65 | * Refactoring.
66 |
67 | Christian Muise
68 | * Project commiter;
69 | * Dot file reading/writing;
70 | * Hypergraph class;
71 | * Refactoring.
72 |
73 | Salim Fadhley
74 | * Project commiter;
75 | * Porting of Roy Smith's A* implementation to python-graph;
76 | * Edmond Chow's heuristic for A*;
77 | * Refactoring.
78 |
79 | Tomaz Kovacic
80 | * Project commiter;
81 | * Transitive edge detection;
82 | * Critical path algorithm;
83 | * Bellman-Ford algorithm;
84 | * Logo design.
85 |
86 |
87 | CONTRIBUTORS
88 |
89 | Eugen Zagorodniy
90 | * Mutual Accessibility (Tarjan's Algorithm).
91 |
92 | Johannes Reinhardt
93 | * Maximum-flow algorithm;
94 | * Gomory-Hu cut-tree algorithm;
95 | * Refactoring.
96 |
97 | Juarez Bochi
98 | * Pagerank algorithm.
99 |
100 | Nathan Davis
101 | * Faster node insertion.
102 |
103 | Paul Harrison
104 | * Mutual Accessibility (Tarjan's Algorithm).
105 |
106 | Peter Sagerson
107 | * Performance improvements on shortest path algorithm.
108 |
109 | Rhys Ulerich
110 | * Dijkstra's Shortest path algorithm.
111 |
112 | Roy Smith
113 | * Heuristic Searching (A* algorithm).
114 |
115 | Zsolt Haraszti
116 | * Weighted random generated graphs.
117 |
118 | Anand Jeyahar
119 | * Edge deletion on hypergraphs (bug fix).
120 |
121 | Emanuele Zattin
122 | * Hyperedge relinking (bug fix).
123 |
124 | Jonathan Sternberg
125 | * Graph comparison (bug fix);
126 | * Proper isolation of attribute lists (bug fix).
127 |
128 | Daniel Merritt
129 | * Fixed reading of XML-stored graphs with edge attributes.
130 |
131 |
132 | LICENSE
133 |
134 | This software is provided under the MIT license. See accompanying COPYING file
135 | for details.
136 |
--------------------------------------------------------------------------------
/python-graph/tests/unittests-heuristics.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Unittests for graph.algorithms.heuristics
27 | """
28 |
29 |
30 | import unittest
31 | import pygraph
32 | from pygraph.classes.graph import graph
33 | from pygraph.classes.digraph import digraph
34 | from pygraph.algorithms.heuristics.euclidean import euclidean
35 | from pygraph.algorithms.heuristics.chow import chow
36 | from pygraph.classes import exceptions
37 |
38 | from test_data import nations_of_the_world
39 |
40 |
41 | class test_chow(unittest.TestCase):
42 |
43 | def setUp(self):
44 | self.G = graph()
45 | nations_of_the_world(self.G)
46 |
47 | def test_basic(self):
48 | """
49 | Test some very basic functionality
50 | """
51 | englands_neighbors = self.G.neighbors("England")
52 | assert set(['Wales', 'Scotland', 'France', 'Ireland']) == set( englands_neighbors )
53 |
54 | def test_chow(self):
55 | heuristic = chow( "Wales", "North Korea", "Russia" )
56 | heuristic.optimize(self.G)
57 | result = pygraph.algorithms.minmax.heuristic_search( self.G, "England", "India", heuristic )
58 |
59 | def test_chow_unreachable(self):
60 | heuristic = chow( "Wales", "North Korea", "Russia" )
61 | self.G.add_node("Sealand")
62 | self.G.add_edge(("England", "Sealand"))
63 | heuristic.optimize(self.G)
64 | self.G.del_edge(("England", "Sealand"))
65 |
66 | try:
67 | result = pygraph.algorithms.minmax.heuristic_search( self.G, "England", "Sealand" , heuristic )
68 | except exceptions.NodeUnreachable as _:
69 | return
70 |
71 | assert False, "This test should raise an unreachable error."
72 |
73 |
74 | class test_euclidean(unittest.TestCase):
75 |
76 | def setUp(self):
77 | self.G = pygraph.classes.graph.graph()
78 | self.G.add_node('A', [('position',[0,0])])
79 | self.G.add_node('B', [('position',[2,0])])
80 | self.G.add_node('C', [('position',[2,3])])
81 | self.G.add_node('D', [('position',[1,2])])
82 | self.G.add_edge(('A', 'B'), wt=4)
83 | self.G.add_edge(('A', 'D'), wt=5)
84 | self.G.add_edge(('B', 'C'), wt=9)
85 | self.G.add_edge(('D', 'C'), wt=2)
86 |
87 | def test_euclidean(self):
88 | heuristic = euclidean()
89 | heuristic.optimize(self.G)
90 | result = pygraph.algorithms.minmax.heuristic_search(self.G, 'A', 'C', heuristic )
91 | assert result == ['A', 'D', 'C']
92 |
93 | if __name__ == "__main__":
94 | unittest.main()
--------------------------------------------------------------------------------
/python-graph/core/pygraph/algorithms/heuristics/euclidean.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | A* heuristic for euclidean graphs.
27 | """
28 |
29 |
30 | # Imports
31 |
32 |
33 | class euclidean(object):
34 | """
35 | A* heuristic for Euclidean graphs.
36 |
37 | This heuristic has three requirements:
38 | 1. All nodes should have the attribute 'position';
39 | 2. The weight of all edges should be the euclidean distance between the nodes it links;
40 | 3. The C{optimize()} method should be called before the heuristic search.
41 |
42 | A small example for clarification:
43 |
44 | >>> g = graph.graph()
45 | >>> g.add_nodes(['A','B','C'])
46 | >>> g.add_node_attribute('A', ('position',(0,0)))
47 | >>> g.add_node_attribute('B', ('position',(1,1)))
48 | >>> g.add_node_attribute('C', ('position',(0,2)))
49 | >>> g.add_edge('A','B', wt=2)
50 | >>> g.add_edge('B','C', wt=2)
51 | >>> g.add_edge('A','C', wt=4)
52 | >>> h = graph.heuristics.euclidean()
53 | >>> h.optimize(g)
54 | >>> g.heuristic_search('A', 'C', h)
55 | """
56 |
57 | def __init__(self):
58 | """
59 | Initialize the heuristic object.
60 | """
61 | self.distances = {}
62 |
63 | def optimize(self, graph):
64 | """
65 | Build a dictionary mapping each pair of nodes to a number (the distance between them).
66 |
67 | @type graph: graph
68 | @param graph: Graph.
69 | """
70 | for start in graph.nodes():
71 | for end in graph.nodes():
72 | for each in graph.node_attributes(start):
73 | if (each[0] == 'position'):
74 | start_attr = each[1]
75 | break
76 | for each in graph.node_attributes(end):
77 | if (each[0] == 'position'):
78 | end_attr = each[1]
79 | break
80 | dist = 0
81 | for i in range(len(start_attr)):
82 | dist = dist + (float(start_attr[i]) - float(end_attr[i]))**2
83 | self.distances[(start,end)] = dist
84 |
85 | def __call__(self, start, end):
86 | """
87 | Estimate how far start is from end.
88 |
89 | @type start: node
90 | @param start: Start node.
91 |
92 | @type end: node
93 | @param end: End node.
94 | """
95 | assert len(list(self.distances.keys())) > 0, "You need to optimize this heuristic for your graph before it can be used to estimate."
96 |
97 | return self.distances[(start,end)]
--------------------------------------------------------------------------------
/python-graph/core/build/lib.linux-i686-2.6/pygraph/algorithms/heuristics/euclidean.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | A* heuristic for euclidean graphs.
27 | """
28 |
29 |
30 | # Imports
31 |
32 |
33 | class euclidean(object):
34 | """
35 | A* heuristic for Euclidean graphs.
36 |
37 | This heuristic has three requirements:
38 | 1. All nodes should have the attribute 'position';
39 | 2. The weight of all edges should be the euclidean distance between the nodes it links;
40 | 3. The C{optimize()} method should be called before the heuristic search.
41 |
42 | A small example for clarification:
43 |
44 | >>> g = graph.graph()
45 | >>> g.add_nodes(['A','B','C'])
46 | >>> g.add_node_attribute('A', ('position',(0,0)))
47 | >>> g.add_node_attribute('B', ('position',(1,1)))
48 | >>> g.add_node_attribute('C', ('position',(0,2)))
49 | >>> g.add_edge('A','B', wt=2)
50 | >>> g.add_edge('B','C', wt=2)
51 | >>> g.add_edge('A','C', wt=4)
52 | >>> h = graph.heuristics.euclidean()
53 | >>> h.optimize(g)
54 | >>> g.heuristic_search('A', 'C', h)
55 | """
56 |
57 | def __init__(self):
58 | """
59 | Initialize the heuristic object.
60 | """
61 | self.distances = {}
62 |
63 | def optimize(self, graph):
64 | """
65 | Build a dictionary mapping each pair of nodes to a number (the distance between them).
66 |
67 | @type graph: graph
68 | @param graph: Graph.
69 | """
70 | for start in graph.nodes():
71 | for end in graph.nodes():
72 | for each in graph.node_attributes(start):
73 | if (each[0] == 'position'):
74 | start_attr = each[1]
75 | break
76 | for each in graph.node_attributes(end):
77 | if (each[0] == 'position'):
78 | end_attr = each[1]
79 | break
80 | dist = 0
81 | for i in range(len(start_attr)):
82 | dist = dist + (float(start_attr[i]) - float(end_attr[i]))**2
83 | self.distances[(start,end)] = dist
84 |
85 | def __call__(self, start, end):
86 | """
87 | Estimate how far start is from end.
88 |
89 | @type start: node
90 | @param start: Start node.
91 |
92 | @type end: node
93 | @param end: End node.
94 | """
95 | assert len(list(self.distances.keys())) > 0, "You need to optimize this heuristic for your graph before it can be used to estimate."
96 |
97 | return self.distances[(start,end)]
--------------------------------------------------------------------------------
/python-graph/tests/unittests-cycles.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Unittests for graph.algorithms.cycles
27 | """
28 |
29 |
30 | import unittest
31 | import pygraph
32 | from pygraph.algorithms.cycles import find_cycle
33 | from pygraph.algorithms.searching import depth_first_search
34 | from pygraph.classes.digraph import digraph
35 | from pygraph.classes.graph import graph
36 | from sys import getrecursionlimit
37 | import testlib
38 |
39 |
40 | def verify_cycle(graph, cycle):
41 | for i in range(len(cycle)):
42 | assert graph.has_edge((cycle[i],cycle[(i+1)%len(cycle)]))
43 |
44 | class test_find_cycle(unittest.TestCase):
45 |
46 | # Graph
47 |
48 | def test_find_cycle_on_graph(self):
49 | gr = testlib.new_graph()
50 | cycle = find_cycle(gr)
51 | verify_cycle(gr, cycle)
52 |
53 | def test_find_cycle_on_graph_withot_cycles(self):
54 | gr = testlib.new_graph()
55 | st, pre, post = depth_first_search(gr)
56 | gr = graph()
57 | gr.add_spanning_tree(st)
58 | assert find_cycle(gr) == []
59 |
60 | # Digraph
61 |
62 | def test_find_cycle_on_digraph(self):
63 | gr = testlib.new_digraph()
64 | cycle = find_cycle(gr)
65 | verify_cycle(gr, cycle)
66 |
67 | def test_find_cycle_on_digraph_without_cycles(self):
68 | gr = testlib.new_digraph()
69 | st, pre, post = depth_first_search(gr)
70 | gr = digraph()
71 | gr.add_spanning_tree(st)
72 | assert find_cycle(gr) == []
73 |
74 | def test_find_small_cycle_on_digraph(self):
75 | gr = digraph()
76 | gr.add_nodes([1, 2, 3, 4, 5])
77 | gr.add_edge((1, 2))
78 | gr.add_edge((2, 3))
79 | gr.add_edge((2, 4))
80 | gr.add_edge((4, 5))
81 | gr.add_edge((2, 1))
82 | # Cycle: 1-2
83 | assert find_cycle(gr) == [1,2]
84 |
85 | def test_find_cycle_on_very_deep_graph(self):
86 | gr = pygraph.classes.graph.graph()
87 | gr.add_nodes(range(0,20001))
88 | for i in range(0,20000):
89 | gr.add_edge((i,i+1))
90 | recursionlimit = getrecursionlimit()
91 | find_cycle(gr)
92 | assert getrecursionlimit() == recursionlimit
93 |
94 | # Regression
95 |
96 | def test_regression1(self):
97 | G = digraph()
98 | G.add_nodes([1, 2, 3, 4, 5])
99 | G.add_edge((1, 2))
100 | G.add_edge((2, 3))
101 | G.add_edge((2, 4))
102 | G.add_edge((4, 5))
103 | G.add_edge((3, 5))
104 | G.add_edge((3, 1))
105 | assert find_cycle(G) == [1, 2, 3]
106 |
107 | if __name__ == "__main__":
108 | unittest.main()
--------------------------------------------------------------------------------
/python-graph/tests/unittests-pagerank.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2010 Pedro Matiello
2 | # Juarez Bochi
3 | #
4 | # Permission is hereby granted, free of charge, to any person
5 | # obtaining a copy of this software and associated documentation
6 | # files (the "Software"), to deal in the Software without
7 | # restriction, including without limitation the rights to use,
8 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | # copies of the Software, and to permit persons to whom the
10 | # Software is furnished to do so, subject to the following
11 | # conditions:
12 |
13 | # The above copyright notice and this permission notice shall be
14 | # included in all copies or substantial portions of the Software.
15 |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 | # OTHER DEALINGS IN THE SOFTWARE.
24 |
25 |
26 | """
27 | Unittests for pygraph.algorithms.pagerank
28 | """
29 |
30 | import unittest
31 | from pygraph.classes.digraph import digraph
32 | from pygraph.algorithms.pagerank import pagerank
33 | import testlib
34 |
35 | class test_pagerank(unittest.TestCase):
36 |
37 | # pagerank algorithm
38 |
39 | def test_pagerank_empty(self):
40 | #Test if an empty dict is returned for an empty graph
41 | G = digraph()
42 | self.assertEqual(pagerank(G), {})
43 |
44 | def test_pagerank_cycle(self):
45 | #Test if all nodes in a cycle graph have the same value
46 | G = digraph()
47 | G.add_nodes([1, 2, 3, 4, 5])
48 | G.add_edge((1, 2))
49 | G.add_edge((2, 3))
50 | G.add_edge((3, 4))
51 | G.add_edge((4, 5))
52 | G.add_edge((5, 1))
53 | self.assertEqual(pagerank(G), {1: 0.2, 2: 0.2, 3: 0.2, 4: 0.2, 5: 0.2})
54 |
55 | def test_pagerank(self):
56 | #Test example from wikipedia: http://en.wikipedia.org/wiki/File:Linkstruct3.svg
57 | G = digraph()
58 | G.add_nodes([1, 2, 3, 4, 5, 6, 7])
59 | G.add_edge((1, 2))
60 | G.add_edge((1, 3))
61 | G.add_edge((1, 4))
62 | G.add_edge((1, 5))
63 | G.add_edge((1, 7))
64 | G.add_edge((2, 1))
65 | G.add_edge((3, 1))
66 | G.add_edge((3, 2))
67 | G.add_edge((4, 2))
68 | G.add_edge((4, 3))
69 | G.add_edge((4, 5))
70 | G.add_edge((5, 1))
71 | G.add_edge((5, 3))
72 | G.add_edge((5, 4))
73 | G.add_edge((5, 6))
74 | G.add_edge((6, 1))
75 | G.add_edge((6, 5))
76 | G.add_edge((7, 5))
77 | expected_pagerank = {
78 | 1: 0.280,
79 | 2: 0.159,
80 | 3: 0.139,
81 | 4: 0.108,
82 | 5: 0.184,
83 | 6: 0.061,
84 | 7: 0.069,
85 | }
86 | pr = pagerank(G)
87 | for k in pr:
88 | self.assertAlmostEqual(pr[k], expected_pagerank[k], places=3)
89 |
90 | def test_pagerank_random(self):
91 | G = testlib.new_digraph()
92 | md = 0.00001
93 | df = 0.85
94 | pr = pagerank(G, damping_factor=df, min_delta=md)
95 | min_value = (1.0-df)/len(G)
96 | for node in G:
97 | expected = min_value
98 | for each in G.incidents(node):
99 | expected += (df * pr[each] / len(G.neighbors(each)))
100 | assert abs(pr[node] - expected) < md
101 |
102 | if __name__ == "__main__":
103 | unittest.main()
104 |
--------------------------------------------------------------------------------
/malwaresamples/Test/mal1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/python-graph/core/pygraph/algorithms/cycles.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Cycle detection algorithms.
27 |
28 | @sort: find_cycle
29 | """
30 |
31 |
32 | # Imports
33 | from pygraph.classes.exceptions import InvalidGraphType
34 | from pygraph.classes.digraph import digraph as digraph_class
35 | from pygraph.classes.graph import graph as graph_class
36 | from sys import getrecursionlimit, setrecursionlimit
37 |
38 | def find_cycle(graph):
39 | """
40 | Find a cycle in the given graph.
41 |
42 | This function will return a list of nodes which form a cycle in the graph or an empty list if
43 | no cycle exists.
44 |
45 | @type graph: graph, digraph
46 | @param graph: Graph.
47 |
48 | @rtype: list
49 | @return: List of nodes.
50 | """
51 |
52 | if (isinstance(graph, graph_class)):
53 | directed = False
54 | elif (isinstance(graph, digraph_class)):
55 | directed = True
56 | else:
57 | raise InvalidGraphType
58 |
59 | def find_cycle_to_ancestor(node, ancestor):
60 | """
61 | Find a cycle containing both node and ancestor.
62 | """
63 | path = []
64 | while (node != ancestor):
65 | if (node is None):
66 | return []
67 | path.append(node)
68 | node = spanning_tree[node]
69 | path.append(node)
70 | path.reverse()
71 | return path
72 |
73 | def dfs(node):
74 | """
75 | Depth-first search subfunction.
76 | """
77 | visited[node] = 1
78 | # Explore recursively the connected component
79 | for each in graph[node]:
80 | if (cycle):
81 | return
82 | if (each not in visited):
83 | spanning_tree[each] = node
84 | dfs(each)
85 | else:
86 | if (directed or spanning_tree[node] != each):
87 | cycle.extend(find_cycle_to_ancestor(node, each))
88 |
89 | recursionlimit = getrecursionlimit()
90 | setrecursionlimit(max(len(graph.nodes())*2,recursionlimit))
91 |
92 | visited = {} # List for marking visited and non-visited nodes
93 | spanning_tree = {} # Spanning tree
94 | cycle = []
95 |
96 | # Algorithm outer-loop
97 | for each in graph:
98 | # Select a non-visited node
99 | if (each not in visited):
100 | spanning_tree[each] = None
101 | # Explore node's connected component
102 | dfs(each)
103 | if (cycle):
104 | setrecursionlimit(recursionlimit)
105 | return cycle
106 |
107 | setrecursionlimit(recursionlimit)
108 | return []
109 |
--------------------------------------------------------------------------------
/python-graph/core/build/lib.linux-i686-2.6/pygraph/algorithms/cycles.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Cycle detection algorithms.
27 |
28 | @sort: find_cycle
29 | """
30 |
31 |
32 | # Imports
33 | from pygraph.classes.exceptions import InvalidGraphType
34 | from pygraph.classes.digraph import digraph as digraph_class
35 | from pygraph.classes.graph import graph as graph_class
36 | from sys import getrecursionlimit, setrecursionlimit
37 |
38 | def find_cycle(graph):
39 | """
40 | Find a cycle in the given graph.
41 |
42 | This function will return a list of nodes which form a cycle in the graph or an empty list if
43 | no cycle exists.
44 |
45 | @type graph: graph, digraph
46 | @param graph: Graph.
47 |
48 | @rtype: list
49 | @return: List of nodes.
50 | """
51 |
52 | if (isinstance(graph, graph_class)):
53 | directed = False
54 | elif (isinstance(graph, digraph_class)):
55 | directed = True
56 | else:
57 | raise InvalidGraphType
58 |
59 | def find_cycle_to_ancestor(node, ancestor):
60 | """
61 | Find a cycle containing both node and ancestor.
62 | """
63 | path = []
64 | while (node != ancestor):
65 | if (node is None):
66 | return []
67 | path.append(node)
68 | node = spanning_tree[node]
69 | path.append(node)
70 | path.reverse()
71 | return path
72 |
73 | def dfs(node):
74 | """
75 | Depth-first search subfunction.
76 | """
77 | visited[node] = 1
78 | # Explore recursively the connected component
79 | for each in graph[node]:
80 | if (cycle):
81 | return
82 | if (each not in visited):
83 | spanning_tree[each] = node
84 | dfs(each)
85 | else:
86 | if (directed or spanning_tree[node] != each):
87 | cycle.extend(find_cycle_to_ancestor(node, each))
88 |
89 | recursionlimit = getrecursionlimit()
90 | setrecursionlimit(max(len(graph.nodes())*2,recursionlimit))
91 |
92 | visited = {} # List for marking visited and non-visited nodes
93 | spanning_tree = {} # Spanning tree
94 | cycle = []
95 |
96 | # Algorithm outer-loop
97 | for each in graph:
98 | # Select a non-visited node
99 | if (each not in visited):
100 | spanning_tree[each] = None
101 | # Explore node's connected component
102 | dfs(each)
103 | if (cycle):
104 | setrecursionlimit(recursionlimit)
105 | return cycle
106 |
107 | setrecursionlimit(recursionlimit)
108 | return []
109 |
--------------------------------------------------------------------------------
/python-graph/tests/unittests-readwrite.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Unittests for graph.algorithms.readwrite
27 | """
28 |
29 |
30 | import unittest
31 | import pygraph
32 | from pygraph.readwrite import dot, markup
33 | import testlib
34 |
35 | def graph_equality(gr1, gr2):
36 | for each in gr1.nodes():
37 | assert each in gr2.nodes()
38 | for each in gr2.nodes():
39 | assert each in gr1.nodes()
40 | for each in gr1.edges():
41 | assert each in gr2.edges()
42 | for each in gr2.edges():
43 | assert each in gr1.edges()
44 |
45 | class test_readwrite_dot(unittest.TestCase):
46 |
47 | def test_dot_for_graph(self):
48 | gr = testlib.new_graph()
49 | dotstr = dot.write(gr)
50 | gr1 = dot.read(dotstr)
51 | dotstr = dot.write(gr1)
52 | gr2 = dot.read(dotstr)
53 | graph_equality(gr1, gr2)
54 | assert len(gr.nodes()) == len(gr1.nodes())
55 | assert len(gr.edges()) == len(gr1.edges())
56 |
57 | def test_dot_for_digraph(self):
58 | gr = testlib.new_digraph()
59 | dotstr = dot.write(gr)
60 | gr1 = dot.read(dotstr)
61 | dotstr = dot.write(gr1)
62 | gr2 = dot.read(dotstr)
63 | graph_equality(gr1, gr2)
64 | assert len(gr.nodes()) == len(gr1.nodes())
65 | assert len(gr.edges()) == len(gr1.edges())
66 |
67 | def test_dot_for_hypergraph(self):
68 | gr = testlib.new_hypergraph()
69 | dotstr = dot.write(gr)
70 | gr1 = dot.read_hypergraph(dotstr)
71 | dotstr = dot.write(gr1)
72 | gr2 = dot.read_hypergraph(dotstr)
73 | graph_equality(gr1, gr2)
74 |
75 | def test_output_names_in_dot(self):
76 | gr1 = testlib.new_graph()
77 | gr1.name = "Some name 1"
78 | gr2 = testlib.new_digraph()
79 | gr2.name = "Some name 2"
80 | gr3 = testlib.new_hypergraph()
81 | gr3.name = "Some name 3"
82 | assert "Some name 1" in dot.write(gr1)
83 | assert "Some name 2" in dot.write(gr2)
84 | assert "Some name 3" in dot.write(gr3)
85 |
86 | class test_readwrite_markup(unittest.TestCase):
87 |
88 | def test_xml_for_graph(self):
89 | gr = testlib.new_graph()
90 | dotstr = markup.write(gr)
91 | gr1 = markup.read(dotstr)
92 | dotstr = markup.write(gr1)
93 | gr2 = markup.read(dotstr)
94 | graph_equality(gr1, gr2)
95 | assert len(gr.nodes()) == len(gr1.nodes())
96 | assert len(gr.edges()) == len(gr1.edges())
97 |
98 | def test_xml_digraph(self):
99 | gr = testlib.new_digraph()
100 | dotstr = markup.write(gr)
101 | gr1 = markup.read(dotstr)
102 | dotstr = markup.write(gr1)
103 | gr2 = markup.read(dotstr)
104 | graph_equality(gr1, gr2)
105 | assert len(gr.nodes()) == len(gr1.nodes())
106 | assert len(gr.edges()) == len(gr1.edges())
107 |
108 | def test_xml_hypergraph(self):
109 | gr = testlib.new_hypergraph()
110 | dotstr = markup.write(gr)
111 | gr1 = markup.read(dotstr)
112 | dotstr = markup.write(gr1)
113 | gr2 = markup.read(dotstr)
114 | graph_equality(gr1, gr2)
115 |
116 | if __name__ == "__main__":
117 | unittest.main()
118 |
--------------------------------------------------------------------------------
/python-graph/core/pygraph/algorithms/generators.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | # Zsolt Haraszti
3 | #
4 | # Permission is hereby granted, free of charge, to any person
5 | # obtaining a copy of this software and associated documentation
6 | # files (the "Software"), to deal in the Software without
7 | # restriction, including without limitation the rights to use,
8 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | # copies of the Software, and to permit persons to whom the
10 | # Software is furnished to do so, subject to the following
11 | # conditions:
12 |
13 | # The above copyright notice and this permission notice shall be
14 | # included in all copies or substantial portions of the Software.
15 |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 | # OTHER DEALINGS IN THE SOFTWARE.
24 |
25 |
26 | """
27 | Random graph generators.
28 |
29 | @sort: generate, generate_hypergraph
30 | """
31 |
32 |
33 | # Imports
34 | from pygraph.classes.graph import graph
35 | from pygraph.classes.digraph import digraph
36 | from pygraph.classes.hypergraph import hypergraph
37 | from random import randint, choice, shuffle #@UnusedImport
38 | from time import time
39 |
40 | # Generator
41 |
42 | def generate(num_nodes, num_edges, directed=False, weight_range=(1, 1)):
43 | """
44 | Create a random graph.
45 |
46 | @type num_nodes: number
47 | @param num_nodes: Number of nodes.
48 |
49 | @type num_edges: number
50 | @param num_edges: Number of edges.
51 |
52 | @type directed: bool
53 | @param directed: Whether the generated graph should be directed or not.
54 |
55 | @type weight_range: tuple
56 | @param weight_range: tuple of two integers as lower and upper limits on randomly generated
57 | weights (uniform distribution).
58 | """
59 | # Graph creation
60 | if directed:
61 | random_graph = digraph()
62 | else:
63 | random_graph = graph()
64 |
65 | # Nodes
66 | nodes = range(num_nodes)
67 | random_graph.add_nodes(nodes)
68 |
69 | # Build a list of all possible edges
70 | edges = []
71 | edges_append = edges.append
72 | for x in nodes:
73 | for y in nodes:
74 | if ((directed and x != y) or (x > y)):
75 | edges_append((x, y))
76 |
77 | # Randomize the list
78 | shuffle(edges)
79 |
80 | # Add edges to the graph
81 | min_wt = min(weight_range)
82 | max_wt = max(weight_range)
83 | for i in range(num_edges):
84 | each = edges[i]
85 | random_graph.add_edge((each[0], each[1]), wt = randint(min_wt, max_wt))
86 |
87 | return random_graph
88 |
89 |
90 | def generate_hypergraph(num_nodes, num_edges, r = 0):
91 | """
92 | Create a random hyper graph.
93 |
94 | @type num_nodes: number
95 | @param num_nodes: Number of nodes.
96 |
97 | @type num_edges: number
98 | @param num_edges: Number of edges.
99 |
100 | @type r: number
101 | @param r: Uniform edges of size r.
102 | """
103 | # Graph creation
104 | random_graph = hypergraph()
105 |
106 | # Nodes
107 | nodes = list(map(str, list(range(num_nodes))))
108 | random_graph.add_nodes(nodes)
109 |
110 | # Base edges
111 | edges = list(map(str, list(range(num_nodes, num_nodes+num_edges))))
112 | random_graph.add_hyperedges(edges)
113 |
114 | # Connect the edges
115 | if 0 == r:
116 | # Add each edge with 50/50 probability
117 | for e in edges:
118 | for n in nodes:
119 | if choice([True, False]):
120 | random_graph.link(n, e)
121 |
122 | else:
123 | # Add only uniform edges
124 | for e in edges:
125 | # First shuffle the nodes
126 | shuffle(nodes)
127 |
128 | # Then take the first r nodes
129 | for i in range(r):
130 | random_graph.link(nodes[i], e)
131 |
132 | return random_graph
133 |
--------------------------------------------------------------------------------
/python-graph/core/build/lib.linux-i686-2.6/pygraph/algorithms/generators.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2008-2009 Pedro Matiello
2 | # Zsolt Haraszti
3 | #
4 | # Permission is hereby granted, free of charge, to any person
5 | # obtaining a copy of this software and associated documentation
6 | # files (the "Software"), to deal in the Software without
7 | # restriction, including without limitation the rights to use,
8 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | # copies of the Software, and to permit persons to whom the
10 | # Software is furnished to do so, subject to the following
11 | # conditions:
12 |
13 | # The above copyright notice and this permission notice shall be
14 | # included in all copies or substantial portions of the Software.
15 |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 | # OTHER DEALINGS IN THE SOFTWARE.
24 |
25 |
26 | """
27 | Random graph generators.
28 |
29 | @sort: generate, generate_hypergraph
30 | """
31 |
32 |
33 | # Imports
34 | from pygraph.classes.graph import graph
35 | from pygraph.classes.digraph import digraph
36 | from pygraph.classes.hypergraph import hypergraph
37 | from random import randint, choice, shuffle #@UnusedImport
38 | from time import time
39 |
40 | # Generator
41 |
42 | def generate(num_nodes, num_edges, directed=False, weight_range=(1, 1)):
43 | """
44 | Create a random graph.
45 |
46 | @type num_nodes: number
47 | @param num_nodes: Number of nodes.
48 |
49 | @type num_edges: number
50 | @param num_edges: Number of edges.
51 |
52 | @type directed: bool
53 | @param directed: Whether the generated graph should be directed or not.
54 |
55 | @type weight_range: tuple
56 | @param weight_range: tuple of two integers as lower and upper limits on randomly generated
57 | weights (uniform distribution).
58 | """
59 | # Graph creation
60 | if directed:
61 | random_graph = digraph()
62 | else:
63 | random_graph = graph()
64 |
65 | # Nodes
66 | nodes = range(num_nodes)
67 | random_graph.add_nodes(nodes)
68 |
69 | # Build a list of all possible edges
70 | edges = []
71 | edges_append = edges.append
72 | for x in nodes:
73 | for y in nodes:
74 | if ((directed and x != y) or (x > y)):
75 | edges_append((x, y))
76 |
77 | # Randomize the list
78 | shuffle(edges)
79 |
80 | # Add edges to the graph
81 | min_wt = min(weight_range)
82 | max_wt = max(weight_range)
83 | for i in range(num_edges):
84 | each = edges[i]
85 | random_graph.add_edge((each[0], each[1]), wt = randint(min_wt, max_wt))
86 |
87 | return random_graph
88 |
89 |
90 | def generate_hypergraph(num_nodes, num_edges, r = 0):
91 | """
92 | Create a random hyper graph.
93 |
94 | @type num_nodes: number
95 | @param num_nodes: Number of nodes.
96 |
97 | @type num_edges: number
98 | @param num_edges: Number of edges.
99 |
100 | @type r: number
101 | @param r: Uniform edges of size r.
102 | """
103 | # Graph creation
104 | random_graph = hypergraph()
105 |
106 | # Nodes
107 | nodes = list(map(str, list(range(num_nodes))))
108 | random_graph.add_nodes(nodes)
109 |
110 | # Base edges
111 | edges = list(map(str, list(range(num_nodes, num_nodes+num_edges))))
112 | random_graph.add_hyperedges(edges)
113 |
114 | # Connect the edges
115 | if 0 == r:
116 | # Add each edge with 50/50 probability
117 | for e in edges:
118 | for n in nodes:
119 | if choice([True, False]):
120 | random_graph.link(n, e)
121 |
122 | else:
123 | # Add only uniform edges
124 | for e in edges:
125 | # First shuffle the nodes
126 | shuffle(nodes)
127 |
128 | # Then take the first r nodes
129 | for i in range(r):
130 | random_graph.link(nodes[i], e)
131 |
132 | return random_graph
133 |
--------------------------------------------------------------------------------
/python-graph/tests/unittests-searching.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Unittests for graph.algorithms.searching
27 | """
28 |
29 |
30 | # Imports
31 | import unittest
32 | import pygraph
33 | import pygraph.classes
34 | from pygraph.algorithms.searching import depth_first_search, breadth_first_search
35 | from sys import getrecursionlimit
36 | import testlib
37 |
38 |
39 | class test_depth_first_search(unittest.TestCase):
40 |
41 | def test_dfs_in_empty_graph(self):
42 | gr = pygraph.classes.graph.graph()
43 | st, pre, post = depth_first_search(gr)
44 | assert st == {}
45 | assert pre == []
46 | assert post == []
47 |
48 | def test_dfs_in_graph(self):
49 | gr = testlib.new_graph()
50 | st, pre, post = depth_first_search(gr)
51 | for each in gr:
52 | if (st[each] != None):
53 | assert pre.index(each) > pre.index(st[each])
54 | assert post.index(each) < post.index(st[each])
55 | for node in st:
56 | assert gr.has_edge((st[node], node)) or st[node] == None
57 |
58 | def test_dfs_in_empty_digraph(self):
59 | gr = pygraph.classes.digraph.digraph()
60 | st, pre, post = depth_first_search(gr)
61 | assert st == {}
62 | assert pre == []
63 | assert post == []
64 |
65 | def test_dfs_in_digraph(self):
66 | gr = testlib.new_digraph()
67 | st, pre, post = depth_first_search(gr)
68 | for each in gr:
69 | if (st[each] != None):
70 | assert pre.index(each) > pre.index(st[each])
71 | assert post.index(each) < post.index(st[each])
72 | for node in st:
73 | assert gr.has_edge((st[node], node)) or st[node] == None
74 |
75 | def test_dfs_very_deep_graph(self):
76 | gr = pygraph.classes.graph.graph()
77 | gr.add_nodes(range(0,20001))
78 | for i in range(0,20000):
79 | gr.add_edge((i,i+1))
80 | recursionlimit = getrecursionlimit()
81 | depth_first_search(gr, 0)
82 | assert getrecursionlimit() == recursionlimit
83 |
84 | class test_breadth_first_search(unittest.TestCase):
85 |
86 | def test_bfs_in_empty_graph(self):
87 | gr = pygraph.classes.graph.graph()
88 | st, lo = breadth_first_search(gr)
89 | assert st == {}
90 | assert lo == []
91 |
92 | def test_bfs_in_graph(self):
93 | gr = pygraph.classes.graph.graph()
94 | gr = testlib.new_digraph()
95 | st, lo = breadth_first_search(gr)
96 | for each in gr:
97 | if (st[each] != None):
98 | assert lo.index(each) > lo.index(st[each])
99 | for node in st:
100 | assert gr.has_edge((st[node], node)) or st[node] == None
101 |
102 | def test_bfs_in_empty_digraph(self):
103 | gr = pygraph.classes.digraph.digraph()
104 | st, lo = breadth_first_search(gr)
105 | assert st == {}
106 | assert lo == []
107 |
108 | def test_bfs_in_digraph(self):
109 | gr = testlib.new_digraph()
110 | st, lo = breadth_first_search(gr)
111 | for each in gr:
112 | if (st[each] != None):
113 | assert lo.index(each) > lo.index(st[each])
114 | for node in st:
115 | assert gr.has_edge((st[node], node)) or st[node] == None
116 |
117 | if __name__ == "__main__":
118 | unittest.main()
--------------------------------------------------------------------------------
/src/malware2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/python-graph/core/pygraph/algorithms/searching.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2007-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Search algorithms.
27 |
28 | @sort: breadth_first_search, depth_first_search
29 | """
30 |
31 |
32 | # Imports
33 | from pygraph.algorithms.filters.null import null
34 | from sys import getrecursionlimit, setrecursionlimit
35 |
36 |
37 | # Depth-first search
38 |
39 | def depth_first_search(graph, root=None, filter=null()):
40 | """
41 | Depth-first search.
42 |
43 | @type graph: graph, digraph
44 | @param graph: Graph.
45 |
46 | @type root: node
47 | @param root: Optional root node (will explore only root's connected component)
48 |
49 | @rtype: tuple
50 | @return: A tupple containing a dictionary and two lists:
51 | 1. Generated spanning tree
52 | 2. Graph's preordering
53 | 3. Graph's postordering
54 | """
55 |
56 | recursionlimit = getrecursionlimit()
57 | setrecursionlimit(max(len(graph.nodes())*2,recursionlimit))
58 |
59 | def dfs(node):
60 | """
61 | Depth-first search subfunction.
62 | """
63 | visited[node] = 1
64 | pre.append(node)
65 | # Explore recursively the connected component
66 | for each in graph[node]:
67 | if (each not in visited and filter(each, node)):
68 | spanning_tree[each] = node
69 | dfs(each)
70 | post.append(node)
71 |
72 | visited = {} # List for marking visited and non-visited nodes
73 | spanning_tree = {} # Spanning tree
74 | pre = [] # Graph's preordering
75 | post = [] # Graph's postordering
76 | filter.configure(graph, spanning_tree)
77 |
78 | # DFS from one node only
79 | if (root is not None):
80 | if filter(root, None):
81 | spanning_tree[root] = None
82 | dfs(root)
83 | setrecursionlimit(recursionlimit)
84 | return spanning_tree, pre, post
85 |
86 | # Algorithm loop
87 | for each in graph:
88 | # Select a non-visited node
89 | if (each not in visited and filter(each, None)):
90 | spanning_tree[each] = None
91 | # Explore node's connected component
92 | dfs(each)
93 |
94 | setrecursionlimit(recursionlimit)
95 |
96 | return (spanning_tree, pre, post)
97 |
98 |
99 | # Breadth-first search
100 |
101 | def breadth_first_search(graph, root=None, filter=null()):
102 | """
103 | Breadth-first search.
104 |
105 | @type graph: graph, digraph
106 | @param graph: Graph.
107 |
108 | @type root: node
109 | @param root: Optional root node (will explore only root's connected component)
110 |
111 | @rtype: tuple
112 | @return: A tuple containing a dictionary and a list.
113 | 1. Generated spanning tree
114 | 2. Graph's level-based ordering
115 | """
116 |
117 | def bfs():
118 | """
119 | Breadth-first search subfunction.
120 | """
121 | while (queue != []):
122 | node = queue.pop(0)
123 |
124 | for other in graph[node]:
125 | if (other not in spanning_tree and filter(other, node)):
126 | queue.append(other)
127 | ordering.append(other)
128 | spanning_tree[other] = node
129 |
130 | queue = [] # Visiting queue
131 | spanning_tree = {} # Spanning tree
132 | ordering = []
133 | filter.configure(graph, spanning_tree)
134 |
135 | # BFS from one node only
136 | if (root is not None):
137 | if filter(root, None):
138 | queue.append(root)
139 | ordering.append(root)
140 | spanning_tree[root] = None
141 | bfs()
142 | return spanning_tree, ordering
143 |
144 | # Algorithm
145 | for each in graph:
146 | if (each not in spanning_tree):
147 | if filter(each, None):
148 | queue.append(each)
149 | ordering.append(each)
150 | spanning_tree[each] = None
151 | bfs()
152 |
153 | return spanning_tree, ordering
154 |
--------------------------------------------------------------------------------
/python-graph/core/build/lib.linux-i686-2.6/pygraph/algorithms/searching.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2007-2009 Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 | """
26 | Search algorithms.
27 |
28 | @sort: breadth_first_search, depth_first_search
29 | """
30 |
31 |
32 | # Imports
33 | from pygraph.algorithms.filters.null import null
34 | from sys import getrecursionlimit, setrecursionlimit
35 |
36 |
37 | # Depth-first search
38 |
39 | def depth_first_search(graph, root=None, filter=null()):
40 | """
41 | Depth-first search.
42 |
43 | @type graph: graph, digraph
44 | @param graph: Graph.
45 |
46 | @type root: node
47 | @param root: Optional root node (will explore only root's connected component)
48 |
49 | @rtype: tuple
50 | @return: A tupple containing a dictionary and two lists:
51 | 1. Generated spanning tree
52 | 2. Graph's preordering
53 | 3. Graph's postordering
54 | """
55 |
56 | recursionlimit = getrecursionlimit()
57 | setrecursionlimit(max(len(graph.nodes())*2,recursionlimit))
58 |
59 | def dfs(node):
60 | """
61 | Depth-first search subfunction.
62 | """
63 | visited[node] = 1
64 | pre.append(node)
65 | # Explore recursively the connected component
66 | for each in graph[node]:
67 | if (each not in visited and filter(each, node)):
68 | spanning_tree[each] = node
69 | dfs(each)
70 | post.append(node)
71 |
72 | visited = {} # List for marking visited and non-visited nodes
73 | spanning_tree = {} # Spanning tree
74 | pre = [] # Graph's preordering
75 | post = [] # Graph's postordering
76 | filter.configure(graph, spanning_tree)
77 |
78 | # DFS from one node only
79 | if (root is not None):
80 | if filter(root, None):
81 | spanning_tree[root] = None
82 | dfs(root)
83 | setrecursionlimit(recursionlimit)
84 | return spanning_tree, pre, post
85 |
86 | # Algorithm loop
87 | for each in graph:
88 | # Select a non-visited node
89 | if (each not in visited and filter(each, None)):
90 | spanning_tree[each] = None
91 | # Explore node's connected component
92 | dfs(each)
93 |
94 | setrecursionlimit(recursionlimit)
95 |
96 | return (spanning_tree, pre, post)
97 |
98 |
99 | # Breadth-first search
100 |
101 | def breadth_first_search(graph, root=None, filter=null()):
102 | """
103 | Breadth-first search.
104 |
105 | @type graph: graph, digraph
106 | @param graph: Graph.
107 |
108 | @type root: node
109 | @param root: Optional root node (will explore only root's connected component)
110 |
111 | @rtype: tuple
112 | @return: A tuple containing a dictionary and a list.
113 | 1. Generated spanning tree
114 | 2. Graph's level-based ordering
115 | """
116 |
117 | def bfs():
118 | """
119 | Breadth-first search subfunction.
120 | """
121 | while (queue != []):
122 | node = queue.pop(0)
123 |
124 | for other in graph[node]:
125 | if (other not in spanning_tree and filter(other, node)):
126 | queue.append(other)
127 | ordering.append(other)
128 | spanning_tree[other] = node
129 |
130 | queue = [] # Visiting queue
131 | spanning_tree = {} # Spanning tree
132 | ordering = []
133 | filter.configure(graph, spanning_tree)
134 |
135 | # BFS from one node only
136 | if (root is not None):
137 | if filter(root, None):
138 | queue.append(root)
139 | ordering.append(root)
140 | spanning_tree[root] = None
141 | bfs()
142 | return spanning_tree, ordering
143 |
144 | # Algorithm
145 | for each in graph:
146 | if (each not in spanning_tree):
147 | if filter(each, None):
148 | queue.append(each)
149 | ordering.append(each)
150 | spanning_tree[each] = None
151 | bfs()
152 |
153 | return spanning_tree, ordering
154 |
--------------------------------------------------------------------------------
/python-graph/tests/unittests-filters.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Pedro Matiello
2 | #
3 | # Permission is hereby granted, free of charge, to any person
4 | # obtaining a copy of this software and associated documentation
5 | # files (the "Software"), to deal in the Software without
6 | # restriction, including without limitation the rights to use,
7 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the
9 | # Software is furnished to do so, subject to the following
10 | # conditions:
11 |
12 | # The above copyright notice and this permission notice shall be
13 | # included in all copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | # OTHER DEALINGS IN THE SOFTWARE.
23 | """
24 | python-graph
25 |
26 | Unit tests for python-graph
27 | """
28 |
29 |
30 | # Imports
31 | import unittest
32 | import pygraph
33 | from pygraph.algorithms.searching import depth_first_search, breadth_first_search
34 | from pygraph.classes.graph import graph
35 |
36 | from pygraph.algorithms.filters.radius import radius
37 | from pygraph.algorithms.filters.find import find
38 | import testlib
39 |
40 |
41 | class test_find_filter(unittest.TestCase):
42 |
43 | def test_bfs_in_empty_graph(self):
44 | gr = graph()
45 | st, lo = breadth_first_search(gr, filter=find(5))
46 | assert st == {}
47 | assert lo == []
48 |
49 | def test_bfs_in_graph(self):
50 | gr = testlib.new_graph()
51 | gr.add_node('find-me')
52 | gr.add_edge((0, 'find-me'))
53 | st, lo = breadth_first_search(gr, root=0, filter=find('find-me'))
54 | assert st['find-me'] == 0
55 | for each in st:
56 | assert st[each] == None or st[each] == 0 or st[st[each]] == 0
57 |
58 | def test_bfs_in_digraph(self):
59 | gr = testlib.new_digraph()
60 | gr.add_node('find-me')
61 | gr.add_edge((0, 'find-me'))
62 | st, lo = breadth_first_search(gr, root=0, filter=find('find-me'))
63 | assert st['find-me'] == 0
64 | for each in st:
65 | assert st[each] == None or st[each] == 0 or st[st[each]] == 0
66 |
67 | def test_dfs_in_empty_graph(self):
68 | gr = graph()
69 | st, pre, post = depth_first_search(gr)
70 | assert st == {}
71 | assert pre == []
72 | assert post == []
73 |
74 | def test_dfs_in_graph(self):
75 | gr = testlib.new_graph()
76 | gr.add_node('find-me')
77 | gr.add_node('dont-find-me')
78 | gr.add_edge((0, 'find-me'))
79 | gr.add_edge(('find-me','dont-find-me'))
80 | st, pre, post = depth_first_search(gr, root=0, filter=find('find-me'))
81 | assert st['find-me'] == 0
82 | assert 'dont-find-me' not in st
83 |
84 | def test_dfs_in_digraph(self):
85 | gr = testlib.new_digraph()
86 | gr.add_node('find-me')
87 | gr.add_node('dont-find-me')
88 | gr.add_edge((0, 'find-me'))
89 | gr.add_edge(('find-me','dont-find-me'))
90 | st, pre, post = depth_first_search(gr, root=0, filter=find('find-me'))
91 | assert st['find-me'] == 0
92 | assert 'dont-find-me' not in st
93 |
94 |
95 | class test_radius_filter(unittest.TestCase):
96 |
97 | def testbfs_in_empty_graph(self):
98 | gr = graph()
99 | st, lo = breadth_first_search(gr, filter=radius(2))
100 | assert st == {}
101 | assert lo == []
102 |
103 | def test_bfs_in_graph(self):
104 | gr = testlib.new_graph()
105 | st, lo = breadth_first_search(gr, root=0, filter=radius(3))
106 | for each in st:
107 | assert (st[each] == None or st[each] == 0
108 | or st[st[each]] == 0 or st[st[st[each]]] == 0)
109 |
110 | def test_bfs_in_digraph(self):
111 | gr = testlib.new_digraph()
112 | st, lo = breadth_first_search(gr, root=0, filter=radius(3))
113 | for each in st:
114 | assert (st[each] == None or st[each] == 0
115 | or st[st[each]] == 0 or st[st[st[each]]] == 0)
116 |
117 | def test_dfs_in_empty_graph(self):
118 | gr = graph()
119 | st, pre, post = depth_first_search(gr, filter=radius(2))
120 | assert st == {}
121 | assert pre == []
122 | assert post == []
123 |
124 | def test_dfs_in_graph(self):
125 | gr = testlib.new_graph()
126 | st, pre, post = depth_first_search(gr, root=0, filter=radius(3))
127 | for each in st:
128 | assert (st[each] == None or st[each] == 0
129 | or st[st[each]] == 0 or st[st[st[each]]] == 0)
130 |
131 | def test_dfs_in_digraph(self):
132 | gr = testlib.new_graph()
133 | st, pre, post = depth_first_search(gr, root=0, filter=radius(3))
134 | for each in st:
135 | assert (st[each] == None or st[each] == 0
136 | or st[st[each]] == 0 or st[st[st[each]]] == 0)
137 |
138 | if __name__ == "__main__":
139 | unittest.main()
--------------------------------------------------------------------------------
/src/mcs.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | import xml.etree.ElementTree as et
3 | from pygraph.classes.digraph import digraph
4 |
5 | # Global variables
6 | GTable = []
7 | currentSize = 0
8 | savedmcs = []
9 |
10 | # Checks if the pair of nodes are legal/feasible
11 | def isFeasiblePair (g1, g2, state, node1, node2):
12 | g_unused = state [1]
13 | if not ((node1, node2) in g_unused):
14 | return False
15 | g_used = state [0]
16 | if (node1, node2) in g_used:
17 | return False
18 | if not (g1.has_node (node1) and g2.has_node (node2)):
19 | return False
20 | if g_used == []:
21 | return True
22 | length = len (g_used)
23 | node1_attr = g1.node_attributes (node1)
24 | node2_attr = g2.node_attributes (node2)
25 | node1_label = node1_attr [0][1]
26 | node2_label = node2_attr [0][1]
27 | if node1_label != node2_label:
28 | return False
29 | i = 0
30 | while i < length:
31 | if (node1, node2) != g_used [i]:
32 | if (g1.has_edge ((g_used [i][0], node1)) ^ g2.has_edge ((g_used [i][1], node2))) or (g1.has_edge ((node1, g_used [i][0])) ^ g2.has_edge ((node2, g_used [i][1]))):
33 | return False
34 | i = i + 1
35 | return True
36 |
37 | # Adds the pair of nodes to the subgraph in the state
38 | def addPair (g1, g2, state, node1, node2):
39 | g_subGraph = state [2]
40 | if g_subGraph == None:
41 | g_subGraph = digraph ()
42 | g_subGraph.add_node ((node1, node2), g1.node_attributes (node1))
43 | state [2] = g_subGraph
44 | state [0].append ((node1, node2))
45 | return state
46 | g_subGraph.add_node ((node1, node2), g1.node_attributes (node1))
47 | g_used = state [0]
48 | for g1_node, g2_node in g_used:
49 | if g1.has_edge ((g1_node, node1)) and g2.has_edge ((g2_node, node2)):
50 | g_subGraph_wt = int(g1.edge_weight ((g1_node, node1))) + int(g2.edge_weight ((g2_node, node2)))
51 | g_subGraph.add_edge (((g1_node, g2_node), (node1, node2)), g_subGraph_wt)
52 | elif g1.has_edge ((node1, g1_node)) and g2.has_edge ((node2, g2_node)):
53 | g_subGraph_wt = int(g1.edge_weight ((node1, g1_node))) + int(g2.edge_weight ((node2, g2_node)))
54 | g_subGraph.add_edge (((node1, node2), (g1_node, g2_node)), g_subGraph_wt)
55 |
56 | state [0].append ((node1, node2))
57 | return state
58 |
59 | # Determines if a state is a leaf
60 | def isLeaf (g1, g2, state):
61 | g_used = state [0]
62 | g1_usedlist = [node1 for node1, node2 in g_used]
63 | g2_usedlist = [node2 for node1, node2 in g_used]
64 | g1_iter = g1.__iter__ ()
65 | g2_iter = g2.__iter__ ()
66 | for g1_node in g1_iter:
67 | if g1_node not in g1_usedlist:
68 | return False
69 |
70 | for g2_node in g2_iter:
71 | if g2_node not in g2_usedlist:
72 | return False
73 | return True
74 |
75 | # Checks if the pruningCondition has arrived
76 | def pruningCondition (g1, g2, state):
77 | g1_len = len (g1)
78 | g2_len = len (g2)
79 |
80 | global currentSize
81 | subGraph_len = len (state [2])
82 | states_left = min (g1_len, g2_len) - len (state [0])
83 | if currentSize >= subGraph_len + states_left:
84 | return True
85 |
86 | # Initializes GTable in each run
87 | def init_GTable (g1, g2):
88 | global GTable
89 | g1_iter = [node for node in g1.__iter__ ()]
90 | g2_iter = [node for node in g2.__iter__ ()]
91 | for g1_node in g1_iter:
92 | for g2_node in g2_iter:
93 | GTable.append ((g1_node, g2_node))
94 |
95 | # Update state information
96 | def update (state):
97 | if state [1] == None:
98 | state [1] = GTable [:]
99 | return
100 | g_unused = state [1][:]
101 | g_used = state [0]
102 | g1_usedlist = [g1_node for g1_node, g2_node in g_used]
103 | g2_usedlist = [g2_node for g1_node, g2_node in g_used]
104 |
105 | for g1_node, g2_node in g_unused:
106 | if g1_node in g1_usedlist or g2_node in g2_usedlist:
107 | state [1].remove ((g1_node, g2_node))
108 |
109 | # Saves a state
110 | def savestate (state):
111 | copyof_used = state [0][:]
112 | copyof_unused = state [1][:]
113 | if state [2] == None:
114 | return [copyof_used, copyof_unused, None]
115 | g_subgraph = state [2]
116 | g_subgraph_nodes = g_subgraph.nodes ()
117 | g_subgraph_edges = g_subgraph.edges ()
118 | g_copy = digraph ()
119 | for node in g_subgraph_nodes:
120 | g_copy.add_node (node, g_subgraph.node_attributes(node))
121 | for edge in g_subgraph_edges:
122 | g_copy.add_edge (edge, g_subgraph.edge_weight (edge))
123 |
124 | copy = [copyof_used, copyof_unused, g_copy]
125 | return copy
126 |
127 | # McGregor algorithm to find the maximum common subgraph (mcs) of two graphs
128 | def maxCS (g1, g2, state):
129 | update (state)
130 | global currentSize
131 | global savedmcs
132 | g_state = state
133 | for nodePair in g_state [1]:
134 | g1_node, g2_node = nodePair
135 | if isFeasiblePair (g1, g2, g_state, g1_node, g2_node):
136 | g_copy = savestate (g_state)
137 | new_state = addPair (g1, g2, g_copy, g1_node, g2_node)
138 | if len (new_state [2]) > currentSize:
139 | currentSize = len (new_state [2])
140 | savedmcs.append (new_state [2])
141 | if not isLeaf (g1, g2, new_state) and not pruningCondition (g1, g2, new_state):
142 | maxCS (g1, g2, new_state)
143 |
144 | # Initializes global variables in each run
145 | def init_globalvar ():
146 | global savedmcs
147 | global currentSize
148 | global GTable
149 | savedmcs = []
150 | currentSize = 0
151 | GTable = []
152 |
153 | # Initializes a run of McGregor algo; Returns mcs
154 | def mcsinit (g1, g2):
155 | init_globalvar ()
156 | state = [[], None, None]
157 | init_GTable (g1, g2)
158 | maxCS (g1, g2, state)
159 | g_subgraph = savedmcs.pop()
160 | return g_subgraph
161 |
162 |
--------------------------------------------------------------------------------
/src/wcbg.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | sys.path.append('/usr/lib/pyshared/python2.6')
3 | import gv
4 | import xml.etree.ElementTree as et
5 | from pygraph.classes.digraph import digraph
6 | from pygraph.readwrite.dot import *
7 | from mcs import *
8 | from mincs import *
9 |
10 | # Thresholds -> THETA for Pruning
11 | # -> GAMMA for Similarity
12 | THETA = 0.3
13 | GAMMA = 0.7
14 |
15 | # Kernel objects
16 | kernelObjects = [
17 | "process_call", "process", "load_dll", "load_image", "open_file", "open_key", "get_file_attributes",
18 | "create_directory", "set_file_attributes", "set_file_time", "create_file", "create_mutex", "query_value",
19 | "set_value" "check_for_debugger", "get_system_directory", "create_thread", "create_window", "find_window",
20 | "enum_window", "show_window", "destroy_window", "set_windows_hook", "stored_created_file", "vm_protect",
21 | "connection", "ping", "find_file"
22 | ]
23 |
24 | # Gets pid from a list of attributes
25 | def getPidFromAttr (nodeAttr):
26 | for k, v in nodeAttr:
27 | if k == "pid":
28 | return v
29 | return -1
30 |
31 | # Gets process node with given pid
32 | def getProcNodeWithPid (g, nodeList, pid):
33 | for node in nodeList:
34 | nodeAttr = g.node_attributes (node)
35 | nodePid = getPidFromAttr (nodeAttr)
36 | if nodePid == pid:
37 | return node
38 | return None
39 |
40 | # Gets parent node of a process
41 | def getProcParent (g, node):
42 | if len (g) == 0:
43 | print 'In getproc(): Empty graph'
44 | return None
45 | nodeList = g.__iter__()
46 | nodeAttr = node.attrib.items ()
47 | if nodeAttr == []:
48 | print 'In getproc(): Empty attribute list'
49 | return None
50 |
51 | pid = getPidFromAttr (nodeAttr)
52 | if pid == -1:
53 | print 'In getproc(): No attribute for pid was not found'
54 | return None
55 |
56 | node = getProcNodeWithPid (g, nodeList, pid)
57 | return node
58 |
59 | # Add nodes in the KOBG
60 | def addNodes (g, root):
61 | global nodeid
62 | parent = nodeid
63 | if len (g) == 0:
64 | nodeAttr = [("nodename", root.tag)] + root.attrib.items ()
65 | g.add_node (nodeid, nodeAttr)
66 |
67 | for child in root:
68 | if child.tag in kernelObjects:
69 | if child.tag == "process":
70 | parent = getProcParent (g, child)
71 |
72 | if parent == None:
73 | print 'In addnodes(): Parent node cannot be None'
74 | sys.exit (0)
75 |
76 | attr = [("nodename", child.tag)] + child.attrib.items ()
77 | nodeid = nodeid + 1
78 | g.add_node (nodeid, attr)
79 | g.add_edge ((parent, nodeid))
80 | addNodes (g, child)
81 |
82 | # Initializes KOBG construction
83 | def makeKOBJGraph (filename):
84 | if os.path.isfile (filename):
85 | pass
86 | else:
87 | raise IOError ('File does not exists')
88 |
89 | tree = et.parse (filename)
90 | root = tree.getroot ()
91 | g = digraph ()
92 | addNodes (g, root)
93 | return g
94 |
95 | # Display graphs
96 | #def display (g):
97 | # l = g.nodes ()
98 | # e = g.edges ()
99 | # print l
100 | # print e
101 |
102 | # Returns a set of KOBGs
103 | def makeGraphSet (malwareDir):
104 | graphSet = []
105 | global nodeid
106 | nodeid = 1
107 | for filename in os.listdir (malwareDir):
108 | filename = malwareDir + "/" + filename
109 | g = makeKOBJGraph (filename)
110 | nodeid = nodeid + 1
111 | graphSet.append (g)
112 | return graphSet
113 |
114 | # Function which initiates construction of KOBG of guest malware (only called by ismalware.py)
115 | def makeMalGraph (malwarefile):
116 | global nodeid
117 | nodeid = 1
118 | return makeKOBJGraph (malwarefile)
119 |
120 | # Normalize edge weights
121 | def normalize_weight (g, n):
122 | for edge in g.edges ():
123 | wt = float (g.edge_weight (edge))
124 | g.set_edge_weight (edge, wt/n)
125 | return g
126 |
127 | # Generate a PNG image of the wcbg
128 | def generate_graph_image (wcbg, png_file):
129 | g = digraph ()
130 | g.add_graph (wcbg)
131 | for edge in g.edges ():
132 | g.set_edge_weight (edge, wcbg.edge_weight (edge))
133 | dot = write (g, True)
134 | gvv = gv.readstring (dot)
135 | gv.layout (gvv, 'dot')
136 | png_file = png_file + '.png'
137 | gv.render (gvv, 'png', png_file)
138 |
139 | # Save wcbg of a family by writing it to a file wcbg.digraph (in DOT language)
140 | def save_graph_in_file (g, filename, wt_flag):
141 | f = open (filename, 'w')
142 | copy = digraph ()
143 | copy.add_graph (g)
144 | for node in copy:
145 | copy.add_node_attribute (node, g.node_attributes (node)[0])
146 | for edge in copy.edges ():
147 | copy.set_edge_weight (edge, g.edge_weight (edge))
148 | dot = write (copy, wt_flag)
149 | f.write (dot)
150 | f.close ()
151 |
152 |
153 | # Init function
154 | if __name__ == '__main__':
155 | malwareDir = sys.argv[1]
156 | if os.path.isdir (malwareDir):
157 | pass
158 | else:
159 | raise IOError ('Directory does not exists')
160 |
161 | if os.listdir (malwareDir) == []:
162 | print 'In main: Directory specified is empty'
163 | sys.exit(0)
164 |
165 | gSet = makeGraphSet (malwareDir)
166 | if not gSet:
167 | print 'In main: Graph set is empty'
168 | sys.exit (0)
169 |
170 | index = 0
171 | length = len (gSet)
172 | g = gSet [0]
173 | while index < length:
174 | g, hotpath = mincs (g, gSet[index])
175 | index = index + 1
176 |
177 | setweight (g, hotpath)
178 | wcbg = normalize_weight (g, length)
179 | generate_graph_image (wcbg, 'cluster')
180 | prunegraph (wcbg, THETA)
181 |
182 | hotpath_file = sys.argv [3]
183 | if os.path.isfile (hotpath_file):
184 | pass
185 | else:
186 | raise IOError ('File does not exists')
187 | save_graph_in_file (hotpath, hotpath_file, True)
188 |
189 | wcbg_file = sys.argv [2]
190 | if os.path.isfile (wcbg_file):
191 | pass
192 | else:
193 | raise IOError ('File does not exists')
194 | save_graph_in_file (wcbg, wcbg_file, True)
195 | png_file = wcbg_file.split ('.')[0]
196 | generate_graph_image (wcbg, png_file)
197 | generate_graph_image (hotpath, 'hotpath')
198 |
199 |
200 |
--------------------------------------------------------------------------------
/malwaresamples/Test/mal2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/python-graph/core/pygraph/algorithms/critical.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2009 Pedro Matiello
2 | # Tomaz Kovacic
3 | #
4 | # Permission is hereby granted, free of charge, to any person
5 | # obtaining a copy of this software and associated documentation
6 | # files (the "Software"), to deal in the Software without
7 | # restriction, including without limitation the rights to use,
8 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | # copies of the Software, and to permit persons to whom the
10 | # Software is furnished to do so, subject to the following
11 | # conditions:
12 |
13 | # The above copyright notice and this permission notice shall be
14 | # included in all copies or substantial portions of the Software.
15 |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 | # OTHER DEALINGS IN THE SOFTWARE.
24 |
25 |
26 | """
27 | Critical path algorithms and transitivity detection algorithm.
28 |
29 | @sort: critical_path, transitive_edges
30 | """
31 |
32 |
33 | # Imports
34 | from pygraph.algorithms.cycles import find_cycle
35 | from pygraph.algorithms.traversal import traversal
36 | from pygraph.algorithms.sorting import topological_sorting
37 |
38 | def _intersection(A,B):
39 | """
40 | A simple function to find an intersection between two arrays.
41 |
42 | @type A: List
43 | @param A: First List
44 |
45 | @type B: List
46 | @param B: Second List
47 |
48 | @rtype: List
49 | @return: List of Intersections
50 | """
51 | intersection = []
52 | for i in A:
53 | if i in B:
54 | intersection.append(i)
55 | return intersection
56 |
57 | def transitive_edges(graph):
58 | """
59 | Return a list of transitive edges.
60 |
61 | Example of transitivity within graphs: A -> B, B -> C, A -> C
62 | in this case the transitive edge is: A -> C
63 |
64 | @attention: This function is only meaningful for directed acyclic graphs.
65 |
66 | @type graph: digraph
67 | @param graph: Digraph
68 |
69 | @rtype: List
70 | @return: List containing tuples with transitive edges (or an empty array if the digraph
71 | contains a cycle)
72 | """
73 | #if the graph contains a cycle we return an empty array
74 | if not len(find_cycle(graph)) == 0:
75 | return []
76 |
77 | tranz_edges = [] # create an empty array that will contain all the tuples
78 |
79 | #run trough all the nodes in the graph
80 | for start in topological_sorting(graph):
81 | #find all the successors on the path for the current node
82 | successors = []
83 | for a in traversal(graph,start,'pre'):
84 | successors.append(a)
85 | del successors[0] #we need all the nodes in it's path except the start node itself
86 |
87 | for next in successors:
88 | #look for an intersection between all the neighbors of the
89 | #given node and all the neighbors from the given successor
90 | intersect_array = _intersection(graph.neighbors(next), graph.neighbors(start) )
91 | for a in intersect_array:
92 | if graph.has_edge((start, a)):
93 | ##check for the detected edge and append it to the returned array
94 | tranz_edges.append( (start,a) )
95 | return tranz_edges # return the final array
96 |
97 |
98 | def critical_path(graph):
99 | """
100 | Compute and return the critical path in an acyclic directed weighted graph.
101 |
102 | @attention: This function is only meaningful for directed weighted acyclic graphs
103 |
104 | @type graph: digraph
105 | @param graph: Digraph
106 |
107 | @rtype: List
108 | @return: List containing all the nodes in the path (or an empty array if the graph
109 | contains a cycle)
110 | """
111 | #if the graph contains a cycle we return an empty array
112 | if not len(find_cycle(graph)) == 0:
113 | return []
114 |
115 | #this empty dictionary will contain a tuple for every single node
116 | #the tuple contains the information about the most costly predecessor
117 | #of the given node and the cost of the path to this node
118 | #(predecessor, cost)
119 | node_tuples = {}
120 |
121 | topological_nodes = topological_sorting(graph)
122 |
123 | #all the tuples must be set to a default value for every node in the graph
124 | for node in topological_nodes:
125 | node_tuples.update( {node :(None, 0)} )
126 |
127 | #run trough all the nodes in a topological order
128 | for node in topological_nodes:
129 | predecessors =[]
130 | #we must check all the predecessors
131 | for pre in graph.incidents(node):
132 | max_pre = node_tuples[pre][1]
133 | predecessors.append( (pre, graph.edge_weight( (pre, node) ) + max_pre ) )
134 |
135 | max = 0; max_tuple = (None, 0)
136 | for i in predecessors:#look for the most costly predecessor
137 | if i[1] >= max:
138 | max = i[1]
139 | max_tuple = i
140 | #assign the maximum value to the given node in the node_tuples dictionary
141 | node_tuples[node] = max_tuple
142 |
143 | #find the critical node
144 | max = 0; critical_node = None
145 | for k,v in list(node_tuples.items()):
146 | if v[1] >= max:
147 | max= v[1]
148 | critical_node = k
149 |
150 |
151 | path = []
152 | #find the critical path with backtracking trought the dictionary
153 | def mid_critical_path(end):
154 | if node_tuples[end][0] != None:
155 | path.append(end)
156 | mid_critical_path(node_tuples[end][0])
157 | else:
158 | path.append(end)
159 | #call the recursive function
160 | mid_critical_path(critical_node)
161 |
162 | path.reverse()
163 | return path #return the array containing the critical path
--------------------------------------------------------------------------------