diff --git a/evidence.inst b/evidence.inst deleted file mode 100644 index 2b91209..0000000 --- a/evidence.inst +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/experiment.py b/experiment.py new file mode 100644 index 0000000..7aa0fc4 --- /dev/null +++ b/experiment.py @@ -0,0 +1,3 @@ + +if __name__ == "__main__": + None diff --git a/factor.py b/factor.py index 0edd343..3196354 100644 --- a/factor.py +++ b/factor.py @@ -1,3 +1,7 @@ +### The main file that was used to run experiments in the paper. +### Defines a simple factor class, a brute force exact inference +### algorithm, lifted orbit generation and orbit-jump MCMC. + from sage.all import * import numpy.random from collections import deque @@ -6,6 +10,7 @@ import my_bliss from my_graphs import * import cProfile, pstats, StringIO +from test import * import itertools import time @@ -38,7 +43,7 @@ def __init__(self, graph, variables, factors, potential): self.variables = variables self.factors = factors self.potential = potential - g = graph.automorphism_group(partition=[variables] + factors) + g = graph.automorphism_group(partition=[variables] + self.factors) self.graph_aut = g # print self.graph_aut self.graph_aut_order = self.graph_aut.order() @@ -83,7 +88,7 @@ def add_vertex(cur_lst, rst): new_lst.append(itm1) new_lst.append(itm2) return add_vertex(new_lst, rst) - tbl = add_vertex([dict()], self.variables) + tbl = add_vertex([dict()], self.variables[:]) res = [] for itm in tbl: l = itm.items() @@ -91,6 +96,27 @@ def add_vertex(cur_lst, rst): res.append(tuple(l)) return res + ### Given a group g, strips the factor generators from that group + def strip_factors(self, g): + stripped_gens = [] + for gen in g.gens(): + sgen = [] + for cycle in gen.cycle_tuples(singletons=True): + # print "checking cycle " + str(cycle) + # check this cycle contains a factor + contains_factor = False + for factor in self.factors: + for e in factor: + # print "checking if " + str(e) + " in " + str(cycle) + if e in cycle: + contains_factor = True + if not contains_factor: + # print "no factor in " + str(cycle) + sgen.append(cycle) + stripped_gens.append(tuple(sgen)) + return PermutationGroup(stripped_gens) + + ### compute partition via exhaustive enumeration using orbit generation def partition(self): @@ -147,6 +173,8 @@ def partition(self): return Z + ### brute forces the partition function by enumerating all possible states + ### for testing and benchmarking purposes def brute_force_partition(self): states = self.gen_all_states() # print "states: " + str(states) @@ -160,20 +188,295 @@ def brute_force_partition(self): Z += self.potential(dict(st)) return Z -def gen_complete_pairwise_factorgraph(n): - (g, (v, factors)) = gen_complete_pairwise_factor(n) - def potential(state): - p = 0.0 - for v in state.itervalues(): - if v: - p += 1 - return p - # make half the factors different colors - # return FactorGraph(g, v, [factors[:len(factors)/2],factors[len(factors)/2:]], potential) - return FactorGraph(g, v, [factors], potential) + ### computes the transition matrix of a single step of the burnside process + def burnside_transition(self): + states = self.gen_all_states() + state_to_idx = dict() + idx_to_state = dict() + for (idx, st) in enumerate(states): + state_to_idx[st] = idx + idx_to_state[idx] = st + + print "states_to_idx: %s" % state_to_idx + transition = np.zeros([len(states),len(states)]) + for (idx, s) in enumerate(states): + var_part = self.state_to_partition(dict(s)) + partition = var_part + stab = self.strip_factors(self.graph.automorphism_group(partition=partition + self.factors)) + order = stab.order() + gelems = stab.list() + for e in gelems: + row_states = [dict()] + # build of list of states which are transitioned to + cyc_tuples = e.cycle_tuples(singletons=True) + for cyc in cyc_tuples: + new_states = [] + for state in row_states: + st1 = state.copy() + st2 = state.copy() + for i in cyc: + st1[i] = True + st2[i] = False + new_states.append(st1) + new_states.append(st2) + row_states = new_states + for st in row_states: + l = st.items() + l.sort() + cur_idx = state_to_idx[tuple(l)] + transition[idx,cur_idx] += (1.0 / order) * (1.0 / (2**len(cyc_tuples))) + return transition + + ### computes the transition matrix for a Gibbs step + def gibbs_transition(self): + states = self.gen_all_states() + state_to_idx = dict() + idx_to_state = dict() + for (idx, st) in enumerate(states): + state_to_idx[st] = idx + idx_to_state[idx] = st + + transition = np.zeros([len(states),len(states)]) + for (idx, s) in enumerate(states): + for v in self.variables: + # compute two resulting new states + st1 = dict(s) + st2 = dict(s) + st1[v] = True + st2[v] = False + + st1prob = self.potential(st1) + st1 = st1.items() + st1.sort() + st1 = tuple(st1) + st1idx = state_to_idx[st1] + + st2prob = self.potential(st2) + st2 = st2.items() + st2.sort() + st2 = tuple(st2) + st2idx = state_to_idx[st2] + if st1prob + st2prob > 0: + transition[idx, st1idx] += ((1.0/ len(self.variables)) * float(st1prob)/ (st1prob + st2prob)) + transition[idx, st2idx] += ((1.0 / len(self.variables)) * float(st2prob)/ (st1prob + st2prob)) + else: + # stay + s_idx = state_to_idx[s] + transition[s_idx, st1idx] += 1.0 / len(self.variables) + return transition + + ### compute transition matrix of a within-orbit step, for implementing + ### lifted MCMC + def orbit_transition(self): + states = self.gen_all_states() + state_to_idx = dict() + idx_to_state = dict() + for (idx, st) in enumerate(states): + state_to_idx[st] = idx + idx_to_state[idx] = st + + transition = np.zeros([len(states),len(states)]) + for (idx, s) in enumerate(states): + st_dict = dict(s) + stripped = self.strip_factors(self.graph_aut) + for g in stripped.list(): + cur_s = dict() + for cyc in g.cycle_tuples(singletons=True): + for i, var in enumerate(cyc): + cur_s[var] = st_dict[cyc[(i + 1) % len(cyc)]] + st = cur_s.items() + st.sort() + st = tuple(st) + + new_idx = state_to_idx[st] + transition[idx, new_idx] += 1.0 / self.graph_aut_order + return transition + + ### computes the metropolis hastings transition matrix for a burnside + ### proposal of `burnsidesteps` steps + def burnside_mh_transition(self, burnsidesteps): + # now apply the metropolis correction for the transition x -> y, where + # each entry in `transition` contains the burnside transition + # probability + states = self.gen_all_states() + state_to_idx = dict() + idx_to_state = dict() + for (idx, st) in enumerate(states): + state_to_idx[st] = idx + idx_to_state[idx] = st + + aut_cache = dict() + B = np.linalg.matrix_power(self.burnside_transition(), burnsidesteps) + for x in range(0, len(states)): + for y in range(0, len(states)): + st_x = idx_to_state[x] + part_x = self.state_to_partition(dict(st_x)) + orbx = None + if st_x in aut_cache: + orbx = aut_cache[st_x] + else: + orbx = self.graph_aut_order / \ + self.graph.automorphism_group(partition=self.state_to_partition(dict(st_x)) + self.factors).order() + aut_cache[st_x] = orbx + prx = self.potential(dict(st_x)) + st_y = idx_to_state[y] + orby = None + if st_y in aut_cache: + orby = aut_cache[st_y] + else: + orby = self.graph_aut_order / \ + self.graph.automorphism_group(partition=self.state_to_partition(dict(st_y)) + self.factors).order() + aut_cache[st_y] = orby + + # orby = self.graph_aut_order / self.graph.automorphism_group(partition=self.state_to_partition(dict(st_y))).order() + pry = self.potential(dict(st_y)) + if prx != 0.0: + B[x,y] = B[x,y] * np.minimum(1, (pry * orby) / (prx * orbx)) + # compute probability of staying in the current position + prob_stay = 0.0 + for yp in range(0, len(states)): + prob_stay += B[x,yp] + prob_stay = 1.0 - prob_stay + B[x,x] = B[x,x] + prob_stay + return B + + def brute_force_prob_vector(self): + states = self.gen_all_states() + state_to_idx = dict() + idx_to_state = dict() + for (idx, st) in enumerate(states): + state_to_idx[st] = idx + idx_to_state[idx] = st + Z = 0.0 + for st in states: + Z += self.potential(dict(st)) + # return the vector + vec = np.zeros(len(states)) + for st in states: + vec[state_to_idx[st]] = self.potential(dict(st)) / Z + + return vec + + ### compute the total variation distance of the factor graph from its + ### stationary distribution + ### for each time step t, print d_tv(stationary_dist, transition_matrix^t * starting_point) + ### transition_matrix: describes transition probabilities between states + ### starting_point: initial probability vector on states + ### num_steps: total number of steps for which to run + def total_variation(self, transition_matrix, starting_point, num_steps): + v = self.brute_force_prob_vector() + T = transition_matrix + for i in range(1, num_steps): + T = np.matmul(T, transition_matrix) + p = starting_point.dot(T) + d = 0.0 + for idx in range(0, len(v)): + d += abs(v[idx] - p[idx]) + print("%s\t%s" % (i, d)) + + ### perform a single step of orbit jumping + ### returns: a pair, (the ratio of transition probabilities, new state) + ### n: number of burnside steps to take + def orbitjump(self, state, n): + hatx = self.burnside(state, n) + probx = self.potential(state) + probhatx = self.potential(hatx) + orbx = self.graph_aut_order / \ + self.graph.automorphism_group(partition=self.state_to_partition(state) + self.factors).order() + orbhatx = self.graph_aut_order / \ + self.graph.automorphism_group(partition=self.state_to_partition(hatx) + self.factors).order() + try: + transitionprob = (probhatx * orbhatx) / (probx * orbx) + return (transitionprob, hatx) + except: + # divided by 0 + return (1.0, hatx) + + ### perform a standard orbital MCMC gibbs update, a la Niepert 2012 + ### state: a state + ### returns: the gibbs update state + def orbitgibbs(self, state): + v = sage.misc.prandom.choice(self.variables) + # resample the variable + v_true = state.copy() + v_true[v] = True + v_false = state.copy() + v_false[v] = False + prob = None + try: + prob = self.potential(v_true) / (self.potential(v_true) + self.potential(v_false)) + except: + return state # evidence was not satisfied + new_v = numpy.random.binomial(1, prob) + state[v] = new_v + + # now walk along the orbit + g = fast_random_element(self.graph_aut) + # apply g to the state + for cyc in g: + fst = state[cyc[0]] + for idx, var in enumerate(cyc): + state[var] = state[cyc[(idx + 1) % len(cyc)]] + state[cyc[-1]] = fst + return state + + ### draw n samples according to orbit jump MCMC with no orbital MCMC + ### burnsidesize: number of burnside steps to take + ### n: int, total number of samples to take + ### gamma: int, number of steps between taking orbit jumps + ### burn: the burn in of the chain + ### returns the probability of the query + def orbitjumpmcmc(self, n, query, burnsidesize=10, gamma=10, burn=100): + samples = [] + # set up initial random state + cur_state = dict() + for v in self.variables: + cur_state[v] = flip() + + query_count = 0.0 + cur_step = 0 + + for i in range(0, n * burn): + if (cur_step % gamma) == 0: + # do a jump update + (ratio, new_state) = self.orbitjump(cur_state, burnsidesize) + # accept with transition probability + acceptprob = numpy.minimum(1, ratio) + if numpy.random.binomial(1, acceptprob): + cur_state = new_state + else: + # do a gibbs update + cur_state = self.orbitgibbs(cur_state) + + if cur_step % burn == 0: + if query(cur_state): + query_count += 1 + cur_step += 1 + return query_count / n if __name__ == "__main__": - fg = gen_complete_pairwise_factorgraph(10) - print fg.partition() - print fg.brute_force_partition() + model = gen_complete_pairwise_factorgraph(6) + gibbs = model.gibbs_transition() + # print(gibbs) + # print(sum(gibbs)) + within_orbit = model.orbit_transition() + orbitalmcmc = np.matmul(within_orbit, gibbs) + # unif = model.uniform_transition() + burnside = model.burnside_mh_transition(4) + M = orbitalmcmc + + pv = model.brute_force_prob_vector() + start = np.zeros([2**len(model.variables)]) + start[10] = 1 + # print(np.linalg.matrix_power(M, 5)) + print("-------------------") + print("pure gibbs") + model.total_variation(gibbs, start, 100) + print("------------------") + print("pure jump") + model.total_variation(burnside, start, 100) + + + # print fg.partition() + # print fg.brute_force_partition() diff --git a/markov.py b/markov.py index 4c12242..7256098 100644 --- a/markov.py +++ b/markov.py @@ -1,3 +1,7 @@ +### orbit generation for symmetric Markov networks +### very similar to factor.py; see that file for the main code used +### in the experiments + from sage.all import * import numpy.random from collections import deque @@ -29,7 +33,7 @@ def fast_random_element(g): class MarkovModel: ### graph: a sage graph - ### variables: a list of graph vertices which correspond to variables + ### variables: a list of graph vertices which correspond to variables in the factor graph ### potential: state -> real: a function which evaluates the potential on a particular state ### a state is a dictionary assigning variables to Boolean values def __init__(self, graph, variables, potential, order=True): @@ -543,7 +547,15 @@ def trivial_query(state): return supp_explored - +def gen_complete_pairwise_factorgraph(n): + (g, (v, factors)) = gen_complete_pairwise_factor(n) + def potential(state): + p = 0.0 + for v in state.itervalues(): + if v: + p += 1 + return p + return FactorGraph(g, v, [factors], potential) def run_burnside(): cur_state = dict() diff --git a/my_graphs.py b/my_graphs.py index 1b43d33..26a4bf7 100644 --- a/my_graphs.py +++ b/my_graphs.py @@ -1,31 +1,12 @@ +### utility file for generating useful factor graphs, and graphs used +### in the experiments + from sage.all import * import itertools def findsubsets(S,m): return set(itertools.combinations(S, m)) -### generates a friends and smokers graph with n people -def gen_friends_smokers(n): - g = graph(sparse=true) - # make n smoker vertices - smokers = [x for x in range(0,n)] - # connect all the smokers - smokeredges = findsubsets(smokers, 2) - # make friends - friends = [] - friendedges = [] - count = n - for (s1,s2) in findsubsets(smokers, 2): - friends += [count] - friendedges += [(s1, count), (s2, count)] - count += 1 - - g.add_vertices(smokers) - g.add_vertices(friends) - g.add_edges(friendedges) - g.add_edges(smokeredges) - return g - ### generates a complete pairwise factor graph ### returns a the graph and a tuple whose first element are the variables ### and second element are the factors diff --git a/orbitgen.py b/orbitgen.py index 7650ca6..81f542a 100644 --- a/orbitgen.py +++ b/orbitgen.py @@ -1,3 +1,7 @@ +### orbit generation for Markov networks +### all cliques are assumed to be symmetric and identical +### this file is for experimenting; it is not what was used in the paper + from sage.all import * from my_graphs import * import cProfile, pstats, StringIO @@ -81,7 +85,7 @@ def bfs_foldrep(graph, colors, fixcolors, acc, f, orders=False): else: acc = f(acc, graph, c) reps.add((gcanon, (tuple(c_canon[0]), tuple(c_canon[1])))) - print(len(reps)) + # print(len(reps)) if len(c_canon[0]) + 1 <= len(colors) / 2.0: # if we can add more colors, try to @@ -154,7 +158,7 @@ def find_representatives(): sortby = 'cumulative' ps = pstats.Stats(pr, stream=s).sort_stats(sortby) ps.print_stats() - print s.getvalue() + # print s.getvalue() if __name__ == "__main__": diff --git a/query.py b/query.py deleted file mode 100644 index 2945724..0000000 --- a/query.py +++ /dev/null @@ -1,227 +0,0 @@ -from sage.all import * -from my_graphs import * -import cProfile, pstats, StringIO -from collections import deque -import my_bliss -from orbitgen import * - -### partition_function -### computes the partition of a fully symmetric MLN the specified parameter -### -### potential: a function which maps variable truth assignments to -### probabilities. This function *must* be invariant wrt. the automorphism -### group of the graph. -def partition(G, variables, factors, potential): - # folding function - print("G: %s, vars: %s, factors: %s" % (G, variables, factors)) - def sum_prob(acc, g, color, A): - # TODO: avoid recomputing these two automorphism groups - g_order = g.automorphism_group().order() - aut_order = A.order() - orbit_sz = g_order / aut_order # yay orbit stabilizer theorem! - if len(color[0]) < len(g.vertices()) / 2.0: - return acc + (orbit_sz * potential(color)) + (orbit_sz * potential(color[::-1])) - - return acc + (orbit_sz * potential(color)) - return bfs_foldrep(G, variables, factors, 0.0, sum_prob) - - -def compute_partition(): - G = gen_complete_pairwise_factor(50) - def potential(assgn): - # count potential: potential is # incoming nodes which are true - p = 0.0 - for factor in G[1][1]: - connected = G[0].neighbors(factor) - for v in connected: - if v in assgn[0]: - p += 1 - return p - - pr = cProfile.Profile() - pr.enable() - - part = partition(G[0], G[1][0], [G[1][1]], potential) - print("partition: %d" % part) - # print("brute forced: %d" % (bruteforce_partition(G, partfun))) - - pr.disable() - s = StringIO.StringIO() - sortby = 'cumulative' - ps = pstats.Stats(pr, stream=s).sort_stats(sortby) - ps.print_stats() - print s.getvalue() - - - -def mpe(G, variables, factors, potential): - # folding function - print("G: %s, vars: %s, factors: %s" % (G, variables, factors)) - def max_prob(acc, g, color): - (cur_max_state, cur_max_value) = acc - if len(color[0]) < len(variables) / 2.0: - # check both possibilities - pot = potential(color[::-1]) - if cur_max_value < pot: - cur_max_value = pot - cur_max_state = color[::-1] - pot = potential(color) - if cur_max_value < pot: - cur_max_value = pot - cur_max_state = color - return (cur_max_state, cur_max_value) - return bfs_foldrep(G, variables, factors, (None, 0.0), max_prob) - - -# potential returns a pair (prob, const) which is the probability and -# normalizing constant on a particular orbit -def prob(G, variables, factors, potential): - # folding function - def sum_prob(acc, g, color, g_order, cur_order): - cur_sz = g_order / cur_order # yay orbit stabilizer theorem! - (cur_prob, cur_z) = acc - if len(color[0]) < len(variables) / 2.0: - # check both possibilities - (prob, z) = potential(color[::-1]) - cur_prob += prob * cur_sz - cur_z += z * cur_sz - (prob, z) = potential(color) - cur_prob += prob * cur_sz - cur_z += z * cur_sz - return (cur_prob, cur_z) - return bfs_foldrep(G, variables, factors, (0.0, 0.0), sum_prob, orders=True) - - -def compute_prob_complete_2factor(): - G = gen_complete_pairwise_factor(55) - # add evidence: the first variable is false - G[0].add_vertex(name="e") - G[0].add_edge(("e", G[1][0][0])) - def potential(assgn): - # print("potential eval: %s" % assgn) - p = 0.0 - # check for evidence - for factor in G[1][1]: - connected = G[0].neighbors(factor) - val1 = connected[0] in assgn[0] - val2 = connected[1] in assgn[1] - if val1 != val2: - p += 0.3 - else: - p += 0.2 - for v in connected: - if v in assgn[0]: - p += 1 - if G[1][0][0] in assgn[0]: - return (0.0, p) - else: - return (p, p) - - pr = cProfile.Profile() - pr.enable() - - res = prob(G[0], G[1][0], [G[1][1], ["e"]], potential) - print("prob: %f" % (res[0] / res[1])) - # print("brute forced: %d" % (bruteforce_partition(G, partfun))) - - pr.disable() - s = StringIO.StringIO() - sortby = 'cumulative' - ps = pstats.Stats(pr, stream=s).sort_stats(sortby) - ps.print_stats() - print s.getvalue() - -def compute_prob_big_factor(): - G = gen_single_big_factor(2) - # add evidence: the first variable is false - G[0].add_vertex(name="e") - G[0].add_edge(("e", G[1][0][0])) - def potential(assgn): - p = 0.0 - for v in assgn[0]: - p += 1 - - if G[1][0][0] in assgn[0]: - return (0.0, p) - else: - return (p, p) - - pr = cProfile.Profile() - pr.enable() - - res = prob(G[0], G[1][0], [G[1][1], ["e"]], potential) - print("prob %f" % (res[0] / res[1])) - # print("brute forced: %d" % (bruteforce_partition(G, partfun))) - - pr.disable() - s = StringIO.StringIO() - sortby = 'cumulative' - ps = pstats.Stats(pr, stream=s).sort_stats(sortby) - ps.print_stats() - print s.getvalue() - -def compute_mpe_big_factor(): - G = gen_single_big_factor(300) - # add evidence: the first variable is false - G[0].add_vertex(name="e") - G[0].add_edge(("e", G[1][0][0])) - def potential(assgn): - p = 0.0 - for v in assgn[0]: - p += 1 - - if G[1][0][0] in assgn[0]: - return 0.0 - else: - return p - - pr = cProfile.Profile() - pr.enable() - - res = mpe(G[0], G[1][0], [G[1][1], ["e"]], potential) - print("mpe %s, %s" % (res[0], res[1])) - # print("brute forced: %d" % (bruteforce_partition(G, partfun))) - - pr.disable() - s = StringIO.StringIO() - sortby = 'cumulative' - ps = pstats.Stats(pr, stream=s).sort_stats(sortby) - ps.print_stats() - print s.getvalue() - -def compute_mpe_full_pairwise_factor(): - G = gen_complete_pairwise_factor(50) - # add evidence: the first variable is false - G[0].add_vertex(name="e") - G[0].add_edge(("e", G[1][0][0])) - def potential(assgn): - p = 0.0 - for v in assgn[0]: - p += 1 - - if G[1][0][0] in assgn[0]: - return 0.0 - else: - return p - - pr = cProfile.Profile() - pr.enable() - - res = mpe(G[0], G[1][0], [G[1][1], ["e"]], potential) - print("mpe %s, %s" % (res[0], res[1])) - # print("brute forced: %d" % (bruteforce_partition(G, partfun))) - - pr.disable() - s = StringIO.StringIO() - sortby = 'cumulative' - ps = pstats.Stats(pr, stream=s).sort_stats(sortby) - ps.print_stats() - print s.getvalue() - - - -if __name__ == "__main__": - set_gap_memory_pool_size(5000000) - compute_prob_complete_2factor() - # compute_prob_big_factor() - # compute_mpe_big_factor() diff --git a/res.txt b/res.txt deleted file mode 100644 index 7d1e5ce..0000000 --- a/res.txt +++ /dev/null @@ -1,407 +0,0 @@ -[(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4)] -------------------- -pure gibbs -1 1.5981501538664418 -2 1.5004375195247162 -3 1.4496907228487779 -4 1.4182910989845776 -5 1.3981186925395104 -6 1.3849631390089514 -7 1.377777799999998 -8 1.3777777800000028 -9 1.3777777780000016 -10 1.377777777799998 -11 1.3777777777799998 -12 1.3777777777779998 -13 1.3777777777777995 -14 1.3777777777777809 -15 1.3777777777777789 -16 1.3777777777777798 -17 1.3777777777777802 -18 1.3777777777777769 -19 1.3777777777777762 -20 1.3777777777777773 -21 1.3777777777777758 -22 1.3777777777777795 -23 1.3777777777777764 -24 1.3777777777777769 -25 1.3777777777777758 -26 1.3777777777777755 -27 1.3777777777777773 -28 1.377777777777776 -29 1.3777777777777782 -30 1.377777777777775 -31 1.3777777777777787 -32 1.3777777777777782 -33 1.3777777777777778 -34 1.3777777777777744 -35 1.377777777777775 -36 1.3777777777777764 -37 1.3777777777777747 -38 1.377777777777776 -39 1.3777777777777753 -40 1.3777777777777764 -41 1.3777777777777755 -42 1.377777777777775 -43 1.3777777777777775 -44 1.3777777777777747 -45 1.377777777777777 -46 1.3777777777777778 -47 1.3777777777777747 -48 1.3777777777777733 -49 1.3777777777777735 -50 1.377777777777775 -51 1.377777777777776 -52 1.377777777777771 -53 1.3777777777777729 -54 1.3777777777777764 -55 1.3777777777777733 -56 1.3777777777777727 -57 1.3777777777777742 -58 1.3777777777777738 -59 1.377777777777775 -60 1.377777777777776 -61 1.3777777777777747 -62 1.3777777777777742 -63 1.3777777777777749 -64 1.377777777777772 -65 1.3777777777777733 -66 1.3777777777777749 -67 1.3777777777777722 -68 1.3777777777777713 -69 1.3777777777777716 -70 1.3777777777777753 -71 1.3777777777777707 -72 1.3777777777777733 -73 1.3777777777777702 -74 1.3777777777777707 -75 1.3777777777777702 -76 1.3777777777777727 -77 1.3777777777777733 -78 1.3777777777777707 -79 1.3777777777777707 -80 1.377777777777771 -81 1.3777777777777716 -82 1.3777777777777713 -83 1.377777777777771 -84 1.3777777777777716 -85 1.3777777777777693 -86 1.3777777777777724 -87 1.3777777777777698 -88 1.3777777777777702 -89 1.3777777777777702 -90 1.3777777777777707 -91 1.3777777777777698 -92 1.377777777777771 -93 1.3777777777777698 -94 1.377777777777771 -95 1.3777777777777704 -96 1.3777777777777698 -97 1.3777777777777698 -98 1.3777777777777684 -99 1.3777777777777707 ------------------- -pure jump -1 1.6635003723115502 -2 1.5166433359182248 -3 1.3825953516110996 -4 1.2602591788325461 -5 1.1486284933971642 -6 1.0467813252904412 -7 0.9538732652636945 -8 0.883764596250683 -9 0.8444326655038324 -10 0.8068360858839644 -11 0.7709011737698167 -12 0.7365569337568991 -13 0.7037350244697836 -14 0.6723697144309758 -15 0.6423978299006284 -16 0.613758696332558 -17 0.586394074857604 -18 0.5602480950009882 -19 0.5352671846627567 -20 0.5113999982358108 -21 0.48859734360152307 -22 0.46681210862697753 -23 0.44599918768640534 -24 0.42611540864241554 -25 0.4071194606469051 -26 0.388971823056626 -27 0.3716346957022396 -28 0.3550719307012587 -29 0.3392489659645463 -30 0.3241327605100748 -31 0.3096917316681709 -32 0.2958956942361696 -33 0.28271580161945054 -34 0.27012448897707475 -35 0.25809541837515876 -36 0.2466034259383597 -37 0.23562447097922168 -38 0.2251355870764453 -39 0.21511483506641446 -40 0.20554125790627836 -41 0.19639483736286117 -42 0.18765645247807033 -43 0.1793078397590062 -44 0.17133155503937333 -45 0.16371093695743477 -46 0.156430071995329 -47 0.1494737610243802 -48 0.1428274873011619 -49 0.13647738585976046 -50 0.13041021424628954 -51 0.12461332454282445 -52 0.1190746366289855 -53 0.11378261263069665 -54 0.10872623250699996 -55 0.10389497072729391 -56 0.09927877399274633 -57 0.09486803995731417 -58 0.09065359690516432 -59 0.08662668434298745 -60 0.082778934467164 -61 0.07910235446723689 -62 0.07558930962875184 -63 0.07223250719987348 -64 0.06902498098774269 -65 0.0659600766518591 -66 0.06303143766320209 -67 0.06023299189910032 -68 0.05755893884514074 -69 0.05500373737668573 -70 0.052562094093695035 -71 0.05022895218380866 -72 0.047999480789651446 -73 0.045869064857448225 -74 0.04383329544505926 -75 0.041887960468506444 -76 0.04002903586703544 -77 0.03825267716762546 -78 0.036555211430775995 -79 0.03493312956015295 -80 0.03338307895956135 -81 0.03190185652137959 -82 0.03048640193137863 -83 0.029133791275510492 -84 0.027841230934919785 -85 0.026606051756052396 -86 0.025425703483365293 -87 0.02429774944267017 -88 0.023219861463748784 -89 0.022189815031333902 -90 0.02120548465412679 -91 0.02026483944192541 -92 0.019365938881447088 -93 0.018506928801818073 -94 0.01768603752114526 -95 0.01690157216599194 -96 0.016151915155893613 -97 0.01543552084548374 -98 0.014750912317087809 -99 0.014096678317008365 ------------------- -5-stagger -1 1.5981501538664418 -2 1.5004375195247162 -3 1.4496907228487779 -4 1.4182910989845776 -5 1.2976802849144122 -6 1.2252678114941664 -7 1.203277682519918 -8 1.1926152826590317 -9 1.1875231764482665 -10 1.084517289429584 -11 1.033354184418927 -12 1.0227497535327723 -13 1.0222585334638412 -14 1.0222094114569509 -15 0.9316458902375643 -16 0.8856564490286666 -17 0.8803638712259338 -18 0.8799410525277808 -19 0.8798987706579686 -20 0.8019432900106778 -21 0.7620523908135743 -22 0.7578007010379936 -23 0.7574367467550058 -24 0.7574003513267072 -25 0.6902986213160989 -26 0.6559611611459036 -27 0.6523006234481656 -28 0.6519873384318713 -29 0.6519560099302396 -30 0.5941968409295196 -31 0.5646396685123674 -32 0.5614881363466384 -33 0.5612184664833659 -34 0.5611914994970408 -35 0.5114740291415684 -36 0.48603167153918225 -37 0.4833184515315103 -38 0.4830863247735172 -39 0.483063112097719 -40 0.44026762925490565 -41 0.4183672550833013 -42 0.4160314536843645 -43 0.41583164332690337 -44 0.41581166229115646 -45 0.3789743846578366 -46 0.3601229038038671 -47 0.35811206856736694 -48 0.35794007556107066 -49 0.35792287626044283 -50 0.3262142306193522 -51 0.3099871944590654 -52 0.30825614870671225 -53 0.3081081003543189 -54 0.30809329551907766 -55 0.28079922397414786 -56 0.26683127085247876 -57 0.2653411084290785 -58 0.26521367118543904 -59 0.265200927461077 -60 0.24170679878104068 -61 0.22968342923068424 -62 0.2284006470520044 -63 0.2282909514640227 -64 0.22827998190522183 -65 0.20805674466849794 -66 0.19770724131879178 -67 0.1966029910805106 -68 0.19650856717679213 -69 0.19649912478642004 -70 0.1790913896694809 -71 0.1701827225802727 -72 0.1692321654982083 -73 0.1691508871737393 -74 0.16914275934129158 -75 0.154158541569524 -76 0.14649012187469573 -77 0.14567187244615817 -78 0.14560190958962954 -79 0.14559491330397778 -80 0.13269680384886698 -81 0.12609596766208842 -82 0.12539161429210824 -83 0.12533139157805123 -84 0.12532536930664562 -85 0.1142229357153165 -86 0.10854105666956562 -87 0.10793474862892571 -88 0.10788291004673449 -89 0.10787772618851539 -90 0.09832097171222598 -91 0.09343011464219139 -92 0.09290820624137146 -93 0.09286358456256318 -94 0.09285912239468265 -95 0.08463285597825658 -96 0.08042289642725103 -97 0.0799736405248435 -98 0.07993523102104463 -99 0.07993139007066502 -None ------------------- -10-stagger -1 1.5981501538664418 -2 1.5004375195247162 -3 1.4496907228487779 -4 1.4182910989845776 -5 1.3981186925395104 -6 1.3849631390089514 -7 1.377777799999998 -8 1.3777777800000028 -9 1.3777777780000016 -10 1.2558275791818083 -11 1.1936392370877034 -12 1.187046322469131 -13 1.1864755310148118 -14 1.186418451869384 -15 1.1864127439548382 -16 1.1864121731633877 -17 1.186412116084244 -18 1.1864121103763288 -19 1.1864121098055278 -20 1.0805432175357892 -21 1.0260910695080114 -22 1.0203998900894466 -23 1.0199118043442146 -24 1.0198629957696865 -25 1.0198581149122372 -26 1.0198576268264945 -27 1.0198575780179182 -28 1.0198575731370632 -29 1.0198575726489745 -30 0.9288473584406167 -31 0.8820342216852579 -32 0.8771411373813263 -33 0.8767215926664986 -34 0.8766796381950113 -35 0.8766754427478628 -36 0.8766750232031527 -37 0.8766749812486786 -38 0.8766749770532347 -39 0.8766749766336897 -40 0.7984425162873132 -41 0.7582016107627431 -42 0.7539951149359403 -43 0.7536344722050614 -44 0.7535984079319726 -45 0.7535948015046651 -46 0.7535944408619337 -47 0.753594404797659 -48 0.7535944011912354 -49 0.7535944008305923 -50 0.6863455815826366 -51 0.6517542606754316 -52 0.6481381489387478 -53 0.6478281385594645 -54 0.6477971375215369 -55 0.647794037417747 -56 0.6477937274073667 -57 0.647793696406327 -58 0.6477936933062212 -59 0.6477936929962174 -60 0.5899863620776037 -61 0.5602514677532395 -62 0.557142946668039 -63 0.5568764601227036 -64 0.5568498114681747 -65 0.5568471466027209 -66 0.5568468801161734 -67 0.5568468534675185 -68 0.5568468508026574 -69 0.5568468505361686 -70 0.5071554190516555 -71 0.4815951413518653 -72 0.47892299431872126 -73 0.4786939210889535 -74 0.47867101376597354 -75 0.4786687230336783 -76 0.47866849396044814 -77 0.4786684710531288 -78 0.47866846876239244 -79 0.47866846853332023 -80 0.43595348013957225 -81 0.4139817281850074 -82 0.41168471369677767 -83 0.4114878011489741 -84 0.4114681098941938 -85 0.41146614076871757 -86 0.4114659438561663 -87 0.41146592416491073 -88 0.4114659221957896 -89 0.411465921998875 -90 0.3747479073996548 -91 0.35586087267570043 -92 0.3538863355949171 -93 0.35371706853773643 -94 0.35370014183201626 -95 0.3536984491614457 -96 0.353698279894387 -97 0.3536982629676809 -98 0.35369826127501086 -99 0.3536982611057453 -None diff --git a/res2.txt b/res2.txt deleted file mode 100644 index 429491e..0000000 --- a/res2.txt +++ /dev/null @@ -1,407 +0,0 @@ -[(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4)] -------------------- -pure gibbs -1 1.698150153866439 -2 1.4808346980777687 -3 1.309143873397979 -4 1.2074163827911193 -5 1.1794331544729182 -6 1.1508988064973302 -7 1.122647612002081 -8 1.0950897122348837 -9 1.0683993644696108 -10 1.0426255334642647 -11 1.0177545051200771 -12 0.9937442770758776 -13 0.9705427902599796 -14 0.9480971056518989 -15 0.9263576256069854 -16 0.9052796881297306 -17 0.8848238347065381 -18 0.8649554627802005 -19 0.8456442398657603 -20 0.8268634698458546 -21 0.8085895000832174 -22 0.7908012039934188 -23 0.7734795464605585 -24 0.7566072268184205 -25 0.740168389185629 -26 0.7241483888994007 -27 0.7085336045444012 -28 0.6933112865170475 -29 0.6784694346465696 -30 0.6639966988582794 -31 0.6498822981171363 -32 0.6361159539132878 -33 0.6226878353651217 -34 0.6095885136517906 -35 0.596808923979451 -36 0.584340333665098 -37 0.572174315214064 -38 0.5603027234926361 -39 0.5487176762727523 -40 0.5374115375622861 -41 0.5263769032425605 -42 0.5156065886205573 -43 0.5050936175723048 -44 0.49483121300977984 -45 0.48481278844923337 -46 0.47503194049660763 -47 0.4654824420965838 -48 0.4561582364177419 -49 0.44705343126784813 -50 0.4381622939512991 -51 0.42947924649592045 -52 0.4231651561515451 -53 0.41726547133977115 -54 0.41145379796093795 -55 0.40572852255126834 -56 0.40025384296059496 -57 0.39493278243105595 -58 0.38968319567775317 -59 0.38450401854545707 -60 0.37939421732632306 -61 0.37435278604034256 -62 0.3693787440806202 -63 0.3644711341718118 -64 0.359629020597622 -65 0.35485148765935004 -66 0.35013763833304135 -67 0.3454865930972169 -68 0.34089748890736155 -69 0.33636947829650676 -70 0.33190172858432054 -71 0.3274934211795715 -72 0.32314375096294423 -73 0.31885192573906485 -74 0.31461716574816784 -75 0.3104387032291946 -76 0.30631578202722176 -77 0.30224765723921526 -78 0.29823359489286894 -79 0.2942728716540992 -80 0.2903647745592922 -81 0.2865086007690833 -82 0.2827036573408007 -83 0.27894926101712725 -84 0.2752447380289151 -85 0.2715894239103589 -86 0.2679826633249552 -87 0.2644238099009496 -88 0.26091222607511294 -89 0.25744728294385927 -90 0.25402836012089697 -91 0.2506548456006009 -92 0.24732613562660727 -93 0.24404163456492003 -94 0.24080075478125357 -95 0.2376029165220473 -96 0.2344475477988717 -97 0.2313340842759566 -98 0.22826196916050384 -99 0.22523065309562124 ------------------- -pure jump -1 1.6642966230769303 -2 1.5180891721090892 -3 1.3846100643649057 -4 1.26275273280817 -5 1.151506108472766 -6 1.0499529084007047 -7 0.9572579602418637 -8 0.8842042789711523 -9 0.8448776933300486 -10 0.8072842911202411 -11 0.7713505478378481 -12 0.7370056425735051 -13 0.7041814159591341 -14 0.6728123188440481 -15 0.6428353547484863 -16 0.6141900177310565 -17 0.5868182267268957 -18 0.5606642571716318 -19 0.5356746706118769 -20 0.511798242930084 -21 0.4889858917487262 -22 0.4671906035169974 -23 0.44636736072204936 -24 0.4264730696062005 -25 0.40746648871523033 -26 0.38930815854985784 -27 0.3719603325451768 -28 0.3553869095598753 -29 0.33955336802009767 -30 0.3244267018291782 -31 0.3099753581269814 -32 0.2961691769571987 -33 0.28297933288077115 -34 0.27037827855525054 -35 0.25833969028528864 -36 0.24683841553658928 -37 0.23585042239535142 -38 0.2253527509465166 -39 0.21532346653707105 -40 0.2057416148850508 -41 0.19658717899039657 -42 0.18784103780023914 -43 0.1794849265787838 -44 0.17150139892985694 -45 0.16387379041922778 -46 0.15658618374281363 -47 0.14962337538687498 -48 0.14297084372629773 -49 0.1366147185074596 -50 0.13054175166299448 -51 0.12473928940648805 -52 0.11919524555637227 -53 0.11389807603929819 -54 0.10883675452472413 -55 0.10400074914372634 -56 0.09938000024646687 -57 0.09496489915432713 -58 0.09074626786399832 -59 0.08671533966258929 -60 0.08286374061401106 -61 0.07918347187862404 -62 0.07566689282945681 -63 0.07230670492979069 -64 0.06909593633833142 -65 0.06602792720952042 -66 0.06309631565792868 -67 0.06029502435693563 -68 0.05761824774322006 -69 0.05506043979971041 -70 0.05261630239096166 -71 0.05028077412589944 -72 0.0480490197241399 -73 0.045916419863012314 -74 0.04387856148348917 -75 0.04193122853419944 -76 0.04007039313361978 -77 0.03829220713144603 -78 0.03659299405098155 -79 0.03496924139524388 -80 0.03341759330022709 -81 0.03193484351955435 -82 0.030517928725427114 -83 0.029163922111524902 -84 0.027870027284096707 -85 0.026633572428173848 -86 0.025452004736390005 -87 0.02432288508849426 -88 0.023243882970163467 -89 0.022212771620283966 -90 0.02122742339630032 -91 0.020285805347775174 -92 0.019385974988732367 -93 0.018526076259735198 -94 0.01770433567117029 -95 0.016919058619504046 -96 0.01616862586868964 -97 0.015451490189289539 -98 0.014766173148137291 -99 0.014111262041809023 ------------------- -5-stagger -1 1.698150153866439 -2 1.4808346980777687 -3 1.309143873397979 -4 1.2074163827911193 -5 1.1124244537995016 -6 1.062132524054861 -7 1.0360266177521185 -8 1.0116122819652342 -9 0.987941343915132 -10 0.9128213938372848 -11 0.8727344911758068 -12 0.8524630620259319 -13 0.8331718868744643 -14 0.8143449214696604 -15 0.7529169129512082 -16 0.7204886677290868 -17 0.7041661978989955 -18 0.6884666780047636 -19 0.6730517838684639 -20 0.6224434800959633 -21 0.5958185274422243 -22 0.5823899940380026 -23 0.5694318642711197 -24 0.5566847481770549 -25 0.5149201257336584 -26 0.4929613765488317 -27 0.4818477558154032 -28 0.47111349929012714 -29 0.4605491561367371 -30 0.426067053538326 -31 0.40793548986105166 -32 0.39872441104099476 -33 0.38982495565128295 -34 0.3810656532521348 -35 0.3525906524418269 -36 0.3376140757786976 -37 0.32997671759026237 -38 0.3225965934812889 -39 0.3153328334036159 -40 0.2918153034779586 -41 0.27944276799012513 -42 0.2731090241096839 -43 0.26698794487239097 -44 0.2609636889555802 -45 0.24153835022495482 -46 0.23131589481297055 -47 0.22606246829695686 -48 0.22098498594282745 -49 0.21598815683473635 -50 0.19994132135498893 -51 0.19149444218816417 -52 0.18713648547643186 -53 0.1829241647543428 -54 0.17877908073800455 -55 0.16552192598642076 -56 0.15854155400602687 -57 0.15492598496647736 -58 0.15143101329434708 -59 0.14799212950137303 -60 0.13703874619331538 -61 0.1312697607874932 -62 0.12826977016571892 -63 0.12536967789591716 -64 0.12251639839084727 -65 0.11346572879131499 -66 0.10869750480887755 -67 0.10620802221776653 -68 0.10380131699731662 -69 0.10143370082765296 -70 0.09395466749736438 -71 0.09001328789184047 -72 0.08794723616957789 -73 0.0859497936178378 -74 0.08398500308601113 -75 0.07780425853160193 -76 0.07454609659633918 -77 0.07283129622367365 -78 0.0711733754682538 -79 0.0695427383524998 -80 0.0644345695923077 -81 0.06174099824217268 -82 0.060317607919857345 -83 0.05894138302252412 -84 0.05758796202622696 -85 0.053365968109656006 -86 0.05113899700966196 -87 0.049957396628091656 -88 0.048814913982083485 -89 0.04769149521695056 -90 0.044201724264429934 -91 0.04236040112542106 -92 0.04137943996223556 -93 0.04043092756739157 -94 0.03949835532662997 -95 0.03661364365540742 -96 0.035091085140387314 -97 0.03427663175955771 -98 0.033489099316331046 -99 0.03271489714434313 -None ------------------- -10-stagger -1 1.698150153866439 -2 1.4808346980777687 -3 1.309143873397979 -4 1.2074163827911193 -5 1.1794331544729182 -6 1.1508988064973302 -7 1.122647612002081 -8 1.0950897122348837 -9 1.0683993644696108 -10 0.9880013678680437 -11 0.9446540399265517 -12 0.9219563390835029 -13 0.9004587089670862 -14 0.8795962048390444 -15 0.8593462735754633 -16 0.8396888453349743 -17 0.8206018785253159 -18 0.8020617328888057 -19 0.7840446092783693 -20 0.7251674419860771 -21 0.6940308901524225 -22 0.6782055599335887 -23 0.6629925161415584 -24 0.6480815183346829 -25 0.6335055007659031 -26 0.6192852449423946 -27 0.6054296961920802 -28 0.5919390960008453 -29 0.5788081612436603 -30 0.5350122952517339 -31 0.5118287858060974 -32 0.5003210589455367 -33 0.48924878403979344 -34 0.47838209094337714 -35 0.46775100258581714 -36 0.45737452485884383 -37 0.4472615289471582 -38 0.43741354849124714 -39 0.4278274597667582 -40 0.395185643671609 -41 0.37788062870848893 -42 0.36949997734095974 -43 0.3614381983963327 -44 0.3535203624596196 -45 0.3457703767523906 -46 0.33820345528424234 -47 0.330826897273291 -48 0.32364229060155586 -49 0.3166475999643184 -50 0.2922847718651395 -51 0.2793543022281483 -52 0.2732468137426813 -53 0.26737345492979064 -54 0.26160074847344045 -55 0.25594745458765034 -56 0.2504255952781495 -57 0.2450410803297997 -58 0.2397954127062101 -59 0.2346872983412661 -60 0.21647892970285637 -61 0.20680571321094107 -62 0.2023495938760589 -63 0.19806565812583365 -64 0.19385199730384842 -65 0.18972326671890438 -66 0.18568892143190827 -67 0.18175370919835968 -68 0.17791898475128895 -69 0.17418394765166012 -70 0.1605576165653183 -71 0.15331242338712153 -72 0.15005688643147858 -73 0.1469281790081634 -74 0.14384847086633468 -75 0.14082917933865186 -76 0.13787771586905842 -77 0.13499787105138034 -78 0.132190825751934 -79 0.12945610193827978 -80 0.1192461061544205 -81 0.11381314103897432 -82 0.11143150040061339 -83 0.10914342748627576 -84 0.10688946743923267 -85 0.10467849681057834 -86 0.10251630973512595 -87 0.10044169704612858 -88 0.09848232381737335 -89 0.09657446696137367 -90 0.08890848224976648 -91 0.08484901558943266 -92 0.08308078067551257 -93 0.08141820350649241 -94 0.07980295839670265 -95 0.07823179132505839 -96 0.07671179817134646 -97 0.0754203133360711 -98 0.07417222937236342 -99 0.07296176374335095 -None diff --git a/test.py b/test.py index 36ca8b1..d9404b4 100644 --- a/test.py +++ b/test.py @@ -1,7 +1,33 @@ +### defines a test suite for testing basic functionality + from sage.all import * import orbitgen from my_graphs import * import unittest +from factor import * + +# generate a complete pairwise factor graph with half the factors different colors +def gen_complete_pairwise_factorgraph_half(n): + (g, (v, factors)) = gen_complete_pairwise_factor(n) + def potential(state): + p = 0.0 + for v in state.itervalues(): + if v: + p += 1 + return p + # make half the factors different colors + return FactorGraph(g, v, [factors[:len(factors)/2],factors[len(factors)/2:]], potential) + +def gen_complete_pairwise_factorgraph(n): + (g, (v, factors)) = gen_complete_pairwise_factor(n) + def potential(state): + p = 0.0 + for v in state.itervalues(): + if v: + p += 1 + return p + return FactorGraph(g, v, [factors], potential) + def count_num_generated(G): colors = [[], [i for i in G.vertices()]] @@ -45,21 +71,21 @@ def test_star(self): self.assertEqual(orbitgen.count_num_distinct(G), count_num_generated(G)) - def test_friends_smokers(self): - G = gen_friends_smokers(3) - self.assertEqual(orbitgen.count_num_distinct(G), - count_num_generated(G)) - - def test_friends_smokers(self): - G = gen_friends_smokers(4) - self.assertEqual(orbitgen.count_num_distinct(G), - count_num_generated(G)) - def test_aug_complete(self): G = gen_complete_extra(8) self.assertEqual(orbitgen.count_num_distinct(G), count_num_generated(G)) + def test_pairwise(self): + fg = gen_complete_pairwise_factorgraph(10) + self.assertEqual(g.partition(), fg.brute_force_partition) + + def test_half_pairwise(self): + fg = gen_complete_pairwise_factorgraph_half(10) + self.assertEqual(g.partition(), fg.brute_force_partition) + + + if __name__ == '__main__': unittest.main()