From 9692a10960691339dc449e4a4e6935c2e8bdb591 Mon Sep 17 00:00:00 2001 From: shimat Date: Sat, 1 Jun 2024 17:44:13 +0900 Subject: [PATCH] unindent --- .editorconfig | 68 ++ LibSVMSharp.Tests/Contants.cs | 13 +- .../Extensions/TestSVMProblemExtensions.cs | 13 +- LibSVMSharp.Tests/Helpers/TestSVMHelper.cs | 13 +- .../Helpers/TestSVMNodeHelper.cs | 13 +- .../Helpers/TestSVMProblemHelper.cs | 13 +- LibSVMSharp.Tests/TestSVM.cs | 403 +++++----- LibSVMSharp.Tests/TestSVMModel.cs | 13 +- LibSVMSharp.Tests/TestSVMNode.cs | 13 +- LibSVMSharp.Tests/TestSVMParameter.cs | 13 +- LibSVMSharp.Tests/TestSVMProblem.cs | 13 +- ...LibSVMsharp.Examples.Classification.csproj | 3 +- .../Program.cs | 117 ++- ...ibSVMsharp.Examples.RapidPrediction.csproj | 4 +- .../Program.cs | 107 ++- .../RapidPredictor.cs | 67 +- LibSVMsharp.sln | 17 +- LibSVMsharp/Core/libsvm.cs | 221 +++--- LibSVMsharp/Core/svm_model.cs | 35 +- LibSVMsharp/Core/svm_node.cs | 13 +- LibSVMsharp/Core/svm_parameter.cs | 39 +- LibSVMsharp/Core/svm_problem.cs | 15 +- LibSVMsharp/Extensions/SVMModelExtensions.cs | 43 +- LibSVMsharp/Extensions/SVMNodeExtensions.cs | 59 +- .../Extensions/SVMProblemExtensions.cs | 155 ++-- LibSVMsharp/Helpers/SVMHelper.cs | 167 ++--- LibSVMsharp/Helpers/SVMNodeHelper.cs | 65 +- LibSVMsharp/Helpers/SVMProblemHelper.cs | 253 ++++--- LibSVMsharp/SVM.cs | 707 +++++++++--------- LibSVMsharp/SVMModel.cs | 647 ++++++++-------- LibSVMsharp/SVMNode.cs | 141 ++-- LibSVMsharp/SVMParameter.cs | 383 +++++----- LibSVMsharp/SVMProblem.cs | 249 +++--- 33 files changed, 2064 insertions(+), 2031 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..2172222 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,68 @@ +# Rules in this file were initially inferred by Visual Studio IntelliCode from the C:\Projects\randd\randd_address_separator\dotnet\Sansan.RD.AddressSeparator.Tests\ codebase based on best match to current usage at 2022/08/18 +# You can modify the rules from these initially generated values to suit your own policies +# You can learn more about editorconfig here: https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference +[*.cs] + + +# IDE0160: Convert to file-scoped namespace +csharp_style_namespace_declarations = file_scoped:warning + +#Core editorconfig formatting - indentation + +#use soft tabs (spaces) for indentation +indent_style = space +indent_size = 4 + +#Formatting - new line options + +#require braces to be on a new line for methods and types (also known as "Allman" style) +csharp_new_line_before_open_brace = all#methods, types + +#Formatting - organize using options + +#sort System.* using directives alphabetically, and place them before other usings +dotnet_sort_system_directives_first = true + +#Formatting - spacing options + +#remove space between method call name and opening parenthesis +csharp_space_between_method_call_name_and_opening_parenthesis = false +#do not place space characters after the opening parenthesis and before the closing parenthesis of a method call +csharp_space_between_method_call_parameter_list_parentheses = false +#place a space character after the opening parenthesis and before the closing parenthesis of a method declaration parameter list. +csharp_space_between_method_declaration_parameter_list_parentheses = false + +#Style - expression bodied member options + +#prefer block bodies for methods +csharp_style_expression_bodied_methods = when_on_single_line:suggestion + +#Style - implicit and explicit types + +#prefer var over explicit type in all cases, unless overridden by another code style rule +csharp_style_var_elsewhere = true:suggestion +#prefer var is used to declare variables with built-in system types such as int +csharp_style_var_for_built_in_types = true:suggestion + +#Style - language keyword and framework type options + +#prefer the language keyword for local variables, method parameters, and class members, instead of the type name, for types that have a keyword to represent them +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion + +#Style - modifier options + +#prefer accessibility modifiers to be declared except for public interface members. This will currently not differ from always and will act as future proofing for if C# adds default interface methods. +dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion + +#Style - Modifier preferences + +#when this rule is set to a list of modifiers, prefer the specified ordering. +csharp_preferred_modifier_order = public,internal:suggestion + +[*.{cs,vb}] +dotnet_style_allow_statement_immediately_after_block_experimental=false:silent + +[*] +insert_final_newline = true + +dotnet_code_quality.CA1826.exclude_ordefault_methods = true diff --git a/LibSVMSharp.Tests/Contants.cs b/LibSVMSharp.Tests/Contants.cs index cd0e6ac..bee3ee3 100644 --- a/LibSVMSharp.Tests/Contants.cs +++ b/LibSVMSharp.Tests/Contants.cs @@ -4,12 +4,11 @@ using System.Text; using System.Threading.Tasks; -namespace LibSVMSharp.Tests +namespace LibSVMSharp.Tests; + +public static class Contants { - public static class Contants - { - public const string WRONG_MODEL_PATH_TO_BE_LOADED = @"Models/model_does_not_exist.txt"; - public const string CORRECT_MODEL_PATH_TO_BE_LOADED = @"Models/correct_model.txt"; - public const string CORRECT_MODEL_PATH_TO_BE_SAVED = @"Models/correct_model.txt"; - } + public const string WRONG_MODEL_PATH_TO_BE_LOADED = @"Models/model_does_not_exist.txt"; + public const string CORRECT_MODEL_PATH_TO_BE_LOADED = @"Models/correct_model.txt"; + public const string CORRECT_MODEL_PATH_TO_BE_SAVED = @"Models/correct_model.txt"; } diff --git a/LibSVMSharp.Tests/Extensions/TestSVMProblemExtensions.cs b/LibSVMSharp.Tests/Extensions/TestSVMProblemExtensions.cs index 2487cca..12971a4 100644 --- a/LibSVMSharp.Tests/Extensions/TestSVMProblemExtensions.cs +++ b/LibSVMSharp.Tests/Extensions/TestSVMProblemExtensions.cs @@ -1,14 +1,13 @@ using System; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace LibSVMSharp.Tests.Extensions +namespace LibSVMSharp.Tests.Extensions; + +[TestClass] +public class TestSVMProblemExtensions { - [TestClass] - public class TestSVMProblemExtensions + [TestMethod] + public void TestMethod1() { - [TestMethod] - public void TestMethod1() - { - } } } diff --git a/LibSVMSharp.Tests/Helpers/TestSVMHelper.cs b/LibSVMSharp.Tests/Helpers/TestSVMHelper.cs index 24424ed..eddcb0b 100644 --- a/LibSVMSharp.Tests/Helpers/TestSVMHelper.cs +++ b/LibSVMSharp.Tests/Helpers/TestSVMHelper.cs @@ -1,14 +1,13 @@ using System; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace LibSVMSharp.Tests.Helpers +namespace LibSVMSharp.Tests.Helpers; + +[TestClass] +public class TestSVMHelper { - [TestClass] - public class TestSVMHelper + [TestMethod] + public void TestMethod1() { - [TestMethod] - public void TestMethod1() - { - } } } diff --git a/LibSVMSharp.Tests/Helpers/TestSVMNodeHelper.cs b/LibSVMSharp.Tests/Helpers/TestSVMNodeHelper.cs index f88939f..7ff2633 100644 --- a/LibSVMSharp.Tests/Helpers/TestSVMNodeHelper.cs +++ b/LibSVMSharp.Tests/Helpers/TestSVMNodeHelper.cs @@ -1,14 +1,13 @@ using System; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace LibSVMSharp.Tests.Helpers +namespace LibSVMSharp.Tests.Helpers; + +[TestClass] +public class TestSVMNodeHelper { - [TestClass] - public class TestSVMNodeHelper + [TestMethod] + public void TestMethod1() { - [TestMethod] - public void TestMethod1() - { - } } } diff --git a/LibSVMSharp.Tests/Helpers/TestSVMProblemHelper.cs b/LibSVMSharp.Tests/Helpers/TestSVMProblemHelper.cs index 9644cb6..08ecb23 100644 --- a/LibSVMSharp.Tests/Helpers/TestSVMProblemHelper.cs +++ b/LibSVMSharp.Tests/Helpers/TestSVMProblemHelper.cs @@ -1,14 +1,13 @@ using System; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace LibSVMSharp.Tests.Helpers +namespace LibSVMSharp.Tests.Helpers; + +[TestClass] +public class TestSVMProblemHelper { - [TestClass] - public class TestSVMProblemHelper + [TestMethod] + public void TestMethod1() { - [TestMethod] - public void TestMethod1() - { - } } } diff --git a/LibSVMSharp.Tests/TestSVM.cs b/LibSVMSharp.Tests/TestSVM.cs index b5f21ff..c336de9 100644 --- a/LibSVMSharp.Tests/TestSVM.cs +++ b/LibSVMSharp.Tests/TestSVM.cs @@ -2,208 +2,207 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using LibSVMsharp; -namespace LibSVMSharp.Tests +namespace LibSVMSharp.Tests; + +[TestClass] +public class TestSVM { - [TestClass] - public class TestSVM - { - [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] - public void SVM_Train_ProblemIsNull_ThrowsException() - { - SVM.Train(null, new SVMParameter()); - } - [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] - public void SVM_Train_ParameterIsNull_ThrowsException() - { - SVM.Train(new SVMProblem(), null); - } - //[TestMethod] - public void SVM_Train_Correct() - { - - } - - [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] - public void SVM_CrossValidation_ProblemIsNull_ThrowsException() - { - double[] target; - SVM.CrossValidation(null, new SVMParameter(), 5, out target); - } - [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] - public void SVM_CrossValidation_ParameterIsNull_ThrowsException() - { - double[] target; - SVM.CrossValidation(new SVMProblem(), null, 5, out target); - } - [TestMethod] - [ExpectedException(typeof(ArgumentOutOfRangeException))] - public void SVM_CrossValidation_FoldNumberIsOutOfRange_ThrowsException() - { - double[] target; - SVM.CrossValidation(new SVMProblem(), new SVMParameter(), 1, out target); - } - //[TestMethod] - public void SVM_CrossValidation_Correct() - { - - } - - [TestMethod] - public void SVM_SaveModel_ModelIsNull_ReturnsFalse() - { - bool success = SVM.SaveModel(null, Contants.CORRECT_MODEL_PATH_TO_BE_SAVED); - - Assert.IsFalse(success); - } - [TestMethod] - public void SVM_SaveModel_FilenameIsInvalid_ReturnsFalse() - { - bool success = SVM.SaveModel(new SVMModel(), ""); - - Assert.IsFalse(success); - } - //[TestMethod] - public void SVM_SaveModel_Correct() - { - - } - - [TestMethod] - public void SVM_LoadModel_FilenameIsInvalid_ReturnsNull() - { - SVM.LoadModel(""); - } - [TestMethod] - public void SVM_LoadModel_FilenameDoesNotExist_ReturnsNull() - { - SVM.LoadModel(Contants.WRONG_MODEL_PATH_TO_BE_LOADED); - } - //[TestMethod] - public void SVM_LoadModel_ModelFileIsInvalid_ReturnsNull() - { - - } - //[TestMethod] - public void SVM_LoadModel_Correct() - { - - } - - [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] - public void SVM_PredictValues_ModelIsNull_ThrowsException() - { - double[] values; - SVM.PredictValues(null, new SVMNode[5], out values); - } - [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] - public void SVM_PredictValues_ModelIsZero_ThrowsException() - { - double[] values; - SVM.PredictValues(IntPtr.Zero, new SVMNode[5], out values); - } - [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] - public void SVM_PredictValues_InputVectorIsNull_ThrowsException() - { - double[] values; - SVM.PredictValues(new SVMModel(), null, out values); - } - //[TestMethod] - public void SVM_PredictValues_Correct() - { - - } - - [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] - public void SVM_Predict_ModelIsNull_ThrowsException() - { - SVM.Predict(null, new SVMNode[5]); - } - [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] - public void SVM_Predict_ModelIsZero_ThrowsException() - { - SVM.Predict(IntPtr.Zero, new SVMNode[5]); - } - [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] - public void SVM_Predict_InputVectorIsNull_ThrowsException() - { - SVM.Predict(new SVMModel(), null); - } - //[TestMethod] - public void SVM_Predict_Correct() - { - - } - - [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] - public void SVM_PredictProbability_ModelIsNull_ThrowsException() - { - double[] values; - SVM.PredictProbability(null, new SVMNode[5], out values); - } - [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] - public void SVM_PredictProbability_ModelIsZero_ThrowsException() - { - double[] values; - SVM.PredictProbability(IntPtr.Zero, new SVMNode[5], out values); - } - [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] - public void SVM_PredictProbability_InputVectorIsNull_ThrowsException() - { - double[] values; - SVM.PredictProbability(new SVMModel(), null, out values); - } - //[TestMethod] - public void SVM_PredictProbability_NotProbabilityModel_ReturnsNegativeNumber() - { - - } - //[TestMethod] - public void SVM_PredictProbability_Correct() - { - - } - - [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] - public void SVM_CheckParameter_ProblemIsNull_ThrowsException() - { - SVM.CheckParameter(null, new SVMParameter()); - } - [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] - public void SVM_CheckParameter_ParameterIsNull_ThrowsException() - { - SVM.CheckParameter(new SVMProblem(), null); - } - //[TestMethod] - public void SVM_CheckParameter_Correct() - { - - } - - [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] - public void SVM_CheckProbabilityModel_ModelIsNull_ThrowsException() - { - SVM.CheckProbabilityModel(null); - } - //[TestMethod] - public void SVM_CheckProbabilityModel_Correct() - { - - } + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void SVM_Train_ProblemIsNull_ThrowsException() + { + SVM.Train(null, new SVMParameter()); + } + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void SVM_Train_ParameterIsNull_ThrowsException() + { + SVM.Train(new SVMProblem(), null); + } + //[TestMethod] + public void SVM_Train_Correct() + { + + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void SVM_CrossValidation_ProblemIsNull_ThrowsException() + { + double[] target; + SVM.CrossValidation(null, new SVMParameter(), 5, out target); + } + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void SVM_CrossValidation_ParameterIsNull_ThrowsException() + { + double[] target; + SVM.CrossValidation(new SVMProblem(), null, 5, out target); + } + [TestMethod] + [ExpectedException(typeof(ArgumentOutOfRangeException))] + public void SVM_CrossValidation_FoldNumberIsOutOfRange_ThrowsException() + { + double[] target; + SVM.CrossValidation(new SVMProblem(), new SVMParameter(), 1, out target); + } + //[TestMethod] + public void SVM_CrossValidation_Correct() + { + + } + + [TestMethod] + public void SVM_SaveModel_ModelIsNull_ReturnsFalse() + { + bool success = SVM.SaveModel(null, Contants.CORRECT_MODEL_PATH_TO_BE_SAVED); + + Assert.IsFalse(success); + } + [TestMethod] + public void SVM_SaveModel_FilenameIsInvalid_ReturnsFalse() + { + bool success = SVM.SaveModel(new SVMModel(), ""); + + Assert.IsFalse(success); + } + //[TestMethod] + public void SVM_SaveModel_Correct() + { + + } + + [TestMethod] + public void SVM_LoadModel_FilenameIsInvalid_ReturnsNull() + { + SVM.LoadModel(""); + } + [TestMethod] + public void SVM_LoadModel_FilenameDoesNotExist_ReturnsNull() + { + SVM.LoadModel(Contants.WRONG_MODEL_PATH_TO_BE_LOADED); + } + //[TestMethod] + public void SVM_LoadModel_ModelFileIsInvalid_ReturnsNull() + { + + } + //[TestMethod] + public void SVM_LoadModel_Correct() + { + + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void SVM_PredictValues_ModelIsNull_ThrowsException() + { + double[] values; + SVM.PredictValues(null, new SVMNode[5], out values); + } + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void SVM_PredictValues_ModelIsZero_ThrowsException() + { + double[] values; + SVM.PredictValues(IntPtr.Zero, new SVMNode[5], out values); + } + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void SVM_PredictValues_InputVectorIsNull_ThrowsException() + { + double[] values; + SVM.PredictValues(new SVMModel(), null, out values); + } + //[TestMethod] + public void SVM_PredictValues_Correct() + { + + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void SVM_Predict_ModelIsNull_ThrowsException() + { + SVM.Predict(null, new SVMNode[5]); + } + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void SVM_Predict_ModelIsZero_ThrowsException() + { + SVM.Predict(IntPtr.Zero, new SVMNode[5]); + } + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void SVM_Predict_InputVectorIsNull_ThrowsException() + { + SVM.Predict(new SVMModel(), null); + } + //[TestMethod] + public void SVM_Predict_Correct() + { + + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void SVM_PredictProbability_ModelIsNull_ThrowsException() + { + double[] values; + SVM.PredictProbability(null, new SVMNode[5], out values); + } + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void SVM_PredictProbability_ModelIsZero_ThrowsException() + { + double[] values; + SVM.PredictProbability(IntPtr.Zero, new SVMNode[5], out values); + } + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void SVM_PredictProbability_InputVectorIsNull_ThrowsException() + { + double[] values; + SVM.PredictProbability(new SVMModel(), null, out values); + } + //[TestMethod] + public void SVM_PredictProbability_NotProbabilityModel_ReturnsNegativeNumber() + { + + } + //[TestMethod] + public void SVM_PredictProbability_Correct() + { + + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void SVM_CheckParameter_ProblemIsNull_ThrowsException() + { + SVM.CheckParameter(null, new SVMParameter()); + } + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void SVM_CheckParameter_ParameterIsNull_ThrowsException() + { + SVM.CheckParameter(new SVMProblem(), null); + } + //[TestMethod] + public void SVM_CheckParameter_Correct() + { + + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void SVM_CheckProbabilityModel_ModelIsNull_ThrowsException() + { + SVM.CheckProbabilityModel(null); + } + //[TestMethod] + public void SVM_CheckProbabilityModel_Correct() + { + } } diff --git a/LibSVMSharp.Tests/TestSVMModel.cs b/LibSVMSharp.Tests/TestSVMModel.cs index 82f39ed..03ed67b 100644 --- a/LibSVMSharp.Tests/TestSVMModel.cs +++ b/LibSVMSharp.Tests/TestSVMModel.cs @@ -1,14 +1,13 @@ using System; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace LibSVMSharp.Tests +namespace LibSVMSharp.Tests; + +[TestClass] +public class TestSVMModel { - [TestClass] - public class TestSVMModel + [TestMethod] + public void TestMethod1() { - [TestMethod] - public void TestMethod1() - { - } } } diff --git a/LibSVMSharp.Tests/TestSVMNode.cs b/LibSVMSharp.Tests/TestSVMNode.cs index d77441c..4073021 100644 --- a/LibSVMSharp.Tests/TestSVMNode.cs +++ b/LibSVMSharp.Tests/TestSVMNode.cs @@ -1,14 +1,13 @@ using System; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace LibSVMSharp.Tests +namespace LibSVMSharp.Tests; + +[TestClass] +public class TestSVMNode { - [TestClass] - public class TestSVMNode + [TestMethod] + public void TestMethod1() { - [TestMethod] - public void TestMethod1() - { - } } } diff --git a/LibSVMSharp.Tests/TestSVMParameter.cs b/LibSVMSharp.Tests/TestSVMParameter.cs index 3aee3f8..f6d912b 100644 --- a/LibSVMSharp.Tests/TestSVMParameter.cs +++ b/LibSVMSharp.Tests/TestSVMParameter.cs @@ -1,14 +1,13 @@ using System; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace LibSVMSharp.Tests +namespace LibSVMSharp.Tests; + +[TestClass] +public class TestSVMParameter { - [TestClass] - public class TestSVMParameter + [TestMethod] + public void TestMethod1() { - [TestMethod] - public void TestMethod1() - { - } } } diff --git a/LibSVMSharp.Tests/TestSVMProblem.cs b/LibSVMSharp.Tests/TestSVMProblem.cs index bcb409f..3350895 100644 --- a/LibSVMSharp.Tests/TestSVMProblem.cs +++ b/LibSVMSharp.Tests/TestSVMProblem.cs @@ -1,14 +1,13 @@ using System; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace LibSVMSharp.Tests +namespace LibSVMSharp.Tests; + +[TestClass] +public class TestSVMProblem { - [TestClass] - public class TestSVMProblem + [TestMethod] + public void TestMethod1() { - [TestMethod] - public void TestMethod1() - { - } } } diff --git a/LibSVMsharp.Examples.Classification/LibSVMsharp.Examples.Classification.csproj b/LibSVMsharp.Examples.Classification/LibSVMsharp.Examples.Classification.csproj index 1fc5277..738b01a 100644 --- a/LibSVMsharp.Examples.Classification/LibSVMsharp.Examples.Classification.csproj +++ b/LibSVMsharp.Examples.Classification/LibSVMsharp.Examples.Classification.csproj @@ -1,14 +1,13 @@  - {40F859AD-241A-4379-831C-8FB69BE6A8B1} Exe net48 - ..\ LibSVMsharp.Examples.Classification LibSVMsharp.Examples.Classification Copyright © 2014 bin\$(Configuration)\ x64 + 12 full diff --git a/LibSVMsharp.Examples.Classification/Program.cs b/LibSVMsharp.Examples.Classification/Program.cs index 628ba06..cee17aa 100644 --- a/LibSVMsharp.Examples.Classification/Program.cs +++ b/LibSVMsharp.Examples.Classification/Program.cs @@ -1,83 +1,78 @@ using LibSVMsharp.Helpers; using LibSVMsharp.Extensions; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -namespace LibSVMsharp.Examples.Classification +namespace LibSVMsharp.Examples.Classification; + +class Program { - class Program + static void PrintFunction(string output) { - static void PrintFunction(string output) - { - Console.Write(output); - } + Console.Write(output); + } - static void Main(string[] args) - { - // Set print function for accessing output logs - // Please do not call this function more than a couple of times since it may cause memory leak ! - SVM.SetPrintStringFunction(new SVMPrintFunction(PrintFunction)); + static void Main(string[] args) + { + // Set print function for accessing output logs + // Please do not call this function more than a couple of times since it may cause memory leak ! + SVM.SetPrintStringFunction(new SVMPrintFunction(PrintFunction)); - // Load the datasets: In this example I use the same datasets for training and testing which is not suggested - SVMProblem trainingSet = SVMProblemHelper.Load(@"Dataset\wine.txt"); - SVMProblem testSet = SVMProblemHelper.Load(@"Dataset\wine.txt"); + // Load the datasets: In this example I use the same datasets for training and testing which is not suggested + SVMProblem trainingSet = SVMProblemHelper.Load(@"Dataset\wine.txt"); + SVMProblem testSet = SVMProblemHelper.Load(@"Dataset\wine.txt"); - // Normalize the datasets if you want: L2 Norm => x / ||x|| - trainingSet = trainingSet.Normalize(SVMNormType.L2); - testSet = testSet.Normalize(SVMNormType.L2); + // Normalize the datasets if you want: L2 Norm => x / ||x|| + trainingSet = trainingSet.Normalize(SVMNormType.L2); + testSet = testSet.Normalize(SVMNormType.L2); - // Select the parameter set - SVMParameter parameter = new SVMParameter(); - parameter.Type = SVMType.C_SVC; - parameter.Kernel = SVMKernelType.RBF; - parameter.C = 1; - parameter.Gamma = 1; + // Select the parameter set + SVMParameter parameter = new SVMParameter(); + parameter.Type = SVMType.C_SVC; + parameter.Kernel = SVMKernelType.RBF; + parameter.C = 1; + parameter.Gamma = 1; - // Do cross validation to check this parameter set is correct for the dataset or not - double[] crossValidationResults; // output labels - int nFold = 5; - trainingSet.CrossValidation(parameter, nFold, out crossValidationResults); + // Do cross validation to check this parameter set is correct for the dataset or not + double[] crossValidationResults; // output labels + int nFold = 5; + trainingSet.CrossValidation(parameter, nFold, out crossValidationResults); - // Evaluate the cross validation result - // If it is not good enough, select the parameter set again - double crossValidationAccuracy = trainingSet.EvaluateClassificationProblem(crossValidationResults); + // Evaluate the cross validation result + // If it is not good enough, select the parameter set again + double crossValidationAccuracy = trainingSet.EvaluateClassificationProblem(crossValidationResults); - // Train the model, If your parameter set gives good result on cross validation - SVMModel model = trainingSet.Train(parameter); + // Train the model, If your parameter set gives good result on cross validation + SVMModel model = trainingSet.Train(parameter); - // Save the model - SVM.SaveModel(model, @"Model\wine_model.txt"); + // Save the model + SVM.SaveModel(model, @"Model\wine_model.txt"); - // Predict the instances in the test set - double[] testResults = testSet.Predict(model); + // Predict the instances in the test set + double[] testResults = testSet.Predict(model); - // Evaluate the test results - int[,] confusionMatrix; - double testAccuracy = testSet.EvaluateClassificationProblem(testResults, model.Labels, out confusionMatrix); + // Evaluate the test results + int[,] confusionMatrix; + double testAccuracy = testSet.EvaluateClassificationProblem(testResults, model.Labels, out confusionMatrix); - // Print the resutls - Console.WriteLine("\n\nCross validation accuracy: " + crossValidationAccuracy); - Console.WriteLine("\nTest accuracy: " + testAccuracy); - Console.WriteLine("\nConfusion matrix:\n"); + // Print the resutls + Console.WriteLine("\n\nCross validation accuracy: " + crossValidationAccuracy); + Console.WriteLine("\nTest accuracy: " + testAccuracy); + Console.WriteLine("\nConfusion matrix:\n"); - // Print formatted confusion matrix - Console.Write(String.Format("{0,6}", "")); - for (int i = 0; i < model.Labels.Length; i++) - Console.Write(String.Format("{0,5}", "(" + model.Labels[i] + ")")); + // Print formatted confusion matrix + Console.Write(String.Format("{0,6}", "")); + for (int i = 0; i < model.Labels.Length; i++) + Console.Write(String.Format("{0,5}", "(" + model.Labels[i] + ")")); + Console.WriteLine(); + for (int i = 0; i < confusionMatrix.GetLength(0); i++) + { + Console.Write(String.Format("{0,5}", "(" + model.Labels[i] + ")")); + for (int j = 0; j < confusionMatrix.GetLength(1); j++) + Console.Write(String.Format("{0,5}", confusionMatrix[i,j])); Console.WriteLine(); - for (int i = 0; i < confusionMatrix.GetLength(0); i++) - { - Console.Write(String.Format("{0,5}", "(" + model.Labels[i] + ")")); - for (int j = 0; j < confusionMatrix.GetLength(1); j++) - Console.Write(String.Format("{0,5}", confusionMatrix[i,j])); - Console.WriteLine(); - } - - Console.WriteLine("\n\nPress any key to quit..."); - Console.ReadLine(); } + + Console.WriteLine("\n\nPress any key to quit..."); + Console.ReadLine(); } } diff --git a/LibSVMsharp.Examples.RapidPrediction/LibSVMsharp.Examples.RapidPrediction.csproj b/LibSVMsharp.Examples.RapidPrediction/LibSVMsharp.Examples.RapidPrediction.csproj index d010974..a267ba6 100644 --- a/LibSVMsharp.Examples.RapidPrediction/LibSVMsharp.Examples.RapidPrediction.csproj +++ b/LibSVMsharp.Examples.RapidPrediction/LibSVMsharp.Examples.RapidPrediction.csproj @@ -1,14 +1,12 @@  - {FFDF7EA5-53DA-4DF7-9DD8-E4E7DE2B5AB6} Exe net48 - ..\ LibSVMsharp.Examples.RapidPrediction LibSVMsharp.Examples.RapidPrediction Copyright © 2014 x64 - bin\$(Configuration)\ + 12 full diff --git a/LibSVMsharp.Examples.RapidPrediction/Program.cs b/LibSVMsharp.Examples.RapidPrediction/Program.cs index b15c14e..804ea44 100644 --- a/LibSVMsharp.Examples.RapidPrediction/Program.cs +++ b/LibSVMsharp.Examples.RapidPrediction/Program.cs @@ -1,81 +1,76 @@ using LibSVMsharp.Helpers; using LibSVMsharp.Extensions; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Diagnostics; -namespace LibSVMsharp.Examples.RapidPrediction +namespace LibSVMsharp.Examples.RapidPrediction; + +class Program { - class Program + static Stopwatch sw = new Stopwatch(); + + static void Main(string[] args) { - static Stopwatch sw = new Stopwatch(); + SVMProblem testSet = SVMProblemHelper.Load(@"Dataset\wine.txt"); // Same as the training set + SVMModel model = SVM.LoadModel(@"Model\wine_model.txt"); - static void Main(string[] args) - { - SVMProblem testSet = SVMProblemHelper.Load(@"Dataset\wine.txt"); // Same as the training set - SVMModel model = SVM.LoadModel(@"Model\wine_model.txt"); + Console.WriteLine("Feature count in one instance: " + model.SV[0].Length +"\n\n"); - Console.WriteLine("Feature count in one instance: " + model.SV[0].Length +"\n\n"); + // Test 1: Predict instances with SVMProblem's Predict extension method. - // Test 1: Predict instances with SVMProblem's Predict extension method. + sw.Start(); - sw.Start(); + double[] target = testSet.Predict(model); - double[] target = testSet.Predict(model); + sw.Stop(); + double elapsedTimeInTest1 = (double)sw.ElapsedMilliseconds / (double)testSet.Length; - sw.Stop(); - double elapsedTimeInTest1 = (double)sw.ElapsedMilliseconds / (double)testSet.Length; + Console.WriteLine("> Test 1: \nPredict instances with SVMProblem's Predict extension method.\n"); + Console.WriteLine("\tAverage elapsed time of one prediction: " + elapsedTimeInTest1 + " ms\n"); + + // Test 2: Predict instances with RapidPreditor class which is an explicit implementation of the method used in Test 1. + + using (RapidPredictor predictor = new RapidPredictor(model)) // It needs to be Disposed + { + sw.Start(); - Console.WriteLine("> Test 1: \nPredict instances with SVMProblem's Predict extension method.\n"); - Console.WriteLine("\tAverage elapsed time of one prediction: " + elapsedTimeInTest1 + " ms\n"); + target = new double[testSet.Length]; + for (int i = 0; i < testSet.Length; i++) + target[i] = predictor.Predict(testSet.X[i]); - // Test 2: Predict instances with RapidPreditor class which is an explicit implementation of the method used in Test 1. + sw.Stop(); + } + double elapsedTimeInTest2 = (double)sw.ElapsedMilliseconds / (double)testSet.Length; - using (RapidPredictor predictor = new RapidPredictor(model)) // It needs to be Disposed - { - sw.Start(); + Console.WriteLine("> Test 2: \nPredict instances with RapidPreditor class which is an explicit implementation of the method used in Test 1.\n"); + Console.WriteLine("\tAverage elapsed time of one prediction: " + elapsedTimeInTest2 + " ms\n"); - target = new double[testSet.Length]; - for (int i = 0; i < testSet.Length; i++) - target[i] = predictor.Predict(testSet.X[i]); + // Test 3: Predict instances with standard SVM.Predict method or SVMNode[]'s predict extension method. - sw.Stop(); - } - double elapsedTimeInTest2 = (double)sw.ElapsedMilliseconds / (double)testSet.Length; + sw.Start(); - Console.WriteLine("> Test 2: \nPredict instances with RapidPreditor class which is an explicit implementation of the method used in Test 1.\n"); - Console.WriteLine("\tAverage elapsed time of one prediction: " + elapsedTimeInTest2 + " ms\n"); + target = new double[testSet.Length]; + for (int i = 0; i < testSet.Length; i++) + target[i] = SVM.Predict(model, testSet.X[i]); - // Test 3: Predict instances with standard SVM.Predict method or SVMNode[]'s predict extension method. + sw.Stop(); + double elapsedTimeInTest3 = (double)sw.ElapsedMilliseconds / (double)testSet.Length; - sw.Start(); + Console.WriteLine("> Test 3: \nPredict instances with standard SVM.Predict method or SVMNode[]'s Predict extension method.\n"); + Console.WriteLine("\tAverage elapsed time of one prediction: " + elapsedTimeInTest3 + " ms\n"); - target = new double[testSet.Length]; - for (int i = 0; i < testSet.Length; i++) - target[i] = SVM.Predict(model, testSet.X[i]); + // Print the results + Console.WriteLine("\nExplanation:\n"); + Console.WriteLine( + "In standard SVM.Predict method, the SVMModel object is allocated and deallocated every time when the method called. " + + "Also the SVMNode[]'s Predict extension methods directly calls the SVM.Predict. " + + "However, the model is allocated once and is used to predict whole instances with its pointer in SVMProblem's " + + "Predict extension method as implemented in the RapidPredictor class. You can take or modify this class in order " + + "to use in your applications, if you have performance considerations. " + + "I am not suggesting that SVMProblem's Predict extension method is used in real-time, because the model is allocated" + + "in every method call."); - sw.Stop(); - double elapsedTimeInTest3 = (double)sw.ElapsedMilliseconds / (double)testSet.Length; - - Console.WriteLine("> Test 3: \nPredict instances with standard SVM.Predict method or SVMNode[]'s Predict extension method.\n"); - Console.WriteLine("\tAverage elapsed time of one prediction: " + elapsedTimeInTest3 + " ms\n"); - - // Print the results - Console.WriteLine("\nExplanation:\n"); - Console.WriteLine( - "In standard SVM.Predict method, the SVMModel object is allocated and deallocated every time when the method called. " + - "Also the SVMNode[]'s Predict extension methods directly calls the SVM.Predict. " + - "However, the model is allocated once and is used to predict whole instances with its pointer in SVMProblem's " + - "Predict extension method as implemented in the RapidPredictor class. You can take or modify this class in order " + - "to use in your applications, if you have performance considerations. " + - "I am not suggesting that SVMProblem's Predict extension method is used in real-time, because the model is allocated" + - "in every method call."); - - Console.WriteLine("\n\nPress any key to quit..."); - Console.ReadLine(); - } + Console.WriteLine("\n\nPress any key to quit..."); + Console.ReadLine(); } } diff --git a/LibSVMsharp.Examples.RapidPrediction/RapidPredictor.cs b/LibSVMsharp.Examples.RapidPrediction/RapidPredictor.cs index 5f877d0..0aabf4f 100644 --- a/LibSVMsharp.Examples.RapidPrediction/RapidPredictor.cs +++ b/LibSVMsharp.Examples.RapidPrediction/RapidPredictor.cs @@ -8,45 +8,44 @@ using System.Text; using System.Threading.Tasks; -namespace LibSVMsharp.Examples.RapidPrediction +namespace LibSVMsharp.Examples.RapidPrediction; + +public class RapidPredictor : IDisposable { - public class RapidPredictor : IDisposable - { - private IntPtr _ptr_model = IntPtr.Zero; + private IntPtr _ptr_model = IntPtr.Zero; - public RapidPredictor() : this(null) { } - public RapidPredictor(SVMModel model) - { - SetModel(model); - } + public RapidPredictor() : this(null) { } + public RapidPredictor(SVMModel model) + { + SetModel(model); + } - public SVMModel Model { get; private set; } + public SVMModel Model { get; private set; } - public void SetModel(SVMModel model) - { - if (model != null) - { - Model = model.Clone(); - _ptr_model = SVMModel.Allocate(Model); - } - } - public double Predict(SVMNode[] x) - { - return x.Predict(_ptr_model); - } - public double PredictProbability(SVMNode[] x, out double[] estimations) - { - return x.PredictProbability(_ptr_model, out estimations); - } - public double PredictValues(SVMNode[] x, out double[] values) - { - return x.PredictValues(_ptr_model, out values); - } - public void Dispose() + public void SetModel(SVMModel model) + { + if (model != null) { - SVMModel.Free(_ptr_model); - _ptr_model = IntPtr.Zero; - Model = null; + Model = model.Clone(); + _ptr_model = SVMModel.Allocate(Model); } } + public double Predict(SVMNode[] x) + { + return x.Predict(_ptr_model); + } + public double PredictProbability(SVMNode[] x, out double[] estimations) + { + return x.PredictProbability(_ptr_model, out estimations); + } + public double PredictValues(SVMNode[] x, out double[] values) + { + return x.PredictValues(_ptr_model, out values); + } + public void Dispose() + { + SVMModel.Free(_ptr_model); + _ptr_model = IntPtr.Zero; + Model = null; + } } diff --git a/LibSVMsharp.sln b/LibSVMsharp.sln index 56abbba..18dbd08 100644 --- a/LibSVMsharp.sln +++ b/LibSVMsharp.sln @@ -1,17 +1,22 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.30723.0 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34616.47 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibSVMsharp", "LibSVMsharp\LibSVMsharp.csproj", "{AC04337C-E542-4BE9-8DBD-5B44535299E2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibSVMsharp", "LibSVMsharp\LibSVMsharp.csproj", "{AC04337C-E542-4BE9-8DBD-5B44535299E2}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{B7C949C2-345F-404F-BD38-4F2C0519A5F2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibSVMsharp.Examples.Classification", "LibSVMsharp.Examples.Classification\LibSVMsharp.Examples.Classification.csproj", "{40F859AD-241A-4379-831C-8FB69BE6A8B1}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibSVMsharp.Examples.Classification", "LibSVMsharp.Examples.Classification\LibSVMsharp.Examples.Classification.csproj", "{40F859AD-241A-4379-831C-8FB69BE6A8B1}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibSVMsharp.Examples.RapidPrediction", "LibSVMsharp.Examples.RapidPrediction\LibSVMsharp.Examples.RapidPrediction.csproj", "{FFDF7EA5-53DA-4DF7-9DD8-E4E7DE2B5AB6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibSVMsharp.Examples.RapidPrediction", "LibSVMsharp.Examples.RapidPrediction\LibSVMsharp.Examples.RapidPrediction.csproj", "{FFDF7EA5-53DA-4DF7-9DD8-E4E7DE2B5AB6}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibSVMSharp.Tests", "LibSVMSharp.Tests\LibSVMSharp.Tests.csproj", "{2DE0BD3C-C37B-4B23-9533-2F91C1DD15C3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibSVMSharp.Tests", "LibSVMSharp.Tests\LibSVMSharp.Tests.csproj", "{2DE0BD3C-C37B-4B23-9533-2F91C1DD15C3}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F41B08D2-3D78-401E-9773-CA850D7744CD}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/LibSVMsharp/Core/libsvm.cs b/LibSVMsharp/Core/libsvm.cs index 1cac652..31527cf 100644 --- a/LibSVMsharp/Core/libsvm.cs +++ b/LibSVMsharp/Core/libsvm.cs @@ -1,116 +1,115 @@ using System; using System.Runtime.InteropServices; -namespace LibSVMsharp.Core +namespace LibSVMsharp.Core; + +/// +/// For more information about libsvm project: +/// Official: http://www.csie.ntu.edu.tw/~cjlin/libsvm/ +/// Github: https://github.com/cjlin1/libsvm +/// +public static class libsvm { - /// - /// For more information about libsvm project: - /// Official: http://www.csie.ntu.edu.tw/~cjlin/libsvm/ - /// Github: https://github.com/cjlin1/libsvm - /// - public static class libsvm - { - public static readonly string VERSION = "3.23"; - - /// svm_problem - /// svm_parameter - /// svm_model - [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] - public static extern IntPtr svm_train(IntPtr prob, IntPtr param); - - /// svm_problem - /// svm_parameter - /// int - /// double[] - [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] - public static extern void svm_cross_validation(IntPtr prob, IntPtr param, int nr_fold, IntPtr target); - - /// string - /// svm_model - /// bool - [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] - public static extern int svm_save_model(IntPtr model_file_name, IntPtr model); - - /// string - /// svm_model - [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] - public static extern IntPtr svm_load_model(IntPtr model_file_name); - - /// svm_model - /// int - [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] - public static extern int svm_get_svm_type(IntPtr model); - - /// svm_model - /// int - [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] - public static extern int svm_get_nr_class(IntPtr model); - - /// svm_model - /// int[] - [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] - public static extern void svm_get_labels(IntPtr model, IntPtr label); - - /// svm_model - /// int[] - [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] - public static extern void svm_get_sv_indices(IntPtr model, IntPtr sv_indices); - - /// svm_model - /// int - [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] - public static extern int svm_get_nr_sv(IntPtr model); - - /// svm_model - /// double - [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] - public static extern double svm_get_svr_probability(IntPtr model); - - /// svm_model - /// svm_node[] - /// double[] - /// double - [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] - public static extern double svm_predict_values(IntPtr model, IntPtr x, IntPtr dec_values); - - /// svm_model - /// double[] - /// double - [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] - public static extern double svm_predict(IntPtr model, IntPtr x); - - /// svm_model - /// svm_node[] - /// double[] - /// double - [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] - public static extern double svm_predict_probability(IntPtr model, IntPtr x, IntPtr prob_estimates); - - /// svm_model - [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] - public static extern void svm_free_model_content(IntPtr model_ptr); - - /// svm_model* - [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] - public static extern void svm_free_and_destroy_model(ref IntPtr model_ptr_ptr); - - /// svm_parameter - [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] - public static extern void svm_destroy_param(IntPtr param); - - /// svm_problem - /// svm_parameter - /// string - [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] - public static extern IntPtr svm_check_parameter(IntPtr prob, IntPtr param); - - /// svm_model - /// int - [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] - public static extern bool svm_check_probability_model(IntPtr model); - - /// void (*)(const char *) - [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] - public static extern void svm_set_print_string_function(IntPtr print_function); - } + public static readonly string VERSION = "3.23"; + + /// svm_problem + /// svm_parameter + /// svm_model + [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr svm_train(IntPtr prob, IntPtr param); + + /// svm_problem + /// svm_parameter + /// int + /// double[] + [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] + public static extern void svm_cross_validation(IntPtr prob, IntPtr param, int nr_fold, IntPtr target); + + /// string + /// svm_model + /// bool + [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] + public static extern int svm_save_model(IntPtr model_file_name, IntPtr model); + + /// string + /// svm_model + [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr svm_load_model(IntPtr model_file_name); + + /// svm_model + /// int + [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] + public static extern int svm_get_svm_type(IntPtr model); + + /// svm_model + /// int + [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] + public static extern int svm_get_nr_class(IntPtr model); + + /// svm_model + /// int[] + [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] + public static extern void svm_get_labels(IntPtr model, IntPtr label); + + /// svm_model + /// int[] + [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] + public static extern void svm_get_sv_indices(IntPtr model, IntPtr sv_indices); + + /// svm_model + /// int + [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] + public static extern int svm_get_nr_sv(IntPtr model); + + /// svm_model + /// double + [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] + public static extern double svm_get_svr_probability(IntPtr model); + + /// svm_model + /// svm_node[] + /// double[] + /// double + [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] + public static extern double svm_predict_values(IntPtr model, IntPtr x, IntPtr dec_values); + + /// svm_model + /// double[] + /// double + [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] + public static extern double svm_predict(IntPtr model, IntPtr x); + + /// svm_model + /// svm_node[] + /// double[] + /// double + [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] + public static extern double svm_predict_probability(IntPtr model, IntPtr x, IntPtr prob_estimates); + + /// svm_model + [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] + public static extern void svm_free_model_content(IntPtr model_ptr); + + /// svm_model* + [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] + public static extern void svm_free_and_destroy_model(ref IntPtr model_ptr_ptr); + + /// svm_parameter + [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] + public static extern void svm_destroy_param(IntPtr param); + + /// svm_problem + /// svm_parameter + /// string + [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr svm_check_parameter(IntPtr prob, IntPtr param); + + /// svm_model + /// int + [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] + public static extern bool svm_check_probability_model(IntPtr model); + + /// void (*)(const char *) + [DllImport("libsvm", CallingConvention = CallingConvention.Cdecl)] + public static extern void svm_set_print_string_function(IntPtr print_function); } diff --git a/LibSVMsharp/Core/svm_model.cs b/LibSVMsharp/Core/svm_model.cs index 154c5d7..06a1814 100644 --- a/LibSVMsharp/Core/svm_model.cs +++ b/LibSVMsharp/Core/svm_model.cs @@ -5,23 +5,22 @@ using System.Text; using System.Threading.Tasks; -namespace LibSVMsharp.Core +namespace LibSVMsharp.Core; + +[StructLayout(LayoutKind.Sequential)] +public struct svm_model { - [StructLayout(LayoutKind.Sequential)] - public struct svm_model - { - [MarshalAs(UnmanagedType.Struct, SizeConst = 96)] - public svm_parameter param; - public int nr_class; - public int l; - public IntPtr SV; // svm_node** - public IntPtr sv_coef; // double** - public IntPtr rho; // double* - public IntPtr probA; // double* - public IntPtr probB; // double* - public IntPtr sv_indices; // int* - public IntPtr label; // int* - public IntPtr nSV; // int* - public int free_sv; - } + [MarshalAs(UnmanagedType.Struct, SizeConst = 96)] + public svm_parameter param; + public int nr_class; + public int l; + public IntPtr SV; // svm_node** + public IntPtr sv_coef; // double** + public IntPtr rho; // double* + public IntPtr probA; // double* + public IntPtr probB; // double* + public IntPtr sv_indices; // int* + public IntPtr label; // int* + public IntPtr nSV; // int* + public int free_sv; } diff --git a/LibSVMsharp/Core/svm_node.cs b/LibSVMsharp/Core/svm_node.cs index f237531..381fe4b 100644 --- a/LibSVMsharp/Core/svm_node.cs +++ b/LibSVMsharp/Core/svm_node.cs @@ -5,12 +5,11 @@ using System.Text; using System.Threading.Tasks; -namespace LibSVMsharp.Core +namespace LibSVMsharp.Core; + +[StructLayout(LayoutKind.Sequential)] +public struct svm_node { - [StructLayout(LayoutKind.Sequential)] - public struct svm_node - { - internal int index; - internal double value; - } + internal int index; + internal double value; } diff --git a/LibSVMsharp/Core/svm_parameter.cs b/LibSVMsharp/Core/svm_parameter.cs index 9e3cb84..6babdab 100644 --- a/LibSVMsharp/Core/svm_parameter.cs +++ b/LibSVMsharp/Core/svm_parameter.cs @@ -5,25 +5,24 @@ using System.Text; using System.Threading.Tasks; -namespace LibSVMsharp.Core +namespace LibSVMsharp.Core; + +[StructLayout(LayoutKind.Sequential)] +public struct svm_parameter { - [StructLayout(LayoutKind.Sequential)] - public struct svm_parameter - { - public int svm_type; - public int kernel_type; - public int degree; - public double gamma; - public double coef0; - public double cache_size; - public double eps; - public double C; - public int nr_weight; - public IntPtr weight_label; // int* - public IntPtr weight; // double* - public double nu; - public double p; - public int shrinking; - public int probability; - } + public int svm_type; + public int kernel_type; + public int degree; + public double gamma; + public double coef0; + public double cache_size; + public double eps; + public double C; + public int nr_weight; + public IntPtr weight_label; // int* + public IntPtr weight; // double* + public double nu; + public double p; + public int shrinking; + public int probability; } diff --git a/LibSVMsharp/Core/svm_problem.cs b/LibSVMsharp/Core/svm_problem.cs index 46d5cb1..3a22d30 100644 --- a/LibSVMsharp/Core/svm_problem.cs +++ b/LibSVMsharp/Core/svm_problem.cs @@ -5,13 +5,12 @@ using System.Text; using System.Threading.Tasks; -namespace LibSVMsharp.Core +namespace LibSVMsharp.Core; + +[StructLayout(LayoutKind.Sequential)] +public struct svm_problem { - [StructLayout(LayoutKind.Sequential)] - public struct svm_problem - { - public int l; - public IntPtr y; // double* - public IntPtr x; // svm_node** - } + public int l; + public IntPtr y; // double* + public IntPtr x; // svm_node** } diff --git a/LibSVMsharp/Extensions/SVMModelExtensions.cs b/LibSVMsharp/Extensions/SVMModelExtensions.cs index 3d85127..20b8913 100644 --- a/LibSVMsharp/Extensions/SVMModelExtensions.cs +++ b/LibSVMsharp/Extensions/SVMModelExtensions.cs @@ -4,29 +4,28 @@ using System.Text; using System.Threading.Tasks; -namespace LibSVMsharp.Extensions +namespace LibSVMsharp.Extensions; + +public static class SVMModelExtensions { - public static class SVMModelExtensions + public static bool CheckProbabilityModel(this SVMModel model) + { + return SVM.CheckProbabilityModel(model); + } + public static double PredictProbability(this SVMModel model, SVMNode[] x, out double[] estimations) + { + return SVM.PredictProbability(model, x, out estimations); + } + public static double Predict(this SVMModel model, SVMNode[] x) + { + return SVM.Predict(model, x); + } + public static double PredictValues(this SVMModel model, SVMNode[] x, out double[] values) + { + return SVM.PredictValues(model, x, out values); + } + public static bool SaveModel(this SVMModel model, string filename) { - public static bool CheckProbabilityModel(this SVMModel model) - { - return SVM.CheckProbabilityModel(model); - } - public static double PredictProbability(this SVMModel model, SVMNode[] x, out double[] estimations) - { - return SVM.PredictProbability(model, x, out estimations); - } - public static double Predict(this SVMModel model, SVMNode[] x) - { - return SVM.Predict(model, x); - } - public static double PredictValues(this SVMModel model, SVMNode[] x, out double[] values) - { - return SVM.PredictValues(model, x, out values); - } - public static bool SaveModel(this SVMModel model, string filename) - { - return SVM.SaveModel(model, filename); - } + return SVM.SaveModel(model, filename); } } diff --git a/LibSVMsharp/Extensions/SVMNodeExtensions.cs b/LibSVMsharp/Extensions/SVMNodeExtensions.cs index afab192..fb8e2aa 100644 --- a/LibSVMsharp/Extensions/SVMNodeExtensions.cs +++ b/LibSVMsharp/Extensions/SVMNodeExtensions.cs @@ -5,37 +5,36 @@ using System.Text; using System.Threading.Tasks; -namespace LibSVMsharp.Extensions +namespace LibSVMsharp.Extensions; + +public static class SVMNodeExtensions { - public static class SVMNodeExtensions + public static SVMNode[] Normalize(this SVMNode[] x, SVMNormType type) + { + return SVMNodeHelper.Normalize(x, type); + } + public static double Predict(this SVMNode[] x, SVMModel model) + { + return SVM.Predict(model, x); + } + public static double Predict(this SVMNode[] x, IntPtr ptr_model) + { + return SVM.Predict(ptr_model, x); + } + public static double PredictProbability(this SVMNode[] x, SVMModel model, out double[] estimations) + { + return SVM.PredictProbability(model, x, out estimations); + } + public static double PredictProbability(this SVMNode[] x, IntPtr ptr_model, out double[] estimations) + { + return SVM.PredictProbability(ptr_model, x, out estimations); + } + public static double PredictValues(this SVMNode[] x, SVMModel model, out double[] values) + { + return SVM.PredictValues(model, x, out values); + } + public static double PredictValues(this SVMNode[] x, IntPtr ptr_model, out double[] values) { - public static SVMNode[] Normalize(this SVMNode[] x, SVMNormType type) - { - return SVMNodeHelper.Normalize(x, type); - } - public static double Predict(this SVMNode[] x, SVMModel model) - { - return SVM.Predict(model, x); - } - public static double Predict(this SVMNode[] x, IntPtr ptr_model) - { - return SVM.Predict(ptr_model, x); - } - public static double PredictProbability(this SVMNode[] x, SVMModel model, out double[] estimations) - { - return SVM.PredictProbability(model, x, out estimations); - } - public static double PredictProbability(this SVMNode[] x, IntPtr ptr_model, out double[] estimations) - { - return SVM.PredictProbability(ptr_model, x, out estimations); - } - public static double PredictValues(this SVMNode[] x, SVMModel model, out double[] values) - { - return SVM.PredictValues(model, x, out values); - } - public static double PredictValues(this SVMNode[] x, IntPtr ptr_model, out double[] values) - { - return SVM.PredictValues(ptr_model, x, out values); - } + return SVM.PredictValues(ptr_model, x, out values); } } diff --git a/LibSVMsharp/Extensions/SVMProblemExtensions.cs b/LibSVMsharp/Extensions/SVMProblemExtensions.cs index 2969e78..d4207f2 100644 --- a/LibSVMsharp/Extensions/SVMProblemExtensions.cs +++ b/LibSVMsharp/Extensions/SVMProblemExtensions.cs @@ -5,92 +5,91 @@ using System.Text; using System.Threading.Tasks; -namespace LibSVMsharp.Extensions +namespace LibSVMsharp.Extensions; + +public static class SVMProblemExtensions { - public static class SVMProblemExtensions + public static string CheckParameter(this SVMProblem problem, SVMParameter parameter) { - public static string CheckParameter(this SVMProblem problem, SVMParameter parameter) - { - return SVM.CheckParameter(problem, parameter); - } - public static SVMProblem RemoveDuplicates(this SVMProblem problem) - { - return SVMProblemHelper.RemoveDuplicates(problem); - } - public static SVMProblem Normalize(this SVMProblem problem, SVMNormType type) - { - return SVMProblemHelper.Normalize(problem, type); - } - public static Dictionary GetLabelsCount(this SVMProblem problem) - { - return SVMProblemHelper.GetLabelsCount(problem); - } - public static bool Save(this SVMProblem problem, string filename) - { - return SVMProblemHelper.Save(problem, filename); - } - public static double EvaluateClassificationProblem(this SVMProblem testset, double[] target) - { - return SVMHelper.EvaluateClassificationProblem(testset, target); - } - public static double EvaluateClassificationProblem(this SVMProblem testset, double[] target, int[] labels, out int[,] confusionMatrix) - { - return SVMHelper.EvaluateClassificationProblem(testset, target, labels, out confusionMatrix); - } - public static double EvaluateRegressionProblem(this SVMProblem testset, double[] target, out double correlation_coef) - { - return SVMHelper.EvaluateRegressionProblem(testset, target, out correlation_coef); - } - public static void CrossValidation(this SVMProblem problem, SVMParameter parameter, int nFolds, out double[] target) - { - SVM.CrossValidation(problem, parameter, nFolds, out target); - } - public static SVMModel Train(this SVMProblem problem, SVMParameter parameter) - { - return SVM.Train(problem, parameter); - } - public static double[] Predict(this SVMProblem problem, SVMModel model) - { - IntPtr ptr_model = SVMModel.Allocate(model); - double[] target = problem.X.Select(x => x.Predict(ptr_model)).ToArray(); - SVMModel.Free(ptr_model); - return target; - } - public static double[] PredictProbability(this SVMProblem problem, SVMModel model, out List estimationsList) + return SVM.CheckParameter(problem, parameter); + } + public static SVMProblem RemoveDuplicates(this SVMProblem problem) + { + return SVMProblemHelper.RemoveDuplicates(problem); + } + public static SVMProblem Normalize(this SVMProblem problem, SVMNormType type) + { + return SVMProblemHelper.Normalize(problem, type); + } + public static Dictionary GetLabelsCount(this SVMProblem problem) + { + return SVMProblemHelper.GetLabelsCount(problem); + } + public static bool Save(this SVMProblem problem, string filename) + { + return SVMProblemHelper.Save(problem, filename); + } + public static double EvaluateClassificationProblem(this SVMProblem testset, double[] target) + { + return SVMHelper.EvaluateClassificationProblem(testset, target); + } + public static double EvaluateClassificationProblem(this SVMProblem testset, double[] target, int[] labels, out int[,] confusionMatrix) + { + return SVMHelper.EvaluateClassificationProblem(testset, target, labels, out confusionMatrix); + } + public static double EvaluateRegressionProblem(this SVMProblem testset, double[] target, out double correlation_coef) + { + return SVMHelper.EvaluateRegressionProblem(testset, target, out correlation_coef); + } + public static void CrossValidation(this SVMProblem problem, SVMParameter parameter, int nFolds, out double[] target) + { + SVM.CrossValidation(problem, parameter, nFolds, out target); + } + public static SVMModel Train(this SVMProblem problem, SVMParameter parameter) + { + return SVM.Train(problem, parameter); + } + public static double[] Predict(this SVMProblem problem, SVMModel model) + { + IntPtr ptr_model = SVMModel.Allocate(model); + double[] target = problem.X.Select(x => x.Predict(ptr_model)).ToArray(); + SVMModel.Free(ptr_model); + return target; + } + public static double[] PredictProbability(this SVMProblem problem, SVMModel model, out List estimationsList) + { + IntPtr ptr_model = SVMModel.Allocate(model); + + List temp = new List(); + double[] target = problem.X.Select(x => { - IntPtr ptr_model = SVMModel.Allocate(model); + double[] estimations; + double y = x.PredictProbability(ptr_model, out estimations); + temp.Add(estimations); + return y; + }).ToArray(); - List temp = new List(); - double[] target = problem.X.Select(x => - { - double[] estimations; - double y = x.PredictProbability(ptr_model, out estimations); - temp.Add(estimations); - return y; - }).ToArray(); + SVMModel.Free(ptr_model); - SVMModel.Free(ptr_model); + estimationsList = temp; + return target; + } + public static double[] PredictValues(this SVMProblem problem, SVMModel model, out List valuesList) + { + IntPtr ptr_model = SVMModel.Allocate(model); - estimationsList = temp; - return target; - } - public static double[] PredictValues(this SVMProblem problem, SVMModel model, out List valuesList) + List temp = new List(); + double[] target = problem.X.Select(x => { - IntPtr ptr_model = SVMModel.Allocate(model); - - List temp = new List(); - double[] target = problem.X.Select(x => - { - double[] estimations; - double y = x.PredictProbability(ptr_model, out estimations); - temp.Add(estimations); - return y; - }).ToArray(); + double[] estimations; + double y = x.PredictProbability(ptr_model, out estimations); + temp.Add(estimations); + return y; + }).ToArray(); - SVMModel.Free(ptr_model); + SVMModel.Free(ptr_model); - valuesList = temp; - return target; - } + valuesList = temp; + return target; } } diff --git a/LibSVMsharp/Helpers/SVMHelper.cs b/LibSVMsharp/Helpers/SVMHelper.cs index dad33d8..e677e6b 100644 --- a/LibSVMsharp/Helpers/SVMHelper.cs +++ b/LibSVMsharp/Helpers/SVMHelper.cs @@ -3,106 +3,105 @@ using System.Linq; using System.Text; -namespace LibSVMsharp.Helpers +namespace LibSVMsharp.Helpers; + +public static class SVMHelper { - public static class SVMHelper + /// + /// + /// + /// + /// + /// Accuracy for C_SVC, NU_SVC and ONE_CLASS. + public static double EvaluateClassificationProblem(SVMProblem testset, double[] target) { - /// - /// - /// - /// - /// - /// Accuracy for C_SVC, NU_SVC and ONE_CLASS. - public static double EvaluateClassificationProblem(SVMProblem testset, double[] target) + if (testset.Length != target.Length) { - if (testset.Length != target.Length) - { - return -1; - } + return -1; + } - int total_correct = 0; - for (int i = 0; i < testset.Length; i++) - { - int y = (int)testset.Y[i]; - int v = (int)target[i]; + int total_correct = 0; + for (int i = 0; i < testset.Length; i++) + { + int y = (int)testset.Y[i]; + int v = (int)target[i]; - if (y == v) - { - ++total_correct; - } + if (y == v) + { + ++total_correct; } - - return 100.0 * ((double)total_correct / (double)testset.Length); } - /// - /// - /// - /// - /// - /// - /// - /// Accuracy for C_SVC, NU_SVC and ONE_CLASS. - public static double EvaluateClassificationProblem(SVMProblem testset, double[] target, int[] labels, out int[,] confusionMatrix) + + return 100.0 * ((double)total_correct / (double)testset.Length); + } + /// + /// + /// + /// + /// + /// + /// + /// Accuracy for C_SVC, NU_SVC and ONE_CLASS. + public static double EvaluateClassificationProblem(SVMProblem testset, double[] target, int[] labels, out int[,] confusionMatrix) + { + if (testset.Length != target.Length) { - if (testset.Length != target.Length) - { - confusionMatrix = null; - return -1; - } + confusionMatrix = null; + return -1; + } - Dictionary indexes = new Dictionary(); - for (int i = 0; i < labels.Length; i++) - { - indexes.Add(labels[i], i); - } - - confusionMatrix = new int[labels.Length, labels.Length]; + Dictionary indexes = new Dictionary(); + for (int i = 0; i < labels.Length; i++) + { + indexes.Add(labels[i], i); + } + + confusionMatrix = new int[labels.Length, labels.Length]; - int total_correct = 0; - for (int i = 0; i < testset.Length; i++) - { - int y = (int)testset.Y[i]; - int v = (int)target[i]; + int total_correct = 0; + for (int i = 0; i < testset.Length; i++) + { + int y = (int)testset.Y[i]; + int v = (int)target[i]; - confusionMatrix[indexes[y], indexes[v]]++; + confusionMatrix[indexes[y], indexes[v]]++; - if (y == v) - { - ++total_correct; - } + if (y == v) + { + ++total_correct; } - - return 100.0 * ((double)total_correct / (double)testset.Length); } - /// - /// - /// - /// - /// - /// Squared correlation coefficient for EPSILON_SVR and NU_SVR. - /// Mean squared error for EPSILON_SVR and NU_SVR. - public static double EvaluateRegressionProblem(SVMProblem testset, double[] target, out double correlationCoeff) + + return 100.0 * ((double)total_correct / (double)testset.Length); + } + /// + /// + /// + /// + /// + /// Squared correlation coefficient for EPSILON_SVR and NU_SVR. + /// Mean squared error for EPSILON_SVR and NU_SVR. + public static double EvaluateRegressionProblem(SVMProblem testset, double[] target, out double correlationCoeff) + { + double total_error = 0; + double sumv = 0, sumy = 0, sumvv = 0, sumyy = 0, sumvy = 0; + for (int i = 0; i < testset.Length; i++) { - double total_error = 0; - double sumv = 0, sumy = 0, sumvv = 0, sumyy = 0, sumvy = 0; - for (int i = 0; i < testset.Length; i++) - { - double y = testset.Y[i]; - double v = target[i]; - total_error += (v - y) * (v - y); - sumv += v; - sumy += y; - sumvv += v * v; - sumyy += y * y; - sumvy += v * y; - } + double y = testset.Y[i]; + double v = target[i]; + total_error += (v - y) * (v - y); + sumv += v; + sumy += y; + sumvv += v * v; + sumyy += y * y; + sumvy += v * y; + } - double mean_squared_error = total_error / (double)testset.Length; - correlationCoeff = - (((double)testset.Length * sumvy - sumv * sumy) * ((double)testset.Length * sumvy - sumv * sumy)) / - (((double)testset.Length * sumvv - sumv * sumv) * ((double)testset.Length * sumyy - sumy * sumy)); + double mean_squared_error = total_error / (double)testset.Length; + correlationCoeff = + (((double)testset.Length * sumvy - sumv * sumy) * ((double)testset.Length * sumvy - sumv * sumy)) / + (((double)testset.Length * sumvv - sumv * sumv) * ((double)testset.Length * sumyy - sumy * sumy)); - return mean_squared_error; - } + return mean_squared_error; } } diff --git a/LibSVMsharp/Helpers/SVMNodeHelper.cs b/LibSVMsharp/Helpers/SVMNodeHelper.cs index 966d71c..3a101a5 100644 --- a/LibSVMsharp/Helpers/SVMNodeHelper.cs +++ b/LibSVMsharp/Helpers/SVMNodeHelper.cs @@ -4,44 +4,43 @@ using System.Text; using System.Threading.Tasks; -namespace LibSVMsharp.Helpers +namespace LibSVMsharp.Helpers; + +public static class SVMNodeHelper { - public static class SVMNodeHelper + /// + /// + /// + /// + /// + /// + /// + /// + public static bool IsEqual(SVMNode[] x1, double y1, SVMNode[] x2, double y2) { - /// - /// - /// - /// - /// - /// - /// - /// - public static bool IsEqual(SVMNode[] x1, double y1, SVMNode[] x2, double y2) + bool same = false; + if (y1 == y2 && x1.Length == x2.Length) { - bool same = false; - if (y1 == y2 && x1.Length == x2.Length) + same = true; + for (int i = 0; i < x1.Length; i++) { - same = true; - for (int i = 0; i < x1.Length; i++) - { - same &= x1[i].Equals(x2[i]); - } + same &= x1[i].Equals(x2[i]); } - return same; - } - /// - /// - /// - /// - /// - /// - public static SVMNode[] Normalize(SVMNode[] x, SVMNormType type) - { - double norm_l = (double)(int)type; - double norm = x.Sum(a => Math.Pow(a.Value, norm_l)); - norm = Math.Pow(norm, 1 / norm_l); - SVMNode[] y = x.Select(a => new SVMNode(a.Index, a.Value / norm)).ToArray(); - return y; } + return same; + } + /// + /// + /// + /// + /// + /// + public static SVMNode[] Normalize(SVMNode[] x, SVMNormType type) + { + double norm_l = (double)(int)type; + double norm = x.Sum(a => Math.Pow(a.Value, norm_l)); + norm = Math.Pow(norm, 1 / norm_l); + SVMNode[] y = x.Select(a => new SVMNode(a.Index, a.Value / norm)).ToArray(); + return y; } } diff --git a/LibSVMsharp/Helpers/SVMProblemHelper.cs b/LibSVMsharp/Helpers/SVMProblemHelper.cs index 50335fc..274bb9c 100644 --- a/LibSVMsharp/Helpers/SVMProblemHelper.cs +++ b/LibSVMsharp/Helpers/SVMProblemHelper.cs @@ -6,173 +6,172 @@ using System.Text; using System.Threading.Tasks; -namespace LibSVMsharp.Helpers +namespace LibSVMsharp.Helpers; + +public enum SVMNormType { - public enum SVMNormType - { - L1 = 1, - L2 = 2, - L3 = 3, - L4 = 4, - L5 = 5 - } + L1 = 1, + L2 = 2, + L3 = 3, + L4 = 4, + L5 = 5 +} - public static class SVMProblemHelper +public static class SVMProblemHelper +{ + /// + /// + /// + /// + /// + public static SVMProblem RemoveDuplicates(SVMProblem problem) { - /// - /// - /// - /// - /// - public static SVMProblem RemoveDuplicates(SVMProblem problem) + SVMProblem temp = new SVMProblem(); + for (int i = 0; i < problem.Length; i++) { - SVMProblem temp = new SVMProblem(); - for (int i = 0; i < problem.Length; i++) + bool same = false; + for (int j = i + 1; j < problem.Length; j++) { - bool same = false; - for (int j = i + 1; j < problem.Length; j++) - { - same |= SVMNodeHelper.IsEqual(problem.X[i], problem.Y[i], problem.X[j], problem.Y[j]); + same |= SVMNodeHelper.IsEqual(problem.X[i], problem.Y[i], problem.X[j], problem.Y[j]); - if (same) - { - break; - } - } - - if (!same) + if (same) { - temp.Add(problem.X[i], problem.Y[i]); + break; } } - return temp; - } - /// - /// - /// - /// - /// - /// - public static SVMProblem Normalize(SVMProblem problem, SVMNormType type) - { - SVMProblem temp = new SVMProblem(); - for (int i = 0; i < problem.Length; i++) + if (!same) { - SVMNode[] x = SVMNodeHelper.Normalize(problem.X[i], type); - temp.Add(x, problem.Y[i]); + temp.Add(problem.X[i], problem.Y[i]); } - return temp; } - /// - /// - /// - /// - /// - public static Dictionary GetLabelsCount(SVMProblem problem) + + return temp; + } + /// + /// + /// + /// + /// + /// + public static SVMProblem Normalize(SVMProblem problem, SVMNormType type) + { + SVMProblem temp = new SVMProblem(); + for (int i = 0; i < problem.Length; i++) { - Dictionary dic = new Dictionary(); - for (int i = 0; i < problem.Length; i++) - { - if (!dic.ContainsKey(problem.Y[i])) - { - dic.Add(problem.Y[i], 1); - } - else - { - dic[problem.Y[i]]++; - } - } - return dic; + SVMNode[] x = SVMNodeHelper.Normalize(problem.X[i], type); + temp.Add(x, problem.Y[i]); } - /// - /// - /// - /// - /// - /// - public static bool Save(SVMProblem problem, string filename) + return temp; + } + /// + /// + /// + /// + /// + public static Dictionary GetLabelsCount(SVMProblem problem) + { + Dictionary dic = new Dictionary(); + for (int i = 0; i < problem.Length; i++) { - if (String.IsNullOrWhiteSpace(filename) || problem == null || problem.Length == 0) + if (!dic.ContainsKey(problem.Y[i])) + { + dic.Add(problem.Y[i], 1); + } + else { - return false; + dic[problem.Y[i]]++; } + } + return dic; + } + /// + /// + /// + /// + /// + /// + public static bool Save(SVMProblem problem, string filename) + { + if (String.IsNullOrWhiteSpace(filename) || problem == null || problem.Length == 0) + { + return false; + } - NumberFormatInfo provider = new NumberFormatInfo(); - provider.NumberDecimalSeparator = "."; + NumberFormatInfo provider = new NumberFormatInfo(); + provider.NumberDecimalSeparator = "."; - using (StreamWriter sw = new StreamWriter(filename)) + using (StreamWriter sw = new StreamWriter(filename)) + { + for (int i = 0; i < problem.Length; i++) { - for (int i = 0; i < problem.Length; i++) + sw.Write(problem.Y[i]); + + if (problem.X[i].Length > 0) { - sw.Write(problem.Y[i]); + sw.Write(" "); - if (problem.X[i].Length > 0) + for (int j = 0; j < problem.X[i].Length; j++) { - sw.Write(" "); + sw.Write(problem.X[i][j].Index); + sw.Write(":"); + sw.Write(problem.X[i][j].Value.ToString(provider)); - for (int j = 0; j < problem.X[i].Length; j++) + if (j < problem.X[i].Length - 1) { - sw.Write(problem.X[i][j].Index); - sw.Write(":"); - sw.Write(problem.X[i][j].Value.ToString(provider)); - - if (j < problem.X[i].Length - 1) - { - sw.Write(" "); - } + sw.Write(" "); } } - - sw.Write("\n"); } - } - return true; + sw.Write("\n"); + } } - /// - /// - /// - /// - /// - public static SVMProblem Load(string filename) + + return true; + } + /// + /// + /// + /// + /// + public static SVMProblem Load(string filename) + { + if (String.IsNullOrWhiteSpace(filename) || !File.Exists(filename)) { - if (String.IsNullOrWhiteSpace(filename) || !File.Exists(filename)) - { - return null; - } + return null; + } - NumberFormatInfo provider = new NumberFormatInfo(); - provider.NumberDecimalSeparator = "."; + NumberFormatInfo provider = new NumberFormatInfo(); + provider.NumberDecimalSeparator = "."; - SVMProblem problem = new SVMProblem(); - using (StreamReader sr = new StreamReader(filename)) + SVMProblem problem = new SVMProblem(); + using (StreamReader sr = new StreamReader(filename)) + { + while (true) { - while (true) - { - string line = sr.ReadLine(); - if (line == null) - break; + string line = sr.ReadLine(); + if (line == null) + break; - string[] list = line.Trim().Split(' '); + string[] list = line.Trim().Split(' '); - double y = Convert.ToDouble(list[0].Trim(), provider); + double y = Convert.ToDouble(list[0].Trim(), provider); - List nodes = new List(); - for (int i = 1; i < list.Length; i++) - { - string[] temp = list[i].Split(':'); - SVMNode node = new SVMNode(); - node.Index = Convert.ToInt32(temp[0].Trim()); - node.Value = Convert.ToDouble(temp[1].Trim(), provider); - nodes.Add(node); - } - - problem.Add(nodes.ToArray(), y); + List nodes = new List(); + for (int i = 1; i < list.Length; i++) + { + string[] temp = list[i].Split(':'); + SVMNode node = new SVMNode(); + node.Index = Convert.ToInt32(temp[0].Trim()); + node.Value = Convert.ToDouble(temp[1].Trim(), provider); + nodes.Add(node); } - } - return problem; + problem.Add(nodes.ToArray(), y); + } } + + return problem; } } diff --git a/LibSVMsharp/SVM.cs b/LibSVMsharp/SVM.cs index 1666d55..5ca193e 100644 --- a/LibSVMsharp/SVM.cs +++ b/LibSVMsharp/SVM.cs @@ -6,429 +6,428 @@ using System.Runtime.InteropServices; using System.Text; -namespace LibSVMsharp +namespace LibSVMsharp; + +public enum SVMType : int { - public enum SVMType : int - { - /// - /// Multi-class classification. - /// - C_SVC = 0, - /// - /// Multi-class classification. - /// - NU_SVC = 1, - /// - /// One class SVM. - /// - ONE_CLASS = 2, - /// - /// Regression. - /// - EPSILON_SVR = 3, - /// - /// Regression. - /// - NU_SVR = 4 - } + /// + /// Multi-class classification. + /// + C_SVC = 0, + /// + /// Multi-class classification. + /// + NU_SVC = 1, + /// + /// One class SVM. + /// + ONE_CLASS = 2, + /// + /// Regression. + /// + EPSILON_SVR = 3, + /// + /// Regression. + /// + NU_SVR = 4 +} - public enum SVMKernelType : int - { - /// - /// Linear: u'*v - /// - LINEAR = 0, - /// - /// Polynomial: (gamma*u'*v + coef0)^degree - /// - POLY = 1, - /// - /// Radial Basis Function: exp(-gamma*|u-v|^2) - /// - RBF = 2, - /// - /// Sigmoid: tanh(gamma*u'*v + coef0) - /// - SIGMOID = 3 - } +public enum SVMKernelType : int +{ + /// + /// Linear: u'*v + /// + LINEAR = 0, + /// + /// Polynomial: (gamma*u'*v + coef0)^degree + /// + POLY = 1, + /// + /// Radial Basis Function: exp(-gamma*|u-v|^2) + /// + RBF = 2, + /// + /// Sigmoid: tanh(gamma*u'*v + coef0) + /// + SIGMOID = 3 +} - public delegate void SVMPrintFunction(string output); +public delegate void SVMPrintFunction(string output); - public static class SVM +public static class SVM +{ + public static string Version { get { return libsvm.VERSION; } } + + /// + /// This function constructs and returns an SVM model according to the given training data and parameters. + /// + /// Training data. + /// Parameter set. + /// SVM model according to the given training data and parameters. + public static SVMModel Train(SVMProblem problem, SVMParameter parameter) { - public static string Version { get { return libsvm.VERSION; } } - - /// - /// This function constructs and returns an SVM model according to the given training data and parameters. - /// - /// Training data. - /// Parameter set. - /// SVM model according to the given training data and parameters. - public static SVMModel Train(SVMProblem problem, SVMParameter parameter) + if (problem == null) { - if (problem == null) - { - throw new ArgumentNullException("problem"); - } + throw new ArgumentNullException("problem"); + } - if (parameter == null) - { - throw new ArgumentNullException("parameter"); - } + if (parameter == null) + { + throw new ArgumentNullException("parameter"); + } - IntPtr ptr_problem = SVMProblem.Allocate(problem); - IntPtr ptr_parameter = SVMParameter.Allocate(parameter); + IntPtr ptr_problem = SVMProblem.Allocate(problem); + IntPtr ptr_parameter = SVMParameter.Allocate(parameter); - IntPtr ptr_model = libsvm.svm_train(ptr_problem, ptr_parameter); - SVMModel model = SVMModel.Convert(ptr_model); + IntPtr ptr_model = libsvm.svm_train(ptr_problem, ptr_parameter); + SVMModel model = SVMModel.Convert(ptr_model); - SVMProblem.Free(ptr_problem); - SVMParameter.Free(ptr_parameter); - libsvm.svm_free_model_content(ptr_model); + SVMProblem.Free(ptr_problem); + SVMParameter.Free(ptr_parameter); + libsvm.svm_free_model_content(ptr_model); - return model; + return model; + } + /// + /// + /// + /// + /// + /// + /// + public static void CrossValidation(SVMProblem problem, SVMParameter parameter, int nFolds, out double[] target) + { + if (problem == null) + { + throw new ArgumentNullException("problem"); } - /// - /// - /// - /// - /// - /// - /// - public static void CrossValidation(SVMProblem problem, SVMParameter parameter, int nFolds, out double[] target) + + if (parameter == null) { - if (problem == null) - { - throw new ArgumentNullException("problem"); - } - - if (parameter == null) - { - throw new ArgumentNullException("parameter"); - } - - if (nFolds < 2) - { - throw new ArgumentOutOfRangeException("nFolds"); - } - - IntPtr ptr_target = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double)) * problem.Length); - IntPtr ptr_problem = SVMProblem.Allocate(problem); - IntPtr ptr_parameter = SVMParameter.Allocate(parameter); - - libsvm.svm_cross_validation(ptr_problem, ptr_parameter, nFolds, ptr_target); - - target = new double[problem.Length]; - Marshal.Copy(ptr_target, target, 0, target.Length); - - SVMProblem.Free(ptr_problem); - SVMParameter.Free(ptr_parameter); - Marshal.FreeHGlobal(ptr_target); - ptr_target = IntPtr.Zero; + throw new ArgumentNullException("parameter"); } - /// - /// - /// - /// - /// - /// - public static bool SaveModel(SVMModel model, string filename) + + if (nFolds < 2) { - if (String.IsNullOrWhiteSpace(filename) || model == null) - { - return false; - } + throw new ArgumentOutOfRangeException("nFolds"); + } - IntPtr ptr_model = SVMModel.Allocate(model); - IntPtr ptr_filename = Marshal.StringToHGlobalAnsi(filename); + IntPtr ptr_target = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double)) * problem.Length); + IntPtr ptr_problem = SVMProblem.Allocate(problem); + IntPtr ptr_parameter = SVMParameter.Allocate(parameter); - bool success = libsvm.svm_save_model(ptr_filename, ptr_model) == 0; + libsvm.svm_cross_validation(ptr_problem, ptr_parameter, nFolds, ptr_target); - Marshal.FreeHGlobal(ptr_filename); - ptr_filename = IntPtr.Zero; + target = new double[problem.Length]; + Marshal.Copy(ptr_target, target, 0, target.Length); - return success; + SVMProblem.Free(ptr_problem); + SVMParameter.Free(ptr_parameter); + Marshal.FreeHGlobal(ptr_target); + ptr_target = IntPtr.Zero; + } + /// + /// + /// + /// + /// + /// + public static bool SaveModel(SVMModel model, string filename) + { + if (String.IsNullOrWhiteSpace(filename) || model == null) + { + return false; } - /// - /// - /// - /// - /// - public static SVMModel LoadModel(string filename) + + IntPtr ptr_model = SVMModel.Allocate(model); + IntPtr ptr_filename = Marshal.StringToHGlobalAnsi(filename); + + bool success = libsvm.svm_save_model(ptr_filename, ptr_model) == 0; + + Marshal.FreeHGlobal(ptr_filename); + ptr_filename = IntPtr.Zero; + + return success; + } + /// + /// + /// + /// + /// + public static SVMModel LoadModel(string filename) + { + if (String.IsNullOrWhiteSpace(filename) || !File.Exists(filename)) { - if (String.IsNullOrWhiteSpace(filename) || !File.Exists(filename)) - { - return null; - } + return null; + } - IntPtr ptr_filename = Marshal.StringToHGlobalAnsi(filename); + IntPtr ptr_filename = Marshal.StringToHGlobalAnsi(filename); - IntPtr ptr_model = libsvm.svm_load_model(ptr_filename); + IntPtr ptr_model = libsvm.svm_load_model(ptr_filename); - Marshal.FreeHGlobal(ptr_filename); - ptr_filename = IntPtr.Zero; + Marshal.FreeHGlobal(ptr_filename); + ptr_filename = IntPtr.Zero; - if (ptr_model == IntPtr.Zero) - { - return null; - } - else - { - SVMModel model = SVMModel.Convert(ptr_model); + if (ptr_model == IntPtr.Zero) + { + return null; + } + else + { + SVMModel model = SVMModel.Convert(ptr_model); - // There is a little memory leackage here !!! - libsvm.svm_free_model_content(ptr_model); - ptr_model = IntPtr.Zero; + // There is a little memory leackage here !!! + libsvm.svm_free_model_content(ptr_model); + ptr_model = IntPtr.Zero; - return model; - } + return model; } - /// - /// - /// - /// - /// - /// - /// - public static double PredictValues(SVMModel model, SVMNode[] x, out double[] values) + } + /// + /// + /// + /// + /// + /// + /// + public static double PredictValues(SVMModel model, SVMNode[] x, out double[] values) + { + if (model == null) { - if (model == null) - { - throw new ArgumentNullException("model"); - } - - if (x == null) - { - throw new ArgumentNullException("x"); - } - - IntPtr ptr_model = SVMModel.Allocate(model); - double result = PredictValues(ptr_model, x, out values); - SVMModel.Free(ptr_model); - return result; + throw new ArgumentNullException("model"); } - /// - /// - /// - /// - /// - /// - /// - public static double PredictValues(IntPtr ptr_model, SVMNode[] x, out double[] values) + + if (x == null) + { + throw new ArgumentNullException("x"); + } + + IntPtr ptr_model = SVMModel.Allocate(model); + double result = PredictValues(ptr_model, x, out values); + SVMModel.Free(ptr_model); + return result; + } + /// + /// + /// + /// + /// + /// + /// + public static double PredictValues(IntPtr ptr_model, SVMNode[] x, out double[] values) + { + if (ptr_model == IntPtr.Zero) { - if (ptr_model == IntPtr.Zero) - { - throw new ArgumentNullException("ptr_model"); - } + throw new ArgumentNullException("ptr_model"); + } - if (x == null) - { - throw new ArgumentNullException("x"); - } + if (x == null) + { + throw new ArgumentNullException("x"); + } - int classCount = libsvm.svm_get_nr_class(ptr_model); - int size = (int)(classCount * (classCount - 1) * 0.5); - IntPtr ptr_values = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double)) * size); + int classCount = libsvm.svm_get_nr_class(ptr_model); + int size = (int)(classCount * (classCount - 1) * 0.5); + IntPtr ptr_values = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double)) * size); - List nodes = x.Select(a => a.Clone()).ToList(); - nodes.Add(new SVMNode(-1, 0)); - IntPtr ptr_nodes = SVMNode.Allocate(nodes.ToArray()); + List nodes = x.Select(a => a.Clone()).ToList(); + nodes.Add(new SVMNode(-1, 0)); + IntPtr ptr_nodes = SVMNode.Allocate(nodes.ToArray()); - double result = libsvm.svm_predict_values(ptr_model, ptr_nodes, ptr_values); + double result = libsvm.svm_predict_values(ptr_model, ptr_nodes, ptr_values); - values = new double[size]; - Marshal.Copy(ptr_values, values, 0, values.Length); + values = new double[size]; + Marshal.Copy(ptr_values, values, 0, values.Length); - SVMNode.Free(ptr_nodes); - Marshal.FreeHGlobal(ptr_values); - ptr_values = IntPtr.Zero; + SVMNode.Free(ptr_nodes); + Marshal.FreeHGlobal(ptr_values); + ptr_values = IntPtr.Zero; - return result; + return result; + } + /// + /// This function does classification or regression on a test vector x given a model. + /// + /// SVM model. + /// Test vector. + /// For a classification model, the predicted class for x is returned. + /// For a regression model, the function value of x calculated using the model is returned. + /// For an one-class model, +1 or -1 is returned. + public static double Predict(SVMModel model, SVMNode[] x) + { + if (model == null) + { + throw new ArgumentNullException("model"); } - /// - /// This function does classification or regression on a test vector x given a model. - /// - /// SVM model. - /// Test vector. - /// For a classification model, the predicted class for x is returned. - /// For a regression model, the function value of x calculated using the model is returned. - /// For an one-class model, +1 or -1 is returned. - public static double Predict(SVMModel model, SVMNode[] x) + + if (x == null) { - if (model == null) - { - throw new ArgumentNullException("model"); - } - - if (x == null) - { - throw new ArgumentNullException("x"); - } - - IntPtr ptr_model = SVMModel.Allocate(model); - double result = Predict(ptr_model, x); - SVMModel.Free(ptr_model); - return result; + throw new ArgumentNullException("x"); } - /// - /// - /// - /// - /// - /// - public static double Predict(IntPtr ptr_model, SVMNode[] x) + + IntPtr ptr_model = SVMModel.Allocate(model); + double result = Predict(ptr_model, x); + SVMModel.Free(ptr_model); + return result; + } + /// + /// + /// + /// + /// + /// + public static double Predict(IntPtr ptr_model, SVMNode[] x) + { + if (ptr_model == IntPtr.Zero) { - if (ptr_model == IntPtr.Zero) - { - throw new ArgumentNullException("ptr_model"); - } + throw new ArgumentNullException("ptr_model"); + } - if (x == null) - { - throw new ArgumentNullException("x"); - } + if (x == null) + { + throw new ArgumentNullException("x"); + } - List nodes = x.Select(a => a.Clone()).ToList(); - nodes.Add(new SVMNode(-1, 0)); - IntPtr ptr_nodes = SVMNode.Allocate(nodes.ToArray()); + List nodes = x.Select(a => a.Clone()).ToList(); + nodes.Add(new SVMNode(-1, 0)); + IntPtr ptr_nodes = SVMNode.Allocate(nodes.ToArray()); - double result = libsvm.svm_predict(ptr_model, ptr_nodes); + double result = libsvm.svm_predict(ptr_model, ptr_nodes); - SVMNode.Free(ptr_nodes); + SVMNode.Free(ptr_nodes); - return result; + return result; + } + /// + /// + /// + /// + /// + /// + /// + public static double PredictProbability(SVMModel model, SVMNode[] x, out double[] estimations) + { + if (model == null) + { + throw new ArgumentNullException("model"); } - /// - /// - /// - /// - /// - /// - /// - public static double PredictProbability(SVMModel model, SVMNode[] x, out double[] estimations) + + if (x == null) { - if (model == null) - { - throw new ArgumentNullException("model"); - } - - if (x == null) - { - throw new ArgumentNullException("x"); - } - - IntPtr ptr_model = SVMModel.Allocate(model); - double result = PredictProbability(ptr_model, x, out estimations); - SVMModel.Free(ptr_model); - return result; + throw new ArgumentNullException("x"); } - /// - /// - /// - /// - /// - /// - /// - public static double PredictProbability(IntPtr ptr_model, SVMNode[] x, out double[] estimations) + + IntPtr ptr_model = SVMModel.Allocate(model); + double result = PredictProbability(ptr_model, x, out estimations); + SVMModel.Free(ptr_model); + return result; + } + /// + /// + /// + /// + /// + /// + /// + public static double PredictProbability(IntPtr ptr_model, SVMNode[] x, out double[] estimations) + { + if (ptr_model == IntPtr.Zero) { - if (ptr_model == IntPtr.Zero) - { - throw new ArgumentNullException("ptr_model"); - } + throw new ArgumentNullException("ptr_model"); + } - if (x == null) - { - throw new ArgumentNullException("x"); - } + if (x == null) + { + throw new ArgumentNullException("x"); + } - bool isProbabilityModel = libsvm.svm_check_probability_model(ptr_model); - if (!isProbabilityModel) - { - SVMModel.Free(ptr_model); - estimations = null; - return -1; - } + bool isProbabilityModel = libsvm.svm_check_probability_model(ptr_model); + if (!isProbabilityModel) + { + SVMModel.Free(ptr_model); + estimations = null; + return -1; + } - int classCount = libsvm.svm_get_nr_class(ptr_model); + int classCount = libsvm.svm_get_nr_class(ptr_model); - IntPtr ptr_estimations = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double)) * classCount); - List nodes = x.Select(a => a.Clone()).ToList(); - nodes.Add(new SVMNode(-1, 0)); - IntPtr ptr_nodes = SVMNode.Allocate(nodes.ToArray()); + IntPtr ptr_estimations = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double)) * classCount); + List nodes = x.Select(a => a.Clone()).ToList(); + nodes.Add(new SVMNode(-1, 0)); + IntPtr ptr_nodes = SVMNode.Allocate(nodes.ToArray()); - double result = libsvm.svm_predict_probability(ptr_model, ptr_nodes, ptr_estimations); + double result = libsvm.svm_predict_probability(ptr_model, ptr_nodes, ptr_estimations); - estimations = new double[classCount]; - Marshal.Copy(ptr_estimations, estimations, 0, estimations.Length); + estimations = new double[classCount]; + Marshal.Copy(ptr_estimations, estimations, 0, estimations.Length); - SVMNode.Free(ptr_nodes); - Marshal.FreeHGlobal(ptr_estimations); - ptr_estimations = IntPtr.Zero; + SVMNode.Free(ptr_nodes); + Marshal.FreeHGlobal(ptr_estimations); + ptr_estimations = IntPtr.Zero; - return result; - } - /// - /// - /// - /// - /// - /// - public static string CheckParameter(SVMProblem problem, SVMParameter parameter) + return result; + } + /// + /// + /// + /// + /// + /// + public static string CheckParameter(SVMProblem problem, SVMParameter parameter) + { + if (problem == null) { - if (problem == null) - { - throw new ArgumentNullException("problem"); - } + throw new ArgumentNullException("problem"); + } - if (parameter == null) - { - throw new ArgumentNullException("parameter"); - } + if (parameter == null) + { + throw new ArgumentNullException("parameter"); + } - IntPtr ptr_problem = SVMProblem.Allocate(problem); - IntPtr ptr_parameter = SVMParameter.Allocate(parameter); + IntPtr ptr_problem = SVMProblem.Allocate(problem); + IntPtr ptr_parameter = SVMParameter.Allocate(parameter); - IntPtr ptr_output = libsvm.svm_check_parameter(ptr_problem, ptr_parameter); + IntPtr ptr_output = libsvm.svm_check_parameter(ptr_problem, ptr_parameter); - SVMProblem.Free(ptr_problem); - SVMParameter.Free(ptr_parameter); + SVMProblem.Free(ptr_problem); + SVMParameter.Free(ptr_parameter); - string output = Marshal.PtrToStringAnsi(ptr_output); - Marshal.FreeHGlobal(ptr_output); - ptr_output = IntPtr.Zero; + string output = Marshal.PtrToStringAnsi(ptr_output); + Marshal.FreeHGlobal(ptr_output); + ptr_output = IntPtr.Zero; - return output; - } - /// - /// - /// - /// - /// - public static bool CheckProbabilityModel(SVMModel model) + return output; + } + /// + /// + /// + /// + /// + public static bool CheckProbabilityModel(SVMModel model) + { + if (model == null) { - if (model == null) - { - throw new ArgumentNullException("model"); - } - - IntPtr ptr_model = SVMModel.Allocate(model); - bool success = libsvm.svm_check_probability_model(ptr_model); - SVMModel.Free(ptr_model); - return success; + throw new ArgumentNullException("model"); } - /// - /// - /// - /// - public static void SetPrintStringFunction(SVMPrintFunction function) - { - if (function == null) - { - throw new ArgumentNullException("function"); - } - IntPtr ptr_function = Marshal.GetFunctionPointerForDelegate(function); - libsvm.svm_set_print_string_function(ptr_function); + IntPtr ptr_model = SVMModel.Allocate(model); + bool success = libsvm.svm_check_probability_model(ptr_model); + SVMModel.Free(ptr_model); + return success; + } + /// + /// + /// + /// + public static void SetPrintStringFunction(SVMPrintFunction function) + { + if (function == null) + { + throw new ArgumentNullException("function"); } + + IntPtr ptr_function = Marshal.GetFunctionPointerForDelegate(function); + libsvm.svm_set_print_string_function(ptr_function); } } diff --git a/LibSVMsharp/SVMModel.cs b/LibSVMsharp/SVMModel.cs index 2843080..a2e1b03 100644 --- a/LibSVMsharp/SVMModel.cs +++ b/LibSVMsharp/SVMModel.cs @@ -5,389 +5,388 @@ using System.Runtime.InteropServices; using System.Text; -namespace LibSVMsharp +namespace LibSVMsharp; + +public class SVMModel { - public class SVMModel + public enum CreationType { - public enum CreationType - { - TRAIN = 0, - LOAD_MODEL = 1 - } + TRAIN = 0, + LOAD_MODEL = 1 + } - public SVMModel() - { - Parameter = new SVMParameter(); - ClassCount = 0; - TotalSVCount = 0; - SV = null; - SVCoefs = null; - Rho = null; - ProbabilityA = null; - ProbabilityB = null; - SVIndices = null; - Labels = null; - SVCounts = null; - Creation = CreationType.LOAD_MODEL; - } + public SVMModel() + { + Parameter = new SVMParameter(); + ClassCount = 0; + TotalSVCount = 0; + SV = null; + SVCoefs = null; + Rho = null; + ProbabilityA = null; + ProbabilityB = null; + SVIndices = null; + Labels = null; + SVCounts = null; + Creation = CreationType.LOAD_MODEL; + } - /// - /// SVM parameter. - /// - public SVMParameter Parameter { get; set; } - /// - /// Number of classes, = 2 in regression/one class svm. - /// - public int ClassCount { get; set; } - /// - /// Total support vector count. - /// - public int TotalSVCount { get; set; } - /// - /// Support vectors (SV[TotalSVCount]) - /// - public List SV { get; set; } - /// - /// Coefficients for SVs in decision functions (sv_coef[ClassCount-1][TotalSVCount]) - /// - public List SVCoefs { get; set; } - /// - /// Constants in decision functions (rho[ClassCount*(ClassCount-1)/2]) - /// - public double[] Rho { get; set; } - /// - /// Pariwise probability information (A) - /// - public double[] ProbabilityA { get; set; } - /// - /// Pariwise probability information (B) - /// - public double[] ProbabilityB { get; set; } - /// - /// SVIndices[0,...,SVCounts-1] are values in [1,...,num_traning_data] to indicate SVs in the training set. - /// - public int[] SVIndices { get; set; } - /// - /// Label of each class (Labels[ClassCount]). - /// - public int[] Labels { get; set; } - /// - /// Number of SVs for each class (SVCounts[ClassCount]). SVCounts[0] + SVCounts[1] + ... + SVCounts[ClassCount-1] = TotalSVCount. - /// - public int[] SVCounts { get; set; } - /// - /// Creation type of the model. - /// - public CreationType Creation { get; set; } - - public SVMModel Clone() - { - SVMModel y = new SVMModel(); + /// + /// SVM parameter. + /// + public SVMParameter Parameter { get; set; } + /// + /// Number of classes, = 2 in regression/one class svm. + /// + public int ClassCount { get; set; } + /// + /// Total support vector count. + /// + public int TotalSVCount { get; set; } + /// + /// Support vectors (SV[TotalSVCount]) + /// + public List SV { get; set; } + /// + /// Coefficients for SVs in decision functions (sv_coef[ClassCount-1][TotalSVCount]) + /// + public List SVCoefs { get; set; } + /// + /// Constants in decision functions (rho[ClassCount*(ClassCount-1)/2]) + /// + public double[] Rho { get; set; } + /// + /// Pariwise probability information (A) + /// + public double[] ProbabilityA { get; set; } + /// + /// Pariwise probability information (B) + /// + public double[] ProbabilityB { get; set; } + /// + /// SVIndices[0,...,SVCounts-1] are values in [1,...,num_traning_data] to indicate SVs in the training set. + /// + public int[] SVIndices { get; set; } + /// + /// Label of each class (Labels[ClassCount]). + /// + public int[] Labels { get; set; } + /// + /// Number of SVs for each class (SVCounts[ClassCount]). SVCounts[0] + SVCounts[1] + ... + SVCounts[ClassCount-1] = TotalSVCount. + /// + public int[] SVCounts { get; set; } + /// + /// Creation type of the model. + /// + public CreationType Creation { get; set; } + + public SVMModel Clone() + { + SVMModel y = new SVMModel(); - if (Parameter != null) - y.Parameter = Parameter.Clone(); + if (Parameter != null) + y.Parameter = Parameter.Clone(); - y.ClassCount = ClassCount; - y.TotalSVCount = TotalSVCount; + y.ClassCount = ClassCount; + y.TotalSVCount = TotalSVCount; - if (SV != null) - y.SV = SV.Select(a => a.Select(b => b.Clone()).ToArray()).ToList(); + if (SV != null) + y.SV = SV.Select(a => a.Select(b => b.Clone()).ToArray()).ToList(); - if (SVCoefs != null) - y.SVCoefs = SVCoefs.Select(a => a.Select(b => b).ToArray()).ToList(); + if (SVCoefs != null) + y.SVCoefs = SVCoefs.Select(a => a.Select(b => b).ToArray()).ToList(); - if (Rho != null) - y.Rho = Rho.Select(a => a).ToArray(); + if (Rho != null) + y.Rho = Rho.Select(a => a).ToArray(); - if (ProbabilityA != null) - y.ProbabilityA = ProbabilityA.Select(a => a).ToArray(); + if (ProbabilityA != null) + y.ProbabilityA = ProbabilityA.Select(a => a).ToArray(); - if (ProbabilityB != null) - y.ProbabilityB = ProbabilityB.Select(a => a).ToArray(); + if (ProbabilityB != null) + y.ProbabilityB = ProbabilityB.Select(a => a).ToArray(); - if (SVIndices != null) - y.SVIndices = SVIndices.Select(a => a).ToArray(); + if (SVIndices != null) + y.SVIndices = SVIndices.Select(a => a).ToArray(); - if (Labels != null) - y.Labels = Labels.Select(a => a).ToArray(); + if (Labels != null) + y.Labels = Labels.Select(a => a).ToArray(); - if (SVCounts != null) - y.SVCounts = SVCounts.Select(a => a).ToArray(); + if (SVCounts != null) + y.SVCounts = SVCounts.Select(a => a).ToArray(); - y.Creation = Creation; - return y; - } + y.Creation = Creation; + return y; + } - public static SVMModel Convert(svm_model x) - { - SVMModel y = new SVMModel(); - y.Creation = (CreationType)x.free_sv; - y.ClassCount = x.nr_class; - y.TotalSVCount = x.l; + public static SVMModel Convert(svm_model x) + { + SVMModel y = new SVMModel(); + y.Creation = (CreationType)x.free_sv; + y.ClassCount = x.nr_class; + y.TotalSVCount = x.l; - if (y.Creation == CreationType.LOAD_MODEL) - { - y.Parameter = new SVMParameter(); - y.Parameter.Type = (SVMType)x.param.svm_type; - y.Parameter.Kernel = (SVMKernelType)x.param.kernel_type; - switch (y.Parameter.Kernel) - { - case SVMKernelType.LINEAR: - break; - case SVMKernelType.POLY: - y.Parameter.Gamma = x.param.gamma; - y.Parameter.Coef0 = x.param.coef0; - y.Parameter.Degree = x.param.degree; - break; - case SVMKernelType.RBF: - y.Parameter.Gamma = x.param.gamma; - break; - case SVMKernelType.SIGMOID: - y.Parameter.Gamma = x.param.gamma; - y.Parameter.Coef0 = x.param.coef0; - break; - } - } - else + if (y.Creation == CreationType.LOAD_MODEL) + { + y.Parameter = new SVMParameter(); + y.Parameter.Type = (SVMType)x.param.svm_type; + y.Parameter.Kernel = (SVMKernelType)x.param.kernel_type; + switch (y.Parameter.Kernel) { - y.Parameter = SVMParameter.Convert(x.param); + case SVMKernelType.LINEAR: + break; + case SVMKernelType.POLY: + y.Parameter.Gamma = x.param.gamma; + y.Parameter.Coef0 = x.param.coef0; + y.Parameter.Degree = x.param.degree; + break; + case SVMKernelType.RBF: + y.Parameter.Gamma = x.param.gamma; + break; + case SVMKernelType.SIGMOID: + y.Parameter.Gamma = x.param.gamma; + y.Parameter.Coef0 = x.param.coef0; + break; } + } + else + { + y.Parameter = SVMParameter.Convert(x.param); + } - int problemCount = (int)(y.ClassCount * (y.ClassCount - 1) * 0.5); - - y.Rho = new double[problemCount]; - Marshal.Copy(x.rho, y.Rho, 0, y.Rho.Length); + int problemCount = (int)(y.ClassCount * (y.ClassCount - 1) * 0.5); - y.ProbabilityA = null; - if (x.probA != IntPtr.Zero) - { - y.ProbabilityA = new double[problemCount]; - Marshal.Copy(x.probA, y.ProbabilityA, 0, y.ProbabilityA.Length); - } + y.Rho = new double[problemCount]; + Marshal.Copy(x.rho, y.Rho, 0, y.Rho.Length); - y.ProbabilityB = null; - if (x.probB != IntPtr.Zero) - { - y.ProbabilityB = new double[problemCount]; - Marshal.Copy(x.probB, y.ProbabilityB, 0, y.ProbabilityB.Length); - } + y.ProbabilityA = null; + if (x.probA != IntPtr.Zero) + { + y.ProbabilityA = new double[problemCount]; + Marshal.Copy(x.probA, y.ProbabilityA, 0, y.ProbabilityA.Length); + } - if (x.nSV != IntPtr.Zero) - { - y.SVCounts = new int[y.ClassCount]; - Marshal.Copy(x.nSV, y.SVCounts, 0, y.SVCounts.Length); + y.ProbabilityB = null; + if (x.probB != IntPtr.Zero) + { + y.ProbabilityB = new double[problemCount]; + Marshal.Copy(x.probB, y.ProbabilityB, 0, y.ProbabilityB.Length); + } - y.Labels = new int[y.ClassCount]; - Marshal.Copy(x.label, y.Labels, 0, y.Labels.Length); - } + if (x.nSV != IntPtr.Zero) + { + y.SVCounts = new int[y.ClassCount]; + Marshal.Copy(x.nSV, y.SVCounts, 0, y.SVCounts.Length); - y.SVCoefs = new List(y.ClassCount - 1); - IntPtr i_ptr_svcoef = x.sv_coef; - for (int i = 0; i < y.ClassCount - 1; i++) - { - y.SVCoefs.Add(new double[y.TotalSVCount]); - IntPtr coef_ptr = (IntPtr)Marshal.PtrToStructure(i_ptr_svcoef, typeof(IntPtr)); - Marshal.Copy(coef_ptr, y.SVCoefs[i], 0, y.SVCoefs[i].Length); - i_ptr_svcoef = IntPtr.Add(i_ptr_svcoef, Marshal.SizeOf(typeof(IntPtr))); - } + y.Labels = new int[y.ClassCount]; + Marshal.Copy(x.label, y.Labels, 0, y.Labels.Length); + } - y.SVIndices = null; - if (x.sv_indices != IntPtr.Zero) - { - y.SVIndices = new int[y.TotalSVCount]; - Marshal.Copy(x.sv_indices, y.SVIndices, 0, y.SVIndices.Length); - } + y.SVCoefs = new List(y.ClassCount - 1); + IntPtr i_ptr_svcoef = x.sv_coef; + for (int i = 0; i < y.ClassCount - 1; i++) + { + y.SVCoefs.Add(new double[y.TotalSVCount]); + IntPtr coef_ptr = (IntPtr)Marshal.PtrToStructure(i_ptr_svcoef, typeof(IntPtr)); + Marshal.Copy(coef_ptr, y.SVCoefs[i], 0, y.SVCoefs[i].Length); + i_ptr_svcoef = IntPtr.Add(i_ptr_svcoef, Marshal.SizeOf(typeof(IntPtr))); + } - y.SV = new List(); - IntPtr i_ptr_sv = x.SV; - for (int i = 0; i < x.l; i++) - { - IntPtr ptr_nodes = (IntPtr)Marshal.PtrToStructure(i_ptr_sv, typeof(IntPtr)); - SVMNode[] nodes = SVMNode.Convert(ptr_nodes); - y.SV.Add(nodes); - i_ptr_sv = IntPtr.Add(i_ptr_sv, Marshal.SizeOf(typeof(IntPtr))); - } + y.SVIndices = null; + if (x.sv_indices != IntPtr.Zero) + { + y.SVIndices = new int[y.TotalSVCount]; + Marshal.Copy(x.sv_indices, y.SVIndices, 0, y.SVIndices.Length); + } - return y; + y.SV = new List(); + IntPtr i_ptr_sv = x.SV; + for (int i = 0; i < x.l; i++) + { + IntPtr ptr_nodes = (IntPtr)Marshal.PtrToStructure(i_ptr_sv, typeof(IntPtr)); + SVMNode[] nodes = SVMNode.Convert(ptr_nodes); + y.SV.Add(nodes); + i_ptr_sv = IntPtr.Add(i_ptr_sv, Marshal.SizeOf(typeof(IntPtr))); } - public static SVMModel Convert(IntPtr ptr) + + return y; + } + public static SVMModel Convert(IntPtr ptr) + { + if (ptr == IntPtr.Zero) + return null; + + svm_model x = (svm_model)Marshal.PtrToStructure(ptr, typeof(svm_model)); + return SVMModel.Convert(x); + } + public static IntPtr Allocate(SVMModel x) + { + if (x == null || x.ClassCount < 1 || x.Parameter == null || x.Rho == null || x.Rho.Length < 1 || + x.SVCoefs == null || x.SVCoefs.Count < 1 || x.TotalSVCount < 1) { - if (ptr == IntPtr.Zero) - return null; + return IntPtr.Zero; + } - svm_model x = (svm_model)Marshal.PtrToStructure(ptr, typeof(svm_model)); - return SVMModel.Convert(x); + if (x.Parameter.Type != SVMType.EPSILON_SVR && x.Parameter.Type != SVMType.NU_SVR && + x.Parameter.Type != SVMType.ONE_CLASS && + (x.Labels == null || x.Labels.Length < 1 || x.SVCounts == null || x.SVCounts.Length < 1)) + { + return IntPtr.Zero; } - public static IntPtr Allocate(SVMModel x) + + svm_model y = new svm_model(); + y.nr_class = x.ClassCount; + y.l = x.TotalSVCount; + y.free_sv = (int)x.Creation; + + // Allocate model.parameter + IntPtr ptr_param = SVMParameter.Allocate(x.Parameter); + y.param = (svm_parameter)Marshal.PtrToStructure(ptr_param, typeof(svm_parameter)); + SVMParameter.Free(ptr_param); + + // Allocate model.rho + y.rho = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double)) * x.Rho.Length); + Marshal.Copy(x.Rho, 0, y.rho, x.Rho.Length); + + // Allocate model.probA + y.probA = IntPtr.Zero; + if (x.ProbabilityA != null) { - if (x == null || x.ClassCount < 1 || x.Parameter == null || x.Rho == null || x.Rho.Length < 1 || - x.SVCoefs == null || x.SVCoefs.Count < 1 || x.TotalSVCount < 1) - { - return IntPtr.Zero; - } + y.probA = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double)) * x.ProbabilityA.Length); + Marshal.Copy(x.ProbabilityA, 0, y.probA, x.ProbabilityA.Length); + } - if (x.Parameter.Type != SVMType.EPSILON_SVR && x.Parameter.Type != SVMType.NU_SVR && - x.Parameter.Type != SVMType.ONE_CLASS && - (x.Labels == null || x.Labels.Length < 1 || x.SVCounts == null || x.SVCounts.Length < 1)) - { - return IntPtr.Zero; - } + // Allocate model.probB + y.probB = IntPtr.Zero; + if (x.ProbabilityB != null) + { + y.probB = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double)) * x.ProbabilityB.Length); + Marshal.Copy(x.ProbabilityB, 0, y.probB, x.ProbabilityB.Length); + } - svm_model y = new svm_model(); - y.nr_class = x.ClassCount; - y.l = x.TotalSVCount; - y.free_sv = (int)x.Creation; - - // Allocate model.parameter - IntPtr ptr_param = SVMParameter.Allocate(x.Parameter); - y.param = (svm_parameter)Marshal.PtrToStructure(ptr_param, typeof(svm_parameter)); - SVMParameter.Free(ptr_param); - - // Allocate model.rho - y.rho = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double)) * x.Rho.Length); - Marshal.Copy(x.Rho, 0, y.rho, x.Rho.Length); - - // Allocate model.probA - y.probA = IntPtr.Zero; - if (x.ProbabilityA != null) - { - y.probA = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double)) * x.ProbabilityA.Length); - Marshal.Copy(x.ProbabilityA, 0, y.probA, x.ProbabilityA.Length); - } + if (x.Parameter.Type != SVMType.EPSILON_SVR && x.Parameter.Type != SVMType.NU_SVR && + x.Parameter.Type != SVMType.ONE_CLASS) + { + // Allocate model.label + y.label = Marshal.AllocHGlobal(Marshal.SizeOf(typeof (int))*x.Labels.Length); + Marshal.Copy(x.Labels, 0, y.label, x.Labels.Length); - // Allocate model.probB - y.probB = IntPtr.Zero; - if (x.ProbabilityB != null) - { - y.probB = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double)) * x.ProbabilityB.Length); - Marshal.Copy(x.ProbabilityB, 0, y.probB, x.ProbabilityB.Length); - } + // Allocate model.nSV + y.nSV = Marshal.AllocHGlobal(Marshal.SizeOf(typeof (int))*x.SVCounts.Length); + Marshal.Copy(x.SVCounts, 0, y.nSV, x.SVCounts.Length); + } + else + { + y.label = IntPtr.Zero; + y.nSV = IntPtr.Zero; + } - if (x.Parameter.Type != SVMType.EPSILON_SVR && x.Parameter.Type != SVMType.NU_SVR && - x.Parameter.Type != SVMType.ONE_CLASS) - { - // Allocate model.label - y.label = Marshal.AllocHGlobal(Marshal.SizeOf(typeof (int))*x.Labels.Length); - Marshal.Copy(x.Labels, 0, y.label, x.Labels.Length); + // Allocate model.sv_coef + y.sv_coef = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)) * x.SVCoefs.Count); + IntPtr i_ptr_svcoef = y.sv_coef; + for (int i = 0; i < x.SVCoefs.Count; i++) + { + IntPtr temp = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double)) * x.SVCoefs[i].Length); + Marshal.Copy(x.SVCoefs[i], 0, temp, x.SVCoefs[i].Length); + Marshal.StructureToPtr(temp, i_ptr_svcoef, true); + i_ptr_svcoef = IntPtr.Add(i_ptr_svcoef, Marshal.SizeOf(typeof(IntPtr))); + } - // Allocate model.nSV - y.nSV = Marshal.AllocHGlobal(Marshal.SizeOf(typeof (int))*x.SVCounts.Length); - Marshal.Copy(x.SVCounts, 0, y.nSV, x.SVCounts.Length); - } - else - { - y.label = IntPtr.Zero; - y.nSV = IntPtr.Zero; - } + // Allocate model.sv_indices + y.sv_indices = IntPtr.Zero; + if (x.SVIndices != null) + { + y.sv_indices = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(int)) * x.SVIndices.Length); + Marshal.Copy(x.SVIndices, 0, y.sv_indices, x.SVIndices.Length); + } - // Allocate model.sv_coef - y.sv_coef = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)) * x.SVCoefs.Count); - IntPtr i_ptr_svcoef = y.sv_coef; - for (int i = 0; i < x.SVCoefs.Count; i++) + // Allocate model.SV + y.SV = IntPtr.Zero; + if (x.SV != null) + { + y.SV = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)) * x.SV.Count); + IntPtr i_ptr_sv = y.SV; + for (int i = 0; i < x.SV.Count; i++) { - IntPtr temp = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double)) * x.SVCoefs[i].Length); - Marshal.Copy(x.SVCoefs[i], 0, temp, x.SVCoefs[i].Length); - Marshal.StructureToPtr(temp, i_ptr_svcoef, true); - i_ptr_svcoef = IntPtr.Add(i_ptr_svcoef, Marshal.SizeOf(typeof(IntPtr))); - } + // Prepare each node array + // 1) All nodes containing zero value is removed + // 2) A node which index is -1 is added to the end + List temp = x.SV[i].Where(a => a.Value != 0).ToList(); + temp.Add(new SVMNode(-1, 0)); + SVMNode[] nodes = temp.ToArray(); - // Allocate model.sv_indices - y.sv_indices = IntPtr.Zero; - if (x.SVIndices != null) - { - y.sv_indices = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(int)) * x.SVIndices.Length); - Marshal.Copy(x.SVIndices, 0, y.sv_indices, x.SVIndices.Length); - } + // Allocate node array + IntPtr ptr_nodes = SVMNode.Allocate(nodes); + Marshal.StructureToPtr(ptr_nodes, i_ptr_sv, true); - // Allocate model.SV - y.SV = IntPtr.Zero; - if (x.SV != null) - { - y.SV = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)) * x.SV.Count); - IntPtr i_ptr_sv = y.SV; - for (int i = 0; i < x.SV.Count; i++) - { - // Prepare each node array - // 1) All nodes containing zero value is removed - // 2) A node which index is -1 is added to the end - List temp = x.SV[i].Where(a => a.Value != 0).ToList(); - temp.Add(new SVMNode(-1, 0)); - SVMNode[] nodes = temp.ToArray(); - - // Allocate node array - IntPtr ptr_nodes = SVMNode.Allocate(nodes); - Marshal.StructureToPtr(ptr_nodes, i_ptr_sv, true); - - i_ptr_sv = IntPtr.Add(i_ptr_sv, Marshal.SizeOf(typeof(IntPtr))); - } + i_ptr_sv = IntPtr.Add(i_ptr_sv, Marshal.SizeOf(typeof(IntPtr))); } - - // Allocate the model - int size = Marshal.SizeOf(y); - IntPtr ptr = Marshal.AllocHGlobal(size); - Marshal.StructureToPtr(y, ptr, true); - - return ptr; } - public static void Free(svm_model x) - { - Marshal.FreeHGlobal(x.rho); - x.rho = IntPtr.Zero; - Marshal.FreeHGlobal(x.probA); - x.probA = IntPtr.Zero; + // Allocate the model + int size = Marshal.SizeOf(y); + IntPtr ptr = Marshal.AllocHGlobal(size); + Marshal.StructureToPtr(y, ptr, true); - Marshal.FreeHGlobal(x.probB); - x.probB = IntPtr.Zero; + return ptr; + } + public static void Free(svm_model x) + { + Marshal.FreeHGlobal(x.rho); + x.rho = IntPtr.Zero; - Marshal.FreeHGlobal(x.sv_indices); - x.sv_indices = IntPtr.Zero; + Marshal.FreeHGlobal(x.probA); + x.probA = IntPtr.Zero; - Marshal.FreeHGlobal(x.label); - x.label = IntPtr.Zero; + Marshal.FreeHGlobal(x.probB); + x.probB = IntPtr.Zero; - Marshal.FreeHGlobal(x.nSV); - x.nSV = IntPtr.Zero; + Marshal.FreeHGlobal(x.sv_indices); + x.sv_indices = IntPtr.Zero; - SVMParameter.Free(x.param); + Marshal.FreeHGlobal(x.label); + x.label = IntPtr.Zero; - IntPtr i_ptr_sv = x.SV; - for (int i = 0; i < x.l; i++) - { - IntPtr ptr_nodes = (IntPtr)Marshal.PtrToStructure(i_ptr_sv, typeof(IntPtr)); - SVMNode.Free(ptr_nodes); + Marshal.FreeHGlobal(x.nSV); + x.nSV = IntPtr.Zero; - i_ptr_sv = IntPtr.Add(i_ptr_sv, Marshal.SizeOf(typeof(IntPtr))); - } + SVMParameter.Free(x.param); - Marshal.FreeHGlobal(x.SV); - x.SV = IntPtr.Zero; + IntPtr i_ptr_sv = x.SV; + for (int i = 0; i < x.l; i++) + { + IntPtr ptr_nodes = (IntPtr)Marshal.PtrToStructure(i_ptr_sv, typeof(IntPtr)); + SVMNode.Free(ptr_nodes); - IntPtr i_ptr_svcoef = x.sv_coef; - for (int i = 0; i < x.nr_class - 1; i++) - { - IntPtr temp = (IntPtr)Marshal.PtrToStructure(i_ptr_svcoef, typeof(IntPtr)); - Marshal.FreeHGlobal(temp); - temp = IntPtr.Zero; + i_ptr_sv = IntPtr.Add(i_ptr_sv, Marshal.SizeOf(typeof(IntPtr))); + } - i_ptr_svcoef = IntPtr.Add(i_ptr_svcoef, Marshal.SizeOf(typeof(IntPtr))); - } + Marshal.FreeHGlobal(x.SV); + x.SV = IntPtr.Zero; - Marshal.FreeHGlobal(x.sv_coef); - x.sv_coef = IntPtr.Zero; - } - public static void Free(IntPtr ptr) + IntPtr i_ptr_svcoef = x.sv_coef; + for (int i = 0; i < x.nr_class - 1; i++) { - if (ptr == IntPtr.Zero) - return; + IntPtr temp = (IntPtr)Marshal.PtrToStructure(i_ptr_svcoef, typeof(IntPtr)); + Marshal.FreeHGlobal(temp); + temp = IntPtr.Zero; - svm_model x = (svm_model)Marshal.PtrToStructure(ptr, typeof(svm_model)); + i_ptr_svcoef = IntPtr.Add(i_ptr_svcoef, Marshal.SizeOf(typeof(IntPtr))); + } + + Marshal.FreeHGlobal(x.sv_coef); + x.sv_coef = IntPtr.Zero; + } + public static void Free(IntPtr ptr) + { + if (ptr == IntPtr.Zero) + return; - SVMModel.Free(x); + svm_model x = (svm_model)Marshal.PtrToStructure(ptr, typeof(svm_model)); - Marshal.DestroyStructure(ptr, typeof(svm_model)); - Marshal.FreeHGlobal(ptr); - ptr = IntPtr.Zero; - } + SVMModel.Free(x); + + Marshal.DestroyStructure(ptr, typeof(svm_model)); + Marshal.FreeHGlobal(ptr); + ptr = IntPtr.Zero; } } diff --git a/LibSVMsharp/SVMNode.cs b/LibSVMsharp/SVMNode.cs index b73f398..dcfac62 100644 --- a/LibSVMsharp/SVMNode.cs +++ b/LibSVMsharp/SVMNode.cs @@ -5,90 +5,89 @@ using System.Runtime.InteropServices; using System.Text; -namespace LibSVMsharp +namespace LibSVMsharp; + +public class SVMNode : IEquatable { - public class SVMNode : IEquatable + public SVMNode(int index, double value) + { + Index = index; + Value = value; + } + public SVMNode() + : this(0, 0) { - public SVMNode(int index, double value) - { - Index = index; - Value = value; - } - public SVMNode() - : this(0, 0) - { - } + } - public int Index { get; set; } - public double Value { get; set; } + public int Index { get; set; } + public double Value { get; set; } - public bool Equals(SVMNode x) - { - if (x == null) return false; - return Index.Equals(x.Index) && Value.Equals(x.Value); - } - public override int GetHashCode() - { - return Index * (int) (Value * 100000000.0); - } - public SVMNode Clone() - { - SVMNode y = new SVMNode(); - y.Index = Index; - y.Value = Value; - return y; - } + public bool Equals(SVMNode x) + { + if (x == null) return false; + return Index.Equals(x.Index) && Value.Equals(x.Value); + } + public override int GetHashCode() + { + return Index * (int) (Value * 100000000.0); + } + public SVMNode Clone() + { + SVMNode y = new SVMNode(); + y.Index = Index; + y.Value = Value; + return y; + } - public static SVMNode[] Convert(IntPtr ptr) - { - if (ptr == IntPtr.Zero) - return null; + public static SVMNode[] Convert(IntPtr ptr) + { + if (ptr == IntPtr.Zero) + return null; - List nodes = new List(); - IntPtr i_ptr_nodes = ptr; - while (true) + List nodes = new List(); + IntPtr i_ptr_nodes = ptr; + while (true) + { + svm_node node = (svm_node)Marshal.PtrToStructure(i_ptr_nodes, typeof(svm_node)); + i_ptr_nodes = IntPtr.Add(i_ptr_nodes, Marshal.SizeOf(typeof(svm_node))); + if (node.index > 0) { - svm_node node = (svm_node)Marshal.PtrToStructure(i_ptr_nodes, typeof(svm_node)); - i_ptr_nodes = IntPtr.Add(i_ptr_nodes, Marshal.SizeOf(typeof(svm_node))); - if (node.index > 0) - { - nodes.Add(new SVMNode(node.index, node.value)); - } - else - { - break; - } + nodes.Add(new SVMNode(node.index, node.value)); } - - return nodes.ToArray(); - } - public static IntPtr Allocate(SVMNode[] x) - { - if (x == null) - return IntPtr.Zero; - - IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(svm_node)) * x.Length); - IntPtr i_ptr_nodes = ptr; - for (int i = 0; i < x.Length; i++) + else { - svm_node node = new svm_node(); - node.index = x[i].Index; - node.value = x[i].Value; - Marshal.StructureToPtr(node, i_ptr_nodes, true); - i_ptr_nodes = IntPtr.Add(i_ptr_nodes, Marshal.SizeOf(typeof(svm_node))); + break; } - - return ptr; } - public static void Free(IntPtr ptr) - { - if (ptr == IntPtr.Zero) - return; - Marshal.DestroyStructure(ptr, typeof(IntPtr)); - Marshal.FreeHGlobal(ptr); - ptr = IntPtr.Zero; + return nodes.ToArray(); + } + public static IntPtr Allocate(SVMNode[] x) + { + if (x == null) + return IntPtr.Zero; + + IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(svm_node)) * x.Length); + IntPtr i_ptr_nodes = ptr; + for (int i = 0; i < x.Length; i++) + { + svm_node node = new svm_node(); + node.index = x[i].Index; + node.value = x[i].Value; + Marshal.StructureToPtr(node, i_ptr_nodes, true); + i_ptr_nodes = IntPtr.Add(i_ptr_nodes, Marshal.SizeOf(typeof(svm_node))); } + + return ptr; + } + public static void Free(IntPtr ptr) + { + if (ptr == IntPtr.Zero) + return; + + Marshal.DestroyStructure(ptr, typeof(IntPtr)); + Marshal.FreeHGlobal(ptr); + ptr = IntPtr.Zero; } } diff --git a/LibSVMsharp/SVMParameter.cs b/LibSVMsharp/SVMParameter.cs index c2dda16..ccef403 100644 --- a/LibSVMsharp/SVMParameter.cs +++ b/LibSVMsharp/SVMParameter.cs @@ -5,209 +5,208 @@ using System.Runtime.InteropServices; using System.Text; -namespace LibSVMsharp +namespace LibSVMsharp; + +public class SVMParameter { - public class SVMParameter + public SVMParameter() { - public SVMParameter() - { - Type = SVMType.C_SVC; - Kernel = SVMKernelType.RBF; - Degree = 3; - Gamma = 1; // divided by num_of_features - Coef0 = 0; - C = 1; - Nu = 0.5; - P = 0.1; - CacheSize = 100; - Eps = 0.001; - Shrinking = true; - Probability = false; - WeightLabels = new int[0]; - Weights = new double[0]; - } - - /// - /// Type of a SVM formulation. Possible values are: - /// [C_SVC] C-Support Vector Classification. n-class classification (n >= 2), allows imperfect separation of classes with penalty multiplier C for outliers. - /// [NU_SVC] nu-Support Vector Classification. n-class classification with possible imperfect separation. Parameter Nu (in the range 0..1, the larger the value, the smoother the decision boundary) is used instead of C. - /// [ONE_CLASS] Distribution Estimation (One-class SVM). All the training data are from the same class, SVM builds a boundary that separates the class from the rest of the feature space. - /// [EPS_SVR] epsilon-Support Vector Regression. The distance between feature vectors from the training set and the fitting hyper-plane must be less than P. For outliers the penalty multiplier C is used. - /// [NU_SVR] nu-Support Vector Regression. Nu is used instead of p. - /// - public SVMType Type { get; set; } - /// - /// Type of a SVM kernel. Possible values are: - /// [LINEAR] Linear kernel. No mapping is done, linear discrimination (or regression) is done in the original feature space. It is the fastest option. - /// [POLY] Polynomial kernel. - /// [RBF] Radial basis function (RBF), a good choice in most cases. - /// [SIGMOID] Sigmoid kernel. - /// - public SVMKernelType Kernel { get; set; } - /// - /// Parameter degree of a kernel function (POLY). - /// - public int Degree { get; set; } - /// - /// Parameter gamma of a kernel function (POLY / RBF / SIGMOID). - /// - public double Gamma { get; set; } - /// - /// Parameter coef0 of a kernel function (POLY / SIGMOID). - /// - public double Coef0 { get; set; } - /// - /// Unit in MegaBytes. - /// - public double CacheSize { get; set; } - /// - /// Term criteria. Tolerance of the iterative SVM training procedure which solves a partial case of constrained quadratic optimization problem - /// - public double Eps { get; set; } - /// - /// Parameter C of a SVM optimization problem (C_SVC / EPS_SVR / NU_SVR). - /// - public double C { get; set; } - /// - /// Optional weights in the C_SVC problem , assigned to particular classes. - /// - public int[] WeightLabels { get; set; } - /// - /// Optional weights in the C_SVC problem , assigned to particular classes. - /// - public double[] Weights { get; set; } - /// - /// Parameter nu of a SVM optimization problem (NU_SVC / ONE_CLASS / NU_SVR). - /// - public double Nu { get; set; } - /// - /// Parameter epsilon of a SVM optimization problem (EPS_SVR). - /// - public double P { get; set; } - /// - /// Use the shrinking heuristics. - /// - public bool Shrinking { get; set; } - /// - /// Train a SVC or SVR model for probability estimates. - /// - public bool Probability { get; set; } - - public SVMParameter Clone() - { - SVMParameter y = new SVMParameter(); - y.Type = Type; - y.Kernel = Kernel; - y.Degree = Degree; - y.Gamma = Gamma; - y.Coef0 = Coef0; - y.C = C; - y.Nu = Nu; - y.P = P; - y.CacheSize = CacheSize; - y.Eps = Eps; - y.Shrinking = Shrinking; - y.Probability = Probability; - y.WeightLabels = WeightLabels.Select(a => a).ToArray(); - y.Weights = Weights.Select(a => a).ToArray(); - return y; - } + Type = SVMType.C_SVC; + Kernel = SVMKernelType.RBF; + Degree = 3; + Gamma = 1; // divided by num_of_features + Coef0 = 0; + C = 1; + Nu = 0.5; + P = 0.1; + CacheSize = 100; + Eps = 0.001; + Shrinking = true; + Probability = false; + WeightLabels = new int[0]; + Weights = new double[0]; + } + + /// + /// Type of a SVM formulation. Possible values are: + /// [C_SVC] C-Support Vector Classification. n-class classification (n >= 2), allows imperfect separation of classes with penalty multiplier C for outliers. + /// [NU_SVC] nu-Support Vector Classification. n-class classification with possible imperfect separation. Parameter Nu (in the range 0..1, the larger the value, the smoother the decision boundary) is used instead of C. + /// [ONE_CLASS] Distribution Estimation (One-class SVM). All the training data are from the same class, SVM builds a boundary that separates the class from the rest of the feature space. + /// [EPS_SVR] epsilon-Support Vector Regression. The distance between feature vectors from the training set and the fitting hyper-plane must be less than P. For outliers the penalty multiplier C is used. + /// [NU_SVR] nu-Support Vector Regression. Nu is used instead of p. + /// + public SVMType Type { get; set; } + /// + /// Type of a SVM kernel. Possible values are: + /// [LINEAR] Linear kernel. No mapping is done, linear discrimination (or regression) is done in the original feature space. It is the fastest option. + /// [POLY] Polynomial kernel. + /// [RBF] Radial basis function (RBF), a good choice in most cases. + /// [SIGMOID] Sigmoid kernel. + /// + public SVMKernelType Kernel { get; set; } + /// + /// Parameter degree of a kernel function (POLY). + /// + public int Degree { get; set; } + /// + /// Parameter gamma of a kernel function (POLY / RBF / SIGMOID). + /// + public double Gamma { get; set; } + /// + /// Parameter coef0 of a kernel function (POLY / SIGMOID). + /// + public double Coef0 { get; set; } + /// + /// Unit in MegaBytes. + /// + public double CacheSize { get; set; } + /// + /// Term criteria. Tolerance of the iterative SVM training procedure which solves a partial case of constrained quadratic optimization problem + /// + public double Eps { get; set; } + /// + /// Parameter C of a SVM optimization problem (C_SVC / EPS_SVR / NU_SVR). + /// + public double C { get; set; } + /// + /// Optional weights in the C_SVC problem , assigned to particular classes. + /// + public int[] WeightLabels { get; set; } + /// + /// Optional weights in the C_SVC problem , assigned to particular classes. + /// + public double[] Weights { get; set; } + /// + /// Parameter nu of a SVM optimization problem (NU_SVC / ONE_CLASS / NU_SVR). + /// + public double Nu { get; set; } + /// + /// Parameter epsilon of a SVM optimization problem (EPS_SVR). + /// + public double P { get; set; } + /// + /// Use the shrinking heuristics. + /// + public bool Shrinking { get; set; } + /// + /// Train a SVC or SVR model for probability estimates. + /// + public bool Probability { get; set; } + + public SVMParameter Clone() + { + SVMParameter y = new SVMParameter(); + y.Type = Type; + y.Kernel = Kernel; + y.Degree = Degree; + y.Gamma = Gamma; + y.Coef0 = Coef0; + y.C = C; + y.Nu = Nu; + y.P = P; + y.CacheSize = CacheSize; + y.Eps = Eps; + y.Shrinking = Shrinking; + y.Probability = Probability; + y.WeightLabels = WeightLabels.Select(a => a).ToArray(); + y.Weights = Weights.Select(a => a).ToArray(); + return y; + } - public static SVMParameter Convert(svm_parameter x) + public static SVMParameter Convert(svm_parameter x) + { + SVMParameter y = new SVMParameter(); + y.Type = (SVMType)x.svm_type; + y.Kernel = (SVMKernelType)x.kernel_type; + y.Degree = x.degree; + y.Gamma = x.gamma; + y.Coef0 = x.coef0; + y.CacheSize = x.cache_size; + y.Eps = x.eps; + y.C = x.C; + y.Nu = x.nu; + y.P = x.p; + y.Shrinking = x.shrinking != 0; + y.Probability = x.probability != 0; + + int length = x.nr_weight; + y.WeightLabels = new int[length]; + if (length > 0) + Marshal.Copy(x.weight_label, y.WeightLabels, 0, length); + + y.Weights = new double[length]; + if (length > 0) + Marshal.Copy(x.weight, y.Weights, 0, length); + + return y; + } + public static SVMParameter Convert(IntPtr ptr) + { + if (ptr == IntPtr.Zero) + return null; + + svm_parameter x = (svm_parameter)Marshal.PtrToStructure(ptr, typeof(svm_parameter)); + return SVMParameter.Convert(x); + } + public static IntPtr Allocate(SVMParameter x) + { + if (x == null) + return IntPtr.Zero; + + svm_parameter y = new svm_parameter(); + y.svm_type = (int)x.Type; + y.kernel_type = (int)x.Kernel; + y.degree = x.Degree; + y.gamma = x.Gamma; + y.coef0 = x.Coef0; + y.cache_size = x.CacheSize; + y.eps = x.Eps; + y.C = x.C; + y.nu = x.Nu; + y.p = x.P; + y.shrinking = x.Shrinking ? 1 : 0; + y.probability = x.Probability ? 1 : 0; + y.nr_weight = x.WeightLabels.Length; + + y.weight_label = IntPtr.Zero; + if (y.nr_weight > 0) { - SVMParameter y = new SVMParameter(); - y.Type = (SVMType)x.svm_type; - y.Kernel = (SVMKernelType)x.kernel_type; - y.Degree = x.degree; - y.Gamma = x.gamma; - y.Coef0 = x.coef0; - y.CacheSize = x.cache_size; - y.Eps = x.eps; - y.C = x.C; - y.Nu = x.nu; - y.P = x.p; - y.Shrinking = x.shrinking != 0; - y.Probability = x.probability != 0; - - int length = x.nr_weight; - y.WeightLabels = new int[length]; - if (length > 0) - Marshal.Copy(x.weight_label, y.WeightLabels, 0, length); - - y.Weights = new double[length]; - if (length > 0) - Marshal.Copy(x.weight, y.Weights, 0, length); - - return y; + y.weight_label = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(int)) * x.WeightLabels.Length); + Marshal.Copy(x.WeightLabels, 0, y.weight_label, x.WeightLabels.Length); } - public static SVMParameter Convert(IntPtr ptr) - { - if (ptr == IntPtr.Zero) - return null; - svm_parameter x = (svm_parameter)Marshal.PtrToStructure(ptr, typeof(svm_parameter)); - return SVMParameter.Convert(x); - } - public static IntPtr Allocate(SVMParameter x) + y.weight = IntPtr.Zero; + if (y.nr_weight > 0) { - if (x == null) - return IntPtr.Zero; - - svm_parameter y = new svm_parameter(); - y.svm_type = (int)x.Type; - y.kernel_type = (int)x.Kernel; - y.degree = x.Degree; - y.gamma = x.Gamma; - y.coef0 = x.Coef0; - y.cache_size = x.CacheSize; - y.eps = x.Eps; - y.C = x.C; - y.nu = x.Nu; - y.p = x.P; - y.shrinking = x.Shrinking ? 1 : 0; - y.probability = x.Probability ? 1 : 0; - y.nr_weight = x.WeightLabels.Length; - - y.weight_label = IntPtr.Zero; - if (y.nr_weight > 0) - { - y.weight_label = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(int)) * x.WeightLabels.Length); - Marshal.Copy(x.WeightLabels, 0, y.weight_label, x.WeightLabels.Length); - } - - y.weight = IntPtr.Zero; - if (y.nr_weight > 0) - { - y.weight = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double)) * x.Weights.Length); - Marshal.Copy(x.Weights, 0, y.weight, x.Weights.Length); - } - - int size = Marshal.SizeOf(y); - IntPtr ptr = Marshal.AllocHGlobal(size); - Marshal.StructureToPtr(y, ptr, true); - - return ptr; + y.weight = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double)) * x.Weights.Length); + Marshal.Copy(x.Weights, 0, y.weight, x.Weights.Length); } - public static void Free(svm_parameter x) - { - Marshal.FreeHGlobal(x.weight); - x.weight = IntPtr.Zero; - Marshal.FreeHGlobal(x.weight_label); - x.weight_label = IntPtr.Zero; - } - public static void Free(IntPtr ptr) - { - if (ptr == IntPtr.Zero) - return; + int size = Marshal.SizeOf(y); + IntPtr ptr = Marshal.AllocHGlobal(size); + Marshal.StructureToPtr(y, ptr, true); + + return ptr; + } + public static void Free(svm_parameter x) + { + Marshal.FreeHGlobal(x.weight); + x.weight = IntPtr.Zero; + + Marshal.FreeHGlobal(x.weight_label); + x.weight_label = IntPtr.Zero; + } + public static void Free(IntPtr ptr) + { + if (ptr == IntPtr.Zero) + return; - svm_parameter x = (svm_parameter)Marshal.PtrToStructure(ptr, typeof(svm_parameter)); + svm_parameter x = (svm_parameter)Marshal.PtrToStructure(ptr, typeof(svm_parameter)); - SVMParameter.Free(x); + SVMParameter.Free(x); - Marshal.DestroyStructure(ptr, typeof(svm_parameter)); - Marshal.FreeHGlobal(ptr); - ptr = IntPtr.Zero; - } + Marshal.DestroyStructure(ptr, typeof(svm_parameter)); + Marshal.FreeHGlobal(ptr); + ptr = IntPtr.Zero; } } diff --git a/LibSVMsharp/SVMProblem.cs b/LibSVMsharp/SVMProblem.cs index 7785c52..a32e8d3 100644 --- a/LibSVMsharp/SVMProblem.cs +++ b/LibSVMsharp/SVMProblem.cs @@ -5,157 +5,156 @@ using System.Runtime.InteropServices; using System.Text; -namespace LibSVMsharp +namespace LibSVMsharp; + +public class SVMProblem { - public class SVMProblem + public SVMProblem() { - public SVMProblem() - { - Y = new List(); - X = new List(); - } + Y = new List(); + X = new List(); + } - public int Length { get { return Y.Count; } } - public List Y { get; private set; } - public List X { get; private set; } + public int Length { get { return Y.Count; } } + public List Y { get; private set; } + public List X { get; private set; } - public void Add(SVMNode[] x, double y) + public void Add(SVMNode[] x, double y) + { + if (x.Length > 0) { - if (x.Length > 0) - { - SVMNode[] nodes = x.OrderBy(a => a.Index).ToArray(); - X.Add(nodes); - Y.Add(y); - } + SVMNode[] nodes = x.OrderBy(a => a.Index).ToArray(); + X.Add(nodes); + Y.Add(y); } - public void RemoveAt(int index) + } + public void RemoveAt(int index) + { + if (index < Length) { - if (index < Length) - { - Y.RemoveAt(index); - X.RemoveAt(index); - } + Y.RemoveAt(index); + X.RemoveAt(index); } - public void Insert(int index, SVMNode[] x, double y) + } + public void Insert(int index, SVMNode[] x, double y) + { + if (x.Length > 0) { - if (x.Length > 0) - { - SVMNode[] nodes = x.OrderBy(a => a.Index).ToArray(); - X.Insert(index, x); - Y.Insert(index, y); - } + SVMNode[] nodes = x.OrderBy(a => a.Index).ToArray(); + X.Insert(index, x); + Y.Insert(index, y); } - public SVMProblem Clone() + } + public SVMProblem Clone() + { + SVMProblem y = new SVMProblem(); + for (int i = 0; i < Length; i++) { - SVMProblem y = new SVMProblem(); - for (int i = 0; i < Length; i++) - { - SVMNode[] nodes = X[i].Select(x => x.Clone()).ToArray(); - y.Add(nodes, Y[i]); - } - return y; + SVMNode[] nodes = X[i].Select(x => x.Clone()).ToArray(); + y.Add(nodes, Y[i]); } + return y; + } + + public static SVMProblem Convert(svm_problem x) + { + double[] y_array = new double[x.l]; + Marshal.Copy(x.y, y_array, 0, y_array.Length); - public static SVMProblem Convert(svm_problem x) + List x_array = new List(); + IntPtr i_ptr_x = x.x; + for (int i = 0; i < x.l; i++) { - double[] y_array = new double[x.l]; - Marshal.Copy(x.y, y_array, 0, y_array.Length); - - List x_array = new List(); - IntPtr i_ptr_x = x.x; - for (int i = 0; i < x.l; i++) - { - IntPtr ptr_nodes = (IntPtr)Marshal.PtrToStructure(i_ptr_x, typeof(IntPtr)); - SVMNode[] nodes = SVMNode.Convert(ptr_nodes); - x_array.Add(nodes); - i_ptr_x = IntPtr.Add(i_ptr_x, Marshal.SizeOf(typeof(IntPtr))); - } - - SVMProblem y = new SVMProblem(); - for (int i = 0; i < x.l; i++) - { - y.Add(x_array[i], y_array[i]); - } - - return y; + IntPtr ptr_nodes = (IntPtr)Marshal.PtrToStructure(i_ptr_x, typeof(IntPtr)); + SVMNode[] nodes = SVMNode.Convert(ptr_nodes); + x_array.Add(nodes); + i_ptr_x = IntPtr.Add(i_ptr_x, Marshal.SizeOf(typeof(IntPtr))); } - public static SVMProblem Convert(IntPtr ptr) - { - if (ptr == IntPtr.Zero) - return null; - svm_problem x = (svm_problem)Marshal.PtrToStructure(ptr, typeof(svm_problem)); - return SVMProblem.Convert(x); - } - public static IntPtr Allocate(SVMProblem x) + SVMProblem y = new SVMProblem(); + for (int i = 0; i < x.l; i++) { - if (x == null || x.X == null || x.Y == null || x.Length < 1) - { - return IntPtr.Zero; - } - - svm_problem y = new svm_problem(); - y.l = x.Length; - - // Allocate problem.y - y.y = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double)) * x.Y.Count); - Marshal.Copy(x.Y.ToArray(), 0, y.y, x.Y.Count); - - // Allocate problem.x - y.x = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)) * x.X.Count); - IntPtr i_ptr_x = y.x; - for (int i = 0; i < x.X.Count; i++) - { - // Prepare each node array - // 1) All nodes containing zero value is removed - // 2) A node which index is -1 is added to the end - List temp = x.X[i].Where(a => a.Value != 0).ToList(); - temp.Add(new SVMNode(-1, 0)); - SVMNode[] nodes = temp.ToArray(); - - // Allocate node array - IntPtr ptr_nodes = SVMNode.Allocate(nodes); - Marshal.StructureToPtr(ptr_nodes, i_ptr_x, true); - - i_ptr_x = IntPtr.Add(i_ptr_x, Marshal.SizeOf(typeof(IntPtr))); - } - - // Allocate the problem - int size = Marshal.SizeOf(y); - IntPtr ptr = Marshal.AllocHGlobal(size); - Marshal.StructureToPtr(y, ptr, true); - - return ptr; + y.Add(x_array[i], y_array[i]); } - public static void Free(svm_problem x) + + return y; + } + public static SVMProblem Convert(IntPtr ptr) + { + if (ptr == IntPtr.Zero) + return null; + + svm_problem x = (svm_problem)Marshal.PtrToStructure(ptr, typeof(svm_problem)); + return SVMProblem.Convert(x); + } + public static IntPtr Allocate(SVMProblem x) + { + if (x == null || x.X == null || x.Y == null || x.Length < 1) { - Marshal.FreeHGlobal(x.y); - x.y = IntPtr.Zero; + return IntPtr.Zero; + } - IntPtr i_ptr_x = x.x; - for (int i = 0; i < x.l; i++) - { - IntPtr ptr_nodes = (IntPtr)Marshal.PtrToStructure(i_ptr_x, typeof(IntPtr)); - SVMNode.Free(ptr_nodes); + svm_problem y = new svm_problem(); + y.l = x.Length; - i_ptr_x = IntPtr.Add(i_ptr_x, Marshal.SizeOf(typeof(IntPtr))); - } + // Allocate problem.y + y.y = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double)) * x.Y.Count); + Marshal.Copy(x.Y.ToArray(), 0, y.y, x.Y.Count); - Marshal.FreeHGlobal(x.x); - x.x = IntPtr.Zero; - } - public static void Free(IntPtr ptr) + // Allocate problem.x + y.x = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)) * x.X.Count); + IntPtr i_ptr_x = y.x; + for (int i = 0; i < x.X.Count; i++) { - if (ptr == IntPtr.Zero) - return; + // Prepare each node array + // 1) All nodes containing zero value is removed + // 2) A node which index is -1 is added to the end + List temp = x.X[i].Where(a => a.Value != 0).ToList(); + temp.Add(new SVMNode(-1, 0)); + SVMNode[] nodes = temp.ToArray(); + + // Allocate node array + IntPtr ptr_nodes = SVMNode.Allocate(nodes); + Marshal.StructureToPtr(ptr_nodes, i_ptr_x, true); + + i_ptr_x = IntPtr.Add(i_ptr_x, Marshal.SizeOf(typeof(IntPtr))); + } - svm_problem x = (svm_problem)Marshal.PtrToStructure(ptr, typeof(svm_problem)); + // Allocate the problem + int size = Marshal.SizeOf(y); + IntPtr ptr = Marshal.AllocHGlobal(size); + Marshal.StructureToPtr(y, ptr, true); - SVMProblem.Free(x); + return ptr; + } + public static void Free(svm_problem x) + { + Marshal.FreeHGlobal(x.y); + x.y = IntPtr.Zero; - Marshal.DestroyStructure(ptr, typeof(svm_problem)); - Marshal.FreeHGlobal(ptr); - ptr = IntPtr.Zero; + IntPtr i_ptr_x = x.x; + for (int i = 0; i < x.l; i++) + { + IntPtr ptr_nodes = (IntPtr)Marshal.PtrToStructure(i_ptr_x, typeof(IntPtr)); + SVMNode.Free(ptr_nodes); + + i_ptr_x = IntPtr.Add(i_ptr_x, Marshal.SizeOf(typeof(IntPtr))); } + + Marshal.FreeHGlobal(x.x); + x.x = IntPtr.Zero; + } + public static void Free(IntPtr ptr) + { + if (ptr == IntPtr.Zero) + return; + + svm_problem x = (svm_problem)Marshal.PtrToStructure(ptr, typeof(svm_problem)); + + SVMProblem.Free(x); + + Marshal.DestroyStructure(ptr, typeof(svm_problem)); + Marshal.FreeHGlobal(ptr); + ptr = IntPtr.Zero; } }