def problem_4_1(n, t, p, q): """ Take n samples the following model, for k=1,...,t: E_k, E'_k ~ Ber(p) iid X_0, Y_0 ~ Ber(q) iid x_k+1 = (x_k or y_k) xor e_k y_k+1 = (x_k or y_k) xor e'_k """ # e.shape = (2, n_samples, n_iters+1) e = ber(p=p, size=2 * n * (t + 1)).reshape([2, n, t + 1]) # Initial conditions x0, y0 = ber(p=q, size=n), ber(p=q, size=n) # x.shape = y.shape = (n_samples, n_iters+1) x, y = x0.reshape([n, 1]), y0.reshape([n, 1]) for k in range(1, t + 1): x = np.hstack( [x, _xor(_or(x[:, -1], y[:, -1]), e[0, :, k]).reshape([n, 1])]) y = np.hstack( [y, _xor(_or(x[:, -1], y[:, -1]), e[1, :, k]).reshape([n, 1])]) return e, x, y
def set_coefficients(self, F, G): """compute initial coefficients based on some f- and g-values. The formulas to set the coefficients:: lam = iqr(f) / (sqrt(n) * iqr(g)) mu = 2 * iqr(f) / (5 * n * (iqr(g) + iqr(g**2))) are taken out of thin air and not thoroughly tested. They are additionally protected against division by zero. Each row of `G` represents the constraints of one sample measure. Set lam and mu until a population contains more than 10% infeasible and more than 10% feasible at the same time. Afterwards, this at least...?... """ self.F, self.G = F, G # versatile storage if self.mu is not None and all(self._initialized * (self.mu > 0)): return # we're all set G = np.asarray(G).T # now row G[i] contains all values of constraint i sign_average = np.mean(np.sign(G), axis=1) # caveat: equality vs inequality if self.lam is None: # destroys all coefficients self.set_m(len(G)) elif not self._initialized.shape: self.lam_old, self.mu_old = self.lam[:], self.mu[:] # in case the user didn't mean to self._initialized = np.array(self.m * [self._initialized]) self._check_dtypes() idx = _and(_or(_not(self._initialized), self.mu == 0), _or(sign_average > -0.8, self.isequality)) # print(len(F), len(self.G)) if np.any(idx): df = _Mh.iqr(F) dG = np.asarray([_Mh.iqr(g) for g in G]) # only needed for G[idx], but like dG2 = np.asarray([_Mh.iqr(g**2) for g in G]) # this simpler in later indexing if np.any(df == 0) or np.any(dG == 0) or np.any(dG2 == 0): _warnings.warn("iqr(f), iqr(G), iqr(G**2)) == %s, %s, %s" % (str(df), str(dG), str(dG2))) assert np.all(df >= 0) and np.all(dG >= 0) and np.all(dG2 >= 0) # 1 * dG2 leads to much too small values for Himmelblau mu_new = 2. / 5 * df / self.dimension / ( dG + 1e-6 * dG2 + 1e-11 * (df + 1)) # TODO: totally out of thin air idx_inequ = _and(idx, _not(self.isequality)) if np.any(idx_inequ): self.lam[idx_inequ] = df / (self.dimension * dG[idx_inequ] + 1e-11 * (df + 1)) # take min or max with existing value depending on the sign average # we don't know whether this is necessary isclose = np.abs(sign_average) <= 0.2 idx1 = _and( _and( _or(isclose, _and(_not(self.isequality), sign_average <= 0.2)), _or(self.mu == 0, self.mu > mu_new)), idx) # only decrease idx2 = _and( _and( _and(_not(isclose), _or(self.isequality, sign_average > 0.2)), self.mu < mu_new), idx) # only increase idx3 = _and(idx, _not(_or(idx1, idx2))) # others assert np.sum(_and(idx1, idx2)) == 0 if np.any(idx1): # decrease iidx1 = self.mu[idx1] > 0 if np.any(iidx1): self.lam[idx1][ iidx1] *= mu_new[idx1][iidx1] / self.mu[idx1][iidx1] self.mu[idx1] = mu_new[idx1] if np.any(idx2): # increase self.mu[idx2] = mu_new[idx2] if np.any(idx3): self.mu[idx3] = mu_new[idx3] if 11 < 3: # simple version, this may be good enough self.mu[idx] = mu_new[idx] self._initialized[_and( idx, _or( self.count > 2 + self.dimension, # in case sign average remains 1 np.abs(sign_average) < 0.8))] = True elif all(self._initialized) and all(self.mu > 0): _warnings.warn( "Coefficients are already fully initialized. This can (only?) happen if\n" "the coefficients are set before the `_initialized` array.")
import numpy as np from numpy import logical_xor as _xor from numpy import logical_or as _or from numpy import logical_and as _and from numpy import logical_not as _not from scipy.stats import binom import pandas as pd N = int(1e6) ber = binom(p=1 / 2, n=1).rvs u1 = ber u2 = ber fs = [ lambda x, ux, uy: _or(_xor(x, ux), uy), lambda x, ux, uy: _xor(_xor(x, ux), uy), ] def model(f, do=False, N=N): ux = u1(size=N) uy = u2(size=N) x = ber(size=N) if do else ux y = f(x, ux, uy) return (x, y) def table(x, y): b = False, True