<s> from __future__ import absolute_import <EOL> import numpy as np <EOL> from autograd . core import ( Node , FloatNode , primitive , cast , <EOL> differentiable_ops , nondifferentiable_ops , getval ) <EOL> from . import numpy_wrapper as anp <EOL> from . use_gpu_numpy import use_gpu_numpy <EOL> @ primitive <EOL> def take ( A , idx ) : <EOL> return A [ idx ] <EOL> def make_grad_take ( ans , A , idx ) : <EOL> return lambda g : untake ( g , idx , A ) <EOL> take . defgrad ( make_grad_take ) <EOL> @ primitive <EOL> def untake ( x , idx , template ) : <EOL> return array_dtype_mappings [ template . dtype ] . new_sparse_array ( template , idx , x ) <EOL> untake . defgrad ( lambda ans , x , idx , template : lambda g : take ( g , idx ) ) <EOL> untake . defgrad_is_zero ( argnums = ( <NUM_LIT:1> , <NUM_LIT:2> ) ) <EOL> Node . __array_priority__ = <NUM_LIT> <EOL> class ArrayNode ( Node ) : <EOL> __slots__ = [ ] <EOL> __getitem__ = take <EOL> __array_priority__ = <NUM_LIT> <EOL> shape = property ( lambda self : self . value . shape ) <EOL> ndim = property ( lambda self : self . value . ndim ) <EOL> size = property ( lambda self : self . value . size ) <EOL> dtype = property ( lambda self : self . value . dtype ) <EOL> T = property ( lambda self : anp . transpose ( self ) ) <EOL> def __len__ ( self ) : <EOL> return len ( self . value ) <EOL> @ staticmethod <EOL> def zeros_like ( value ) : <EOL> return anp . zeros ( value . shape ) <EOL> @ staticmethod <EOL> def sum_outgrads ( outgrads ) : <EOL> if len ( outgrads ) is <NUM_LIT:1> and not isinstance ( getval ( outgrads [ <NUM_LIT:0> ] ) , SparseArray ) : <EOL> return outgrads [ <NUM_LIT:0> ] <EOL> else : <EOL> return primitive_sum_arrays ( * outgrads ) <EOL> @ staticmethod <EOL> def cast ( value , example ) : <EOL> result = arraycast ( value ) <EOL> if result . shape != example . shape : <EOL> result = result . reshape ( example . shape ) <EOL> return result <EOL> @ staticmethod <EOL> def new_sparse_array ( template , idx , x ) : <EOL> return SparseArray ( template , idx , x ) <EOL> def __neg__ ( self ) : return anp . negative ( self ) <EOL> def __add__ ( self , other ) : return anp . add ( self , other ) <EOL> def __sub__ ( self , other ) : return anp . subtract ( self , other ) <EOL> def __mul__ ( self , other ) : return anp . multiply ( self , other ) <EOL> def __pow__ ( self , other ) : return anp . power ( self , other ) <EOL> def __div__ ( self , other ) : return anp . divide ( self , other ) <EOL> def __mod__ ( self , other ) : return anp . mod ( self , other ) <EOL> def __truediv__ ( self , other ) : return anp . true_divide ( self , other ) <EOL> def __radd__ ( self , other ) : return anp . add ( other , self ) <EOL> def __rsub__ ( self , other ) : return anp . subtract ( other , self ) <EOL> def __rmul__ ( self , other ) : return anp . multiply ( other , self ) <EOL> def __rpow__ ( self , other ) : return anp . power ( other , self ) <EOL> def __rdiv__ ( self , other ) : return anp . divide ( other , self ) <EOL> def __rmod__ ( self , other ) : return anp . mod ( other , self ) <EOL> def __rtruediv__ ( self , other ) : return anp . true_divide ( other , self ) <EOL> def __eq__ ( self , other ) : return anp . equal ( self , other ) <EOL> def __ne__ ( self , other ) : return anp . not_equal ( self , other ) <EOL> def __gt__ ( self , other ) : return anp . greater ( self , other ) <EOL> def __ge__ ( self , other ) : return anp . greater_equal ( self , other ) <EOL> def __lt__ ( self , other ) : return anp . less ( self , other ) <EOL> def __le__ ( self , other ) : return anp . less_equal ( self , other ) <EOL> def new_array_node ( value , tapes ) : <EOL> try : <EOL> return array_dtype_mappings [ value . dtype ] ( value , tapes ) <EOL> except KeyError : <EOL> raise TypeError ( "<STR_LIT>" . format ( value . dtype ) ) <EOL> Node . type_mappings [ anp . ndarray ] = new_array_node <EOL> array_dtype_mappings = { } <EOL> for float_type in [ anp . float64 , anp . float32 , anp . float16 ] : <EOL> array_dtype_mappings [ anp . dtype ( float_type ) ] = ArrayNode <EOL> Node . type_mappings [ float_type ] = FloatNode <EOL> if use_gpu_numpy ( ) : <EOL> @ primitive <EOL> def arraycast ( val ) : <EOL> if isinstance ( val , float ) : <EOL> return anp . array ( val ) <EOL> elif anp . is_garray ( val ) : <EOL> return anp . array ( val , dtype = anp . float64 ) <EOL> elif anp . iscomplexobj ( val ) : <EOL> return anp . array ( anp . real ( val ) ) <EOL> else : <EOL> raise TypeError ( "<STR_LIT>" . format ( type ( val ) ) ) <EOL> else : <EOL> @ primitive <EOL> def arraycast ( val ) : <EOL> if isinstance ( val , float ) : <EOL> return anp . array ( val ) <EOL> elif anp . iscomplexobj ( val ) : <EOL> return anp . array ( anp . real ( val ) ) <EOL> else : <EOL> raise TypeError ( "<STR_LIT>" . format ( type ( val ) ) ) <EOL> arraycast . defgrad ( lambda ans , val : lambda g : g ) <EOL> @ primitive <EOL> def primitive_sum_arrays ( * arrays ) : <EOL> new_array = type ( new_array_node ( arrays [ <NUM_LIT:0> ] , [ ] ) ) . zeros_like ( arrays [ <NUM_LIT:0> ] ) <EOL> for array in arrays : <EOL> if isinstance ( array , SparseArray ) : <EOL> np . add . at ( new_array , array . idx , array . val ) <EOL> else : <EOL> new_array += array <EOL> return new_array <EOL> primitive_sum_arrays . gradmaker = lambda * args : lambda g : g <EOL> nondiff_methods = [ '<STR_LIT:all>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] <EOL> diff_methods = [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] <EOL> for method_name in nondiff_methods + diff_methods : <EOL> setattr ( ArrayNode , method_name , anp . __dict__ [ method_name ] ) <EOL> setattr ( ArrayNode , '<STR_LIT>' , anp . __dict__ [ '<STR_LIT>' ] ) <EOL> for method_name in differentiable_ops + nondifferentiable_ops + [ '<STR_LIT>' , '<STR_LIT>' ] : <EOL> setattr ( FloatNode , method_name , ArrayNode . __dict__ [ method_name ] ) <EOL> class SparseArray ( object ) : <EOL> __array_priority__ = <NUM_LIT> <EOL> def __init__ ( self , template , idx , val ) : <EOL> self . shape = template . shape <EOL> self . idx = idx <EOL> self . val = val <EOL> self . dtype = template . dtype <EOL> Node . type_mappings [ SparseArray ] = ArrayNode </s>
