/******************************************************************************
* Copyright (c) Intel Corporation - All rights reserved.                      *
* This file is part of the LIBXSMM library.                                   *
*                                                                             *
* For information on the license, see the LICENSE file.                       *
* Further information: https://github.com/hfp/libxsmm/                        *
* SPDX-License-Identifier: BSD-3-Clause                                       *
******************************************************************************/
/* Sasikanth Avancha, Dhiraj Kalamkar (Intel Corp.)
******************************************************************************/

syntax = "proto2";

package gxm;

enum Mode {
   TRAIN = 0;
   VAL = 1;
   TEST = 2;
}

enum DataType {
  FLOAT = 0;
  INT = 1;
  BF16 = 2;
  FP16 = 3;
  INT16 = 4;
  INT8 = 5; 
}

enum ComputeEngine {
  LOOP = 0;
  XSMM = 1;
}

enum AlgorithmType {
  AUTO = 0;
  DIRECT = 1;
}

//Machine parameters
message MachineParameter {
  optional int32 num_machine_groups = 1 [default = 1];
  optional int32 num_machines = 2 [default = 1];
  optional int32 num_cores_per_machine = 3;
  optional int32 num_threads_per_core = 4 [default = 1];
  optional int32 SIMD_width = 5;
  optional uint32 max_endpoints = 6 [default = 8];
  optional uint32 io_endpoints = 7 [default = 2];
}

// Tensor shape.
message TensorShape {
  repeated int32 dim = 1 [packed = true];
}

message TensorProto {
  repeated float data = 1 [packed = true];
}

message TensorProtoVector {
  repeated TensorProto tensors = 1;
}

message Datum {
  optional int32 channels = 1;
  optional int32 height = 2;
  optional int32 width = 3;
  // the actual image data, in bytes
  optional bytes data = 4;
  optional int32 label = 5;
  // Optionally, the datum could also hold float data.
  repeated float float_data = 6;
  // If true data contains an encoded image that need to be decoded
  optional bool encoded = 7 [default = false];
}

message FillerParameter {
  // The filler type.
  optional string type = 1 [default = 'constant'];
  optional float value = 2 [default = 0]; // the value in constant filler
  optional float min = 3 [default = 0]; // the min value in uniform filler
  optional float max = 4 [default = 1]; // the max value in uniform filler
  optional float mean = 5 [default = 0]; // the mean value in Gaussian filler
  optional float std = 6 [default = 1]; // the std value in Gaussian filler
  // The expected number of non-zero output weights for a given input in
  // Gaussian filler -- the default -1 means don't perform sparsification.
  optional int32 sparse = 7 [default = -1];
  // Normalize the filler variance by fan_in, fan_out, or their average.
  // Applies to 'xavier' and 'msra' fillers.
  enum VarianceNorm {
    FAN_IN = 0;
    FAN_OUT = 1;
    AVERAGE = 2;
  }
  optional VarianceNorm variance_norm = 8 [default = FAN_IN];
}

message NTGParameter {
  optional string name = 1; // consider giving the network a name
  optional string net = 2; // Proto file for net
  optional NTGParameter test_net_param = 3; // Inline test net params
  optional NetState state = 4; // State of NTG

  // The nodes that make up the graph.  Each of their configurations, including
  // connectivity and behavior, is specified as a NodeParameter.
  repeated NodeParameter node = 100;  // ID 100 so nodes are printed last.
}

