Skip to content

Commit

Permalink
omg
Browse files Browse the repository at this point in the history
  • Loading branch information
SHoltzen committed Mar 5, 2019
1 parent 2da4cbc commit 88326ff
Showing 1 changed file with 103 additions and 3 deletions.
106 changes: 103 additions & 3 deletions factor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import numpy.random
from collections import deque
import random
import numpy as np
import my_bliss
from my_graphs import *
import cProfile, pstats, StringIO
Expand Down Expand Up @@ -125,7 +126,7 @@ def burnside(self, state, n):
partition = var_part
stab = self.graph.automorphism_group(partition=partition)
p = fast_random_element(stab)
#p = stab.random_element().cycle_tuples(singletons=True)
#p = stab.random_element()cycle_tuples(singletons=True)

# now convert p into a state
# print(p)
Expand All @@ -137,6 +138,95 @@ def burnside(self, state, n):
state[idx] = v
return state

### returns: a list of all possible states (as sorted tuples)
def gen_all_states(self):
def add_vertex(cur_lst, rst):
if len(rst) == 0:
return cur_lst
cur_add = rst.pop()
new_lst = []
for itm in cur_lst:
itm1 = itm.copy()
itm2 = itm.copy()
itm1[cur_add] = False
itm2[cur_add] = True
new_lst.append(itm1)
new_lst.append(itm2)
return add_vertex(new_lst, rst)
tbl = add_vertex([dict()], self.graph.vertices())
res = []
for itm in tbl:
l = itm.items()
l.sort()
res.append(tuple(l))
return res


### computes the transition matrix of a single step of the burnside process
### Z: the normalizing constant for the distribution
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

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.graph.automorphism_group(partition=partition)
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 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

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]
orbx = self.graph.automorphism_group(partition=self.state_to_partition(dict(st_x))).order()
prx = self.potential(dict(st_x))
st_y = idx_to_state[y]
orby = 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))
return B

### perform a single step of orbit jumping
### returns: a pair, (the ratio of transition probabilities, new state)
### n: number of burnside steps to take
Expand Down Expand Up @@ -183,7 +273,7 @@ def orbitgibbs(self, state):
state[cyc[-1]] = fst
return state


# def total_variation(self, burnsidesize):

### draw n samples according to orbit jump MCMC with no orbital MCMC
### burnsidesize: number of burnside steps to take
Expand Down Expand Up @@ -470,6 +560,16 @@ def query(state):
# v1 = graph.orbitjumpmcmc(20, query, gamma=1, burn=2, burnsidesize=5)
# print("exact: %s, approx: %s" % (exact, v1))

def test():
def potential(state):
num_t = 0.0
for v in state.itervalues():
if v:
num_t += 1
return num_t
g = graphs.CompleteGraph(3)
graph = MarkovModel(g, g.vertices(), potential)
print(graph.burnside_mh_transition(4))

if __name__ == "__main__":
experiment_pigeonhole()
test()

0 comments on commit 88326ff

Please sign in to comment.