예제 #1
0
def test_factor_and_dimension():
    assert (3000, Dimension(1)) == Quantity._collect_factor_and_dimension(3000)
    assert (1001, length) == Quantity._collect_factor_and_dimension(meter + km)
    assert (2, length/time) == Quantity._collect_factor_and_dimension(
        meter/second + 36*km/(10*hour))

    x, y = symbols('x y')
    assert (x + y/100, length) == Quantity._collect_factor_and_dimension(
        x*m + y*centimeter)

    cH = Quantity('cH', amount_of_substance/volume)
    pH = -log(cH)

    assert (1, volume/amount_of_substance) == Quantity._collect_factor_and_dimension(
        exp(pH))

    v_w1 = Quantity('v_w1', length/time, S(3)/2*meter/second)
    v_w2 = Quantity('v_w2', length/time, 2*meter/second)
    expr = Abs(v_w1/2 - v_w2)
    assert (S(5)/4, length/time) == \
        Quantity._collect_factor_and_dimension(expr)

    expr = S(5)/2*second/meter*v_w1 - 3000
    assert (-(2996 + S(1)/4), Dimension(1)) == \
        Quantity._collect_factor_and_dimension(expr)

    expr = v_w1**(v_w2/v_w1)
    assert ((S(3)/2)**(S(4)/3), (length/time)**(S(4)/3)) == \
        Quantity._collect_factor_and_dimension(expr)
예제 #2
0
파일: util.py 프로젝트: PWJ1900/Rlearncirq
def _get_conversion_matrix_for_expr(expr, target_units, unit_system):
    from sympy import Matrix

    dimension_system = unit_system.get_dimension_system()

    expr_dim = Dimension(unit_system.get_dimensional_expr(expr))
    dim_dependencies = dimension_system.get_dimensional_dependencies(
        expr_dim, mark_dimensionless=True)
    target_dims = [
        Dimension(unit_system.get_dimensional_expr(x)) for x in target_units
    ]
    canon_dim_units = [
        i for x in target_dims
        for i in dimension_system.get_dimensional_dependencies(
            x, mark_dimensionless=True)
    ]
    canon_expr_units = {i for i in dim_dependencies}

    if not canon_expr_units.issubset(set(canon_dim_units)):
        return None

    seen = set([])
    canon_dim_units = [
        i for i in canon_dim_units if not (i in seen or seen.add(i))
    ]

    camat = Matrix([[
        dimension_system.get_dimensional_dependencies(
            i, mark_dimensionless=True).get(j, 0) for i in target_dims
    ] for j in canon_dim_units])
    exprmat = Matrix([dim_dependencies.get(k, 0) for k in canon_dim_units])

    res_exponents = camat.solve_least_squares(exprmat, method=None)
    return res_exponents
예제 #3
0
def _get_conversion_matrix_for_expr(expr, target_units):
    from sympy import Matrix

    expr_dim = Dimension(Quantity.get_dimensional_expr(expr))
    dim_dependencies = dimsys_default.get_dimensional_dependencies(
        expr_dim, mark_dimensionless=True)
    target_dims = [
        Dimension(Quantity.get_dimensional_expr(x)) for x in target_units
    ]
    canon_dim_units = {
        i
        for x in target_dims for i in
        dimsys_default.get_dimensional_dependencies(x, mark_dimensionless=True)
    }
    canon_expr_units = {i for i in dim_dependencies}

    if not canon_expr_units.issubset(canon_dim_units):
        return None

    canon_dim_units = sorted(canon_dim_units)

    camat = Matrix([[
        dimsys_default.get_dimensional_dependencies(
            i, mark_dimensionless=True).get(j, 0) for i in target_dims
    ] for j in canon_dim_units])
    exprmat = Matrix([dim_dependencies.get(k, 0) for k in canon_dim_units])

    res_exponents = camat.solve_least_squares(exprmat, method=None)
    return res_exponents
