diff --git a/README.md b/README.md index 0d84b2a1..eb09467b 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![Python Versions](https://img.shields.io/pypi/pyversions/m2cgen.svg?logo=python&logoColor=white)](https://pypi.org/project/m2cgen) [![PyPI Version](https://img.shields.io/pypi/v/m2cgen.svg?logo=pypi&logoColor=white)](https://pypi.org/project/m2cgen) -**m2cgen** (Model 2 Code Generator) - is a lightweight library which provides an easy way to transpile trained statistical models into a native code (Python, C, Java, Go, JavaScript, Visual Basic). +**m2cgen** (Model 2 Code Generator) - is a lightweight library which provides an easy way to transpile trained statistical models into a native code (Python, C, Java, Go, JavaScript, Visual Basic, C#). * [Installation](#installation) * [Supported Languages](#supported-languages) @@ -26,6 +26,7 @@ pip install m2cgen ## Supported Languages - C +- C# - Go - Java - JavaScript @@ -100,8 +101,8 @@ public class Model { `m2cgen` can be used as a CLI tool to generate code using serialized model objects (pickle protocol): ``` -$ m2cgen --language [--indent ] - [--class_name ] [--module_name ] [--package_name ] +$ m2cgen --language [--indent ] [--class_name ] + [--module_name ] [--package_name ] [--namespace ] [--recursion-limit ] ``` diff --git a/generated_code_examples/c_sharp/classification/decision_tree.cs b/generated_code_examples/c_sharp/classification/decision_tree.cs new file mode 100644 index 00000000..1b1a2e85 --- /dev/null +++ b/generated_code_examples/c_sharp/classification/decision_tree.cs @@ -0,0 +1,25 @@ +namespace ML { + public static class Model { + public static double[] Score(double[] input) { + double[] var0; + if ((input[2]) <= (2.6)) { + var0 = new double[3] {1.0, 0.0, 0.0}; + } else { + if ((input[2]) <= (4.8500004)) { + if ((input[3]) <= (1.6500001)) { + var0 = new double[3] {0.0, 1.0, 0.0}; + } else { + var0 = new double[3] {0.0, 0.3333333333333333, 0.6666666666666666}; + } + } else { + if ((input[3]) <= (1.75)) { + var0 = new double[3] {0.0, 0.42857142857142855, 0.5714285714285714}; + } else { + var0 = new double[3] {0.0, 0.0, 1.0}; + } + } + } + return var0; + } + } +} diff --git a/generated_code_examples/c_sharp/classification/lightgbm.cs b/generated_code_examples/c_sharp/classification/lightgbm.cs new file mode 100644 index 00000000..9da0de3d --- /dev/null +++ b/generated_code_examples/c_sharp/classification/lightgbm.cs @@ -0,0 +1,84 @@ +using static System.Math; +namespace ML { + public static class Model { + public static double[] Score(double[] input) { + double var0; + if ((input[2]) > (1.8)) { + if ((input[2]) > (4.250000000000001)) { + var0 = -1.1736122903444903; + } else { + var0 = -1.1633850173886202; + } + } else { + var0 = -0.9486122853153485; + } + double var1; + if ((input[2]) > (1.8)) { + if ((input[1]) > (3.0500000000000003)) { + var1 = -0.06193194743580539; + } else { + var1 = -0.07237070828653688; + } + } else { + var1 = 0.12984943093573026; + } + double var2; + var2 = Exp(((0) + (var0)) + (var1)); + double var3; + if ((input[2]) > (1.8)) { + if ((input[2]) > (4.8500000000000005)) { + var3 = -1.1807342692411888; + } else { + var3 = -0.9831932134295853; + } + } else { + var3 = -1.1952609652674462; + } + double var4; + if ((input[2]) > (1.8)) { + if ((input[2]) > (4.8500000000000005)) { + var4 = -0.05694282927518771; + } else { + var4 = 0.11960489254350348; + } + } else { + var4 = -0.07151978915296087; + } + double var5; + var5 = Exp(((0) + (var3)) + (var4)); + double var6; + if ((input[2]) > (4.8500000000000005)) { + if ((input[3]) > (1.9500000000000002)) { + var6 = -0.9298942558407184; + } else { + var6 = -0.9632815288936335; + } + } else { + if ((input[2]) > (4.250000000000001)) { + var6 = -1.1322413652523249; + } else { + var6 = -1.1524760761934856; + } + } + double var7; + if ((input[2]) > (4.8500000000000005)) { + if ((input[3]) > (1.9500000000000002)) { + var7 = 0.12809276954555665; + } else { + var7 = 0.09898817876916756; + } + } else { + if ((input[2]) > (4.250000000000001)) { + var7 = -0.052710589717642864; + } else { + var7 = -0.07292857712854424; + } + } + double var8; + var8 = Exp(((0) + (var6)) + (var7)); + double var9; + var9 = ((var2) + (var5)) + (var8); + return new double[3] {(var2) / (var9), (var5) / (var9), (var8) / (var9)}; + } + } +} diff --git a/generated_code_examples/c_sharp/classification/linear.cs b/generated_code_examples/c_sharp/classification/linear.cs new file mode 100644 index 00000000..1e29cfd2 --- /dev/null +++ b/generated_code_examples/c_sharp/classification/linear.cs @@ -0,0 +1,7 @@ +namespace ML { + public static class Model { + public static double[] Score(double[] input) { + return new double[3] {((((0.2614587435880605) + ((input[0]) * (0.42474116053569605))) + ((input[1]) * (1.3963906033045026))) + ((input[2]) * (-2.215054318516674))) + ((input[3]) * (-0.9587396176450289)), ((((1.1348839223808307) + ((input[0]) * (0.2567965976997648))) + ((input[1]) * (-1.3904789369836008))) + ((input[2]) * (0.596683023311173))) + ((input[3]) * (-1.2690022726388828)), ((((-1.2162802012560197) + ((input[0]) * (-1.6357766989177105))) + ((input[1]) * (-1.5040638728422817))) + ((input[2]) * (2.427835933129272))) + ((input[3]) * (2.3469310693367276))}; + } + } +} diff --git a/generated_code_examples/c_sharp/classification/random_forest.cs b/generated_code_examples/c_sharp/classification/random_forest.cs new file mode 100644 index 00000000..811a2be5 --- /dev/null +++ b/generated_code_examples/c_sharp/classification/random_forest.cs @@ -0,0 +1,57 @@ +namespace ML { + public static class Model { + public static double[] Score(double[] input) { + double[] var0; + if ((input[3]) <= (0.8)) { + var0 = new double[3] {1.0, 0.0, 0.0}; + } else { + if ((input[2]) <= (4.8500004)) { + var0 = new double[3] {0.0, 0.9795918367346939, 0.02040816326530612}; + } else { + if ((input[3]) <= (1.75)) { + if ((input[3]) <= (1.6500001)) { + var0 = new double[3] {0.0, 0.25, 0.75}; + } else { + var0 = new double[3] {0.0, 1.0, 0.0}; + } + } else { + var0 = new double[3] {0.0, 0.0, 1.0}; + } + } + } + double[] var1; + if ((input[3]) <= (0.8)) { + var1 = new double[3] {1.0, 0.0, 0.0}; + } else { + if ((input[0]) <= (6.05)) { + if ((input[2]) <= (4.9)) { + var1 = new double[3] {0.0, 0.9032258064516129, 0.0967741935483871}; + } else { + var1 = new double[3] {0.0, 0.0, 1.0}; + } + } else { + if ((input[3]) <= (1.75)) { + var1 = new double[3] {0.0, 0.8, 0.2}; + } else { + var1 = new double[3] {0.0, 0.0, 1.0}; + } + } + } + return AddVectors(MulVectorNumber(var0, 0.5), MulVectorNumber(var1, 0.5)); + } + private static double[] AddVectors(double[] v1, double[] v2) { + double[] result = new double[v1.Length]; + for (int i = 0; i < v1.Length; ++i) { + result[i] = v1[i] + v2[i]; + } + return result; + } + private static double[] MulVectorNumber(double[] v1, double num) { + double[] result = new double[v1.Length]; + for (int i = 0; i < v1.Length; ++i) { + result[i] = v1[i] * num; + } + return result; + } + } +} diff --git a/generated_code_examples/c_sharp/classification/svm.cs b/generated_code_examples/c_sharp/classification/svm.cs new file mode 100644 index 00000000..4b99a802 --- /dev/null +++ b/generated_code_examples/c_sharp/classification/svm.cs @@ -0,0 +1,74 @@ +using static System.Math; +namespace ML { + public static class Model { + public static double[] Score(double[] input) { + double var0; + var0 = (0) - (0.25); + double var1; + var1 = Exp((var0) * ((((Pow((5.4) - (input[0]), 2)) + (Pow((3.0) - (input[1]), 2))) + (Pow((4.5) - (input[2]), 2))) + (Pow((1.5) - (input[3]), 2)))); + double var2; + var2 = Exp((var0) * ((((Pow((6.2) - (input[0]), 2)) + (Pow((2.2) - (input[1]), 2))) + (Pow((4.5) - (input[2]), 2))) + (Pow((1.5) - (input[3]), 2)))); + double var3; + var3 = Exp((var0) * ((((Pow((5.0) - (input[0]), 2)) + (Pow((2.3) - (input[1]), 2))) + (Pow((3.3) - (input[2]), 2))) + (Pow((1.0) - (input[3]), 2)))); + double var4; + var4 = Exp((var0) * ((((Pow((5.9) - (input[0]), 2)) + (Pow((3.2) - (input[1]), 2))) + (Pow((4.8) - (input[2]), 2))) + (Pow((1.8) - (input[3]), 2)))); + double var5; + var5 = Exp((var0) * ((((Pow((5.0) - (input[0]), 2)) + (Pow((2.0) - (input[1]), 2))) + (Pow((3.5) - (input[2]), 2))) + (Pow((1.0) - (input[3]), 2)))); + double var6; + var6 = Exp((var0) * ((((Pow((6.7) - (input[0]), 2)) + (Pow((3.0) - (input[1]), 2))) + (Pow((5.0) - (input[2]), 2))) + (Pow((1.7) - (input[3]), 2)))); + double var7; + var7 = Exp((var0) * ((((Pow((7.0) - (input[0]), 2)) + (Pow((3.2) - (input[1]), 2))) + (Pow((4.7) - (input[2]), 2))) + (Pow((1.4) - (input[3]), 2)))); + double var8; + var8 = Exp((var0) * ((((Pow((4.9) - (input[0]), 2)) + (Pow((2.4) - (input[1]), 2))) + (Pow((3.3) - (input[2]), 2))) + (Pow((1.0) - (input[3]), 2)))); + double var9; + var9 = Exp((var0) * ((((Pow((6.3) - (input[0]), 2)) + (Pow((2.5) - (input[1]), 2))) + (Pow((4.9) - (input[2]), 2))) + (Pow((1.5) - (input[3]), 2)))); + double var10; + var10 = Exp((var0) * ((((Pow((6.0) - (input[0]), 2)) + (Pow((2.7) - (input[1]), 2))) + (Pow((5.1) - (input[2]), 2))) + (Pow((1.6) - (input[3]), 2)))); + double var11; + var11 = Exp((var0) * ((((Pow((5.7) - (input[0]), 2)) + (Pow((2.6) - (input[1]), 2))) + (Pow((3.5) - (input[2]), 2))) + (Pow((1.0) - (input[3]), 2)))); + double var12; + var12 = Exp((var0) * ((((Pow((5.1) - (input[0]), 2)) + (Pow((3.8) - (input[1]), 2))) + (Pow((1.9) - (input[2]), 2))) + (Pow((0.4) - (input[3]), 2)))); + double var13; + var13 = Exp((var0) * ((((Pow((4.4) - (input[0]), 2)) + (Pow((2.9) - (input[1]), 2))) + (Pow((1.4) - (input[2]), 2))) + (Pow((0.2) - (input[3]), 2)))); + double var14; + var14 = Exp((var0) * ((((Pow((5.7) - (input[0]), 2)) + (Pow((4.4) - (input[1]), 2))) + (Pow((1.5) - (input[2]), 2))) + (Pow((0.4) - (input[3]), 2)))); + double var15; + var15 = Exp((var0) * ((((Pow((5.8) - (input[0]), 2)) + (Pow((4.0) - (input[1]), 2))) + (Pow((1.2) - (input[2]), 2))) + (Pow((0.2) - (input[3]), 2)))); + double var16; + var16 = Exp((var0) * ((((Pow((5.1) - (input[0]), 2)) + (Pow((3.3) - (input[1]), 2))) + (Pow((1.7) - (input[2]), 2))) + (Pow((0.5) - (input[3]), 2)))); + double var17; + var17 = Exp((var0) * ((((Pow((5.7) - (input[0]), 2)) + (Pow((3.8) - (input[1]), 2))) + (Pow((1.7) - (input[2]), 2))) + (Pow((0.3) - (input[3]), 2)))); + double var18; + var18 = Exp((var0) * ((((Pow((4.3) - (input[0]), 2)) + (Pow((3.0) - (input[1]), 2))) + (Pow((1.1) - (input[2]), 2))) + (Pow((0.1) - (input[3]), 2)))); + double var19; + var19 = Exp((var0) * ((((Pow((4.5) - (input[0]), 2)) + (Pow((2.3) - (input[1]), 2))) + (Pow((1.3) - (input[2]), 2))) + (Pow((0.3) - (input[3]), 2)))); + double var20; + var20 = Exp((var0) * ((((Pow((6.3) - (input[0]), 2)) + (Pow((2.7) - (input[1]), 2))) + (Pow((4.9) - (input[2]), 2))) + (Pow((1.8) - (input[3]), 2)))); + double var21; + var21 = Exp((var0) * ((((Pow((6.0) - (input[0]), 2)) + (Pow((3.0) - (input[1]), 2))) + (Pow((4.8) - (input[2]), 2))) + (Pow((1.8) - (input[3]), 2)))); + double var22; + var22 = Exp((var0) * ((((Pow((6.3) - (input[0]), 2)) + (Pow((2.8) - (input[1]), 2))) + (Pow((5.1) - (input[2]), 2))) + (Pow((1.5) - (input[3]), 2)))); + double var23; + var23 = Exp((var0) * ((((Pow((5.8) - (input[0]), 2)) + (Pow((2.8) - (input[1]), 2))) + (Pow((5.1) - (input[2]), 2))) + (Pow((2.4) - (input[3]), 2)))); + double var24; + var24 = Exp((var0) * ((((Pow((6.1) - (input[0]), 2)) + (Pow((3.0) - (input[1]), 2))) + (Pow((4.9) - (input[2]), 2))) + (Pow((1.8) - (input[3]), 2)))); + double var25; + var25 = Exp((var0) * ((((Pow((7.7) - (input[0]), 2)) + (Pow((2.6) - (input[1]), 2))) + (Pow((6.9) - (input[2]), 2))) + (Pow((2.3) - (input[3]), 2)))); + double var26; + var26 = Exp((var0) * ((((Pow((6.9) - (input[0]), 2)) + (Pow((3.1) - (input[1]), 2))) + (Pow((5.1) - (input[2]), 2))) + (Pow((2.3) - (input[3]), 2)))); + double var27; + var27 = Exp((var0) * ((((Pow((6.3) - (input[0]), 2)) + (Pow((3.3) - (input[1]), 2))) + (Pow((6.0) - (input[2]), 2))) + (Pow((2.5) - (input[3]), 2)))); + double var28; + var28 = Exp((var0) * ((((Pow((4.9) - (input[0]), 2)) + (Pow((2.5) - (input[1]), 2))) + (Pow((4.5) - (input[2]), 2))) + (Pow((1.7) - (input[3]), 2)))); + double var29; + var29 = Exp((var0) * ((((Pow((6.0) - (input[0]), 2)) + (Pow((2.2) - (input[1]), 2))) + (Pow((5.0) - (input[2]), 2))) + (Pow((1.5) - (input[3]), 2)))); + double var30; + var30 = Exp((var0) * ((((Pow((7.9) - (input[0]), 2)) + (Pow((3.8) - (input[1]), 2))) + (Pow((6.4) - (input[2]), 2))) + (Pow((2.0) - (input[3]), 2)))); + double var31; + var31 = Exp((var0) * ((((Pow((7.2) - (input[0]), 2)) + (Pow((3.0) - (input[1]), 2))) + (Pow((5.8) - (input[2]), 2))) + (Pow((1.6) - (input[3]), 2)))); + double var32; + var32 = Exp((var0) * ((((Pow((7.7) - (input[0]), 2)) + (Pow((3.8) - (input[1]), 2))) + (Pow((6.7) - (input[2]), 2))) + (Pow((2.2) - (input[3]), 2)))); + return new double[3] {(((((((((((((((((((-0.08359187780790468) + ((var1) * (-0.0))) + ((var2) * (-0.0))) + ((var3) * (-0.4393498355605194))) + ((var4) * (-0.009465620856664334))) + ((var5) * (-0.16223369966927))) + ((var6) * (-0.26861888775075243))) + ((var7) * (-0.4393498355605194))) + ((var8) * (-0.4393498355605194))) + ((var9) * (-0.0))) + ((var10) * (-0.0))) + ((var11) * (-0.19673905328606292))) + ((var12) * (0.3340655283922188))) + ((var13) * (0.3435087305152051))) + ((var14) * (0.4393498355605194))) + ((var15) * (0.0))) + ((var16) * (0.28614124535416424))) + ((var17) * (0.11269159286168087))) + ((var18) * (0.0))) + ((var19) * (0.4393498355605194)), (((((((((((((((((((((-0.18563912331454907) + ((var20) * (-0.0))) + ((var21) * (-0.06014273244194299))) + ((var22) * (-0.0))) + ((var23) * (-0.031132453078851926))) + ((var24) * (-0.0))) + ((var25) * (-0.3893079321588921))) + ((var26) * (-0.06738007627290196))) + ((var27) * (-0.1225075748937126))) + ((var28) * (-0.3893079321588921))) + ((var29) * (-0.29402231709614085))) + ((var30) * (-0.3893079321588921))) + ((var31) * (-0.0))) + ((var32) * (-0.028242141062729226))) + ((var12) * (0.16634667752431267))) + ((var13) * (0.047772685163074764))) + ((var14) * (0.3893079321588921))) + ((var15) * (0.3893079321588921))) + ((var16) * (0.0))) + ((var17) * (0.0))) + ((var18) * (0.3893079321588921))) + ((var19) * (0.3893079321588921)), ((((((((((((((((((((((((0.5566649875797668) + ((var20) * (-25.563066587228416))) + ((var21) * (-38.35628154976547))) + ((var22) * (-38.35628154976547))) + ((var23) * (-0.0))) + ((var24) * (-38.35628154976547))) + ((var25) * (-0.0))) + ((var26) * (-0.0))) + ((var27) * (-0.0))) + ((var28) * (-6.2260303727828745))) + ((var29) * (-18.42781911624364))) + ((var30) * (-0.14775026537286423))) + ((var31) * (-7.169755983020096))) + ((var32) * (-0.0))) + ((var1) * (12.612328267927264))) + ((var2) * (6.565812506955159))) + ((var3) * (0.0))) + ((var4) * (38.35628154976547))) + ((var5) * (0.0))) + ((var6) * (38.35628154976547))) + ((var7) * (0.0))) + ((var8) * (0.0))) + ((var9) * (38.35628154976547))) + ((var10) * (38.35628154976547))) + ((var11) * (0.0))}; + } + } +} diff --git a/generated_code_examples/c_sharp/classification/xgboost.cs b/generated_code_examples/c_sharp/classification/xgboost.cs new file mode 100644 index 00000000..f1b8c497 --- /dev/null +++ b/generated_code_examples/c_sharp/classification/xgboost.cs @@ -0,0 +1,76 @@ +using static System.Math; +namespace ML { + public static class Model { + public static double[] Score(double[] input) { + double var0; + if ((input[2]) >= (2.5999999)) { + var0 = -0.0731707439; + } else { + var0 = 0.142857149; + } + double var1; + if ((input[2]) >= (2.5999999)) { + var1 = -0.0705206916; + } else { + var1 = 0.12477719; + } + double var2; + var2 = Exp(((0.5) + (var0)) + (var1)); + double var3; + if ((input[2]) >= (2.5999999)) { + if ((input[2]) >= (4.85000038)) { + var3 = -0.0578680299; + } else { + var3 = 0.132596686; + } + } else { + var3 = -0.0714285821; + } + double var4; + if ((input[2]) >= (2.5999999)) { + if ((input[2]) >= (4.85000038)) { + var4 = -0.0552999265; + } else { + var4 = 0.116139404; + } + } else { + var4 = -0.0687687024; + } + double var5; + var5 = Exp(((0.5) + (var3)) + (var4)); + double var6; + if ((input[2]) >= (4.85000038)) { + if ((input[3]) >= (1.75)) { + var6 = 0.142011836; + } else { + var6 = 0.0405405387; + } + } else { + if ((input[3]) >= (1.6500001)) { + var6 = 0.0428571403; + } else { + var6 = -0.0730659068; + } + } + double var7; + if ((input[2]) >= (4.85000038)) { + if ((input[3]) >= (1.75)) { + var7 = 0.124653697; + } else { + var7 = 0.035562478; + } + } else { + if ((input[3]) >= (1.6500001)) { + var7 = 0.0425687581; + } else { + var7 = -0.0704230517; + } + } + double var8; + var8 = Exp(((0.5) + (var6)) + (var7)); + double var9; + var9 = ((var2) + (var5)) + (var8); + return new double[3] {(var2) / (var9), (var5) / (var9), (var8) / (var9)}; + } + } +} diff --git a/generated_code_examples/c_sharp/regression/decision_tree.cs b/generated_code_examples/c_sharp/regression/decision_tree.cs new file mode 100644 index 00000000..6775b406 --- /dev/null +++ b/generated_code_examples/c_sharp/regression/decision_tree.cs @@ -0,0 +1,25 @@ +namespace ML { + public static class Model { + public static double Score(double[] input) { + double var0; + if ((input[5]) <= (6.941)) { + if ((input[12]) <= (14.395)) { + if ((input[7]) <= (1.43365)) { + var0 = 45.58; + } else { + var0 = 22.865022421524642; + } + } else { + var0 = 14.924358974358983; + } + } else { + if ((input[5]) <= (7.4370003)) { + var0 = 32.09534883720931; + } else { + var0 = 45.275; + } + } + return var0; + } + } +} diff --git a/generated_code_examples/c_sharp/regression/lightgbm.cs b/generated_code_examples/c_sharp/regression/lightgbm.cs new file mode 100644 index 00000000..4758e96e --- /dev/null +++ b/generated_code_examples/c_sharp/regression/lightgbm.cs @@ -0,0 +1,35 @@ +namespace ML { + public static class Model { + public static double Score(double[] input) { + double var0; + if ((input[5]) > (6.8455)) { + if ((input[5]) > (7.437)) { + var0 = 24.906664851995615; + } else { + var0 = 23.513674700555555; + } + } else { + if ((input[12]) > (14.395000000000001)) { + var0 = 21.863487452747595; + } else { + var0 = 22.70305627629392; + } + } + double var1; + if ((input[12]) > (9.63)) { + if ((input[12]) > (19.830000000000002)) { + var1 = -0.9644646678713786; + } else { + var1 = -0.30629733662250097; + } + } else { + if ((input[5]) > (7.437)) { + var1 = 2.0368334157126293; + } else { + var1 = 0.4576204330349962; + } + } + return ((0) + (var0)) + (var1); + } + } +} diff --git a/generated_code_examples/c_sharp/regression/linear.cs b/generated_code_examples/c_sharp/regression/linear.cs new file mode 100644 index 00000000..c032ae74 --- /dev/null +++ b/generated_code_examples/c_sharp/regression/linear.cs @@ -0,0 +1,7 @@ +namespace ML { + public static class Model { + public static double Score(double[] input) { + return (((((((((((((36.006810733650326) + ((input[0]) * (-0.10081655845910407))) + ((input[1]) * (0.04403556956079904))) + ((input[2]) * (0.030804434213336))) + ((input[3]) * (2.9326736094672676))) + ((input[4]) * (-17.09336013214799))) + ((input[5]) * (3.74506822086355))) + ((input[6]) * (0.0033774353698562175))) + ((input[7]) * (-1.4348015681660853))) + ((input[8]) * (0.2901581119428308))) + ((input[9]) * (-0.011463487956327859))) + ((input[10]) * (-0.9500012437313143))) + ((input[11]) * (0.010374330909981067))) + ((input[12]) * (-0.5713890449294768)); + } + } +} diff --git a/generated_code_examples/c_sharp/regression/random_forest.cs b/generated_code_examples/c_sharp/regression/random_forest.cs new file mode 100644 index 00000000..d1db0367 --- /dev/null +++ b/generated_code_examples/c_sharp/regression/random_forest.cs @@ -0,0 +1,43 @@ +namespace ML { + public static class Model { + public static double Score(double[] input) { + double var0; + if ((input[5]) <= (6.92)) { + if ((input[12]) <= (14.3)) { + if ((input[7]) <= (1.47415)) { + var0 = 50.0; + } else { + var0 = 23.203669724770638; + } + } else { + var0 = 15.177333333333326; + } + } else { + if ((input[5]) <= (7.4370003)) { + var0 = 32.92407407407408; + } else { + var0 = 45.04827586206897; + } + } + double var1; + if ((input[12]) <= (9.725)) { + if ((input[5]) <= (7.4525)) { + if ((input[5]) <= (6.7539997)) { + var1 = 24.805; + } else { + var1 = 32.55238095238095; + } + } else { + var1 = 47.88333333333334; + } + } else { + if ((input[12]) <= (15.0)) { + var1 = 20.52100840336134; + } else { + var1 = 14.718709677419358; + } + } + return ((var0) * (0.5)) + ((var1) * (0.5)); + } + } +} diff --git a/generated_code_examples/c_sharp/regression/svm.cs b/generated_code_examples/c_sharp/regression/svm.cs new file mode 100644 index 00000000..b8e43cd8 --- /dev/null +++ b/generated_code_examples/c_sharp/regression/svm.cs @@ -0,0 +1,10 @@ +using static System.Math; +namespace ML { + public static class Model { + public static double Score(double[] input) { + double var0; + var0 = (0) - (0.07692307692307693); + return ((((((((((((((((((((((((((((((((((((((((((((((((((((27.02162490523095) + ((Exp((var0) * (((((((((((((Pow((25.9406) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.679) - (input[4]), 2))) + (Pow((5.304) - (input[5]), 2))) + (Pow((89.1) - (input[6]), 2))) + (Pow((1.6475) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((127.36) - (input[11]), 2))) + (Pow((26.64) - (input[12]), 2))))) * (-0.11849528386764518))) + ((Exp((var0) * (((((((((((((Pow((6.53876) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((1.0) - (input[3]), 2))) + (Pow((0.631) - (input[4]), 2))) + (Pow((7.016) - (input[5]), 2))) + (Pow((97.5) - (input[6]), 2))) + (Pow((1.2024) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((392.05) - (input[11]), 2))) + (Pow((2.96) - (input[12]), 2))))) * (1.0))) + ((Exp((var0) * (((((((((((((Pow((22.5971) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.7) - (input[4]), 2))) + (Pow((5.0) - (input[5]), 2))) + (Pow((89.5) - (input[6]), 2))) + (Pow((1.5184) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((396.9) - (input[11]), 2))) + (Pow((31.99) - (input[12]), 2))))) * (-1.0))) + ((Exp((var0) * (((((((((((((Pow((45.7461) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.693) - (input[4]), 2))) + (Pow((4.519) - (input[5]), 2))) + (Pow((100.0) - (input[6]), 2))) + (Pow((1.6582) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((88.27) - (input[11]), 2))) + (Pow((36.98) - (input[12]), 2))))) * (-1.0))) + ((Exp((var0) * (((((((((((((Pow((11.8123) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.718) - (input[4]), 2))) + (Pow((6.824) - (input[5]), 2))) + (Pow((76.5) - (input[6]), 2))) + (Pow((1.794) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((48.45) - (input[11]), 2))) + (Pow((22.74) - (input[12]), 2))))) * (-1.0))) + ((Exp((var0) * (((((((((((((Pow((0.08187) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((2.89) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.445) - (input[4]), 2))) + (Pow((7.82) - (input[5]), 2))) + (Pow((36.9) - (input[6]), 2))) + (Pow((3.4952) - (input[7]), 2))) + (Pow((2.0) - (input[8]), 2))) + (Pow((276.0) - (input[9]), 2))) + (Pow((18.0) - (input[10]), 2))) + (Pow((393.53) - (input[11]), 2))) + (Pow((3.57) - (input[12]), 2))))) * (0.2750000000382897))) + ((Exp((var0) * (((((((((((((Pow((7.67202) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.693) - (input[4]), 2))) + (Pow((5.747) - (input[5]), 2))) + (Pow((98.9) - (input[6]), 2))) + (Pow((1.6334) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((393.1) - (input[11]), 2))) + (Pow((19.92) - (input[12]), 2))))) * (-1.0))) + ((Exp((var0) * (((((((((((((Pow((1.46336) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((19.58) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.605) - (input[4]), 2))) + (Pow((7.489) - (input[5]), 2))) + (Pow((90.8) - (input[6]), 2))) + (Pow((1.9709) - (input[7]), 2))) + (Pow((5.0) - (input[8]), 2))) + (Pow((403.0) - (input[9]), 2))) + (Pow((14.7) - (input[10]), 2))) + (Pow((374.43) - (input[11]), 2))) + (Pow((1.73) - (input[12]), 2))))) * (1.0))) + ((Exp((var0) * (((((((((((((Pow((20.0849) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.7) - (input[4]), 2))) + (Pow((4.368) - (input[5]), 2))) + (Pow((91.2) - (input[6]), 2))) + (Pow((1.4395) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((285.83) - (input[11]), 2))) + (Pow((30.63) - (input[12]), 2))))) * (-1.0))) + ((Exp((var0) * (((((((((((((Pow((1.83377) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((19.58) - (input[2]), 2))) + (Pow((1.0) - (input[3]), 2))) + (Pow((0.605) - (input[4]), 2))) + (Pow((7.802) - (input[5]), 2))) + (Pow((98.2) - (input[6]), 2))) + (Pow((2.0407) - (input[7]), 2))) + (Pow((5.0) - (input[8]), 2))) + (Pow((403.0) - (input[9]), 2))) + (Pow((14.7) - (input[10]), 2))) + (Pow((389.61) - (input[11]), 2))) + (Pow((1.92) - (input[12]), 2))))) * (1.0))) + ((Exp((var0) * (((((((((((((Pow((73.5341) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.679) - (input[4]), 2))) + (Pow((5.957) - (input[5]), 2))) + (Pow((100.0) - (input[6]), 2))) + (Pow((1.8026) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((16.45) - (input[11]), 2))) + (Pow((20.62) - (input[12]), 2))))) * (-1.0))) + ((Exp((var0) * (((((((((((((Pow((0.33147) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((6.2) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.507) - (input[4]), 2))) + (Pow((8.247) - (input[5]), 2))) + (Pow((70.4) - (input[6]), 2))) + (Pow((3.6519) - (input[7]), 2))) + (Pow((8.0) - (input[8]), 2))) + (Pow((307.0) - (input[9]), 2))) + (Pow((17.4) - (input[10]), 2))) + (Pow((378.95) - (input[11]), 2))) + (Pow((3.95) - (input[12]), 2))))) * (1.0))) + ((Exp((var0) * (((((((((((((Pow((25.0461) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.693) - (input[4]), 2))) + (Pow((5.987) - (input[5]), 2))) + (Pow((100.0) - (input[6]), 2))) + (Pow((1.5888) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((396.9) - (input[11]), 2))) + (Pow((26.77) - (input[12]), 2))))) * (-1.0))) + ((Exp((var0) * (((((((((((((Pow((0.57834) - (input[0]), 2)) + (Pow((20.0) - (input[1]), 2))) + (Pow((3.97) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.575) - (input[4]), 2))) + (Pow((8.297) - (input[5]), 2))) + (Pow((67.0) - (input[6]), 2))) + (Pow((2.4216) - (input[7]), 2))) + (Pow((5.0) - (input[8]), 2))) + (Pow((264.0) - (input[9]), 2))) + (Pow((13.0) - (input[10]), 2))) + (Pow((384.54) - (input[11]), 2))) + (Pow((7.44) - (input[12]), 2))))) * (1.0))) + ((Exp((var0) * (((((((((((((Pow((16.8118) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.7) - (input[4]), 2))) + (Pow((5.277) - (input[5]), 2))) + (Pow((98.1) - (input[6]), 2))) + (Pow((1.4261) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((396.9) - (input[11]), 2))) + (Pow((30.81) - (input[12]), 2))))) * (-1.0))) + ((Exp((var0) * (((((((((((((Pow((0.31533) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((6.2) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.504) - (input[4]), 2))) + (Pow((8.266) - (input[5]), 2))) + (Pow((78.3) - (input[6]), 2))) + (Pow((2.8944) - (input[7]), 2))) + (Pow((8.0) - (input[8]), 2))) + (Pow((307.0) - (input[9]), 2))) + (Pow((17.4) - (input[10]), 2))) + (Pow((385.05) - (input[11]), 2))) + (Pow((4.14) - (input[12]), 2))))) * (1.0))) + ((Exp((var0) * (((((((((((((Pow((67.9208) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.693) - (input[4]), 2))) + (Pow((5.683) - (input[5]), 2))) + (Pow((100.0) - (input[6]), 2))) + (Pow((1.4254) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((384.97) - (input[11]), 2))) + (Pow((22.98) - (input[12]), 2))))) * (-1.0))) + ((Exp((var0) * (((((((((((((Pow((0.18337) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((27.74) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.609) - (input[4]), 2))) + (Pow((5.414) - (input[5]), 2))) + (Pow((98.3) - (input[6]), 2))) + (Pow((1.7554) - (input[7]), 2))) + (Pow((4.0) - (input[8]), 2))) + (Pow((711.0) - (input[9]), 2))) + (Pow((20.1) - (input[10]), 2))) + (Pow((344.05) - (input[11]), 2))) + (Pow((23.97) - (input[12]), 2))))) * (-1.0))) + ((Exp((var0) * (((((((((((((Pow((14.3337) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.7) - (input[4]), 2))) + (Pow((4.88) - (input[5]), 2))) + (Pow((100.0) - (input[6]), 2))) + (Pow((1.5895) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((372.92) - (input[11]), 2))) + (Pow((30.62) - (input[12]), 2))))) * (-0.3179880503820858))) + ((Exp((var0) * (((((((((((((Pow((0.20746) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((27.74) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.609) - (input[4]), 2))) + (Pow((5.093) - (input[5]), 2))) + (Pow((98.0) - (input[6]), 2))) + (Pow((1.8226) - (input[7]), 2))) + (Pow((4.0) - (input[8]), 2))) + (Pow((711.0) - (input[9]), 2))) + (Pow((20.1) - (input[10]), 2))) + (Pow((318.43) - (input[11]), 2))) + (Pow((29.68) - (input[12]), 2))))) * (-1.0))) + ((Exp((var0) * (((((((((((((Pow((41.5292) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.693) - (input[4]), 2))) + (Pow((5.531) - (input[5]), 2))) + (Pow((85.4) - (input[6]), 2))) + (Pow((1.6074) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((329.46) - (input[11]), 2))) + (Pow((27.38) - (input[12]), 2))))) * (-1.0))) + ((Exp((var0) * (((((((((((((Pow((1.51902) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((19.58) - (input[2]), 2))) + (Pow((1.0) - (input[3]), 2))) + (Pow((0.605) - (input[4]), 2))) + (Pow((8.375) - (input[5]), 2))) + (Pow((93.9) - (input[6]), 2))) + (Pow((2.162) - (input[7]), 2))) + (Pow((5.0) - (input[8]), 2))) + (Pow((403.0) - (input[9]), 2))) + (Pow((14.7) - (input[10]), 2))) + (Pow((388.45) - (input[11]), 2))) + (Pow((3.32) - (input[12]), 2))))) * (1.0))) + ((Exp((var0) * (((((((((((((Pow((11.5779) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.7) - (input[4]), 2))) + (Pow((5.036) - (input[5]), 2))) + (Pow((97.0) - (input[6]), 2))) + (Pow((1.77) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((396.9) - (input[11]), 2))) + (Pow((25.68) - (input[12]), 2))))) * (-0.7698794401926943))) + ((Exp((var0) * (((((((((((((Pow((14.2362) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.693) - (input[4]), 2))) + (Pow((6.343) - (input[5]), 2))) + (Pow((100.0) - (input[6]), 2))) + (Pow((1.5741) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((396.9) - (input[11]), 2))) + (Pow((20.32) - (input[12]), 2))))) * (-1.0))) + ((Exp((var0) * (((((((((((((Pow((9.2323) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.631) - (input[4]), 2))) + (Pow((6.216) - (input[5]), 2))) + (Pow((100.0) - (input[6]), 2))) + (Pow((1.1691) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((366.15) - (input[11]), 2))) + (Pow((9.53) - (input[12]), 2))))) * (1.0))) + ((Exp((var0) * (((((((((((((Pow((9.91655) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.693) - (input[4]), 2))) + (Pow((5.852) - (input[5]), 2))) + (Pow((77.8) - (input[6]), 2))) + (Pow((1.5004) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((338.16) - (input[11]), 2))) + (Pow((29.97) - (input[12]), 2))))) * (-1.0))) + ((Exp((var0) * (((((((((((((Pow((22.0511) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.74) - (input[4]), 2))) + (Pow((5.818) - (input[5]), 2))) + (Pow((92.4) - (input[6]), 2))) + (Pow((1.8662) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((391.45) - (input[11]), 2))) + (Pow((22.11) - (input[12]), 2))))) * (-0.017541052270521836))) + ((Exp((var0) * (((((((((((((Pow((0.61154) - (input[0]), 2)) + (Pow((20.0) - (input[1]), 2))) + (Pow((3.97) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.647) - (input[4]), 2))) + (Pow((8.704) - (input[5]), 2))) + (Pow((86.9) - (input[6]), 2))) + (Pow((1.801) - (input[7]), 2))) + (Pow((5.0) - (input[8]), 2))) + (Pow((264.0) - (input[9]), 2))) + (Pow((13.0) - (input[10]), 2))) + (Pow((389.7) - (input[11]), 2))) + (Pow((5.12) - (input[12]), 2))))) * (1.0))) + ((Exp((var0) * (((((((((((((Pow((10.8342) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.679) - (input[4]), 2))) + (Pow((6.782) - (input[5]), 2))) + (Pow((90.8) - (input[6]), 2))) + (Pow((1.8195) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((21.57) - (input[11]), 2))) + (Pow((25.79) - (input[12]), 2))))) * (-1.0))) + ((Exp((var0) * (((((((((((((Pow((15.8603) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.679) - (input[4]), 2))) + (Pow((5.896) - (input[5]), 2))) + (Pow((95.4) - (input[6]), 2))) + (Pow((1.9096) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((7.68) - (input[11]), 2))) + (Pow((24.39) - (input[12]), 2))))) * (-1.0))) + ((Exp((var0) * (((((((((((((Pow((17.8667) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.671) - (input[4]), 2))) + (Pow((6.223) - (input[5]), 2))) + (Pow((100.0) - (input[6]), 2))) + (Pow((1.3861) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((393.74) - (input[11]), 2))) + (Pow((21.78) - (input[12]), 2))))) * (-0.17127153707291753))) + ((Exp((var0) * (((((((((((((Pow((8.26725) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((1.0) - (input[3]), 2))) + (Pow((0.668) - (input[4]), 2))) + (Pow((5.875) - (input[5]), 2))) + (Pow((89.6) - (input[6]), 2))) + (Pow((1.1296) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((347.88) - (input[11]), 2))) + (Pow((8.88) - (input[12]), 2))))) * (1.0))) + ((Exp((var0) * (((((((((((((Pow((0.52693) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((6.2) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.504) - (input[4]), 2))) + (Pow((8.725) - (input[5]), 2))) + (Pow((83.0) - (input[6]), 2))) + (Pow((2.8944) - (input[7]), 2))) + (Pow((8.0) - (input[8]), 2))) + (Pow((307.0) - (input[9]), 2))) + (Pow((17.4) - (input[10]), 2))) + (Pow((382.0) - (input[11]), 2))) + (Pow((4.63) - (input[12]), 2))))) * (1.0))) + ((Exp((var0) * (((((((((((((Pow((0.0351) - (input[0]), 2)) + (Pow((95.0) - (input[1]), 2))) + (Pow((2.68) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.4161) - (input[4]), 2))) + (Pow((7.853) - (input[5]), 2))) + (Pow((33.2) - (input[6]), 2))) + (Pow((5.118) - (input[7]), 2))) + (Pow((4.0) - (input[8]), 2))) + (Pow((224.0) - (input[9]), 2))) + (Pow((14.7) - (input[10]), 2))) + (Pow((392.78) - (input[11]), 2))) + (Pow((3.81) - (input[12]), 2))))) * (1.0))) + ((Exp((var0) * (((((((((((((Pow((12.2472) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.584) - (input[4]), 2))) + (Pow((5.837) - (input[5]), 2))) + (Pow((59.7) - (input[6]), 2))) + (Pow((1.9976) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((24.65) - (input[11]), 2))) + (Pow((15.69) - (input[12]), 2))))) * (-0.31798805038208666))) + ((Exp((var0) * (((((((((((((Pow((14.4208) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.74) - (input[4]), 2))) + (Pow((6.461) - (input[5]), 2))) + (Pow((93.3) - (input[6]), 2))) + (Pow((2.0026) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((27.49) - (input[11]), 2))) + (Pow((18.05) - (input[12]), 2))))) * (-0.9183413019645936))) + ((Exp((var0) * (((((((((((((Pow((0.29819) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((6.2) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.504) - (input[4]), 2))) + (Pow((7.686) - (input[5]), 2))) + (Pow((17.0) - (input[6]), 2))) + (Pow((3.3751) - (input[7]), 2))) + (Pow((8.0) - (input[8]), 2))) + (Pow((307.0) - (input[9]), 2))) + (Pow((17.4) - (input[10]), 2))) + (Pow((377.51) - (input[11]), 2))) + (Pow((3.92) - (input[12]), 2))))) * (1.0))) + ((Exp((var0) * (((((((((((((Pow((38.3518) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.693) - (input[4]), 2))) + (Pow((5.453) - (input[5]), 2))) + (Pow((100.0) - (input[6]), 2))) + (Pow((1.4896) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((396.9) - (input[11]), 2))) + (Pow((30.59) - (input[12]), 2))))) * (-1.0))) + ((Exp((var0) * (((((((((((((Pow((0.06129) - (input[0]), 2)) + (Pow((20.0) - (input[1]), 2))) + (Pow((3.33) - (input[2]), 2))) + (Pow((1.0) - (input[3]), 2))) + (Pow((0.4429) - (input[4]), 2))) + (Pow((7.645) - (input[5]), 2))) + (Pow((49.7) - (input[6]), 2))) + (Pow((5.2119) - (input[7]), 2))) + (Pow((5.0) - (input[8]), 2))) + (Pow((216.0) - (input[9]), 2))) + (Pow((14.9) - (input[10]), 2))) + (Pow((377.07) - (input[11]), 2))) + (Pow((3.01) - (input[12]), 2))))) * (1.0))) + ((Exp((var0) * (((((((((((((Pow((88.9762) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.671) - (input[4]), 2))) + (Pow((6.968) - (input[5]), 2))) + (Pow((91.9) - (input[6]), 2))) + (Pow((1.4165) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((396.9) - (input[11]), 2))) + (Pow((17.21) - (input[12]), 2))))) * (-0.11849528386764341))) + ((Exp((var0) * (((((((((((((Pow((0.05602) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((2.46) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.488) - (input[4]), 2))) + (Pow((7.831) - (input[5]), 2))) + (Pow((53.6) - (input[6]), 2))) + (Pow((3.1992) - (input[7]), 2))) + (Pow((3.0) - (input[8]), 2))) + (Pow((193.0) - (input[9]), 2))) + (Pow((17.8) - (input[10]), 2))) + (Pow((392.63) - (input[11]), 2))) + (Pow((4.45) - (input[12]), 2))))) * (1.0))) + ((Exp((var0) * (((((((((((((Pow((0.01501) - (input[0]), 2)) + (Pow((90.0) - (input[1]), 2))) + (Pow((1.21) - (input[2]), 2))) + (Pow((1.0) - (input[3]), 2))) + (Pow((0.401) - (input[4]), 2))) + (Pow((7.923) - (input[5]), 2))) + (Pow((24.8) - (input[6]), 2))) + (Pow((5.885) - (input[7]), 2))) + (Pow((1.0) - (input[8]), 2))) + (Pow((198.0) - (input[9]), 2))) + (Pow((13.6) - (input[10]), 2))) + (Pow((395.52) - (input[11]), 2))) + (Pow((3.16) - (input[12]), 2))))) * (1.0))) + ((Exp((var0) * (((((((((((((Pow((0.02009) - (input[0]), 2)) + (Pow((95.0) - (input[1]), 2))) + (Pow((2.68) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.4161) - (input[4]), 2))) + (Pow((8.034) - (input[5]), 2))) + (Pow((31.9) - (input[6]), 2))) + (Pow((5.118) - (input[7]), 2))) + (Pow((4.0) - (input[8]), 2))) + (Pow((224.0) - (input[9]), 2))) + (Pow((14.7) - (input[10]), 2))) + (Pow((390.55) - (input[11]), 2))) + (Pow((2.88) - (input[12]), 2))))) * (1.0))) + ((Exp((var0) * (((((((((((((Pow((15.1772) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.74) - (input[4]), 2))) + (Pow((6.152) - (input[5]), 2))) + (Pow((100.0) - (input[6]), 2))) + (Pow((1.9142) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((9.32) - (input[11]), 2))) + (Pow((26.45) - (input[12]), 2))))) * (-1.0))) + ((Exp((var0) * (((((((((((((Pow((18.0846) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.679) - (input[4]), 2))) + (Pow((6.434) - (input[5]), 2))) + (Pow((100.0) - (input[6]), 2))) + (Pow((1.8347) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((27.25) - (input[11]), 2))) + (Pow((29.05) - (input[12]), 2))))) * (-1.0))) + ((Exp((var0) * (((((((((((((Pow((0.01381) - (input[0]), 2)) + (Pow((80.0) - (input[1]), 2))) + (Pow((0.46) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.422) - (input[4]), 2))) + (Pow((7.875) - (input[5]), 2))) + (Pow((32.0) - (input[6]), 2))) + (Pow((5.6484) - (input[7]), 2))) + (Pow((4.0) - (input[8]), 2))) + (Pow((255.0) - (input[9]), 2))) + (Pow((14.4) - (input[10]), 2))) + (Pow((394.23) - (input[11]), 2))) + (Pow((2.97) - (input[12]), 2))))) * (1.0))) + ((Exp((var0) * (((((((((((((Pow((5.66998) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((1.0) - (input[3]), 2))) + (Pow((0.631) - (input[4]), 2))) + (Pow((6.683) - (input[5]), 2))) + (Pow((96.8) - (input[6]), 2))) + (Pow((1.3567) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((375.33) - (input[11]), 2))) + (Pow((3.73) - (input[12]), 2))))) * (1.0))) + ((Exp((var0) * (((((((((((((Pow((0.01538) - (input[0]), 2)) + (Pow((90.0) - (input[1]), 2))) + (Pow((3.75) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.394) - (input[4]), 2))) + (Pow((7.454) - (input[5]), 2))) + (Pow((34.2) - (input[6]), 2))) + (Pow((6.3361) - (input[7]), 2))) + (Pow((3.0) - (input[8]), 2))) + (Pow((244.0) - (input[9]), 2))) + (Pow((15.9) - (input[10]), 2))) + (Pow((386.34) - (input[11]), 2))) + (Pow((3.11) - (input[12]), 2))))) * (0.47499999996189857))) + ((Exp((var0) * (((((((((((((Pow((4.89822) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.631) - (input[4]), 2))) + (Pow((4.97) - (input[5]), 2))) + (Pow((100.0) - (input[6]), 2))) + (Pow((1.3325) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((375.52) - (input[11]), 2))) + (Pow((3.26) - (input[12]), 2))))) * (1.0))) + ((Exp((var0) * (((((((((((((Pow((2.01019) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((19.58) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.605) - (input[4]), 2))) + (Pow((7.929) - (input[5]), 2))) + (Pow((96.2) - (input[6]), 2))) + (Pow((2.0459) - (input[7]), 2))) + (Pow((5.0) - (input[8]), 2))) + (Pow((403.0) - (input[9]), 2))) + (Pow((14.7) - (input[10]), 2))) + (Pow((369.3) - (input[11]), 2))) + (Pow((3.7) - (input[12]), 2))))) * (1.0))) + ((Exp((var0) * (((((((((((((Pow((0.52014) - (input[0]), 2)) + (Pow((20.0) - (input[1]), 2))) + (Pow((3.97) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.647) - (input[4]), 2))) + (Pow((8.398) - (input[5]), 2))) + (Pow((91.5) - (input[6]), 2))) + (Pow((2.2885) - (input[7]), 2))) + (Pow((5.0) - (input[8]), 2))) + (Pow((264.0) - (input[9]), 2))) + (Pow((13.0) - (input[10]), 2))) + (Pow((386.86) - (input[11]), 2))) + (Pow((5.91) - (input[12]), 2))))) * (1.0))) + ((Exp((var0) * (((((((((((((Pow((9.33889) - (input[0]), 2)) + (Pow((0.0) - (input[1]), 2))) + (Pow((18.1) - (input[2]), 2))) + (Pow((0.0) - (input[3]), 2))) + (Pow((0.679) - (input[4]), 2))) + (Pow((6.38) - (input[5]), 2))) + (Pow((95.6) - (input[6]), 2))) + (Pow((1.9682) - (input[7]), 2))) + (Pow((24.0) - (input[8]), 2))) + (Pow((666.0) - (input[9]), 2))) + (Pow((20.2) - (input[10]), 2))) + (Pow((60.72) - (input[11]), 2))) + (Pow((24.08) - (input[12]), 2))))) * (-1.0)); + } + } +} diff --git a/generated_code_examples/c_sharp/regression/xgboost.cs b/generated_code_examples/c_sharp/regression/xgboost.cs new file mode 100644 index 00000000..1b960bf0 --- /dev/null +++ b/generated_code_examples/c_sharp/regression/xgboost.cs @@ -0,0 +1,35 @@ +namespace ML { + public static class Model { + public static double Score(double[] input) { + double var0; + if ((input[12]) >= (9.72500038)) { + if ((input[12]) >= (19.8299999)) { + var0 = 1.1551429; + } else { + var0 = 1.8613131; + } + } else { + if ((input[5]) >= (6.94099998)) { + var0 = 3.75848508; + } else { + var0 = 2.48056006; + } + } + double var1; + if ((input[12]) >= (7.68499994)) { + if ((input[12]) >= (15)) { + var1 = 1.24537706; + } else { + var1 = 1.92129695; + } + } else { + if ((input[5]) >= (7.43700027)) { + var1 = 3.96021533; + } else { + var1 = 2.51493931; + } + } + return ((0.5) + (var0)) + (var1); + } + } +} diff --git a/m2cgen/__init__.py b/m2cgen/__init__.py index 8e49a7e6..c0aa1e3c 100644 --- a/m2cgen/__init__.py +++ b/m2cgen/__init__.py @@ -7,6 +7,7 @@ export_to_python, export_to_javascript, export_to_visual_basic, + export_to_c_sharp, ) __all__ = [ @@ -16,6 +17,7 @@ export_to_go, export_to_javascript, export_to_visual_basic, + export_to_c_sharp, ] with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), diff --git a/m2cgen/cli.py b/m2cgen/cli.py index f9d1701e..e8cbb89b 100644 --- a/m2cgen/cli.py +++ b/m2cgen/cli.py @@ -24,6 +24,8 @@ "javascript": (m2cgen.export_to_javascript, ["indent"]), "visual_basic": (m2cgen.export_to_visual_basic, ["module_name", "indent"]), + "c_sharp": (m2cgen.export_to_c_sharp, + ["indent", "class_name", "namespace"]), } @@ -54,6 +56,10 @@ "--module_name", "-mn", dest="module_name", type=str, help="Module name for the generated code " "(if supported by target language)") +parser.add_argument( + "--namespace", "-ns", dest="namespace", type=str, + help="Namespace for the generated code " + "(if supported by target language)") parser.add_argument( "--indent", "-i", dest="indent", type=int, default=4, diff --git a/m2cgen/exporters.py b/m2cgen/exporters.py index 0418a413..d467a599 100644 --- a/m2cgen/exporters.py +++ b/m2cgen/exporters.py @@ -168,6 +168,32 @@ def export_to_visual_basic(model, module_name="Model", indent=4): return _export(model, interpreter) +def export_to_c_sharp(model, namespace="ML", class_name="Model", indent=4): + """ + Generates a C# code representation of the given model. + + Parameters + ---------- + model : object + The model object that should be transpiled into code. + namespace : string, optional + The namespace for the generated code. + class_name : string, optional + The name of the generated class. + indent : int, optional + The size of indents in the generated code. + + Returns + ------- + code : string + """ + interpreter = interpreters.CSharpInterpreter( + namespace=namespace, + class_name=class_name, + indent=indent) + return _export(model, interpreter) + + def _export(model, interpreter): assembler_cls = assemblers.get_assembler_cls(model) model_ast = assembler_cls(model).assemble() diff --git a/m2cgen/interpreters/__init__.py b/m2cgen/interpreters/__init__.py index fb713e4b..7bc80053 100644 --- a/m2cgen/interpreters/__init__.py +++ b/m2cgen/interpreters/__init__.py @@ -4,6 +4,7 @@ from .go.interpreter import GoInterpreter from .javascript.interpreter import JavascriptInterpreter from .visual_basic.interpreter import VisualBasicInterpreter +from .c_sharp.interpreter import CSharpInterpreter __all__ = [ JavaInterpreter, @@ -12,4 +13,5 @@ GoInterpreter, JavascriptInterpreter, VisualBasicInterpreter, + CSharpInterpreter, ] diff --git a/m2cgen/interpreters/c_sharp/__init__.py b/m2cgen/interpreters/c_sharp/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/m2cgen/interpreters/c_sharp/code_generator.py b/m2cgen/interpreters/c_sharp/code_generator.py new file mode 100644 index 00000000..502449b3 --- /dev/null +++ b/m2cgen/interpreters/c_sharp/code_generator.py @@ -0,0 +1,65 @@ +import contextlib + +from m2cgen.interpreters.code_generator import CLikeCodeGenerator + + +class CSharpCodeGenerator(CLikeCodeGenerator): + + scalar_type = "double" + vector_type = "double[]" + + def __init__(self, *args, **kwargs): + super(CSharpCodeGenerator, self).__init__(*args, **kwargs) + + def add_class_def(self, class_name, modifier="public"): + class_def = modifier + " static class " + class_name + " {" + self.add_code_line(class_def) + self.increase_indent() + + def add_method_def(self, name, args, is_vector_output, + modifier="private"): + return_type = self._get_var_declare_type(is_vector_output) + method_def = modifier + " static " + return_type + " " + name + "(" + method_def += ",".join([ + self._get_var_declare_type(is_vector) + " " + n + for is_vector, n in args]) + method_def += ") {" + self.add_code_line(method_def) + self.increase_indent() + + def add_namespace_def(self, namespace): + namespace_def = "namespace " + namespace + " {" + self.add_code_line(namespace_def) + self.increase_indent() + + @contextlib.contextmanager + def class_definition(self, class_name, modifier="public"): + self.add_class_def(class_name, modifier=modifier) + yield + self.add_block_termination() + + @contextlib.contextmanager + def method_definition(self, name, args, is_vector_output, + modifier="private"): + self.add_method_def(name, args, is_vector_output, modifier=modifier) + yield + self.add_block_termination() + + @contextlib.contextmanager + def namespace_definition(self, namespace): + self.add_namespace_def(namespace) + yield + self.add_block_termination() + + def vector_init(self, values): + return ("new double[{}] {{".format(len(values)) + + ", ".join(values) + "}") + + def _get_var_declare_type(self, is_vector): + return ( + self.vector_type if is_vector + else self.scalar_type) + + def add_dependency(self, dep, modifier="static"): + dep_str = "using {0} {1};".format(modifier, dep) + self.prepend_code_line(dep_str) diff --git a/m2cgen/interpreters/c_sharp/interpreter.py b/m2cgen/interpreters/c_sharp/interpreter.py new file mode 100644 index 00000000..f7d52909 --- /dev/null +++ b/m2cgen/interpreters/c_sharp/interpreter.py @@ -0,0 +1,58 @@ +import os + +from m2cgen import ast +from m2cgen.interpreters import mixins +from m2cgen.interpreters import utils +from m2cgen.interpreters.interpreter import ToCodeInterpreter +from m2cgen.interpreters.c_sharp.code_generator import CSharpCodeGenerator + + +class CSharpInterpreter(ToCodeInterpreter, mixins.LinearAlgebraMixin): + + supported_bin_vector_ops = { + ast.BinNumOpType.ADD: "AddVectors", + } + + supported_bin_vector_num_ops = { + ast.BinNumOpType.MUL: "MulVectorNumber", + } + + exponent_function_name = "Exp" + power_function_name = "Pow" + tanh_function_name = "Tanh" + + def __init__(self, namespace="ML", class_name="Model", indent=4, + *args, **kwargs): + self.namespace = namespace + self.class_name = class_name + self.indent = indent + + cg = CSharpCodeGenerator(indent=indent) + super(CSharpInterpreter, self).__init__(cg, *args, **kwargs) + + def interpret(self, expr): + self._cg.reset_state() + self._reset_reused_expr_cache() + + method_name = "Score" + args = [(True, self._feature_array_name)] + + with self._cg.namespace_definition(self.namespace): + with self._cg.class_definition(self.class_name): + with self._cg.method_definition( + name=method_name, + args=args, + is_vector_output=expr.output_size > 1, + modifier="public"): + last_result = self._do_interpret(expr) + self._cg.add_return_statement(last_result) + + if self.with_linear_algebra: + filename = os.path.join( + os.path.dirname(__file__), "linear_algebra.cs") + self._cg.add_code_lines(utils.get_file_content(filename)) + + if self.with_math_module: + self._cg.add_dependency("System.Math") + + return self._cg.code diff --git a/m2cgen/interpreters/c_sharp/linear_algebra.cs b/m2cgen/interpreters/c_sharp/linear_algebra.cs new file mode 100644 index 00000000..0147e04c --- /dev/null +++ b/m2cgen/interpreters/c_sharp/linear_algebra.cs @@ -0,0 +1,14 @@ +private static double[] AddVectors(double[] v1, double[] v2) { + double[] result = new double[v1.Length]; + for (int i = 0; i < v1.Length; ++i) { + result[i] = v1[i] + v2[i]; + } + return result; +} +private static double[] MulVectorNumber(double[] v1, double num) { + double[] result = new double[v1.Length]; + for (int i = 0; i < v1.Length; ++i) { + result[i] = v1[i] * num; + } + return result; +} diff --git a/tests/e2e/executors/__init__.py b/tests/e2e/executors/__init__.py index cf5eb443..449b9d8d 100644 --- a/tests/e2e/executors/__init__.py +++ b/tests/e2e/executors/__init__.py @@ -4,6 +4,7 @@ from tests.e2e.executors.go import GoExecutor from tests.e2e.executors.javascript import JavascriptExecutor from tests.e2e.executors.visual_basic import VisualBasicExecutor +from tests.e2e.executors.c_sharp import CSharpExecutor __all__ = [ JavaExecutor, @@ -12,4 +13,5 @@ GoExecutor, JavascriptExecutor, VisualBasicExecutor, + CSharpExecutor, ] diff --git a/tests/e2e/executors/c_sharp.py b/tests/e2e/executors/c_sharp.py new file mode 100644 index 00000000..c59fe667 --- /dev/null +++ b/tests/e2e/executors/c_sharp.py @@ -0,0 +1,93 @@ +import os +import string +import subprocess + +from m2cgen import assemblers, interpreters +from tests import utils +from tests.e2e.executors import base + +EXECUTOR_CODE_TPL = """ +using System; + +namespace TestConsoleApp { + class Program { + static void Main(string[] args) { + double[] input_ = new double[args.Length]; + for(int i = 0; i < input_.Length; ++i) { + input_[i] = double.Parse(args[i]); + } + ${print_code} + } + } +} +""" + +EXECUTE_AND_PRINT_SCALAR = """ + double res = ML.Model.Score(input_); + Console.Write(res); +""" + +EXECUTE_AND_PRINT_VECTOR = """ + double[] res = ML.Model.Score(input_); + for(int i = 0; i < res.Length; ++i) { + Console.Write("{0} ", res[i]); + } +""" + + +class CSharpExecutor(base.BaseExecutor): + + target_exec_dir = None + project_name = "test_model" + _dotnet = "dotnet" + + def __init__(self, model): + self.model = model + self.interpreter = interpreters.CSharpInterpreter() + + assembler_cls = assemblers.get_assembler_cls(model) + self.model_ast = assembler_cls(model).assemble() + + def predict(self, X): + exec_args = [os.path.join(self.target_exec_dir, self.project_name)] + exec_args.extend(map(str, X)) + return utils.predict_from_commandline(exec_args) + + @classmethod + def prepare_global(cls, **kwargs): + super(CSharpExecutor, cls).prepare_global(**kwargs) + if cls.target_exec_dir is None: + cls.target_exec_dir = os.path.join(cls._global_tmp_dir, "bin") + + subprocess.call([cls._dotnet, + "new", + "console", + "--output", + cls._global_tmp_dir, + "--name", + cls.project_name, + "--language", + "C#"]) + + def prepare(self): + if self.model_ast.output_size > 1: + print_code = EXECUTE_AND_PRINT_VECTOR + else: + print_code = EXECUTE_AND_PRINT_SCALAR + executor_code = string.Template(EXECUTOR_CODE_TPL).substitute( + print_code=print_code) + model_code = self.interpreter.interpret(self.model_ast) + + model_file_name = os.path.join(self._global_tmp_dir, "Model.cs") + executor_file_name = os.path.join(self._global_tmp_dir, "Program.cs") + with open(model_file_name, "w") as f: + f.write(model_code) + with open(executor_file_name, "w") as f: + f.write(executor_code) + + subprocess.call([self._dotnet, + "build", + os.path.join(self._global_tmp_dir, + "{}.csproj".format(self.project_name)), + "--output", + self.target_exec_dir]) diff --git a/tests/e2e/test_e2e.py b/tests/e2e/test_e2e.py index 2cf7db65..8b64bb4a 100644 --- a/tests/e2e/test_e2e.py +++ b/tests/e2e/test_e2e.py @@ -21,6 +21,7 @@ GO = pytest.mark.go JAVASCRIPT = pytest.mark.javascript VISUAL_BASIC = pytest.mark.visual_basic +C_SHARP = pytest.mark.c_sharp REGRESSION = pytest.mark.regr CLASSIFICATION = pytest.mark.clf @@ -73,6 +74,7 @@ def classification_binary(model): (executors.GoExecutor, GO), (executors.JavascriptExecutor, JAVASCRIPT), (executors.VisualBasicExecutor, VISUAL_BASIC), + (executors.CSharpExecutor, C_SHARP), ], # These models will be tested against each language specified in the diff --git a/tests/interpreters/test_c_sharp.py b/tests/interpreters/test_c_sharp.py new file mode 100644 index 00000000..c59e186a --- /dev/null +++ b/tests/interpreters/test_c_sharp.py @@ -0,0 +1,369 @@ +from m2cgen import ast +from m2cgen.interpreters import CSharpInterpreter +from tests import utils + + +def test_if_expr(): + expr = ast.IfExpr( + ast.CompExpr(ast.NumVal(1), ast.FeatureRef(0), ast.CompOpType.EQ), + ast.NumVal(2), + ast.NumVal(3)) + + expected_code = """ +namespace ML { + public static class Model { + public static double Score(double[] input) { + double var0; + if ((1) == (input[0])) { + var0 = 2; + } else { + var0 = 3; + } + return var0; + } + } +} +""" + + interpreter = CSharpInterpreter() + utils.assert_code_equal(interpreter.interpret(expr), expected_code) + + +def test_bin_num_expr(): + expr = ast.BinNumExpr( + ast.BinNumExpr( + ast.FeatureRef(0), ast.NumVal(-2), ast.BinNumOpType.DIV), + ast.NumVal(2), + ast.BinNumOpType.MUL) + + expected_code = """ +namespace ML { + public static class Model { + public static double Score(double[] input) { + return ((input[0]) / (-2)) * (2); + } + } +} +""" + + interpreter = CSharpInterpreter() + utils.assert_code_equal(interpreter.interpret(expr), expected_code) + + +def test_dependable_condition(): + left = ast.BinNumExpr( + ast.IfExpr( + ast.CompExpr(ast.NumVal(1), + ast.NumVal(1), + ast.CompOpType.EQ), + ast.NumVal(1), + ast.NumVal(2)), + ast.NumVal(2), + ast.BinNumOpType.ADD) + + right = ast.BinNumExpr(ast.NumVal(1), ast.NumVal(2), ast.BinNumOpType.DIV) + bool_test = ast.CompExpr(left, right, ast.CompOpType.GTE) + + expr = ast.IfExpr(bool_test, ast.NumVal(1), ast.FeatureRef(0)) + + expected_code = """ +namespace ML { + public static class Model { + public static double Score(double[] input) { + double var0; + double var1; + if ((1) == (1)) { + var1 = 1; + } else { + var1 = 2; + } + if (((var1) + (2)) >= ((1) / (2))) { + var0 = 1; + } else { + var0 = input[0]; + } + return var0; + } + } +} +""" + + interpreter = CSharpInterpreter() + utils.assert_code_equal(interpreter.interpret(expr), expected_code) + + +def test_nested_condition(): + left = ast.BinNumExpr( + ast.IfExpr( + ast.CompExpr(ast.NumVal(1), + ast.NumVal(1), + ast.CompOpType.EQ), + ast.NumVal(1), + ast.NumVal(2)), + ast.NumVal(2), + ast.BinNumOpType.ADD) + + bool_test = ast.CompExpr(ast.NumVal(1), left, ast.CompOpType.EQ) + + expr_nested = ast.IfExpr(bool_test, ast.FeatureRef(2), ast.NumVal(2)) + + expr = ast.IfExpr(bool_test, expr_nested, ast.NumVal(2)) + + expected_code = """ +namespace ML { + public static class Model { + public static double Score(double[] input) { + double var0; + double var1; + if ((1) == (1)) { + var1 = 1; + } else { + var1 = 2; + } + if ((1) == ((var1) + (2))) { + double var2; + if ((1) == (1)) { + var2 = 1; + } else { + var2 = 2; + } + if ((1) == ((var2) + (2))) { + var0 = input[2]; + } else { + var0 = 2; + } + } else { + var0 = 2; + } + return var0; + } + } +} +""" + + interpreter = CSharpInterpreter() + utils.assert_code_equal(interpreter.interpret(expr), expected_code) + + +def test_namespace(): + expr = ast.NumVal(1) + + expected_code = """ +namespace ML.Tests { + public static class Model { + public static double Score(double[] input) { + return 1; + } + } +} +""" + + interpreter = CSharpInterpreter(namespace="ML.Tests") + utils.assert_code_equal(interpreter.interpret(expr), expected_code) + + +def test_class_name(): + expr = ast.NumVal(1) + + expected_code = """ +namespace ML { + public static class TestModel { + public static double Score(double[] input) { + return 1; + } + } +} +""" + + interpreter = CSharpInterpreter(class_name="TestModel") + utils.assert_code_equal(interpreter.interpret(expr), expected_code) + + +def test_raw_array(): + expr = ast.VectorVal([ast.NumVal(3), ast.NumVal(4)]) + + expected_code = """ +namespace ML { + public static class Model { + public static double[] Score(double[] input) { + return new double[2] {3, 4}; + } + } +} +""" + + interpreter = CSharpInterpreter() + utils.assert_code_equal(interpreter.interpret(expr), expected_code) + + +def test_multi_output(): + expr = ast.SubroutineExpr( + ast.IfExpr( + ast.CompExpr( + ast.NumVal(1), + ast.NumVal(1), + ast.CompOpType.EQ), + ast.VectorVal([ast.NumVal(1), ast.NumVal(2)]), + ast.VectorVal([ast.NumVal(3), ast.NumVal(4)]))) + + expected_code = """ +namespace ML { + public static class Model { + public static double[] Score(double[] input) { + double[] var0; + if ((1) == (1)) { + var0 = new double[2] {1, 2}; + } else { + var0 = new double[2] {3, 4}; + } + return var0; + } + } +} +""" + + interpreter = CSharpInterpreter() + utils.assert_code_equal(interpreter.interpret(expr), expected_code) + + +def test_bin_vector_expr(): + expr = ast.BinVectorExpr( + ast.VectorVal([ast.NumVal(1), ast.NumVal(2)]), + ast.VectorVal([ast.NumVal(3), ast.NumVal(4)]), + ast.BinNumOpType.ADD) + + expected_code = """ +namespace ML { + public static class Model { + public static double[] Score(double[] input) { + return AddVectors(new double[2] {1, 2}, new double[2] {3, 4}); + } + private static double[] AddVectors(double[] v1, double[] v2) { + double[] result = new double[v1.Length]; + for (int i = 0; i < v1.Length; ++i) { + result[i] = v1[i] + v2[i]; + } + return result; + } + private static double[] MulVectorNumber(double[] v1, double num) { + double[] result = new double[v1.Length]; + for (int i = 0; i < v1.Length; ++i) { + result[i] = v1[i] * num; + } + return result; + } + } +} +""" + + interpreter = CSharpInterpreter() + utils.assert_code_equal(interpreter.interpret(expr), expected_code) + + +def test_bin_vector_num_expr(): + expr = ast.BinVectorNumExpr( + ast.VectorVal([ast.NumVal(1), ast.NumVal(2)]), + ast.NumVal(1), + ast.BinNumOpType.MUL) + + expected_code = """ +namespace ML { + public static class Model { + public static double[] Score(double[] input) { + return MulVectorNumber(new double[2] {1, 2}, 1); + } + private static double[] AddVectors(double[] v1, double[] v2) { + double[] result = new double[v1.Length]; + for (int i = 0; i < v1.Length; ++i) { + result[i] = v1[i] + v2[i]; + } + return result; + } + private static double[] MulVectorNumber(double[] v1, double num) { + double[] result = new double[v1.Length]; + for (int i = 0; i < v1.Length; ++i) { + result[i] = v1[i] * num; + } + return result; + } + } +} +""" + + interpreter = CSharpInterpreter() + utils.assert_code_equal(interpreter.interpret(expr), expected_code) + + +def test_exp_expr(): + expr = ast.ExpExpr(ast.NumVal(1.0)) + + expected_code = """ +using static System.Math; +namespace ML { + public static class Model { + public static double Score(double[] input) { + return Exp(1.0); + } + } +} +""" + + interpreter = CSharpInterpreter() + utils.assert_code_equal(interpreter.interpret(expr), expected_code) + + +def test_pow_expr(): + expr = ast.PowExpr(ast.NumVal(2.0), ast.NumVal(3.0)) + + expected_code = """ +using static System.Math; +namespace ML { + public static class Model { + public static double Score(double[] input) { + return Pow(2.0, 3.0); + } + } +} +""" + + interpreter = CSharpInterpreter() + utils.assert_code_equal(interpreter.interpret(expr), expected_code) + + +def test_tanh_expr(): + expr = ast.TanhExpr(ast.NumVal(2.0)) + + expected_code = """ +using static System.Math; +namespace ML { + public static class Model { + public static double Score(double[] input) { + return Tanh(2.0); + } + } +} +""" + + interpreter = CSharpInterpreter() + utils.assert_code_equal(interpreter.interpret(expr), expected_code) + + +def test_reused_expr(): + reused_expr = ast.ExpExpr(ast.NumVal(1.0), to_reuse=True) + expr = ast.BinNumExpr(reused_expr, reused_expr, ast.BinNumOpType.DIV) + + expected_code = """ +using static System.Math; +namespace ML { + public static class Model { + public static double Score(double[] input) { + double var0; + var0 = Exp(1.0); + return (var0) / (var0); + } + } +} +""" + + interpreter = CSharpInterpreter() + utils.assert_code_equal(interpreter.interpret(expr), expected_code) diff --git a/tests/test_cli.py b/tests/test_cli.py index 6663c22b..296ba55d 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -10,11 +10,13 @@ from tests import utils -def _get_mock_args(indent=4, module_name=None, package_name=None, - class_name=None, infile=None, language=None): +def _get_mock_args(indent=4, namespace=None, module_name=None, + package_name=None, class_name=None, + infile=None, language=None): return mock.MagicMock( - indent=indent, module_name=module_name, package_name=package_name, - class_name=class_name, infile=infile, language=language, + indent=indent, namespace=namespace, module_name=module_name, + package_name=package_name, class_name=class_name, + infile=infile, language=language, recursion_limit=cli.MAX_RECURSION_DEPTH) @@ -114,6 +116,16 @@ def test_module_name(): assert generated_code.startswith("Module TestModule") +def test_namespace(): + infile = _get_pickled_trained_model() + mock_args = _get_mock_args( + infile=infile, language="c_sharp", namespace="Tests.ML") + + generated_code = cli.generate_code(mock_args).strip() + + assert generated_code.find("namespace Tests.ML {") != -1 + + def test_unsupported_args_are_ignored(): infile = _get_pickled_trained_model() diff --git a/tools/generate_code_examples.py b/tools/generate_code_examples.py index 6c6c30a9..bc833f8d 100644 --- a/tools/generate_code_examples.py +++ b/tools/generate_code_examples.py @@ -38,6 +38,7 @@ ("go", m2c.export_to_go, "go"), ("javascript", m2c.export_to_javascript, "js"), ("visual_basic", m2c.export_to_visual_basic, "vb"), + ("c_sharp", m2c.export_to_c_sharp, "cs"), ] EXAMPLE_MODELS = [