Exemple #1
0
def computeConstBinaryExpr(op, opd0, opd1):
    assert (isinstance(op, EXPR.BinaryOp))
    assert (isinstance(opd0, EXPR.ConstantExpr))
    assert (isinstance(opd1, EXPR.ConstantExpr))

    v0 = opd0.value()
    v1 = opd1.value()

    assert ((type(v0) is int) or (type(v0) is float)
            or isinstance(v0, Fraction))
    assert ((type(v1) is int) or (type(v1) is float)
            or isinstance(v1, Fraction))

    if (op.label == "+"):
        return EXPR.ConstantExpr(v0 + v1)
    elif (op.label == "-"):
        return EXPR.ConstantExpr(v0 - v1)
    elif (op.label == "*"):
        return EXPR.ConstantExpr(v0 * v1)
    elif (op.label == "/"):
        return EXPR.ConstantExpr(v0 / v1)
    elif (op.label == "^"):
        return EXPR.ConstantExpr(v0**v1)
    else:
        assert (False)
    def scalingUpFactor (self):         
        if   (IR.PREC_CANDIDATES == ["e32", "e64"]): 
            return tft_expr.ConstantExpr(math.pow(2, 21))
        elif (IR.PREC_CANDIDATES == ["e64", "e128"]):
            return tft_expr.ConstantExpr(math.pow(2, 50))
        elif (IR.PREC_CANDIDATES == ["e32", "e64", "e128"]):
            return tft_expr.ConstantExpr(math.pow(2, 48))
        else: 
            sys.exit("Error: invalid setting of IR.PREC_CANDIDATES: " + str(IR.PREC_CANDIDATES))

        # scaling_eps = Fraction(0.0) 
        scaling_eps = Fraction(1.0) 
        
        for gid,epss in self.gid2epsilons.items(): 
            for eps in epss: 
                assert(eps.value() >= 0.0) 

                if (eps.value() == 0.0): 
                    continue 

#                if (scaling_eps < eps.value()): 
                if (scaling_eps > eps.value()): 
                    scaling_eps = eps.value() 

        up_fac = Fraction(scaling_eps.denominator, scaling_eps.numerator) 
        # return tft_expr.ConstantExpr(up_fac) 
        # return tft_expr.ConstantExpr(up_fac * 512.0) 
        return tft_expr.ConstantExpr(up_fac / 8.0 ) # It is just a heuristic to divide by 8.0 
def TCastErrorVar (gid, select, cgid, cselect):
    evar = tft_expr.VariableExpr(TCastErrorVarName(gid, select,
                                                   cgid, cselect),
                                 int, -1, False)
    evar.setLB(tft_expr.ConstantExpr(int(0)))
    evar.setUB(tft_expr.ConstantExpr(int(1)))
    assert(tft_expr.isPseudoBooleanVar(evar))
    return evar 
Exemple #4
0
def FindExprBound (optimizer, obj_expr, direction, constraints = []): 
    assert(direction in ["max", "min"]) 
    assert(optimizer in ALL_OPTIMIZERS) 
    assert(isinstance(obj_expr, tft_expr.Expr)) 

    if (isinstance(obj_expr, tft_expr.ConstantExpr)): 
        assert(obj_expr.lb().value() == obj_expr.ub().value()) 
        return obj_expr.lb().value() 

    value_bound = None 

    if (optimizer == "gelpia"): 
        assert(len(constraints) == 0) 

        if (direction == "min"): 
            obj_expr = IR.MakeBinaryExpr("*", -1, tft_expr.ConstantExpr(Fraction(-1, 1)), obj_expr, True)

        glob_solver = None 

        assert(optimizer == "gelpia") 

        glob_solver = tft_ask_gelpia.GelpiaSolver() 

        max_retries = 3 
        n_retries = 0 
        value_bound = None 
        while (True): 
            value_bound = glob_solver.maxObj(obj_expr) 
            if (value_bound is not None): 
                break 
            else: 
                n_retries = n_retries + 1 
            if (n_retries >= max_retries): 
                break 

        assert((value_bound is None) or (isinstance(value_bound, Fraction))) 

        if ((value_bound is not None) and (direction == "min")): 
            value_bound = value_bound * Fraction(-1, 1) 

    else: 
        sys.exit("ERROR: unknown optimizer: " + optimizer) 
    
    if (value_bound is None): 
        return None 

    # check and set expr_min 
    assert(isinstance(value_bound, Fraction))
    if (direction == "max"): 
        obj_expr.setUB(tft_expr.ConstantExpr(value_bound)) 
    elif (direction == "min"): 
        obj_expr.setLB(tft_expr.ConstantExpr(value_bound)) 
    else: 
        sys.exit("ERROR: invalid opt. direction for FindExprBound") 
        
    # return 
    assert(type(value_bound) is Fraction)
    return value_bound
def CastingNumExprTemplate (func_compare, casting_map = {}, gid2epsilons = {}):
    # generate the casting num. expr. 
    cnum_expr = None 
    for p,c in casting_map.items(): 
        assert(len(p) == 2) 
        assert((type(p[0]) is int) and (type(p[1]) is int)) 

        gid_from = p[0] 
        gid_to = p[1] 

        assert(gid_to != tft_expr.PRESERVED_CONST_GID) 
        if (gid_from == tft_expr.PRESERVED_CONST_GID): 
            continue 
            
        assert(0 <= gid_from) 
        assert(gid_from in gid2epsilons.keys())
        assert(0 <= gid_to)
        assert(gid_to in gid2epsilons.keys())

        epss_from = gid2epsilons[gid_from] 
        epss_to = gid2epsilons[gid_to] 

        this_expr = None 
        for f in range(0, len(epss_from)): 
            sum_expr = None
            var_from = GroupErrorVar(gid_from, f)
            
            for t in range(0, len(epss_to)): 
                if (func_compare(epss_from[f], epss_to[t])):
                    tc_expr = None
                    if (tft_utils.LINEAR_TYPE_CASTING_CONSTRAINTS):
                        tc_expr = TCastErrorVar(gid_from, f,
                                                gid_to, t)
                    else:
                        tc_expr = IR.BE("*", -1,
                                        var_from, GroupErrorVar(gid_to, t), True)
                    
                    if (sum_expr is None): 
                        sum_expr = tc_expr
                    else:
                        sum_expr = IR.BE("+", -1, sum_expr, tc_expr, True)

            if (sum_expr is None): 
                continue 

            if (this_expr is None): 
                this_expr = sum_expr
            else:
                this_expr = IR.BE("+", -1, this_expr, sum_expr, True)

        if (this_expr is None): 
            continue 

        this_expr = IR.BE("*", -1, tft_expr.ConstantExpr(c), this_expr, True) 
        if (cnum_expr is None): 
            cnum_expr = this_expr
        else:
            cnum_expr = IR.BE("+", -1, cnum_expr, this_expr, True) 

    return cnum_expr 
Exemple #6
0
def EList2BinaryExpr(elist=[]):
    assert (len(elist) > 0)

    if ((len(elist) == 2) and isinstance(elist[0], EXPR.BinaryOp)
            and (elist[0].label == "-") and isinstance(elist[1], EXPR.Expr)):
        revised_bop = String2BinaryOp("*")
        return EList2BinaryExpr(
            [EXPR.ConstantExpr(-1.0), revised_bop, elist[1]])

    if (len(elist) != 3):
        return None

    else:
        if (not isinstance(elist[0], EXPR.ArithmeticExpr)):
            return None
        if (not isinstance(elist[1], EXPR.BinaryOp)):
            return None
        if (not isinstance(elist[2], EXPR.ArithmeticExpr)):
            return None

        if (coalesceConstBinaryExpr(elist[0], elist[2])):
            return computeConstBinaryExpr(elist[1], elist[0], elist[2])

        else:
            if (elist[1].label == "^"):
                assert (isinstance(elist[2], EXPR.ConstantExpr))
                return ExpandConstPowerExpression(elist[1], elist[0],
                                                  elist[2].value())
            else:
                return EXPR.BinaryExpr(elist[1], elist[0], elist[2])
Exemple #7
0
def String2ConstantExpr(s):
    s = sstrip(s)

    if ((s.find(".") >= 0) or (s.find("e") > 0)):
        try:
            v = float(s)
            return EXPR.ConstantExpr(v)
        except:
            return None

    else:
        try:
            v = int(s)
            if (not BIAS_FLOAT_CONST):
                v = float(s)
            return EXPR.ConstantExpr(v)
        except:
            return None
def SolveErrorForms(eforms=[], optimizers={}):
    assert (len(eforms) > 0)
    assert (all([isinstance(ef, tft_error_form.ErrorForm) for ef in eforms]))
    assert ("vrange" in optimizers.keys())
    assert ("alloc" in optimizers.keys())

    alloc = None
    err_M2 = 0.0

    while (True):
        # -- solve the problem --
        alloc = tft_solver.FirstLevelAllocSolver(optimizers, eforms)

        if (alloc is None):
            break

        if (tft_utils.NO_M2_CHECK):
            break

        # -- check the effect of M2 --
        time_m2 = time.time()
        err_exc = EnsureM2(alloc)

        tft_utils.TIME_CHECK_M2 = tft_utils.TIME_CHECK_M2 + (time.time() -
                                                             time_m2)

        if (type(err_exc) is bool):
            if (err_exc):
                break
            else:
                sys.exit("Error: invalid return value of boolean EnsureM2")

        elif (type(err_exc) is float):
            assert (err_exc > 0.0)

            alloc = None
            err_M2 = err_M2 + (err_exc / 2.0)

            tft_utils.VerboseMessage(
                "For the actual error is " + str(err_exc) +
                " higher than the threshold, retune with M2 = " + str(err_M2))

            # -- adjust the M2 --
            for ef in eforms:
                ef.M2 = tft_expr.ConstantExpr(err_M2)

        else:
            sys.exit("Error: invalid return value type of EnsureM2")

    # assert(alloc is not None)

    return eforms, alloc
Exemple #9
0
def FConst(fpn):
    global CONST_ID

    assert ((type(fpn) is float) or (isinstance(fpn, Fraction)))
    # return tft_expr.ConstantExpr(fpn)

    const_value = tft_expr.ConstantExpr(fpn)
    const_name = tft_expr.PRESERVED_CONST_VPREFIX + "_" + str(CONST_ID)
    CONST_ID = CONST_ID + 1

    return DeclareBoundedVar(const_name, Fraction,
                             tft_expr.PRESERVED_CONST_GID, const_value,
                             const_value, True)
