def zeros_for(self, mimic_sym, right=False): """Create a constant that when [left, right] multiplied onto mimic_sym, gives zeros. If `right`, it is as though the constant were multiplied on the *right* If `left`, it is as though the constant were multiplied on the *left* """ props = self.get_properties(mimic_sym) if props['type'] == 'matrix': dim = props['dim'] if right: return op_defs.Constant(op_defs.create_matrix((dim[1], dim[1])), 'zero') else: return op_defs.Constant(op_defs.create_matrix((dim[0], dim[0])), 'zero') else: return self.constant_like(mimic_sym, 'zero')
def zeros_between(self, from_sym, to_sym): self._needs_vector(from_sym) self._needs_vector(to_sym) return op_defs.Constant( op_defs.create_matrix( self.cross_dim(from_sym, to_sym) ) )
def forward_mode_differentiate(self, wrt): """Differentiate the graph with respect to wrt "wrt" -> "w.r.t" -> "with respect to" in case you are a goober """ self._needs_input(wrt) inv_adj = self._inverse_adjacency() diffed = {} for inp in get_inputs(self): diffed[inp] = self.zeros_for(inp, right=False) diffed[wrt] = self.identity_for(wrt, right=False) to_diff = deque() to_diff.extend(inv_adj[wrt]) while(len(to_diff)): td = to_diff.popleft() if td in diffed.keys(): continue op = self._adj[td] Log.success('To diff', td) if op is not None: args = get_args(op) arg_types = self._types(args) df = self._d_table[get_opname(op)][arg_types] df_dx_summands = [] for n, df_darg in enumerate(df): df_du_sexpr = df_darg['generate'](*args) df_du_sym = s_expressions.apply_s_expression(self, df_du_sexpr, self.anon()) if self.is_constant(args[n]): du_dx = op_defs.Constant(self.get_properties(args[n]), 'zero') else: Log.warn("d-d", args[n], self.get_properties(args[n])) du_dx = diffed[args[n]] Log.warn(df_du_sym, du_dx) Log.warn(self.get_properties(df_du_sym), self.get_properties(du_dx)) df_dx_summands.append(self._anony_call('mul', df_du_sym, du_dx)) if td in self._outputs: df_dx_sym = 'd{}_d{}'.format(td, wrt) else: df_dx_sym = self.anon() if df_dx_sym not in self._adj: for sm in df_dx_summands: Log.warn(" sm:", sm, self.get_properties(sm)) total = self.reduce_binary_op('add', df_dx_sym, df_dx_summands) else: total = df_dx_sym diffed[td] = total
def scalar_difftest(): gr = OpGraph('DifferentationGraph') gr.scalar('x1') gr.scalar('x2') a = gr.mul(gr.anon(), 'x1', op_defs.Constant(op_defs.create_scalar(), 'I')) # a = gr.mul(gr.anon(), 'x1', 'x1') b = gr.mul(gr.anon(), a, 'x1') gr.add('c', b, 'x2') gr.output('c') gr.forward_mode_differentiate('x1') print '--------\n\n' print gr.arrows(skip_uniques=True) gr.simplify() print '\n' print gr.arrows(skip_uniques=True) gr.simplify() print gr.arrows(skip_uniques=True)
def constant_scalar(self, name, value): props = op_defs.create_scalar() constant = op_defs.Constant(props, value) self._adj[name] = self._op('I', constant) self._properties[name] = props return name
def constant_vector(self, name, dim, value): props = op_defs.create_vector(dim) constant = op_defs.Constant(props, value) self._adj[name] = self._op('I', constant) self._properties[name] = props return name
def constant_like(self, mimic_sym, value): return op_defs.Constant(self.get_properties(mimic_sym), value)