Example #1
0
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
Example #2
0
    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)
Example #3
0
    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
Example #4
0
    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
Example #5
0
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)
Example #6
0
    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()')
Example #7
0
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
Example #8
0
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
Example #9
0
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
Example #10
0
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)
Example #11
0
            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)
Example #12
0
    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
Example #13
0
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
Example #14
0
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_)
Example #15
0
 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