Exemple #10
0
def DeclareBoundedVar(label, vtype, gid, lb, ub, check_prefix=True):
    global EXTERNAL_GIDS
    global INPUT_VARS

    if (TUNE_FOR_ALL):
        gid = 0

    CountGID(gid)

    assert (type(gid) is int)
    assert (0 <= gid)

    if (gid not in EXTERNAL_GIDS):
        EXTERNAL_GIDS.append(gid)

    if ((type(lb) is float) or (type(lb) is int)):
        lb = tft_expr.ConstantExpr(lb)
    elif (isinstance(lb, tft_expr.ConstantExpr)):
        pass
    else:
        sys.exit("ERROR: invalid type of var's lower bound")

    if ((type(ub) is float) or (type(ub) is int)):
        ub = tft_expr.ConstantExpr(ub)
    elif (isinstance(ub, tft_expr.ConstantExpr)):
        pass
    else:
        sys.exit("ERROR: invalid type of var's upper bound")
    assert (lb <= ub)

    var = tft_expr.VariableExpr(label, vtype, gid, check_prefix)
    var.setBounds(lb, ub)

    if (var not in INPUT_VARS):
        INPUT_VARS.append(var)

    AppendCppInst(var)

    return var
    def copy (self, specific_alloc=None): 
        ef_ret = ErrorForm(self.upper_bound) 
        ef_ret.M2 = self.M2
        for et in self.terms: 
            epss = None 
            if (specific_alloc is not None): 
                assert(specific_alloc.isAssigned(et))
                epss = [tft_expr.ConstantExpr(specific_alloc[et])]
            ef_ret.add(et.copy(epss)) 

        ef_ret.gid2epsilons = self.gid2epsilons.copy() 
        ef_ret.gid_counts = self.gid_counts.copy() 
        ef_ret.casting_map = self.casting_map.copy() 

        return ef_ret 
Exemple #12
0
def String2BoundedVariableExpr(s):
    tokens = tft_utils.String2Tokens(s, "in")
    assert (len(tokens) == 2)
    assert (tokens[1].startswith("[") and tokens[1].endswith("]"))

    var = String2Expr(tokens[0], True)
    assert (isinstance(var, EXPR.VariableExpr))

    ran = tft_utils.String2Tokens(tokens[1][1:len(tokens[1]) - 1], ",")
    assert (len(ran) == 2)
    vlb = EXPR.ConstantExpr(var.type()(ran[0]))
    vub = EXPR.ConstantExpr(var.type()(ran[1]))
    assert (isinstance(vlb, EXPR.ConstantExpr))
    assert (isinstance(vub, EXPR.ConstantExpr))

    if (not var.hasBounds()):
        var.setBounds(vlb, vub)
    else:
        # assert(var.lb() == vlb)
        # assert(var.ub() == vub)
        assert (abs(var.lb().value() - vlb.value()) <= float(1e-07))
        assert (abs(var.ub().value() - vub.value()) <= float(1e-07))

    return var
Exemple #13
0
def ExpandConstPowerExpression(op, e_base, c_power):
    assert ((isinstance(op, EXPR.BinaryOp)) and (op.label == "^"))
    assert (isinstance(e_base, EXPR.Expr))
    assert (float(c_power) == int(c_power))

    c_power = int(c_power)
    assert (c_power >= 0)

    if (c_power == 0):
        return EXPR.ConstantExpr(1.0)

    elif (c_power == 1):
        return e_base

    else:
        return EXPR.BinaryExpr(
            EXPR.BinaryOp(op.gid, "*"),
            ExpandConstPowerExpression(op, e_base, (c_power - 1)), e_base)
    def overApproxExpr (self, error_expr): 
        assert(isinstance(error_expr, tft_expr.ArithmeticExpr)) 
        
        if (self.stored_overapprox_expr is not None): 
            return self.stored_overapprox_expr 

        expr_abs_expr = self.absexpr() 
        if ((not expr_abs_expr.hasLB()) or (not expr_abs_expr.hasUB())): 
            sys.exit("ERROR: cannot over-approximate expr. without both LB and UB...")             

        value_lb = expr_abs_expr.lb().value() 
        value_ub = expr_abs_expr.ub().value() 
            
        assert(Fraction(0, 1) <= value_lb) 
        assert(value_lb <= value_ub) 
        
        self.stored_overapprox_expr = IR.MakeBinaryExpr("*", -1, 
                                                        tft_expr.ConstantExpr(value_ub), 
                                                        error_expr, 
                                                        True)

        return self.stored_overapprox_expr 
Exemple #15
0
def MakeBinaryExpr(op_label, op_gid, opd0, opd1, internal=False):
    global EXTERNAL_GIDS

    if ((not internal) and (TUNE_FOR_ALL)):
        op_gid = 0

    assert (type(op_label) is str)
    assert (type(op_gid) is int)
    assert (isinstance(opd0, tft_expr.Expr))
    assert (isinstance(opd1, tft_expr.Expr))

    if (COALESCE_CONST):
        #        if (isinstance(opd0, tft_expr.ConstantExpr) and isinstance(opd1, tft_expr.ConstantExpr)):
        if (isinstance(opd0, tft_expr.ConstantExpr)
                and isinstance(opd1, tft_expr.ConstantExpr)
                and tft_expr.isPreciseConstantExpr(opd0)
                and tft_expr.isPreciseConstantExpr(opd1)):
            v0 = opd0.value()
            v1 = opd1.value()

            if (op_label == "+"):
                eret = tft_expr.ConstantExpr(v0 + v1)
                AppendCppInst(eret)
                return eret

            elif (op_label == "-"):
                eret = tft_expr.ConstantExpr(v0 - v1)
                AppendCppInst(eret)
                return eret

            elif (op_label == "*"):
                eret = tft_expr.ConstantExpr(v0 * v1)
                AppendCppInst(eret)
                return eret

            elif (op_label == "/"):
                eret = tft_expr.ConstantExpr(v0 / v1)
                AppendCppInst(eret)
                return eret

            else:
                sys.exit("ERROR: unknown Binary Operator: " + op_label)

    # possibly bind the constant type
    if ((not tft_utils.FIX_CONST_TYPE) and tft_expr.isConstVar(opd0)):
        if (opd0.getGid() == tft_expr.PRESERVED_CONST_GID):
            CountGID(tft_expr.PRESERVED_CONST_GID, -1)
            opd0.gid = op_gid
        else:
            if (opd0.getGid() != op_gid):
                print("Warning: conflicting constant type...")
    if ((not tft_utils.FIX_CONST_TYPE) and tft_expr.isConstVar(opd1)):
        if (opd1.getGid() == tft_expr.PRESERVED_CONST_GID):
            CountGID(tft_expr.PRESERVED_CONST_GID, -1)
            opd1.gid = op_gid
        else:
            if (opd1.getGid() != op_gid):
                print("Warning: conflicting constant type...")

    if (not internal):
        CountGID(op_gid)
        CountCasting(opd0, op_gid)
        CountCasting(opd1, op_gid)

    if (internal):
        assert (-1 == op_gid)
    else:
        assert (0 <= op_gid)
    if (op_gid not in EXTERNAL_GIDS):
        EXTERNAL_GIDS.append(op_gid)

    ret_expr = tft_expr.BinaryExpr(tft_expr.BinaryOp(op_gid, op_label),
                                   opd0.copy((not internal)),
                                   opd1.copy((not internal)))

    AppendCppInst(ret_expr)

    return ret_expr
def Testing (): 
    print ("==== testing in small-scale ====") 

    # turn off tft_solver.LIMIT_N_CASTINGS
    tft_solver.LIMIT_N_CASTINGS = False 

    # load CID_Training_Counts 
    if (DEF.CID_Training_Counts is None): 
        DEF.CID_Training_Counts = {} 

        assert(os.path.isfile(DEF.FNAME_CID_Training_Counts)) 
        file_ctc = open(DEF.FNAME_CID_Training_Counts, "r")

        for aline in file_ctc: 
            aline = aline.strip() 
            if (aline == ""): 
                continue 
            tokens = tft_utils.String2Tokens(aline, " ") 
            assert(len(tokens) == 2) 
            cid = int(tokens[0]) 
            tcounts = int(tokens[1]) 

            print ("CID Counts : " + str(cid) + " : " + str(tcounts)) 

            assert(cid not in DEF.CID_Training_Counts.keys()) 
            DEF.CID_Training_Counts[cid] = tcounts 
            