예제 #4
0
def test_Dimension_error_regisration():
    with warns_deprecated_sympy():
        # tuple with more or less than two entries
        raises(IndexError, lambda: length._register_as_base_dim())

    with warns_deprecated_sympy():
        one = Dimension(1)
        raises(TypeError, lambda: one._register_as_base_dim())
예제 #5
0
def test_Dimension_error_regisration():
    with warns_deprecated_sympy():
        # tuple with more or less than two entries
        raises(IndexError, lambda: length._register_as_base_dim())

    with warns_deprecated_sympy():
        one = Dimension(1)
        raises(TypeError, lambda: one._register_as_base_dim())
예제 #6
0
def test_Dimension_error_regisration():
    with warnings.catch_warnings():
        warnings.filterwarnings("ignore", category=SymPyDeprecationWarning)

        # tuple with more or less than two entries
        raises(IndexError, lambda: length._register_as_base_dim())

        one = Dimension(1)
        raises(TypeError, lambda: one._register_as_base_dim())
예제 #7
0
def check_dimensions(expr, unit_system="SI"):
    """Return expr if units in addends have the same
    base dimensions, else raise a ValueError."""
    # the case of adding a number to a dimensional quantity
    # is ignored for the sake of SymPy core routines, so this
    # function will raise an error now if such an addend is
    # found.
    # Also, when doing substitutions, multiplicative constants
    # might be introduced, so remove those now

    from sympy.physics.units import UnitSystem
    unit_system = UnitSystem.get_unit_system(unit_system)

    def addDict(dict1, dict2):
        """Merge dictionaries by adding values of common keys and
        removing keys with value of 0."""
        dict3 = {**dict1, **dict2}
        for key, value in dict3.items():
            if key in dict1 and key in dict2:
                dict3[key] = value + dict1[key]
        return {key: val for key, val in dict3.items() if val != 0}

    adds = expr.atoms(Add)
    DIM_OF = unit_system.get_dimension_system().get_dimensional_dependencies
    for a in adds:
        deset = set()
        for ai in a.args:
            if ai.is_number:
                deset.add(())
                continue
            dims = []
            skip = False
            dimdict = {}
            for i in Mul.make_args(ai):
                if i.has(Quantity):
                    i = Dimension(unit_system.get_dimensional_expr(i))
                if i.has(Dimension):
                    dimdict = addDict(dimdict, DIM_OF(i))
                elif i.free_symbols:
                    skip = True
                    break
            dims.extend(dimdict.items())
            if not skip:
                deset.add(tuple(sorted(dims, key=default_sort_key)))
                if len(deset) > 1:
                    raise ValueError(
                        "addends have incompatible dimensions: {}".format(
                            deset))

    # clear multiplicative constants on Dimensions which may be
    # left after substitution
    reps = {}
    for m in expr.atoms(Mul):
        if any(isinstance(i, Dimension) for i in m.args):
            reps[m] = m.func(*[i for i in m.args if not i.is_number])

    return expr.xreplace(reps)
예제 #8
0
def test_error_definition():
    # tuple with more or less than two entries
    raises(TypeError, lambda: Dimension(("length", 1, 2)))
    raises(TypeError, lambda: Dimension(["length"]))

    # non-number power
    raises(TypeError, lambda: Dimension({"length": "a"}))

    # non-number with named argument
    raises(TypeError, lambda: Dimension({"length": (1, 2)}))
예제 #9
0
def test_quantity_postprocessing():
    q1 = Quantity('q1', length*pressure**2*temperature/time)
    q2 = Quantity('q2', energy*pressure*temperature/(length**2*time))
    assert q1 + q2
    q = q1 + q2
    Dq = Dimension(Quantity.get_dimensional_expr(q))
    assert Dimension.get_dimensional_dependencies(Dq) == {
        'length': -1,
        'mass': 2,
        'temperature': 1,
        'time': -5,
    }
예제 #10
0
def test_abs():
    v_w1 = Quantity('v_w1', length/time, meter/second)
    v_w2 = Quantity('v_w2', length/time, meter/second)
    v_w3 = Quantity('v_w3', length/time, meter/second)
    expr = v_w3 - Abs(v_w1 - v_w2)

    Dq = Dimension(Quantity.get_dimensional_expr(expr))
    assert Dimension.get_dimensional_dependencies(Dq) == {
        'length': 1,
        'time': -1,
    }
    assert meter == sqrt(meter**2)