// NOTE
// Update the next available ID when you add a new SolverParameter field.
//
// SolverParameter next available ID: 24 (last added: warmup_lr)
message SolverParameter {
  // The number of epochs for each net.
  optional int32 max_epochs = 1;

  // The number of epochs to test after.
  optional int32 test_epoch = 2 [default = 1];
  repeated int32 lr_change_epochs = 3; // epochs at which learning rate changes
  repeated float learning_rate = 4; // The base learning rate
  repeated float warmup_lr = 23; // The base learning rate
  repeated float momentum = 5; // The momentum value.
  repeated float weight_decay = 6; // The weight decay.

  // The learning rate decay policy. The currently implemented learning rate
  // policies are as follows:
  //    - fixed: always return base_lr.
  //    - pcl_dnn: fixed sequence of learning rates
  //    - step: return base_lr * gamma ^ (floor(iter / step))
  //    - exp: return base_lr * gamma ^ iter
  //    - inv: return base_lr * (1 + gamma * iter) ^ (- power)
  //    - multistep: similar to step but it allows non uniform steps defined by
  //      stepvalue
  //    - poly: the effective learning rate follows a polynomial decay, to be
  //      zero by the max_iter. return base_lr (1 - iter/max_iter) ^ (power)
  //    - sigmoid: the effective learning rate follows a sigmod decay
  //      return base_lr ( 1/(1 + exp(-gamma * (iter - stepsize))))
  //
  // where base_lr, max_iter, gamma, step, stepvalue and power are defined
  // in the solver parameter protocol buffer, and iter is the current iteration.
  optional string lr_policy = 13;
  optional float gamma = 14; // The parameter to compute the learning rate.
  optional float power = 15; // The parameter to compute the learning rate.
  // the stepsize for learning rate policy "step"
  optional int32 stepsize = 16;
  optional int32 max_iter = 17;
  repeated int32 step_values = 19;
  optional bool load_checkpoint = 7 [default = false]; // The snapshot interval
  optional string checkpoint_dir = 8; 
  optional string checkpoint_format = 18;
  
  // type of the solver
  optional string type = 9 [default = "SGD"];

  // numerical stability for RMSProp, AdaGrad and AdaDelta and Adam
  optional float delta = 10 [default = 1e-8];
  // parameters for the Adam solver
  optional float momentum2 = 11 [default = 0.999];

  // RMSProp decay value
  // MeanSquare(t) = rms_decay*MeanSquare(t-1) + (1-rms_decay)*SquareGradient(t)
  optional float rms_decay = 12;
  optional int32 warmup_epochs = 20 [default = 5];
  optional bool global = 21 [default = false];
  optional DataType data_type = 22 [default = FLOAT];
}

// A message that stores the solver snapshots
message SolverState {
  optional int32 epoch = 1; // The current iteration
  optional string learned_net = 2; // The file that stores the learned net.
  repeated TensorProto history = 3; // The history for sgd solvers
  optional int32 current_step = 4 [default = 0]; // The current step for learning rate
}
 
message NetState {
  optional Mode mode = 1 [default = TRAIN];
  optional int32 level = 2 [default = 0];
  repeated string stage = 3;
}

message NetStateRule {
  // Set mode to require the NetState have a particular mode (TRAIN or TEST)
  // to meet this rule.
  optional Mode mode = 1;

  // Set the minimum and/or maximum levels in which the node should be used.
  // Leave undefined to meet the rule regardless of level.
  optional int32 min_level = 2;
  optional int32 max_level = 3;

  // Customizable sets of stages to include or exclude.
  // The net must have ALL of the specified stages and NONE of the specified
  // "not_stage"s to meet the rule.
  // (Use multiple NetStateRules to specify conjunctions of stages.)
  repeated string stage = 4;
  repeated string not_stage = 5;
}

// Specifies training parameters (multipliers on global learning constants,
// and the name and other settings used for weight sharing).
message ParamSpec {
  // The names of the parameter blobs -- useful for sharing parameters among
  // layers, but never required otherwise.  To share a parameter between two
  // layers, give it a (non-empty) name.
  optional string name = 1;

  // Whether to require shared weights to have the same shape, or just the same
  // count -- defaults to STRICT if unspecified.
  optional DimCheckMode share_mode = 2;
  enum DimCheckMode {
    // STRICT (default) requires that num, channels, height, width each match.
    STRICT = 0;
    // PERMISSIVE requires only the count (num*channels*height*width) to match.
    PERMISSIVE = 1;
  }

  // The multiplier on the global learning rate for this parameter.
  optional float lr_mult = 3 [default = 1.0];

  // The multiplier on the global weight decay for this parameter.
  optional float decay_mult = 4 [default = 1.0];
}