#        assert(sum(DEF.CID_Training_Counts.values()) == DEF.N_Samples) 
        
        file_ctc.close() 

    # load HDLID_GID 
    if (DEF.HDLID_GID is None): 
        DEF.HDLID_GID = {} 

        assert(os.path.isfile(DEF.FNAME_HDLID_GID)) 
        fild_hdlid_gid = open(DEF.FNAME_HDLID_GID, "r") 
        
        for aline in fild_hdlid_gid: 
            aline = aline.strip() 
            if (aline == ""): 
                continue 
            tokens = tft_utils.String2Tokens(aline, " ") 
            assert(len(tokens) == 2) 
            hdlid = int(tokens[0]) 
            gid = int(tokens[1]) 

            print ("HDLID: " + str(hdlid) + " : GID: " + str(gid)) 
            
            assert(hdlid not in DEF.HDLID_GID.keys()) 
            DEF.HDLID_GID[hdlid] = gid

        fild_hdlid_gid.close() 

    # load CID_HDLabel 
    if (DEF.CID_HDLabel is None): 
        DEF.CID_HDLabel = {} 
        assert(DEF.DIM_HDL == 0) 
        DEF.DIM_HDL = None 

        assert(os.path.isfile(DEF.FNAME_CID_HDLabel)) 
        file_cid_hdlabel = open(DEF.FNAME_CID_HDLabel, "r") 

        for aline in file_cid_hdlabel: 
            aline = aline.strip() 
            if (aline == ""): 
                continue 
            tokens = tft_utils.String2Tokens(aline, ":") 
            assert(len(tokens) == 2) 
            cid = int(tokens[0]) 
            str_hdlabel = tokens[1] 

            assert((0 <= cid) and (cid < DEF.N_Clusters)) 
            assert(cid not in DEF.CID_HDLabel.keys()) 
            assert(str_hdlabel.startswith("[") and str_hdlabel.endswith("]")) 
            str_hdlabel = str_hdlabel[1:len(str_hdlabel)-1] 
            
            tokens = tft_utils.String2Tokens(str_hdlabel, ",")
            hdlabel = [int(tokens[i]) for i in range(0, len(tokens))] 

            print ("CID: " + str(cid) + " : " + str(hdlabel))

            if (DEF.DIM_HDL is None): 
                DEF.DIM_HDL = len(hdlabel) 
            else: 
                assert(DEF.DIM_HDL == len(hdlabel)) 

            DEF.CID_HDLabel[cid] = hdlabel[:]

        file_cid_hdlabel.close() 

    
    # count DEF.N_CTT_Samples 
    if (DEF.N_CTT_Samples is None): 
        DEF.N_CTT_Samples = 0 

        file_fc = open(DEF.FNAME_SVM_TRAIN_FEATURE_CLUSTER, "r") 

        for aline in file_fc: 
            aline = aline.strip() 

            if (aline == ""): 
                continue 

            DEF.N_CTT_Samples = DEF.N_CTT_Samples + 1 

        file_fc.close() 

        file_fc = open(DEF.FNAME_SVM_TEST_FEATURE_CLUSTER, "r") 
        
        for aline in file_fc: 
            aline = aline.strip() 

            if (aline == ""): 
                continue 

            DEF.N_CTT_Samples = DEF.N_CTT_Samples + 1 

        file_fc.close() 

    # load testing partitions 
    assert((type(DEF.N_CTT_Samples) is int) and (DEF.N_CTT_Samples > 0)) 
    
    file_parts = open(DEF.FNAME_Partitions, "r") 

    String_Partitions = [] 
    
    for aline in file_parts: 
        aline = aline.strip() 

        if (aline == ""): 
            continue 

        assert(len(String_Partitions) <= DEF.N_CTT_Samples) 
        if (len(String_Partitions) == DEF.N_CTT_Samples): 
            break 

        String_Partitions.append(aline)

    file_parts.close() 

    assert(len(String_Partitions) == DEF.N_CTT_Samples) 

    Testing_Partitions = [] 
    pid = -1 

    for i in range(0, DEF.N_CTT_Samples): 
        aline = String_Partitions[i] 

        pid = pid + 1 

        if (DEF.isTrainingID(pid, DEF.N_CTT_Samples)): 
            continue 

        tokens = tft_utils.String2Tokens(aline, " ") 
        this_part = [] 
        
        for i in range(0, len(tokens)): 
            bs = tft_utils.String2Tokens(tokens[i], "~") 
            assert(len(bs) == 2) 
            
            lb = float(bs[0]) 
            ub = float(bs[1]) 

            this_part.append((lb, ub)) 

        Testing_Partitions.append(this_part) 

    String_Partitions = [] # release the space ... 

    # load testing feature -> CID
    Testing_Features = []
    Testing_CIDs = [] 
    assert(os.path.isfile(DEF.FNAME_SVM_TEST_FEATURE_CLUSTER)) 
    file_fc = open(DEF.FNAME_SVM_TEST_FEATURE_CLUSTER, "r")

    for aline in file_fc: 
        aline = aline.strip()

        if (aline == ""): 
            continue 

        tokens = tft_utils.String2Tokens(aline, " ") 

        cid = int(tokens[0]) 
        assert(cid in DEF.CID_HDLabel.keys()) 
        
        this_feature = [] 
        for i in range(1, len(tokens)): 
            fv = tft_utils.String2Tokens(tokens[i], ":") 
            assert(len(fv) == 2) 
            assert(i == int(fv[0])) 
            
            this_feature.append(float(fv[1])) 

        Testing_CIDs.append(cid) 
        Testing_Features.append(this_feature) 
    
    file_fc.close() 

    # check the validity of the data 
    n_tests = len(Testing_Partitions) 
    assert(n_tests == len(Testing_Features)) 
    assert(n_tests == len(Testing_CIDs)) 

    # go testing 
    n_test_success = 0 
    n_exact_allocs = 0 
    CID_Testing_Counts = {} # [0 for i in range(0, DEF.N_Clusters)] 

    while (len(Testing_Partitions) > 0): 
        assert(len(Testing_Partitions) == len(Testing_Features)) 
        assert(len(Testing_Features) == len(Testing_CIDs)) 

        # print out the testing progress 
        sys.stdout.write("\rTest [" + str(n_tests - len(Testing_Partitions)) + "] : ") 

        # get this partition, feature, and the cid 
        this_part = Testing_Partitions[0] 
        this_dvec = DEF.InverseSampleInputPartitionFromVec(this_part) 

        this_feature = Testing_Features[0] 

        exact_cid = Testing_CIDs[0] 

        # sanitation check 
        this_feature_2 = DEF.InputPartition2Feature([DEF.Feature_Option, []], this_dvec)
        assert(len(this_feature) == len(this_feature_2)) 

        for i in range(0, len(this_feature)): 
            f = this_feature[i] 
            f2 = this_feature_2[i] 
            assert(abs(f - f2) < 0.00000001) 

        # predict the alloc 
        this_cid = CIDPredict(this_feature)
        assert(this_cid in DEF.CID_HDLabel.keys()) 

        if (this_cid not in CID_Testing_Counts.keys()): 
            CID_Testing_Counts[this_cid] = 0 

        sys.stdout.write("predicted/exact CID : [" + str(this_cid) + " / " + str(exact_cid) + "] ") 
        sys.stdout.flush() 

        CID_Testing_Counts[this_cid] = CID_Testing_Counts[this_cid] + 1 

        predicted_alloc = DEF.HDLabel2Alloc(DEF.CID_HDLabel[this_cid]) 
        assert(predicted_alloc is not None) 

        # count exact prediction 
        if (this_cid == exact_cid): 
            n_exact_allocs = n_exact_allocs + 1 

        # solve the alloc 
        this_eforms = None 
        this_alloc = None 

        if (DEF.REUSE_EFORMS): 
            assert(DEF.BASE_EFORMS is not None) 

            original_gid_epss = None 
            new_gid_epss      = {} 
            
            # record and overwrite epsilons 
            for ef in DEF.BASE_EFORMS: 
                if (original_gid_epss is None): 
                    original_gid_epss = ef.gid2epsilons.copy() 
                else: 
                    assert(original_gid_epss.keys() == ef.gid2epsilons.keys()) 
                    for gid,epss in original_gid_epss.items():
                        assert(ef.gid2epsilons[gid] == epss) 

                for et in ef.terms: 
                    
                    et.stored_overapprox_expr = None 

                    etgid = et.getGid() 
                    assert(etgid >= 0) 
                    assert(predicted_alloc.isAssigned(etgid)) 

                    assert(etgid in original_gid_epss.keys()) 

                    ow_epss = [tft_expr.ConstantExpr(predicted_alloc[etgid])] 

                    if (etgid in new_gid_epss.keys()): 
                        assert(new_gid_epss[etgid] == ow_epss) 
                    else:
                        new_gid_epss[etgid] = ow_epss 

            for gid in original_gid_epss.keys(): 
                assert(predicted_alloc.isAssigned(gid))
                new_gid_epss[gid] = [tft_expr.ConstantExpr(predicted_alloc[gid])] 

            assert(new_gid_epss.keys() == original_gid_epss.keys()) 

            for ef in DEF.BASE_EFORMS: 
                ef.gid2epsilons = new_gid_epss.copy() 

            # solve alloc. 
            tft_tuning.TFTSystemReset() 
            DEF.RewriteVarBounds(this_part) 
            this_eforms, this_alloc = tft_sol_exprs.SolveErrorForms(DEF.BASE_EFORMS, tft_tuning.OPTIMIZERS) 

            # restore the original epsilons 
            for ef in DEF.BASE_EFORMS: 
                ef.gid2epsilons = original_gid_epss.copy() 
            
        else: 
            # create the exprs file 
            fname_part = tft_dat_sampling.FNameExprs(tft_dat_sampling.FNAME_EXPRS, id_feat) 
            
            # solve alloc. 
            tft_dat_sampling.WriteExprsFile(fname_part, this_part, predicted_alloc)     
            tft_tuning.TFTSystemReset() 
            this_eforms, this_alloc = tft_sol_exprs.SolveExprs(fname_part, tft_tuning.OPTIMIZERS) 
            os.system("rm " + fname_part) 

        # count the correct prediction 
        if (this_alloc is not None): 
            assert(this_alloc == predicted_alloc) 

            n_test_success = n_test_success + 1 
        
            if (VERBOSE): 
                sys.stdout.write(" ---- prediction successed!!") 
                sys.stdout.flush() 
                
        else: 
            if (VERBOSE): 
                print (" ---- prediction failed...") 

        # finalizing 
        del Testing_Partitions[0] 
        del Testing_Features[0] 
        del Testing_CIDs[0]

    print ("") 
    print ("Small-scale Testing Result: " + str(n_test_success) + " / " + str(n_tests) + " (" + str(float(n_test_success)/float(n_tests)) + ")") 
    print ("    Exact Result : " + str(n_exact_allocs) + " / " + str(n_tests) + " (" + str(float(n_exact_allocs)/float(n_tests)) + ")") 

    # show CID_Testing_Counts 
    assert(sum(CID_Testing_Counts.values()) == n_tests) 
    if (VERBOSE): 
        print ("---- cid to # of training partitions ----") 
        for cid in range(0, DEF.N_Clusters): 
            if (cid in CID_Testing_Counts.keys()): 
                print ("CID: " + str(cid) + " : " + str(CID_Testing_Counts[cid])) 
    def errorExpr (self, context_gid, gid): 
        assert(False) 
        assert(type(context_gid)   is int) 
        assert(type(gid)           is int)
        assert(context_gid         in self.gid2epsilons.keys()) 
        assert(gid                 in self.gid2epsilons.keys()) 
        assert((gid == context_gid) or 
               ((gid, context_gid) in self.casting_map.keys()))

        temp_epss         = self.gid2epsilons[gid]
        temp_context_epss = self.gid2epsilons[context_gid]
        epss              = [] 
        context_epss      = []

        checkValidEpsilonList(temp_epss)
        checkValidEpsilonList(temp_context_epss)

        # scaling up the epsilons 
        scaling_expr = self.scalingUpFactor() 
        for i in range(0, len(temp_epss)): 
            epss.append(         tft_expr.ConstantExpr(temp_epss[i].value() * scaling_expr.value()) )
        for j in range(0, len(temp_context_epss)): 
            context_epss.append( tft_expr.ConstantExpr(temp_context_epss[j].value() * scaling_expr.value()) ) 
                
        error_expr = IR.BE("*", -1, 
                           GroupErrorVar(gid, 0), 
                           epss[0], 
                           True) 

        for i in range(1, len(epss)): 
            error_expr = IR.BE("+", -1, 
                               error_expr, 
                               IR.BE("*", -1, 
                                     GroupErrorVar(gid, i), 
                                     epss[i], 
                                     True), 
                               True) 

        tc_error = None 
        
        if (gid != context_gid): 
            for i in range(0, len(epss)): 
                for j in range(0, len(context_epss)): 
                    if (epss[i] < context_epss[j]): 
                        temp_error = IR.BE("*", -1, 
                                           GroupErrorVar(gid, i), 
                                           GroupErrorVar(context_gid, j), 
                                           True) 
                        temp_error = IR.BE("*", -1, 
                                           temp_error, 
                                           context_epss[j], 
                                           # tft_expr.ConstantExpr(context_epss[j].value() + 
                                           #                       (context_epss[j].value() * epss[i].value())), 
                                           True) 
                        if (tc_error is None): 
                            tc_error = temp_error 
                        else:
                            tc_error = IR.BE("+", -1, 
                                             tc_error, 
                                             temp_error, 
                                             True) 

        if (tc_error is None): 
            return error_expr 
                        
        else: 
            return IR.BE("+", -1, error_expr, tc_error, True) 
