Skip to content
This repository has been archived by the owner on Dec 4, 2024. It is now read-only.

Commit

Permalink
Merge pull request #7 from bellert/0.0.2
Browse files Browse the repository at this point in the history
0.0.2
  • Loading branch information
bellert authored May 18, 2018
2 parents dfd04b3 + a9c7625 commit a733b89
Show file tree
Hide file tree
Showing 15 changed files with 595 additions and 105 deletions.
142 changes: 142 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
version: 2
jobs:
test-3.6: &full-test-template
docker:
- image: circleci/python:3.6-jessie

working_directory: ~/repo

steps:

- checkout

- restore_cache:
keys:
- v1-dependencies-{{ checksum "tests/requirements.txt" }}-{{ .Environment.CIRCLE_JOB }}

- run:
name: create virtualenv
command: |
python -m virtualenv env
- run: &install-dependencies-template
name: install dependencies
command: |
. env/bin/activate
python --version
pip install -r tests/requirements.txt --extra-index-url https://pypi.dwavesys.com/simple
- save_cache:
paths:
- ./env
key: v1-dependencies-{{ checksum "tests/requirements.txt" }}-{{ .Environment.CIRCLE_JOB }}

- run: &run-tests-template
name: run unittests
command: |
. env/bin/activate
python --version
coverage run -m unittest discover
test-3.5:
<<: *full-test-template
docker:
- image: circleci/python:3.5-jessie

test-3.4:
<<: *full-test-template
docker:
- image: circleci/python:3.4-jessie

test-2.7:
<<: *full-test-template
docker:
- image: circleci/python:2.7-jessie

test-osx:
macos:
xcode: "9.0"

working_directory: ~/repo

steps:
- checkout

- run:
name: install pyenv
command: |
brew install pyenv
- restore_cache:
keys:
- pyenv-versions-{{ .Environment.CIRCLE_JOB }}
- dependencies2.7-{{ checksum "tests/requirements.txt" }}-{{ .Environment.CIRCLE_JOB }}

- run:
name: install python 2.7.14 and 3.6.5 with pyenv
command: |
pyenv install 2.7.14 -s
pyenv install 3.6.5 -s
- save_cache:
paths:
- ~/.pyenv
key: pyenv-versions-{{ .Environment.CIRCLE_JOB }}

- run:
name: create virtualenv for 2.7.14
command: |
eval "$(pyenv init -)"
pyenv local 2.7.14
python -m pip install virtualenv
python -m virtualenv env
- run: *install-dependencies-template

- save_cache:
paths:
- ./env
key: dependencies2.7-{{ checksum "tests/requirements.txt" }}-{{ .Environment.CIRCLE_JOB }}

- run: *run-tests-template

- run:
name: clear virtual environment
command: |
rm -rf env
- restore_cache:
keys:
- dependencies3.6-{{ checksum "tests/requirements.txt" }}-{{ .Environment.CIRCLE_JOB }}

- run:
name: create virtualenv for 3.6.5
command: |
eval "$(pyenv init -)"
pyenv local 3.6.5
python -m pip install virtualenv
python -m virtualenv env
- run: *install-dependencies-template

- save_cache:
paths:
- ./env
key: dependencies3.6-{{ checksum "tests/requirements.txt" }}-{{ .Environment.CIRCLE_JOB }}

- run: *run-tests-template

workflows:
version: 2
test:
jobs:
- test-3.6
- test-2.7
- test-3.5
- test-3.4
- test-osx:
requires:
- test-3.6
- test-2.7
- test-3.5
- test-3.4
34 changes: 23 additions & 11 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,32 +1,44 @@
Demo for the Structural Imbalance Project
=========================================

References
----------

Data is from the Stanford Militants Mapping Project

Mapping Militant Organizations, Stanford University, last modified February 28, 2016, http://web.stanford.edu/group/mappingmilitants/cgi-bin/.
Mapping Militant Organizations, Stanford University, last modified February 28, 2016,
http://web.stanford.edu/group/mappingmilitants/cgi-bin/.