//
// NodeParameter 
message NodeParameter {
  optional string name = 1; // the node name
  optional string type = 2; // the node type
  repeated string bottom = 3; // the name of each bottom tensor
  repeated string top = 4; // the name of each top tensor

  // The train / test mode for computation.
  optional Mode mode = 5;

  // The amount of weight to assign each top blob in the objective.
  // Each node assigns a default value, usually of either 0 or 1,
  // to each top blob.
  repeated float loss_weight = 6;

  // The tensors containing the numeric parameters of the node.
  repeated TensorProto tensors = 7;

  // Specifies on which bottoms the backpropagation should be skipped.
  // The size must be either 0 or equal to the number of bottoms.
  optional bool propagate_down = 8 [default = true];

  // Rules controlling whether and when a node is included in the network,
  // based on the current NetState.  You may specify a non-zero number of rules
  // to include OR exclude, but not both.  If no include or exclude rules are
  // specified, the node is always included.  If the current NetState meets
  // ANY (i.e., one or more) of the specified rules, the node is
  // included/excluded.
  repeated NetStateRule include = 9;
  repeated NetStateRule exclude = 10;

  // Allow recursive definition of a Node
  optional NodeParameter node = 11;

  // Specifies training parameters (multipliers on global learning constants,
  // and the name and other settings used for weight sharing).
  repeated ParamSpec param = 12;

  // Parameters for data pre-processing.
  
  // Parameters shared by loss nodes.
  optional LossParameter loss_param = 101;

  // Node type-specific parameters.
  //
  // Note: certain nodess may have more than one computational engine
  // for their implementation. These nodess include an Engine type and
  // engine parameter for selecting the implementation. Last ID = 123
  // The default for the engine is set by the ENGINE switch at compile-time.
  optional AccuracyParameter accuracy_param = 102;
  optional ArgMaxParameter argmax_param = 103;
  optional ConcatParameter concat_param = 104;
  optional ConvolutionParameter convolution_param = 105;
  optional DataParameter data_param = 106;
  optional DropoutParameter dropout_param = 107;
  optional DummyDataParameter dummy_data_param = 108;
  optional EltwiseParameter eltwise_param = 109;
  optional EmbedParameter embed_param = 110;
  optional FullyConnectedParameter fc_param = 111;
  optional FusedBNormParameter fused_bnorm_param = 112;
  optional FusedConvBNParameter fused_conv_bn_param = 123;
  optional LogParameter log_param = 113;
  optional PoolingParameter pooling_param = 114;
  optional PReLUParameter prelu_param = 115;
  optional ReLUParameter relu_param = 116;
  optional SoftmaxParameter softmax_param = 117;
  optional SPPParameter spp_param = 118;
  optional SplitParameter split_param = 119;
  optional TanHParameter tanh_param = 120;
  optional ThresholdParameter threshold_param = 121;
  optional WindowDataParameter window_data_param = 122;
}

// Messages that store parameters used by individual nodes types follow, in
// alphabetical order.

message AccuracyParameter {
  // When computing accuracy, count as correct by comparing the true label to
  // the top k scoring classes.  By default, only compare to the top scoring
  // class (i.e. argmax).
  optional uint32 top_k = 1 [default = 1];

  // The "label" axis of the prediction blob, whose argmax corresponds to the
  // predicted label -- may be negative to index from the end (e.g., -1 for the
  // last axis).  For example, if axis == 1 and the predictions are
  // (N x C x H x W), the label blob is expected to contain N*H*W ground truth
  // labels with integer values in {0, 1, ..., C-1}.
  optional int32 axis = 2 [default = 1];

  // If specified, ignore instances with the given label.
  optional int32 ignore_label = 3;
}

message ArgMaxParameter {
  // If true produce pairs (argmax, maxval)
  optional bool out_max_val = 1 [default = false];
  optional uint32 top_k = 2 [default = 1];
  // The axis along which to maximise -- may be negative to index from the
  // end (e.g., -1 for the last axis).
  // By default ArgMaxnodes maximizes over the flattened trailing dimensions
  // for each index of the first / num dimension.
  optional int32 axis = 3;
}

message ConcatParameter {
  // The axis along which to concatenate -- may be negative to index from the
  // end (e.g., -1 for the last axis).  Other axes must have the
  // same dimension for all the bottom blobs.
  // By default, Concatnodes concatenates blobs along the "channels" axis (1).
  optional int32 axis = 1 [default = 1];
  optional ComputeEngine engine = 2 [default = XSMM];
  optional AlgorithmType algotype = 3 [default = DIRECT];
  optional DataType data_type = 4 [default = FLOAT];
}