Exemple #18
0
def ExportExpr2ExprsFile(expr_or_exprs, upper_bound, ifname):
    tft_ir_api.STAT = False

    if (tft_ir_api.TUNE_FOR_ALL):
        assert (len(tft_ir_api.EXTERNAL_GIDS) <= 1)

    if (tft_ir_api.PREC_CANDIDATES == ["e32", "e64"]):
        tft_ir_api.GID_EPSS[tft_expr.PRESERVED_CONST_GID] = ["e64"]

    elif (tft_ir_api.PREC_CANDIDATES == ["e64", "e128"]
          or tft_ir_api.PREC_CANDIDATES == ["e32", "e64", "e128"]):
        tft_ir_api.GID_EPSS[tft_expr.PRESERVED_CONST_GID] = ["e128"]

    else:
        sys.exit("ERROR: invalid setting of tft_ir_api.PREC_CANDIDATES: " +
                 str(tft_ir_api.PREC_CANDIDATES))

    exprs = None
    if (isinstance(expr_or_exprs, tft_expr.Expr)):
        exprs = [expr_or_exprs]
    else:
        assert (len(expr_or_exprs) > 0)
        for expr in expr_or_exprs:
            assert (isinstance(expr, tft_expr.Expr))
        exprs = expr_or_exprs

    # -- check the # of gangs and the # of error terms in the original error form)
    if (isinstance(upper_bound, tft_expr.ConstantExpr)):
        pass
    elif (isinstance(upper_bound, Fraction) or (type(upper_bound) is float)):
        upper_bound = tft_expr.ConstantExpr(upper_bound)
    else:
        sys.exit("ERROR: unsupported type of upper_bound...")

    assert (isinstance(upper_bound, tft_expr.ConstantExpr))

    for v in tft_ir_api.INPUT_VARS:
        assert (isinstance(v, tft_expr.VariableExpr))
        assert (v.hasBounds())

    if (os.path.isfile(ifname)):
        print("WARNING: delete file : " + ifname)
        os.system("rm " + ifname)
    ifile = open(ifname, "w")

    # write options
    ifile.write("options:\n")
    ifile.write("opt-error-form : " + str(tft_ir_api.OPT_ERROR_FORM) + "\n")
    ifile.write("\n")

    # write upper-bound
    ifile.write("upper-bound:\n")
    ifile.write(upper_bound.toCString() + "\n")
    ifile.write("\n")

    # write var-ranges
    ifile.write("var-ranges:\n")
    for i in range(0, len(tft_ir_api.INPUT_VARS)):
        v = tft_ir_api.INPUT_VARS[i]
        ir_var = v.toIRString()
        assert (ir_var.startswith("(") and ir_var.endswith(")"))
        ir_var = ir_var[1:len(ir_var) - 1]
        ifile.write(ir_var + " in [" + v.lb().toCString() + ", " +
                    v.ub().toCString() + "]\n")

    ifile.write("\n")

    # write group-epsilons
    ifile.write("group-epsilons:\n")
    for gid in tft_ir_api.EXTERNAL_GIDS:
        ifile.write(str(gid) + " : ")

        g_epss = None
        if (gid in tft_ir_api.GID_EPSS.keys()):
            g_epss = tft_ir_api.GID_EPSS[gid]
        else:
            g_epss = tft_ir_api.PREC_CANDIDATES

        for i in range(0, len(g_epss)):
            str_eps = g_epss[i]
            if (type(str_eps) is str):
                pass
            elif (type(str_eps) is float):
                str_eps = "(" + str(str_eps) + ")"
            else:
                sys.exit("ERROR: invalid type of group epsilon...")

            if (i == 0):
                ifile.write("[" + str_eps)
            else:
                ifile.write(", " + str_eps)

        ifile.write("]\n")

    ifile.write("\n")

    # write equal bit-width gids
    ifile.write("eq-gids:\n")
    for gp in tft_ir_api.EQ_GIDS:
        assert (len(gp) == 2)
        ifile.write(str(gp[0]) + " = " + str(gp[1]) + "\n")

    ifile.write("\n")

    # write gid counts
    ifile.write("gid-counts:\n")
    for gid, c in tft_ir_api.GID_COUNTS.items():
        ifile.write(str(gid) + " : " + str(c) + "\n")

    ifile.write("\n")

    # write casting counts
    ifile.write("casting-counts:\n")
    for p, c in tft_ir_api.CAST_COUNTS.items():
        ifile.write(str(p) + " : " + str(c) + "\n")
    ifile.write("\n")

    # write gid weight
    ifile.write("gid-weight:\n")
    for g, w in tft_ir_api.GID_WEIGHT.items():
        ifile.write(str(g) + " : " + str(w) + "\n")
    ifile.write("\n")

    # write exprs
    ifile.write("exprs:\n")
    for i in range(0, len(tft_ir_api.INTERVAR_EXPR)):
        var_expr = tft_ir_api.INTERVAR_EXPR[i]
        assert (len(var_expr) == 2)
        assert (isinstance(var_expr[0], tft_expr.VariableExpr))
        assert (isinstance(var_expr[1], tft_expr.Expr))
        ir_var = var_expr[0].toIRString()
        assert (ir_var.startswith("(") and ir_var.endswith(")"))
        ir_var = ir_var[1:len(ir_var) - 1]
        ifile.write(ir_var + " = " + var_expr[1].toIRString() + "\n")
    for expr in exprs:
        ifile.write(expr.toIRString() + "\n")

    ifile.write("\n")

    # write constraints
    ifile.write("constraints:\n")
    for cons in tft_ir_api.CONSTRAINTS:
        ifile.write(cons.toIRString() + "\n")

    # finalize
    ifile.close()
    def errorExpr (self, scaling_expr, gid2epsilons={}, casting_map={}): 
        assert(isinstance(scaling_expr, tft_expr.ConstantExpr))
        assert(type(self.context_gid)   is int) 
        assert(type(self.gid)           is int)
        assert(self.context_gid         in gid2epsilons.keys()) 
        assert(self.gid                 in gid2epsilons.keys()) 
        assert((self.gid == self.context_gid) or 
               ((self.gid, self.context_gid) in casting_map.keys()))

        temp_epss         = gid2epsilons[self.gid]
        temp_context_epss = gid2epsilons[self.context_gid]
        epss              = [] 
        context_epss      = []

        checkValidEpsilonList(temp_epss)
        checkValidEpsilonList(temp_context_epss)

        # scaling up the epsilons 
        for i in range(0, len(temp_epss)): 
            epss.append( tft_expr.ConstantExpr(temp_epss[i].value() * scaling_expr.value()) )
        for j in range(0, len(temp_context_epss)): 
            context_epss.append( tft_expr.ConstantExpr(temp_context_epss[j].value() * scaling_expr.value()) ) 

        error_expr = None

        if (not self.is_precise_opt): 
            error_expr = IR.BE("*", -1, 
                               GroupErrorVar(self.gid, 0), 
                               epss[0], 
                               True) 

            for i in range(1, len(epss)): 
                error_expr = IR.BE("+", -1, 
                                   error_expr, 
                                   IR.BE("*", -1, 
                                         GroupErrorVar(self.gid, i), 
                                         epss[i], 
                                         True), 
                                   True) 

        tc_error = None 
        
        if (self.gid != self.context_gid): 
            for i in range(0, len(epss)): 
                for j in range(0, len(context_epss)): 
                    if (epss[i] < context_epss[j]): 
                        temp_error = self.tcastExpr(i, j)
                        temp_error = IR.BE("*", -1, 
                                           temp_error, 
                                           context_epss[j], 
                                           # tft_expr.ConstantExpr(context_epss[j].value() + 
                                           #                       (context_epss[j].value() * epss[i].value())), 
                                           True) 
                        if (tc_error is None): 
                            tc_error = temp_error 
                        else:
                            tc_error = IR.BE("+", -1, 
                                             tc_error, 
                                             temp_error, 
                                             True) 
        
        if   (error_expr is None and tc_error is None): 
            return tft_expr.ConstantExpr(0.0)
        elif (tc_error is None): 
            return error_expr 
        elif (error_expr is None): 
            return tc_error
        else: 
            return IR.BE("+", -1, error_expr, tc_error, True) 
Exemple #20
0
def GenerateErrorTermsFromExpr(context_expr,
                               expr,
                               error_exprs=[],
                               program_exprs=[]):
    assert (len(error_exprs) == len(program_exprs))

    if (isinstance(expr, tft_expr.ConstantExpr)):
        return []

    elif (isinstance(expr, tft_expr.VariableExpr)
          or isinstance(expr, tft_expr.BinaryExpr)
          or isinstance(expr, tft_expr.UnaryExpr)):

        my_et = None
        gid = expr.getGid()

        assert (gid in GID_EPSS.keys())
        epss = GID_EPSS[gid]

        prog_expr = None
        error_expr = None

        if (False):
            #        if (tft_expr.isPreciseOperation(expr)):
            error_expr = tft_expr.ConstantExpr(0.0)

        else:
            for i in range(0, len(program_exprs)):
                pe = program_exprs[i]
                if (expr.identical(pe)):
                    prog_expr = pe
                    error_expr = error_exprs[i]

            if (error_expr is None):
                print("<<<< expr >>>>")
                print(expr.toIRString())
                print(expr.toASTString())
                print(">>>> program exprs <<<<")
                for pe in program_exprs:
                    print(pe.toIRString())
                    print(pe.toASTString())
                    print("------------")

        assert (error_expr is not None)

        # get my ErrorTerm
        my_et = tft_error_form.ErrorTerm(error_expr,
                                         context_expr.getGid(), gid,
                                         tft_expr.isPreciseOperation(expr))

        # get my operands' ErrorTerms and do some more book keeping
        if (isinstance(expr, tft_expr.VariableExpr)):
            return [my_et]

        elif (isinstance(expr, tft_expr.UnaryExpr)):
            ets_opd = GenerateErrorTermsFromExpr(expr, expr.opd(), error_exprs,
                                                 program_exprs)

            return [my_et] + ets_opd

        elif (isinstance(expr, tft_expr.BinaryExpr)):

            ets_lhs = GenerateErrorTermsFromExpr(expr, expr.lhs(), error_exprs,
                                                 program_exprs)

            ets_rhs = GenerateErrorTermsFromExpr(expr, expr.rhs(), error_exprs,
                                                 program_exprs)

            return [my_et] + ets_lhs + ets_rhs

        else:
            sys.exit(
                "ERROR: broken control flow in GenerateErrorTermsFromExpr...")

    else:
        sys.exit("ERROR: invlaid expr. type...")