Running the Demo
----------------
Setting Up the Demo
-------------------

Copy (clone) this structural-imbalance-demo repository to your local machine.

You can run the demo on classical hardware (a CPU) or on a D-Wave QPU, with the selection made by the pip requirements
file used.
To set up the required dependencies, in the root directory of a copy (clone) of this repository, run the following:

.. code-block:: bash
pip install -r requirements_cpu.txt # to run on CPU
pip install -r requirements_qpu.txt --extra-index-url https://pypi.dwavesys.com/simple # to run on QPU
pip install .
Configuring the Demo
--------------------

To run the demo on the QPU, extra dependencies must be installed by running the following:

.. code-block:: bash
pip install .[qpu] --extra-index-url https://pypi.dwavesys.com/simple
Access to a D-Wave system must be configured, as described in the `dwave-cloud-client
<http://dwave-cloud-client.readthedocs.io/en/latest/reference/intro.html#configuration>`_ documentation. A default
solver is required.

Running the Demo
----------------

To run the demo:

.. code-block:: bash
python demo.py
License
-------

Expand Down
101 changes: 34 additions & 67 deletions demo.py
Original file line number Diff line number Diff line change
@@ -1,73 +1,41 @@
from __future__ import division
import os

import dwave_qbsolv as qbsolv

import dwave_networkx as dnx

try:
import dwave.system.samplers as dwsamplers
import dwave.system.composites as dwcomposites
_qpu = True
except ImportError:
_qpu = False

import dwave_structural_imbalance_demo as sbdemo


def maps():
Global = sbdemo.global_signed_social_network()

# The Syria subregion
syria_groups = set()
for v, data in Global.nodes(data=True):
if 'map' not in data:
continue
if data['map'] in {'Syria', 'Aleppo'}:
syria_groups.add(v)
Syria = Global.subgraph(syria_groups)

# The Iraq subregion
iraq_groups = set()
for v, data in Global.nodes(data=True):
if 'map' not in data:
continue
if data['map'] == 'Iraq':
iraq_groups.add(v)
Iraq = Global.subgraph(iraq_groups)

return Global, Syria, Iraq


def diagramDateRange(directory_name, start, end, graph, sampler, subsolver, subarea=None, subarea_name=None):
def diagramDateRange(gssn, graph_name, start, end, subarea_name=None):
# Create directories
directory_path = os.path.join('Results', directory_name)
directory_path = os.path.join('Results', graph_name)
if not os.path.exists(directory_path):
os.makedirs(directory_path)

# Write .csv header line
csv = open(os.path.join(directory_path, 'Structural Imbalance.csv'), 'w')
csv_name = 'Structural Imbalance.csv'
csv_path = os.path.join(directory_path, 'Structural Imbalance.csv')
csv = open(csv_path, 'w')
csv.write('year,total groups,total edges,imbalanced edges,structural imbalance')
if subarea is not None and subarea_name is not None:
if subarea_name is not None:
csv.write(',%s groups,%s edges,%s imbalanced edges,%s structural imbalance' % tuple([subarea_name] * 4))
csv.write('\n')

for year in range(start, end):
# Compute structural imbalance up to and including year
filtered_edges = ((u, v) for u, v, a in graph.edges(data=True) if a['event_date'].year <= year)
subrange = graph.edge_subgraph(filtered_edges)
imbalance, bicoloring = dnx.structural_imbalance(subrange, sampler, solver=subsolver)
nld_subrange = gssn.get_node_link_data(graph_name, year)
nld_subrange_solved = gssn.solve_structural_imbalance(graph_name, year)