message ConvolutionParameter {
  optional uint32 num_output = 1; // The number of outputs for the nodes
  optional bool bias_term = 2 [default = true]; // whether to have bias terms
  // Pad, kernel size, and stride are all given as a single value for equal
  // dimensions in all spatial dimensions, or once per spatial dimension.
  repeated uint32 pad = 3; // The padding size; defaults to 0
  repeated uint32 opad = 4; // The padding size; defaults to 0
  repeated uint32 kernel_size = 5; // The kernel size
  optional uint32 group = 6 [default = 1]; // The group size for group conv
  repeated uint32 stride = 7; // The stride; defaults to 1
  optional FillerParameter weight_filler = 8; // The filler for the weight
  optional FillerParameter bias_filler = 9; // The filler for the bias
  // Factor used to dilate the kernel, (implicitly) zero-filling the resulting
  // holes. (Kernel dilation is sometimes referred to by its use in the
  // algorithme à trous from Holschneider et al. 1987.)
  repeated uint32 dilation = 10; // The dilation; defaults to 1

  // For 2D convolution only, the *_h and *_w versions may also be used to
  // specify both spatial dimensions.
  optional uint32 pad_h = 11 [default = 0]; // The padding height (2D only)
  optional uint32 pad_w = 12 [default = 0]; // The padding width (2D only)
  optional uint32 pad_d = 13 [default = 0]; // The padding width (2D only)
  optional uint32 kernel_h = 14; // The kernel height (2D only)
  optional uint32 kernel_w = 15; // The kernel width (2D only)
  optional uint32 kernel_d = 16; // The kernel width (2D only)
  optional uint32 stride_h = 17 [default = 1]; // The stride height (2D only)
  optional uint32 stride_w = 18 [default = 1]; // The stride width (2D only)
  optional uint32 stride_d = 19 [default = 1]; // The stride width (2D only)
  optional uint32 opad_h = 20 [default = 0]; // The padding height (2D only)
  optional uint32 opad_w = 21 [default = 0]; // The padding width (2D only)
  optional uint32 opad_d = 22 [default = 0]; // The padding width (2D only)
  optional uint32 ndims = 23 [default = 2];

  optional ComputeEngine engine = 24 [default = XSMM];
  optional AlgorithmType algotype = 25 [default = DIRECT];

  optional bool fusedReLU = 26 [default = false];
  optional bool bwd_relu = 27 [default = false];
  optional bool compute_stats = 28 [default = false];
  optional bool physical_padding = 29 [default = false];
  optional DataType data_type = 30 [default = FLOAT];
}

message DataParameter {
  enum DB {
    FLATFILE = 0;
    LEVELDB = 1;
    LMDB = 2;
  }
  // Specify the data source.
  optional string train_source = 1;
  optional string test_source = 15;
  // Specify the batch size.
  optional uint32 batch_size = 2;
  optional DB backend = 3 [default = FLATFILE];
  // Specify the lookahead i.e., #minibatches to prefetch.
  optional uint32 lookahead = 4 [default = 2];
  optional string root_folder = 5 [default = ""];
  optional uint32 num_train_files = 6;
  optional uint32 num_test_files = 7;
  optional string train_data_info = 8;
  optional string test_data_info = 9;
  optional ImageTransformParameter image_xform_param = 10;
//  optional SpeechTransformParameter speech_xform_param = 11;
//  optional TextTransformParameter text_xform_param = 12;
  optional DataType data_type = 13 [default = FLOAT];
  optional DataType label_data_type = 14 [default = INT];
  optional bool split_db = 16 [default = false];
  optional string train_list = 17;
  optional string test_list = 18;
  optional int32 numsplits = 19;
  optional bool shuffle = 20 [default = false];
  optional ComputeEngine engine = 21 [default = XSMM];
}

message DropoutParameter {
  optional float dropout_ratio = 1 [default = 0.5]; // dropout ratio
  optional ComputeEngine engine = 2 [default = XSMM];
  optional AlgorithmType algotype = 3 [default = DIRECT];
  optional DataType data_type = 4 [default = FLOAT];
}

message DummyDataParameter {
  repeated FillerParameter data_filler = 1;
  repeated TensorShape shape = 2;
  optional int32 pad_h = 3 [default = 0];
  optional int32 pad_w = 4 [default = 0];
  optional ComputeEngine engine = 5 [default = XSMM];
  optional DataType data_type = 6 [default = FLOAT];
}