Exemple #21
0
def SolveExprs(fname_exprs, optimizers={}):
    global EFORMS
    global E_UPPER_BOUND
    global M2

    global GID_EPSS
    global GID_COUNTS
    global GID_WEIGHT
    global CASTING_MAP
    global EQ_GIDS
    global CONSTRAINT_EXPRS
    global OPT_ERROR_FORM
    global TARGET_EXPRS

    EFORMS = None
    E_UPPER_BOUND = None
    M2 = None

    time_parsing = time.time()

    tft_utils.VerboseMessage("parsing input expression...")
    tft_utils.DebugMessage("reading .exprs file...")

    assert (os.path.isfile(fname_exprs))
    assert (ERROR_TYPE in ["abs", "rel"])

    # variables
    input_vars = []
    E_UPPER_BOUND = None

    ilines = []

    efile = open(fname_exprs, "r")
    for aline in efile:
        aline = aline.strip()
        if (aline == ""):
            continue
        if (aline.startswith("#")):
            continue
        ilines.append(aline)
    efile.close()

    # options
    assert (ilines[0] == "options:")
    ilines = ilines[1:]
    while True:
        if (ilines[0] == "upper-bound:"):
            break

        tokens = tft_utils.String2Tokens(ilines[0], ":")
        assert (len(tokens) == 2)

        if (tokens[0] == "opt-error-form"):
            OPT_ERROR_FORM = tft_utils.String2Bool(tokens[1])

        else:
            sys.exit("ERROR: unknown option setting: " + ilines[0])

        ilines = ilines[1:]

    # read error bound
    assert (ilines[0] == "upper-bound:")
    ilines = ilines[1:]
    E_UPPER_BOUND = tft_expr.ConstantExpr(float(ilines[0]))
    ilines = ilines[1:]

    # M2
    M2 = tft_expr.ConstantExpr(0.0)

    # read variable ranges
    assert (ilines[0] == "var-ranges:")
    ilines = ilines[1:]
    while True:
        if (ilines[0] == "group-epsilons:"):
            break

        var = tft_parser.String2BoundedVariableExpr(ilines[0])

        assert (var not in input_vars)
        input_vars.append(var)

        ilines = ilines[1:]

    # get groups' epsilons
    assert (ilines[0] == "group-epsilons:")
    ilines = ilines[1:]
    while True:
        if (ilines[0] == "eq-gids:"):
            break

        tokens = tft_utils.String2Tokens(ilines[0], ":")
        assert (len(tokens) == 2)

        gid = int(tokens[0])
        str_epss = tokens[1]

        assert (str_epss.startswith("[") and str_epss.endswith("]"))
        str_epss = str_epss[1:len(str_epss) - 1]
        str_eps_list = tft_utils.String2Tokens(str_epss, ",")

        eps_list = []

        for i in range(0, len(str_eps_list)):
            try:
                i = tft_alloc.EpsLabels_String().index(str_eps_list[i])
                eps_list.append(
                    tft_expr.ConstantExpr(tft_alloc.EPSILONS[i].value))
            except ValueError:
                expr_eps = tft_parser.String2Expr(str_eps_list[i], True)
                assert (isinstance(expr_eps, tft_expr.ConstantExpr))
                eps_list.append(expr_eps)

        assert (gid not in GID_EPSS.keys())
        GID_EPSS[gid] = eps_list

        ilines = ilines[1:]

    # get equal bit-width groups
    assert (len(ilines) > 0)
    assert (ilines[0] == "eq-gids:")
    ilines = ilines[1:]
    while True:
        assert (len(ilines) > 0)
        if (ilines[0] == "gid-counts:"):
            break

        tokens = tft_utils.String2Tokens(ilines[0], "=")
        assert (len(tokens) == 2)

        gid_1 = int(tokens[0])
        gid_2 = int(tokens[1])

        if (gid_1 == gid_2):
            ilines = ilines[1:]
            continue

        assert (gid_1 in GID_EPSS.keys())
        assert (gid_2 in GID_EPSS.keys())
        assert (GID_EPSS[gid_1] == GID_EPSS[gid_2])

        gp12 = (gid_1, gid_2)
        gp21 = (gid_2, gid_1)

        if ((gp12 not in EQ_GIDS) and (gp21 not in EQ_GIDS)):
            EQ_GIDS.append(gp12)

        ilines = ilines[1:]

    # get GID_COUNTS
    assert (len(ilines) > 0)
    assert (ilines[0] == "gid-counts:")
    ilines = ilines[1:]
    while True:
        assert (len(ilines) > 0)
        if (ilines[0] == "casting-counts:"):
            break

        tokens = tft_utils.String2Tokens(ilines[0], ":")
        assert (len(tokens) == 2)

        gid = int(tokens[0])
        c = int(tokens[1])

        assert (gid >= 0)
        assert (c >= 0)
        assert (gid not in GID_COUNTS.keys())

        if (c > 0):
            GID_COUNTS[gid] = c

        ilines = ilines[1:]

    # get CASTING_MAP
    assert (len(ilines) > 0)
    assert (ilines[0] == "casting-counts:")
    ilines = ilines[1:]
    while True:
        assert (len(ilines) > 0)
        if (ilines[0] == "gid-weight:"):
            break

        tokens = tft_utils.String2Tokens(ilines[0], ":")
        assert (len(tokens) == 2)

        p = tokens[0]
        c = int(tokens[1])

        assert (c > 0)
        assert (p.startswith("(") and p.endswith(")"))
        p = p[1:len(p) - 1]

        tokens = tft_utils.String2Tokens(p, ",")
        assert (len(tokens) == 2)

        gid_from = int(tokens[0])
        gid_to = int(tokens[1])

        p = (gid_from, gid_to)

        assert (p not in CASTING_MAP.keys())
        CASTING_MAP[p] = c

        ilines = ilines[1:]

    # get gid-weight mapping
    assert (len(ilines) > 0)
    assert (ilines[0] == "gid-weight:")
    ilines = ilines[1:]
    while True:
        assert (len(ilines) > 0)
        if (ilines[0] == "exprs:"):
            break

        tokens = tft_utils.String2Tokens(ilines[0], ":")
        assert (len(tokens) == 2)

        gid = int(tokens[0])
        weight = float(tokens[1])
        assert (0 <= gid)
        assert (0 <= weight)

        GID_WEIGHT[gid] = weight

        ilines = ilines[1:]

    # get expressions
    assert (len(ilines) > 0)
    assert (ilines[0] == "exprs:")
    ilines = ilines[1:]
    while True:
        assert (len(ilines) > 0)
        if (ilines[0] == "constraints:"):
            break

        target_expr = tft_parser.String2Expr(ilines[0], False)
        assert (isinstance(target_expr, tft_expr.ArithmeticExpr))

        TARGET_EXPRS.append(target_expr)

        ilines = ilines[1:]

    assert (len(TARGET_EXPRS) > 0)
    assert (all([isinstance(te, tft_expr.Expr) for te in TARGET_EXPRS]))

    # get constraints
    assert (len(ilines) > 0)
    assert (ilines[0] == "constraints:")
    ilines = ilines[1:]
    while True:
        if (len(ilines) == 0):
            break

        pred_expr = tft_parser.String2Expr(ilines[0], False)
        assert (isinstance(pred_expr, tft_expr.Predicate))

        CONSTRAINT_EXPRS.append(pred_expr)

        ilines = ilines[1:]

    # ---- generate the Error Forms ----
    tft_utils.DebugMessage(".exprs file read")
    tft_utils.DebugMessage("generating ErrorForms...")

    target_alloc = None
    irstrings = None

    EFORMS = []
    for te in TARGET_EXPRS:
        ef = GenerateErrorFormFromExpr(te, ERROR_TYPE, E_UPPER_BOUND, M2,
                                       EQ_GIDS, CONSTRAINT_EXPRS)
        EFORMS.append(ef)

    assert (len(EFORMS) == len(TARGET_EXPRS))

    # ---- solve from the ErrorForms ----
    tft_utils.DebugMessage("ErrorForms generated")

    tft_utils.TIME_PARSING = tft_utils.TIME_PARSING + (time.time() -
                                                       time_parsing)

    EFORMS, target_alloc = SolveErrorForms(EFORMS, optimizers)

    if (VERBOSE):
        print("---- Error Forms after solving ----")
        for ef in EFORMS:
            print(str(ef))
            print("------------")

    if (target_alloc is None):
        print("TFT: no available allocation for the main expr...")
        return EFORMS, None

    # ---- some finalize before return ----
    if (VERBOSE):
        stat = {}
        for te in TARGET_EXPRS:
            tft_expr.ExprStatistics(te, stat)

        assert ("# constants" in stat.keys())
        assert ("# variables" in stat.keys())
        assert ("# operations" in stat.keys())
        assert ("groups" in stat.keys())

        stat["groups"].sort()

        print("---- # constants:  " + str(stat["# constants"]) +
              "  (# of appearances)")
        print("---- # variables:  " + str(stat["# variables"]) +
              "  (# of appearances)")
        print("---- # operations: " + str(stat["# operations"]))
        print("---- groups: " + str(stat["groups"]))

#        n_opts,n_insts = tft_error_form.countOptsInsts(EFORMS)
#        print ("---- # of (static) operations: " + str(n_opts)  + " ----")
#        print ("---- # of (dynamic) instances: " + str(n_insts) + " ----")

# ---- return ----
    return EFORMS, target_alloc
