def all_generators(self): """Return an iterator on all field's generators""" sz = len(self) - 1 loopends = [sz // f for f in factor(sz)] one = self.one() for x in self: if one not in x.multi_pows(loopends): yield x
def same_divisor_count(i, div_factor_diff, equal, factorcounts, bounds): # remove 0 entries and do bounds check for k, c in div_factor_diff.items(): if c==0: del div_factor_diff[k] else: if i==len(bounds) or abs(c) > bounds[i][k]: return 0 if i==len(factorcounts): assert len(div_factor_diff) == 0 return 2 if equal else 1 key = (i, frozenset(div_factor_diff.items()), equal) if key in _mem: return _mem[key] ret = 0 for j in xrange(factorcounts[i]+1): newequal = (equal and j == factorcounts[i]-j) af, bf = factor(j+1, primes), factor(factorcounts[i]-j+1, primes) div_factor_diff.update(bf) div_factor_diff.subtract(af) ret += same_divisor_count(i+1, div_factor_diff, newequal, factorcounts, bounds) div_factor_diff.subtract(bf) div_factor_diff.update(af) _mem[key] = ret return ret
def GF(q, n=1): factors = factor(q) assert len( factors) == 1 and q > 1, "Cannot create GF with non prime power %d" % q p = factors[0] if q == p: if n == 1: return Zmod(p) else: return Extension(p, n) else: log = 1 while q > p: q = q // p log += 1 f = Extension(p, log) if n == 1: return f else: return Extension(f, n)
def main(): """Solves this problem Calculates the sum of the factors of all numbers under 10000. Then checks each result for amicable numbers. Nothing very special in terms of calculations. Returns: Integer: Solution to this problem """ dn = {} for i in range(1, 10000): dn[i] = sum(factor(i)) amicable = set() for k, v in dn.items(): if k != v and v in dn and dn[v] == k: amicable.add(k) return sum(amicable)
def _is_irreducible_coefs(cls, F, coef): """Rabin irreducibility test""" zero, one = F.zero(), F.one() if cls._is_zero_coefs(zero, coef): return False # Make polynomial monic if coef[-1] != one: inverse = coef[-1]**(-1) coef = cls._scalar_mult_coefs(zero, coef, inverse) modulo = lambda pol: cls._divmod_coefs(zero, pol, coef)[1] deg = cls._deg_coefs(coef) deg_factors = factor(deg) pows = [deg // f for f in reversed(deg_factors)] pows.append(deg) # Calculate `x^(q^deg)` as well # Calc (x^q mod f) and then its powers, make irreducibility tests on the fly q = len(F) cur_val = modulo([zero] * q + [one]) cur_exp = 1 minus_x = [zero, -one] for d in pows: # Calc next power exp = d - cur_exp cur_val = cls._pow_coefs(F, cur_val, int(q**exp), coef) cur_exp = d pol = cls._add_coefs(zero, cur_val, minus_x) # x^(q^d) - x # Do test for current power (except for last power) if d < deg: gcd = cls._gcd_coefs(zero, pol, coef) if gcd != [one]: return False # Final test on `x^(q^deg) - x` if cls._is_zero_coefs(zero, modulo(pol)): return True # else: return False
def generator(self): """Find a generator for F""" if self._g is not None: return self._g sz = len(self) - 1 if sz == 1: self._g = self.one() return self._g # Check g**((n-1)/p) for all factors p of n-1 # g is a generator if and only if none of these powers are `one` one = self.one() loopends = [sz // f for f in factor(sz)] found = False while not found: g = self.rand(nonzero=True) res = g.multi_pows(loopends) if one not in res: found = True self._g = g return g
def main(): """Solves this problem There are probably better solutions to this. Step 1: Calculate all abundant numbers < 28124 Step 2: Sum ALL combinations of these and place into a SET (important) Step 3: Check each number < 28124 if it is in the set above and sum the values that aren't Note: This relies HEAVILY on attributes of sets to quickly index values Returns: Integer: Solution to this problem """ # Step 1: Calculate all abundant numbers < 28124 abundant = [] for i in range(12, 28124): if sum(factor(i)) > i: abundant.append(i) # Step 2: Calculate all possible sums of the abundant numbers < 28124 sums = set() for i in abundant: for j in abundant: s = i + j # This is faster than adding every combination - YMMV if s > 28123: break sums.add(s) # Step 3: Check each number if it was produced via two abundant numbers non_abundant = 0 for n in range(1, 28124): if n not in sums: non_abundant += n return non_abundant
def td_solve(ss, block_list, unknowns, targets, H_U=None, H_U_factored=None, monotonic=False, returnindividual=False, tol=1E-8, maxit=30, noisy=True, save=False, use_saved=False, **kwargs): """Solves for GE nonlinear perfect foresight paths for SHADE model, given shocks in kwargs. Use a quasi-Newton method with the Jacobian H_U mapping unknowns to targets around steady state. Parameters ---------- ss : dict, all steady-state information block_list : list, blocks in model (SimpleBlocks or HetBlocks) unknowns : list, unknowns of SHADE DAG, the 'U' in H(U, Z) targets : list, targets of SHADE DAG, the 'H' in H(U, Z) H_U : [optional] array (nU*nU), Jacobian of targets with respect to unknowns H_U_factored : [optional] tuple, LU decomposition of H_U, save time by supplying this from utils.factor() monotonic : [optional] bool, flag indicating HetBlock policy for some k' is monotonic in state k (allows more efficient interpolation) returnindividual: [optional] bool, flag to return individual outcomes from HetBlock.td tol : [optional] scalar, for convergence of Newton's method we require |H|<tol maxit : [optional] int, maximum number of iterations of Newton's method noisy : [optional] bool, flag to print largest absolute error for each target save : [optional] bool, flag for saving Jacobians inside HetBlocks during calc of H_U use_saved : [optional] bool, flag for using saved Jacobians inside HetBlocks during calc of H_U kwargs : dict, all shocked Z go here, must all have same length T Returns ---------- results : dict, return paths for all aggregate variables, plus individual outcomes of HetBlock if returnindividual """ # check to make sure that kwargs are valid shocks for x in unknowns + targets: if x in kwargs: raise ValueError( f'Shock {x} in td_solve cannot also be an unknown or target!') # infer T from a single shocked Z in kwargs for v in kwargs.values(): T = v.shape[0] break # initialize guess for unknowns to steady state length T Us = {k: np.full(T, ss[k]) for k in unknowns} Uvec = jac.pack_vectors(Us, unknowns, T) # obtain H_U_factored if we don't have it already if H_U_factored is None: if H_U is None: # not even H_U is supplied, get it (costly if there are HetBlocks) H_U = jac.get_H_U(block_list, unknowns, targets, T, ss, save=save, use_saved=use_saved) H_U_factored = utils.factor(H_U) # do a topological sort once to avoid some redundancy sort = utils.block_sort(block_list) # iterate until convergence for it in range(maxit): results = td_map(ss, block_list, sort, monotonic, returnindividual, **kwargs, **Us) errors = {k: np.max(np.abs(results[k])) for k in targets} if noisy: print(f'On iteration {it}') for k in errors: print(f' max error for {k} is {errors[k]:.2E}') if all(v < tol for v in errors.values()): break else: # update guess U by -H_U^(-1) times errors H Hvec = jac.pack_vectors(results, targets, T) Uvec -= utils.factored_solve(H_U_factored, Hvec) Us = jac.unpack_vectors(Uvec, unknowns, T) else: raise ValueError(f'No convergence after {maxit} backward iterations!') return results
def __init__(self, p): FF.__init__(self, p) assert p > 1 and factor(p) == [p], "%r must be a prime integer!" % p
def factor_consequtive(x): factors = utils.factor(x, primes) counts = Counter(factors) for k in counts: yield k ** counts[k]
factors of N! in decreasing order of multiplicity. Last trick is a counting trick: if a<b and a and b have same number of factors, note that we will double count this case if we do not have some extra bookkeeping. Instead of tracking whether a<b in the dp (which is hard), we track whether a==b in the dp (which is much easier), and if the have the same number of factors in the end, we add 2 to the total instead of 1. Since we have now double-counted all the cases, the final answer is achieved halving. """ N = 100 # we need to factor largest multiplicity of anything <= 100 (+1), which will never exceed 100 itself primes = np.nonzero(sieve(N))[0] factors = Counter() for i in xrange(2, N+1): factors.update(factor(i, primes)) _mem = {} def same_divisor_count(i, div_factor_diff, equal, factorcounts, bounds): # remove 0 entries and do bounds check for k, c in div_factor_diff.items(): if c==0: del div_factor_diff[k] else: if i==len(bounds) or abs(c) > bounds[i][k]: return 0 if i==len(factorcounts): assert len(div_factor_diff) == 0 return 2 if equal else 1 key = (i, frozenset(div_factor_diff.items()), equal) if key in _mem: return _mem[key]
def draw_grid(name): N = 100 width = math.log(N, 2) dwg = svgwrite.Drawing( filename=name, debug=True ) limitItems = defaultdict(list) limitCurrent = 0 def coord(i, j): return math.log(i,2)+math.log(j,2), math.log(i,2) def getLineWidth(p, j): k = 1.5/p return k / j def getPointRadius(j): return 0.6/j def getColor(index): h = getHue(index) col = colorsys.hsv_to_rgb( h, 0.7, 0.9 ) return "#%02x%02x%02x" % tuple( map( lambda f: int(f*0xFF), col ) ) scale = 100 def scalePoint(c): return (c[0]+0.5)*scale, (c[1]+0.5)*scale def line(c0,c1, w, stroke): if c1[0] > width: c1 = (width, c1[1]) limitItems[limitCurrent].append(dwg.line(start=scalePoint(c0), end=scalePoint(c1), stroke='white', stroke_width= w*1.2*scale)) limitItems[limitCurrent].append(dwg.line(start=scalePoint(c0), end=scalePoint(c1), stroke=stroke, stroke_width= w*scale)) def point(c,r, fill, i): limitItems[limitCurrent].append(dwg.circle(center=scalePoint(c), r= r*scale, fill= fill)) # minsize = 0.035 s = r*1.8 + minsize c = (c[0], c[1] + s*0.35) #c = (c[0], c[1] + (i%3)*minsize) if getPointRadius(i) <= minsize: c = (c[0], c[1] + (i%3-1)*minsize) limitItems[limitCurrent].append(dwg.text(`i`, scalePoint(c), font_size= s*scale, font_family= "Arial", style="text-anchor:middle;text-align:center")) ns = range(1, N+1) ps = list(itertools.takewhile(lambda p: p <= N, primes())) limitCurrent = 1 point(coord(1, 1), getPointRadius(1), getColor(0), 1) #for pi,p in enumerate(ps): # ji limit for pi,p in enumerate([2,3,5,7]): # ji limit limitCurrent = p fillColor = getColor(pi) # verticals for j in ns: if j>1 and max(factor(j))==p: c0 = coord(1, j) c1 = coord(j, 1) line(c0,c1, getLineWidth(p, j), fillColor) # horizontals for i in ns: for j in ps: if i==1 or max(factor(i*j))==p: if j<=p and i*(j-1)<=N: c0 = coord(i, j-1) c1 = coord(i, j) line(c0,c1, getLineWidth(p, j*i), fillColor) # points for j in ns: if j>1 and max(factor(j))==p: for i in getAllDivisors(j): jj = j/i c0 = coord(i, jj) point(c0, getPointRadius(jj*i), fillColor, jj) for l in sorted(limitItems.keys())[::-1]: group = dwg.add(dwg.g(id='limit'+`l`)) for i in limitItems[l]: group.add(i) dwg.save()