예제 #11
0
def test_Dimension_error_definition():
    # tuple with more or less than two entries
    raises(TypeError, lambda: Dimension(("length", 1, 2)))
    raises(TypeError, lambda: Dimension(["length"]))

    # non-number power
    raises(TypeError, lambda: Dimension({"length": "a"}))

    # non-number with named argument
    raises(TypeError, lambda: Dimension({"length": (1, 2)}))

    # symbol should by Symbol or str
    raises(AssertionError, lambda: Dimension("length", symbol=1))
예제 #12
0
def dim_simplify(expr):
    """
    NOTE: this function could be deprecated in the future.

    Simplify expression by recursively evaluating the dimension arguments.

    This function proceeds to a very rough dimensional analysis. It tries to
    simplify expression with dimensions, and it deletes all what multiplies a
    dimension without being a dimension. This is necessary to avoid strange
    behavior when Add(L, L) be transformed into Mul(2, L).
    """

    if isinstance(expr, Dimension):
        return expr

    if isinstance(expr, Pow):
        return dim_simplify(expr.base)**dim_simplify(expr.exp)
    elif isinstance(expr, Function):
        return dim_simplify(expr.args[0])
    elif isinstance(expr, Add):
        if (all(isinstance(arg, Dimension) for arg in expr.args)
                or all(arg.is_dimensionless
                       for arg in expr.args if isinstance(arg, Dimension))):
            return reduce(lambda x, y: x.add(y), expr.args)
        else:
            raise ValueError("Dimensions cannot be added: %s" % expr)
    elif isinstance(expr, Mul):
        return Dimension(
            Mul(*[
                dim_simplify(i).name for i in expr.args
                if isinstance(i, Dimension)
            ]))

    raise ValueError("Cannot be simplifed: %s", expr)
예제 #13
0
def check_dimensions(expr, unit_system="SI"):
    """Return expr if there are not unitless values added to
    dimensional quantities, else raise a ValueError."""
    # the case of adding a number to a dimensional quantity
    # is ignored for the sake of SymPy core routines, so this
    # function will raise an error now if such an addend is
    # found.
    # Also, when doing substitutions, multiplicative constants
    # might be introduced, so remove those now

    from sympy.physics.units import UnitSystem
    unit_system = UnitSystem.get_unit_system(unit_system)

    adds = expr.atoms(Add)
    DIM_OF = unit_system.get_dimension_system().get_dimensional_dependencies
    for a in adds:
        deset = set()
        for ai in a.args:
            if ai.is_number:
                deset.add(())
                continue
            dims = []
            skip = False
            for i in Mul.make_args(ai):
                if i.has(Quantity):
                    i = Dimension(unit_system.get_dimensional_expr(i))
                if i.has(Dimension):
                    dims.extend(DIM_OF(i).items())
                elif i.free_symbols:
                    skip = True
                    break
            if not skip:
                deset.add(tuple(sorted(dims)))
                if len(deset) > 1:
                    raise ValueError(
                        "addends have incompatible dimensions")

    # clear multiplicative constants on Dimensions which may be
    # left after substitution
    reps = {}
    for m in expr.atoms(Mul):
        if any(isinstance(i, Dimension) for i in m.args):
            reps[m] = m.func(*[
                i for i in m.args if not i.is_number])

    return expr.xreplace(reps)
예제 #14
0
def test_Dimension_properties():
    assert dimsys_SI.is_dimensionless(length) is False
    assert dimsys_SI.is_dimensionless(length/length) is True
    assert dimsys_SI.is_dimensionless(Dimension("undefined")) is False

    assert length.has_integer_powers(dimsys_SI) is True
    assert (length**(-1)).has_integer_powers(dimsys_SI) is True
    assert (length**1.5).has_integer_powers(dimsys_SI) is False