message EltwiseParameter {
  enum EltwiseOp {
    ELSUM = 0;
    ELPROD = 1;
    ELMAX = 2;
  }
  optional EltwiseOp op = 1 [default = ELSUM]; // element-wise operation, default is SUM
  optional float coeff = 2; // blob-wise coefficient for SUM operation

  // Whether to use an asymptotically slower (for >2 inputs) but stabler method
  // of computing the gradient for the PROD operation. (No effect for SUM op.)
  optional bool stable_prod_grad = 3 [default = true];
  optional ComputeEngine engine = 4 [default = XSMM];
  optional AlgorithmType algotype = 5 [default = DIRECT];
  optional DataType data_type = 6 [default = FLOAT];
}

// Message that stores parameters used by Embednodes
message EmbedParameter {
  optional uint32 num_output = 1; // The number of outputs for the nodes
  // The input is given as integers to be interpreted as one-hot
  // vector indices with dimension num_input.  Hence num_input should be
  // 1 greater than the maximum possible input value.
  optional uint32 input_dim = 2;

  optional bool bias_term = 3 [default = true]; // Whether to use a bias term
  optional FillerParameter weight_filler = 4; // The filler for the weight
  optional FillerParameter bias_filler = 5; // The filler for the bias

}

message FullyConnectedParameter {
  optional uint32 num_output = 1; // The number of outputs for the node
  optional bool bias_term = 2 [default = true]; // whether to have bias terms
  optional FillerParameter weight_filler = 3; // The filler for the weight
  optional FillerParameter bias_filler = 4; // The filler for the bias

  // The first axis to be lumped into a single inner product computation;
  // all preceding axes are retained in the output.
  // May be negative to index from the end (e.g., -1 for the last axis).
  optional int32 axis = 5 [default = 1];
  // Specify whether to transpose the weight matrix or not.
  // If transpose == true, any operations will be performed on the transpose
  // of the weight matrix. The weight matrix itself is not going to be transposed
  // but rather the transfer flag of operations will be toggled accordingly.
  optional bool transpose = 6 [default = false];
  optional int32 num_timesteps = 7 [default = 0];
  optional bool activation_term = 8 [default = false];
  optional FillerParameter activation_filler = 9; // block output in timestep t=0 for RNN/LSTM
  optional ComputeEngine engine = 10 [default = XSMM];
  optional AlgorithmType algotype = 11 [default = DIRECT];
  optional DataType data_type = 12 [default = FLOAT];
}

message FusedBNormParameter {
  // If false, accumulate global mean/variance values via a moving average. If
  // true, use those accumulated values instead of computing mean/variance
  // across the batch.
  optional bool use_global_stats = 1;
  // How much does the moving average decay each iteration?
  optional float mmf = 2 [default = .999];
  // Small value to add to the variance estimate so that we don't divide by zero.
  optional float eps = 3 [default = 1e-7];
  optional bool relu = 4 [default = true];
  optional bool bwd_relu = 20 [default = true];
  optional bool eltwise = 5 [default = false];
  repeated uint32 pad = 6; // The padding size; defaults to 0
  optional uint32 pad_h = 7 [default = 0]; // The padding height (2D only)
  optional uint32 pad_w = 8 [default = 0]; // The padding width (2D only)
  optional uint32 pad_d = 9 [default = 0]; // The padding width (2D only)
  repeated uint32 ipad = 10; // The padding size; defaults to 0
  optional uint32 ipad_h = 11 [default = 0]; // The padding height (2D only)
  optional uint32 ipad_w = 12 [default = 0]; // The padding width (2D only)
  optional uint32 ipad_d = 13 [default = 0]; // The padding width (2D only)
  repeated uint32 stride = 14; // The stride; defaults to 1
  optional uint32 stride_h = 15 [default = 1]; // The stride height (2D only)
  optional uint32 stride_w = 16 [default = 1]; // The stride width (2D only)
  optional uint32 stride_d = 17 [default = 1]; // The stride width (2D only)
  optional float lr_mult = 21 [default = 1.0];
  optional float decay_mult = 22 [default = 0.0];
  optional ComputeEngine engine = 18 [default = XSMM];
  optional AlgorithmType algotype = 19 [default = DIRECT];
  optional DataType data_type = 23 [default = FLOAT];
}