# Write stats to .csv
num_nodes = len(subrange.nodes)
num_edges = len(subrange.edges)
num_imbalanced = len(imbalance)
num_nodes = len(nld_subrange['nodes'])
num_edges = len(nld_subrange['links'])
num_imbalanced = sum([edge['frustrated'] for edge in nld_subrange_solved['links']])
ratio = num_imbalanced / num_edges
csv.write('%s,%s,%s,%s,%s' % (year, num_nodes, num_edges, num_imbalanced, ratio))
if subarea is not None and subarea_name is not None:
num_nodes = len(set.intersection(set(subrange.nodes), set(subarea.nodes)))
num_edges = len(set.intersection(set(subrange.edges), set(subarea.edges)))
num_imbalanced = len(set.intersection(set(imbalance), set(subarea.edges)))
if subarea_name is not None:
nld_subarea = gssn.get_node_link_data(subarea_name, year)
num_nodes = len([node for node in nld_subrange['nodes'] if node in nld_subarea['nodes']])
event_ids = [edge['event_id'] for edge in nld_subrange['links'] if edge in nld_subarea['links']]
num_edges = len(event_ids)
num_imbalanced = len([edge['event_id'] for edge in nld_subrange_solved['links'] if edge['event_id'] in event_ids])
if num_edges != 0:
ratio = num_imbalanced / num_edges
else:
Expand All @@ -78,36 +46,35 @@ def diagramDateRange(directory_name, start, end, graph, sampler, subsolver, suba
# Draw graph
file_name = 'Structural Imbalance %s.png' % year
file_path = os.path.join(directory_path, file_name)
sbdemo.draw(file_path, subrange, imbalance, bicoloring)
print('output %s' % file_path)
sbdemo.draw(file_path, nld_subrange_solved)
print('Output %s\n' % file_path)

print('Output %s' % csv_path)
csv.close()


if __name__ == '__main__':
# get a sampler
sampler = qbsolv.QBSolv()

if _qpu:
subsolver = dwcomposites.EmbeddingComposite(dwsamplers.DWaveSampler())
print("Running on the QPU")
else:
print("Running classically")
subsolver = None

# get the graphs
Global, Syria, Iraq = maps()
gssn = sbdemo.GlobalSignedSocialNetwork()

# draw Global graph before solving; save node layout for reuse
nld_global = gssn.get_node_link_data()
position = sbdemo.draw('global.png', nld_global)
print('Output %s' % 'global.png')

# calculate the imbalance of Global
imbalance, bicoloring = dnx.structural_imbalance(Global, sampler, solver=subsolver)
nld_global_solved = gssn.solve_structural_imbalance()

# draw the Global graph
sbdemo.draw('syria_imbalance.png', Global, imbalance, bicoloring)
# draw the Global graph; reusing the above layout, and calculating a new grouped layout
sbdemo.draw('global_imbalance.png', nld_global_solved, position)
print('Output %s' % 'global_imbalance.png')
sbdemo.draw('global_imbalance_grouped', nld_global_solved)
print('Output %s' % 'global_imbalance_grouped\n')

# Images of the structural imbalance in the local Syrian SSN
# for years 2010-2016 showing frustrated and unfrustrated edges.
diagramDateRange('Syrian Theatre', 2010, 2016 + 1, Syria, sampler, subsolver)
diagramDateRange(gssn, 'Syria', 2010, 2016 + 1)

# Images of the structural imbalance in the world SSN for
# years 2007-2016 showing frustrated and unfrustrated edges.
diagramDateRange('World Network', 2007, 2016 + 1, Global, sampler, subsolver, Syria, 'Syria')
diagramDateRange(gssn, 'Global', 2007, 2016 + 1, 'Syria')
2 changes: 2 additions & 0 deletions dwave_structural_imbalance_demo/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
from dwave_structural_imbalance_demo.interfaces import *
from dwave_structural_imbalance_demo.mmp_network import *
from dwave_structural_imbalance_demo.drawing import *
from dwave_structural_imbalance_demo.json_schema import *
Loading

0 comments on commit a733b89

Please sign in to comment.