예제 #15
0
def test_properties():
    assert length.is_dimensionless is False
    assert (length / length).is_dimensionless is True
    assert Dimension("undefined").is_dimensionless is True

    assert length.has_integer_powers is True
    assert (length**(-1)).has_integer_powers is True
    assert (length**1.5).has_integer_powers is False
예제 #16
0
파일: util.py 프로젝트: sixpearls/sympy
def _get_conversion_matrix_for_expr(expr, target_units):
    from sympy import Matrix

    expr_dim = Dimension(Quantity.get_dimensional_expr(expr))
    dim_dependencies = expr_dim.get_dimensional_dependencies(mark_dimensionless=True)
    target_dims = [Dimension(Quantity.get_dimensional_expr(x)) for x in target_units]
    canon_dim_units = {i for x in target_dims for i in x.get_dimensional_dependencies(mark_dimensionless=True)}
    canon_expr_units = {i for i in dim_dependencies}

    if not canon_expr_units.issubset(canon_dim_units):
        return None

    canon_dim_units = sorted(canon_dim_units)

    camat = Matrix([[i.get_dimensional_dependencies(mark_dimensionless=True).get(j, 0)  for i in target_dims] for j in canon_dim_units])
    exprmat = Matrix([dim_dependencies.get(k, 0) for k in canon_dim_units])

    res_exponents = camat.solve_least_squares(exprmat, method=None)
    return res_exponents
예제 #17
0
파일: util.py 프로젝트: bjodah/sympy
def check_dimensions(expr):
    """Return expr if there are not unitless values added to
    dimensional quantities, else raise a ValueError."""
    from sympy.solvers.solveset import _term_factors
    # the case of adding a number to a dimensional quantity
    # is ignored for the sake of SymPy core routines, so this
    # function will raise an error now if such an addend is
    # found.
    # Also, when doing substitutions, multiplicative constants
    # might be introduced, so remove those now
    adds = expr.atoms(Add)
    DIM_OF = dimsys_default.get_dimensional_dependencies
    for a in adds:
        deset = set()
        for ai in a.args:
            if ai.is_number:
                deset.add(())
                continue
            dims = []
            skip = False
            for i in Mul.make_args(ai):
                if i.has(Quantity):
                    i = Dimension(Quantity.get_dimensional_expr(i))
                if i.has(Dimension):
                    dims.extend(DIM_OF(i).items())
                elif i.free_symbols:
                    skip = True
                    break
            if not skip:
                deset.add(tuple(sorted(dims)))
                if len(deset) > 1:
                    raise ValueError(
                        "addends have incompatible dimensions")

    # clear multiplicative constants on Dimensions which may be
    # left after substitution
    reps = {}
    for m in expr.atoms(Mul):
        if any(isinstance(i, Dimension) for i in m.args):
            reps[m] = m.func(*[
                i for i in m.args if not i.is_number])

    return expr.xreplace(reps)
예제 #18
0
def test_factor_and_dimension():
    assert (3000, Dimension(1)) == Quantity._collect_factor_and_dimension(3000)
    assert (1001, length) == Quantity._collect_factor_and_dimension(meter + km)
    assert (2, length /
            time) == Quantity._collect_factor_and_dimension(meter / second +
                                                            36 * km /
                                                            (10 * hour))

    x, y = symbols('x y')
    assert (x + y / 100,
            length) == Quantity._collect_factor_and_dimension(x * m +
                                                              y * centimeter)

    cH = Quantity('cH')
    cH.set_dimension(amount_of_substance / volume)

    pH = -log(cH)

    assert (1, volume /
            amount_of_substance) == Quantity._collect_factor_and_dimension(
                exp(pH))

    v_w1 = Quantity('v_w1')
    v_w2 = Quantity('v_w2')

    v_w1.set_dimension(length / time)
    v_w2.set_dimension(length / time)
    v_w1.set_scale_factor(Rational(3, 2) * meter / second)
    v_w2.set_scale_factor(2 * meter / second)

    expr = Abs(v_w1 / 2 - v_w2)
    assert (Rational(5, 4), length/time) == \
        Quantity._collect_factor_and_dimension(expr)

    expr = Rational(5, 2) * second / meter * v_w1 - 3000
    assert (-(2996 + Rational(1, 4)), Dimension(1)) == \
        Quantity._collect_factor_and_dimension(expr)

    expr = v_w1**(v_w2 / v_w1)
    assert ((Rational(3, 2))**Rational(4, 3), (length/time)**Rational(4, 3)) == \
        Quantity._collect_factor_and_dimension(expr)