message FusedConvBNParameter {
  optional uint32 num_output = 1; // The number of outputs for the nodes
  // Pad, kernel size, and stride are all given as a single value for equal
  // dimensions in all spatial dimensions, or once per spatial dimension.
  repeated uint32 ipad = 2; // The padding size; defaults to 0
  repeated uint32 mpad = 3; // The padding size; defaults to 0
  repeated uint32 opad = 4; // The padding size; defaults to 0
  repeated uint32 kernel_size = 5; // The kernel size
  optional uint32 group = 6 [default = 1]; // The group size for group conv
  repeated uint32 c_stride = 7; // The stride; defaults to 1
  repeated uint32 bn_stride = 8; // The stride; defaults to 1
  optional FillerParameter weight_filler = 9; // The filler for the weight
  // Factor used to dilate the kernel, (implicitly) zero-filling the resulting
  // holes. (Kernel dilation is sometimes referred to by its use in the
  // algorithme à trous from Holschneider et al. 1987.)
  repeated uint32 dilation = 10; // The dilation; defaults to 1

  // For 2D convolution only, the *_h and *_w versions may also be used to
  // specify both spatial dimensions.
  optional uint32 ipad_h = 11 [default = 0]; // The padding height (2D only)
  optional uint32 ipad_w = 12 [default = 0]; // The padding width (2D only)
  optional uint32 mpad_h = 13 [default = 0]; // The padding width (2D only)
  optional uint32 mpad_w = 14 [default = 0]; // The padding width (2D only)
  optional uint32 opad_h = 15 [default = 0]; // The padding width (2D only)
  optional uint32 opad_w = 16 [default = 0]; // The padding width (2D only)
  optional uint32 kernel_h = 17; // The kernel height (2D only)
  optional uint32 kernel_w = 18; // The kernel width (2D only)
  optional uint32 c_stride_h = 19 [default = 1]; // The stride height (2D only)
  optional uint32 c_stride_w = 20 [default = 1]; // The stride width (2D only)
  optional uint32 bn_stride_h = 21 [default = 1]; // The stride width (2D only)
  optional uint32 bn_stride_w = 22 [default = 1]; // The stride width (2D only)
  optional uint32 ndims = 23 [default = 2];
  optional bool relu_fwd = 24 [default = true];
  optional bool relu_bwd = 25 [default = true];
  optional bool physical_padding = 26 [default = false];

  // If false, accumulate global mean/variance values via a moving average. If
  // true, use those accumulated values instead of computing mean/variance
  // across the batch.
  optional bool use_global_stats = 27;
  // How much does the moving average decay each iteration?
  optional float mmf = 28 [default = .999];
  // Small value to add to the variance estimate so that we don't divide by zero.
  optional float eps = 29 [default = 1e-7];
  optional bool eltwise = 30 [default = false];
  optional ComputeEngine engine = 31 [default = XSMM];
  optional AlgorithmType algotype = 32 [default = DIRECT];
  optional DataType data_type = 33 [default = FLOAT];
}