Exemple #22
0
def main():
    # ==== get parameters ====
    parser = argparse.ArgumentParser()
    parser.add_argument("expr_spec", help="Expression Specification")

    parser.add_argument("-v",
                        "--verbose",
                        action="store_true",
                        default=False,
                        help="Verbose mode")

    parser.add_argument("-d",
                        "--debug",
                        action="store_true",
                        default=False,
                        help="Debug mode")

    parser.add_argument("-n",
                        "--no-m2-check",
                        action="store_true",
                        default=False,
                        help="Skip m2 check")

    parser.add_argument("-m",
                        "--maxc",
                        type=int,
                        help="Maximum number of type casts")

    parser.add_argument("--linear-tc",
                        action="store_true",
                        default=False,
                        help="Use linear type casting constraints")

    parser.add_argument(
        "--aopt",
        type=str,
        default="gurobi",
        help=
        "Allocation optimization solver: \"gurobi\" for Gurobi and \"glpk\" for GLPK (must work with --linear-tc)"
    )

    parser.add_argument("--gopt-timeout",
                        type=int,
                        default=120,
                        help="Timeout of the global optimization")

    parser.add_argument("--gopt-tolerance",
                        type=float,
                        default=5e-02,
                        help="Tolerance of the global optimization")

    parser.add_argument("--optm",
                        type=str,
                        default="max-benefit",
                        choices=tft_utils.OPT_METHODS,
                        help="Optimization method")

    parser.add_argument("-e",
                        "--error-bounds",
                        type=str,
                        required=True,
                        help="Error bounds")

    parser.add_argument("-b",
                        "--bitwidths",
                        type=str,
                        default="32 64",
                        help="Bit-width candidates")

    parser.add_argument("--fix-const-type",
                        action="store_true",
                        default=False,
                        help="Fix the constant type to the highest bit-width")

    args = parser.parse_args()

    INPUT_FILE = args.expr_spec
    if not os.path.isfile(INPUT_FILE):
        error("Input expression file doesn't exist: {}".format(INPUT_FILE))

    tft_utils.FPTUNER_VERBOSE = args.verbose or args.debug

    tft_utils.FPTUNER_DEBUG = args.debug

    tft_utils.NO_M2_CHECK = args.no_m2_check

    if args.maxc != None:
        if args.maxc < 0:
            error("maxc must be >= 0")
        tft_utils.N_MAX_CASTINGS = args.maxc

    if args.gopt_timeout <= 0:
        error("gopt-timeout must be > 0")
    tft_utils.GOPT_TIMEOUT = args.gopt_timeout

    if args.gopt_tolerance < 0.0:
        error("gopt-tolerance must be >= 0.0")
    tft_utils.GOPT_TOLERANCE = args.gopt_tolerance

    tft_utils.OPT_METHOD = args.optm

    err_list = args.error_bounds.split()
    try:
        err_list = [float(e) for e in err_list]
        if len(err_list) == 0 or not all([e > 0.0 for e in err_list]):
            raise ValueError
    except ValueError:
        error("The error bounds must all be non-negative floats.")
    tft_tuning.ERROR_BOUNDS = err_list

    bit_widths = args.bitwidths.replace(',', ' ').split()
    try:
        bit_widths = [int(b) for b in bit_widths]
        bit_widths = list(set(bit_widths))
        bit_widths.sort()
        if bit_widths not in ([32, 64, 128], [32, 64], [64, 128]):
            raise ValueError
    except ValueError:
        error(
            "Accepted bitwidth candidates are: '32 64', '64 128', '32 64 128'")
    IR.PREC_CANDIDATES = ["e{}".format(b) for b in bit_widths]

    tft_utils.FIX_CONST_TYPE = args.fix_const_type

    tft_utils.LINEAR_TYPE_CASTING_CONSTRAINTS = args.linear_tc

    tft_tuning.OPTIMIZERS["alloc"] = args.aopt
    if (tft_tuning.OPTIMIZERS['alloc'] == 'glpk'):
        assert (tft_utils.LINEAR_TYPE_CASTING_CONSTRAINTS
                ), "Solver GLPK must work with --linear-tc"

    # ==== load the input file as a module ====
    if INPUT_FILE.endswith(".py"):
        tokens = tft_utils.String2Tokens(INPUT_FILE, "/")
        assert (len(tokens) >= 1)

        module_name = tokens[-1]
        assert (module_name.endswith(".py"))
        module_name = module_name[0:len(module_name) - 3]

        IR.LOAD_CPP_INSTS = True
        module_in = imp.load_source(module_name, INPUT_FILE)
        if (IR.TARGET_EXPR is None):
            error("no tuning target expression was specified.")
        IR.LOAD_CPP_INSTS = False

    else:  # New frontend
        with open(INPUT_FILE, 'r') as f:
            data = f.read()
        processed_data = get_runmain_input(data)
        py_source = translate(processed_data)

        code_obj = compile(py_source, '<string>', 'exec')

        IR.LOAD_CPP_INSTS = True
        exec(code_obj)
        if (IR.TARGET_EXPR is None):
            error("No tuning target expression was specified.")
        IR.LOAD_CPP_INSTS = False

    # ==== tune the targeted expression ====
    # reset the timers
    tft_utils.TIME_PARSING = 0
    tft_utils.TIME_FIRST_DERIVATIVES = 0
    tft_utils.TIME_GLOBAL_OPT = 0
    tft_utils.TIME_ALLOCATION = 0
    tft_utils.TIME_CHECK_M2 = 0

    # possibly remove the .exprs file
    EXPRS_NAME = INPUT_FILE + ".exprs"
    if (os.path.isfile(EXPRS_NAME)):
        tft_utils.VerboseMessage("Warning: overwriting existing file: " +
                                 EXPRS_NAME)
        os.system("rm " + EXPRS_NAME)

    # go tuning
    for i in range(0, len(tft_tuning.ERROR_BOUNDS)):
        eforms = None
        alloc = None

        # Tune for the first error bound.
        # Need to generate the .exprs file first.
        if (i == 0):
            tft_ir_backend.ExportExpr2ExprsFile(IR.TARGET_EXPR,
                                                tft_tuning.ERROR_BOUNDS[0],
                                                EXPRS_NAME)

            # tune!
            eforms, alloc = tft_tuning.TFTRun(EXPRS_NAME)

        # otherwise, do some reset tasks
        else:
            tft_sol_exprs.ReadyToTune()

            new_eup = tft_expr.ConstantExpr(tft_tuning.ERROR_BOUNDS[i])

            for ef in tft_sol_exprs.EFORMS:
                ef.upper_bound = new_eup

            # solve the error form
            eforms, alloc = tft_sol_exprs.SolveErrorForms(
                tft_sol_exprs.EFORMS, tft_tuning.OPTIMIZERS)

        # show the allocation
        print("==== error bound : " + str(tft_tuning.ERROR_BOUNDS[i]) +
              " ====")
        tft_tuning.PrintAlloc(alloc, eforms)
        print("")
        tft_ir_backend.ExportColorInsts(alloc)
        print("")

        # -- synthesize the mixed precision cpp file --
        if (alloc is None):
            print(
                "Warning: no allocation was generated... Thus no .cpp file will be generated..."
            )
        else:
            assert (isinstance(alloc, tft_alloc.Alloc))
            assert (eforms is not None)

            str_error_bound = str(float(tft_tuning.ERROR_BOUNDS[i]))
            base = os.path.basename(INPUT_FILE)
            base = os.path.splitext(base)[0]
            fname_cpp = base + "." + str_error_bound + ".cpp"

            if (os.path.isfile(fname_cpp)):
                tft_utils.VerboseMessage(
                    "Warning: overwrite the existed .cpp file: " + fname_cpp)

            tft_ir_backend.ExportCppInsts(alloc, fname_cpp)

    # show the timers
    timer_fname = base + ".timers.csv"
    write_header = (not os.path.isfile(timer_fname))

    timer_file = None

    if (write_header):
        timer_file = open(timer_fname, "w")
        timer_file.write(
            "Total Parsing Time,First Derivatives,Global Optimization,QCQP,Check Higher-order Errors\n"
        )
    else:
        timer_file = open(timer_fname, "a")

    timer_file.write(
        str(float(tft_utils.TIME_PARSING)) + "," +
        str(float(tft_utils.TIME_FIRST_DERIVATIVES)) + "," +
        str(float(tft_utils.TIME_GLOBAL_OPT)) + "," +
        str(float(tft_utils.TIME_ALLOCATION)) + "," +
        str(float(tft_utils.TIME_CHECK_M2)) + "\n")

    tft_utils.VerboseMessage("Total Parsing time          : " +
                             str(float(tft_utils.TIME_PARSING)))
    tft_utils.VerboseMessage("    First Dev.              : " +
                             str(float(tft_utils.TIME_FIRST_DERIVATIVES)))
    tft_utils.VerboseMessage("Time for global optimization: " +
                             str(float(tft_utils.TIME_GLOBAL_OPT)))
    tft_utils.VerboseMessage("Time for solving QCQP       : " +
                             str(float(tft_utils.TIME_ALLOCATION)))
    tft_utils.VerboseMessage("Time for checking M2        : " +
                             str(float(tft_utils.TIME_CHECK_M2)))

    timer_file.close()
Exemple #23
0
        "WARNING: no additional tuning when the \"base\" allocation is None..."
    )
    exit(1)

assert (tft_sol_exprs.EFORMS is not None)
assert (len(tft_sol_exprs.EFORMS) > 0)
assert (all(
    [isinstance(ef, tft_error_form.ErrorForm) for ef in tft_sol_exprs.EFORMS]))
assert (len(tft_tuning.OPTIMIZERS) > 0)