예제 #19
0
def test_abs():
    v_w1 = Quantity('v_w1', length/time, meter/second)
    v_w2 = Quantity('v_w2', length/time, meter/second)
    v_w3 = Quantity('v_w3', length/time, meter/second)
    expr = v_w3 - Abs(v_w1 - v_w2)

    Dq = Dimension(Quantity.get_dimensional_expr(expr))
    assert Dimension.get_dimensional_dependencies(Dq) == {
        'length': 1,
        'time': -1,
    }
    assert meter == sqrt(meter**2)
예제 #20
0
def test_quantity_postprocessing():
    q1 = Quantity('q1', length*pressure**2*temperature/time)
    q2 = Quantity('q2', energy*pressure*temperature/(length**2*time))
    assert q1 + q2
    q = q1 + q2
    Dq = Dimension(Quantity.get_dimensional_expr(q))
    assert Dimension.get_dimensional_dependencies(Dq) == {
        'length': -1,
        'mass': 2,
        'temperature': 1,
        'time': -5,
    }
예제 #21
0
def test_quantity_abs():
    v_w1 = Quantity('v_w1')
    v_w2 = Quantity('v_w2')
    v_w3 = Quantity('v_w3')

    v_w1.set_dimension(length/time)
    v_w2.set_dimension(length/time)
    v_w3.set_dimension(length/time)

    v_w1.set_scale_factor(meter/second)
    v_w2.set_scale_factor(meter/second)
    v_w3.set_scale_factor(meter/second)

    expr = v_w3 - Abs(v_w1 - v_w2)

    Dq = Dimension(Quantity.get_dimensional_expr(expr))
    assert dimsys_default.get_dimensional_dependencies(Dq) == {
        'length': 1,
        'time': -1,
    }
    assert meter == sqrt(meter**2)
예제 #22
0
 def _convert_to(expr, quantity):
     if isinstance(expr, Add):
         return Add(*[_convert_to(i, quantity) for i in expr.args])
     elif isinstance(expr, Mul):
         new_args = [_convert_to(i, quantity) for i in expr.args]
         edim = Dimension(Quantity.get_dimensional_expr(expr))
         if edim == quantity.dimension:
             scale_factor_old = get_total_scale_factor(expr)
             return expr / get_units(
                 expr) * scale_factor_old / quantity.scale_factor * quantity
         return Mul(*new_args)
     elif isinstance(expr, Pow):
         base = _convert_to(expr.base, quantity)
         edim = Dimension(Quantity.get_dimensional_expr(base))**expr.exp
         if edim == quantity.dimension:
             scale_factor_old = get_total_scale_factor(expr)
             return expr / get_units(
                 expr) * scale_factor_old / quantity.scale_factor * quantity
         return base**expr.exp
     elif isinstance(expr, Quantity):
         edim = Dimension(Quantity.get_dimensional_expr(expr))
         edep1 = edim.get_dimensional_dependencies()
         edep2 = quantity.dimension.get_dimensional_dependencies()
         if edim == quantity.dimension:
             return expr.scale_factor / quantity.scale_factor * quantity
         if set(edep1.keys()) == set(edep2.keys()):
             fracs = [
                 Rational(v1, v2)
                 for v1, v2 in zip(edep1.values(), edep2.values())
             ]
             powers = list(set(fracs))
             if len(powers) == 1:
                 return expr.scale_factor / quantity.scale_factor**powers[
                     0] * quantity**powers[0]
         else:
             return expr
     return expr
