I'm trying to generate MLIR using Tensorflow (2.2.0) as a front-end and I would like to clarify the following.
Let's consider the example below that implements direct matrix multiplication of two 2x2 matrices.
import tensorflow as tf
import tensorflow.mlir as mlir
with tf.Graph().as_default() as g:
with tf.device('/cpu:0'):
#tf.function
def mymatmul(A, B, C):
for i in range(2):
for j in range(2):
cij = 0.0
for k in range(2):
cij += A[i, k]*B[i, j]
C[i, j].assign(cij)
A = tf.constant([[1., 2.], [3., 4.]])
B = tf.constant([[2., 1.], [4., 3.]])
C = tf.Variable([[0., 0.], [0., 0.]])
mymatmul(A, B, C)
tf_mlir_graph = mlir.experimental.convert_graph_def(g.as_graph_def())
print(tf_mlir_graph)
This code emits the following MLIR.
module attributes {tf.versions = {bad_consumers = [], min_consumer = 12 : i32, producer = 175 : i32}} {
func #main() {
%0 = "tf.Const"() {value = dense<0.000000e+00> : tensor<2x2xf32>} : () -> tensor<2x2xf32>
%1 = "tf.Const"() {value = dense<[[2.000000e+00, 1.000000e+00], [4.000000e+00, 3.000000e+00]]> : tensor<2x2xf32>} : () -> tensor<2x2xf32>
%2 = "tf.Const"() {value = dense<[[1.000000e+00, 2.000000e+00], [3.000000e+00, 4.000000e+00]]> : tensor<2x2xf32>} : () -> tensor<2x2xf32>
%3 = "tf.VarHandleOp"() {_class = ["loc:#Variable"], container = "", device = "/device:CPU:0", dtype = f32, shape = "tfshape$dim { size: 2 } dim { size: 2 }", shared_name = "Variable"} : () -> tensor<!tf.resource<tensor<2x2xf32>>>
"tf.StatefulPartitionedCall"(%2, %1, %3) {Tin = ["tfdtype$DT_FLOAT", "tfdtype$DT_FLOAT", "tfdtype$DT_RESOURCE"], Tout = [], _read_only_resource_inputs = [], config = "", config_proto = "\0A\07\0A\03CPU\10\01\0A\07\0A\03GPU\10\002\02J\008\01", device = "/device:CPU:0", executor_type = "", f = #__inference_mymatmul_1160} : (tensor<2x2xf32>, tensor<2x2xf32>, tensor<!tf.resource<tensor<2x2xf32>>>) -> ()
%4 = "tf.VarIsInitializedOp"(%3) {device = "/device:CPU:0"} : (tensor<!tf.resource<tensor<2x2xf32>>>) -> tensor<i1>
%5 = "tf.ReadVariableOp"(%3) {device = "/device:CPU:0", dtype = f32} : (tensor<!tf.resource<tensor<2x2xf32>>>) -> tensor<2x2xf32>
"tf.AssignVariableOp"(%3, %0) {device = "/device:CPU:0", dtype = f32} : (tensor<!tf.resource<tensor<2x2xf32>>>, tensor<2x2xf32>) -> ()
return
}
func #__inference_mymatmul_1160(%arg0: tensor<2x2xf32>, %arg1: tensor<2x2xf32>, %arg2: tensor<!tf.resource>) attributes {tf.signature.is_stateful} {
%0 = "tf.Const"() {value = dense<1> : tensor<2xi32>} : () -> tensor<2xi32>
%1 = "tf.Const"() {value = dense<[1, 2]> : tensor<2xi32>} : () -> tensor<2xi32>
%2 = "tf.Const"() {value = dense<[0, 1]> : tensor<2xi32>} : () -> tensor<2xi32>
%3 = "tf.Const"() {value = dense<0> : tensor<2xi32>} : () -> tensor<2xi32>
%4 = "tf.Const"() {value = dense<2> : tensor<2xi32>} : () -> tensor<2xi32>
%5 = "tf.Const"() {value = dense<[2, 1]> : tensor<2xi32>} : () -> tensor<2xi32>
%6 = "tf.Const"() {value = dense<[1, 0]> : tensor<2xi32>} : () -> tensor<2xi32>
%7 = "tf.Const"() {value = dense<0.000000e+00> : tensor<f32>} : () -> tensor<f32>
%8 = "tf.ReadVariableOp"(%arg2) {device = "", dtype = f32} : (tensor<!tf.resource>) -> tensor<*xf32>
%9 = "tf.StridedSlice"(%arg0, %3, %0, %0) {Index = i32, T = f32, begin_mask = 0 : i64, device = "", ellipsis_mask = 0 : i64, end_mask = 0 : i64, new_axis_mask = 0 : i64, shrink_axis_mask = 3 : i64} : (tensor<2x2xf32>, tensor<2xi32>, tensor<2xi32>, tensor<2xi32>) -> tensor<f32>
%10 = "tf.StridedSlice"(%arg1, %3, %0, %0) {Index = i32, T = f32, begin_mask = 0 : i64, device = "", ellipsis_mask = 0 : i64, end_mask = 0 : i64, new_axis_mask = 0 : i64, shrink_axis_mask = 3 : i64} : (tensor<2x2xf32>, tensor<2xi32>, tensor<2xi32>, tensor<2xi32>) -> tensor<f32>
%11 = "tf.Mul"(%9, %10) {T = f32, device = ""} : (tensor<f32>, tensor<f32>) -> tensor<f32>
%12 = "tf.AddV2"(%11, %7) {T = f32, device = ""} : (tensor<f32>, tensor<f32>) -> tensor<f32>
%13 = "tf.StridedSlice"(%arg0, %6, %5, %0) {Index = i32, T = f32, begin_mask = 0 : i64, device = "", ellipsis_mask = 0 : i64, end_mask = 0 : i64, new_axis_mask = 0 : i64, shrink_axis_mask = 3 : i64} : (tensor<2x2xf32>, tensor<2xi32>, tensor<2xi32>, tensor<2xi32>) -> tensor<f32>
%14 = "tf.StridedSlice"(%arg1, %6, %5, %0) {Index = i32, T = f32, begin_mask = 0 : i64, device = "", ellipsis_mask = 0 : i64, end_mask = 0 : i64, new_axis_mask = 0 : i64, shrink_axis_mask = 3 : i64} : (tensor<2x2xf32>, tensor<2xi32>, tensor<2xi32>, tensor<2xi32>) -> tensor<f32>
%15 = "tf.Mul"(%13, %14) {T = f32, device = ""} : (tensor<f32>, tensor<f32>) -> tensor<f32>
%16 = "tf.AddV2"(%15, %7) {T = f32, device = ""} : (tensor<f32>, tensor<f32>) -> tensor<f32>
%17 = "tf.StridedSlice"(%arg0, %0, %4, %0) {Index = i32, T = f32, begin_mask = 0 : i64, device = "", ellipsis_mask = 0 : i64, end_mask = 0 : i64, new_axis_mask = 0 : i64, shrink_axis_mask = 3 : i64} : (tensor<2x2xf32>, tensor<2xi32>, tensor<2xi32>, tensor<2xi32>) -> tensor<f32>
%18 = "tf.Mul"(%17, %14) {T = f32, device = ""} : (tensor<f32>, tensor<f32>) -> tensor<f32>
%19 = "tf.AddV2"(%16, %18) {T = f32, device = ""} : (tensor<f32>, tensor<f32>) -> tensor<f32>
%20 = "tf.StridedSlice"(%arg1, %0, %4, %0) {Index = i32, T = f32, begin_mask = 0 : i64, device = "", ellipsis_mask = 0 : i64, end_mask = 0 : i64, new_axis_mask = 0 : i64, shrink_axis_mask = 3 : i64} : (tensor<2x2xf32>, tensor<2xi32>, tensor<2xi32>, tensor<2xi32>) -> tensor<f32>
%21 = "tf.Mul"(%13, %20) {T = f32, device = ""} : (tensor<f32>, tensor<f32>) -> tensor<f32>
%22 = "tf.AddV2"(%21, %7) {T = f32, device = ""} : (tensor<f32>, tensor<f32>) -> tensor<f32>
%23 = "tf.Mul"(%17, %20) {T = f32, device = ""} : (tensor<f32>, tensor<f32>) -> tensor<f32>
%24 = "tf.AddV2"(%22, %23) {T = f32, device = ""} : (tensor<f32>, tensor<f32>) -> tensor<f32>
%25 = "tf.StridedSlice"(%arg0, %2, %1, %0) {Index = i32, T = f32, begin_mask = 0 : i64, device = "", ellipsis_mask = 0 : i64, end_mask = 0 : i64, new_axis_mask = 0 : i64, shrink_axis_mask = 3 : i64} : (tensor<2x2xf32>, tensor<2xi32>, tensor<2xi32>, tensor<2xi32>) -> tensor<f32>
%26 = "tf.Mul"(%25, %10) {T = f32, device = ""} : (tensor<f32>, tensor<f32>) -> tensor<f32>
%27 = "tf.AddV2"(%12, %26) {T = f32, device = ""} : (tensor<f32>, tensor<f32>) -> tensor<f32>
"tf.ResourceStridedSliceAssign"(%arg2, %3, %0, %0, %27) {Index = i32, T = f32, begin_mask = 0 : i64, device = "", ellipsis_mask = 0 : i64, end_mask = 0 : i64, new_axis_mask = 0 : i64, shrink_axis_mask = 3 : i64} : (tensor<!tf.resource>, tensor<2xi32>, tensor<2xi32>, tensor<2xi32>, tensor<f32>) -> ()
%28 = "tf.ReadVariableOp"(%arg2) {device = "", dtype = f32} : (tensor<!tf.resource>) -> tensor<*xf32>
%29 = "tf.StridedSlice"(%arg1, %2, %1, %0) {Index = i32, T = f32, begin_mask = 0 : i64, device = "", ellipsis_mask = 0 : i64, end_mask = 0 : i64, new_axis_mask = 0 : i64, shrink_axis_mask = 3 : i64} : (tensor<2x2xf32>, tensor<2xi32>, tensor<2xi32>, tensor<2xi32>) -> tensor<f32>
%30 = "tf.Mul"(%9, %29) {T = f32, device = ""} : (tensor<f32>, tensor<f32>) -> tensor<f32>
%31 = "tf.AddV2"(%30, %7) {T = f32, device = ""} : (tensor<f32>, tensor<f32>) -> tensor<f32>
%32 = "tf.Mul"(%25, %29) {T = f32, device = ""} : (tensor<f32>, tensor<f32>) -> tensor<f32>
%33 = "tf.AddV2"(%31, %32) {T = f32, device = ""} : (tensor<f32>, tensor<f32>) -> tensor<f32>
"tf.ResourceStridedSliceAssign"(%arg2, %2, %1, %0, %33) {Index = i32, T = f32, begin_mask = 0 : i64, device = "", ellipsis_mask = 0 : i64, end_mask = 0 : i64, new_axis_mask = 0 : i64, shrink_axis_mask = 3 : i64} : (tensor<!tf.resource>, tensor<2xi32>, tensor<2xi32>, tensor<2xi32>, tensor<f32>) -> ()
%34 = "tf.ReadVariableOp"(%arg2) {device = "", dtype = f32} : (tensor<!tf.resource>) -> tensor<*xf32>
"tf.ResourceStridedSliceAssign"(%arg2, %6, %5, %0, %19) {Index = i32, T = f32, begin_mask = 0 : i64, device = "", ellipsis_mask = 0 : i64, end_mask = 0 : i64, new_axis_mask = 0 : i64, shrink_axis_mask = 3 : i64} : (tensor<!tf.resource>, tensor<2xi32>, tensor<2xi32>, tensor<2xi32>, tensor<f32>) -> ()
%35 = "tf.ReadVariableOp"(%arg2) {device = "", dtype = f32} : (tensor<!tf.resource>) -> tensor<*xf32>
"tf.ResourceStridedSliceAssign"(%arg2, %0, %4, %0, %24) {Index = i32, T = f32, begin_mask = 0 : i64, device = "", ellipsis_mask = 0 : i64, end_mask = 0 : i64, new_axis_mask = 0 : i64, shrink_axis_mask = 3 : i64} : (tensor<!tf.resource>, tensor<2xi32>, tensor<2xi32>, tensor<2xi32>, tensor<f32>) -> ()
return
}
}
What is interesting, at least for my purposes, is the loss of the loop structure of the computation. In the tf dialect, the loop structure is flattened but I would like the output MLIR to reflect/preserve the original loop structure expressed in the TF operator graph.
I suppose, another way of phrasing this question is to ask whether TensorFlow dialect supports control constructs (in my belief it does via tf.IfOp and tf.WhileOp) and if there are any particular syntax restrictions the input should adhere to in order to retain the loop structure.
What would be the best way to go about this?
P.S. I suspect this might have something to do with eager execution which is the default behavior in tf =>2.0. Maybe someone can verify this?
Thanks,
Modifying the input computation to the following did the trick. I believe the problem was with (at least partly) the use of python variables along with tf variables. The following effectively preserves the symbolic structure of the computation.
with tf.Graph().as_default() as g:
with tf.device('/cpu:0'):
#tf.function
def mymatmul(A, B, C, m, n):
for i in range(m):
for j in range(m):
for k in range(n):
C[i,j].assign(tf.math.add(C[i, j], tf.math.multiply(A[i, k], B[k, j])))
return C
A = tf.constant([[1., 2.], [3., 4.]])
B = tf.constant([[2., 1.], [4., 3.]])
C = tf.Variable((tf.zeros((2, 2), dtype=tf.float32)))
m = tf.constant(2)
n = tf.constant(2)
mymatmul(A, B, C, m, n)
This generates the following MLIR with tf.While.
module attributes {tf.versions = {bad_consumers = [], min_consumer = 12 : i32, producer = 412 : i32}} {
func #main() {
%0 = "tf.Const"() {value = dense<[[1.000000e+00, 2.000000e+00], [3.000000e+00, 4.000000e+00]]> : tensor<2x2xf32>} : () -> tensor<2x2xf32>
%1 = "tf.Const"() {value = dense<[[2.000000e+00, 1.000000e+00], [4.000000e+00, 3.000000e+00]]> : tensor<2x2xf32>} : () -> tensor<2x2xf32>
%2 = "tf.Const"() {value = dense<2> : tensor<i32>} : () -> tensor<i32>
%3 = "tf.Const"() {value = dense<0.000000e+00> : tensor<2x2xf32>} : () -> tensor<2x2xf32>
%4 = "tf.VarHandleOp"() {_class = ["loc:#Variable"], allowed_devices = [], container = "", device = "/device:CPU:0", shared_name = "Variable"} : () -> tensor<!tf.resource<tensor<2x2xf32>>>
%5 = "tf.StatefulPartitionedCall"(%0, %1, %4, %2, %2) {_collective_manager_ids = [], _read_only_resource_inputs = [], config = "", config_proto = "\0A\07\0A\03CPU\10\01\0A\07\0A\03GPU\10\002\02J\008\01", device = "/device:CPU:0", executor_type = "", f = #__inference_mymatmul_3650} : (tensor<2x2xf32>, tensor<2x2xf32>, tensor<!tf.resource<tensor<2x2xf32>>>, tensor<i32>, tensor<i32>) -> tensor<2x2xf32>
%6 = "tf.VarIsInitializedOp"(%4) {device = "/device:CPU:0"} : (tensor<!tf.resource<tensor<2x2xf32>>>) -> tensor<i1>
%7 = "tf.ReadVariableOp"(%4) {device = "/device:CPU:0"} : (tensor<!tf.resource<tensor<2x2xf32>>>) -> tensor<2x2xf32>
"tf.AssignVariableOp"(%4, %3) {device = "/device:CPU:0"} : (tensor<!tf.resource<tensor<2x2xf32>>>, tensor<2x2xf32>) -> ()
return
}
func #__inference_mymatmul_3650(%arg0: tensor<2x2xf32>, %arg1: tensor<2x2xf32>, %arg2: tensor<!tf.resource<tensor<2x2xf32>>>, %arg3: tensor<i32>, %arg4: tensor<i32>) -> tensor<2x2xf32> attributes {tf.signature.is_stateful} {
%0 = "tf.Const"() {value = dense<[[1.000000e+00, 2.000000e+00], [3.000000e+00, 4.000000e+00]]> : tensor<2x2xf32>} : () -> tensor<2x2xf32>
%1 = "tf.Const"() {value = dense<[[2.000000e+00, 1.000000e+00], [4.000000e+00, 3.000000e+00]]> : tensor<2x2xf32>} : () -> tensor<2x2xf32>
%2 = "tf.Const"() {value = dense<1> : tensor<i32>} : () -> tensor<i32>
%3 = "tf.Const"() {value = dense<0> : tensor<i32>} : () -> tensor<i32>
%4 = "tf.Const"() {value = dense<2> : tensor<i32>} : () -> tensor<i32>
%5:10 = "tf.While"(%3, %4, %3, %2, %4, %4, %4, %arg2, %0, %1) {_lower_using_switch_merge = true, _num_original_outputs = 10 : i64, _read_only_resource_inputs = [], body = #while_body_1410, cond = #while_cond_1400, device = "", is_stateless = false, output_shapes = [#tf.shape<>, #tf.shape<>, #tf.shape<>, #tf.shape<>, #tf.shape<>, #tf.shape<>, #tf.shape<>, #tf.shape<>, #tf.shape<2x2>, #tf.shape<2x2>], parallel_iterations = 10 : i64} : (tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<!tf.resource<tensor<2x2xf32>>>, tensor<2x2xf32>, tensor<2x2xf32>) -> (tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<!tf.resource<tensor<2x2xf32>>>, tensor<2x2xf32>, tensor<2x2xf32>)
%6 = "tf.ReadVariableOp"(%arg2) {device = ""} : (tensor<!tf.resource<tensor<2x2xf32>>>) -> tensor<2x2xf32>
%7 = "tf.Identity"(%6) {device = ""} : (tensor<2x2xf32>) -> tensor<2x2xf32>
return %7 : tensor<2x2xf32>
}
func #while_body_1410(%arg0: tensor<i32>, %arg1: tensor<i32>, %arg2: tensor<i32>, %arg3: tensor<i32>, %arg4: tensor<i32>, %arg5: tensor<i32>, %arg6: tensor<i32>, %arg7: tensor<!tf.resource<tensor<2x2xf32>>>, %arg8: tensor<2x2xf32>, %arg9: tensor<2x2xf32>) -> (tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<!tf.resource<tensor<2x2xf32>>>, tensor<2x2xf32>, tensor<2x2xf32>) attributes {tf.signature.is_stateful} {
%0 = "tf.Const"() {value = dense<1> : tensor<i32>} : () -> tensor<i32>
%1 = "tf.Const"() {value = dense<0> : tensor<i32>} : () -> tensor<i32>
%2 = "tf.Maximum"(%arg5, %1) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i32>
%3 = "tf.FloorDiv"(%2, %0) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i32>
%4 = "tf.FloorMod"(%2, %0) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i32>
%5 = "tf.AddV2"(%arg2, %arg3) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i32>
%6 = "tf.AddV2"(%arg0, %0) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i32>
%7 = "tf.NotEqual"(%4, %1) {device = "", incompatible_shape_error = true} : (tensor<i32>, tensor<i32>) -> tensor<i1>
%8 = "tf.Cast"(%7) {Truncate = false, device = ""} : (tensor<i1>) -> tensor<i32>
%9 = "tf.AddV2"(%3, %8) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i32>
%10 = "tf.Maximum"(%9, %1) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i32>
%11:10 = "tf.While"(%1, %10, %1, %0, %2, %arg6, %arg7, %arg2, %arg8, %arg9) {_lower_using_switch_merge = true, _num_original_outputs = 10 : i64, _read_only_resource_inputs = [], body = #while_body_1830, cond = #while_cond_1820, device = "", is_stateless = false, output_shapes = [#tf.shape<>, #tf.shape<>, #tf.shape<>, #tf.shape<>, #tf.shape<>, #tf.shape<>, #tf.shape<>, #tf.shape<>, #tf.shape<2x2>, #tf.shape<2x2>], parallel_iterations = 10 : i64} : (tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<!tf.resource<tensor<2x2xf32>>>, tensor<i32>, tensor<2x2xf32>, tensor<2x2xf32>) -> (tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<!tf.resource<tensor<2x2xf32>>>, tensor<i32>, tensor<2x2xf32>, tensor<2x2xf32>)
%12 = "tf.Identity"(%6) {device = ""} : (tensor<i32>) -> tensor<i32>
%13 = "tf.Identity"(%arg1) {device = ""} : (tensor<i32>) -> tensor<i32>
%14 = "tf.Identity"(%5) {device = ""} : (tensor<i32>) -> tensor<i32>
return %12, %13, %14, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9 : tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<!tf.resource<tensor<2x2xf32>>>, tensor<2x2xf32>, tensor<2x2xf32>
}
func #while_body_1830(%arg0: tensor<i32>, %arg1: tensor<i32>, %arg2: tensor<i32>, %arg3: tensor<i32>, %arg4: tensor<i32>, %arg5: tensor<i32>, %arg6: tensor<!tf.resource<tensor<2x2xf32>>>, %arg7: tensor<i32>, %arg8: tensor<2x2xf32>, %arg9: tensor<2x2xf32>) -> (tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<!tf.resource<tensor<2x2xf32>>>, tensor<i32>, tensor<2x2xf32>, tensor<2x2xf32>) attributes {tf.signature.is_stateful} {
%0 = "tf.Const"() {value = dense<1> : tensor<i32>} : () -> tensor<i32>
%1 = "tf.Const"() {value = dense<0> : tensor<i32>} : () -> tensor<i32>
%2 = "tf.Maximum"(%arg5, %1) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i32>
%3 = "tf.FloorDiv"(%2, %0) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i32>
%4 = "tf.FloorMod"(%2, %0) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i32>
%5 = "tf.AddV2"(%arg2, %arg3) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i32>
%6 = "tf.AddV2"(%arg0, %0) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i32>
%7 = "tf.NotEqual"(%4, %1) {device = "", incompatible_shape_error = true} : (tensor<i32>, tensor<i32>) -> tensor<i1>
%8 = "tf.Cast"(%7) {Truncate = false, device = ""} : (tensor<i1>) -> tensor<i32>
%9 = "tf.AddV2"(%3, %8) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i32>
%10 = "tf.Maximum"(%9, %1) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i32>
%11:10 = "tf.While"(%1, %10, %1, %0, %2, %arg6, %arg7, %arg2, %arg8, %arg9) {_lower_using_switch_merge = true, _num_original_outputs = 10 : i64, _read_only_resource_inputs = [], body = #while_body_2250, cond = #while_cond_2240, device = "", is_stateless = false, output_shapes = [#tf.shape<>, #tf.shape<>, #tf.shape<>, #tf.shape<>, #tf.shape<>, #tf.shape<>, #tf.shape<>, #tf.shape<>, #tf.shape<2x2>, #tf.shape<2x2>], parallel_iterations = 10 : i64} : (tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<!tf.resource<tensor<2x2xf32>>>, tensor<i32>, tensor<i32>, tensor<2x2xf32>, tensor<2x2xf32>) -> (tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<!tf.resource<tensor<2x2xf32>>>, tensor<i32>, tensor<i32>, tensor<2x2xf32>, tensor<2x2xf32>)
%12 = "tf.Identity"(%6) {device = ""} : (tensor<i32>) -> tensor<i32>
%13 = "tf.Identity"(%arg1) {device = ""} : (tensor<i32>) -> tensor<i32>
%14 = "tf.Identity"(%5) {device = ""} : (tensor<i32>) -> tensor<i32>
return %12, %13, %14, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9 : tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<!tf.resource<tensor<2x2xf32>>>, tensor<i32>, tensor<2x2xf32>, tensor<2x2xf32>
}
func #while_body_2250(%arg0: tensor<i32>, %arg1: tensor<i32>, %arg2: tensor<i32>, %arg3: tensor<i32>, %arg4: tensor<i32>, %arg5: tensor<!tf.resource<tensor<2x2xf32>>>, %arg6: tensor<i32>, %arg7: tensor<i32>, %arg8: tensor<2x2xf32>, %arg9: tensor<2x2xf32>) -> (tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<!tf.resource<tensor<2x2xf32>>>, tensor<i32>, tensor<i32>, tensor<2x2xf32>, tensor<2x2xf32>) attributes {tf.signature.is_stateful} {
%0 = "tf.Const"() {value = dense<1> : tensor<i32>} : () -> tensor<i32>
%1 = "tf.Const"() {value = dense<1> : tensor<2xi32>} : () -> tensor<2xi32>
%2 = "tf.AddV2"(%arg7, %0) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i32>
%3 = "tf.AddV2"(%arg6, %0) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i32>
%4 = "tf.Pack"(%3, %2) {axis = 0 : i64, device = ""} : (tensor<i32>, tensor<i32>) -> tensor<2xi32>
%5 = "tf.Pack"(%arg6, %arg7) {axis = 0 : i64, device = ""} : (tensor<i32>, tensor<i32>) -> tensor<2xi32>
%6 = "tf.AddV2"(%arg2, %0) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i32>
%7 = "tf.Pack"(%3, %6) {axis = 0 : i64, device = ""} : (tensor<i32>, tensor<i32>) -> tensor<2xi32>
%8 = "tf.Pack"(%6, %2) {axis = 0 : i64, device = ""} : (tensor<i32>, tensor<i32>) -> tensor<2xi32>
%9 = "tf.Pack"(%arg6, %arg2) {axis = 0 : i64, device = ""} : (tensor<i32>, tensor<i32>) -> tensor<2xi32>
%10 = "tf.Pack"(%arg2, %arg7) {axis = 0 : i64, device = ""} : (tensor<i32>, tensor<i32>) -> tensor<2xi32>
%11 = "tf.AddV2"(%arg2, %arg3) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i32>
%12 = "tf.ReadVariableOp"(%arg5) {device = ""} : (tensor<!tf.resource<tensor<2x2xf32>>>) -> tensor<2x2xf32>
%13 = "tf.ReadVariableOp"(%arg5) {device = ""} : (tensor<!tf.resource<tensor<2x2xf32>>>) -> tensor<2x2xf32>
%14 = "tf.StridedSlice"(%13, %5, %4, %1) {begin_mask = 0 : i64, device = "", ellipsis_mask = 0 : i64, end_mask = 0 : i64, new_axis_mask = 0 : i64, shrink_axis_mask = 3 : i64} : (tensor<2x2xf32>, tensor<2xi32>, tensor<2xi32>, tensor<2xi32>) -> tensor<f32>
%15 = "tf.StridedSlice"(%arg8, %9, %7, %1) {begin_mask = 0 : i64, device = "", ellipsis_mask = 0 : i64, end_mask = 0 : i64, new_axis_mask = 0 : i64, shrink_axis_mask = 3 : i64} : (tensor<2x2xf32>, tensor<2xi32>, tensor<2xi32>, tensor<2xi32>) -> tensor<f32>
%16 = "tf.StridedSlice"(%arg9, %10, %8, %1) {begin_mask = 0 : i64, device = "", ellipsis_mask = 0 : i64, end_mask = 0 : i64, new_axis_mask = 0 : i64, shrink_axis_mask = 3 : i64} : (tensor<2x2xf32>, tensor<2xi32>, tensor<2xi32>, tensor<2xi32>) -> tensor<f32>
%17 = "tf.Mul"(%15, %16) {device = ""} : (tensor<f32>, tensor<f32>) -> tensor<f32>
%18 = "tf.AddV2"(%14, %17) : (tensor<f32>, tensor<f32>) -> tensor<f32>
"tf.ResourceStridedSliceAssign"(%arg5, %5, %4, %1, %18) {Index = i32, T = f32, begin_mask = 0 : i64, device = "", ellipsis_mask = 0 : i64, end_mask = 0 : i64, new_axis_mask = 0 : i64, shrink_axis_mask = 3 : i64} : (tensor<!tf.resource<tensor<2x2xf32>>>, tensor<2xi32>, tensor<2xi32>, tensor<2xi32>, tensor<f32>) -> ()
%19 = "tf.Identity"(%arg1) {device = ""} : (tensor<i32>) -> tensor<i32>
%20 = "tf.Identity"(%11) {device = ""} : (tensor<i32>) -> tensor<i32>
%21 = "tf.AddV2"(%arg0, %0) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i32>
%22 = "tf.Identity"(%21) {device = ""} : (tensor<i32>) -> tensor<i32>
return %22, %19, %20, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9 : tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<!tf.resource<tensor<2x2xf32>>>, tensor<i32>, tensor<i32>, tensor<2x2xf32>, tensor<2x2xf32>
}
func #while_cond_2240(%arg0: tensor<i32>, %arg1: tensor<i32>, %arg2: tensor<i32>, %arg3: tensor<i32>, %arg4: tensor<i32>, %arg5: tensor<!tf.resource<tensor<2x2xf32>>>, %arg6: tensor<i32>, %arg7: tensor<i32>, %arg8: tensor<2x2xf32>, %arg9: tensor<2x2xf32>) -> tensor<i1> {
%0 = "tf.Const"() {value = dense<0> : tensor<i32>} : () -> tensor<i32>
%1 = "tf.GreaterEqual"(%arg3, %0) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i1>
%2 = "tf.Less"(%arg3, %0) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i1>
%3 = "tf.Greater"(%arg2, %arg4) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i1>
%4 = "tf.LogicalAnd"(%2, %3) {device = ""} : (tensor<i1>, tensor<i1>) -> tensor<i1>
%5 = "tf.Less"(%arg2, %arg4) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i1>
%6 = "tf.LogicalAnd"(%1, %5) {device = ""} : (tensor<i1>, tensor<i1>) -> tensor<i1>
%7 = "tf.LogicalOr"(%6, %4) {device = ""} : (tensor<i1>, tensor<i1>) -> tensor<i1>
%8 = "tf.Less"(%arg0, %arg1) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i1>
%9 = "tf.LogicalAnd"(%8, %7) {device = ""} : (tensor<i1>, tensor<i1>) -> tensor<i1>
%10 = "tf.Identity"(%9) {device = ""} : (tensor<i1>) -> tensor<i1>
return %10 : tensor<i1>
}
func #while_cond_1820(%arg0: tensor<i32>, %arg1: tensor<i32>, %arg2: tensor<i32>, %arg3: tensor<i32>, %arg4: tensor<i32>, %arg5: tensor<i32>, %arg6: tensor<!tf.resource<tensor<2x2xf32>>>, %arg7: tensor<i32>, %arg8: tensor<2x2xf32>, %arg9: tensor<2x2xf32>) -> tensor<i1> {
%0 = "tf.Const"() {value = dense<0> : tensor<i32>} : () -> tensor<i32>
%1 = "tf.GreaterEqual"(%arg3, %0) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i1>
%2 = "tf.Less"(%arg3, %0) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i1>
%3 = "tf.Greater"(%arg2, %arg4) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i1>
%4 = "tf.LogicalAnd"(%2, %3) {device = ""} : (tensor<i1>, tensor<i1>) -> tensor<i1>
%5 = "tf.Less"(%arg2, %arg4) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i1>
%6 = "tf.LogicalAnd"(%1, %5) {device = ""} : (tensor<i1>, tensor<i1>) -> tensor<i1>
%7 = "tf.LogicalOr"(%6, %4) {device = ""} : (tensor<i1>, tensor<i1>) -> tensor<i1>
%8 = "tf.Less"(%arg0, %arg1) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i1>
%9 = "tf.LogicalAnd"(%8, %7) {device = ""} : (tensor<i1>, tensor<i1>) -> tensor<i1>
%10 = "tf.Identity"(%9) {device = ""} : (tensor<i1>) -> tensor<i1>
return %10 : tensor<i1>
}
func #while_cond_1400(%arg0: tensor<i32>, %arg1: tensor<i32>, %arg2: tensor<i32>, %arg3: tensor<i32>, %arg4: tensor<i32>, %arg5: tensor<i32>, %arg6: tensor<i32>, %arg7: tensor<!tf.resource<tensor<2x2xf32>>>, %arg8: tensor<2x2xf32>, %arg9: tensor<2x2xf32>) -> tensor<i1> {
%0 = "tf.Const"() {value = dense<0> : tensor<i32>} : () -> tensor<i32>
%1 = "tf.GreaterEqual"(%arg3, %0) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i1>
%2 = "tf.Less"(%arg3, %0) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i1>
%3 = "tf.Greater"(%arg2, %arg4) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i1>
%4 = "tf.LogicalAnd"(%2, %3) {device = ""} : (tensor<i1>, tensor<i1>) -> tensor<i1>
%5 = "tf.Less"(%arg2, %arg4) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i1>
%6 = "tf.LogicalAnd"(%1, %5) {device = ""} : (tensor<i1>, tensor<i1>) -> tensor<i1>
%7 = "tf.LogicalOr"(%6, %4) {device = ""} : (tensor<i1>, tensor<i1>) -> tensor<i1>
%8 = "tf.Less"(%arg0, %arg1) {device = ""} : (tensor<i32>, tensor<i32>) -> tensor<i1>
%9 = "tf.LogicalAnd"(%8, %7) {device = ""} : (tensor<i1>, tensor<i1>) -> tensor<i1>
%10 = "tf.Identity"(%9) {device = ""} : (tensor<i1>) -> tensor<i1>
return %10 : tensor<i1>
}
}
This is still too verbose and dense to my liking (and for is my preferred loop construct whenever possible), but that will have to be addressed during dialect conversion and is a different problem altogether.
Related
I'm trying to generate Walmart's API WM_SEC.AUTH_SIGNATURE header.
I found a lot of examples in Ruby and Python, but no examples in Elixir. I've been trying to create one and try it out.
Here's what I attempted.
# mix.exs
{:ex_crypto, git: "https://github.com/ntrepid8/ex_crypto.git", branch: "master"}
def scrape_store_item(store_item) do
consumer_id = "my-consumer-id"
private_key_version = "1"
private_key_password = "my-private-key-password"
private_key =
Application.app_dir(:my_app, "priv/keys/walmart/WM_IO_private_key.pem")
|> ExPublicKey.load!(private_key_password)
timestamp = DateTime.utc_now() |> DateTime.to_unix()
url = "https://developer.api.walmart.com/api-proxy/service/affil/product/v2/taxonomy"
message = "#{consumer_id}\n#{timestamp}\n#{private_key_version}\n"
encoded_message = Base.encode64(message)
{:ok, auth_signature} = ExPublicKey.sign(encoded_message, private_key)
auth_signature = Base.encode64(auth_signature)
middleware = [
{Tesla.Middleware.BaseUrl,
"https://developer.api.walmart.com/api-proxy/service/affil/product/v2"},
{Tesla.Middleware.Headers,
[
{"WM_CONSUMER.ID", consumer_id},
{"WM_CONSUMER.INTIMESTAMP", timestamp},
{"WM_SEC.KEY_VERSION", private_key_version},
{"WM_SEC.AUTH_SIGNATURE", auth_signature},
{"WM_SHOW_REASON_CODES", "ALL"},
{"Content-Type", "application/json"}
]}
]
client = Tesla.client(middleware)
{:ok, response} = Tesla.get(client, "/taxonomy") |> IO.inspect()
IO.inspect(response.body)
end
I get a 401 response with this code:
{:ok,
%Tesla.Env{
__client__: %Tesla.Client{
adapter: nil,
fun: nil,
post: [],
pre: [
{Tesla.Middleware.BaseUrl, :call,
["https://developer.api.walmart.com/api-proxy/service/affil/product/v2"]},
{Tesla.Middleware.Headers, :call,
[
[
{"WM_CONSUMER.ID", "my-consumer-id"},
{"WM_CONSUMER.INTIMESTAMP", 1654443660},
{"WM_SEC.KEY_VERSION", "1"},
{"WM_SEC.AUTH_SIGNATURE",
"kdXG+e6R/n+8pH1ha1WKnzLrAHbUqmJsZfN9nOIyOzp6gsHAH7/VrX0K477cdzAq/v7YLpNJXZug3Yt6WTZoP17sZhz6Dig1BK1gg+EZqVqRaF3VJdRwBKlVgBO31s634xL7M8kPhXK11CsMxG8/9xjTGn2cDKEZ9aLeq15ECIfYa5tVtCdTcjNS4u6a7npByU9PIFp9a7n3h1KbW9C/9EA05kTuC1N0oS8nBlnKbA2+C0UW9EAvN4MaIkG0SqOqf/uEHn9BteAv8hI0Ayyny9RpJQmfZEpZ0G3htA7t1pWTzwxUsIJrF/5D1gV+IIYR7OiwHUg2RsIrnPohbznPQw=="}
]
]}
]
},
__module__: Tesla,
body: <<31, 139, 8, 0, 0, 9, 110, 136, 0, 255, 68, 204, 65, 138, 131, 64, 16,
70, 225, 171, 20, 255, 122, 70, 156, 25, 199, 69, 175, 115, 132, 236, 67,
97, 151, 177, 192, 110, 155, 174, 210, 4, 196, 187, 135, ...>>,
headers: [
{"content-encoding", "gzip"},
{"content-type", "application/json;charset=utf-8"},
{"last-modified", "Sun, 05 Jun 2022 15:41:00 GMT"},
{"strict-transport-security", "max-age=86400"},
{"wm_svc.env", "prod"},
{"wm_svc.name", "affil-product"},
{"wm_svc.version", "2.0.0"},
{"x-lua-strict-transport-security", "max-age=86400"},
{"x-tb", "1"},
{"x-tb-optimization-total-bytes-saved", "0"},
{"date", "Sun, 05 Jun 2022 15:41:00 GMT"},
{"connection", "close"},
{"set-cookie",
"TS01a35e2a=01c5a4e2f95f0b472a3a7606aa7c7c33653874c13d636655443ecbca84d23369b19bc1de1973ac24c93ff1f24512e7af49264d46c6; Path=/; Secure"}
],
method: :get,
opts: [],
query: [],
status: 401,
url: "https://developer.api.walmart.com/api-proxy/service/affil/product/v2/taxonomy"
}}
Here's the example code someone shared for a working Ruby version.
version = 'YOUR VERSION'
consumer_id = "YOUR CONSUMER ID"
time_stamp = (Time.now.to_i * 1000).to_s
p_key = "YOUR PRIVATE KEY"
digest = OpenSSL::Digest.new('sha256')
data = consumer_id + "\n" + time_stamp + "\n" + version + "\n"
k = OpenSSL::PKey::RSA.new(p_key.to_s)
digest = OpenSSL::Digest::SHA256.new
signature = k.sign(digest,data)
signature = Base64.strict_encode64(signature)
headers = {
"WM_SEC.KEY_VERSION": version,
"WM_CONSUMER.ID": consumer_id,
"WM_CONSUMER.INTIMESTAMP": time_stamp,
"WM_SEC.AUTH_SIGNATURE": signature
}
puts HTTParty.get("https://developer.api.walmart.com/api-proxy/service/affil/product/v2/taxonomy", headers: headers).parsed_response
Here's a script that does it without ex_crypto. Nice challenge, those Wallmart docs are terrible.
Mix.install([:tesla])
key_version = System.fetch_env!("WALLMART_KEY_VERSION")
consumer_id = System.fetch_env!("WALLMART_CONSUMER_ID")
private_key_pem = File.read!("WM_IO_private_key.pem")
[pem_entry] = :public_key.pem_decode(private_key_pem)
private_key = :public_key.pem_entry_decode(pem_entry)
timestamp = System.os_time(:millisecond)
auth_signature =
"#{consumer_id}\n#{timestamp}\n#{key_version}\n"
|> :public_key.sign(:sha256, private_key)
|> Base.encode64()
url = "https://developer.api.walmart.com/api-proxy/service/affil/product/v2/taxonomy"
headers = [
{"WM_CONSUMER.ID", consumer_id},
{"WM_CONSUMER.INTIMESTAMP", timestamp},
{"WM_SEC.KEY_VERSION", key_version},
{"WM_SEC.AUTH_SIGNATURE", auth_signature}
]
{:ok, %{body: body}} = Tesla.get(url, headers: headers)
IO.puts(body)
Output:
{"categories":[{"id":"0","name":"Home Page","path":"Home Page",...
Here's how you generate WM_SEC.AUTH_SIGNATURE in Elixir:
Make sure you have ex_crypto package installed from master branch since the latest version has necessary changes but is not published.
{:ex_crypto, git: "https://github.com/ntrepid8/ex_crypto.git", branch: "master"}
Then here's the solution:
version = "1"
consumer_id = "my-consumer-id"
timestamp = DateTime.utc_now() |> DateTime.to_unix(:millisecond)
data = "#{consumer_id}\n#{timestamp}\n#{version}\n"
private_key =
Application.app_dir(:my_app, "priv/keys/walmart/WM_IO_private_key.pem")
|> ExPublicKey.load!()
{:ok, auth_signature} = ExPublicKey.sign(data, private_key)
auth_signature = Base.encode64(auth_signature)
middleware = [
{Tesla.Middleware.BaseUrl,
"https://developer.api.walmart.com/api-proxy/service/affil/product/v2"},
{Tesla.Middleware.Headers,
[
{"WM_CONSUMER.ID", consumer_id},
{"WM_CONSUMER.INTIMESTAMP", timestamp},
{"WM_SEC.KEY_VERSION", version},
{"WM_SEC.AUTH_SIGNATURE", auth_signature}
]}
]
client = Tesla.client(middleware)
Tesla.get(client, "/taxonomy")
I am trying to solve a travelling salesman problem with Pyomo framework. However, I am stuck, as the solver is informing me that I have formulated it as infeasible.
import numpy as np
import pyomo.environ as pyo
from pyomo.environ import *
from pyomo.opt import SolverFactory
journey_distances = np.array([[0, 28, 34, 45, 36],
[28, 0, 45, 52, 64],
[34, 45, 0, 11, 34],
[45, 52, 11, 0, 34],
[36, 64, 34, 34, 0]])
# create variables - integers
num_locations = M.shape[0]
model = pyo.ConcreteModel()
model.journeys = pyo.Var(range(num_locations), range(num_locations), domain=pyo.Binary, bounds = (0,None))
journeys = model.journeys
# add A to B constraints
model.AtoB = pyo.ConstraintList()
model.BtoA = pyo.ConstraintList()
AtoB = model.AtoB
BtoA = model.BtoA
AtoB_sum = [sum([ journeys[i,j] for j in range(num_locations) if i!=j]) for i in range(num_locations)]
BtoA_sum = [sum([ journeys[i,j] for i in range(num_locations) if j!=i]) for j in range(num_locations)]
for journey_sum in range(num_locations):
AtoB.add(AtoB_sum[journey_sum] == 1)
if journey_sum <num_locations -1:
BtoA.add(BtoA_sum[journey_sum] == 1)
# add auxilliary variables to ensure that each successive journey ends and starts on the same town. E.g. A to B, then B to C.
# u_j - u_i >= -(n+1) + num_locations*journeys_{ij} for i,j = 1...n, i!=j
model.successive_aux = pyo.Var(range(0,num_locations), domain = pyo.Integers, bounds = (0,num_locations-1))
model.successive_constr = pyo.ConstraintList()
successive_aux = model.successive_aux
successive_constr = model.successive_constr
successive_constr.add(successive_aux[0] == 1)
for i in range(num_locations):
for j in range(num_locations):
if i!=j:
successive_constr.add(successive_aux[j] - successive_aux[i] >= -(num_locations - 1) + num_locations*journeys[i,j])
obj_sum = sum([ sum([journey_distances [i,j]*journeys[i,j] for j in range(num_locations) if i!=j]) for i in range(num_locations)])
model.obj = pyo.Objective(expr = obj_sum, sense = minimize)
opt = SolverFactory('cplex')
opt.solve(model)
journey_res = np.array([model.journeys[journey].value for journey in journeys])
print(journey_res)
# results output is:
print(results)
Problem:
- Lower bound: -inf
Upper bound: inf
Number of objectives: 1
Number of constraints: 31
Number of variables: 26
Number of nonzeros: 98
Sense: unknown
Solver:
- Status: ok
User time: 0.02
Termination condition: infeasible
Termination message: MIP - Integer infeasible.
Error rc: 0
Time: 0.10198116302490234
# model.pprint()
7 Set Declarations
AtoB_index : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 5 : {1, 2, 3, 4, 5}
BtoA_index : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 4 : {1, 2, 3, 4}
journeys_index : Size=1, Index=None, Ordered=False
Key : Dimen : Domain : Size : Members
None : 2 : journeys_index_0*journeys_index_1 : 25 : {(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (4, 0), (4, 1), (4, 2), (4, 3), (4, 4)}
journeys_index_0 : Size=1, Index=None, Ordered=False
Key : Dimen : Domain : Size : Members
None : 1 : Any : 5 : {0, 1, 2, 3, 4}
journeys_index_1 : Size=1, Index=None, Ordered=False
Key : Dimen : Domain : Size : Members
None : 1 : Any : 5 : {0, 1, 2, 3, 4}
successive_aux_index : Size=1, Index=None, Ordered=False
Key : Dimen : Domain : Size : Members
None : 1 : Any : 5 : {0, 1, 2, 3, 4}
successive_constr_index : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 21 : {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21}
2 Var Declarations
journeys : Size=25, Index=journeys_index
Key : Lower : Value : Upper : Fixed : Stale : Domain
(0, 0) : 0 : None : 1 : False : True : Binary
(0, 1) : 0 : None : 1 : False : True : Binary
(0, 2) : 0 : None : 1 : False : True : Binary
(0, 3) : 0 : None : 1 : False : True : Binary
(0, 4) : 0 : None : 1 : False : True : Binary
(1, 0) : 0 : None : 1 : False : True : Binary
(1, 1) : 0 : None : 1 : False : True : Binary
(1, 2) : 0 : None : 1 : False : True : Binary
(1, 3) : 0 : None : 1 : False : True : Binary
(1, 4) : 0 : None : 1 : False : True : Binary
(2, 0) : 0 : None : 1 : False : True : Binary
(2, 1) : 0 : None : 1 : False : True : Binary
(2, 2) : 0 : None : 1 : False : True : Binary
(2, 3) : 0 : None : 1 : False : True : Binary
(2, 4) : 0 : None : 1 : False : True : Binary
(3, 0) : 0 : None : 1 : False : True : Binary
(3, 1) : 0 : None : 1 : False : True : Binary
(3, 2) : 0 : None : 1 : False : True : Binary
(3, 3) : 0 : None : 1 : False : True : Binary
(3, 4) : 0 : None : 1 : False : True : Binary
(4, 0) : 0 : None : 1 : False : True : Binary
(4, 1) : 0 : None : 1 : False : True : Binary
(4, 2) : 0 : None : 1 : False : True : Binary
(4, 3) : 0 : None : 1 : False : True : Binary
(4, 4) : 0 : None : 1 : False : True : Binary
successive_aux : Size=5, Index=successive_aux_index
Key : Lower : Value : Upper : Fixed : Stale : Domain
0 : 0 : None : 4 : False : True : Integers
1 : 0 : None : 4 : False : True : Integers
2 : 0 : None : 4 : False : True : Integers
3 : 0 : None : 4 : False : True : Integers
4 : 0 : None : 4 : False : True : Integers
1 Objective Declarations
obj : Size=1, Index=None, Active=True
Key : Active : Sense : Expression
None : True : minimize : 28*journeys[0,1] + 34*journeys[0,2] + 45*journeys[0,3] + 36*journeys[0,4] + 28*journeys[1,0] + 45*journeys[1,2] + 52*journeys[1,3] + 64*journeys[1,4] + 34*journeys[2,0] + 45*journeys[2,1] + 11*journeys[2,3] + 34*journeys[2,4] + 45*journeys[3,0] + 52*journeys[3,1] + 11*journeys[3,2] + 34*journeys[3,4] + 36*journeys[4,0] + 64*journeys[4,1] + 34*journeys[4,2] + 34*journeys[4,3]
3 Constraint Declarations
AtoB : Size=5, Index=AtoB_index, Active=True
Key : Lower : Body : Upper : Active
1 : 1.0 : journeys[0,1] + journeys[0,2] + journeys[0,3] + journeys[0,4] : 1.0 : True
2 : 1.0 : journeys[1,0] + journeys[1,2] + journeys[1,3] + journeys[1,4] : 1.0 : True
3 : 1.0 : journeys[2,0] + journeys[2,1] + journeys[2,3] + journeys[2,4] : 1.0 : True
4 : 1.0 : journeys[3,0] + journeys[3,1] + journeys[3,2] + journeys[3,4] : 1.0 : True
5 : 1.0 : journeys[4,0] + journeys[4,1] + journeys[4,2] + journeys[4,3] : 1.0 : True
BtoA : Size=4, Index=BtoA_index, Active=True
Key : Lower : Body : Upper : Active
1 : 1.0 : journeys[1,0] + journeys[2,0] + journeys[3,0] + journeys[4,0] : 1.0 : True
2 : 1.0 : journeys[0,1] + journeys[2,1] + journeys[3,1] + journeys[4,1] : 1.0 : True
3 : 1.0 : journeys[0,2] + journeys[1,2] + journeys[3,2] + journeys[4,2] : 1.0 : True
4 : 1.0 : journeys[0,3] + journeys[1,3] + journeys[2,3] + journeys[4,3] : 1.0 : True
successive_constr : Size=21, Index=successive_constr_index, Active=True
Key : Lower : Body : Upper : Active
1 : 1.0 : successive_aux[0] : 1.0 : True
2 : -Inf : -4 + 5*journeys[0,1] - (successive_aux[1] - successive_aux[0]) : 0.0 : True
3 : -Inf : -4 + 5*journeys[0,2] - (successive_aux[2] - successive_aux[0]) : 0.0 : True
4 : -Inf : -4 + 5*journeys[0,3] - (successive_aux[3] - successive_aux[0]) : 0.0 : True
5 : -Inf : -4 + 5*journeys[0,4] - (successive_aux[4] - successive_aux[0]) : 0.0 : True
6 : -Inf : -4 + 5*journeys[1,0] - (successive_aux[0] - successive_aux[1]) : 0.0 : True
7 : -Inf : -4 + 5*journeys[1,2] - (successive_aux[2] - successive_aux[1]) : 0.0 : True
8 : -Inf : -4 + 5*journeys[1,3] - (successive_aux[3] - successive_aux[1]) : 0.0 : True
9 : -Inf : -4 + 5*journeys[1,4] - (successive_aux[4] - successive_aux[1]) : 0.0 : True
10 : -Inf : -4 + 5*journeys[2,0] - (successive_aux[0] - successive_aux[2]) : 0.0 : True
11 : -Inf : -4 + 5*journeys[2,1] - (successive_aux[1] - successive_aux[2]) : 0.0 : True
12 : -Inf : -4 + 5*journeys[2,3] - (successive_aux[3] - successive_aux[2]) : 0.0 : True
13 : -Inf : -4 + 5*journeys[2,4] - (successive_aux[4] - successive_aux[2]) : 0.0 : True
14 : -Inf : -4 + 5*journeys[3,0] - (successive_aux[0] - successive_aux[3]) : 0.0 : True
15 : -Inf : -4 + 5*journeys[3,1] - (successive_aux[1] - successive_aux[3]) : 0.0 : True
16 : -Inf : -4 + 5*journeys[3,2] - (successive_aux[2] - successive_aux[3]) : 0.0 : True
17 : -Inf : -4 + 5*journeys[3,4] - (successive_aux[4] - successive_aux[3]) : 0.0 : True
18 : -Inf : -4 + 5*journeys[4,0] - (successive_aux[0] - successive_aux[4]) : 0.0 : True
19 : -Inf : -4 + 5*journeys[4,1] - (successive_aux[1] - successive_aux[4]) : 0.0 : True
20 : -Inf : -4 + 5*journeys[4,2] - (successive_aux[2] - successive_aux[4]) : 0.0 : True
21 : -Inf : -4 + 5*journeys[4,3] - (successive_aux[3] - successive_aux[4]) : 0.0 : True
13 Declarations: journeys_index_0 journeys_index_1 journeys_index journeys AtoB_index AtoB BtoA_index BtoA successive_aux_index successive_aux successive_constr_index successive_constr obj
If anyone can see what the problem is, and let me know, then that would be a great help.
I'm not overly familiar w/ coding TSP problems, and I'm not sure of all the details in your code, but this (below) is a problem. It seems you are coding successive_aux (call it sa for short) as a sequencing of integers. In this snippet (I chopped down to 3 points), if you think about the legal route of 0-1-2-0, sa_1 > sa_0 and sa_2 > sa_1, then it is infeasible to require sa_0 > sa_2. Also, your bounds on sa appear infeasible as well. In this example, sa_0 is 1, and the upper bound on sa is 2. Those are 2 "infeasibilities" in your formulation.
Key : Lower : Body : Upper : Active
1 : 1.0 : successive_aux[0] : 1.0 : True
2 : -Inf : -2 + 3*journeys[0,1] - (successive_aux[1] - successive_aux[0]) : 0.0 : True
3 : -Inf : -2 + 3*journeys[0,2] - (successive_aux[2] - successive_aux[0]) : 0.0 : True
4 : -Inf : -2 + 3*journeys[1,0] - (successive_aux[0] - successive_aux[1]) : 0.0 : True
5 : -Inf : -2 + 3*journeys[1,2] - (successive_aux[2] - successive_aux[1]) : 0.0 : True
6 : -Inf : -2 + 3*journeys[2,0] - (successive_aux[0] - successive_aux[2]) : 0.0 : True
7 : -Inf : -2 + 3*journeys[2,1] - (successive_aux[1] - successive_aux[2]) : 0.0 : True
I'm not an optimization expert but it looks like you need to change the distances between the cities since you're basically saying that the distance from city1 to city1 = 0, city2 to city2 = 0 etc. If you change these distances to a very large number (say 1000000) the optimizer will never pick to go from city1 back to city1.
Hope this helps.
I am new to TradingView Pine scripting. I am working on some study/strategy but currently seeking for help with a pine script which is on version 2 right now but I am trying convert it into Version 4 and is having so many compilation errors.
Below is the complete script I am trying to convert from V2 to V2 and error I am facing.
Script
//#version=4
//Trend Trading Study by MSM *Sanjay.r* Trend Trading Indicator
study("MystockMoney Trend Trading Tool 1.0", overlay=true)
res = input(title="Main MSM Time Frame", type=resolution, defval="120")
Factor=input(1, minval=1,maxval = 100)
Pd=input(1, minval=1,maxval = 100)
tp = input(500,title="Take Profit")
sl = input(200,title="Stop Loss")
//Plots VWAP and MVWAP for intraday trading. Useful to avoid whipsaws
//study("VWAP MVWAP with pivot points", overlay = true)
avlen = input(50)
color1 = blue
color2 = black
mvwap = ema(vwap,avlen)
plot(vwap,linewidth = 2,style = circles, color = color2)
plot(mvwap,color= color1)
Up=hl2-(Factor*atr(Pd))
Dn=hl2+(Factor*atr(Pd))
MUp=security(tickerid,res,hl2-(Factor*atr(Pd)))
MDn=security(tickerid,res,hl2+(Factor*atr(Pd)))
Mclose=security(tickerid,res,close)
TrendUp=close[1]>TrendUp[1]? max(Up,TrendUp[1]) : Up
TrendDown=close[1]<TrendDown[1]? min(Dn,TrendDown[1]) : Dn
MTrendUp=Mclose[1]>MTrendUp[1]? max(MUp,MTrendUp[1]) : MUp
MTrendDown=Mclose[1]<MTrendDown[1]? min(MDn,MTrendDown[1]) : MDn
Trend = close > TrendDown[1] ? 1: close< TrendUp[1]? -1: nz(Trend[1],1)
Tsl = Trend==1? TrendUp: TrendDown
MTrend = Mclose > MTrendDown[1] ? 1: Mclose< MTrendUp[1]? -1: nz(MTrend[1],1)
MTsl = MTrend==1? MTrendUp: MTrendDown
linecolor = Trend == 1 ? green : red
plot(Tsl, color = linecolor , style = line , linewidth = 2,title = "MSM")
Mlinecolor = MTrend == 1 ? blue : orange
plot(MTsl, color = Mlinecolor , style = line , linewidth = 2,title = "Main MSM")
plotshape(cross(close,Tsl) and close>Tsl , "Up Arrow", shape.triangleup,location.belowbar,green,0,0)
plotshape(cross(Tsl,close) and close<Tsl , "Down Arrow", shape.triangledown , location.abovebar, red,0,0)
up = Trend == 1 and Trend[1] == -1 and MTrend == 1
down = Trend == -1 and Trend[1] == 1 and MTrend == -1
plotarrow(up ? Trend : na, title="Up Entry Arrow", colorup=lime, maxheight=60, minheight=50, transp=0)
plotarrow(down ? Trend : na, title="Down Entry Arrow", colordown=red, maxheight=60, minheight=50, transp=0)
golong = Trend == 1 and Trend[1] == -1 and MTrend == 1
goshort = Trend == -1 and Trend[1] == 1 and MTrend == -1
length=input(21, "length", minval=1)
avrg=sma(volume,length)
vold1 = volume > avrg*1.5 and close<open
vold2 = volume >= avrg*0.5 and volume<=avrg*1.5 and close<open
vold3 = volume < avrg *0.5 and close<open
volu1 = volume > avrg*1.5 and close>open
volu2 = volume >= avrg*0.5 and volume<=avrg*1.5 and close>open
volu3 = volume< avrg*0.5 and close>open
cold1=#800000
cold2=#FF0000
cold3=orange
colu1=#006400
colu2=lime
colu3=#7FFFD4
color = vold1 ? cold1 : vold2 ? cold2 : vold3 ? cold3 : volu1 ? colu1 : volu2 ? colu2 : volu3 ? colu3 : na
barcolor(color)
//Code merged for another indicator
sd = input(true, title="Show Daily Pivots?")
//Pivot Range Calculations - Mark Fisher
pivot = (high + low + close ) / 3.0
bc = (high + low ) / 2.0
tc = (pivot - bc) + pivot
r1 = (pivot * 2) - low
s1 = (pivot * 2) - high
r2 = pivot + (high - low)
s2 = pivot - (high - low)
r3 = r1 + (high - low)
s3 = s1 - (high - low)
r4 = r3 + (r2 - r1)
s4 = s3 - (s1 - s2)
//Daily Pivot Range
dtime_pivot = security(tickerid, 'D', pivot[1])
dtime_bc = security(tickerid, 'D', bc[1])
dtime_tc = security(tickerid, 'D', tc[1])
dtime_r1 = security(tickerid, 'D', r1[1])
dtime_r2 = security(tickerid, 'D', r2[1])
dtime_r3 = security(tickerid, 'D', r3[1])
dtime_r4 = security(tickerid, 'D', r4[1])
dtime_s1 = security(tickerid, 'D', s1[1])
dtime_s2 = security(tickerid, 'D', s2[1])
dtime_s3 = security(tickerid, 'D', s3[1])
dtime_s4 = security(tickerid, 'D', s4[1])
offs_daily = 0
plot(sd and dtime_pivot ? dtime_pivot : na, title="Daily Pivot",style=circles, color=blue,linewidth=3)
plot(sd and dtime_bc ? dtime_bc : na, title="Daily BC",style=circles, color=blue,linewidth=3)
plot(sd and dtime_tc ? dtime_tc : na, title="Daily TC",style=circles, color=blue,linewidth=3)
plot(sd and dtime_r1 ? dtime_r1 : na, title="Daily r1",style=circles, color=green,linewidth=3)
plot(sd and dtime_s1 ? dtime_s1 : na, title="Daily s1",style=circles, color=red,linewidth=3)
Errors after compiling above script
Processing script...
line 5: Undeclared identifier 'resolution';
line 18: Undeclared identifier 'blue';
line 19: Undeclared identifier 'black';
line 21: Undeclared identifier 'circles';
line 21: Undeclared identifier 'color2';
line 22: Undeclared identifier 'color1';
line 26: Undeclared identifier 'res';
line 27: Undeclared identifier 'res';
line 29: Undeclared identifier 'res';
line 31: Undeclared identifier 'TrendUp';
line 32: Undeclared identifier 'TrendDown';
line 34: Undeclared identifier 'Mclose';
line 34: Undeclared identifier 'MTrendUp';
line 34: Undeclared identifier 'MUp';
line 35: Undeclared identifier 'Mclose';
line 35: Undeclared identifier 'MTrendDown';
line 35: Undeclared identifier 'MDn';
line 37: Undeclared identifier 'TrendDown';
line 37: Undeclared identifier 'TrendUp';
line 37: Undeclared identifier 'Trend';
line 38: Undeclared identifier 'Trend';
line 38: Undeclared identifier 'TrendUp';
line 38: Undeclared identifier 'TrendDown';
line 40: Undeclared identifier 'Mclose';
line 40: Undeclared identifier 'MTrendDown';
line 40: Undeclared identifier 'MTrendUp';
line 40: Undeclared identifier 'MTrend';
line 41: Undeclared identifier 'MTrend';
line 41: Undeclared identifier 'MTrendUp';
line 41: Undeclared identifier 'MTrendDown';
line 43: Undeclared identifier 'Trend';
line 43: Undeclared identifier 'green';
line 43: Undeclared identifier 'red';
line 44: Undeclared identifier 'Tsl';
line 44: Undeclared identifier 'linecolor';
line 44: Undeclared identifier 'line';
line 46: Undeclared identifier 'MTrend';
line 46: Undeclared identifier 'blue';
line 46: Undeclared identifier 'orange';
line 47: Undeclared identifier 'MTsl';
line 47: Undeclared identifier 'Mlinecolor';
line 47: Undeclared identifier 'line';
line 49: Undeclared identifier 'Tsl';
line 49: Undeclared identifier 'green';
line 50: Undeclared identifier 'Tsl';
line 50: Undeclared identifier 'red';
line 52: Undeclared identifier 'Trend';
line 52: Undeclared identifier 'MTrend';
line 53: Undeclared identifier 'Trend';
line 53: Undeclared identifier 'MTrend';
line 54: Undeclared identifier 'up';
line 54: Undeclared identifier 'Trend';
line 54: Undeclared identifier 'lime';
line 55: Undeclared identifier 'down';
line 55: Undeclared identifier 'Trend';
line 55: Undeclared identifier 'red';
line 58: Undeclared identifier 'Trend';
line 58: Undeclared identifier 'MTrend';
line 59: Undeclared identifier 'Trend';
line 59: Undeclared identifier 'MTrend';
line 76: Undeclared identifier 'orange';
line 80: Undeclared identifier 'lime';
line 84: Undeclared identifier 'cold3';
line 84: Undeclared identifier 'colu2';
line 86: Undeclared identifier 'color';
line 105: Cannot call 'security' with arguments (const integer, literal string, series[float]); available overloads: security(string, string, series[float], const bool, const bool, string) => series[float]; security(string, string, series[integer], const bool, const bool, string) => series[integer]; security(string, string, series[bool], const bool, const bool, string) => series[bool]; security(string, string, series[color], const bool, const bool, string) => series[color]; security(string, string, <arg_expr_type>, const bool, const bool, string) => <arg_expr_type>;
line 106: Cannot call 'security' with arguments (const integer, literal string, series[float]); available overloads: security(string, string, series[float], const bool, const bool, string) => series[float]; security(string, string, series[integer], const bool, const bool, string) => series[integer]; security(string, string, series[bool], const bool, const bool, string) => series[bool]; security(string, string, series[color], const bool, const bool, string) => series[color]; security(string, string, <arg_expr_type>, const bool, const bool, string) => <arg_expr_type>;
line 107: Cannot call 'security' with arguments (const integer, literal string, series[float]); available overloads: security(string, string, series[float], const bool, const bool, string) => series[float]; security(string, string, series[integer], const bool, const bool, string) => series[integer]; security(string, string, series[bool], const bool, const bool, string) => series[bool]; security(string, string, series[color], const bool, const bool, string) => series[color]; security(string, string, <arg_expr_type>, const bool, const bool, string) => <arg_expr_type>;
line 108: Cannot call 'security' with arguments (const integer, literal string, series[float]); available overloads: security(string, string, series[float], const bool, const bool, string) => series[float]; security(string, string, series[integer], const bool, const bool, string) => series[integer]; security(string, string, series[bool], const bool, const bool, string) => series[bool]; security(string, string, series[color], const bool, const bool, string) => series[color]; security(string, string, <arg_expr_type>, const bool, const bool, string) => <arg_expr_type>;
line 109: Cannot call 'security' with arguments (const integer, literal string, series[float]); available overloads: security(string, string, series[float], const bool, const bool, string) => series[float]; security(string, string, series[integer], const bool, const bool, string) => series[integer]; security(string, string, series[bool], const bool, const bool, string) => series[bool]; security(string, string, series[color], const bool, const bool, string) => series[color]; security(string, string, <arg_expr_type>, const bool, const bool, string) => <arg_expr_type>;
line 110: Cannot call 'security' with arguments (const integer, literal string, series[float]); available overloads: security(string, string, series[float], const bool, const bool, string) => series[float]; security(string, string, series[integer], const bool, const bool, string) => series[integer]; security(string, string, series[bool], const bool, const bool, string) => series[bool]; security(string, string, series[color], const bool, const bool, string) => series[color]; security(string, string, <arg_expr_type>, const bool, const bool, string) => <arg_expr_type>;
line 111: Cannot call 'security' with arguments (const integer, literal string, series[float]); available overloads: security(string, string, series[float], const bool, const bool, string) => series[float]; security(string, string, series[integer], const bool, const bool, string) => series[integer]; security(string, string, series[bool], const bool, const bool, string) => series[bool]; security(string, string, series[color], const bool, const bool, string) => series[color]; security(string, string, <arg_expr_type>, const bool, const bool, string) => <arg_expr_type>;
line 112: Cannot call 'security' with arguments (const integer, literal string, series[float]); available overloads: security(string, string, series[float], const bool, const bool, string) => series[float]; security(string, string, series[integer], const bool, const bool, string) => series[integer]; security(string, string, series[bool], const bool, const bool, string) => series[bool]; security(string, string, series[color], const bool, const bool, string) => series[color]; security(string, string, <arg_expr_type>, const bool, const bool, string) => <arg_expr_type>;
line 113: Cannot call 'security' with arguments (const integer, literal string, series[float]); available overloads: security(string, string, series[float], const bool, const bool, string) => series[float]; security(string, string, series[integer], const bool, const bool, string) => series[integer]; security(string, string, series[bool], const bool, const bool, string) => series[bool]; security(string, string, series[color], const bool, const bool, string) => series[color]; security(string, string, <arg_expr_type>, const bool, const bool, string) => <arg_expr_type>;
line 114: Cannot call 'security' with arguments (const integer, literal string, series[float]); available overloads: security(string, string, series[float], const bool, const bool, string) => series[float]; security(string, string, series[integer], const bool, const bool, string) => series[integer]; security(string, string, series[bool], const bool, const bool, string) => series[bool]; security(string, string, series[color], const bool, const bool, string) => series[color]; security(string, string, <arg_expr_type>, const bool, const bool, string) => <arg_expr_type>;
line 115: Cannot call 'security' with arguments (const integer, literal string, series[float]); available overloads: security(string, string, series[float], const bool, const bool, string) => series[float]; security(string, string, series[integer], const bool, const bool, string) => series[integer]; security(string, string, series[bool], const bool, const bool, string) => series[bool]; security(string, string, series[color], const bool, const bool, string) => series[color]; security(string, string, <arg_expr_type>, const bool, const bool, string) => <arg_expr_type>;
line 119: Undeclared identifier 'dtime_pivot';
line 119: Undeclared identifier 'circles';
line 119: Undeclared identifier 'blue';
line 120: Undeclared identifier 'dtime_bc';
line 120: Undeclared identifier 'circles';
line 120: Undeclared identifier 'blue';
line 121: Undeclared identifier 'dtime_tc';
line 121: Undeclared identifier 'circles';
line 121: Undeclared identifier 'blue';
line 122: Undeclared identifier 'dtime_r1';
line 122: Undeclared identifier 'circles';
line 122: Undeclared identifier 'green';
line 123: Undeclared identifier 'dtime_s1';
line 123: Undeclared identifier 'circles';
line 123: Undeclared identifier 'red'
Script 'MystockMoney Trend Trading Tool 1.0' has been saved
Converted to Pine v4
//#version=4
//Trend Trading Study by MSM *Sanjay.r* Trend Trading Indicator
study("MystockMoney Trend Trading Tool 1.0", overlay=true)
res = input(title="Main MSM Time Frame", type=input.resolution, defval="120")
Factor = input(1, minval = 1, maxval = 100)
Pd = input(1, minval = 1, maxval = 100)
tp = input(500, title="Take Profit")
sl = input(200, title="Stop Loss")
avlen = input(50)
var float TrendUp = na
var float TrendDown = na
var float MTrendUp = na
var float MTrendDown = na
var float Trend = na
var float Tsl = na
var float MTrend = na
var float MTsl = na
var color linecolor = na
//Plots VWAP and MVWAP for intraday trading. Useful to avoid whipsaws
//study("VWAP MVWAP with pivot points", overlay = true)
color1 = color.blue
color2 = color.black
mvwap = ema(vwap,avlen)
plot(vwap, linewidth = 2, style = plot.style_circles, color = color2)
plot(mvwap, color= color1)
delta = (Factor*atr(Pd))
Up = hl2 - delta
Dn = hl2 + delta
MUp = security(syminfo.tickerid, res, Up)
MDn = security(syminfo.tickerid, res, Dn)
Mclose = security(syminfo.tickerid, res, close)
TrendUp := close[1]>TrendUp[1]? max(Up,TrendUp[1]) : Up
TrendDown := close[1]<TrendDown[1]? min(Dn,TrendDown[1]) : Dn
MTrendUp := Mclose[1]>MTrendUp[1]? max(MUp,MTrendUp[1]) : MUp
MTrendDown := Mclose[1]<MTrendDown[1]? min(MDn,MTrendDown[1]) : MDn
Trend := close > TrendDown[1] ? 1: close< TrendUp[1]? -1: nz(Trend[1],1)
Tsl := Trend==1? TrendUp: TrendDown
MTrend := Mclose > MTrendDown[1] ? 1: Mclose< MTrendUp[1]? -1: nz(MTrend[1],1)
MTsl := MTrend==1? MTrendUp: MTrendDown
linecolor := Trend == 1 ? color.green : color.red
plot(Tsl, color = linecolor , style = plot.style_line , linewidth = 2, title = "MSM")
Mlinecolor = MTrend == 1 ? color.blue : color.orange
plot(MTsl, color = Mlinecolor , style = plot.style_line , linewidth = 2,title = "Main MSM")
plotshape(cross(close,Tsl) and close>Tsl , "Up Arrow", shape.triangleup,location.belowbar, color.green, 0, 0)
plotshape(cross(Tsl,close) and close<Tsl , "Down Arrow", shape.triangledown , location.abovebar, color.red, 0, 0)
up = Trend == 1 and Trend[1] == -1 and MTrend == 1
down = Trend == -1 and Trend[1] == 1 and MTrend == -1
plotarrow(up ? Trend : na, title="Up Entry Arrow", colorup=color.lime, maxheight=60, minheight=50, transp=0)
plotarrow(down ? Trend : na, title="Down Entry Arrow", colordown=color.red, maxheight=60, minheight=50, transp=0)
golong = up
goshort = down
length = input(21, "length", minval=1)
avrg = sma(volume, length)
vold1 = volume > avrg*1.5 and close < open
vold2 = volume >= avrg*0.5 and volume <= avrg*1.5 and close < open
vold3 = volume < avrg*0.5 and close < open
volu1 = volume > avrg*1.5 and close > open
volu2 = volume >= avrg*0.5 and volume <= avrg*1.5 and close > open
volu3 = volume < avrg*0.5 and close > open
cold1 = #800000
cold2 = #FF0000
cold3 = color.orange
colu1 = #006400
colu2 = color.lime
colu3 = #7FFFD4
bcolor = vold1 ? cold1 : vold2 ? cold2 : vold3 ? cold3 : volu1 ? colu1 : volu2 ? colu2 : volu3 ? colu3 : na
barcolor(bcolor)
//Code merged for another indicator
sd = input(true, title="Show Daily Pivots?")
//Pivot Range Calculations - Mark Fisher
pivot = hlc3
bc = hl2
tc = (pivot - bc) + pivot
r1 = (pivot * 2) - low
s1 = (pivot * 2) - high
r2 = pivot + (high - low)
s2 = pivot - (high - low)
r3 = r1 + (high - low)
s3 = s1 - (high - low)
r4 = r3 + (r2 - r1)
s4 = s3 - (s1 - s2)
//Daily Pivot Range
dtime_pivot = security(syminfo.tickerid, 'D', pivot[1])
dtime_bc = security(syminfo.tickerid, 'D', bc[1])
dtime_tc = security(syminfo.tickerid, 'D', tc[1])
dtime_r1 = security(syminfo.tickerid, 'D', r1[1])
dtime_r2 = security(syminfo.tickerid, 'D', r2[1])
dtime_r3 = security(syminfo.tickerid, 'D', r3[1])
dtime_r4 = security(syminfo.tickerid, 'D', r4[1])
dtime_s1 = security(syminfo.tickerid, 'D', s1[1])
dtime_s2 = security(syminfo.tickerid, 'D', s2[1])
dtime_s3 = security(syminfo.tickerid, 'D', s3[1])
dtime_s4 = security(syminfo.tickerid, 'D', s4[1])
offs_daily = 0
plot(sd and dtime_pivot ? dtime_pivot : na, title="Daily Pivot", style=plot.style_circles, color=color.blue, linewidth=3)
plot(sd and dtime_bc ? dtime_bc : na, title="Daily BC", style=plot.style_circles, color=color.blue, linewidth=3)
plot(sd and dtime_tc ? dtime_tc : na, title="Daily TC", style=plot.style_circles, color=color.blue, linewidth=3)
plot(sd and dtime_r1 ? dtime_r1 : na, title="Daily r1", style=plot.style_circles, color=color.green, linewidth=3)
plot(sd and dtime_s1 ? dtime_s1 : na, title="Daily s1", style=plot.style_circles, color=color.red, linewidth=3)
I am reading about LLVM Code optimization.I tried to apply opt command options on a number of examples but they do not have any effect. For example.Here is a c++ code called deadCode.cpp:
#include<stdio.h>
int square(int x){
return x*x;
}
int main(){
int a=2;
int b=3;
int c=4;
int result =square(a);
printf("%d\n",b);
}
I generated the LLVM IR with clang like this:
clang -emit-llvm -S deadCode.cpp -o deadCodeBefore
and the result file deadCodeBefore content is :
; ModuleID = 'deadCode.cpp'
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
#.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
; Function Attrs: nounwind uwtable
define i32 #_Z6squarei(i32 %x) #0 {
%1 = alloca i32, align 4
store i32 %x, i32* %1, align 4
%2 = load i32, i32* %1, align 4
%3 = load i32, i32* %1, align 4
%4 = mul nsw i32 %2, %3
ret i32 %4
}
; Function Attrs: norecurse uwtable
define i32 #main() #1 {
%a = alloca i32, align 4
%b = alloca i32, align 4
%c = alloca i32, align 4
%result = alloca i32, align 4
store i32 2, i32* %a, align 4
store i32 3, i32* %b, align 4
store i32 4, i32* %c, align 4
%1 = load i32, i32* %a, align 4
%2 = call i32 #_Z6squarei(i32 %1)
store i32 %2, i32* %result, align 4
%3 = load i32, i32* %b, align 4
%4 = call i32 (i8*, ...) #printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* #.str, i32 0, i32 0), i32 %3)
ret i32 0
}
declare i32 #printf(i8*, ...) #2
attributes #0 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { norecurse uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #2 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
!llvm.ident = !{!0}
!0 = !{!"clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)"}
the optimization command I used:
opt -S -adce deadCodeBefore -o deadCodeAfter1
As I read it should remove the call to square function and also the declaration of c variable because they have no effect. But the result is the same. Here is deadCodeAfter1 which is the same as deadCodeBefore:
; ModuleID = 'deadCodeBefore'
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
#.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
; Function Attrs: nounwind uwtable
define i32 #_Z6squarei(i32 %x) #0 {
%1 = alloca i32, align 4
store i32 %x, i32* %1, align 4
%2 = load i32, i32* %1, align 4
%3 = load i32, i32* %1, align 4
%4 = mul nsw i32 %2, %3
ret i32 %4
}
; Function Attrs: norecurse uwtable
define i32 #main() #1 {
%a = alloca i32, align 4
%b = alloca i32, align 4
%c = alloca i32, align 4
%result = alloca i32, align 4
store i32 2, i32* %a, align 4
store i32 3, i32* %b, align 4
store i32 4, i32* %c, align 4
%1 = load i32, i32* %a, align 4
%2 = call i32 #_Z6squarei(i32 %1)
store i32 %2, i32* %result, align 4
%3 = load i32, i32* %b, align 4
%4 = call i32 (i8*, ...) #printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* #.str, i32 0, i32 0), i32 %3)
ret i32 0
}
declare i32 #printf(i8*, ...) #2
attributes #0 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { norecurse uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #2 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
!llvm.ident = !{!0}
!0 = !{!"clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)"}
Because it's doing exactly as it is supposed to do. It checks in the IR if an instruction is being used by some other instruction or not. If not only then it removes it. For example in your code, declaration of variable %a (%a = alloca i32, align 4) is being used in the store instruction store i32 2, i32* %a, align 4
If you had just declare a variable and not assigned any value to it, then adce pass would have eliminated it. You can see that by just declaring a variable like int e; and run the optimization on it.
Usually passes in LLVM are dependent on the output of some other pass in order to be effective. An individual pass on itself might not give you the result that you might have expected it to provide.
I have declared a iVar in a class:
#implementation LLVMIRTest{
NSString* ivarTest;
}
When I check for LLVM IR it shows me:
#OBJC_METH_VAR_NAME_ = private global [9 x i8] c"ivarTest\00", section "__TEXT,__objc_methname,cstring_literals", align 1
#OBJC_METH_VAR_TYPE_ = private global [12 x i8] c"#\22NSString\22\00", section "__TEXT,__objc_methtype,cstring_literals", align 1
I have to ask why it is private global mention in LLVM IR. Why not only private?
This is full Module LLVM IR:
; ModuleID = 'LLVMIRTest.m'
source_filename = "LLVMIRTest.m"
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.12.0"
%struct._objc_cache = type opaque
%struct._class_t = type { %struct._class_t*, %struct._class_t*, %struct._objc_cache*, i8* (i8*, i8*)**, %struct._class_ro_t* }
%struct._class_ro_t = type { i32, i32, i32, i8*, i8*, %struct.__method_list_t*, %struct._objc_protocol_list*, %struct._ivar_list_t*, i8*, %struct._prop_list_t* }
%struct.__method_list_t = type { i32, i32, [0 x %struct._objc_method] }
%struct._objc_method = type { i8*, i8*, i8* }
%struct._objc_protocol_list = type { i64, [0 x %struct._protocol_t*] }
%struct._protocol_t = type { i8*, i8*, %struct._objc_protocol_list*, %struct.__method_list_t*, %struct.__method_list_t*, %struct.__method_list_t*, %struct.__method_list_t*, %struct._prop_list_t*, i32, i32, i8**, i8*, %struct._prop_list_t* }
%struct._ivar_list_t = type { i32, i32, [0 x %struct._ivar_t] }
%struct._ivar_t = type { i64*, i8*, i8*, i32, i32 }
%struct._prop_list_t = type { i32, i32, [0 x %struct._prop_t] }
%struct._prop_t = type { i8*, i8* }
#_objc_empty_cache = external global %struct._objc_cache
#"OBJC_METACLASS_$_NSObject" = external global %struct._class_t
#OBJC_CLASS_NAME_ = private global [11 x i8] c"LLVMIRTest\00", section "__TEXT,__objc_classname,cstring_literals", align 1
#"\01l_OBJC_METACLASS_RO_$_LLVMIRTest" = private global %struct._class_ro_t { i32 1, i32 40, i32 40, i8* null, i8* getelementptr inbounds ([11 x i8], [11 x i8]* #OBJC_CLASS_NAME_, i32 0, i32 0), %struct.__method_list_t* null, %struct._objc_protocol_list* null, %struct._ivar_list_t* null, i8* null, %struct._prop_list_t* null }, section "__DATA, __objc_const", align 8
#"OBJC_METACLASS_$_LLVMIRTest" = global %struct._class_t { %struct._class_t* #"OBJC_METACLASS_$_NSObject", %struct._class_t* #"OBJC_METACLASS_$_NSObject", %struct._objc_cache* #_objc_empty_cache, i8* (i8*, i8*)** null, %struct._class_ro_t* #"\01l_OBJC_METACLASS_RO_$_LLVMIRTest" }, section "__DATA, __objc_data", align 8
#"OBJC_CLASS_$_NSObject" = external global %struct._class_t
#"OBJC_IVAR_$_LLVMIRTest.ivarTest" = hidden global i64 8, section "__DATA, __objc_ivar", align 8
#OBJC_METH_VAR_NAME_ = private global [9 x i8] c"ivarTest\00", section "__TEXT,__objc_methname,cstring_literals", align 1
#OBJC_METH_VAR_TYPE_ = private global [12 x i8] c"#\22NSString\22\00", section "__TEXT,__objc_methtype,cstring_literals", align 1
#"\01l_OBJC_$_INSTANCE_VARIABLES_LLVMIRTest" = private global { i32, i32, [1 x %struct._ivar_t] } { i32 32, i32 1, [1 x %struct._ivar_t] [%struct._ivar_t { i64* #"OBJC_IVAR_$_LLVMIRTest.ivarTest", i8* getelementptr inbounds ([9 x i8], [9 x i8]* #OBJC_METH_VAR_NAME_, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8], [12 x i8]* #OBJC_METH_VAR_TYPE_, i32 0, i32 0), i32 3, i32 8 }] }, section "__DATA, __objc_const", align 8
#"\01l_OBJC_CLASS_RO_$_LLVMIRTest" = private global %struct._class_ro_t { i32 0, i32 8, i32 16, i8* null, i8* getelementptr inbounds ([11 x i8], [11 x i8]* #OBJC_CLASS_NAME_, i32 0, i32 0), %struct.__method_list_t* null, %struct._objc_protocol_list* null, %struct._ivar_list_t* bitcast ({ i32, i32, [1 x %struct._ivar_t] }* #"\01l_OBJC_$_INSTANCE_VARIABLES_LLVMIRTest" to %struct._ivar_list_t*), i8* null, %struct._prop_list_t* null }, section "__DATA, __objc_const", align 8
#"OBJC_CLASS_$_LLVMIRTest" = global %struct._class_t { %struct._class_t* #"OBJC_METACLASS_$_LLVMIRTest", %struct._class_t* #"OBJC_CLASS_$_NSObject", %struct._objc_cache* #_objc_empty_cache, i8* (i8*, i8*)** null, %struct._class_ro_t* #"\01l_OBJC_CLASS_RO_$_LLVMIRTest" }, section "__DATA, __objc_data", align 8
#"OBJC_LABEL_CLASS_$" = private global [1 x i8*] [i8* bitcast (%struct._class_t* #"OBJC_CLASS_$_LLVMIRTest" to i8*)], section "__DATA, __objc_classlist, regular, no_dead_strip", align 8
#llvm.compiler.used = appending global [5 x i8*] [i8* getelementptr inbounds ([11 x i8], [11 x i8]* #OBJC_CLASS_NAME_, i32 0, i32 0), i8* getelementptr inbounds ([9 x i8], [9 x i8]* #OBJC_METH_VAR_NAME_, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8], [12 x i8]* #OBJC_METH_VAR_TYPE_, i32 0, i32 0), i8* bitcast ({ i32, i32, [1 x %struct._ivar_t] }* #"\01l_OBJC_$_INSTANCE_VARIABLES_LLVMIRTest" to i8*), i8* bitcast ([1 x i8*]* #"OBJC_LABEL_CLASS_$" to i8*)], section "llvm.metadata"
!llvm.module.flags = !{!0, !1, !2, !3, !4, !5}
!llvm.ident = !{!6}
!0 = !{i32 1, !"Objective-C Version", i32 2}
!1 = !{i32 1, !"Objective-C Image Info Version", i32 0}
!2 = !{i32 1, !"Objective-C Image Info Section", !"__DATA, __objc_imageinfo, regular, no_dead_strip"}
!3 = !{i32 4, !"Objective-C Garbage Collection", i32 0}
!4 = !{i32 1, !"Objective-C Class Properties", i32 64}
!5 = !{i32 1, !"PIC Level", i32 2}
!6 = !{!"Apple LLVM version 8.0.0 (clang-800.0.38)"}
Global variables are considered module scoped that are initialized at compile time versus runtime.
Most front-ends to LLVM put strings at the module scope and those require a global or a constant tag. There is a way to store strings on the stack instead but that is a rare occurrence in my experience. I typically create strings as
#somename = internal constant....
The private is instructing not to expose the symbols outside of the module.
I assume this is how Objective-C adds type and instrumentation support for classes. If you look at the rest of the output it is likely that the pointers to those strings are getting passed into the RT library (e.g. %x = load ...) prior to some call.
Update after OP added listing
What you've listed is the 'static' module level constructs representing your class. If you look closely, the class declaration consists of a number of embedded structures and strings. Because these declarations are at the module level they are declared global which puts them, as you would expect, in the data segment as it is data after-all and not method implementation. Think of your class as a structure containing not only space for your variable 'iVar` but additional information necessary for the Objective-C RT.
So, classes and their variables are considered module level declarations which are represented as data structures at the module level which is marked global by LLVM standards. See LLVM Global Variable documentation.