def get_expr_coefficient(expr): if expr.op == baseoplib.OpType.INTEG: return 1.0, expr elif expr.op == baseoplib.OpType.MULT: c1, e1 = get_expr_coefficient(expr.arg(0)) c2, e2 = get_expr_coefficient(expr.arg(1)) if e1 is None and e2 is None: return c1 * c2, genoplib.Const(1.0) elif e1 is None: return c1 * c2, e2 elif e2 is None: return c1 * c2, e1 else: return c1 * c2, genoplib.Mult(e1, e2) elif expr.op == baseoplib.OpType.ADD: c1, _e1 = get_expr_coefficient(expr.arg(0)) c2, _e2 = get_expr_coefficient(expr.arg(1)) e1 = genoplib.Const(1) if _e1 is None else _e1 e2 = genoplib.Const(1) if _e2 is None else _e2 if c1 == c2: return c1, genoplib.Add(e1, e2) else: return c1, genoplib.Add(e1, genoplib.Mult(genoplib.Const(c2 / c1), e2)) elif expr.op == baseoplib.OpType.CONST: return expr.value, None elif expr.op == baseoplib.OpType.VAR: return 1.0, expr elif expr.op == baseoplib.OpType.EMIT: c1, _e1 = get_expr_coefficient(expr.arg(0)) return c1, genoplib.Emit(_e1, expr.loc) else: raise Exception("unhandled: %s" % expr)
def harmonize(baseline,deviations,modes): if harmonizable(baseline,deviations,modes): master_expr,gains_expr = \ do_harmonize(baseline, \ deviations, \ modes) return master_expr,gains_expr if baseline.op == baseoplib.OpType.MULT and \ match_op(baseoplib.OpType.MULT, deviations): master_expr1,gains_expr1 = \ do_harmonize(baseline.arg(0), \ get_term(deviations,0),modes) master_expr2,gains_expr2 = \ do_harmonize(baseline.arg(1), \ get_term(deviations,1),modes) gains_expr = gains_expr1 + gains_expr2 return genoplib.Mult(master_expr1,master_expr2),gains_expr elif baseline.op == baseoplib.OpType.INTEG and \ match_op(baseoplib.OpType.INTEG, deviations): master_expr1,gains_expr1 = \ do_harmonize(baseline.arg(0), \ get_term(deviations,0),modes) master_expr2,gains_expr2 = \ do_harmonize(baseline.arg(1), \ get_term(deviations,1),modes) gains_expr = gains_expr1 + gains_expr2 return genoplib.Integ(master_expr1,master_expr2),gains_expr elif match_op(baseline.op, deviations): raise NotImplementedError else: raise NotHarmonizableError("cannot harmonize baseline and deviations")
def canonicalize_integration_operation(expr): has_integ_op = any( map(lambda n: n.op == baseoplib.OpType.INTEG, expr.nodes())) if has_integ_op: if expr.op == baseoplib.OpType.MULT: c, e = get_expr_coefficient(expr) if (e.op == baseoplib.OpType.INTEG): return genoplib.Integ( genoplib.Mult(genoplib.Const(c), e.deriv), genoplib.Mult(genoplib.Const(c), e.init_cond)) elif expr.op == baseoplib.OpType.INTEG: return expr else: raise Exception("unhandled: %s" % expr) else: return expr
def apply_fuse_lut(goal,rule,unif): law_var = tablib.LawVar(rule.law,rule.ident,tablib.LawVar.APPLY) stmts = [] if isinstance(goal.variable, tablib.DSVar): var_name = goal.variable.var stmts.append(tablib.VADPSource(law_var,genoplib.Var(var_name))) else: stmts.append(tablib.VADPConn(law_var,goal.variable)) inpexpr = unif.get_by_name('a') coeff,base_expr = genoplib.factor_coefficient(inpexpr) assert(not base_expr is None) expr = unif.get_by_name('e') repl = {'T': genoplib.Mult(genoplib.Const(1.0/coeff), \ genoplib.Var("y")) \ } rule_var = vadplib.LawVar(rule.law,rule.ident) cfg = tablib.VADPConfig(rule_var,rule.mode) cfg.bind('e',expr.substitute(repl)) stmts.append(cfg) new_unif = unifylib.Unification() new_unif.set_by_name('a', base_expr) return new_unif,stmts
def mutate(self, p): def const_expr(p): len(p.vars()) == 0 or \ all(map(lambda n: "par" in n, p.vars())) par_idx = len(self.get_params(p)) if not const_expr(p) and \ all(map(lambda n: isinstance(n,genoplib.Var), p.nodes())): yield genoplib.Mult(lamboplib.SmoothStep(p.copy()), p.copy())
def root_functions(self): yield genoplib.Var('par0') for v in self.variables: yield genoplib.Mult(genoplib.Var('par0'), genoplib.Var(v)) for v in self.variables: rng = self.ranges[v] middle = np.mean(rng) scale = max(abs(max(rng)), abs(min(rng))) norm = lamboplib.Normalize(genoplib.Var(v), offset=middle, ampl=scale)
def simplify_flip(dev,vadp_stmts,rule): sink_stmt = None for stmt in vadp_stmts: # identify a connection or source flip is used if isinstance(stmt, tablib.VADPConn) and \ isinstance(stmt.source, tablib.LawVar) and \ stmt.source.law == rule.law: sink_stmt = stmt sink_var = stmt.sink target_var = stmt.source break elif isinstance(stmt,tablib.VADPSource) and \ isinstance(stmt.target, tablib.LawVar) and \ stmt.target.law == rule.law: sink_stmt = stmt sink_var = VirtualSourceVar(stmt.dsexpr.name) target_var = stmt.port break # is there is no statement with rule variables if sink_stmt is None: return False,vadp_stmts # identify sink statement connected to law variable new_stmt = [] replaced_stmts = [sink_stmt] for stmt in vadp_stmts: if isinstance(stmt,tablib.VADPSink) and \ isinstance(stmt.port, tablib.LawVar) and \ stmt.port.same_usage(target_var): new_stmt.append(tablib.VADPSink(sink_var, \ genoplib.Mult(genoplib.Const(-1), \ stmt.dsexpr) \ )) replaced_stmts.append(stmt) new_vadp = [] for stmt in vadp_stmts: if not stmt in replaced_stmts: new_vadp.append(stmt) return True,new_vadp
def do_harmonize(baseline,deviations,modes): coeff,expr = genoplib \ .factor_positive_coefficient(baseline) new_gains = [] new_modes = [] gains = {} gain_var_name = gain_var(GAIN_ID) for mode,deviation in zip(modes,deviations): coeff_dev,expr_dev = genoplib \ .factor_positive_coefficient(deviation) if lambdaoplib.equivalent(expr,expr_dev): gain_value = coeff_dev/coeff gains[mode] = gain_value else: raise NotHarmonizableError("expressions not equal") master_expr = genoplib.Mult(genoplib.Var(gain_var_name),expr) return master_expr,[(gain_var_name,gains)]
def canonicalize_call(expr): call_expr = None if expr.op == oplib.OpType.MULT: args_const, args_exprs = separate(oplib.OpType.CONST, get_assoc(oplib.OpType.MULT, expr)) const_val = 1.0 for arg in args_const: const_val *= arg.value if len(args_exprs) == 1 and \ args_exprs[0].op == oplib.OpType.CALL: call_expr = args_exprs[0] func_expr = call_expr.func new_impl = genoplib.Mult(genoplib.Const(const_val), \ func_expr.expr) return genoplib.Call(call_expr.values, \ lambdoplib.Func(func_expr.func_args, \ new_impl)) else: return None
def render_config_info(board,graph,cfg): blk = board.get_block(cfg.inst.block) st = [] st.append("\modes: %s" % (cfg.modes)) for data in cfg.stmts_of_type(adplib \ .ConfigStmtType \ .CONSTANT): st.append("%s=%.2f scf=%.2e" % (data.name, \ data.value, \ data.scf)) for data in cfg.stmts_of_type(adplib \ .ConfigStmtType \ .EXPR): inj_args = dict(map(lambda tup: (tup[0], \ genoplib.Mult(genoplib.Var(tup[0]), \ genoplib.Const(tup[1]))), \ data.injs.items())) subexpr = data.expr.substitute(inj_args) st.append("%s=%s injs=%s scfs=%s" \ % (data.name,data.expr,data.injs,data.scfs)) ident = "%s-config" % cfg.inst graph.node(ident, "%s" % "\n".join(st), \ shape="note", \ style="filled", \ fillcolor=Colors.LIGHTYELLOW) port_id = "%s:block" % (cfg.inst) graph.edge(ident,port_id, \ penwidth="2", \ style="dashed", \ arrowhead="tee", arrowtail="normal", \ color=Colors.ORANGE) return st
def compute_expression_fields(board,adp,cfg,compensate=True, debug=False): #print(cfg) blk = board.get_block(cfg.inst.block) if(len(blk.data) < 1): return data = list(filter(lambda d: d.type == blocklib.BlockDataType.EXPR, \ blk.data)) if(len(data) < 1): return assert(len(data) == 1) # only allowed to have one output. output_port = blk.outputs.singleton() calib_obj = llenums.CalibrateObjective(adp.metadata[adplib.ADPMetadata.Keys.RUNTIME_CALIB_OBJ]) rel = output_port.relation[cfg.mode] fn_call= util.singleton(filter(lambda n: n.op == oplib.OpType.CALL, rel.nodes())) fn_spec=fn_call.func fn_params = fn_call.values data_expr_field_name = util.singleton(fn_spec.expr.vars()) data_expr_field = cfg.get(data_expr_field_name) # build offset map repls = {} for input_port, func_arg in zip(fn_call.values,fn_spec.func_args): if compensate: assert(input_port.op == oplib.OpType.VAR) conn = util.singleton(adp.incoming_conns(blk.name, cfg.inst.loc, input_port.name)) src_block = board.get_block(conn.source_inst.block) src_cfg = adp.configs.get(conn.source_inst.block, conn.source_inst.loc) model = get_experimental_model(board, \ src_block, \ conn.source_inst.loc, \ src_cfg, \ calib_obj=calib_obj) gain,offset = get_compensation_parameters(model,init_cond=False) else: gain,offset = 1.0,0.0 inj = data_expr_field.injs[func_arg] repls[func_arg] = genoplib.Mult(genoplib.Const(inj), \ genoplib.Add( \ genoplib.Var(func_arg), \ genoplib.Const(-offset) )) if debug: print("inp-var %s inj=%f offset=%f" % (func_arg,inj,offset)) # compute model of output block if compensate: conn = util.singleton(adp.outgoing_conns(blk.name, cfg.inst.loc, output_port.name)) dest_block = board.get_block(conn.dest_inst.block) dest_cfg = adp.configs.get(conn.dest_inst.block, conn.dest_inst.loc) model = get_experimental_model(board, \ dest_block, \ dest_cfg.inst.loc, \ dest_cfg, \ calib_obj=calib_obj) gain,offset = get_compensation_parameters(model,False) else: gain,offset = 1.0,0.0 inj = data_expr_field.injs[data_expr_field.name] if debug: print("out-var %s inj=%f gain=%f offset=%f" % (data_expr_field.name, \ inj,gain,offset)) func_impl = genoplib.Mult(genoplib.Const(inj), \ data_expr_field.expr.substitute(repls)) if debug: print("func-expr: %s" % func_impl) rel_impl = genoplib.Add( \ rel.substitute({data_expr_field.name:func_impl}), \ genoplib.Const(-offset/gain) \ ) output_port = blk.outputs.singleton() input_port = blk.inputs.singleton() final_expr = rel_impl.concretize() if debug: print("rel-expr: %s" % rel_impl) print("--- building lookup table ---") print(final_expr) input_values = input_port.quantize[cfg.mode] \ .get_values(input_port \ .interval[cfg.mode]) cfg[data_expr_field.name].set_input(input_port,input_values) lut_outs = [] for val in input_values: out = final_expr.compute({input_port.name:val}) out = max(min(1.0-1.0/128.0,out),-1.0) cfg[data_expr_field.name].set_output({input_port.name:val},out) cfg[data_expr_field.name].concrete_expr = final_expr
def Div(a, b): return genop.Mult(a, Pow(b, genop.Const(-1)))
def Square(a): return genop.Mult(a, a)