bool SimpleSequenceModel::CreateModel()

in nn-samples/sequence/src/main/cpp/sequence_model.cpp [147:355]


bool SimpleSequenceModel::CreateModel() {
  int32_t status;

  // Create the ANeuralNetworksModel handle.
  status = ANeuralNetworksModel_create(&model_);
  if (status != ANEURALNETWORKS_NO_ERROR) {
    __android_log_print(ANDROID_LOG_ERROR,
                        LOG_TAG,
                        "ANeuralNetworksModel_create failed");
    return false;
  }

  uint32_t dimensions[] = {dimLength_, dimLength_};
  ANeuralNetworksOperandType float32TensorType{
      .type = ANEURALNETWORKS_TENSOR_FLOAT32,
      .dimensionCount = sizeof(dimensions) / sizeof(dimensions[0]),
      .dimensions = dimensions,
      .scale = 0.0f,
      .zeroPoint = 0,
  };
  ANeuralNetworksOperandType scalarInt32Type{
      .type = ANEURALNETWORKS_INT32,
      .dimensionCount = 0,
      .dimensions = nullptr,
      .scale = 0.0f,
      .zeroPoint = 0,
  };

  /**
   * Add operands and operations to construct the model.
   *
   * Operands are implicitly identified by the order in which they are added to the model,
   * starting from 0.
   *
   * These indexes are not returned by the model_addOperand call. The application must
   * manage these values. Here, we use opIdx to do the bookkeeping.
   */
  uint32_t opIdx = 0;

  // We first add the operand for the NONE activation function, and set its
  // value to ANEURALNETWORKS_FUSED_NONE.
  // This constant scalar operand will be used for both ADD and MUL.
  status = ANeuralNetworksModel_addOperand(model_, &scalarInt32Type);
  uint32_t fusedActivationFuncNone = opIdx++;
  if (status != ANEURALNETWORKS_NO_ERROR) {
    __android_log_print(ANDROID_LOG_ERROR,
                        LOG_TAG,
                        "ANeuralNetworksModel_addOperand failed for operand (%d)",
                        fusedActivationFuncNone);
    return false;
  }
  FuseCode fusedActivationCodeValue = ANEURALNETWORKS_FUSED_NONE;
  status = ANeuralNetworksModel_setOperandValue(model_, fusedActivationFuncNone,
                                                &fusedActivationCodeValue,
                                                sizeof(fusedActivationCodeValue));
  if (status != ANEURALNETWORKS_NO_ERROR) {
    __android_log_print(ANDROID_LOG_ERROR,
                        LOG_TAG,
                        "ANeuralNetworksModel_setOperandValue failed for operand (%d)",
                        fusedActivationFuncNone);
    return false;
  }

  // sumIn is one of the user provided input tensors to the trained model.
  // Its value is determined pre-execution.
  status = ANeuralNetworksModel_addOperand(model_, &float32TensorType);
  uint32_t sumIn = opIdx++;
  if (status != ANEURALNETWORKS_NO_ERROR) {
    __android_log_print(ANDROID_LOG_ERROR,
                        LOG_TAG,
                        "ANeuralNetworksModel_addOperand failed for operand (%d)",
                        sumIn);
    return false;
  }

  // stateIn is one of the user provided input tensors to the trained model.
  // Its value is determined pre-execution.
  status = ANeuralNetworksModel_addOperand(model_, &float32TensorType);
  uint32_t stateIn = opIdx++;
  if (status != ANEURALNETWORKS_NO_ERROR) {
    __android_log_print(ANDROID_LOG_ERROR,
                        LOG_TAG,
                        "ANeuralNetworksModel_addOperand failed for operand (%d)",
                        stateIn);
    return false;
  }

  // ratio is a constant tensor that was established during training.
  // We read these values from the corresponding ANeuralNetworksMemory object.
  status = ANeuralNetworksModel_addOperand(model_, &float32TensorType);
  uint32_t ratio = opIdx++;
  if (status != ANEURALNETWORKS_NO_ERROR) {
    __android_log_print(ANDROID_LOG_ERROR,
                        LOG_TAG,
                        "ANeuralNetworksModel_addOperand failed for operand (%d)",
                        ratio);
    return false;
  }
  status = ANeuralNetworksModel_setOperandValueFromMemory(model_,
                                                          ratio,
                                                          memoryRatio_,
                                                          0,
                                                          tensorSize_
                                                              * sizeof(float));
  if (status != ANEURALNETWORKS_NO_ERROR) {
    __android_log_print(
        ANDROID_LOG_ERROR,
        LOG_TAG,
        "ANeuralNetworksModel_setOperandValueFromMemory failed for operand (%d)",
        ratio);
    return false;
  }

  // sumOut is the output of the ADD operation.
  // Its value will be computed during execution.
  status = ANeuralNetworksModel_addOperand(model_, &float32TensorType);
  uint32_t sumOut = opIdx++;
  if (status != ANEURALNETWORKS_NO_ERROR) {
    __android_log_print(ANDROID_LOG_ERROR,
                        LOG_TAG,
                        "ANeuralNetworksModel_addOperand failed for operand (%d)",
                        sumOut);
    return false;
  }

  // stateOut is the output of the MUL operation.
  // Its value will be computed during execution.
  status = ANeuralNetworksModel_addOperand(model_, &float32TensorType);
  uint32_t stateOut = opIdx++;
  if (status != ANEURALNETWORKS_NO_ERROR) {
    __android_log_print(ANDROID_LOG_ERROR,
                        LOG_TAG,
                        "ANeuralNetworksModel_addOperand failed for operand (%d)",
                        stateOut);
    return false;
  }

  // Add the ADD operation.
  std::vector<uint32_t> addInputOperands = {
      sumIn,
      stateIn,
      fusedActivationFuncNone,
  };
  status = ANeuralNetworksModel_addOperation(model_,
                                             ANEURALNETWORKS_ADD,
                                             addInputOperands.size(),
                                             addInputOperands.data(),
                                             1,
                                             &sumOut);
  if (status != ANEURALNETWORKS_NO_ERROR) {
    __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
                        "ANeuralNetworksModel_addOperation failed for ADD");
    return false;
  }

  // Add the MUL operation.
  std::vector<uint32_t> mulInputOperands = {
      stateIn,
      ratio,
      fusedActivationFuncNone,
  };
  status = ANeuralNetworksModel_addOperation(model_,
                                             ANEURALNETWORKS_MUL,
                                             mulInputOperands.size(),
                                             mulInputOperands.data(),
                                             1,
                                             &stateOut);
  if (status != ANEURALNETWORKS_NO_ERROR) {
    __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
                        "ANeuralNetworksModel_addOperation failed for MUL");
    return false;
  }

  // Identify the input and output tensors to the model.
  // Inputs: {sumIn, stateIn}
  // Outputs: {sumOut, stateOut}
  std::vector<uint32_t> modelInputs = {
      sumIn,
      stateIn,
  };
  std::vector<uint32_t> modelOutputs = {
      sumOut,
      stateOut,
  };
  status =
      ANeuralNetworksModel_identifyInputsAndOutputs(model_,
                                                    modelInputs.size(),
                                                    modelInputs.data(),
                                                    modelOutputs.size(),
                                                    modelOutputs.data());
  if (status != ANEURALNETWORKS_NO_ERROR) {
    __android_log_print(ANDROID_LOG_ERROR,
                        LOG_TAG,
                        "ANeuralNetworksModel_identifyInputsAndOutputs failed");
    return false;
  }

  // Finish constructing the model.
  // The values of constant operands cannot be altered after
  // the finish function is called.
  status = ANeuralNetworksModel_finish(model_);
  if (status != ANEURALNETWORKS_NO_ERROR) {
    __android_log_print(ANDROID_LOG_ERROR,
                        LOG_TAG,
                        "ANeuralNetworksModel_finish failed");
    return false;
  }
  return true;
}