def run(self): #These tasks must be done at the beginning of the run function #as it is not until the run function starts that the program #actually forks, thus if we need tasks to happen in a new process #they must be done here #The numpy random system must have its seen relinitialized in the #new process or each of the sub processes will inherit the same #seed, and produce the same 'random' steps. Such is the downfall #of random numbers in computers. The random.randomint function is #process and thread safe and will produce different random numbers #in each thread. self.myname = mp.current_process().name.split("-")[-1] np.random.seed(random.randint(0,100000)) self.z_view = np.ctypeslib.as_array(self.z_array.get_obj()) self.zview = self.z_view.reshape(self.shape) ########## BART specific for initializing needed objects self.bartc = BARTclass(self.conffile) self.function = self.bartc.run self.bartc.my_init() self.par_p = [] self.chi_p = [] for i in xrange(self.num_sp): randomint = np.random.randint(self.M.value) self.par_p.append(np.copy(self.zview[randomint])) model = self.function(self.par_p[i],self.ind,self.ex) self.chi_p.append(self.chi_func(model,self.data,self.errors,self.ex)) self.chi_p[i] += self.con_func(self.par_p[i],self.const) self.par_c = np.copy(self.par_p) self.chi_c = np.copy(self.chi_p) self.chi_b = np.copy(self.chi_p) self.par_b = np.copy(self.par_p) self.gamma = 2.38/np.sqrt(2*len(self.par_p[0])) self.accept = [0]*self.num_sp self.gen = 0 stop_con = self.its/self.thinning npru = np.random.uniform jrange = xrange(self.num_sp) irange = xrange(self.thinning) con_func = self.con_func function = self.function chi_func = self.chi_func snooker = self.snooker gamma = self.gamma nc = self.nc getvec = self.getvec while self.gen < stop_con: start_time= tm.time() for j in jrange: for i in irange: if npru() < 0.1: self.par_c[j] = self.par_p[j] + snooker(j) else: if npru() < 0.2: bamma = 1 else: bamma = gamma*1/(nc*2) self.par_c[j] = self.par_p[j] + getvec(bamma) con_check = con_func(self.par_c[j],self.const) if con_check == 0: try: model = function(self.par_c[j],self.ind,self.ex) self.chi_c[j] = chi_func(model,self.data, self.errors,self.ex) del model except: print("model failed failed",self.par_c[j]) self.chi_c[j] = 9e99 else: self.chi_c[j] = con_check #self.chi_c[j] += self.con_func(self.par_c[j],self.const) alpha = np.exp(-0.5*(self.chi_c[j] - self.chi_p[j])) if not np.isfinite(alpha): alpha = 0.0 if alpha >=1 or alpha > npru(): self.accept[j] += 1 self.chi_p[j] = self.chi_c[j] self.par_p[j][:] = self.par_c[j][:] if self.chi_c[j] < self.chi_b[j]: self.chi_b[j] = self.chi_c[j] self.par_b[j][:] = self.par_c[j][:] del alpha self.update() self.cleanup() return
class my_process(mp.Process): def __init__(self,itterations,thinning,data,ind,errors,function,\ chi_func,con_func,const,ex,smstp,queuet,z_array,shape,\ M,num_chain,num_split,pre_hist,chi_array): mp.Process.__init__(self) #global z_array self.its = itterations self.thinning = thinning self.data = data self.ind = ind self.errors = errors ############## BART specific, set the extra argument as the conf ############## file. comment out the function assignment, as it is ############## set later in the bart init #self.ex = ex self.conffile = ex[0] #self.function = function self.chi_func = chi_func self.con_func = con_func self.const = const self.ex = ex self.smstp = smstp self.queuet = queuet self.lock = M.get_lock() self.M = M self.nc = num_chain self.num_sp = num_split self.pre_hist = pre_hist self.z_array = z_array self.shape = shape self.z_view = np.ctypeslib.as_array(z_array.get_obj()) self.zview = self.z_view.reshape(shape) self.chi_arr = np.ctypeslib.as_array(chi_array.get_obj()) self.zlocs = [] for i in range(self.num_sp): self.zlocs.append([]) def run(self): #These tasks must be done at the beginning of the run function #as it is not until the run function starts that the program #actually forks, thus if we need tasks to happen in a new process #they must be done here #The numpy random system must have its seen relinitialized in the #new process or each of the sub processes will inherit the same #seed, and produce the same 'random' steps. Such is the downfall #of random numbers in computers. The random.randomint function is #process and thread safe and will produce different random numbers #in each thread. self.myname = mp.current_process().name.split("-")[-1] np.random.seed(random.randint(0,100000)) self.z_view = np.ctypeslib.as_array(self.z_array.get_obj()) self.zview = self.z_view.reshape(self.shape) ########## BART specific for initializing needed objects self.bartc = BARTclass(self.conffile) self.function = self.bartc.run self.bartc.my_init() self.par_p = [] self.chi_p = [] for i in xrange(self.num_sp): randomint = np.random.randint(self.M.value) self.par_p.append(np.copy(self.zview[randomint])) model = self.function(self.par_p[i],self.ind,self.ex) self.chi_p.append(self.chi_func(model,self.data,self.errors,self.ex)) self.chi_p[i] += self.con_func(self.par_p[i],self.const) self.par_c = np.copy(self.par_p) self.chi_c = np.copy(self.chi_p) self.chi_b = np.copy(self.chi_p) self.par_b = np.copy(self.par_p) self.gamma = 2.38/np.sqrt(2*len(self.par_p[0])) self.accept = [0]*self.num_sp self.gen = 0 stop_con = self.its/self.thinning npru = np.random.uniform jrange = xrange(self.num_sp) irange = xrange(self.thinning) con_func = self.con_func function = self.function chi_func = self.chi_func snooker = self.snooker gamma = self.gamma nc = self.nc getvec = self.getvec while self.gen < stop_con: start_time= tm.time() for j in jrange: for i in irange: if npru() < 0.1: self.par_c[j] = self.par_p[j] + snooker(j) else: if npru() < 0.2: bamma = 1 else: bamma = gamma*1/(nc*2) self.par_c[j] = self.par_p[j] + getvec(bamma) con_check = con_func(self.par_c[j],self.const) if con_check == 0: try: model = function(self.par_c[j],self.ind,self.ex) self.chi_c[j] = chi_func(model,self.data, self.errors,self.ex) del model except: print("model failed failed",self.par_c[j]) self.chi_c[j] = 9e99 else: self.chi_c[j] = con_check #self.chi_c[j] += self.con_func(self.par_c[j],self.const) alpha = np.exp(-0.5*(self.chi_c[j] - self.chi_p[j])) if not np.isfinite(alpha): alpha = 0.0 if alpha >=1 or alpha > npru(): self.accept[j] += 1 self.chi_p[j] = self.chi_c[j] self.par_p[j][:] = self.par_c[j][:] if self.chi_c[j] < self.chi_b[j]: self.chi_b[j] = self.chi_c[j] self.par_b[j][:] = self.par_c[j][:] del alpha self.update() self.cleanup() return def cleanup(self): self.queuet.send([self.par_b,self.chi_b,self.accept,self.zlocs]) ##################### BART specific to free up memory self.bartc.trm.free_memory() def update(self): with self.lock: for l in xrange(self.num_sp): self.zview[self.M.value][:] = self.par_p[l][:] self.chi_arr[self.M.value-self.pre_hist] = self.chi_p[l] self.zlocs[l].append(self.M.value) self.M.value += 1 self.gen += 1 def snooker(self,j): randint = np.random.randint(self.M.value-self.nc) ints = self.getrandints(0,self.M.value) #ints = np.random.permutation(self.M.value) direc = self.par_p[j] - self.zview[randint] while np.sum(direc) == 0.0: randint = np.random.randint(self.M.value-self.nc) direc = self.par_p[j] - self.zview[randint] zp1 = np.dot(self.zview[ints[0]],direc)/\ np.dot(direc,direc)*\ direc zp2 = np.dot(self.zview[ints[1]],direc)/\ np.dot(direc,direc)*\ direc return np.random.uniform(1.2,2.2)*(zp1-zp2) def getrandints(self,low,high): ints = np.random.randint(low,high,2) while ints[1] is ints[0]: ints[1] = np.random.randint(low,high) return ints def getvec(self,gamma): #ints = np.random.permutation(np.arange(0,self.M.value)) ints = self.getrandints(0,self.M.value) retval = gamma*(self.zview[ints[0]][:] - self.zview[ints[1]][:]) error = np.zeros((self.smstp.shape)) for i in xrange(len(self.smstp)): if (self.smstp[i] == 0): error[i] = 0 else: error[i] = np.random.normal(0,self.smstp[i]) return retval + error