예제 #23
0
def test_error_regisration():
    # tuple with more or less than two entries
    raises(IndexError, lambda: length._register_as_base_dim())

    one = Dimension(1)
    raises(TypeError, lambda: one._register_as_base_dim())
예제 #24
0
def test_str():
    assert str(Dimension("length")) == "Dimension(length)"
    assert str(Dimension("length", "L")) == "Dimension(length, L)"
예제 #25
0
mebibyte = mebibytes = Quantity("mebibyte")
mebibyte.set_dimension(information)
mebibyte.set_scale_factor(mebi * byte)

gibibyte = gibibytes = Quantity("gibibyte")
gibibyte.set_dimension(information)
gibibyte.set_scale_factor(gibi * byte)

tebibyte = tebibytes = Quantity("tebibyte")
tebibyte.set_dimension(information)
tebibyte.set_scale_factor(tebi * byte)

pebibyte = pebibytes = Quantity("pebibyte")
pebibyte.set_dimension(information)
pebibyte.set_scale_factor(pebi * byte)

exbibyte = exbibytes = Quantity("exbibyte")
exbibyte.set_dimension(information)
exbibyte.set_scale_factor(exbi * byte)

# check that scale factors are the right SI dimensions:
for _scale_factor, _dimension in zip(
        Quantity.SI_quantity_scale_factors.values(),
        Quantity.SI_quantity_dimension_map.values()):
    dimex = Quantity.get_dimensional_expr(_scale_factor)
    if dimex != 1:
        if not dimsys_default.equivalent_dims(_dimension, Dimension(dimex)):
            raise ValueError("quantity value and dimension mismatch")
del _scale_factor, _dimension
예제 #26
0
def test_Dimension_mul_div_exp():
    assert 2 * length == length * 2 == length / 2 == length
    assert 2 / length == 1 / length
    x = Symbol('x')
    m = x * length
    assert m == length * x and m.is_Mul and set(m.args) == {x, length}
    d = x / length
    assert d == x * length**-1 and d.is_Mul and set(d.args) == {x, 1 / length}
    d = length / x
    assert d == length * x**-1 and d.is_Mul and set(d.args) == {1 / x, length}

    velo = length / time

    assert (length * length) == length**2

    assert dimsys_SI.get_dimensional_dependencies(length * length) == {
        length: 2
    }
    assert dimsys_SI.get_dimensional_dependencies(length**2) == {length: 2}
    assert dimsys_SI.get_dimensional_dependencies(length * time) == {
        length: 1,
        time: 1
    }
    assert dimsys_SI.get_dimensional_dependencies(velo) == {
        length: 1,
        time: -1
    }
    assert dimsys_SI.get_dimensional_dependencies(velo**2) == {
        length: 2,
        time: -2
    }

    assert dimsys_SI.get_dimensional_dependencies(length / length) == {}
    assert dimsys_SI.get_dimensional_dependencies(velo / length * time) == {}
    assert dimsys_SI.get_dimensional_dependencies(length**-1) == {length: -1}
    assert dimsys_SI.get_dimensional_dependencies(velo**-1.5) == {
        length: -1.5,
        time: 1.5
    }

    length_a = length**"a"
    assert dimsys_SI.get_dimensional_dependencies(length_a) == {
        length: Symbol("a")
    }

    assert dimsys_SI.get_dimensional_dependencies(length**pi) == {length: pi}
    assert dimsys_SI.get_dimensional_dependencies(
        length**(length / length)) == {
            length: Dimension(1)
        }

    raises(TypeError,
           lambda: dimsys_SI.get_dimensional_dependencies(length**length))

    assert length != 1
    assert length / length != 1

    length_0 = length**0
    assert dimsys_SI.get_dimensional_dependencies(length_0) == {}

    # issue 18738
    a = Symbol('a')
    b = Symbol('b')
    c = sqrt(a**2 + b**2)
    c_dim = c.subs({a: length, b: length})
    assert dimsys_SI.equivalent_dims(c_dim, length)
