GithubHelp home page GithubHelp logo

graphillion's Introduction

Graphillion - Fast, lightweight library for a huge number of graphs

Japanese page

News

  • Graphillion version 1.0 is released with long-awaited features:
    • Python 3 is supported (Python 2 is as well),
    • Parallel computing is enabled with OpenMP,
    • More efficient configuration (i.e., the edge order) is introduced, and
    • Advanced set operations (e.g., join, meet, quotient) are introduced.
  • Graphillion book was published in April 2015 (sorry, written in Japanese).
  • Graphillion was used in the lecture by Prof. Jun Kawahara at Nara Institute of Science and Technology in January and February 2015.

Features

Graphillion is a Python software package on search, optimization, and enumeration for a graphset, or a set of graphs.

  • Lightweight data structures for handling x-illions of graphs
  • Search, optimization, and enumeration performed over a large number of graphs
  • Used for several applications, e.g., power network evaluation (DNET), railway analysis (Ekillion), as shown in References
  • Efficient implementation extending Python with C/C++
  • Parallel computing with OpenMP
  • Working with existing graph tools like NetworkX
  • Open source MIT license
  • Well tested: more than 600 unit tests
  • Additional benefits from Python: fast prototyping, easy to teach, and multi-platform

We provide fun short movies to answer the following questions.

Overview

Graphillion is a Python library for efficient graphset operations. Unlike existing graph tools such as NetworkX, which are designed to manipulate just a single graph at a time, Graphillion handles a large set of graphs very efficiently. Surprisingly, trillions of trillions of graphs can be processed on a single computer with Graphillion.

You may be curious about an uncommon concept of graphset, but it comes along with any graph or network when you consider multiple subgraphs cut from the graph; e.g., considering possible driving routes on a road map, examining feasible electric flows on a power grid, or evaluating the structure of chemical reaction networks. The number of such subgraphs can be trillions even in a graph with just a few hundred edges, since subgraphs increase exponentially with the graph size. It takes millions of years to examine all subgraphs with a naive approach as demonstrated in the fun movie above; Graphillion is our answer to resolve this issue.

Graphillion allows you to exhaustively but efficiently search a graphset with complex, even nonconvex, constraints. In addition, you can find top-k optimal graphs from the complex graphset, and can also extract common properties among all graphs in the set. Thanks to these features, Graphillion has a variety of applications, including graph database, combinatorial optimization, and graph structure analysis. We will show some practical use cases in the following tutorial, including the evaluation of power distribution networks.

Graphillion can be used freely under the MIT license. It is mainly developed by JST ERATO Minato project. We would really appreciate it if you would refer to our paper and address our contribution to the use of Graphillion in your paper.

Takeru Inoue, Hiroaki Iwashita, Jun Kawahara, and Shin-ichi Minato: "Graphillion: Software Library Designed for Very Large Sets of Labeled Graphs," International Journal on Software Tools for Technology Transfer, Springer, vol.18, issue 1, pp.57-66, February 2016. (pdf)

Graphillion is still under development. We really appreciate any pull request and patch if you add some changes that benefit a wide variety of people.

Now, install Graphillion and go to the tutorial. You'll find its power and utility.

Installing

Requirements

All OSes

  • 64-bit machines
    • It is required to handle large numbers
  • Python version 2.7/3.4 or later
  • NetworkX and Matplotlib - optional for the tutorial
    • NetworkX and Matplotlib are Python modules for creating and drawing a graph. These packages are not required for Graphillion, but used in tutorial. They can be installed by:
$ sudo pip install networkx
$ sudo pip install matplotlib

UNIX including Linux and macOS

  • Python development environment (Python.h)
    • It is included with XCode in macOS, while it can be installed by apt-get install python-dev in Ubuntu.
  • GCC or Clang
    • To build Graphillion, you need gcc version 4.2 or later.
    • For macOS: use Apple official Clang included in XCode, or a memory allocation error might occur.

Windows

Quick install

Just type:

$ sudo pip install graphillion

and an attempt will be made to find and install an appropriate version that matches your operating system and Python version.

For FreeBSD: Graphillion can also be installed by FreeBSD Ports.

Installing from source

You can install from the source by downloading a source archive file (tar.gz or zip) or by checking out the source files from the GitHub source code repository.

Source archive file

  1. Download the source (tar.gz or zip file) from https://github.com/takemaru/graphillion
  2. Unpack and change the directory to the source directory (it should have the file setup.py)
  3. Run python setup.py build to build
  4. (optional) Run python setup.py test -q to execute the tests
  5. Run sudo python setup.py install to install

GitHub repository

  1. Clone the Graphillion repository git clone https://github.com/takemaru/graphillion.git
  2. Change the directory to "graphillion"
  3. Run python setup.py build to build
  4. (optional) Run python setup.py test -q to execute the tests
  5. Run sudo python setup.py install to install

If you don't have permission to install software on your system, you can install it into another directory using the -user, -prefix, or -home flags to setup.py. For example:

$ python setup.py install --prefix=/home/username/python
  or
$ python setup.py install --home=~
  or
$ python setup.py install --user

If you didn't install in the standard Python site-packages directory you will need to set your PYTHONPATH variable to the alternate location. See http://docs.python.org/inst/search-path.html for further details.

Windows

Please see Graphillion for Windows.

Tutorial

If you haven't seen our fun movie, Time with class! Let's count!, please watch it before beginning the tutorial. This movie, which has been watched more than a million times, will convince you of a need for Graphillion. The summary of this tutorial is also provided as a movie, Graphillion: Don't count naively.

We believe that you enjoyed the movies and understood the necessity and features of Graphillion. Now, let's see Graphillion in more detail.

We first introduce the terminology used in Graphillion, as follows:

Term Description Example
vertex any hashable object 1, 'v1', (x, y)
edge tuple of vertices (1, 2)
weighted edge tuple of vertices with weight (1, 2, -1.5)
graph list of (weighted) edges [(1, 2, -1.5), (1, 3)]
set of graphs GraphSet object GraphSet([[(1, 2), (1, 3)], [(1, 2), (2, 3)]])

Vertices (or nodes) can be any hashable object; e.g., a number, a text string, etc. Edges (or links) are defined as a pair of vertices, and a graph is a list of edges; currently, Graphillion supports undirected graphs only. A GraphSet object stores a set of graphs.

Before anything else, we start the Python interpreter and import Graphillion and a helper module; the latter provides some functions like graph creation and drawing for the tutorial.

$ python
>>> from graphillion import GraphSet
>>> import graphillion.tutorial as tl  # helper functions just for the tutorial

Paths on a grid graph

In the beginning, we define our universe. The universe can be any graph, and a graph handled by Graphillion must be a subgraph of this graph. In this tutorial, we use the 8x8 grid graph as our universe (the graph size should be regarded as 9x9, but we follow the definition in the movie).

>>> universe = tl.grid(8, 8)
>>> GraphSet.set_universe(universe)
>>> tl.draw(universe)  # show a pop-up window of our universe

A grid graph

We find all the simple paths between the opposing corners; it took four hours with the supercomputer in the movie.

>>> start = 1
>>> goal = 81
>>> paths = GraphSet.paths(start, goal)
>>> len(paths)  # or paths.len() for very large set
3266598486981642

It's very quick, isn't it? (If you get 980466698, check whether your machine is 32-bit; Graphillion requires 64-bit machines.) Since the paths object contains all the paths, you can enumerate them one by one.

>>> for path in paths:
...     path
... # stop by Ctrl-C because it'll take years
>>> tl.draw(paths.choice())  # show one of the paths

A path from start to goal

Next, in order to demonstrate the filtering or search capability of Graphillion, we choose paths with given conditions. Let's assume that a treasure box and its key are placed on the grid as shown in the figure.

Key and treasure box

We consider all paths on which the key is picked up before reaching the treasure box. We're not allowed to pass through the same place twice. First, search for the paths to the key not through the treasure box, and then select the paths including the key's paths and the treasure box.

>>> key = 64
>>> treasure = 18
>>> paths_to_key = GraphSet.paths(start, key).excluding(treasure)  # paths to the key not through the treasure box
>>> treasure_paths = paths.including(paths_to_key).including(treasure)  # paths to goal via the key and treasure box
>>> len(treasure_paths)
789438891932744
>>> tl.draw(treasure_paths.choice())  # show one of the paths

A path on which the box is opened

Test if all the treasure paths are a subset of the original paths, which connect between the corners.

>>> treasure_paths < paths  # "<" means "subset-of" in Graphillion
True

We conduct statistical processing with random sampling. Graphillion enables you to choose a sample (a graph) from the graphset uniformly randomly. Draw a histogram of "how many turns on the treasure paths" as follows:

>>> i = 0
>>> data = []
>>> for path in treasure_paths.rand_iter():
...     data.append(tl.how_many_turns(path))  # count the number of turns on the path
...     if i == 100: break
...     i += 1
...
>>> tl.hist(data)

Histogram of turn counts

The histogram shows that we make a turn at a corner usually 30-50 times through a single path. Without Graphillion, it would be very hard to investigate such a complicated property for a very large set with 10^14 paths. We also find that the shortest path involves only five turns, which is derived by method min_iter(), an optimizer provided by Graphillion.

>>> for path in treasure_paths.min_iter():
...     print(tl.how_many_turns(path))
...     break  # if not break, multiple paths can be yielded in the ascending order
...
5

As an application of path enumeration, you'll find Ekillion very interesting, which enumerates all JR train paths in Japan's metropolitan and suburbs from startpoint to endpoint.

Power flows on a distribution network

Graphillion works on any graphs other than square grids, and handles other subgraphs than simple paths. Next, we consider a power distribution network in the figure. In this network, we assume that a vertex is a house and an edge is a power line with a switch. The power is provided by the four generators at the corners.

>>> universe = tl.grid(8, 8, 0.37)  # 37 % of edges are randomly removed from 8x8 grid
>>> GraphSet.set_universe(universe)
>>> generators = [1, 9, 73, 81]
>>> tl.draw(universe)

A power distribution network

The power flow is determined by configuring switches, which are placed on each line. If a switch is closed (an edge exists on a graph), the power is transmitted on the line; otherwise, not. The power must be transmitted to all houses, while the flow must not have a loop to protect against short circuits. The power flow, hence, must form a forest, a set of trees, rooted at generators. We find all of such forests as follows: (note that the number, 54060425088, can be different since the network was randomly generated in tl.grid())

>>> forests = GraphSet.forests(roots=generators, is_spanning=True)  # a forest represents a power flow covering all houses without loop
>>> len(forests)
54060425088
>>> tl.draw(forests.choice())

An unsafe power flow

The amount of power transmitted from a single generator should be strictly restricted, so as not to exceed the capacity. The forest shown above may have a very large tree, which implies that the generator sends too much power beyond its capacity. Here, we assume that each generator is allowed to provide power to less than 23 houses. We first find all dangerous cases of too much power, and then select safe flows without the dangerous cases.