for ai in range(3, len(sys.argv)):
    af = None
    try:
        af = float(sys.argv[ai])
    except:
        print("ERROR: invalid additional error threshold: " +
              str(sys.argv[ai]))

    new_eup = tft_expr.ConstantExpr(af)

    for ef in tft_sol_exprs.EFORMS:
        ef.upper_bound = new_eup

    # solve the error form
    eforms, alloc = tft_sol_exprs.SolveErrorForms(tft_sol_exprs.EFORMS,
                                                  tft_tuning.OPTIMIZERS)

    print("==== Additional Allocation with Error Threshold: " + str(new_eup) +
          " ====")
    FinalizeAlloc(FNAME_ATEXT + "-" + sys.argv[ai], alloc, eforms)
    def scoreExpr (self):
        global EPS_SCORE
        
        ret_se = None 

        if   (len(IR.PREC_CANDIDATES) == 2): 
            for gid,c in self.gid_counts.items(): 
                if (gid == tft_expr.PRESERVED_CONST_GID): 
                    continue 

                checkValidEpsilonList(self.gid2epsilons[gid]) 

                group_evar = None 
                assert(tft_utils.OPT_METHOD in tft_utils.OPT_METHODS) 
                if   (tft_utils.OPT_METHOD == "max-benefit"):
                    group_evar = GroupErrorVar(gid, 0)
                elif (tft_utils.OPT_METHOD == "min-penalty"):
                    group_evar = GroupErrorVar(gid, 1)
                else:
                    assert(False), "No such optimization method: " + str(tft_utils.OPT_METHOD)
                assert(group_evar is not None)
                
                expr_score = IR.BE("*", -1, group_evar, tft_expr.ConstantExpr(int(c)), True) 

                assert(group_evar.hasBounds()) 

                if gid in self.gid_weight.keys(): 
                    weight = self.gid_weight[gid] 
                    assert((type(weight) is float) and (0 <= weight)) 

                    expr_score = IR.BE("*", -1, expr_score, tft_expr.ConstantExpr(weight), True) 
            
                if (ret_se is None): 
                    ret_se = expr_score 
                else: 
                    ret_se = IR.BE("+", -1, ret_se, expr_score, True)

            assert(ret_se is not None)
            return ret_se

        elif (len(IR.PREC_CANDIDATES) >= 3):
            assert(tft_utils.OPT_METHOD in tft_utils.OPT_METHODS) 
            if   (tft_utils.OPT_METHOD == "max-benefit"):
                EPS_SCORE[tft_alloc.EPSILON_32]  = 100.0
                EPS_SCORE[tft_alloc.EPSILON_64]  = 1.0
                EPS_SCORE[tft_alloc.EPSILON_128] = 0.0
            elif (tft_utils.OPT_METHOD == "min-penalty"):
                EPS_SCORE[tft_alloc.EPSILON_32]  = 0.0 
                EPS_SCORE[tft_alloc.EPSILON_64]  = 1.0
                EPS_SCORE[tft_alloc.EPSILON_128] = 100.0                
            else:
                assert(False), "No such optimization method: " + str(tft_utils.OPT_METHOD)
            
            for gid,c in self.gid_counts.items(): 
                if (gid == tft_expr.PRESERVED_CONST_GID): 
                    continue 

                checkValidEpsilonList(self.gid2epsilons[gid]) 
                
                for ei in range(0, len(self.gid2epsilons[gid])): 
                    expr_score = None 

                    group_evar = GroupErrorVar(gid, ei)
                    assert(group_evar.hasBounds()) 

                    eps = self.gid2epsilons[gid][ei].value()
                    assert(eps in EPS_SCORE.keys())
                    
                    weight = EPS_SCORE[eps]
                    assert(type(weight) is float) 

                    weight = weight * float(c) 

                    if gid in self.gid_weight.keys(): 
                        ext_weight = self.gid_weight[gid]
                        assert((type(ext_weight) is float) and (0 <= ext_weight)) 
                        weight = weight * ext_weight 

                    assert(0 <= weight) 

                    if (weight > 0.0):
                        expr_score = IR.BE("*", -1, group_evar, tft_expr.ConstantExpr(weight), True) 

                        if (ret_se is None): 
                            ret_se = expr_score 
                        else: 
                            ret_se = IR.BE("+", -1, ret_se, expr_score, True)

                    else: 
                        pass 

            assert(ret_se is not None)
            return ret_se

        else: 
            sys.exit("Error: invalid # of bit-width candidates...") 
Exemple #25
0
def MakeUnaryExpr(op_label, op_gid, opd0, internal=False):
    global EXTERNAL_GIDS

    if ((not internal) and (TUNE_FOR_ALL)):
        op_gid = 0

    assert (type(op_label) is str)
    assert (type(op_gid) is int)
    assert (isinstance(opd0, tft_expr.Expr))

    if (COALESCE_CONST):
        if (isinstance(opd0, tft_expr.ConstantExpr)):
            if (op_label == "abs"):
                eret = tft_expr.ConstantExpr(abs(opd0.value()))
                AppendCppInst(eret)
                return eret

            elif (op_label == "-"):
                eret = tft_expr.ConstantExpr(-1.0 * opd0.value())
                AppendCppInst(eret)
                return eret

            elif (op_label == "sqrt"):
                cv = opd0.value()
                assert (cv >= 0.0)
                eret = tft_expr.ConstantExpr(math.sqrt(cv))
                AppendCppInst(eret)
                return eret

            else:
                sys.exit("ERROR: unknown Unary Operator: " + op_label)

    # possibly bind the constant type
    if ((not tft_utils.FIX_CONST_TYPE) and tft_expr.isConstVar(opd0)):
        if (opd0.getGid() == tft_expr.PRESERVED_CONST_GID):
            CountGID(tft_expr.PRESERVED_CONST_GID, -1)
            opd0.gid = op_gid
        else:
            if (opd0.getGId() != op_gid):
                print("Warning: conflicting constant type...")

    if (not internal):
        CountGID(op_gid)
        CountCasting(opd0, op_gid)

    if (internal):
        assert (-1 == op_gid)
    else:
        assert (0 <= op_gid)
    if (op_gid not in EXTERNAL_GIDS):
        EXTERNAL_GIDS.append(op_gid)

    ret_expr = None
    if (op_label == "-"):
        ret_expr = BE("*", op_gid, FConst(-1.0), opd0)

    else:
        ret_expr = tft_expr.UnaryExpr(tft_expr.UnaryOp(op_gid, op_label),
                                      opd0.copy((not internal)))

        AppendCppInst(ret_expr)

    return ret_expr
Exemple #26
0
def FirstLevelAllocSolver (optimizers, error_forms = []): 
    assert(len(error_forms) > 0) 
    assert(("vrange" in optimizers.keys()) and ("alloc" in optimizers.keys())) 
    assert(optimizers["vrange"] in ALL_OPTIMIZERS) 
    assert(optimizers["alloc"] in ALL_OPTIMIZERS)
    assert(all([isinstance(error_forms[i], tft_error_form.ErrorForm) for i in range(0, len(error_forms))]))

    time_global_opt = time.time() 

    tft_utils.VerboseMessage("invoking global optimization to bound first derivatives...") 


    # ==== solve expressions' ranges ====
    if (VERBOSE): 
        print ("---- val. range opt. in FirstLevelAllocSolver [" + optimizers["vrange"] + "] ----")

   #  unbounded_range = False 

    for eform in error_forms: # len(error_forms) == 1 
        for et in eform.terms: 
            assert(isinstance(et, tft_error_form.ErrorTerm)) 
            value_max = None 
            value_min = None 

            # an optimization here: if the only epsilon for the ErrorTerm is 0.0, 
            # set arbitrary bounds for the Term's expression since it will contribute 0.0 error anyway 
            if (OPTIMIZATION_SKIP_PRECISE_OPTS and (len(et.epsilons) == 1) and (et.epsilons[0].value() == 0.0)): 
                et.expr.setBounds(tft_expr.ConstantExpr(0.0), tft_expr.ConstantExpr(0.0)) 
                et.absexpr().setBounds(tft_expr.ConstantExpr(0.0), tft_expr.ConstantExpr(0.0)) 

                if (VERBOSE): 
                    print ("ErrorTerm[" + str(et.index) + "] which has expression \n" + str(et.expr) + "\nhas an only epsilon 0.0. Therefore, set arbitrary expression bounds for it.") 
                    print ("--------------------------------------------------")

                continue 
            
            # find the obj_expr 
            obj_expr = et.absexpr() 
            obj_expr.setLB(tft_expr.ConstantExpr(Fraction(0, 1))) 

            # ---- go solve the expression's range ---- 
            if (optimizers["vrange"] in ["samplers"]): # parallel solvers 
                SAMPLERS.addTask(obj_expr) 

            else: # sequential solvers 
                if (VERBOSE): 
                    print (str(obj_expr) + "  IN...")

                if (obj_expr.hasUB()):
                    value_max = obj_expr.ub().value()
                        
                else:
                    value_max = FindExprBound(optimizers["vrange"], obj_expr, "max", eform.constraints)
                    if (value_max is None): 
                        return None 
                    obj_expr.setUB(tft_expr.ConstantExpr(value_max)) 
                assert(value_max is not None)
                if (VERBOSE): 
                    print ("    UB: " + str(float(value_max))) 

                if (obj_expr.hasLB()): 
                    value_min = obj_expr.lb().value() 
                else:
                    value_min = FindExprBound(optimizers["vrange"], obj_expr, "min", eform.constraints) 
                    if (value_min is None): 
                        return None 
                    obj_expr.setLB(tft_expr.ConstantExpr(value_min)) 
                assert(value_min is not None)
                if (VERBOSE): 
                    print ("    LB: " + str(float(value_min))) 

            if (VERBOSE): 
                print ("--------------------------------------------------")

        # ---- for paralllel solvers, solve the expressions' ranges now ---- 
        if (optimizers["vrange"] in ["samplers"]): 
            SAMPLERS.goSample(eform.constraints) 

            for et in eform.terms: 
                if (OPTIMIZATION_SKIP_PRECISE_OPTS and (len(et.epsilons) == 1) and (et.epsilons[0].value() == 0.0)): 
                    continue 

                obj_expr = et.absexpr() 

                lb, ub = SAMPLERS.getRange(obj_expr) 

                if ((lb is None) and (ub is None)): 
                    return None 

                assert((lb is not None) and (ub is not None)) 
                
                assert(lb <= ub) 
                obj_expr.setLB(tft_expr.ConstantExpr(lb)) 
                obj_expr.setUB(tft_expr.ConstantExpr(ub)) 

                if (VERBOSE): 
                    print (str(obj_expr) + "  IN  [", str(float(lb)) + ", " + str(float(ub)) + "]")

                if (VERBOSE): 
                    print ("--------------------------------------------------")

    tft_utils.TIME_GLOBAL_OPT = tft_utils.TIME_GLOBAL_OPT + (time.time() - time_global_opt)
    time_allocation           = time.time()

    # ==== dump the bounds of the first derivative expressions ====
