def fixNegsConstrainedOpt(self, to_minimize=norm_diff, badness=1e6): """Uses constrained minimization to find approx q matrix. to_minimize: metric for comparing orig result and new result. badness: scale factor for penalizing negative off-diagonal values. """ if not sum_neg_off_diags(self._data): return self q = ravel(without_diag(self._data)) p = expm(self._data)(t=1) def err_f(q): new_q = reshape(array(q), (4, 3)) new_q = with_diag(new_q, -sum(new_q, 1)) p_new = expm(new_q)(t=1) result = to_minimize(ravel(p), ravel(p_new)) if q.min() < 0: result += -q.min() * badness return result a = array(q) xmin = fmin(func=err_f, x0=a, disp=0) r = reshape(xmin, (4, 3)) new_q = with_diag(r, -sum(r, 1)) return self.__class__(new_q, self.Alphabet)
def fixNegsFmin(self, method=fmin, to_minimize=norm_diff, debug=False): """Uses an fmin method to find a good approximate q matrix. Possible values for method: fmin: simplex method (the default) fmin_bfgs: bfgs optimizer #always produces negative elements! fmin_cg: cg optimizer #doesn't work! fmin_powell: powell method #doesn't work! """ q = self._data #bail out if q is already ok to start with if not sum_neg_off_diags(q): return self err_f = self._make_error_f(to_minimize) initial_guess = q.copy() xmin = method(err_f, initial_guess.flat, disp=0) #disp=0 turns off messages new_q = reshape(xmin, self.Alphabet.Shape)[:] if debug: if sum_neg_off_diags(new_q): raise Exception, 'Made invalid Q matrix: %s' % q return self.__class__(new_q, self.Alphabet)
def fixNegsConstrainedOpt(self, to_minimize=norm_diff, badness=1e6): """Uses constrained minimization to find approx q matrix. to_minimize: metric for comparing orig result and new result. badness: scale factor for penalizing negative off-diagonal values. """ if not sum_neg_off_diags(self._data): return self q = ravel(without_diag(self._data)) p = expm(self._data)(t=1) def err_f(q): new_q = reshape(array(q), (4,3)) new_q = with_diag(new_q, -sum(new_q, 1)) p_new = expm(new_q)(t=1) result = to_minimize(ravel(p), ravel(p_new)) if q.min() < 0: result += -q.min() * badness return result a = array(q) xmin = fmin(func=err_f, x0=a, disp=0) r = reshape(xmin, (4,3)) new_q = with_diag(r, -sum(r, 1)) return self.__class__(new_q, self.Alphabet)
def result(q): new_q = reshape(q, (4,4)) neg_sum = sum_neg_off_diags(new_q) p_new = expm(new_q)(t=1) return to_minimize(ravel(p), ravel(p_new)) - (BIG * neg_sum) \ + (BIG * sum(abs(sum(new_q,1))))
def sumNegOffDiags(self): """Returns sum of negative off-diagonal elements.""" return sum_neg_off_diags(self._data)
def result(q): new_q = reshape(q, (4, 4)) neg_sum = sum_neg_off_diags(new_q) p_new = expm(new_q)(t=1) return to_minimize(ravel(p), ravel(p_new)) - (BIG * neg_sum) \ + (BIG * sum(abs(sum(new_q,1))))