예제 #27
0
def convert_to(expr, quantity):
    """
    Convert `expr` to the same expression with all of its units and quantities
    represented as factors of `quantity`, whenever the dimension is compatible.

    Examples
    ========

    >>> from sympy.physics.units import speed_of_light, meter, gram, \
        second, day, mile, newton, kilogram, inch, centimeter, atomic_mass_constant
    >>> from sympy.physics.units.definitions import kilometer
    >>> from sympy.physics.units import convert_to
    >>> convert_to(mile, kilometer)
    25146*kilometer/15625
    >>> convert_to(mile, kilometer).n()
    1.609344*kilometer
    >>> convert_to(speed_of_light, meter/second)
    299792458*meter/second
    >>> convert_to(day, second)
    86400*second
    >>> 3*newton
    3*newton
    >>> convert_to(3*newton, kilogram*meter/second**2)
    3*kilogram*meter/second**2
    >>> convert_to(atomic_mass_constant, gram)
    1.66053904e-24*gram
    """
    def get_total_scale_factor(expr):
        if isinstance(expr, Mul):
            return reduce(lambda x, y: x * y,
                          [get_total_scale_factor(i) for i in expr.args])
        elif isinstance(expr, Pow):
            return get_total_scale_factor(expr.base)**expr.exp
        elif isinstance(expr, Quantity):
            return expr.scale_factor
        return 1

    def get_units(expr):
        if isinstance(expr, Mul):
            return reduce(lambda x, y: x * y,
                          [get_units(i) for i in expr.args])
        elif isinstance(expr, Pow):
            return get_units(expr.base)**expr.exp
        elif isinstance(expr, Quantity):
            return expr
        return 1

    if isinstance(quantity, Quantity):
        backup_quantity = None
    else:
        backup_quantity = quantity
        quantity = Quantity("_temp",
                            Dimension(Quantity.get_dimensional_expr(quantity)),
                            get_total_scale_factor(quantity))

    def _convert_to(expr, quantity):
        if isinstance(expr, Add):
            return Add(*[_convert_to(i, quantity) for i in expr.args])
        elif isinstance(expr, Mul):
            new_args = [_convert_to(i, quantity) for i in expr.args]
            edim = Dimension(Quantity.get_dimensional_expr(expr))
            if edim == quantity.dimension:
                scale_factor_old = get_total_scale_factor(expr)
                return expr / get_units(
                    expr) * scale_factor_old / quantity.scale_factor * quantity
            return Mul(*new_args)
        elif isinstance(expr, Pow):
            base = _convert_to(expr.base, quantity)
            edim = Dimension(Quantity.get_dimensional_expr(base))**expr.exp
            if edim == quantity.dimension:
                scale_factor_old = get_total_scale_factor(expr)
                return expr / get_units(
                    expr) * scale_factor_old / quantity.scale_factor * quantity
            return base**expr.exp
        elif isinstance(expr, Quantity):
            edim = Dimension(Quantity.get_dimensional_expr(expr))
            edep1 = edim.get_dimensional_dependencies()
            edep2 = quantity.dimension.get_dimensional_dependencies()
            if edim == quantity.dimension:
                return expr.scale_factor / quantity.scale_factor * quantity
            if set(edep1.keys()) == set(edep2.keys()):
                fracs = [
                    Rational(v1, v2)
                    for v1, v2 in zip(edep1.values(), edep2.values())
                ]
                powers = list(set(fracs))
                if len(powers) == 1:
                    return expr.scale_factor / quantity.scale_factor**powers[
                        0] * quantity**powers[0]
            else:
                return expr
        return expr

    res = _convert_to(expr, quantity)
    if backup_quantity:
        res = res.subs(quantity, backup_quantity)
    return res
예제 #28
0
def test_error_regisration():
    # tuple with more or less than two entries
    raises(IndexError, lambda: length._register_as_base_dim())

    one = Dimension(1)
    raises(TypeError, lambda: one._register_as_base_dim())
예제 #29
0
def test_quantity_dimension_not_registered():
    d = Dimension("someDimension")
    raises(ValueError, lambda: Quantity("q", d, 1))
    raises(ValueError, lambda: Quantity("q", d/length, 1))