#    for et in eform.terms:
#        print ("GID: " + str(et.gid) + " (context: " + str(et.context_gid) + " ) : [" + str(et.absexpr().lb().value()) + ", " + str(float(et.absexpr().ub().value())) + "]")

    tft_utils.VerboseMessage("allocating bit-widths...") 
        

    # ==== solve the allocation problem ====
    mprog_back = tft_mathprog_backend.MathProg_Backend()
    
    # ---- solve the alloc. problem by using gurobi ----
    alloc_solver = None 
    if   (optimizers["alloc"] == "gurobi"): 
        alloc_solver = tft_ask_gurobi.GurobiSolver()
    elif (optimizers["alloc"] == "glpk"):
        alloc_solver = tft_ask_glpk.GLPKSolver("__mathprog_glpk.mp")
    else:
        sys.exit("ERROR: unknown alloc. optimizer: " + optimizers["alloc"]) 

    # ---- solve ---- 
    for eform in error_forms: 
        # -- declare error variables and their range constraints --
        # declare ref. variables 
        for et in eform.terms: 
            assert(isinstance(et, tft_error_form.ErrorTerm)) 
            assert(not et.refVar().hasBounds())
            alloc_solver.addVar(et.refVar())

        for gid,epss in eform.gid2epsilons.items(): 
            for ei in range(0, len(epss)): 
                evar = tft_error_form.GroupErrorVar(gid, ei)
                alloc_solver.addVar(evar)
                    
            # add constraints for error variables
            if   (optimizers['alloc'] == 'gurobi'):
                alloc_solver.addConstraint("linear", "==", tft_expr.ConstantExpr(1), tft_error_form.GroupErrorVarSum(gid, epss))
            elif (optimizers['alloc'] == 'glpk'):
                alloc_solver.addConstraint('==',
                                           tft_expr.ConstantExpr(1),
                                           tft_error_form.GroupErrorVarSum(gid, epss))
            else:
                assert(False) 

            if (VERBOSE): 
                print ("Error Var Constraint: " + tft_error_form.GroupErrorVarSum(gid, epss).toCString() + " == 1")

        # add the optional type casting variables and constraints
        if (tft_utils.LINEAR_TYPE_CASTING_CONSTRAINTS):
            for gid,epss in eform.gid2epsilons.items():
                for cgid, cepss in eform.gid2epsilons.items():
                    for ei in range(0, len(epss)):
                        gvar = tft_error_form.GroupErrorVar(gid, ei)
                        for cei in range(0, len(cepss)):
                            cgvar = tft_error_form.GroupErrorVar(cgid, cei)
                            evar  = tft_error_form.TCastErrorVar(gid, ei, cgid, cei)
                            ubv   = IR.BE("+", -1, tft_expr.ConstantExpr(1), evar, True)
                            lbv   = IR.BE("+", -1, gvar, cgvar, True)
                            
                            alloc_solver.addVar(evar)
                            if   (optimizers['alloc'] == 'gurobi'):
                                alloc_solver.addConstraint("linear", ">=", gvar, evar)
                                alloc_solver.addConstraint("linear", ">=", cgvar, evar) 
                                alloc_solver.addConstraint("linear", ">=", ubv, lbv)
                                
                            elif (optimizers['alloc'] == 'glpk'):
                                alloc_solver.addConstraint('<=', evar, gvar)
                                alloc_solver.addConstraint('<=', evar, cgvar)
                                alloc_solver.addConstraint('<=', lbv, ubv)

                            else:
                                assert(False) 

        score_expr = eform.scoreExpr()
        for v in score_expr.vars():
            assert(tft_expr.isPseudoBooleanVar(v))
            alloc_solver.addVar(v) 

        if (VERBOSE): 
            print ("Score Expr: " + score_expr.toCString())

        # add constraints for ref. variables 
        ref_sum = None 
        expr_up_scaling = eform.scalingUpFactor() 
        assert(isinstance(expr_up_scaling, tft_expr.ConstantExpr)) 
            
        if (VERBOSE): 
            print ("Scaling up Expr: " + str(expr_up_scaling)) 

        for et in eform.terms: 
            # ref. variable 
            rvar       = et.refVar() 

            error_expr = et.errorExpr(eform.scalingUpFactor(), 
                                      eform.gid2epsilons, 
                                      eform.casting_map) 

            term_expr  = et.overApproxExpr(error_expr) 

            assert(all([pvar.isPreservedVar() for pvar in term_expr.vars()]))

            if   (optimizers['alloc'] == 'gurobi'):
                alloc_solver.addConstraint("quadratic", "==", rvar, term_expr)
            elif (optimizers['alloc'] == 'glpk'):
                alloc_solver.addConstraint('==', rvar, term_expr)
            else:
                assert(False)

            if (VERBOSE): 
                print ("Ref. Expr.: " + rvar.toCString() + " == " + term_expr.toCString()) 

            if (ref_sum is None): 
                ref_sum = rvar 
            else: 
                ref_sum = IR.BE("+", -1, ref_sum, rvar, True) 

        # add M2 to ref_sum 
        M2             = eform.M2 
        assert(isinstance(M2,              tft_expr.ConstantExpr)) 
        assert(isinstance(expr_up_scaling, tft_expr.ConstantExpr))
        expr_scaled_M2 = tft_expr.ConstantExpr(M2.value() * expr_up_scaling.value()) 
        # expr_scaled_M2 = IR.BE("*", -1, M2, expr_up_scaling, True) 
        ref_sum        = IR.BE("+", -1, ref_sum, expr_scaled_M2, True) 
            
        # write error form upper found 
        assert(isinstance(eform.upper_bound, tft_expr.ConstantExpr))
        assert(eform.upper_bound > tft_expr.ConstantExpr(0)) 
        assert(isinstance(ref_sum, tft_expr.Expr)) 
        expr_scaled_upper_bound = IR.BE("*", -1, eform.upper_bound, expr_up_scaling, True)
        if   (optimizers['alloc'] == 'gurobi'):
            alloc_solver.addConstraint("linear", "<=", ref_sum, expr_scaled_upper_bound)
        elif (optimizers['alloc'] == 'glpk'):
            alloc_solver.addConstraint('<=', ref_sum, expr_scaled_upper_bound)
        else:
            assert(False) 

        if (VERBOSE): 
            print ("expr_scaled_upper_bound: " + str(expr_scaled_upper_bound)) 
            
        if (VERBOSE): 
            print ("Reference Constraint: " + ref_sum.toCString() + " <= " + expr_scaled_upper_bound.toCString())  

        # write the constraints for equal bit-width groups 
        for gp in eform.eq_gids: 
            assert(len(gp) == 2) 
            gid_1 = gp[0]
            gid_2 = gp[1] 

            assert(gid_1 != gid_2) 
            assert(gid_1 in eform.gid2epsilons.keys()) 
            assert(gid_2 in eform.gid2epsilons.keys()) 
            assert(eform.gid2epsilons[gid_1] == eform.gid2epsilons[gid_2]) 

            len_epss = len(eform.gid2epsilons[gid_1]) 

            for j in range(0, len_epss): 
                ev_1 = tft_error_form.GroupErrorVar(gid_1, j) 
                ev_2 = tft_error_form.GroupErrorVar(gid_2, j) 

                if   (optimizers['alloc'] == 'gurobi'):
                    alloc_solver.addConstraint("linear", "==", ev_1, ev_2)
                elif (optimizers['alloc'] == 'glpk'):
                    alloc_solver.addConstraint('==', ev_1, ev_2) 

    # ---- generate the constraint for the number of castings ---- 
    if (tft_utils.N_MAX_CASTINGS is not None):
        assert(type(tft_utils.N_MAX_CASTINGS) is int)
        assert(tft_utils.N_MAX_CASTINGS >= 0) 
            
        cnum_expr = UnifiedCastingNumExpr(error_forms) 

        if (cnum_expr is not None): 
            assert(isinstance(cnum_expr, tft_expr.Expr)) 

            cnum_var = tft_expr.VariableExpr(tft_expr.CNUM_PREFIX+"_var", int, -1, False) 
            alloc_solver.addVar(cnum_var)
            if   (optimizers['alloc'] == 'gurobi'):
                alloc_solver.addConstraint("quadratic", "==", cnum_expr, cnum_var) 
                alloc_solver.addConstraint("linear", "<=", cnum_var, tft_expr.ConstantExpr(tft_utils.N_MAX_CASTINGS))
            elif (optimizers['alloc'] == 'glpk'):
                alloc_solver.addConstraint('==', cnum_expr, cnum_var)
                alloc_solver.addConstraint('<=', cnum_var, tft_expr.ConstantExpr(tft_utils.N_MAX_CASTINGS))
            else:
                assert(False) 

            if (VERBOSE): 
                print ("Casting Constraint: " + cnum_expr.toCString() + " <= " + str(tft_utils.N_MAX_CASTINGS)) 
        
    # ---- add optimization obj. ----
    score_sum = None 
    for eform in error_forms: 
        if (score_sum is None): 
            score_sum = eform.scoreExpr() 
        else: 
            assert(score_sum == eform.scoreExpr()) 
            # score_sum = IR.BE("+", -1, score_sum, eform.scoreExpr(), True)

    assert(tft_utils.OPT_METHOD in tft_utils.OPT_METHODS) 
    if   (tft_utils.OPT_METHOD == "max-benefit"):
        alloc_solver.setOptObj(score_sum, "max")
    elif (tft_utils.OPT_METHOD == "min-penalty"):
        alloc_solver.setOptObj(score_sum, "min")
    else:
        assert(False), "No such optimization method: " + str(tft_utils.OPT_METHOD)

    if (VERBOSE): 
        print ("Tuning Objective: ") 
        print (str(score_sum)) 

    # go opt. 
    levar_sum_max = alloc_solver.goOpt() 

    alloc = tft_alloc.Alloc()
    if (levar_sum_max is None): 
        return None 
    else: 
        alloc.score = float(levar_sum_max) 
        if (VERBOSE): 
            print ("==== solver: the optimal score is : " + str(float(levar_sum_max)))

    for eform in error_forms: 
        for gid,c in eform.gid_counts.items(): 
            evvs = [] 
            assert(gid in eform.gid2epsilons.keys()) 

            for ei in range(0, len(eform.gid2epsilons[gid])): 
                evv = alloc_solver.getOptVarValue(tft_error_form.GroupErrorVar(gid, ei))
                assert(evv is not None) 
                assert(isinstance(evv, Fraction))
                # adjust value 
                tolerance = 0.01 
                if (((1 - tolerance) <= evv) and (evv <= (1 + tolerance))): 
                    evv = Fraction(1, 1)
                if (((0 - tolerance) <= evv) and (evv <= (0 + tolerance))): 
                    evv = Fraction(0, 1) 

                evvs.append(evv) 

            if (sum(evvs) != Fraction(1, 1)): 
                print ("ERROR:[ " + str(gid) + "] : " + str(evvs) + " : " + str(sum(evvs))) 
            assert(sum(evvs) == Fraction(1, 1)) 
            assert(len(evvs) == len(eform.gid2epsilons[gid]))
            
            for ei in range(0, len(evvs)): 
                if (evvs[ei] == Fraction(1, 1)): 
                    eps = eform.gid2epsilons[gid][ei]
                    assert(isinstance(eps, tft_expr.ConstantExpr)) 
                    alloc[gid] = eps.value() 
                    break 

    tft_utils.TIME_ALLOCATION = tft_utils.TIME_ALLOCATION + (time.time() - time_allocation) 

    return alloc