def f(fself, question = ("Question:", HtmlBox(self._question)), attempt = ('Answer:',self._answer[1]), submit = UpdateButton('Submit'), feedback = HtmlBox('')): if 'attempt' in fself._changed and attempt != '': attempts.append(attempt) if self._start_time == 0: self._start_time = walltime() self._number_of_attempts += 1 correct, fself.feedback = self._check_attempt(attempt) if correct: cb({'attempts':attempts, 'time':walltime()-self._start_time})
def f(fself, question=("Question:", HtmlBox(self._question)), attempt=('Answer:', self._answer[1]), submit=UpdateButton('Submit'), feedback=HtmlBox('')): if 'attempt' in fself._changed and attempt != '': attempts.append(attempt) if self._start_time == 0: self._start_time = walltime() self._number_of_attempts += 1 correct, fself.feedback = self._check_attempt(attempt) if correct: cb({ 'attempts': attempts, 'time': walltime() - self._start_time })
def _check_attempt(self, attempt): from sage.misc.all import walltime response = "<div class='well'>" correct = False try: r = self._check(attempt) if isinstance(r, tuple) and len(r) == 2: correct = r[0] comment = r[1] else: correct = bool(r) comment = '' except TypeError as msg: response += "<h3 style='color:darkgreen'>Huh? -- %s (attempt=%s)</h3>" % ( msg, attempt) else: if correct: response += "<h1 style='color:blue'>RIGHT!</h1>" if self._start_time: response += "<h2 class='lighten'>Time: %.1f seconds</h2>" % ( walltime() - self._start_time, ) if self._number_of_attempts == 1: response += "<h3 class='lighten'>You got it first try!</h3>" else: response += "<h3 class='lighten'>It took you %s attempts.</h3>" % ( self._number_of_attempts, ) else: response += "<h3 style='color:darkgreen'>Not correct yet...</h3>" if self._number_of_attempts == 1: response += "<h4 style='lighten'>(first attempt)</h4>" else: response += "<h4 style='lighten'>(%s attempts)</h4>" % self._number_of_attempts if self._number_of_attempts > len(self._hints): hint = self._hints[-1] else: hint = self._hints[self._number_of_attempts - 1] if hint: response += "<span class='lighten'>(HINT: %s)</span>" % ( hint, ) if comment: response += '<h4>%s</h4>' % comment response += "</div>" #interact.feedback = response#HtmlBox(response,label='') return correct, response
def _check_attempt(self, attempt): from sage.misc.all import walltime response = "<div class='well'>" correct=False try: r = self._check(attempt) if isinstance(r, tuple) and len(r)==2: correct = r[0] comment = r[1] else: correct = bool(r) comment = '' except TypeError as msg: response += "<h3 style='color:darkgreen'>Huh? -- %s (attempt=%s)</h3>"%(msg, attempt) else: if correct: response += "<h1 style='color:blue'>RIGHT!</h1>" if self._start_time: response += "<h2 class='lighten'>Time: %.1f seconds</h2>"%(walltime()-self._start_time,) if self._number_of_attempts == 1: response += "<h3 class='lighten'>You got it first try!</h3>" else: response += "<h3 class='lighten'>It took you %s attempts.</h3>"%(self._number_of_attempts,) else: response += "<h3 style='color:darkgreen'>Not correct yet...</h3>" if self._number_of_attempts == 1: response += "<h4 style='lighten'>(first attempt)</h4>" else: response += "<h4 style='lighten'>(%s attempts)</h4>"%self._number_of_attempts if self._number_of_attempts > len(self._hints): hint = self._hints[-1] else: hint = self._hints[self._number_of_attempts-1] if hint: response += "<span class='lighten'>(HINT: %s)</span>"%(hint,) if comment: response += '<h4>%s</h4>'%comment response += "</div>" #interact.feedback = response#HtmlBox(response,label='') return correct, response
def ask(self, cb): from sage.misc.all import walltime self._start_time = walltime() self._number_of_attempts = 0 attempts = [] @interact(layout=[[('question',12)],[('attempt',12)], [('submit',12)],[('feedback',12)]]) def f(fself, question = ("Question:", HtmlBox(self._question)), attempt = ('Answer:',self._answer[1]), submit = UpdateButton('Submit'), feedback = HtmlBox('')): if 'attempt' in fself._changed and attempt != '': attempts.append(attempt) if self._start_time == 0: self._start_time = walltime() self._number_of_attempts += 1 correct, fself.feedback = self._check_attempt(attempt) if correct: cb({'attempts':attempts, 'time':walltime()-self._start_time})
def ask(self, cb): from sage.misc.all import walltime self._start_time = walltime() self._number_of_attempts = 0 attempts = [] @interact(layout=[[('question', 12)], [('attempt', 12)], [('submit', 12)], [('feedback', 12)]]) def f(fself, question=("Question:", HtmlBox(self._question)), attempt=('Answer:', self._answer[1]), submit=UpdateButton('Submit'), feedback=HtmlBox('')): if 'attempt' in fself._changed and attempt != '': attempts.append(attempt) if self._start_time == 0: self._start_time = walltime() self._number_of_attempts += 1 correct, fself.feedback = self._check_attempt(attempt) if correct: cb({ 'attempts': attempts, 'time': walltime() - self._start_time })
correct=False try: r = self._check(attempt) if isinstance(r, tuple) and len(r)==2: correct = r[0] comment = r[1] else: correct = bool(r) comment = '' except TypeError, msg: response += "<h3 style='color:darkgreen'>Huh? -- %s (attempt=%s)</h3>"%(msg, attempt) else: if correct: response += "<h1 style='color:blue'>RIGHT!</h1>" if self._start_time: response += "<h2 class='lighten'>Time: %.1f seconds</h2>"%(walltime()-self._start_time,) if self._number_of_attempts == 1: response += "<h3 class='lighten'>You got it first try!</h3>" else: response += "<h3 class='lighten'>It took you %s attempts.</h3>"%(self._number_of_attempts,) else: response += "<h3 style='color:darkgreen'>Not correct yet...</h3>" if self._number_of_attempts == 1: response += "<h4 style='lighten'>(first attempt)</h4>" else: response += "<h4 style='lighten'>(%s attempts)</h4>"%self._number_of_attempts if self._number_of_attempts > len(self._hints): hint = self._hints[-1] else: hint = self._hints[self._number_of_attempts-1]
def __call__(self, f, inputs): """ Parallel iterator using ``fork()``. INPUT: - ``f`` -- a Python function that need not be pickleable or anything else! - ``inputs`` -- a list of pickleable pairs ``(args, kwds)``, where ``args`` is a tuple and ``kwds`` is a dictionary. OUTPUT: EXAMPLES:: sage: F = sage.parallel.use_fork.p_iter_fork(2,3) sage: sorted(list( F( (lambda x: x^2), [([10],{}), ([20],{})]))) [(([10], {}), 100), (([20], {}), 400)] sage: sorted(list( F( (lambda x, y: x^2+y), [([10],{'y':1}), ([20],{'y':2})]))) [(([10], {'y': 1}), 101), (([20], {'y': 2}), 402)] TESTS: The output of functions decorated with :func:parallel is read as a pickle by the parent process. We intentionally break the unpickling and demonstrate that this failure is handled gracefully (an exception is displayed and an empty list is returned):: sage: Polygen = parallel(polygen) sage: list(Polygen([QQ])) [(((Rational Field,), {}), x)] sage: from sage.structure.sage_object import unpickle_override, register_unpickle_override sage: register_unpickle_override('sage.rings.polynomial.polynomial_rational_flint', 'Polynomial_rational_flint', Integer) sage: L = list(Polygen([QQ])) ('__init__() takes at most 2 positional arguments (4 given)', <type 'sage.rings.integer.Integer'>, (Univariate Polynomial Ring in x over Rational Field, [0, 1], False, True)) sage: L [] Fix the unpickling:: sage: del unpickle_override[('sage.rings.polynomial.polynomial_rational_flint', 'Polynomial_rational_flint')] sage: list(Polygen([QQ,QQ])) [(((Rational Field,), {}), x), (((Rational Field,), {}), x)] """ n = self.ncpus v = list(inputs) import os, sys, signal from sage.structure.sage_object import load from sage.misc.all import tmp_dir, walltime dir = tmp_dir() timeout = self.timeout workers = {} try: while len(v) > 0 or len(workers) > 0: # Spawn up to n subprocesses while len(v) > 0 and len(workers) < n: # Subprocesses shouldn't inherit unflushed buffers (cf. #11778): sys.stdout.flush() sys.stderr.flush() pid = os.fork() # The way fork works is that pid returns the # nonzero pid of the subprocess for the master # process and returns 0 for the subprocess. if pid: # This is the parent master process. workers[pid] = [v[0], walltime(), ''] del v[0] else: # This is the subprocess. self._subprocess(f, dir, v[0]) if len(workers) > 0: # Now wait for one subprocess to finish and report the result. # However, wait at most the time since the oldest process started. if timeout: oldest = min([X[1] for X in workers.values()]) alarm(max(timeout - (walltime() - oldest), 0.1)) try: pid = os.wait()[0] cancel_alarm() w = workers.pop(pid) except AlarmInterrupt: cancel_alarm() # Kill workers that are too old for pid, X in workers.iteritems(): if walltime() - X[1] > timeout: if self.verbose: print( "Killing subprocess %s with input %s which took too long" % (pid, X[0])) os.kill(pid, signal.SIGKILL) X[-1] = ' (timed out)' except KeyError: # Some other process exited, not our problem... pass else: # collect data from process that successfully terminated sobj = os.path.join(dir, '%s.sobj' % pid) if not os.path.exists(sobj): X = "NO DATA" + w[-1] # the message field else: X = load(sobj, compress=False) os.unlink(sobj) out = os.path.join(dir, '%s.out' % pid) if not os.path.exists(out): output = "NO OUTPUT" else: output = open(out).read() os.unlink(out) if output.strip(): print output, yield (w[0], X) except Exception as msg: print msg finally: # Clean up all temporary files. try: for X in os.listdir(dir): os.unlink(os.path.join(dir, X)) os.rmdir(dir) except OSError as msg: if self.verbose: print msg # Send "kill -9" signal to workers that are left. if len(workers) > 0: if self.verbose: print "Killing any remaining workers..." sys.stdout.flush() for pid in workers.keys(): try: os.kill(pid, signal.SIGKILL) os.waitpid(pid, 0) except OSError as msg: if self.verbose: print msg
r = self._check(attempt) if isinstance(r, tuple) and len(r) == 2: correct = r[0] comment = r[1] else: correct = bool(r) comment = '' except TypeError, msg: response += "<h3 style='color:darkgreen'>Huh? -- %s (attempt=%s)</h3>" % ( msg, attempt) else: if correct: response += "<h1 style='color:blue'>RIGHT!</h1>" if self._start_time: response += "<h2 class='lighten'>Time: %.1f seconds</h2>" % ( walltime() - self._start_time, ) if self._number_of_attempts == 1: response += "<h3 class='lighten'>You got it first try!</h3>" else: response += "<h3 class='lighten'>It took you %s attempts.</h3>" % ( self._number_of_attempts, ) else: response += "<h3 style='color:darkgreen'>Not correct yet...</h3>" if self._number_of_attempts == 1: response += "<h4 style='lighten'>(first attempt)</h4>" else: response += "<h4 style='lighten'>(%s attempts)</h4>" % self._number_of_attempts if self._number_of_attempts > len(self._hints): hint = self._hints[-1] else:
def __call__(self, f, inputs): """ Parallel iterator using ``fork()``. INPUT: - ``f`` -- a Python function that need not be pickleable or anything else! - ``inputs`` -- a list of pickleable pairs ``(args, kwds)``, where ``args`` is a tuple and ``kwds`` is a dictionary. OUTPUT: EXAMPLES:: sage: F = sage.parallel.use_fork.p_iter_fork(2,3) sage: sorted(list( F( (lambda x: x^2), [([10],{}), ([20],{})]))) [(([10], {}), 100), (([20], {}), 400)] sage: sorted(list( F( (lambda x, y: x^2+y), [([10],{'y':1}), ([20],{'y':2})]))) [(([10], {'y': 1}), 101), (([20], {'y': 2}), 402)] TESTS: The output of functions decorated with :func:parallel is read as a pickle by the parent process. We intentionally break the unpickling and demonstrate that this failure is handled gracefully (an exception is displayed and an empty list is returned):: sage: Polygen = parallel(polygen) sage: list(Polygen([QQ])) [(((Rational Field,), {}), x)] sage: from sage.structure.sage_object import unpickle_override, register_unpickle_override sage: register_unpickle_override('sage.rings.polynomial.polynomial_rational_flint', 'Polynomial_rational_flint', Integer) sage: L = list(Polygen([QQ])) ('__init__() takes at most 2 positional arguments (4 given)', <type 'sage.rings.integer.Integer'>, (Univariate Polynomial Ring in x over Rational Field, [0, 1], False, True)) sage: L [] Fix the unpickling:: sage: del unpickle_override[('sage.rings.polynomial.polynomial_rational_flint', 'Polynomial_rational_flint')] sage: list(Polygen([QQ,QQ])) [(((Rational Field,), {}), x), (((Rational Field,), {}), x)] """ n = self.ncpus v = list(inputs) import os, sys, signal from sage.structure.sage_object import load from sage.misc.all import tmp_dir, walltime dir = tmp_dir() timeout = self.timeout workers = {} try: while len(v) > 0 or len(workers) > 0: # Spawn up to n subprocesses while len(v) > 0 and len(workers) < n: # Subprocesses shouldn't inherit unflushed buffers (cf. #11778): sys.stdout.flush() sys.stderr.flush() pid = os.fork() # The way fork works is that pid returns the # nonzero pid of the subprocess for the master # process and returns 0 for the subprocess. if pid: # This is the parent master process. workers[pid] = [v[0], walltime(), ''] del v[0] else: # This is the subprocess. self._subprocess(f, dir, v[0]) if len(workers) > 0: # Now wait for one subprocess to finish and report the result. # However, wait at most the time since the oldest process started. if timeout: oldest = min([X[1] for X in workers.values()]) alarm(max(timeout - (walltime()-oldest), 0.1)) try: pid = os.wait()[0] cancel_alarm() w = workers.pop(pid) except AlarmInterrupt: cancel_alarm() # Kill workers that are too old for pid, X in workers.iteritems(): if walltime() - X[1] > timeout: if self.verbose: print( "Killing subprocess %s with input %s which took too long" % (pid, X[0]) ) os.kill(pid, signal.SIGKILL) X[-1] = ' (timed out)' except KeyError: # Some other process exited, not our problem... pass else: # collect data from process that successfully terminated sobj = os.path.join(dir, '%s.sobj'%pid) if not os.path.exists(sobj): X = "NO DATA" + w[-1] # the message field else: X = load(sobj, compress=False) os.unlink(sobj) out = os.path.join(dir, '%s.out'%pid) if not os.path.exists(out): output = "NO OUTPUT" else: output = open(out).read() os.unlink(out) if output.strip(): print output, yield (w[0], X) except Exception as msg: print msg finally: # Clean up all temporary files. try: for X in os.listdir(dir): os.unlink(os.path.join(dir, X)) os.rmdir(dir) except OSError as msg: if self.verbose: print msg # Send "kill -9" signal to workers that are left. if len(workers) > 0: if self.verbose: print "Killing any remaining workers..." sys.stdout.flush() for pid in workers.keys(): try: os.kill(pid, signal.SIGKILL) os.waitpid(pid, 0) except OSError as msg: if self.verbose: print msg
def __init__(self,base,p,discriminant,abtuple = None,level = 1,grouptype = None,seed = None,outfile = None,magma = None,timeout = 0, use_shapiro = True, character = None, nscartan = None, matrix_group = False): self.seed = seed self.magma = magma self._use_shapiro = use_shapiro self._matrix_group = matrix_group if seed is not None: verbose('Setting Magma seed to %s'%seed) self.magma.eval('SetSeed(%s)'%seed) self.F = base if self.F != QQ: Fideal = self.F.maximal_order().ideal self.ideal_p = Fideal(p) self.norm_p = ZZ(p.norm()) self.discriminant = Fideal(discriminant) self.level = Fideal(level) else: self.ideal_p = ZZ(p) self.norm_p = ZZ(p) self.discriminant = ZZ(discriminant) self.level = ZZ(level) if nscartan is not None: self.level *= nscartan self.p = self.norm_p.prime_divisors()[0] if not self.ideal_p.is_prime(): raise ValueError('p (=%s) must be prime'%self.p) if self._use_shapiro: covol = covolume(self.F,self.discriminant,self.level) else: covol = covolume(self.F,self.discriminant,self.ideal_p * self.level) verbose('Estimated Covolume = %s'%covol) difficulty = covol**2 verbose('Estimated Difficulty = %s'%difficulty) verbose('Initializing arithmetic group G(pn)...') t = walltime() lev = self.ideal_p * self.level if character is not None: lev = [lev, character] self.Gpn = ArithGroup(self.F,self.discriminant,abtuple,lev,grouptype = grouptype,magma = magma, compute_presentation = not self._use_shapiro, timeout = timeout,nscartan=nscartan) self.Gpn.get_embedding = self.get_embedding self.Gpn.embed = self.embed self.Gpn.embed_matrix = self.embed_matrix verbose('Initializing arithmetic group G(n)...') lev = self.level if character is not None: lev = [lev, character] self.Gn = ArithGroup(self.F,self.discriminant,abtuple,lev,info_magma = self.Gpn,grouptype = grouptype,magma = magma, compute_presentation = True, timeout = timeout,nscartan=nscartan) self.Gn.embed_matrix = self.embed_matrix t = walltime(t) verbose('Time for calculation T = %s'%t) verbose('T = %s x difficulty'%RealField(25)(t/difficulty)) self.Gn.get_embedding = self.get_embedding self.Gn.embed = self.embed if hasattr(self.Gn.B,'is_division_algebra'): fwrite('# B = F<i,j,k>, with i^2 = %s and j^2 = %s'%(self.Gn.B.gens()[0]**2,self.Gn.B.gens()[1]**2),outfile) else: fwrite('# B = M_2(F)',outfile) try: basis_data_1 = list(self.Gn.Obasis) if not self.use_shapiro(): basis_data_p = list(self.Gpn.Obasis) except AttributeError: try: basis_data_1 = self.Gn.basis_invmat.inverse().columns() if not self.use_shapiro(): basis_data_p = self.Gpn.basis_invmat.inverse().columns() except AttributeError: basis_data_1 = '?' basis_data_p = '?' self._prec = -1 self.get_embedding(200) fwrite('# R with basis %s'%basis_data_1,outfile) self.Gn.get_Up_reps = self.get_Up_reps if not self.use_shapiro(): fwrite('# R(p) with basis %s'%basis_data_p,outfile) self.Gpn.get_Up_reps = self.get_Up_reps self.Gn.wp = self.wp self.Gpn.wp = self.wp verbose('Done initializing arithmetic groups') verbose('Done initialization of BigArithmeticGroup')
def __init__(self, base, p, discriminant, abtuple=None, level=1, outfile=None, magma=None, character=None, **kwargs): seed = kwargs.get('seed', None) self.seed = seed self.magma = magma self._use_shapiro = kwargs.get('use_shapiro', True) hardcode_matrices = kwargs.get('hardcode_matrices', None) if hardcode_matrices is None: self._hardcode_matrices = ((abtuple is None and discriminant == 1) or abtuple == (1, 1)) nscartan = kwargs.get('nscartan', None) if seed is not None: verbose('Setting Magma seed to %s' % seed) self.magma.eval('SetSeed(%s)' % seed) self.F = base if self.F != QQ: Fideal = self.F.maximal_order().ideal self.ideal_p = Fideal(p) self.norm_p = ZZ(p.norm()) self.discriminant = Fideal(discriminant) self.level = Fideal(level) else: self.ideal_p = ZZ(p) self.norm_p = ZZ(p) self.discriminant = ZZ(discriminant) self.level = ZZ(level) if nscartan is not None: self.level *= nscartan if self._hardcode_matrices: assert abtuple is None and self.discriminant == 1 or abtuple == (1, 1) self.p = self.norm_p.prime_divisors()[0] if not self.ideal_p.is_prime(): raise ValueError('p (=%s) must be prime' % self.p) if self._use_shapiro: covol = covolume(self.F, self.discriminant, self.level) else: covol = covolume(self.F, self.discriminant, self.ideal_p * self.level) verbose('Estimated Covolume = %s' % covol) difficulty = covol**2 verbose('Estimated Difficulty = %s' % difficulty) verbose('Initializing arithmetic group G(pn)...') t = walltime() lev = self.ideal_p * self.level if character is not None: lev = [lev, character] self.Gpn = ArithGroup(self.F, self.discriminant, abtuple, lev, magma=magma, compute_presentation=not self._use_shapiro, **kwargs) self.Gpn.get_embedding = self.get_embedding self.Gpn.embed = self.embed verbose('Initializing arithmetic group G(n)...') lev = self.level if character is not None: lev = [lev, character] self.Gn = ArithGroup(self.F, self.discriminant, abtuple, lev, info_magma=self.Gpn, magma=magma, compute_presentation=True, **kwargs) t = walltime(t) verbose('Time for calculation T = %s' % t) verbose('T = %s x difficulty' % RealField(25)(t / difficulty)) self.Gn.get_embedding = self.get_embedding self.Gn.embed = self.embed if hasattr(self.Gpn.B, 'is_division_algebra'): fwrite( '# B = F<i,j,k>, with i^2 = %s and j^2 = %s' % (self.Gpn.B.gens()[0]**2, self.Gpn.B.gens()[1]**2), outfile) else: fwrite('# B = M_2(F)', outfile) try: basis_data_1 = list(self.Gn.Obasis) if not self.use_shapiro(): basis_data_p = list(self.Gpn.Obasis) except AttributeError: try: basis_data_1 = self.Gn._get_basis_invmat().inverse().columns() if not self.use_shapiro(): basis_data_p = self.Gpn._get_basis_invmat().inverse( ).columns() except AttributeError: basis_data_1 = '?' basis_data_p = '?' self._prec = -1 self.get_embedding(200) fwrite('# R with basis %s' % basis_data_1, outfile) self.Gn.get_Up_reps = self.get_Up_reps if not self.use_shapiro(): fwrite('# R(p) with basis %s' % basis_data_p, outfile) self.Gpn.get_Up_reps = self.get_Up_reps self.Gn.wp = self.wp self.Gpn.wp = self.wp self.Gn._F_to_local = self._F_to_local self.Gpn._F_to_local = self._F_to_local verbose('Done initializing arithmetic groups') verbose('Done initialization of BigArithmeticGroup')