diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..bee8a64b79a99590d5303307144172cfe824fbf7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+__pycache__
diff --git a/elect.py b/elect.py
new file mode 100755
index 0000000000000000000000000000000000000000..7ebcd12a14c92b64eb70de01dc937c51278363c2
--- /dev/null
+++ b/elect.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python3
+import argparse
+import json
+import numpy as np
+
+# N[a,b] is the number of voters who prefer candidate a to candidate b
+def load_pairwise_preferences_matrix(file):
+    list_of_lists = json.load(file)
+    n = np.stack([np.asarray(l, dtype=np.int8) for l in list_of_lists])
+    return n
+
+# As defined in section 4.12.1 https://arxiv.org/pdf/1804.02973.pdf,
+# A Condorcet winner is an alternative a ∈ A that wins every head-to-head
+# contest with some other alternative b ∈ A \ {a}.
+def condorcet_winner(n, candidates):
+    nb_candidates = len(candidates)
+    for potential_winner in range(nb_candidates):
+        won_all_contests = True
+        for opponent in range(nb_candidates):
+            if n[opponent][potential_winner] > n[potential_winner][opponent]:
+                won_all_contests = False
+        if won_all_contests:
+            return candidates[potential_winner]
+    return None
+
+# As defined in section 4.12.1 https://arxiv.org/pdf/1804.02973.pdf,
+# A weak Condorcet winner is an alternative a ∈ A that doesn’t lose any
+# head-to-head contest with some other alternative b ∈ A \ {a}
+def weak_condorcet_winners(n, candidates):
+    weak_winners = []
+    nb_candidates = len(candidates)
+    for potential_winner in range(nb_candidates):
+        lost_a_contest = False
+        for opponent in range(nb_candidates):
+            if n[opponent][potential_winner] > n[potential_winner][opponent]:
+                lost_a_contest = True
+        if not lost_a_contest:
+            weak_winners.append(candidates[potential_winner])
+    return weak_winners
+
+# As defined in section 4 https://citizensassembly.arts.ubc.ca/resources/submissions/csharman-10_0409201706-143.pdf
+def schulze_winners(n, candidates):
+    nb_candidates = len(candidates)
+    p = np.zeros((nb_candidates, nb_candidates), dtype=np.int8)
+    for i in range(nb_candidates):
+        for j in range(nb_candidates):
+            if i != j:
+                p[i][j] = n[i][j] - n[j][i]
+
+    for i in range(nb_candidates):
+        for j in range(nb_candidates):
+            if i != j:
+                for k in range(nb_candidates):
+                    if i != k and j != k:
+                        s = min(p[j][i], p[i][k])
+                        if p[j][k] < s:
+                            p[j][k] = s
+
+    winners = []
+    for i in range(nb_candidates):
+        has_lost_directly_or_indirectly = False
+        for j in range(nb_candidates):
+            if i != j:
+                if p[j][i] > p[i][j]:
+                    has_lost_directly_or_indirectly = True
+        if not has_lost_directly_or_indirectly:
+            winners.append(candidates[i])
+    return winners
+
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser(description='Computes winners of the election')
+    parser.add_argument('-c', '--candidates-file', help='candidates JSON file', type=argparse.FileType('r', encoding='utf-8'), required=True)
+    parser.add_argument('matrix_file', help="pairwise preference matric JSON file", type=argparse.FileType('r', encoding='utf-8'))
+    args = parser.parse_args()
+
+    n = load_pairwise_preferences_matrix(args.matrix_file)
+    assert(n.shape[0] > 0)
+    assert(n.shape[0] == n.shape[1])
+
+    candidates = json.load(args.candidates_file)
+    assert(len(candidates) == n.shape[0])
+
+    # Condorcet winner (win every head-to-head contest)
+    c_winner = condorcet_winner(n, candidates)
+    if c_winner is None:
+        print('There is no Condorcet winner')
+    else:
+        print(f'Condorcet winner: {c_winner}')
+
+    # Condorcet weak winner (do not lose any head-to-head contest)
+    weak_c_winners = weak_condorcet_winners(n, candidates)
+    if len(weak_c_winners) == 0:
+        print('There are no weak Condorcet winners')
+    else:
+        print(f'Weak Condorcet winners: {weak_c_winners}')
+
+    # Schulze winners (win every head-to-head contest, directly or indirectly)
+    schulze_winners = schulze_winners(n, candidates)
+    assert(len(schulze_winners) > 0)
+    print(f'Schulze winners: {schulze_winners}')
diff --git a/preference_counter.py b/preference_counter.py
new file mode 100755
index 0000000000000000000000000000000000000000..3f0c48969525dce61f755cb91d140e476d159a02
--- /dev/null
+++ b/preference_counter.py
@@ -0,0 +1,125 @@
+#!/usr/bin/env python3
+import argparse
+import json
+import numpy as np
+import pygraphviz as pgv
+from itertools import groupby
+
+def all_equal(iterable):
+    g = groupby(iterable)
+    return next(g, True) and not next(g, False)
+
+def is_blank(ballot, unranked_value):
+    for x in ballot:
+        if x != 0 and x != unranked_value:
+            return False
+    return True
+
+# ballot values should be consistent (unranked value should be the greatest)
+# N[a,b] is the number of voters who prefer candidate a to candidate b
+def pairwise_preferences(ballot, nb_candidates):
+    n = np.zeros((nb_candidates, nb_candidates), dtype=np.int8)
+
+    for a in range(nb_candidates):
+        for b in range(a, nb_candidates):
+            if ballot[a] < ballot[b]:
+                n[a][b] = 1
+            elif ballot[a] > ballot[b]:
+                n[b][a] = 1
+    return n
+
+def pairwise_preferences_matrix(belenios_raw_data):
+    # traverse data to compute some stuff and check some assumptions
+    max_observed_value = -1
+    nb_blank = 0
+    min_nb_candidates = 1000
+    max_nb_candidates = -1
+    for ballot in belenios_raw_data:
+        max_observed_value = max(max_observed_value, max(ballot))
+        nb_candidates = len(ballot)
+        min_nb_candidates = min(min_nb_candidates, nb_candidates)
+        max_nb_candidates = max(max_nb_candidates, nb_candidates)
+    assert(max_observed_value > -1)
+    assert(min_nb_candidates == max_nb_candidates)
+    nb_candidates = min_nb_candidates
+    unranked_value = max_observed_value + 1
+
+    # put a consistent value for unranked candidates
+    fix_unranked_value = lambda x: unranked_value if x == 0 else x
+    data = [ list(map(fix_unranked_value, ballot)) for ballot in belenios_raw_data ]
+
+    # compute some stats
+    nb_voters = len(data)
+    nb_blank = sum([int(is_blank(ballot, unranked_value)) for ballot in data])
+
+    # compute N, the matrix of pairwise preferences
+    # N[a,b] is the number of voters who prefer candidate a to candidate b
+    n = np.zeros((nb_candidates, nb_candidates), dtype=np.int8)
+    for ballot in data:
+        n += pairwise_preferences(ballot, nb_candidates)
+
+    return (n, nb_candidates, nb_voters, nb_blank)
+
+# compute graph of pairwise preferences
+# When N[i,j] > N[j,i], then there is a link from candidate i to candidate j of strength N[i,j] – N[j,i]
+def pairwise_preferences_graph(n, candidates):
+    graph = pgv.AGraph(strict=True, directed=True)
+
+    graph.add_nodes_from(candidates)
+
+    assert n.shape[0] == n.shape[1]
+    assert n.shape[0] == len(candidates)
+    nb_candidates = len(candidates)
+    for a in range(nb_candidates):
+        for b in range(a, nb_candidates):
+            margin = n[a][b] - n[b][a]
+            if margin != 0:
+                (x, y) = (a, b) if margin > 0 else (b, a)
+                margin = abs(margin)
+                cx = candidates[x]
+                cy = candidates[y]
+                text_fr = f"{cx} domine {cy} par {margin} votants\n{n[x][y]} votants préfèrent {cx} à {cy}\n{n[y][x]} votants préfèrent {cy} à {cx}"
+                text_en = f"{cx} dominates {cy} by a margin of {margin} voters\n{n[x][y]} voters prefer {cx} over {cy}\n{n[y][x]} voters prefer {cy} over {cx}"
+                graph.add_edge(cx, cy, label=f"{margin}", tooltip=f"{text_fr}\n\n{text_en}")
+
+    return graph
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser(description='Computes pairwise preferences matrix and graph from belenios ballot files')
+    parser.add_argument('-om', '--output-matrix-file', required=True)
+    parser.add_argument('-og', '--output-graph-file', required=True)
+    parser.add_argument('-c', '--candidates-file', help='candidates JSON file', type=argparse.FileType('r', encoding='utf-8'), required=True)
+    parser.add_argument('ballot_file', nargs='+', help="belenios ballot JSON file", type=argparse.FileType('r', encoding='utf-8'))
+    args = parser.parse_args()
+
+    # compute the pairwise preference matrix from all belenios ballot files
+    ballot_data = []
+    for file in args.ballot_file:
+        raw_data = json.load(file)
+        (n, nb_candidates, nb_voters, nb_blank) = pairwise_preferences_matrix(raw_data)
+        #print(n)
+        ballot_data.append((n, nb_candidates, nb_voters, nb_blank))
+
+    # make sure that the ballot fires are consistent with each other
+    nb_candidates = [b[1] for b in ballot_data]
+    assert(all_equal(nb_candidates))
+
+    # aggregate values
+    nb_voters = sum([b[2] for b in ballot_data])
+    nb_blank = sum([b[3] for b in ballot_data])
+    n = sum([b[0] for b in ballot_data])
+    print(n)
+
+    with open(args.output_matrix_file, 'w') as matrix_file:
+        json.dump(n.tolist(), matrix_file)
+
+    candidates = json.load(args.candidates_file)
+
+    g = pairwise_preferences_graph(n, candidates)
+    with open(args.output_graph_file, 'w') as graph_file:
+        graph_file.write(g.to_string())
+
+    #print(args)
+    #raw_data = [[0,0,0,0,0,0],[1,2,3,4,5,5],[1,2,3,0,0,0],[0,0,0,0,0,0],[1,2,3,4,5,5]]
+
+    #(n, nb_candidates, nb_voters, nb_blank) = pairwise_preferences_matrix(raw_data)
diff --git a/test_schulze_examples.py b/test_schulze_examples.py
new file mode 100644
index 0000000000000000000000000000000000000000..1272428ce63e528471beacc15e2619d049193d79
--- /dev/null
+++ b/test_schulze_examples.py
@@ -0,0 +1,402 @@
+#!/usr/bin/env python3
+import numpy as np
+
+import preference_counter
+import elect
+
+# all examples are from Section 3 of Markus Schulze's "The Schulze Method of Voting",
+# version 13 (latest as I write these lines: 2023-07-14). https://arxiv.org/pdf/1804.02973.pdf
+
+def test_example1():
+    candidates = ['a', 'b', 'c', 'd']
+    ballots =   [[  1,   4,   2,   3]] * 8 + \
+                [[  2,   1,   4,   3]] * 2 + \
+                [[  4,   3,   1,   2]] * 4 + \
+                [[  3,   2,   4,   1]] * 4 + \
+                [[  4,   3,   2,   1]] * 3
+
+    (n, nb_candidates, nb_voters, nb_blank) = preference_counter.pairwise_preferences_matrix(ballots)
+    expected_n = np.array([[ 0,  8, 14, 10],
+                           [13,  0,  6,  2],
+                           [ 7, 15,  0, 12],
+                           [11, 19,  9,  0]], dtype=np.int8)
+    assert nb_candidates == len(candidates)
+    assert nb_voters == 8+2+4+4+3
+    assert nb_blank == 0
+    assert np.array_equal(n, expected_n)
+
+    assert elect.condorcet_winner(n, candidates) is None
+    assert len(elect.weak_condorcet_winners(n, candidates)) == 0
+    assert elect.schulze_winners(n, candidates) == ['d']
+
+
+def test_example2():
+    candidates = ['a', 'b', 'c', 'd']
+    ballots =   [[  1,   4,   2,   3]] * 3 + \
+                [[  2,   1,   3,   4]] * 9 + \
+                [[  3,   4,   1,   2]] * 8 + \
+                [[  2,   3,   4,   1]] * 5 + \
+                [[  4,   2,   3,   1]] * 5
+
+    (n, nb_candidates, nb_voters, nb_blank) = preference_counter.pairwise_preferences_matrix(ballots)
+    expected_n = np.array([[ 0, 16, 17, 12],
+                           [14,  0, 19,  9],
+                           [13, 11,  0, 20],
+                           [18, 21, 10,  0]], dtype=np.int8)
+    assert nb_candidates == len(candidates)
+    assert nb_voters == 3+9+8+5+5
+    assert nb_blank == 0
+    assert np.array_equal(n, expected_n)
+
+    assert elect.condorcet_winner(n, candidates) is None
+    assert len(elect.weak_condorcet_winners(n, candidates)) == 0
+    assert elect.schulze_winners(n, candidates) == ['c']
+
+
+def test_example3():
+    candidates = ['a', 'b', 'c', 'd', 'e']
+    ballots =   [[  1,   3,   2,   5,   4]] * 5 + \
+                [[  1,   5,   4,   2,   3]] * 5 + \
+                [[  4,   1,   5,   3,   2]] * 8 + \
+                [[  2,   3,   1,   5,   4]] * 3 + \
+                [[  2,   4,   1,   5,   3]] * 7 + \
+                [[  3,   2,   1,   4,   5]] * 2 + \
+                [[  5,   4,   2,   1,   3]] * 7 + \
+                [[  3,   2,   5,   4,   1]] * 8
+
+    (n, nb_candidates, nb_voters, nb_blank) = preference_counter.pairwise_preferences_matrix(ballots)
+    expected_n = np.array([[ 0, 20, 26, 30, 22],
+                           [25,  0, 16, 33, 18],
+                           [19, 29,  0, 17, 24],
+                           [15, 12, 28,  0, 14],
+                           [23, 27, 21, 31,  0]], dtype=np.int8)
+    assert nb_candidates == len(candidates)
+    assert nb_voters == 5+5+8+3+7+2+7+8
+    assert nb_blank == 0
+    assert np.array_equal(n, expected_n)
+
+    assert elect.condorcet_winner(n, candidates) is None
+    assert len(elect.weak_condorcet_winners(n, candidates)) == 0
+    assert elect.schulze_winners(n, candidates) == ['e']
+
+
+def test_example4():
+    candidates = ['a', 'b', 'c', 'd']
+    ballots =   [[  1,   2,   3,   4]] * 3 + \
+                [[  4,   2,   1,   3]] * 2 + \
+                [[  2,   3,   4,   1]] * 2 + \
+                [[  4,   2,   3,   1]] * 2
+
+    (n, nb_candidates, nb_voters, nb_blank) = preference_counter.pairwise_preferences_matrix(ballots)
+    expected_n = np.array([[ 0,  5,  5,  3],
+                           [ 4,  0,  7,  5],
+                           [ 4,  2,  0,  5],
+                           [ 6,  4,  4,  0]], dtype=np.int8)
+    assert nb_candidates == len(candidates)
+    assert nb_voters == 3+2+2+2
+    assert nb_blank == 0
+    assert np.array_equal(n, expected_n)
+
+    assert elect.condorcet_winner(n, candidates) is None
+    assert len(elect.weak_condorcet_winners(n, candidates)) == 0
+    assert elect.schulze_winners(n, candidates) == ['b', 'd']
+
+
+def test_example5():
+    candidates = ['a', 'b', 'c', 'd']
+    ballots =   [[  1,   2,   3,   4]] * 12 + \
+                [[  1,   3,   4,   2]] * 6 + \
+                [[  4,   1,   2,   3]] * 9 + \
+                [[  3,   4,   1,   2]] * 15 + \
+                [[  3,   2,   4,   1]] * 21
+
+    (n, nb_candidates, nb_voters, nb_blank) = preference_counter.pairwise_preferences_matrix(ballots)
+    expected_n = np.array([[ 0, 33, 39, 18],
+                           [30,  0, 48, 21],
+                           [24, 15,  0, 36],
+                           [45, 42, 27,  0]], dtype=np.int8)
+    assert nb_candidates == len(candidates)
+    assert nb_voters == 12+6+9+15+21
+    assert nb_blank == 0
+    assert np.array_equal(n, expected_n)
+
+    assert elect.condorcet_winner(n, candidates) is None
+    assert len(elect.weak_condorcet_winners(n, candidates)) == 0
+    assert elect.schulze_winners(n, candidates) == ['d']
+
+
+def test_example6():
+    candidates = ['a', 'b', 'c', 'd']
+    ballots =   [[  1,   4,   2,   3]] * 8 + \
+                [[  4,   1,   2,   3]] * 2 + \
+                [[  3,   1,   4,   2]] * 3 + \
+                [[  4,   2,   1,   3]] * 5 + \
+                [[  4,   3,   1,   2]] * 1 + \
+                [[  2,   3,   4,   1]] * 3 + \
+                [[  3,   2,   4,   1]] * 1
+
+    (n, nb_candidates, nb_voters, nb_blank) = preference_counter.pairwise_preferences_matrix(ballots)
+    expected_n = np.array([[ 0, 11, 15,  8],
+                           [12,  0,  9, 10],
+                           [ 8, 14,  0, 16],
+                           [15, 13,  7,  0]], dtype=np.int8)
+    assert nb_candidates == len(candidates)
+    assert nb_voters == 8+2+3+5+1+3+1
+    assert nb_blank == 0
+    assert np.array_equal(n, expected_n)
+
+    assert elect.condorcet_winner(n, candidates) is None
+    assert len(elect.weak_condorcet_winners(n, candidates)) == 0
+    assert elect.schulze_winners(n, candidates) == ['a', 'c']
+
+def test_example7():
+    # situation 1
+    candidates = ['a', 'b', 'c', 'd', 'e', 'f']
+    ballots =   [[  1,   4,   5,   2,   3,   6]] * 3 + \
+                [[  6,   1,   4,   5,   3,   2]] * 3 + \
+                [[  2,   3,   1,   5,   6,   4]] * 4 + \
+                [[  6,   2,   3,   1,   4,   5]] * 1 + \
+                [[  4,   5,   6,   1,   2,   3]] * 4 + \
+                [[  6,   3,   2,   4,   1,   5]] * 2 + \
+                [[  2,   5,   3,   4,   6,   1]] * 2
+
+    (n, nb_candidates, nb_voters, nb_blank) = preference_counter.pairwise_preferences_matrix(ballots)
+    expected_n = np.array([[ 0, 13,  9,  9,  9,  7],
+                           [ 6,  0, 11,  9, 10, 13],
+                           [10,  8,  0, 11,  7, 10],
+                           [10, 10,  8,  0, 14, 10],
+                           [10,  9, 12,  5,  0, 10],
+                           [12,  6,  9,  9,  9,  0]], dtype=np.int8)
+    assert nb_candidates == len(candidates)
+    assert nb_voters == 3+3+4+1+4+2+2
+    assert nb_blank == 0
+    assert np.array_equal(n, expected_n)
+
+    assert elect.condorcet_winner(n, candidates) is None
+    assert len(elect.weak_condorcet_winners(n, candidates)) == 0
+    assert elect.schulze_winners(n, candidates) == ['a']
+
+    # situation 2
+    candidates = ['a', 'b', 'c', 'd', 'e', 'f']
+    ballots2 =  [[  1,   5,   4,   6,   2,   3]] * 2
+    new_ballots = ballots + ballots2
+    (n, nb_candidates, nb_voters, nb_blank) = preference_counter.pairwise_preferences_matrix(new_ballots)
+    expected_n = np.array([[ 0, 15, 11, 11, 11,  9],
+                           [ 6,  0, 11, 11, 10, 13],
+                           [10, 10,  0, 13,  7, 10],
+                           [10, 10,  8,  0, 14, 10],
+                           [10, 11, 14,  7,  0, 12],
+                           [12,  8, 11, 11,  9,  0]], dtype=np.int8)
+    assert nb_candidates == len(candidates)
+    assert nb_voters == 3+3+4+1+4+2+2+2
+    assert nb_blank == 0
+    assert np.array_equal(n, expected_n)
+
+    assert elect.condorcet_winner(n, candidates) is None
+    assert len(elect.weak_condorcet_winners(n, candidates)) == 0
+    assert elect.schulze_winners(n, candidates) == ['d']
+
+
+def test_example8():
+    # situation 1
+    candidates = ['a', 'b', 'c', 'd']
+    ballots =   [[  1,   2,   4,   3]] * 3 + \
+                [[  1,   3,   4,   2]] * 5 + \
+                [[  1,   4,   3,   2]] * 1 + \
+                [[  2,   1,   4,   3]] * 2 + \
+                [[  4,   1,   3,   2]] * 2 + \
+                [[  2,   3,   1,   4]] * 4 + \
+                [[  3,   2,   1,   4]] * 6 + \
+                [[  4,   2,   3,   1]] * 2 + \
+                [[  3,   4,   2,   1]] * 5
+
+    (n, nb_candidates, nb_voters, nb_blank) = preference_counter.pairwise_preferences_matrix(ballots)
+    expected_n = np.array([[ 0, 18, 11, 21],
+                           [12,  0, 14, 17],
+                           [19, 16,  0, 10],
+                           [ 9, 13, 20,  0]], dtype=np.int8)
+    assert nb_candidates == len(candidates)
+    assert nb_voters == 3+5+1+2+2+4+6+2+5
+    assert nb_blank == 0
+    assert np.array_equal(n, expected_n)
+
+    assert elect.condorcet_winner(n, candidates) is None
+    assert len(elect.weak_condorcet_winners(n, candidates)) == 0
+    assert elect.schulze_winners(n, candidates) == ['a']
+
+    # situation 2
+    candidates = ['a', 'b', 'c', 'd', 'e']
+    ballots =   [[  1,   2,   5,   3,   4]] * 3 + \
+                [[  1,   4,   5,   2,   3]] * 5 + \
+                [[  1,   5,   4,   2,   3]] * 1 + \
+                [[  2,   1,   5,   3,   4]] * 2 + \
+                [[  5,   1,   4,   2,   3]] * 2 + \
+                [[  2,   3,   1,   4,   5]] * 4 + \
+                [[  3,   2,   1,   4,   5]] * 6 + \
+                [[  5,   2,   4,   1,   3]] * 2 + \
+                [[  4,   5,   3,   1,   2]] * 5
+
+    (n, nb_candidates, nb_voters, nb_blank) = preference_counter.pairwise_preferences_matrix(ballots)
+    expected_n = np.array([[ 0, 18, 11, 21, 21],
+                           [12,  0, 14, 17, 19],
+                           [19, 16,  0, 10, 10],
+                           [ 9, 13, 20,  0, 30],
+                           [ 9, 11, 20,  0,  0]], dtype=np.int8)
+    assert nb_candidates == len(candidates)
+    assert nb_voters == 3+5+1+2+2+4+6+2+5
+    assert nb_blank == 0
+    assert np.array_equal(n, expected_n)
+
+    assert elect.condorcet_winner(n, candidates) is None
+    assert len(elect.weak_condorcet_winners(n, candidates)) == 0
+    assert elect.schulze_winners(n, candidates) == ['b']
+
+
+def test_example9():
+    # situation 1
+    candidates = ['a', 'b', 'c', 'd']
+    ballots =   [[  1,   4,   2,   3]] * 5 + \
+                [[  4,   1,   2,   3]] * 2 + \
+                [[  3,   1,   4,   2]] * 4 + \
+                [[  3,   4,   1,   2]] * 2
+
+    (n, nb_candidates, nb_voters, nb_blank) = preference_counter.pairwise_preferences_matrix(ballots)
+    expected_n = np.array([[ 0,  7,  9,  5],
+                           [ 6,  0,  6,  6],
+                           [ 4,  7,  0,  9],
+                           [ 8,  7,  4,  0]], dtype=np.int8)
+    assert nb_candidates == len(candidates)
+    assert nb_voters == 5+2+4+2
+    assert nb_blank == 0
+    assert np.array_equal(n, expected_n)
+
+    assert elect.condorcet_winner(n, candidates) is None
+    assert len(elect.weak_condorcet_winners(n, candidates)) == 0
+    assert elect.schulze_winners(n, candidates) == ['a']
+
+    # situation 2
+    candidates = ['a', 'b', 'c', 'd', 'e']
+    ballots =   [[  1,   5,   3,   4,   2]] * 5 + \
+                [[  4,   1,   2,   3,   5]] * 2 + \
+                [[  3,   1,   5,   2,   4]] * 4 + \
+                [[  3,   4,   1,   2,   5]] * 2
+
+    (n, nb_candidates, nb_voters, nb_blank) = preference_counter.pairwise_preferences_matrix(ballots)
+    expected_n = np.array([[ 0,  7,  9,  5, 13],
+                           [ 6,  0,  6,  6,  8],
+                           [ 4,  7,  0,  9,  4],
+                           [ 8,  7,  4,  0,  8],
+                           [ 0,  5,  9,  5,  0]], dtype=np.int8)
+    assert nb_candidates == len(candidates)
+    assert nb_voters == 5+2+4+2
+    assert nb_blank == 0
+    assert np.array_equal(n, expected_n)
+
+    assert elect.condorcet_winner(n, candidates) is None
+    assert len(elect.weak_condorcet_winners(n, candidates)) == 0
+    assert elect.schulze_winners(n, candidates) == ['b']
+
+def test_example10():
+    candidates = ['a', 'b', 'c', 'd']
+    ballots =   [[  1,   2,   3,   4]] * 6 + \
+                [[  1,   1,   2,   2]] * 8 + \
+                [[  1,   2,   1,   2]] * 8 + \
+                [[  1,   3,   1,   2]] * 18 + \
+                [[  1,   2,   1,   1]] * 8 + \
+                [[  2,   1,   2,   2]] * 40 + \
+                [[  4,   2,   1,   3]] * 4 + \
+                [[  3,   4,   1,   2]] * 9 + \
+                [[  2,   2,   1,   1]] * 8 + \
+                [[  2,   3,   4,   1]] * 14 + \
+                [[  4,   2,   3,   1]] * 11 + \
+                [[  3,   4,   2,   1]] * 4
+
+    (n, nb_candidates, nb_voters, nb_blank) = preference_counter.pairwise_preferences_matrix(ballots)
+    expected_n = np.array([[ 0, 67, 28, 40],
+                           [55,  0, 79, 58],
+                           [36, 59,  0, 45],
+                           [50, 72, 29,  0]], dtype=np.int8)
+    assert nb_candidates == len(candidates)
+    assert nb_voters == 6+8+8+18+8+40+4+9+8+14+11+4
+    assert nb_blank == 0
+    assert np.array_equal(n, expected_n)
+
+    assert elect.condorcet_winner(n, candidates) is None
+    assert len(elect.weak_condorcet_winners(n, candidates)) == 0
+    assert elect.schulze_winners(n, candidates) == ['a']
+
+    #assert False, "TODO: implement other methods to compute strength of link"
+
+
+def test_example11():
+    candidates = ['a', 'b', 'c', 'd', 'e']
+    ballots =   [[  1,   3,   5,   2,   4]] * 9 + \
+                [[  3,   1,   2,   4,   5]] * 6 + \
+                [[  5,   1,   2,   3,   4]] * 5 + \
+                [[  5,   3,   1,   2,   4]] * 2 + \
+                [[  5,   4,   3,   1,   2]] * 6 + \
+                [[  2,   4,   3,   5,   1]] * 14 + \
+                [[  3,   4,   2,   5,   1]] * 2 + \
+                [[  3,   5,   4,   2,   1]] * 1
+
+    (n, nb_candidates, nb_voters, nb_blank) = preference_counter.pairwise_preferences_matrix(ballots)
+    expected_n = np.array([[ 0, 26, 24, 31, 15],
+                           [19,  0, 20, 27, 22],
+                           [21, 25,  0, 29, 13],
+                           [14, 18, 16,  0, 28],
+                           [30, 23, 32, 17,  0]], dtype=np.int8)
+    assert nb_candidates == len(candidates)
+    assert nb_voters == 9+6+5+2+6+14+2+1
+    assert nb_blank == 0
+    assert np.array_equal(n, expected_n)
+
+    assert elect.condorcet_winner(n, candidates) is None
+    assert len(elect.weak_condorcet_winners(n, candidates)) == 0
+    assert elect.schulze_winners(n, candidates) == ['b']
+
+
+def test_example12():
+    candidates = ['a', 'b', 'c', 'd', 'e']
+    ballots =   [[  1,   3,   5,   2,   4]] * 9 + \
+                [[  2,   1,   3,   5,   4]] * 1 + \
+                [[  3,   2,   1,   4,   5]] * 6 + \
+                [[  5,   3,   1,   2,   4]] * 2 + \
+                [[  4,   5,   1,   2,   3]] * 5 + \
+                [[  4,   5,   3,   1,   2]] * 6 + \
+                [[  3,   2,   4,   5,   1]] * 14 + \
+                [[  4,   2,   3,   5,   1]] * 2
+
+    (n, nb_candidates, nb_voters, nb_blank) = preference_counter.pairwise_preferences_matrix(ballots)
+    expected_n = np.array([[ 0, 20, 24, 32, 16],
+                           [25,  0, 26, 23, 18],
+                           [21, 19,  0, 30, 14],
+                           [13, 22, 15,  0, 28],
+                           [29, 27, 31, 17,  0]], dtype=np.int8)
+    assert nb_candidates == len(candidates)
+    assert nb_voters == 9+1+6+2+5+6+14+2
+    assert nb_blank == 0
+    assert np.array_equal(n, expected_n)
+
+    assert elect.condorcet_winner(n, candidates) is None
+    assert len(elect.weak_condorcet_winners(n, candidates)) == 0
+    assert elect.schulze_winners(n, candidates) == ['e']
+
+
+def test_example13():
+    candidates = ['a', 'b', 'c']
+    ballots =   [[  1,   2,   3]] * 2 + \
+                [[  3,   1,   2]] * 2 + \
+                [[  2,   3,   1]] * 1
+
+    (n, nb_candidates, nb_voters, nb_blank) = preference_counter.pairwise_preferences_matrix(ballots)
+    expected_n = np.array([[0, 3, 2],
+                           [2, 0, 4],
+                           [3, 1, 0]], dtype=np.int8)
+    assert nb_candidates == len(candidates)
+    assert nb_voters == 2+2+1
+    assert nb_blank == 0
+    assert np.array_equal(n, expected_n)
+
+    assert elect.condorcet_winner(n, candidates) is None
+    assert len(elect.weak_condorcet_winners(n, candidates)) == 0
+    assert elect.schulze_winners(n, candidates) == ['a', 'b']