public Pair<Map<SDVariable, DifferentialFunction>, List<DifferentialFunction>> execBackwards() {

        final SameDiff outer = this;
        if (getFunction("grad") == null)
            defineFunction("grad", new SameDiffFunctionDefinition() {

                @Override
                public SDVariable[] define(SameDiff sameDiff, Map<String, INDArray> inputs, SDVariable[] variableInputs) {
                    //propagate graph to this samediff instance
                    //which will also contain the backward
                    if (SameDiff.this.debugMode) {
                        sameDiff.enableDebugMode();
                    }

                    outer.invokeGraphOn(sameDiff);

                    List<DifferentialFunction> allFunctions = new ArrayList<>(sameDiff.functionInstancesById.values());
                    if (allFunctions.isEmpty()) {
                        throw new ND4JIllegalStateException("No ops found!");
                    }


                    for (val func : allFunctions) {
                        if (func instanceof SDVariable) {
                            continue;
                        }

                        val args = func.args();
                        for (val arg : args)
                            arg.setSameDiff(sameDiff);
                        val outputs = func.outputVariables();
                        for (val output : outputs)
                            output.setSameDiff(sameDiff);
                        func.setSameDiff(sameDiff);
                    }

                    val initialOuts = allFunctions.get(allFunctions.size() - 1).outputVariables();
                    val firstBackward = initialOuts[0];

                    //start with scalar backprop
                    SDVariable initialGrad = sameDiff.var("one-var", Nd4j.scalar(1.0));
                    sameDiff.forwardVarForGrad.put(firstBackward.getVarName(), initialGrad);
                    sameDiff.gradients.put(firstBackward.getVarName(), initialGrad);

                    SDVariable gradientBackwardsMarker = sameDiff.gradientBackwardsMarker(firstBackward);

                    //reinitialize list with all declared variables
                    allFunctions = new ArrayList<DifferentialFunction>(sameDiff.functionInstancesById.values());
                    Collections.reverse(allFunctions);


                    for (DifferentialFunction action : allFunctions) {
                        if (action instanceof GradientBackwardsMarker) {
                            log.warn("Action op state is null for " + action.opName());
                            continue;
                        }

                        DifferentialFunction currFunction = action;
                        Preconditions.checkState(currFunction.getSameDiff() == sameDiff, "Wrong samediff instance found!");
                        //Preconditions.checkNotNull("Gradient for " + currFunction.opName() + " was null ! " + sameDiff.getVariableForVertexId(currFunction.getVertexId()).getGradient());
                        val args = currFunction.outputVariables();
                        for (val arg : args) {
                            if (arg.getSameDiff() != sameDiff) {
                                arg.setSameDiff(sameDiff);
                            }
                        }


                        List<SDVariable> grads = new ArrayList<>();
                        for (val varToGrad : args) {
                            val grad = varToGrad.gradient();
                            if (grad == null)
                                throw new ND4JIllegalStateException("No gradient found for " + varToGrad.getVarName());
                            grads.add(grad);
                        }

                        List<SDVariable> currFnGrads = currFunction.diff(grads);
                    }


                    if (sameDiff.isDebugMode()) {
                        //ensure all gradients are present for all variables
                        for (SDVariable sdVariable : variables()) {
                            sdVariable.gradient();
                        }
                    }


                    return new SDVariable[]{sameDiff.var("grad", new int[]{1, 1})};
                }
            });


        Pair<Map<SDVariable, DifferentialFunction>, List<DifferentialFunction>> forward = exec("grad");
        SameDiff grad = getFunction("grad");
        if (grad.isDebugMode()) {
            //ensure all gradients are present for all variables
            for (SDVariable sdVariable : grad.variables()) {
                sdVariable.gradient();
            }
        }

        return forward;
    }
public Pair < Map < SDVariable , DifferentialFunction > , List < DifferentialFunction > > execBackwards ( ) { final SameDiff outer = this ; if ( getFunction ( "grad" ) == null ) defineFunction ( "grad" , new SameDiffFunctionDefinition ( ) { @ Override public SDVariable [ ] define ( SameDiff sameDiff , Map < String , INDArray > inputs , SDVariable [ ] variableInputs ) { if ( SameDiff . this . debugMode ) { sameDiff . enableDebugMode ( ) ; } outer . invokeGraphOn ( sameDiff ) ; List < DifferentialFunction > allFunctions = new ArrayList < > ( sameDiff . functionInstancesById . values ( ) ) ; if ( allFunctions . isEmpty ( ) ) { throw new ND4JIllegalStateException ( "No ops found!" ) ; } for ( val func : allFunctions ) { if ( func instanceof SDVariable ) { continue ; } val args = func . args ( ) ; for ( val arg : args ) arg . setSameDiff ( sameDiff ) ; val outputs = func . outputVariables ( ) ; for ( val output : outputs ) output . setSameDiff ( sameDiff ) ; func . setSameDiff ( sameDiff ) ; } val initialOuts = allFunctions . get ( allFunctions . size ( ) - 1 ) . outputVariables ( ) ; val firstBackward = initialOuts [ 0 ] ; SDVariable initialGrad = sameDiff . var ( "one-var" , Nd4j . scalar ( 1.0 ) ) ; sameDiff . forwardVarForGrad . put ( firstBackward . getVarName ( ) , initialGrad ) ; sameDiff . gradients . put ( firstBackward . getVarName ( ) , initialGrad ) ; SDVariable gradientBackwardsMarker = sameDiff . gradientBackwardsMarker ( firstBackward ) ; allFunctions = new ArrayList < DifferentialFunction > ( sameDiff . functionInstancesById . values ( ) ) ; Collections . reverse ( allFunctions ) ; for ( DifferentialFunction action : allFunctions ) { if ( action instanceof GradientBackwardsMarker ) { log . warn ( "Action op state is null for " + action . opName ( ) ) ; continue ; } DifferentialFunction currFunction = action ; Preconditions . checkState ( currFunction . getSameDiff ( ) == sameDiff , "Wrong samediff instance found!" ) ; val args = currFunction . outputVariables ( ) ; for ( val arg : args ) { if ( arg . getSameDiff ( ) != sameDiff ) { arg . setSameDiff ( sameDiff ) ; } } List < SDVariable > grads = new ArrayList < > ( ) ; for ( val varToGrad : args ) { val grad = varToGrad . gradient ( ) ; if ( grad == null ) throw new ND4JIllegalStateException ( "No gradient found for " + varToGrad . getVarName ( ) ) ; grads . add ( grad ) ; } List < SDVariable > currFnGrads = currFunction . diff ( grads ) ; } if ( sameDiff . isDebugMode ( ) ) { for ( SDVariable sdVariable : variables ( ) ) { sdVariable . gradient ( ) ; } } return new SDVariable [ ] { sameDiff . var ( "grad" , new int [ ] { 1 , 1 } ) } ; } } ) ; Pair < Map < SDVariable , DifferentialFunction > , List < DifferentialFunction > > forward = exec ( "grad" ) ; SameDiff grad = getFunction ( "grad" ) ; if ( grad . isDebugMode ( ) ) { for ( SDVariable sdVariable : grad . variables ( ) ) { sdVariable . gradient ( ) ; } } return forward ; }
Builds a backwards graph
and executes the operations
on that graph.

@return