def rcomp_add(x, y): from .rcomp import Rcomp P = Rcomp() x_is_top = is_top(P, x) y_is_top = is_top(P, y) if x_is_top or y_is_top: return P.get_top() mcdp_dev_warning('underflow, overflow') return x + y
def get_top(self): if isinstance(self.S, FiniteCollectionAsSpace): res = FiniteCollection(elements=self.S.elements, S=self.S) if do_extra_checks(): self.belongs(res) return res mcdp_dev_warning('Maybe should use a TooMuchComputation error.') msg = 'Cannot enumerate the elements of this space.' raise_desc(NotBounded, msg, space=self.S)
def solve(self, f): R = self.get_res_space() s = [] mcdp_dev_warning('use specific operation on antichains') for dp in self.dps: rs = dp.solve(f) s.extend(rs.minimals) res = R.Us(poset_minima(s, R.leq)) return res
def solve_r(self, r): F = self.get_fun_space() s = [] mcdp_dev_warning('use specific operation on antichains') for dp in self.dps: lf = dp.solve_r(r) s.extend(lf.maximals) res = F.Ls(poset_maxima(s, F.leq)) return res
def add_where_information(where): """ Adds where field to DPSyntaxError or DPSemanticError thrown by code. """ active = True if not active: logger.debug('Note: Error tracing disabled in add_where_information().') if not active: mcdp_dev_warning('add_where_information is disabled') yield else: try: yield except MCDPExceptionWithWhere as e: mcdp_dev_warning('add magic traceback handling here') _, _, tb = sys.exc_info() raise_with_info(e, where, tb)
def __init__(self, maximals, P): self.maximals = frozenset(maximals) self.P = P if do_extra_checks(): # XXX problems = [] for m in maximals: try: self.P.belongs(m) except NotBelongs as e: problems.append(e) if problems: msg = "Cannot create upper set:\n" msg += "\n".join(str(p) for p in problems) raise NotBelongs(msg) mcdp_dev_warning('check_maximal()')
def Rcomp_multiply_upper_topology(A, a, B, b, C): """ Multiplication, extended for top, such that the upper topology is respected. So 0 * Top = 0. and x * Top = Top. """ a_is_top = is_top(A, a) b_is_top = is_top(B, b) a_is_zero = not a_is_top and a == 0.0 b_is_zero = not b_is_top and b == 0.0 # 0 * Top = 0 if b_is_top: if a_is_zero: return 0.0 else: return C.get_top() elif a_is_top: if b_is_zero: return 0.0 else: return C.get_top() else: assert isinstance(a, float) assert isinstance(b, float) # XXX: overflow try: return a * b except FloatingPointError as e: if 'underflow' in str(e): mcdp_dev_warning('Not sure about this.') return finfo.tiny elif 'overflow' in str(e): return C.get_top() else: raise
def invmultL_solve_options(F, R, f, n, algo): """ Returns a set of points that are *below* r1*r2 = f """ from .dp_inv_mult import InvMult2 assert algo in [InvMult2.ALGO_UNIFORM, InvMult2.ALGO_VAN_DER_CORPUT] if f == 0.0: return set([(0.0, 0.0)]) if is_top(F, f): mcdp_dev_warning('FIXME Need much more thought about this') top1 = R[0].get_top() top2 = R[1].get_top() s = set([(top1, top2)]) return s if algo == InvMult2.ALGO_UNIFORM: if n == 1: points = [(0.0, 0.0)] elif n == 2: points = [(0.0, 0.0)] else: pu = sorted(samplec(n - 1, f), key=lambda _: _[0]) assert len(pu) == n - 1, (len(pu), n - 1) nu = len(pu) points = set() points.add((0.0, pu[0][1])) points.add((pu[-1][0], 0.0)) for i in range(nu - 1): p = (pu[i][0], pu[i + 1][1]) points.add(p) elif algo == InvMult2.ALGO_VAN_DER_CORPUT: if n == 1: points = set([(0.0, 0.0)]) else: x1, x2 = generate_exp_van_der_corput_sequence(n=n - 1, C=f) pu = zip(x1, x2) assert len(pu) == n - 1, pu if do_extra_checks(): check_minimal(pu, R) nu = len(pu) points = [] points.append((0.0, pu[0][1])) for i in range(nu - 1): p = (pu[i][0], pu[i + 1][1]) points.append(p) points.append((pu[-1][0], 0.0)) points = set(points) else: # pragma: no cover assert False assert len(points) == n, (n, len(points), points) return points
def sample_sum_lowersets(F, R, f, n): """ Returns a set of points in R *above* the line {(a,b) | a + b = f } such that the line is contained in the downclosure of the points. It uses the variable InvPlus2.ALGO to decide the type of sampling. """ check_isinstance(R, PosetProduct) assert len(R) == 2 if is_top(F, f): # this is not correct, however it does not form a monotone sequence # +infinity top1 = R[0].get_top() top2 = R[1].get_top() return set([(top1, top2)]) if F.leq(f, 0.0): # f == 0 return set([(0.0, 0.0)]) from mcdp_dp.dp_inv_plus import InvPlus2 if InvPlus2.ALGO == InvPlus2.ALGO_VAN_DER_CORPUT: options = van_der_corput_sequence(n + 1) elif InvPlus2.ALGO == InvPlus2.ALGO_UNIFORM: options = np.linspace(0.0, 1.0, n + 1) else: assert False, InvPlus2.ALGO s = [] for o in options: try: s.append((f * o, f * (1.0 - o))) except FloatingPointError as e: if 'underflow' in str(e): # assert f <= finfo.tiny, (f, finfo.tiny) mcdp_dev_warning('not sure about this') s.append((finfo.eps, finfo.eps)) else: raise_wrapped(FloatingPointError, e, 'error', f=f, o=o) # the sequence s[] is ordered for i in range(len(s) - 1): xs = [_[0] for _ in s] ys = [_[1] for _ in s] if not xs[i] < xs[i + 1]: msg = 'Invalid sequence (s[%s].x = %s !< s[%s].x = %s.' % ( i, xs[i], i + 1, xs[i + 1]) xs2 = map(R[0].format, xs) ys2 = map(R[1].format, ys) raise_desc(AssertionError, msg, s=s, xs=xs, ys=ys, xs2=xs2, ys2=ys2) options = set() for i in range(n): x = s[i + 1][0] y = s[i][1] # join a = R.join(s[i], s[i + 1]) if (x, y) != a: msg = 'Numerical error' raise_desc(AssertionError, msg, x=x, y=y, a=a, s_i=s[i], s_i_plus=s[i + 1]) options.add((x, y)) return options
def eval_constant_space_custom_value(op, context): from .eval_space_imp import eval_space assert isinstance(op, CDP.SpaceCustomValue) space = eval_space(op.space, context) custom_string = op.custom_string # print('custom string %r' % (custom_string).__repr__()) if isinstance(space, FiniteCollectionAsSpace): if custom_string == '*': if len(space.elements) == 1: value = list(space.elements)[0] return ValueWithUnits(unit=space, value=value) else: msg = 'You can use "*" only if the space has one element.' raise_desc(DPSemanticError, msg, elements=space.elements) try: space.belongs(custom_string) mcdp_dev_warning('this does not seem to work...') except NotBelongs: msg = 'The value "%s" is not an element of this poset.' % custom_string msg += '\n\nThese are the valid values: ' + ", ".join( map(str, space.elements)) + '.' raise_desc(DPSemanticError, msg) return ValueWithUnits(unit=space, value=op.custom_string) if isinstance(space, Nat): if isinstance(custom_string, CDP.ValueExpr): value = int(custom_string.value) # XXX: warn if value != custom_string.value: msg = 'Invalid value %s' % value raise_desc(DPSemanticError, msg, value=value, value0=custom_string.value) elif isinstance(custom_string, str): value = int(custom_string) else: msg = 'Cannot interpret value.' raise_desc(DPInternalError, msg, value=value) return ValueWithUnits(unit=Nat(), value=value) if isinstance(space, Int): mcdp_dev_warning('Top?') if isinstance(custom_string, CDP.ValueExpr): value = int(custom_string.value) # XXX: warn if value != custom_string.value: msg = 'Invalid value %s' % value raise_desc(DPSemanticError, msg, value=value, value0=custom_string.value) elif isinstance(custom_string, str): value = int(custom_string) else: msg = 'Cannot interpret value.' raise_desc(DPInternalError, msg, value=value) return ValueWithUnits(unit=Int(), value=value) if isinstance(space, Rcomp): mcdp_dev_warning('Top?') if isinstance(custom_string, CDP.ValueExpr): value = float(custom_string.value) elif isinstance(custom_string, str): value = float(custom_string) else: msg = 'Cannot interpret value.' raise_desc(DPInternalError, msg, value=value) return ValueWithUnits(unit=Rcomp(), value=value) msg = 'Custom parsing not implemented for space.' raise_desc(DPInternalError, msg, space=space, custom_string=custom_string)
return eq return False def format(self, x): if x == self.top: s = self.top.__repr__() else: s = RcompBase.format(self, x) if self.units_formatted: return '%s %s' % (s, self.units_formatted) else: return s mcdp_dev_warning('(!) Need to create plenty of checks for this Rbicomb.') class RbicompUnits(Rbicomp): """ [-inf, inf] """ def __init__(self, pint_unit, string): if do_extra_checks(): ureg = get_ureg() check_isinstance(pint_unit, ureg.Quantity) Rbicomp.__init__(self) self.units = pint_unit self.string = string u = parse_pint(string) assert u == self.units, (self.units, u, string)
try: import procgraph_mplayer # @UnusedImport except ImportError as e: logger.error('Cannot use Procgraph to create video.') logger.error(e) logger.info('The frames are in the directory %s' % tmpdir) else: join_video_29_fixed(output=out, dirname=tmpdir, pattern='.*.png', fps=fps) mcdp_dev_warning('Add procgraph as dependency') def join_video_29_fixed(output, dirname, pattern, fps): """ Note that the pattern is a Python regex: pg-video-join -d anim-simple/ -p '*.png' -o anim-simple-collate.mp4 --fps 1 """ from procgraph.core.registrar_other import register_model_spec # @UnresolvedImport from procgraph import pg # @UnresolvedImport register_model_spec(""" --- model join_video_helper_29 config output
class LowerSets(Poset): @contract(P='$Poset') def __init__(self, P): self.P = P # self.top = self.get_top() # self.bot = self.get_bottom() # if do_extra_checks(): # self.belongs(self.top) # self.belongs(self.bot) # assert self.leq(self.bot, self.top) # assert not self.leq(self.top, self.bot) # unless empty def witness(self): w = self.P.witness() return LowerSet([w], self.P) mcdp_dev_warning('need to think about this') def get_bottom(self): maximals = self.P.get_maximal_elements() return LowerSet(set(maximals), self.P) def get_top(self): return LowerSet(set(), self.P) def get_test_chain(self, n): chain = reversed(self.P.get_test_chain(n)) f = lambda x: LowerSet(set([x]), self.P) return map(f, chain) def belongs(self, x): if not isinstance(x, LowerSet): msg = 'Not a lower set.' raise NotBelongs(msg) if not x.P == self.P: mcdp_dev_warning('should we try casting?') msg = 'Different poset: %s ≠ %s' % (self.P, x.P) raise_desc(NotBelongs, msg, self=self, x=x) return True def check_equal(self, a, b): m1 = a.maximals m2 = b.maximals if not (m1 == m2): msg = 'The two sets are not equal\n %s\n!= %s' % (self.format(a), self.format(b)) raise NotEqual(msg) def check_leq(self, a, b): if do_extra_checks(): self.belongs(a) self.belongs(b) if a == b: return True if False: if a == self.bot: return True if b == self.top: return True if b == self.bot: raise NotLeq('b = my ⊥') if a == self.top: raise NotLeq('a = my ⊤') self.my_leq_(a, b) def my_leq_(self, A, B): # there exists an a in A that a >= b def dominated(b): problems = [] for a in A.maximals: try: # if inverted: self.P.check_leq(b, a) self.P.check_leq(b, a) return True, None except NotLeq as e: problems.append(e) return False, problems # for all elements in B for b in B.maximals: is_dominated, whynot = dominated(b) if not is_dominated: msg = "b = %s not dominated by any a in %s" % (b, A.maximals) msg += '\n' + '\n- '.join(map(str, whynot)) raise NotLeq(msg) def meet(self, a, b): # "min" ∨ # To compute the meet (min) of two upper sets # just take the union of the minimal elements # (without redundant elements) elements = set() elements.update(a.maximals) elements.update(b.maximals) elements0 = poset_maxima(elements, self.P.leq) r = LowerSet(elements0, self.P) self.check_leq(r, a) self.check_leq(r, b) return r def format(self, x): contents = ", ".join(self.P.format(m) for m in sorted(x.maximals)) return "↓{%s}" % contents def __repr__(self): return "LowerSets(%r)" % self.P def __str__(self): return "L(%s)" % self.P
def highlight_mcdp_code(library, soup, realpath, res, location, generate_pdf=False, raise_errors=False): # print(indent(frag, 'highlight_mcdp_code ')) """ Looks for codes like: <pre class="mcdp">mcdp { # empty model } </pre> and does syntax hihglighting. """ assert soup.name == 'fragment' def go(selector, parse_expr, extension, use_pre=True, refine=None): for tag in soup.select(selector): source_code = '<unset>' # XXX try: if tag.string is None: # or not tag.string.strip(): if not tag.has_attr('id'): msg = "If <pre> is empty then it needs to have an id." raise_desc(ValueError, msg, tag=describe_tag(tag)) # load it tag_id = tag['id'].encode('utf-8') if '.' in tag_id: i = tag_id.index('.') libname, name = tag_id[:i], tag_id[i + 1:] use_library = library.load_library(libname) else: name = tag_id use_library = library basename = '%s.%s' % (name, extension) data = use_library._get_file_data(basename) source_code = data['data'] else: source_code = get_source_code(tag) # prettify. # remove spurious indentation source_code = source_code.strip() do_apply_suggestions = (not tag.has_attr('noprettify') and not tag.has_attr('np')) # then apply suggestions try: if do_apply_suggestions: x = parse_wrap(parse_expr, source_code)[0] xr = parse_ndp_refine(x, Context()) suggestions = get_suggestions(xr) source_code = apply_suggestions( source_code, suggestions) except DPSyntaxError as e: if raise_errors: raise else: res.note_error(str(e), HTMLIDLocation.for_element(tag)) continue # we don't want the browser to choose different tab size # source_code = source_code.replace('\t', ' ' * 4) # we are not using it _realpath = realpath context = Context() def postprocess(x): if refine is not None: return refine(x, context=context) else: return x # print('rendering source code %r' % source_code) html = ast_to_html(source_code, parse_expr=parse_expr, add_line_gutter=False, postprocess=postprocess) for w in context.warnings: if w.where is not None: from mcdp_web.editor_fancy.app_editor_fancy_generic import html_mark html = html_mark(html, w.where, "language_warning") frag2 = BeautifulSoup(html, 'lxml', from_encoding='utf-8') if use_pre: rendered = Tag(name='div', attrs={'class': 'rendered'}) pre = frag2.pre pre.extract() rendered.append(pre) if not rendered.has_attr('class'): rendered['class'] = "" if tag.has_attr('label'): text = tag['label'] tag_label = Tag(name='span') add_class(tag_label, 'label') add_class(tag_label, 'label_inside') tag_label.append(NavigableString(text)) pre.insert(0, tag_label) tag_label_outside = Tag(name='span') add_class(tag_label_outside, 'label') add_class(tag_label_outside, 'label_outside') tag_label_outside.append(NavigableString(text)) rendered.insert(0, tag_label_outside) max_len = max_len_of_pre_html(html) if tag.has_attr('label'): add_class(rendered, 'has_label') max_len = max(max_len, len(tag['label']) + 6) style = '' else: # using <code> rendered = frag2.pre.code rendered.extract() if not rendered.has_attr('class'): rendered['class'] = "" style = '' if tag.has_attr('style'): style = style + tag['style'] if style: rendered['style'] = style if tag.has_attr('class'): add_class(rendered, tag['class']) if tag.has_attr('id'): rendered['id'] = tag['id'] if use_pre: if generate_pdf: pdf = get_ast_as_pdf(source_code, parse_expr) if tag.has_attr('id'): basename = tag['id'] else: hashcode = hashlib.sha224( source_code).hexdigest()[-8:] basename = 'code-%s' % hashcode docname = os.path.splitext( os.path.basename(realpath))[0] download = docname + '.' + basename + '.source_code.pdf' a = create_a_to_data(download=download, data_format='pdf', data=pdf) a['class'] = 'pdf_data' a.append(NavigableString(download)) div = Tag(name='div') div.append(rendered) div.append(a) tag.replaceWith(div) else: tag.replaceWith(rendered) else: tag.replaceWith(rendered) except DPSyntaxError as e: if raise_errors: raise else: res.note_error(str(e), HTMLIDLocation.for_element(tag)) # note_error(tag, e) if tag.string is None: tag.string = "`%s" % tag['id'] continue except DPSemanticError as e: if raise_errors: raise else: res.note_error(str(e), HTMLIDLocation.for_element(tag)) # note_error(tag, e) if tag.string is None: tag.string = "`%s" % tag['id'] continue except DPInternalError as ex: msg = 'Error while interpreting the code:\n\n' msg += indent(source_code, ' | ') raise_wrapped(DPInternalError, ex, msg, exc=sys.exc_info()) abbrevs = { # tag name: (new name, classes to add) 'fname': ('code', ['FName']), 'rname': ('code', ['RName']), 'poset': ('code', ['mcdp_poset']), 'value': ('code', ['mcdp_value']), 'fvalue': ('code', ['mcdp_value', 'fvalue']), 'rvalue': ('code', ['mcdp_value', 'rvalue']), 'impname': ('code', ['impname']), 'k': ('code', ['keyword']), 'program': ('code', ['program']), 'f': ('span', ['f']), 'r': ('span', ['r']), 'imp': ('span', ['imp']), 'kf': ('code', ['f', 'keyword']), 'kr': ('code', ['r', 'keyword']), 'cf': ('code', ['f']), 'cr': ('code', ['r']), } for original_tag_name, (new_tag_name, classes_to_add) in abbrevs.items(): for e in soup.select(original_tag_name): e.name = new_tag_name for c in classes_to_add: add_class(e, c) # warn not to get confused ith '_' and '-' special_classes = [ 'mcdp_poset', 'mcdp_fvalue', 'mcdp_rvalue', 'mcdp_value' ] for x in special_classes: # we do not expect to see an element that has class with '-' instead of '_' erroring = x.replace('_', '-') mistakes = list(soup.select('.%s' % erroring)) if mistakes: msg = 'You cannot use %r as a class; use lowercase.' % erroring tags = "\n\n".join( indent(describe_tag(_), ' | ') for _ in mistakes) raise_desc(ValueError, msg, tags=tags) for x in special_classes: # mcdp_poset -> mcdp-poset corresponding = x.replace('_', '-') for e in soup.select(corresponding): # e2 = Tag(name='code') # copy_string_and_attrs(e, e2) e.name = 'code' # THEN add class add_class(e, x) prettify = list(soup.select('fname')) + list(soup.select('rname')) for e in prettify: if e.has_attr('np') or e.has_attr('noprettify'): x0 = e.text.encode('utf-88') x1 = get_suggested_identifier(x0) e.text = unicode(x1, 'utf-8') mcdp_dev_warning('lets try if this goes away') # XXX # this is a bug with bs4. The replace_with above only adds an escaped # text rather than the actual tag (!). # soup = bs(to_html_stripping_fragment(soup)) # assert soup.name == 'fragment' go('pre.mcdp', Syntax.ndpt_dp_rvalue, "mcdp", use_pre=True, refine=parse_ndp_refine) go('pre.mcdp_poset', Syntax.space, "mcdp_poset", use_pre=True, refine=parse_poset_refine) go('pre.mcdp_template', Syntax.template, "mcdp_template", use_pre=True, refine=parse_template_refine) go('pre.mcdp_statements', Syntax.dp_model_statements, "mcdp_statements", use_pre=True) go('pre.mcdp_fvalue', Syntax.fvalue, "mcdp_fvalue", use_pre=True) go('pre.mcdp_rvalue', Syntax.rvalue, "mcdp_rvalue", use_pre=True) # todo: add deprecation go('pre.mcdp_value', Syntax.rvalue, "mcdp_value", use_pre=True) go('code.mcdp', Syntax.ndpt_dp_rvalue, "mcdp", use_pre=False) go('code.mcdp_poset', Syntax.space, "mcdp_poset", use_pre=False) go('code.mcdp_value', Syntax.rvalue, "mcdp_value", use_pre=False) go('code.mcdp_template', Syntax.template, "mcdp_template", use_pre=False) # this is a bug with bs4... for pre in soup.select('pre + pre'): # print('adding br between PREs') br_ = br() br_['class'] = 'pre_after_pre' pre.parent.insert(pre.parent.index(pre), br_)
def add(self, a, b): """ Addition, extended for top """ if a == self.top or b == self.top: return self.top mcdp_dev_warning('overflow check') return a + b