def make_quadratic(poly, strength, vartype=None, bqm=None):
    """Create a binary quadratic model from a higher order polynomial.

    Args:
        poly (dict):
            Polynomial as a dict of form {term: bias, ...}, where `term` is a tuple of
            variables and `bias` the associated bias.

        strength (float):
            Strength of the reduction constraint. Insufficient strength can result in the
            binary quadratic model not having the same minimizations as the polynomial.

        vartype (:class:`.Vartype`, optional):
            Vartype of the polynomial. If `bqm` is provided, vartype is not required.

        bqm (:class:`.BinaryQuadraticModel`, optional):
            The terms of the reduced polynomial are added to this binary quadratic model.
            If not provided, a new binary quadratic model is created.

    Returns:
        :class:`.BinaryQuadraticModel`

    Examples:

        >>> poly = {(0,): -1, (1,): 1, (2,): 1.5, (0, 1): -1, (0, 1, 2): -2}
        >>> bqm = dimod.make_quadratic(poly, 5.0, dimod.SPIN)

    """

    if bqm is None:
        if vartype is None:
            raise ValueError("one of vartype and bqm must be provided")
        bqm = BinaryQuadraticModel.empty(vartype)
    else:
        if not isinstance(bqm, BinaryQuadraticModel):
            raise TypeError('create_using must be a BinaryQuadraticModel')
        if vartype is not None and vartype is not bqm.vartype:
            raise ValueError("one of vartype and create_using must be provided")
    bqm.info['reduction'] = {}

    new_poly = {}
    for term, bias in iteritems(poly):
        if len(term) == 0:
            bqm.add_offset(bias)
        elif len(term) == 1:
            v, = term
            bqm.add_variable(v, bias)
        else:
            new_poly[term] = bias

    return _reduce_degree(bqm, new_poly, vartype, strength)