// Message that stores parameters used to apply transformation
// to the image node's data
message ImageTransformParameter {
  // For image data pre-processing, we can do simple scaling and subtracting the
  // data mean, if provided. Note that the mean subtraction is always carried
  // out before scaling.
  // Single scale for baseline
  optional uint32 scale = 1 [default = 256];
  // Multiple scales for scale-jittering
  repeated uint32 jitters = 2;
  // Specify if we want to randomly mirror data.
  optional bool mirror = 3 [default = false];
  // Specify the base crop size for a(n) square image (repeated for height, width)
  repeated uint32 crop_size = 4;
  // Specify base crop height for an image (not necessarily square)
  optional uint32 crop_h = 5 [default = 227];
  // Specify base crop width for an image (not necessarily square)
  optional uint32 crop_w = 6 [default = 227];
  // Specify if we would like to randomly crop an image.
  optional bool crop_image = 7 [default = false];
  // mean_file and mean_value cannot be specified at the same time
  optional string mean_file = 8;
  // if specified can be repeated once (would subtract it from all the channels)
  // or can be repeated the same number of times as channels
  // (would subtract them from the corresponding channel)
  repeated float mean_values = 9;
  // Force the decoded image to have 3 color channels.
  optional bool force_color = 10 [default = false];
  // Force the decoded image to have 1 color channels.
  optional bool force_gray = 11 [default = false];
  // Assume that input images have 3 channels (i.e., they are color images) by default. Set to 1 for grayscale
  optional uint32 channels = 12 [default = 3];
  // Random Vignette augmentation
  optional bool vignette = 13 [default = false];
  optional bool color_bump = 14 [default = false];
  // Specify the base original size for a(n) square image (repeated for height, width)
  repeated uint32 orig_size = 15;
  // Specify base original height for an image (not necessarily square)
  optional uint32 orig_h = 16 [default = 256];
  // Specify base original width for an image (not necessarily square)
  optional uint32 orig_w = 17 [default = 256];
  // Specify the number of crops for testing
  optional uint32 test_views = 18 [default = 1];
  //Specify standard deviation for normalizing convnet
  repeated float scale_values = 19;
  optional float scalejittering_min = 20 [default = 256];
  optional float scalejittering_max = 21 [default = 512];
  optional float min_percent_area = 22 [default = 0.08];
  optional float max_percent_area = 23 [default = 1];
  optional float min_aspect_ratio = 24 [default = 0.75];
  optional float max_aspect_ratio = 25 [default = 1.3333];
  optional int32 test_smaller_side = 26 [default = 256];
  optional int32 pad_h = 27 [default = 0];
  optional int32 pad_w = 28 [default = 0];
  optional bool physical_padding = 29 [default = false];
}

// Message that stores parameters used by Lognodes
message LogParameter {
  // Lognodes computes outputs y = log_base(shift + scale * x), for base > 0.
  // Or if base is set to the default (-1), base is set to e,
  // so y = ln(shift + scale * x) = log_e(shift + scale * x)
  optional float base = 1 [default = -1.0];
  optional float scale = 2 [default = 1.0];
  optional float shift = 3 [default = 0.0];
}

// Message that stores parameters shared by loss nodess
message LossParameter {
  // If specified, ignore instances with the given label.
  optional int32 ignore_label = 1;
  // How to normalize the loss for loss nodess that aggregate across batches,
  // spatial dimensions, or other dimensions.  Currently only implemented in
  // SoftmaxWithLoss nodes.
  enum NormalizationMode {
    // Divide by the number of examples in the batch times spatial dimensions.
    // Outputs that receive the ignore label will NOT be ignored in computing
    // the normalization factor.
    FULL = 0;
    // Divide by the total number of output locations that do not take the
    // ignore_label.  If ignore_label is not set, this behaves like FULL.
    VALID = 1;
    // Divide by the batch size.
    BATCH_SIZE = 2;
    // Do not normalize the loss.
    NONE = 3;
  }
  optional NormalizationMode normalization = 3 [default = VALID];
  // Deprecated.  Ignored if normalization is specified.  If normalization
  // is not specified, then setting this to false will be equivalent to
  // normalization = BATCH_SIZE to be consistent with previous behavior.
  optional bool normalize = 2;
}

message PoolingParameter {
  enum PoolMethod {
    MAX = 0;
    AVE = 1;
    STOCHASTIC = 2;
  }
  optional PoolMethod pool = 1 [default = MAX]; // The pooling method
  // Pad, kernel size, and stride are all given as a single value for equal
  // dimensions in height and width or as Y, X pairs.
  repeated uint32 kernel_size = 2; // The kernel size (square)
  optional uint32 kernel_h = 3; // The kernel height
  optional uint32 kernel_w = 4; // The kernel width
  optional uint32 kernel_d = 5; // The kernel depth (for 3D)
  repeated uint32 stride = 6; // The stride (equal in Y, X)
  optional uint32 stride_h = 7 [default = 1]; // The stride height
  optional uint32 stride_w = 8 [default = 1]; // The stride width
  optional uint32 stride_d = 9 [default = 1]; // The stride depth (for 3D)
  repeated uint32 pad = 10; // The padding size (equal in Y, X)
  optional uint32 pad_h = 13 [default = 0]; // The padding height
  optional uint32 pad_w = 14 [default = 0]; // The padding width
  optional uint32 pad_d = 15 [default = 0]; // The padding depth (for 3D)
  optional uint32 ndims = 17 [default = 2];
  optional ComputeEngine engine = 11 [default = XSMM];
  // If global_pooling then it will pool over the size of the bottom by doing
  // kernel_h = bottom->height and kernel_w = bottom->width
  optional bool global_pooling = 12 [default = false];
  optional AlgorithmType algotype = 16 [default = DIRECT];
  optional DataType data_type = 18 [default = FLOAT];
}