>>> too_large_trees = GraphSet()  # empty graphset
>>> for substation in generators:
...     too_large_trees |= GraphSet.trees(root=substation).larger(23)  # unsafe power flows
...
>>> safe_forests = forests.excluding(too_large_trees)  # power flows without the unsafe ones
>>> len(safe_forests)
294859080
>>> tl.draw(safe_forests.choice())

A safe power flow

Since we found all the safe flows, we try to change the network from the current configuration to a safe one using an optimization technique. The current configuration is given by:

>>> closed_switches = (forests - safe_forests).choice()  # sets of closed switches in unsafe power flows
>>> tl.draw(closed_switches)

Current unsafe configuration

New configuration must be one of the safe flows, and must be realized with least switch operations. We put a score (edge weight) on a new switch status if it is inconsistent with the current status, as shown in the table.

current \ next open closed
open 0 -1
closed 0 1
>>> scores = {}  # scores for closed switches in the new configuration (default is 0)
>>> for switch in universe:
...     # if current status is closed then the score is 1, else -1
...     scores[switch] = 1 if switch in closed_switches else -1
...

We try to find a new configuration (forest) with a maximum score. The configuration has a maximum score and can be realized with the least switch operations. Compare it with the current configuration above, and you'll find them quite alike; only eight switch operations are required from the terrible unsafe configuration to a safe one.

>>> for forest in safe_forests.max_iter(scores):
...     tl.draw(forest)
...     break  # if not break, multiple configs are yielded from the highest score
...

Similar but safe configuration

Finally, we investigate serious failures that prevent safe power delivery. We search for minimal blocking sets, or minimal hitting sets more generally, to study such failures. A hitting set is roughly defined such that all the given sets are hit by at least one element in the hitting set; e.g., given {1, 2}, {2, 3}, and {3}, minimal hitting sets are {1, 3} and {2, 3}. A hitting set indicates a critical failure pattern; if power lines in a hitting set are broken, all the flows can't be configured.

>>> failures = safe_forests.blocking().minimal()  # a set of all minimal blocking sets

To help your understanding, remove all lines in a hitting set from the network, and you'll find no safe flow.

>>> failure = failures.choice()  # a hitting set (a set of critical power lines)
>>> for line in failure:
...     safe_forests = safe_forests.excluding(line)  # remove a line in the hitting set
...
>>> len(safe_forests)
0

Small hitting sets (e.g., less than five lines) might imply vulnerability of the network. We now find 767 small failure patterns, which should be investigated carefully.

>>> len(failures.smaller(5))
767

Though actual power distribution networks are much more complicated, we basically rely on the same idea in the study of power distribution networks. Our power loss minimization tool, which optimizes a network with a nonlinear objective function with nonconvex constraints, is available online at DNET.

Creating graphsets

Graphillion provides three ways to create a GraphSet object; with a graph list, edge constraints, and graph types like paths and trees.

Please don't forget to set the universe before working with GraphSet, as mentioned in tutorial. We use the following universe in this section.

>>> from graphillion import GraphSet
>>> universe = [(1, 2), (1, 4), (2, 3), (2, 5), (3, 6), (4, 5), (5, 6)]
>>> GraphSet.set_universe(universe)

Graph list

This is the most straightforward way to create a GraphSet object. Specify a list of graphs and get an object with the graphs.

In the following example, two graphs, one has a single edge and the other has two edges, are given. A GraphSet object with the two graphs is created.

>>> graph1 = [(1, 4)]
>>> graph2 = [(1, 2), (2, 3)]
>>> gs = GraphSet([graph1, graph2])
>>> gs
GraphSet([[(1, 4)], [(1, 2), (2, 3)]])

If no argument is given, it is treated as an empty list [] and an empty GraphSet is returned.

>>> gs = GraphSet()
>>> gs
GraphSet([])

Edge constraints

Edge constraints specify edges to be included or not included in the object. These constraints must be represented by a dict of included or excluded edge lists. Edges not specified in the dict are "don't-care"; they can be included and excluded in the object.

In the following example, edge (1, 4) is included while edges (1, 2) and (2, 3) aren't.