// Message that stores parameters used by ReLUnodes
message ReLUParameter {
  // Allow non-zero slope for negative inputs to speed up optimization
  // Described in:
  // Maas, A. L., Hannun, A. Y., & Ng, A. Y. (2013). Rectifier nonlinearities
  // improve neural network acoustic models. In ICML Workshop on Deep Learning
  // for Audio, Speech, and Language Processing.
  optional float negative_slope = 1 [default = 0];
  optional ComputeEngine engine = 2 [default = XSMM];
  optional AlgorithmType algotype = 3 [default = DIRECT];
  optional DataType data_type = 4 [default = FLOAT];
}

// Message that stores parameters used by Softmaxnodes, SoftmaxWithLossnodes
message SoftmaxParameter {
  optional ComputeEngine engine = 1 [default = XSMM];

  // The axis along which to perform the softmax -- may be negative to index
  // from the end (e.g., -1 for the last axis).
  // Any other axes will be evaluated as independent softmaxes.
  optional int32 axis = 2 [default = 1];
  optional AlgorithmType algotype = 3 [default = DIRECT];  
  optional DataType data_type = 4 [default = FLOAT];
}

message SplitParameter {
  optional ComputeEngine engine = 1 [default = XSMM];
  optional AlgorithmType algotype = 2 [default = DIRECT];
  optional DataType data_type = 3 [default = FLOAT];
}

message TanHParameter {
  optional ComputeEngine engine = 1 [default = XSMM];
  optional AlgorithmType algotype = 2 [default = DIRECT];
}

// Message that stores parameters used by Thresholdnodes
message ThresholdParameter {
  optional float threshold = 1 [default = 0]; // Strictly positive values
}

message WindowDataParameter {
  // Specify the data source.
  optional string source = 1;
  // For data pre-processing, we can do simple scaling and subtracting the
  // data mean, if provided. Note that the mean subtraction is always carried
  // out before scaling.
  optional float scale = 2 [default = 1];
  optional string mean_file = 3;
  // Specify the batch size.
  optional uint32 batch_size = 4;
  // Specify if we would like to randomly crop an image.
  optional uint32 crop_size = 5 [default = 0];
  // Specify if we want to randomly mirror data.
  optional bool mirror = 6 [default = false];
  // Foreground (object) overlap threshold
  optional float fg_threshold = 7 [default = 0.5];
  // Background (non-object) overlap threshold
  optional float bg_threshold = 8 [default = 0.5];
  // Fraction of batch that should be foreground objects
  optional float fg_fraction = 9 [default = 0.25];
  // Amount of contextual padding to add around a window
  // (used only by the window_data_nodes)
  optional uint32 context_pad = 10 [default = 0];
  // Mode for cropping out a detection window
  // warp: cropped window is warped to a fixed size and aspect ratio
  // square: the tightest square around the window is cropped
  optional string crop_mode = 11 [default = "warp"];
  // cache_images: will load all images in memory for faster access
  optional bool cache_images = 12 [default = false];
  // append root_folder to locate images
  optional string root_folder = 13 [default = ""];
}

message SPPParameter {
  enum PoolMethod {
    MAX = 0;
    AVE = 1;
    STOCHASTIC = 2;
  }
  optional uint32 pyramid_height = 1;
  optional PoolMethod pool = 2 [default = MAX]; // The pooling method
  optional ComputeEngine engine = 3 [default = XSMM];
  optional AlgorithmType algotype = 4 [default = DIRECT];
}

message PReLUParameter {
  // Parametric ReLU described in K. He et al, Delving Deep into Rectifiers:
  // Surpassing Human-Level Performance on ImageNet Classification, 2015.

  // Initial value of a_i. Default is a_i=0.25 for all i.
  optional FillerParameter filler = 1;
  // Whether or not slope paramters are shared across channels.
  optional bool channel_shared = 2 [default = false];
}