>>> edges1 = [(1, 4)]
>>> edges2 = [(1, 2), (2, 3)]
>>> GraphSet({'include': edges1, 'exclude': edges2})
GraphSet([[(1, 4)], [(1, 4), (2, 5)], [(1, 4), (3, 6)], ...

An empty dict {} means that no constraint is specified, and so a GraphSet including all possible graphs in the universe is returned (let N the number of edges in the universe, 2^N graphs are stored in the new object).

>>> gs = GraphSet({})
>>> len(gs)
128  # 2^7

Graph types

You can specify a graph type, such as paths and trees, and create a GraphSet object that stores all graphs matching the type. Graphillion supports the following graph types:

  • connected components,
  • cliques,
  • trees,
  • forests,
  • cycles, and
  • paths.

For example, paths() method takes two arguments, two end vertices, and finds all paths between the vertices.

>>> paths = GraphSet.paths(1, 6)
>>> paths
GraphSet([[(1, 2), (2, 3), (3, 6)], [(1, 2), (2, 5), (5, 6)], [(1, 4), (4, 5 ...

The arguments are defined for each type, please see the library reference in detail.

Graphillion also provides low-level interface graphs() to specify more complicated graph types; actually, the specific methods call this low-level interface internally. The following example is the same with paths(1, 6).

>>> start = 1
>>> end = 6
>>> zero_or_two = xrange(0, 3, 2)
>>> degree_constraints = {start: 1, end: 1,
...                       2: zero_or_two, 3: zero_or_two,
...                       4: zero_or_two, 5: zero_or_two}
>>> GraphSet.graphs(vertex_groups=[[start, end]],
...                 degree_constraints=degree_constraints,
...                 no_loop=True)
GraphSet([[(1, 2), (2, 3), (3, 6)], [(1, 2), (2, 5), (5, 6)], [(1, 4), (4, 5 ...

If these methods are called object methods, like gs.paths(1, 6), graphs are selected only from the GraphSet object. Please see the library reference for more details. The internal implementation of graphs() is independently available as TdZdd.

Manipulating graphsets

Graphillion provides many operations to manipulate graphs in a GraphSet object. These operations are classified into selection, modification, and comparison; some of them are derived from Python's set methods. Graphillion also provides some iterators and serialization. Please see the library reference for details of each method.

Selection methods

The following methods select graphs from a given GraphSet object (or two given GraphSet objects if binary operation). No new graphs are generated during the operation.

Method Description
gs.union(other(s)), gs (pipe) other Returns a new GraphSet with graphs from gs and all others
gs.intersection(other(s)), gs & other Returns a new GraphSet with graphs common to gs and all others
gs.difference(other(s)), gs - other Returns a new GraphSet with graphs in gs that are not in the others
gs.symmetric_difference(other(s)), gs ^ other Returns a new GraphSet with graphs in either gs or other but not both
gs.quotient(other), gs / other Returns a new GraphSet of quotient.
gs.remainder(other), gs % other Returns a new GraphSet of remainder.
gs.update(other(s)) Updates gs, adding graphs from all others
gs.join(other) Returns a new GraphSet of join between self and other
gs.meet(other) Returns a new GraphSet of meet between self and other
gs.subgraphs(other) Returns a new GraphSet with subgraphs of a graph in other
gs.supergraphs(other) Returns a new GraphSet with supergraphs of a graph in other
gs.non_subgraphs(other) Returns a new GraphSet with graphs that aren't subgraphs of any graph in other
gs.non_supergraphs(other) Returns a new GraphSet with graphs that aren't supergraphs of any graph in other
gs.including(obj) Returns a new GraphSet that includes supergraphs of obj (graphset, graph, edge, or vertex)
gs.excluding(obj) Returns a new GraphSet that doesn't include obj (graphset, graph, edge, or vertex)
gs.included(obj) Returns a new GraphSet with subgraphs of a graph in obj (graphset or graph)
gs.larger(size) Returns a new GraphSet with graphs that have more than size edges
gs.smaller(size) Returns a new GraphSet with graphs that have less than size edges
gs.graph_size(size) Returns a new GraphSet with size edges
gs.minimal() Returns a new GraphSet of minimal graphs
gs.maximal() Returns a new GraphSet of maximal graphs
gs.cost_le(costs, cost_bound) Returns a new GraphSet with subgraphs whose cost is less than or equal to the cost bound
gs.cost_ge(costs, cost_bound) Returns a new GraphSet with subgraphs whose cost is greater than or equal to the cost bound
gs.cost_eq(costs, cost_bound) Returns a new GraphSet with subgraphs whose cost is equal to the cost bound

Creation methods specifying graph types also work as selection methods.

Method Description
gs.graphs(constraints) Returns a GraphSet with graphs under given constraints
gs.connected_components(vertices) Returns a GraphSet of connected components
gs.cliques(k) Returns a GraphSet of k-cliques
gs.trees(root, is_spanning) Returns a GraphSet of trees
gs.forests(roots, is_spanning) Returns a GraphSet of forests, sets of trees
gs.cycles(is_hamilton) Returns a GraphSet of cycles
gs.paths(terminal1, terminal2, is_hamilton) Returns a GraphSet of paths
gs.matchings() Returns a GraphSet of matchings
gs.perfect_matchings() Returns a GraphSet of perfect matchings
gs.partitions(num_comp_lb, num_comp_ub) Returns a GraphSet of partitions
gs.balanced_partitions(weight_list, ratio, lower, upper, num_comps) Returns a GraphSet of balanced_partitions
gs.induced_graphs() Returns a GraphSet of induced graphs
gs.weighted_induced_graphs(weight_list, lower, upper) Returns a GraphSet of induced graphs with weight_list
gs.chordal_graphs() Returns a GraphSet of chordal graphs
gs.bipartite_graphs() Returns a GraphSet of bipartite graphs

Modification or generation methods

The following methods generate new graphs. Some methods modify graphs stored in gs (self), while others return a GraphSet with the newly generated graphs.

Modifying graphs in gs (self)

Method Description
gs.add(graph_or_edge) Adds a given graph to gs, or grafts a given edge to graphs in gs
gs.remove(obj), gs.discard(obj) Removes a given graph, edge, or vertex from gs
gs.flip(edge) Flips the state of a given edge over all graphs in gs
gs.clear() Removes all graphs from gs

Generating new graphs

Method Description
~gs Returns a new GraphSet with graphs not stored in gs
gs.complement() Returns a new GraphSet with complement graphs of gs
gs.blocking() Returns a new GraphSet of all blocking (hitting) sets
gs.hitting() Same as gs.blocking()

Comparison and evaluation methods

The following methods provide comparison or evaluation for GraphSet objects.

Method Description
gs.isdisjoint(other) Returns True if gs has no graphs in common with other
gs.issubset(other) Tests if every graph in gs is in other
gs.issuperset(other) Tests if every graph in other is in gs
obj in gs Returns True if obj (graph, edge, or vertex) is in the gs, False otherwise
len(gs), gs.len() Returns the number of graphs in gs
gs.probability(probabilities) Returns the probability of gs with given probabilities.

Iterators

Graphillion provides various iterators. rand_iter() can be used for random sampling in statistical analysis. min_iter() and max_iter() can be used as optimizers, and they yield not just an optimal graph but top-k graphs. pop() and choice() return a graph in the GraphSet object, though they aren't iterators.

Method Description
iter(gs) Iterates over graphs
gs.rand_iter() Iterates over graphs uniformly randomly
gs.min_iter() Iterates over graphs in the ascending order of weights
gs.max_iter() Iterates over graphs in the descending order of weights
gs.pop() Removes and returns an arbitrary graph from gs
gs.choice() Returns an arbitrary graph from gs

Dumping and loading methods

Graphillion allows you to dump a graphset to a file, and to load it from the file. Dumping and loading operations must be done together with pickling the universe; see the library reference in detail.

Method Description
gs.dump(fp) Serialize gs to a file fp
GraphSet.load(fp) Deserialize a file fp and return the new GraphSet

Python's set methods

Graphillion supports Python's set methods. These methods treat a graph just as an element of the set and don't care the graph structure.

  • gs.union(other), gs | other,
  • gs.intersection(other), gs & other,
  • gs.difference(other), gs - other,
  • gs.symmetric_difference(other), gs ^ other,
  • gs.update(other), gs |= other,
  • gs.add(graph),
  • gs.remove(graph), gs.discard(graph),
  • gs.clear(),
  • gs.isdisjoint(gs),
  • gs.issubset(gs),
  • gs.issuperset(gs),
  • graph in gs,
  • len(gs),
  • gs.pop(), and
  • gs.copy().

Parallel computing

Graphillion runs in parallel using OpenMP, an API supporting multi-platform shared memory multiprocessing. To enjoy parallel computing, specify the number of CPU cores to use by the environmental variable OMP_NUM_THREADS. An example of using four cores is:

$ OMP_NUM_THREADS=4 python your_graphillion_script.py

Currently, the following methods can be parallelized:

  • GraphSet.graphs(constraints)
  • GraphSet.connected_components(vertices)
  • GraphSet.cliques(k)
  • GraphSet.trees(root, is_spanning)
  • GraphSet.forests(roots, is_spanning)
  • GraphSet.cycles(is_hamilton)
  • GraphSet.paths(terminal1, terminal2, is_hamilton)
  • GraphSet.matchings()
  • GraphSet.perfect_matchings()
  • GraphSet.induced_graphs()

Working with NetworkX

Graphillion transparently works with existing graph tools like NetworkX. Any object like networkx.Graph can be recognized as a graph in Graphillion, while an edge list is a graph by default.

Define two methods that associate a new graph object with an edge list; one method is used for converting an edge list into a graph object, and the other is vice versa. We show an example for NetworkX.

>>> import networkx as nx
>>> # for NetworkX version 1.x
...
>>> GraphSet.converters['to_graph'] = nx.Graph
>>> GraphSet.converters['to_edges'] = nx.Graph.edges
>>> # for NetworkX version 2.x
...
>>> GraphSet.converters['to_graph'] = nx.from_edgelist
>>> GraphSet.converters['to_edges'] = nx.to_edgelist

We can now pass NetworkX's graph objects to Graphillion like this.

>>> g = nx.Graph(...)  # create a graph by NetworkX
>>> GraphSet.set_universe(g)

We also receive NetworkX's graph objects from Graphillion.

>>> gs.choice()  # return a NeworkX's graph object
<networkx.classes.graph.Graph object at 0x100456d10>

For visualizing graphs, NetworkX provides an interface to Matplotlib plotting package along with several node positioning algorithms.

>>> nx.draw(gs.choice())
>>> import matplotlib.pyplot as plt
>>> plt.show()  # show a pop-up window

Library reference

The library reference can be browsed using pydoc in your terminal window:

$ pydoc graphillion.GraphSet

Or in HTML:

$ pydoc -w graphillion.GraphSet

Example code

Example code is found here.

Future work

  • More efficient internal data conversion
  • More efficient search algorithms for optimization
  • Nonlinear objective functions in optimization
  • More efficient algorithms for hitting sets and cliques
  • Sync the internal random seed with Python's random
  • Documentation on performance
  • Multithreading
  • Garbage collections
  • Mailing lists
  • Coding rules
  • Developer documents

References

About Graphillion and its internals

  • Takeru Inoue, Hiroaki Iwashita, Jun Kawahara, and Shin-ichi Minato: "Graphillion: Software Library Designed for Very Large Sets of Labeled Graphs," International Journal on Software Tools for Technology Transfer, Springer, vol.18, issue 1, pp.57-66, February 2016. (doi)

  • Yuma Inoue and Shin-ichi Minato, "Acceleration of ZDD Construction for Subgraph Enumeration via Path-width Optimization," TCS Technical Reports, TCS-TR-A-16-80, October 2016. (pdf)

  • Hana Ito, Yuma Inoue, and Shin-ichi Minato, "Experiments and Considerations on Variable Ordering in Top-Down Construction of ZDDs," Forum on Information Technology, vol.14, no.1, pp.115-116, September 2015. (pdf, in Japanese)

  • JST ERATO Minato Discrete Structure Manipulation System Project, "High-Speed Graph Enumeration Algorithms," Morikita Publishing, April 2015. (amazon, in Japanese)

  • Jun Kawahara, "Graphillion: Python library handling a huge number of subgraphs," Python Seminer, December 2014. (pdf, in Japanese)

  • Jun Kawahara, Takeru Inoue, Hiroaki Iwashita and Shin-ichi Minato, "Frontier-based Search for Enumerating All Constrained Subgraphs with Compressed Representation," Hokkaido University, Division of Computer Science, TCS Technical Reports, TCS-TR-A-14-76, September 2014. (pdf)

  • Takeru Inoue, "Graphillion updates," JST ERATO Minato project seminar, February 2014. (pdf)

  • Hiroaki Iwashita and Shin-ichi Minato, "Efficient Top-Down ZDD Construction Techniques Using Recursive Specifications," TCS Technical Reports, TCS-TR-A-13-69, December 2013. (pdf)

  • Takeru Inoue, Hiroaki Iwashita, Jun Kawahara, and Shin-ichi Minato, "Graphillion: ZDD-based Software Library for Very Large Sets of Graphs," Proc. of the 18th Workshop on Synthesis And System Integration of Mixed Information Technologies (SASIMI), Poster Presentation, October 2013. (html)

  • Takeru Inoue, "Graphillion: Python module for very large sets of graphs," PyCon APAC, September 2013.

  • Takeru Inoue, "[Invited Talk] Graphillion: Software Library for Very Large Sets of Graphs," Technical Report of IEICE, vol.113, no.140, IN2013-43, pp.43-47, July 2013. (pdf, in Japanese)

  • Takahisa Toda, "Hypergraph Transversal Computation with Binary Decision Diagrams," Proc. of 12th International Symposium on Experimental Algorithms (SEA), pp.91-102, June 2013. (doi)

  • Graphillion for Windows

  • TdZdd - A top-down/breadth-first decision diagram manipulation framework

  • GGCount - A C++ program for fast computation of the number of paths in a grid graph

Using Graphillion or related algorithms

  • DNET - Distribution Network Evaluation Tool

  • Ekillion - Enumerating all JR train paths in Japan

  • Teru Ohashi and Tatsuhiro Tsuchiya, "Generating High Strength Test Suites for Combinatorial Interaction Testing Using ZDD-Based Graph Algorithms," Proc. of IEEE 22nd Pacific Rim International Symposium on Dependable Computing (PRDC), pp.78-85, January 2017. (doi)

  • Daisuke Yoshino and Eiji Hato, "Fast Enumeration Method of Travel Route of DRT Using Zero-suppressed Binary Decision Diagram," Journal of Japan Society of Civil Engineers, vol.72, no.5, pp.1229-1239, December 2016. (doi)

  • Jun Kawahara, Toshiki Saitoh, Hirofumi Suzuki, and Ryo Yoshinaka, "Solving the Longest Oneway-Ticket Problem and Enumerating Letter Graphs by Augmenting the Two Representative Approaches with ZDDs," Proc. of the Computational Intelligence in Information Systems Conference (CIIS), pp.294-305, November 2016. (doi)

  • Yuji Takenobu, Norihito Yasuda, Shunsuke Kawano, Yasuhiro Hayashi, and Shin-ichi Minato, "Evaluation of Annual Energy Loss Reduction Based on Reconfiguration Scheduling," IEEE Transactions on Smart Grid, September 2016. (doi)

  • Masashi Hashimoto, Tomihiro Utsumi, and Takeru Inoue, "[Invited Talk] Availability Analyses for Photonic Network by Minimal Blocking Set using ZDD based Graphillion," Technical Report of IEICE, vol.116, no.205, PN2016-22, pp.45-51, September 2016. (html, in Japanese)

  • Y. Takenobu, S. Kawano, Y. Hayashi, N. Yasuda and S. Minato, "Maximizing hosting capacity of distributed generation by network reconfiguration in distribution system," Proc. of Power Systems Computation Conference (PSCC), pp.1-7, June 2016. (doi)

  • Subaru Fukuda and Naoshi Sakamoto, "A Failure Estimation System for Networks Applying Graphillion," Technical Report of IEICE, vol.115, no.483, NS2015-212, pp.255-260, March 2016. (html, in Japanese)

  • Arthur Choi, Nazgol Tavabi, and Adnan Darwiche, "Structured Features in Naive Bayes Classification," AAAI, pp.3233-3240, February 2016. (pdf)

  • Ikki Fujiwara, Satoshi Fujita, Koji Nakano, Takeru Inoue, and Michihiro Koibuchi, "Let's Solve the Order/Degree Problem to Make the Lowest-latency Interconnections," Technical Report of IEICE, vol.115, no.174, CPSY2015-38, pp.223-228, August 2015. (html, in Japanese)

  • Atsushi Takizawa, Yushi Miyata, and Naoki Katoh, "Enumeration of Floor Plans Based on a Zero-Suppressed Binary Decision Diagram," International Journal of Architectural Computing, vol.13, no.1, pp.25-44, March 2015. (pdf)

  • Hiroyuki Hanada, Shuhei Denzumi, Yuma Inoue, Hiroshi Aoki, Norihito Yasuda, Shogo Takeuchi, and Shin-ichi Minato, "Enumerating Eulerian Trails via Hamiltonian Path Enumeration," International Workshop on Algorithms and Computation (WALCOM), pp.161-174, February 2015. (doi)

  • Takeru Inoue, Norihito Yasuda, Shunsuke Kawano, Yuji Takenobu, Shin-ichi Minato, and Yasuhiro Hayashi, "Distribution Network Verification for Secure Restoration by Enumerating All Critical Failures," IEEE Transactions on Smart Grid, October 2014. (doi)

  • Takeru Inoue, Keiji Takano, Takayuki Watanabe, Jun Kawahara, Ryo Yoshinaka, Akihiro Kishimoto, Koji Tsuda, Shin-ichi Minato, and Yasuhiro Hayashi, "Distribution Loss Minimization with Guaranteed Error Bound," IEEE Transactions on Smart Grid, vol.5, issue.1, pp.102-111, January 2014. (doi)

  • Ryo Yoshinaka, Toshiki Saitoh, Jun Kawahara, Koji Tsuruma, Hiroaki Iwashita, and Shin-ichi Minato, "Finding All Solutions and Instances of Numberlink and Slitherlink by ZDDs," Algorithms 2012, 5(2), pp.176-213, 2012. (doi)

Citing Graphillion

  • Arthur Choi, Yujia Shen, and Adnan Darwiche, "Tractability in Structured Probability Spaces," Proc. of Advances in Neural Information Processing Systems (NIPS), pp.3480-3488, 2017.
  • Michihiro Koibuchi, Ikki Fujiwara, Fabien Chaix, and Henri Casanova, "Towards Ideal Hop Counts in Interconnection Networks with Arbitrary Size," Proc. of 4th International Symposium on Computing and Networking (CANDAR), pp.188-194, November 2016. (doi)
  • Shin-ichi Minato, "Power of Enumeration -- BDD/ZDD-Based Techniques for Discrete Structure Manipulation," IEEE 46th International Symposium on Multiple-Valued Logic (ISMVL), pp.143-143, July 2016. (doi)
  • Masahiro Kawahara, Takehide Soh, Mutsunori Banbara, and Naoyuki Tamura, "Constraint Models for SAT-based Subgraph Search," Proc. of the 30th Annual Conference of the Japanese Society for Artificial Intelligence, 1D4-OS-02a-4, June 2016. (pdf, in Japanese)
  • Shin-ichi Minato, "Counting by ZDD," Encyclopedia of Algorithms, Springer, pp.454-458, April 2016. (doi)
  • Yasuhiro Takei, Masanori Hariyama, and Michitaka Kameyama, "Evaluation of an FPGA-Based Shortest-Path-Search Accelerator," Proc. of the International Conference on Parallel and Distributed Processing Techniques and Applications (PDPTA), pp.613-617, 2015. (pdf)
  • Tsutomu Sasao and Jon T. Butler, "Applications of Zero-Suppressed Decision Diagrams," Morgan & Claypool Publishers, November 2014. (doi)

graphillion's People

Contributors

0kina avatar duerrp avatar jbking avatar junkawahara avatar o-kei avatar pombredanne avatar qny31541 avatar seanlaw avatar takemaru avatar the-alchemist avatar xu-cheng avatar zaki-joho avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

graphillion's Issues

Creating a Graphset Using a Toy Example

Hi @takemaru! I hope you are well. Can you please help me understand if Graphillion could be used to represent and solve the following toy problem?

Let's say that I have a discrete function that can be described as $2x_{0}+3x_{1}+5x_{2}+5x_{3} \ge 7$, where $x_{i} \in \set{0,1}$. Once I find all of the combinations of $(x_{0}, x_{1}, x_{2}, x_{3})$ that satisfy this constraint, I would like to find the shortest path that minimizes the objective function $2x_{0}-3x_{1}+4x_{2}+6x_{3}$.

For example, $(x_{0}, x_{1}, x_{2}, x_{3}) = (0, 1, 1, 0)$ would satisfy the function since $2\cdot0+3\cdot0+5\cdot1+5\cdot1 = 10$, which is greater than or equal to $7$. Next, substituting $(x_{0}, x_{1}, x_{2}, x_{3}) = (0, 1, 1, 0)$ into the objective function would result in a path length of $2\cdot0-3\cdot0+4\cdot1+6\cdot1=10$. However, this is only one solution and it is also not the shortest path!

Can you please tell me the best way to:

  1. Construct the graphset for this problem using Graphillion
    • I believe that this step may be referred to as "enumeration" in the literature. If I understand correctly, this can be done naively by iterating through $2^{n}$ combinations (e.g., for $(x_{0}, x_{1}, x_{2}, x_{3}),$ there would be $2^{4} = 16$ combinations) but this is very inefficient for large $n$. Perhaps, this is where the "frontier-based search" comes in but I don't understand what inputs I need to provide to Graphillion to do this automatically
  2. Find all values of $(x_{0}, x_{1}, x_{2}, x_{3})$ that satisfy $2x_{0}+3x_{1}+5x_{2}+5x_{3} \ge 7$
  3. Find the 3 shortest paths (computed from $2x_{0}-3x_{1}+4x_{2}+6x_{3}$) using the solutions identified in step 2

I'm having some conceptual trouble setting this up using the Graphillion framework. I understand that I could try to enumerate all of combinations of $(x_{0}, x_{1}, x_{2}, x_{3})$ but, in my real use case, I may have as many as $(x_{0}, x_{1}, ..., x_{1000})$. Also, $x_{i} \in \set{0, ..., 25}$ and so I was hoping that Graphillion may be a good use case.

Any help, suggestions, or code examples using Graphillion would be greatly appreciated!

Extend parameters for large graphs

To support large universes, we should change the following parameters in the next release.

src/SAPPOROBDD/bddc.c:134
const int BDD_RecurLimit = 65536;

src/SAPPOROBDD/bddc.h:41

define B_VAR_WIDTH 20U

Feature request: minimum cut function

Hello,
I know that NetworkX has a direct function to implement min cut max flow algorithm (minimum_cut()). It works well with small graphs but fails for large graphs.

I checked Graphillion and found that it can use graphs from NetworkX but I couldn't find a direct minimum_cut() function.

This is a feature request to add this functionality in Graphillion.

Clang compiler warnings on FreeBSD

Reporting clang compiler warnings at your request :)

I have complete build logs of graphillion on FreeBSD 8.x through 10.x on both amd64/i386 too if you would like them.

Operating System: FreeBSD 9.1-STABLE amd64 r250655
Compiler: clang version 3.2 (tags/RELEASE_32/final 170710) 20121221

Build log:

[user@9-STABLE-amd64:/usr/home/user/repos/freebsd/ports/graphics/py-graphillion] make
===>  License MIT accepted by the user
===>   py27-graphillion-0.93 depends on file: /usr/local/sbin/pkg - found
===> Fetching all distfiles required by py27-graphillion-0.93 for building
===>  Extracting for py27-graphillion-0.93
=> SHA256 Checksum OK for graphillion-0.93.tar.gz.
===>  Patching for py27-graphillion-0.93
===>  Applying FreeBSD patches for py27-graphillion-0.93
===>   py27-graphillion-0.93 depends on file: /usr/local/bin/easy_install-2.7 - found
===>   py27-graphillion-0.93 depends on file: /usr/local/bin/python2.7 - found
===>  Configuring for py27-graphillion-0.93
running config
===>  Building for py27-graphillion-0.93
running setopt
Writing setup.cfg
running setopt
Writing setup.cfg
running setopt
Writing setup.cfg
running setopt
Writing setup.cfg
running bdist_egg
running egg_info
creating Graphillion.egg-info
writing Graphillion.egg-info/PKG-INFO
writing top-level names to Graphillion.egg-info/top_level.txt
writing dependency_links to Graphillion.egg-info/dependency_links.txt
writing manifest file 'Graphillion.egg-info/SOURCES.txt'
reading manifest file 'Graphillion.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'Graphillion.egg-info/SOURCES.txt'
installing library code to build/bdist.freebsd-9.1-STABLE-amd64/egg
running install_lib
running build_py
creating lib.freebsd-9.1-STABLE-amd64
creating lib.freebsd-9.1-STABLE-amd64/graphillion
copying graphillion/__init__.py -> lib.freebsd-9.1-STABLE-amd64/graphillion
copying graphillion/graphset.py -> lib.freebsd-9.1-STABLE-amd64/graphillion
copying graphillion/tutorial.py -> lib.freebsd-9.1-STABLE-amd64/graphillion
copying graphillion/release.py -> lib.freebsd-9.1-STABLE-amd64/graphillion
copying graphillion/setset.py -> lib.freebsd-9.1-STABLE-amd64/graphillion
running build_ext
building '_graphillion' extension
creating temp.freebsd-9.1-STABLE-amd64-2.7
creating temp.freebsd-9.1-STABLE-amd64-2.7/src
creating temp.freebsd-9.1-STABLE-amd64-2.7/src/graphillion
creating temp.freebsd-9.1-STABLE-amd64-2.7/src/SAPPOROBDD
clang -DNDEBUG -O2 -pipe -fno-strict-aliasing -O2 -pipe -fno-strict-aliasing -fPIC -Isrc -I/usr/local/include/python2.7 -c src/pygraphillion.cc -o temp.freebsd-9.1-STABLE-amd64-2.7/src/pygraphillion.o
clang -DNDEBUG -O2 -pipe -fno-strict-aliasing -O2 -pipe -fno-strict-aliasing -fPIC -Isrc -I/usr/local/include/python2.7 -c src/graphillion/graphset.cc -o temp.freebsd-9.1-STABLE-amd64-2.7/src/graphillion/graphset.o
In file included from src/graphillion/graphset.cc:32:
In file included from src/subsetting/dd/ZddStructure.hpp:14:
In file included from src/subsetting/dd/DdBuilder.hpp:20:
In file included from src/subsetting/dd/DdNodeTable.hpp:17:
src/subsetting/dd/../util/MessageHandler.hpp:118:37: warning: adding 'int' to a string does not append to the string [-Wstring-plus-int]
        name = s.empty() ? "level-" + indentLevel : s;
                           ~~~~~~~~~^~~~~~~~~~~~~
src/subsetting/dd/../util/MessageHandler.hpp:118:37: note: use array indexing to silence this warning
        name = s.empty() ? "level-" + indentLevel : s;
                                    ^
                           &        [            ]
src/subsetting/dd/../util/MessageHandler.hpp:118:37: warning: adding 'int' to a string does not append to the string [-Wstring-plus-int]
        name = s.empty() ? "level-" + indentLevel : s;
                           ~~~~~~~~~^~~~~~~~~~~~~
src/subsetting/dd/ZddStructure.hpp:164:12: note: in instantiation of member function 'MessageHandler_<cerr>::begin' requested here
        mh.begin("reduction") << " ";
           ^
src/subsetting/dd/../util/MessageHandler.hpp:118:37: note: use array indexing to silence this warning
        name = s.empty() ? "level-" + indentLevel : s;
                                    ^
                           &        [            ]
In file included from src/graphillion/graphset.cc:32:
In file included from src/subsetting/dd/ZddStructure.hpp:14:
In file included from src/subsetting/dd/DdBuilder.hpp:20:
In file included from src/subsetting/dd/DdNodeTable.hpp:18:
src/subsetting/dd/../util/MyVector.hpp:177:21: warning: destination for this 'memcpy' call is a pointer to dynamic class 'MyList<DdBuilderBase::SpecNode, 1000>'; vtable pointer
      will be overwritten [-Wdynamic-class-memaccess]
        std::memcpy(tmp, array_, size_ * sizeof(T));
        ~~~~~~~~~~~ ^
src/subsetting/dd/../util/MyVector.hpp:188:9: note: in instantiation of member function 'MyVector<MyList<DdBuilderBase::SpecNode, 1000> >::shrink' requested here
        shrink(0);
        ^
src/subsetting/dd/../util/MyVector.hpp:87:9: note: in instantiation of member function 'MyVector<MyList<DdBuilderBase::SpecNode, 1000> >::clear' requested here
        clear();
        ^
src/subsetting/dd/DdBuilder.hpp:79:7: note: in instantiation of member function 'MyVector<MyList<DdBuilderBase::SpecNode, 1000> >::~MyVector' requested here
class DdBuilder: DdBuilderBase {
      ^
src/subsetting/dd/ZddStructure.hpp:68:9: note: in instantiation of function template specialization 'ZddStructure::construct_<SapporoZdd>' requested here
        construct_(spec.entity());
        ^
src/graphillion/graphset.cc:90:14: note: in instantiation of function template specialization 'ZddStructure::ZddStructure<SapporoZdd>' requested here
    dd = new ZddStructure(f);
                                    ^
                           &        [            ]
In file included from src/graphillion/setset.cc:32:
In file included from src/subsetting/dd/PathCounter.hpp:22:
src/subsetting/dd/../util/MyVector.hpp:177:21: warning: destination for this 'memcpy' call is a pointer to dynamic class 'MyList<unsigned long, 1000>'; vtable pointer will be
      overwritten [-Wdynamic-class-memaccess]
        std::memcpy(tmp, array_, size_ * sizeof(T));
        ~~~~~~~~~~~ ^
src/subsetting/dd/../util/MyVector.hpp:188:9: note: in instantiation of member function 'MyVector<MyList<unsigned long, 1000> >::shrink' requested here
        shrink(0);
        ^
src/subsetting/dd/../util/MyVector.hpp:87:9: note: in instantiation of member function 'MyVector<MyList<unsigned long, 1000> >::clear' requested here
        clear();
        ^
src/subsetting/dd/PathCounter.hpp:219:33: note: in instantiation of member function 'MyVector<MyList<unsigned long, 1000> >::~MyVector' requested here
        MyVector<MyList<Word> > vnodeTable(n + 1);
                                ^
src/subsetting/dd/PathCounter.hpp:411:22: note: in instantiation of member function 'PathCounter<SapporoZdd>::countFast' requested here
    return fast ? pc.countFast() : pc.count();
                     ^
src/graphillion/setset.cc:270:10: note: in instantiation of function template specialization 'countPaths<SapporoZdd>' requested here
  return countPaths(f, true);
         ^
src/subsetting/dd/../util/MyVector.hpp:177:21: note: explicitly cast the pointer to silence this warning
        std::memcpy(tmp, array_, size_ * sizeof(T));
                    ^
                    (void*)
src/subsetting/dd/../util/MyVector.hpp:177:21: warning: destination for this 'memcpy' call is a pointer to dynamic class 'MyHashTable<unsigned long *,
      PathCounter<SapporoZdd>::Hasher, PathCounter<SapporoZdd>::Hasher>'; vtable pointer will be overwritten [-Wdynamic-class-memaccess]
        std::memcpy(tmp, array_, size_ * sizeof(T));
        ~~~~~~~~~~~ ^
src/subsetting/dd/../util/MyVector.hpp:188:9: note: in instantiation of member function 'MyVector<MyHashTable<unsigned long *, PathCounter<SapporoZdd>::Hasher,
      PathCounter<SapporoZdd>::Hasher> >::shrink' requested here
        shrink(0);
        ^
src/subsetting/dd/../util/MyVector.hpp:87:9: note: in instantiation of member function 'MyVector<MyHashTable<unsigned long *, PathCounter<SapporoZdd>::Hasher,
      PathCounter<SapporoZdd>::Hasher> >::clear' requested here
        clear();
        ^
src/subsetting/dd/PathCounter.hpp:104:29: note: in instantiation of member function 'MyVector<MyHashTable<unsigned long *, PathCounter<SapporoZdd>::Hasher,
      PathCounter<SapporoZdd>::Hasher> >::~MyVector' requested here
        MyVector<UniqTable> uniqTable;
                            ^
src/subsetting/dd/PathCounter.hpp:411:39: note: in instantiation of member function 'PathCounter<SapporoZdd>::count' requested here
    return fast ? pc.countFast() : pc.count();
                                      ^
src/graphillion/setset.cc:270:10: note: in instantiation of function template specialization 'countPaths<SapporoZdd>' requested here
  return countPaths(f, true);
         ^
src/subsetting/dd/../util/MyVector.hpp:177:21: note: explicitly cast the pointer to silence this warning
        std::memcpy(tmp, array_, size_ * sizeof(T));
                    ^
                    (void*)
4 warnings generated.
clang -DNDEBUG -O2 -pipe -fno-strict-aliasing -O2 -pipe -fno-strict-aliasing -fPIC -Isrc -I/usr/local/include/python2.7 -c src/graphillion/util.cc -o temp.freebsd-9.1-STABLE-amd64-2.7/src/graphillion/util.o
clang -DNDEBUG -O2 -pipe -fno-strict-aliasing -O2 -pipe -fno-strict-aliasing -fPIC -Isrc -I/usr/local/include/python2.7 -c src/graphillion/zdd.cc -o temp.freebsd-9.1-STABLE-amd64-2.7/src/graphillion/zdd.o
clang -DNDEBUG -O2 -pipe -fno-strict-aliasing -O2 -pipe -fno-strict-aliasing -fPIC -Isrc -I/usr/local/include/python2.7 -c src/SAPPOROBDD/bddc.c -o temp.freebsd-9.1-STABLE-amd64-2.7/src/SAPPOROBDD/bddc.o
src/SAPPOROBDD/bddc.c:564:28: warning: format specifies type 'long long' but the argument has type 'bddp' (aka 'unsigned long') [-Wformat]
  fprintf(strm, B_BDDP_FD, bddvsize(p, n));
                           ^~~~~~~~~~~~~~
src/SAPPOROBDD/bddc.c:576:35: warning: format specifies type 'long long' but the argument has type 'bddp' (aka 'unsigned long') [-Wformat]
    else fprintf(strm, B_BDDP_FD, p[i]);
                                  ^~~~
src/SAPPOROBDD/bddc.c:641:15: warning: promoted type 'int' of K&R function parameter is not compatible with the parameter type 'unsigned char' declared in a previous prototype
      [-Wknr-promoted-parameter]
unsigned char op;
              ^
src/SAPPOROBDD/bddc.h:125:46: note: previous declaration is here
extern bddp   bddrcache B_ARG((unsigned char op, bddp f, bddp g));
                                             ^
src/SAPPOROBDD/bddc.h:36:20: note: expanded from macro 'B_ARG'
#  define B_ARG(a) a       /* ANSI C style */
                   ^
src/SAPPOROBDD/bddc.c:655:15: warning: promoted type 'int' of K&R function parameter is not compatible with the parameter type 'unsigned char' declared in a previous prototype
      [-Wknr-promoted-parameter]
unsigned char op;
              ^
src/SAPPOROBDD/bddc.h:127:36: note: previous declaration is here
              B_ARG((unsigned char op, bddp f, bddp g, bddp h));
                                   ^
src/SAPPOROBDD/bddc.h:36:20: note: expanded from macro 'B_ARG'
#  define B_ARG(a) a       /* ANSI C style */
                   ^
src/SAPPOROBDD/bddc.c:1570:15: warning: promoted type 'int' of K&R function parameter is not compatible with the parameter type 'unsigned char' declared in a previous prototype
      [-Wknr-promoted-parameter]
unsigned char op, skip;
              ^
src/SAPPOROBDD/bddc.c:220:56: note: previous declaration is here
static bddp apply B_ARG((bddp f, bddp g, unsigned char op, unsigned char skip));
                                                       ^
src/SAPPOROBDD/bddc.h:36:20: note: expanded from macro 'B_ARG'
#  define B_ARG(a) a       /* ANSI C style */
                   ^
src/SAPPOROBDD/bddc.c:1570:19: warning: promoted type 'int' of K&R function parameter is not compatible with the parameter type 'unsigned char' declared in a previous prototype
      [-Wknr-promoted-parameter]
unsigned char op, skip;
                  ^
src/SAPPOROBDD/bddc.c:220:74: note: previous declaration is here
static bddp apply B_ARG((bddp f, bddp g, unsigned char op, unsigned char skip));
                                                                         ^
src/SAPPOROBDD/bddc.h:36:20: note: expanded from macro 'B_ARG'
#  define B_ARG(a) a       /* ANSI C style */
                   ^
src/SAPPOROBDD/bddc.c:2258:33: warning: format specifies type 'long long' but the argument has type 'bddp' (aka 'unsigned long') [-Wformat]
  else fprintf(strm, B_BDDP_FD, f0);
                                ^~
src/SAPPOROBDD/bddc.c:2262:33: warning: format specifies type 'long long' but the argument has type 'bddp' (aka 'unsigned long') [-Wformat]
  else fprintf(strm, B_BDDP_FD, f1);
                                ^~
src/SAPPOROBDD/bddc.c:2432:30: warning: format specifies type 'unsigned long long' but the argument has type 'bddp' (aka 'unsigned long') [-Wformat]
  fprintf(stderr, B_BDDP_FX, num);
                             ^~~
src/SAPPOROBDD/bddc.c:2435:30: warning: format specifies type 'long long' but the argument has type 'bddp' (aka 'unsigned long') [-Wformat]
  fprintf(stderr, B_BDDP_FD, NodeLimit);
                             ^~~~~~~~~
src/SAPPOROBDD/bddc.c:2437:30: warning: format specifies type 'long long' but the argument has type 'bddp' (aka 'unsigned long') [-Wformat]
  fprintf(stderr, B_BDDP_FD, NodeSpc);
                             ^~~~~~~
src/SAPPOROBDD/bddc.c:2440:30: warning: format specifies type 'long long' but the argument has type 'bddp' (aka 'unsigned long') [-Wformat]
  fprintf(stderr, B_BDDP_FD, CacheSpc);
                             ^~~~~~~~
src/SAPPOROBDD/bddc.c:2442:30: warning: format specifies type 'long long' but the argument has type 'bddp' (aka 'unsigned long') [-Wformat]
  fprintf(stderr, B_BDDP_FD, NodeUsed);
                             ^~~~~~~~
13 warnings generated.
clang -DNDEBUG -O2 -pipe -fno-strict-aliasing -O2 -pipe -fno-strict-aliasing -fPIC -Isrc -I/usr/local/include/python2.7 -c src/SAPPOROBDD/BDD.cc -o temp.freebsd-9.1-STABLE-amd64-2.7/src/SAPPOROBDD/BDD.o
clang -DNDEBUG -O2 -pipe -fno-strict-aliasing -O2 -pipe -fno-strict-aliasing -fPIC -Isrc -I/usr/local/include/python2.7 -c src/SAPPOROBDD/ZBDD.cc -o temp.freebsd-9.1-STABLE-amd64-2.7/src/SAPPOROBDD/ZBDD.o
clang++ -shared -O2 -pipe -fno-strict-aliasing temp.freebsd-9.1-STABLE-amd64-2.7/src/pygraphillion.o temp.freebsd-9.1-STABLE-amd64-2.7/src/graphillion/graphset.o temp.freebsd-9.1-STABLE-amd64-2.7/src/graphillion/setset.o temp.freebsd-9.1-STABLE-amd64-2.7/src/graphillion/util.o temp.freebsd-9.1-STABLE-amd64-2.7/src/graphillion/zdd.o temp.freebsd-9.1-STABLE-amd64-2.7/src/SAPPOROBDD/bddc.o temp.freebsd-9.1-STABLE-amd64-2.7/src/SAPPOROBDD/BDD.o temp.freebsd-9.1-STABLE-amd64-2.7/src/SAPPOROBDD/ZBDD.o -o lib.freebsd-9.1-STABLE-amd64/_graphillion.so
creating build
creating build/bdist.freebsd-9.1-STABLE-amd64
creating build/bdist.freebsd-9.1-STABLE-amd64/egg
creating build/bdist.freebsd-9.1-STABLE-amd64/egg/graphillion
copying lib.freebsd-9.1-STABLE-amd64/graphillion/tutorial.py -> build/bdist.freebsd-9.1-STABLE-amd64/egg/graphillion
copying lib.freebsd-9.1-STABLE-amd64/graphillion/release.py -> build/bdist.freebsd-9.1-STABLE-amd64/egg/graphillion
copying lib.freebsd-9.1-STABLE-amd64/graphillion/setset.py -> build/bdist.freebsd-9.1-STABLE-amd64/egg/graphillion
copying lib.freebsd-9.1-STABLE-amd64/graphillion/graphset.py -> build/bdist.freebsd-9.1-STABLE-amd64/egg/graphillion
copying lib.freebsd-9.1-STABLE-amd64/graphillion/__init__.py -> build/bdist.freebsd-9.1-STABLE-amd64/egg/graphillion
copying lib.freebsd-9.1-STABLE-amd64/_graphillion.so -> build/bdist.freebsd-9.1-STABLE-amd64/egg
byte-compiling build/bdist.freebsd-9.1-STABLE-amd64/egg/graphillion/tutorial.py to tutorial.pyc
byte-compiling build/bdist.freebsd-9.1-STABLE-amd64/egg/graphillion/release.py to release.pyc
byte-compiling build/bdist.freebsd-9.1-STABLE-amd64/egg/graphillion/setset.py to setset.pyc
byte-compiling build/bdist.freebsd-9.1-STABLE-amd64/egg/graphillion/graphset.py to graphset.pyc
byte-compiling build/bdist.freebsd-9.1-STABLE-amd64/egg/graphillion/__init__.py to __init__.pyc
creating stub loader for _graphillion.so
byte-compiling build/bdist.freebsd-9.1-STABLE-amd64/egg/_graphillion.py to _graphillion.pyc
creating build/bdist.freebsd-9.1-STABLE-amd64/egg/EGG-INFO
copying Graphillion.egg-info/PKG-INFO -> build/bdist.freebsd-9.1-STABLE-amd64/egg/EGG-INFO
copying Graphillion.egg-info/SOURCES.txt -> build/bdist.freebsd-9.1-STABLE-amd64/egg/EGG-INFO
copying Graphillion.egg-info/dependency_links.txt -> build/bdist.freebsd-9.1-STABLE-amd64/egg/EGG-INFO
copying Graphillion.egg-info/not-zip-safe -> build/bdist.freebsd-9.1-STABLE-amd64/egg/EGG-INFO
copying Graphillion.egg-info/top_level.txt -> build/bdist.freebsd-9.1-STABLE-amd64/egg/EGG-INFO
writing build/bdist.freebsd-9.1-STABLE-amd64/egg/EGG-INFO/native_libs.txt
creating dist
creating 'dist/Graphillion-0.93-py2.7-freebsd-9.1-STABLE-amd64.egg' and adding 'build/bdist.freebsd-9.1-STABLE-amd64/egg' to it
removing 'build/bdist.freebsd-9.1-STABLE-amd64/egg' (and everything under it)

Missing sources in Pypi

Dear Takeru-san:
The Pypi 0.95 archive is missing the mingw sources and does not compile (on windows)
This is missing in the MANIFEST

ImportError: undefined symbol: _ZNSt7__cxx1119basic_ostringstreamIcSt11char_traitsIcESaIcEEC1Ev

I have trouble with the following error when importing a graphillion.

Python 3.7.0 (default, Jun 28 2018, 13:15:42)
[GCC 7.2.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import graphillion
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/user/.pyenv/versions/anaconda3-5.3.1/lib/python3.7/site-packages/graphillion/__init__.py", line 27, in <module>
    from graphillion.setset import setset
  File "/home/user/.pyenv/versions/anaconda3-5.3.1/lib/python3.7/site-packages/graphillion/setset.py", line 25, in <module>
    import _graphillion
ImportError: /home/user/.pyenv/versions/anaconda3-5.3.1/lib/python3.7/site-packages/_graphillion.cpython-37m-x86_64-linux-gnu.so: undefined symbol: _ZNSt7__cxx1119basic_ostringstreamIcSt11char_traitsIcESaIcEEC1Ev

My environment is

OS: Ubuntu 20.04.1 LTS
Python: Python 3.7.0 (pyenv: anaconda3-5.3.1)

The OS has just been cleanly installed.
The environment has barely changed from the default state.

I installed Graphillion by the following command.

pip install graphillion

I also tried installing from the source code, but ended up with the same error.

I would appreciate it if somebody could help me out.

Python Dict Memo Caching or Memoization

I would like to create a dictionary where I specify keys that point to different individual subgraphs within the Graphset. For example,

memo = {}
universe = [(0,1), (1,2), (2,3), (3,4), (0,2)]
GraphSet.set_universe(universe)
gs = GraphSet()

gs.add([(0,1), (1,2)])
memo['sub1'] = direct reference to subgraph [(0,1), (1,2)] within gs and not a copy

gs.add([(0, 2), (2, 3)])
memo['sub2'] = direct reference to subgraph [(0, 2), (2, 3)] within gs and not a copy

gs.add([(1, 2), (2, 3), (3, 4)])
memo['sub3'] = direct reference to subgraph [(1, 2), (2, 3), (3, 4)] within gs and not a copy

Is this possible in graphillion?

how can I call zdd library from graphillion

Dear all

I would like to use only the zdd part from graphillion for set manipulation and not a graph . Since graphillion requests to use edges as tuples in the graph but in my case i don't need edges i need the structure of zdd and operation on zdd only using python.
how can i call the zdd from graphillion.
waiting to hear from you soon ;

Best Regards

DAG

I'd like to use one way direction edge in graph in case of finding all pathes.
Probably as default behavior, this library computes
on bidirectional graph. when some edges have only one direction, how to support them in
program ? can I have your advice?

Add FreeBSD to Graphillion pypi Trove Classifier

Request to add "Operating System :: POSIX :: BSD :: FreeBSD" to setup.py.

Graphillion builds, installs and passes the test suite successfully on the following FreeBSD versions:

FreeBSD 10.0-CURRENT (HEAD) amd64/i386
FreeBSD 8.4-RELEASE amd64/i386
FreeBSD 9.1-RELEASE amd64/i386
FreeBSD 9-STABLE amd64/i386

Diff to setup.py:

--- setup.py.orig       2013-06-21 21:15:12.038833699 +1000
+++ setup.py    2013-06-21 21:15:31.398877289 +1000
@@ -20,6 +20,7 @@
         'Intended Audience :: Developers',
         'Intended Audience :: Science/Research',
         'License :: OSI Approved :: MIT License',
+        'Operating System :: POSIX :: BSD :: FreeBSD,
         'Operating System :: POSIX :: Linux',
         'Operating System :: MacOS :: MacOS X',
         'Programming Language :: C',

Generating nondisjoint set families

I have a combinatorial problem that I'm trying to solve using Graphillion (and its underlying ZDD implementation). I hope this is the right place to ask for advice; my apologies if not.

I wish to generate all the set families on a universe U that are nondisjoint in the sense that all members of the family have at least one element in common: ${f | \bigcap_{\alpha \in f} \alpha \neq \emptyset}$.

Initially I thought this would be very easy with the set family algebra that ZDDs provide, but now I'm realizing that it's actually not trivial. I thought that I could make a sort of "meta-universal" set U' where the elements are all the set families on U, and then consider set families on that universe (i.e., setsetsets 😁 ). That way I could use this meta-algebra on U' to create a meta-family of the nondisjoint families on U (which is what I'm after), since I would have access to both the meta-join on U' and join on U. But this meta-universe idea won't work because (1) setsets are not hashable and cannot be used as the universe elements, and (2) it seems that the universe is a global variable so that doing something like this with Graphillion is impossible in any case.

So, my questions are: is my understanding of (1) and (2) correct, and if so, is there another way of generating this collection of families?

By the way, I only recently discovered ZDDs and was thrilled to find that Graphillion exists. And the videos on combinatorial explosion are great 😸 Thank you so much for your excellent work on this!

Add LICENSE file to repository, add to MANIFEST.in

Add a LICENSE file to the repository. Useful for downstream OS packagers/porters to include it in OS packages.

  • LICENSE: Header contains Copyright notice
  • LICENSE: MIT License content
  • Add to MANIFEST.in, so to include it in PyPI sdist

Cannot build o OSX 10.9.5

this is the log:

[arthurnn@ralph graphillion]$ sudo python setup.py build
running build
running build_py
creating build
creating build/lib.macosx-10.9-x86_64-2.7
creating build/lib.macosx-10.9-x86_64-2.7/graphillion
copying graphillion/__init__.py -> build/lib.macosx-10.9-x86_64-2.7/graphillion
copying graphillion/graphset.py -> build/lib.macosx-10.9-x86_64-2.7/graphillion
copying graphillion/release.py -> build/lib.macosx-10.9-x86_64-2.7/graphillion
copying graphillion/setset.py -> build/lib.macosx-10.9-x86_64-2.7/graphillion
copying graphillion/tutorial.py -> build/lib.macosx-10.9-x86_64-2.7/graphillion
running build_ext
building '_graphillion' extension
creating build/temp.macosx-10.9-x86_64-2.7
creating build/temp.macosx-10.9-x86_64-2.7/src
creating build/temp.macosx-10.9-x86_64-2.7/src/graphillion
creating build/temp.macosx-10.9-x86_64-2.7/src/SAPPOROBDD
clang -fno-strict-aliasing -fno-common -dynamic -I/usr/local/include -I/usr/local/opt/sqlite/include -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -DB_64 -Isrc -I/usr/local/Cellar/python/2.7.6_1/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c src/pygraphillion.cc -o build/temp.macosx-10.9-x86_64-2.7/src/pygraphillion.o
clang -fno-strict-aliasing -fno-common -dynamic -I/usr/local/include -I/usr/local/opt/sqlite/include -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -DB_64 -Isrc -I/usr/local/Cellar/python/2.7.6_1/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c src/graphillion/graphset.cc -o build/temp.macosx-10.9-x86_64-2.7/src/graphillion/graphset.o
In file included from src/graphillion/graphset.cc:32:
In file included from src/subsetting/dd/ZddStructure.hpp:14:
In file included from src/subsetting/dd/DdBuilder.hpp:20:
In file included from src/subsetting/dd/DdNodeTable.hpp:16:
src/subsetting/dd/DataTable.hpp:161:20: error: array 'new' cannot have initialization arguments
        rowSize_ = new size_t[n]();
                   ^
src/subsetting/dd/DdNodeTable.hpp:42:15: note: in instantiation of member function 'DataTable<DdNode>::init' requested here
        base::init(n);
              ^
In file included from src/graphillion/graphset.cc:32:
In file included from src/subsetting/dd/ZddStructure.hpp:14:
In file included from src/subsetting/dd/DdBuilder.hpp:20:
In file included from src/subsetting/dd/DdNodeTable.hpp:16:
src/subsetting/dd/DataTable.hpp:161:20: error: array 'new' cannot have initialization arguments
        rowSize_ = new size_t[n]();
                   ^
src/subsetting/dd/DataTable.hpp:76:9: note: in instantiation of member function 'DataTable<DdNodeId>::init' requested here
        init(n);
        ^
src/subsetting/dd/DdNodeTable.hpp:218:37: note: in instantiation of member function 'DataTable<DdNodeId>::DataTable' requested here
            : nodeTable(nodeTable), dataTable(nodeTable.numRows()) {
                                    ^
src/subsetting/dd/ZddStructure.hpp:193:34: note: in instantiation of member function 'DdNodeProperty<DdNodeId>::DdNodeProperty' requested here
        DdNodeProperty<DdNodeId> newIdTable(table);
                                 ^
In file included from src/graphillion/graphset.cc:32:
In file included from src/subsetting/dd/ZddStructure.hpp:14:
In file included from src/subsetting/dd/DdBuilder.hpp:20:
In file included from src/subsetting/dd/DdNodeTable.hpp:16:
src/subsetting/dd/DataTable.hpp:161:20: error: array 'new' cannot have initialization arguments
        rowSize_ = new size_t[n]();
                   ^
src/subsetting/dd/DataTable.hpp:76:9: note: in instantiation of member function 'DataTable<unsigned long>::init' requested here
        init(n);
        ^
src/subsetting/dd/DdNodeTable.hpp:218:37: note: in instantiation of member function 'DataTable<unsigned long>::DataTable' requested here
            : nodeTable(nodeTable), dataTable(nodeTable.numRows()) {
                                    ^
src/subsetting/dd/ZddStructure.hpp:709:32: note: in instantiation of member function 'DdNodeProperty<unsigned long>::DdNodeProperty' requested here
        DdNodeProperty<size_t> nodeId(*nodeTable);
                               ^
In file included from src/graphillion/graphset.cc:32:
In file included from src/subsetting/dd/ZddStructure.hpp:14:
In file included from src/subsetting/dd/DdBuilder.hpp:20:
In file included from src/subsetting/dd/DdNodeTable.hpp:18:
src/subsetting/dd/../util/MyVector.hpp:177:21: warning: destination for this 'memcpy' call is a pointer to dynamic class 'MyList<DdBuilderBase::SpecNode, 1000>'; vtable
      pointer will be overwritten [-Wnon-pod-memaccess]
        std::memcpy(tmp, array_, size_ * sizeof(T));
        ~~~~~~~~~~~ ^
src/subsetting/dd/../util/MyVector.hpp:188:9: note: in instantiation of member function 'MyVector<MyList<DdBuilderBase::SpecNode, 1000> >::shrink' requested here
        shrink(0);
        ^
src/subsetting/dd/../util/MyVector.hpp:87:9: note: in instantiation of member function 'MyVector<MyList<DdBuilderBase::SpecNode, 1000> >::clear' requested here
        clear();
        ^
src/subsetting/dd/DdBuilder.hpp:79:7: note: in instantiation of member function 'MyVector<MyList<DdBuilderBase::SpecNode, 1000> >::~MyVector' requested here
class DdBuilder: DdBuilderBase {
      ^
src/subsetting/dd/ZddStructure.hpp:68:9: note: in instantiation of function template specialization 'ZddStructure::construct_<SapporoZdd>' requested here
        construct_(spec.entity());
        ^
src/graphillion/graphset.cc:90:14: note: in instantiation of function template specialization 'ZddStructure::ZddStructure<SapporoZdd>' requested here
    dd = new ZddStructure(f);
             ^
src/subsetting/dd/../util/MyVector.hpp:177:21: note: explicitly cast the pointer to silence this warning
        std::memcpy(tmp, array_, size_ * sizeof(T));
                    ^
                    (void*)
In file included from src/graphillion/graphset.cc:32:
In file included from src/subsetting/dd/ZddStructure.hpp:14:
In file included from src/subsetting/dd/DdBuilder.hpp:20:
In file included from src/subsetting/dd/DdNodeTable.hpp:16:
src/subsetting/dd/DataTable.hpp:161:20: error: array 'new' cannot have initialization arguments
        rowSize_ = new size_t[n]();
                   ^
src/subsetting/dd/DataTable.hpp:76:9: note: in instantiation of member function 'DataTable<MyListOnPool<DdBuilderBase::SpecNode> >::init' requested here
        init(n);
        ^
src/subsetting/dd/DdNodeTable.hpp:218:37: note: in instantiation of member function 'DataTable<MyListOnPool<DdBuilderBase::SpecNode> >::DataTable' requested here
            : nodeTable(nodeTable), dataTable(nodeTable.numRows()) {
                                    ^
src/subsetting/dd/DdBuilder.hpp:388:63: note: in instantiation of member function 'DdNodeProperty<MyListOnPool<DdBuilderBase::SpecNode> >::DdNodeProperty' requested here
              specNodeSize(getSpecNodeSize(spec.datasize())), work(input) {
                                                              ^
src/subsetting/dd/ZddStructure.hpp:133:28: note: in instantiation of member function 'ZddSubsetter<DegreeConstraint>::ZddSubsetter' requested here
        ZddSubsetter<SPEC> zs(*nodeTable, spec, tmpTable.privateEntity());
                           ^
src/subsetting/dd/ZddStructure.hpp:89:9: note: in instantiation of function template specialization 'ZddStructure::subset_<DegreeConstraint>' requested here
        subset_(spec.entity());
        ^
src/graphillion/graphset.cc:109:9: note: in instantiation of function template specialization 'ZddStructure::subset<DegreeConstraint>' requested here
    dd->subset(dc);
        ^
In file included from src/graphillion/graphset.cc:32:
In file included from src/subsetting/dd/ZddStructure.hpp:14:
In file included from src/subsetting/dd/DdBuilder.hpp:20:
In file included from src/subsetting/dd/DdNodeTable.hpp:16:
src/subsetting/dd/DataTable.hpp:161:20: error: array 'new' cannot have initialization arguments
        rowSize_ = new size_t[n]();
                   ^
src/subsetting/dd/DataTable.hpp:76:9: note: in instantiation of member function 'DataTable<ZBDD>::init' requested here
        init(n);
        ^
src/subsetting/dd/DdNodeTable.hpp:218:37: note: in instantiation of member function 'DataTable<ZBDD>::DataTable' requested here
            : nodeTable(nodeTable), dataTable(nodeTable.numRows()) {
                                    ^
src/subsetting/dd/ZddStructure.hpp:569:29: note: in instantiation of member function 'DdNodeProperty<ZBDD>::DdNodeProperty' requested here
        DdNodeProperty<Val> work(*nodeTable);
                            ^
src/graphillion/graphset.cc:120:17: note: in instantiation of function template specialization 'ZddStructure::evaluate<ToZBDD>' requested here
  zdd_t f = dd->evaluate(ToZBDD(setset::max_elem() - setset::num_elems()));
                ^
1 warning and 5 errors generated.
error: command 'clang' failed with exit status 1

The Question about connection with networkX

Hello.
I'm a student in Japan, recently using graphillion.

I found that GraphSet.converters is strange in source code, and happens error.

import matplotlib.pyplot as plt
from graphillion import GraphSet
import graphillion.tutorial as tl
import random
import networkx as nx

CONST_H = 500
CONST_W = 500

N = int(input())
M = int(input())

# Graphの接続設定
G = [[] for i in range(N)]
for i in range(M):
    while True:
        a = random.randint(0, N - 1)
        b = random.randint(0, N - 1)
        if a != b:
            break
    G[a].append(b)
    G[b].append(a)

# 位置の設定
P = [(random.uniform(-CONST_W, CONST_W), random.uniform(-CONST_H, CONST_H))
     for i in range(N)]


GraphSet.converters['to_edges'] = nx.Graph
GraphSet.converters['to_graph'] = nx.Graph.edges()

graph = nx.Graph()

for i in range(N):
    graph.add_node(i)

for i in range(N):
    for j in range(len(G[i])):
        graph.add_edge(i, G[i][j])

# 全体図の描画
# nx.draw_networkx(graph, pos=P)
# plt.show()

GraphSet.set_universe(graph)

This code arises error in "GraphSet.set_universe(graph)", which error represents

Traceback (most recent call last):
  File "graph.py", line 30, in <module>
    GraphSet.converters['to_graph'] = nx.Graph.edges()
TypeError: 'property' object is not callable

When I saw the source code about set_converters
2101, 2102, rows

    converters = { 'to_graph': lambda edges: edges,
                   'to_edges': lambda graph: graph }

Is this correct?
I think this source code made mistake about changing position in 'to_graph', 'to_edges'.

Thank you.

setset load does not work problem

dear all ;

when i dump a setset MM in file like this :
with open('statespace.data', 'wb') as f:
MM.dump(f)

satespace file looks like this

1211954 511 B T
1211440 510 B T
1179340 509 B T
1178184 508 B T
1094540 507 B T
1093960 506 B T
1079978 505 B T
1078212 504 B T
.....

when i want to load it it does not work
f=open('statespace.data', 'rb')
gs.load(f)
please I need help

Store Path Counts in Graphillion

Let's say that I have 8 paths/sequences where each number represents a node:

x = [[1, 2, 3, 4, 5], 
     [8, 9, 10], 
     [4, 6, 8, 10], 
     [1, 2, 3, 4, 5], 
     [8, 9, 10], 
     [11, 13, 14, 16],
     [1, 2, 3],
     [9, 10]
    ]

Is there a way to push these into a graph using Graphillion and then be able to keep track of the fact that paths [1, 2, 3, 4, 5] and [8, 9, 10] each have a count of 2 (i.e., these two paths are observed twice) while the other 6 paths have a count of 1?

In my case, I don't know ahead of time that, say, [1, 2, 3, 4, 5] is counted twice since the data is large so I would need a way to update the count as new data is being read. Is this possible with Graphillion?

Add to `conda-forge` to allow installation with `conda`?

First, thank you for your work on this package! 😁

It would be wonderful if Graphillion were available for installing through conda. There is a guide for adding packages to conda-forge here.

For context: I am the maintainer of the PyPhi library, which depends on Graphillion's ZDD implementation of efficient set family operations. I would like to distribute the latest version of PyPhi on conda, but to do that, all dependencies need to also be available on conda.

GraphSet([[]]).min_iter() should return the set consisting of the empty graph but not so.

The following code should print '[[]]' (the set consisting of the empty graph) but actually
it prints '[]' (the empty set) in the current version.

gs = GraphSet([[]])
print(list(gs.min_iter()))

Note that the below code correctly outputs the answer.

GraphSet.set_universe([(1,2)])
gs = GraphSet([[], [(1,2)]])
print(list(gs.min_iter()))   # correctly output '[[], [(1, 2)]]'

Generators Failing

According to PEP479, you'll have to update your generators for compatibility with the latest versions of Python 3.7. Otherwise, users will get an error like:

Traceback (most recent call last):
  File "./dxz.py", line 116, in <module>
    for sol in dxz.solutions:
  File "./dxz.py", line 45, in solutions
    for x in iter(self.zdd):
  File "/home/miniconda3/lib/python3.7/site-packages/graphillion/graphset.py", line 653, in __iter__
    for g in self._ss.__iter__():
RuntimeError: generator raised StopIteration

Graphillion and the exact cover problem

Hi,

I would like to know if it is possible to use the Graphillion library to solve an exact cover problem.

For example, let's say I have a set of 4 tetrominos and I would like to find all the possible tilling combinations inside a 4x4 grid. At the moment I am using Donald Kuth's "Dancing Links" technique to find all the solutions but I have heard that using a ZDD data structure could drastically improve the searching process.

Could Graphillion be used to solve this type of problem ? If so, would you mind to provide a simple example or some guidance ?

Reproducing Paper Results

In this recent paper published by Prof. Minato titled, "Interval-Memoized Backtracking on ZDDs for Fast Enumeration of All Lower Cost Solutions", it is mentioned that Graphillion was used. Are you able to give any advice/suggestions on how to use Graphillion to reproduce their results and implement their published algorithms?

Enable advanced methods

The following advanced methods are disabled at commit 4784ec8 (I can't recall the reason...), but they should be enabled in the next release.

  • quotient (/, /=)
  • remainder (%, %=)
  • join
  • meet
  • subgraphs
  • supergraphs
  • non_subgraphs
  • non_supergraphs

Install graphillion in Windows 7

Hi,

Tried to install graphillion in Windows 7 with Python 2.7 and MingW. Error message indicated sys/resource.h not found.

Any hints to make it works in Windows platform?

The question about the graphillion

    Hi, I am a freshman in this field. Great work in terms of graphillion!  I have a question about graphillion. Could this graphillion support the mutli classification problem?If yes, I noticed that the forest was mentioned in the graphillion.  What's the most advantageous parts using this graphillion to solve the classification problem?

Best regards
Irving

GraphSet as a hash key

GraphSet objects (and its internal setset objects) should not be used as a hash key since they are mutable, but they can be a hash key in the current implementation.
FrozenGraphSet objects will be introduced to be a hash key, in accordance with Python policy.

Unable to install on Win8.1 64 bit Python2.7

I am getting following error while trying to install ON a Windows 8.1 64 bit machine running python 27

up.py install
running install
running bdist_egg
running egg_info
creating Graphillion.egg-info
writing Graphillion.egg-info\PKG-INFO
writing top-level names to Graphillion.egg-info\top_level.txt
writing dependency_links to Graphillion.egg-info\dependency_links.txt
writing manifest file 'Graphillion.egg-info\SOURCES.txt'
reading manifest file 'Graphillion.egg-info\SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'Graphillion.egg-info\SOURCES.txt'
installing library code to build\bdist.win-amd64\egg
running install_lib
running build_py
creating build
creating build\lib.win-amd64-2.7
creating build\lib.win-amd64-2.7\graphillion
copying graphillion\graphset.py -> build\lib.win-amd64-2.7\graphillion
copying graphillion\release.py -> build\lib.win-amd64-2.7\graphillion
copying graphillion\setset.py -> build\lib.win-amd64-2.7\graphillion
copying graphillion\tutorial.py -> build\lib.win-amd64-2.7\graphillion
copying graphillion__init__.py -> build\lib.win-amd64-2.7\graphillion
running build_ext
building '_graphillion' extension
Traceback (most recent call last):
File "setup.py", line 67, in
test_suite='graphillion.test',
File "C:\Python27\lib\distutils\core.py", line 152, in setup
dist.run_commands()
File "C:\Python27\lib\distutils\dist.py", line 953, in run_commands
self.run_command(cmd)
File "C:\Python27\lib\distutils\dist.py", line 972, in run_command
cmd_obj.run()
File "build\bdist.win-amd64\egg\setuptools\command\install.py", line 73, in ru
n
File "build\bdist.win-amd64\egg\setuptools\command\install.py", line 93, in do
_egg_install
File "C:\Python27\lib\distutils\cmd.py", line 326, in run_command
self.distribution.run_command(command)
File "C:\Python27\lib\distutils\dist.py", line 972, in run_command
cmd_obj.run()
File "build\bdist.win-amd64\egg\setuptools\command\bdist_egg.py", line 185, in
run
File "build\bdist.win-amd64\egg\setuptools\command\bdist_egg.py", line 171, in
call_command
File "C:\Python27\lib\distutils\cmd.py", line 326, in run_command
self.distribution.run_command(command)
File "C:\Python27\lib\distutils\dist.py", line 972, in run_command
cmd_obj.run()
File "build\bdist.win-amd64\egg\setuptools\command\install_lib.py", line 20, i
n run
File "C:\Python27\lib\distutils\command\install_lib.py", line 111, in build
self.run_command('build_ext')
File "C:\Python27\lib\distutils\cmd.py", line 326, in run_command
self.distribution.run_command(command)
File "C:\Python27\lib\distutils\dist.py", line 972, in run_command
cmd_obj.run()
File "build\bdist.win-amd64\egg\setuptools\command\build_ext.py", line 52, in
run
File "C:\Python27\lib\distutils\command\build_ext.py", line 339, in run
self.build_extensions()
File "C:\Python27\lib\distutils\command\build_ext.py", line 448, in build_exte
nsions
self.build_extension(ext)
File "build\bdist.win-amd64\egg\setuptools\command\build_ext.py", line 186, in
build_extension
File "C:\Python27\lib\distutils\command\build_ext.py", line 498, in build_exte
nsion
depends=ext.depends)
File "C:\Python27\lib\distutils\msvc9compiler.py", line 473, in compile
self.initialize()
File "C:\Python27\lib\distutils\msvc9compiler.py", line 383, in initialize
vc_env = query_vcvarsall(VERSION, plat_spec)
File "C:\Python27\lib\distutils\msvc9compiler.py", line 299, in query_vcvarsal
l
raise ValueError(str(list(result.keys())))
ValueError: [u'path']

how to create a graph faslty from a BIG file with graphillion!!??

hello!
I have a file of 1Gb , the format of each line be like this :
word1 word2 distance
i would like to creat an undirected graph of the related words quicly ,

i've using this function
G = nx.read_edgelist("neighbours.txt", delimiter="\t", data=[("weight", float)])
it's work BUT 1h45mn to build the graph it's too much , i don't have too much time , i have lot of files to do the same process with them :(

can I do that faslty with graphillion??

What forces the paths / cycles to have one connected component?

Thank you for making this! I am trying to use this to construct BDDs of some graphsets, and am looking at the methods here as examples of how to specify subgraphs: https://github.com/takemaru/graphillion/blob/master/graphillion/graphset.py

Based on the "Paths on a grid graph" section here https://github.com/takemaru/graphillion#tutorial , it seems that the paths method should build a graphset of simple paths.

Here is the method:

def paths(terminal1, terminal2, is_hamilton=False, graphset=None):
    dc = {}
    for v in GraphSet._vertices:
        if v in (terminal1, terminal2):
            dc[v] = 1
        else:
            dc[v] = 2 if is_hamilton else range(0, 3, 2)
    return GraphSet.graphs(vertex_groups=[[terminal1, terminal2]],
                           degree_constraints=dc,
                           no_loop=True, graphset=graphset)

I see that the constraints produce a simple path from terminal1 to terminal2, but what rules out having simple cycles disjoint from the path?

Does vertex_groups have additional functionality I'm unaware of?

The documentation in graphset.py says:

" vertex_groups: Optional. A nested list. Vertices in an
inner list are connected while those in different inner
lists are disconnected. For [[1, 5], [3]], 1 and 5 are
connected, while they are not connected with 3. "

Is there some additional documentation somewhere?

I have a similar concern about the cycles method, which calls GraphSet.graphs(vertex_groups=[[]], degree_constraints=dc,
graphset=graphset) .

Maybe passing [[]] to vertex_groups forces the subgraphs to be connected? Otherwise, what prevents a disjoint union of 2 simple cycles from being accepted?

Thank you for reading!

update sapporobdd

update sapporobdd for fixing its bug, though the bug code is not used by graphillion.

Limiting amount of results in creation methods

Hi,

I am trying to find Hamiltonian cycles in homogeneous grids of certain number of nodes and limited node degree.
I can perform the full computation for a universe/grid up to 4x4 size, but if I go to a 5x5 grid graph, then calling:

GraphSet.cycles(is_hamilton=True)

...overflows my 500 GB of RAM without finishing, in a matter of a few minutes.

I don't need the whole set of cycles. Is there a way to get something like a regular Python generator, so that I can consume results lazily? Or a parameter to limit the number of results that are computed eagerly before returning?

Thanks in advance

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.