Hello, I'm new to this forum.
Right now I'm developing a software based on Genetic Algorithms. I really have almost none experience, and I have a question.

First of, this software is a prototype, a template. So the user can choose between a lot of choices (types of crossing and mutations). And I have many radio buttons for that.
The question, like in the thread title is, can I give the name of a suroutine to a variable, so that sub executes instead of making a comparisson about which radio button is selecten, THEN execute the sub of that option. This is sort of the problem:


for i=0 to 1000 ' A long for statement
if radiobutton1.checked = true then
method1(var1, var2)
elseif radiobutton2.checked = true then
method2(var1, var2)
...
else
methodn(var1, var2)
endif

some other code..
next


And I want something like:


if radiobutton1.checked = true then
method = method1(var1, var2)
elseif radiobutton2.checked = true then
method = method2(var1, var2)
...
else
method = methodn(var1, var2)
endif

for i = 0 to 1000
method(var1, var2)
some other code...
next

I'm studying Software Engineering but I'm just starting really.
And sorry for my bad english (not my language).

Recommended Answers

All 10 Replies

It is not possible to assign a method to a variable like that.
But you can create a class that holds all those methods, where you tell the constructor which method to execute.
Like this:

Public Class Methods
   Private strMethodName As String
   Private objVar1 As Object
   Private objVar2 As Object

   Public Sub New(NameOfMethod As String)
      Me.strMethodName = NameOfMethod
   End Sub

   Public Function Method(Var1 As Object, Var2 As Object) As Object
      objVar1 = Var1
      objVar2 = Var2

      Select Case strMethodName
         Case "method1":
            Return method_1()
         Case "method2":
            Return method_2()
         'And so on
         Else
            Return method_n()
      End Select
   End Function

   Private Function method_1() As Object
      'Do something with var1 and var2
      Return result
   End Function

   Private Function method_2() As Object
      'Do something else with var1 and var2
      Return result
   End Function

   Private Function method_n() As Object
      'Do something else with var1 and var2
      Return result
   End Function
End Class

Then do this in your code:

'This is your code
Dim clsMethods As Methods
If radiobutton1.checked = true then
   clsMethods = New Methods("method1")
ElseIf radiobutton2.checked = true then
   clsMethods = New Methods("method2")
Else
   clsMethods = New Methods("method3")
End If

For i = 0 To 1000
   Dim value As Object = clsMethods.Method(var1, var2)
   'Do something with the value
Next

I don't have return values. So they are subroutines, not functions, and they can't be "as object".
Also, I don't know how to use your line 12 in "do this in your code" part.

This is the class I made with your help:

Public Class Cruce
    Structure individuo
        Dim x() As Double
        Dim fx As Double
    End Structure
    Structure poblacion
        Dim ind() As individuo
    End Structure

    Private strMethodName As String
    Private objVar1 As Object
    Private objVar2 As Object
    Dim tpob, nvars, ngen, pto, p1, p2, ini As Integer

    Public Sub New(ByVal NameOfMethod As String)
        Me.strMethodName = NameOfMethod
    End Sub

    Public Sub Method(ByRef ind1 As individuo, ByRef ind2 As individuo)
        objVar1 = ind1
        objVar2 = ind2

        Select Case strMethodName
            Case "cruce_unpunto"
                cruce_unpunto(ind1, ind2)
            Case "cruce_dospuntos"
                cruce_dospuntos(ind1, ind2)
            Case "cruce_uniforme"
                cruce_uniforme(ind1, ind2)
            Case "cruce_intermedio"
                cruce_intermedio(ind1, ind2)
            Case "cruce_sbx"
                cruce_sbx(ind1, ind2)
            Case "cruce_arit"
                cruce_arit(ind1, ind2)
            Case Else
                cruce_arit_total(ind1, ind2)
        End Select
    End Sub


    Sub cruce_unpunto(ByRef ind1 As individuo, ByRef ind2 As individuo)
        'Cruce de un punto
        'Se elije un punto de cruza 
        'swap de valores de X entre individuos
        For i = 0 To pto
            swap_ind(ind1, ind2, i)
        Next

        For i = pto + 1 To UBound(ind1.x)
            swap_ind(ind1, ind2, i)
        Next
    End Sub
    Sub cruce_dospuntos(ByRef ind1 As individuo, ByRef ind2 As individuo)
        'Cruce de dos puntos
        'Se elijen dos puntos de cruza
        'y se intercambia lo que haya en el intermedio
        For i = p1 To p2
            swap_ind(ind1, ind2, i)
        Next
    End Sub
    Sub cruce_uniforme(ByRef ind1 As individuo, ByRef ind2 As individuo)
        'Se elije un numero n de puntos de cruce

    End Sub
    Public Sub swap_ind(ByRef ind1 As individuo, ByRef ind2 As individuo, ByVal i As Integer)
        Dim temp As Double
        temp = ind1.x(i)
        ind1.x(i) = ind2.x(i)
        ind2.x(i) = temp
    End Sub

    Sub cruce_intermedio(ByRef ind1 As individuo, ByRef ind2 As individuo)
        Dim a As Double = valor_random()
        For i = ini + 1 To UBound(ind1.x)
            ind1.x(i) = fun_cruce_int(i, ind1, ind2, a)
            ind2.x(i) = fun_cruce_int(i, ind2, ind1, a)
        Next
    End Sub
    Sub cruce_sbx(ByRef ind1 As individuo, ByRef ind2 As individuo)
        Dim u As Double = valor_random(), b, nc, p1, p2 As Double
        nc = 2
        'Obtener b
        If u > 0.5 Then
            b = (1 / (2 * (1 - u))) ^ (1 / (nc + 1))
        Else
            b = (2 * u) * (1 / (nc + 1))
        End If
        'Obtener valores de x
        For i = 0 To UBound(ind1.x)
            p1 = ind1.x(i)
            p2 = ind2.x(i)
            ind1.x(i) = 0.5 * ((p1 + p2) - b * Math.Abs(p1 - p2))
            ind2.x(i) = 0.5 * ((p1 + p2) - b * Math.Abs(p1 + p2))
        Next

    End Sub
    Function fun_cruce_int(ByVal i As Integer, ByRef ind As individuo, ByRef ind2 As individuo, ByVal a As Integer)
        Dim cruce As Double
        cruce = ind2.x(i) * a + ind.x(i) * (1 - a)
        Return cruce
    End Function

    Sub cruce_arit(ByRef ind1 As individuo, ByRef ind2 As individuo)
        Dim a As Double
        For i = ini + 1 To UBound(ind1.x)
            a = obtener_a(i, ind1, ind2)
            ind1.x(i) = fun_cruce_int(i, ind1, ind2, a)
            ind2.x(i) = fun_cruce_int(i, ind1, ind2, a)
        Next
    End Sub
    Function obtener_a(ByVal ini As Integer, ByRef ind1 As individuo, ByRef ind2 As individuo)
        Dim a, b, c, d, l, u, x As Double
        l = ind1.x(ini)
        u = ind1.x(ini)
        'Se buscan los limites superiores e inferiores
        For i = ini To UBound(ind1.x)
            If l > ind1.x(ini) Then
                l = ind1.x(ini)
            End If
            If l > ind2.x(ini) Then
                l = ind2.x(ini)
            End If
            If u < ind1.x(ini) Then
                u = ind1.x(ini)
            End If
            If u < ind2.x(ini) Then
                u = ind2.x(ini)
            End If
        Next

        a = (l - ind2.x(ini)) / (ind1.x(ini) - ind2.x(ini))
        b = (u - ind1.x(ini)) / (ind2.x(ini) - ind1.x(ini))
        c = (l - ind1.x(ini)) / (ind2.x(ini) - ind1.x(ini))
        d = (u - ind2.x(ini)) / (ind1.x(ini) - ind2.x(ini))

        If ind1.x(ini) > ind2.x(ini) Then
            x = Random(Random(a, b), Random(c, d))
        ElseIf ind1.x(ini) = ind2.x(ini) Then
            x = 0
        Else
            x = Random(Random(c, d), Random(a, b))
        End If
        Return x
    End Function
    Sub cruce_arit_total(ByRef ind1 As individuo, ByRef ind2 As individuo)
        Dim a As Double = valor_random()
        For i = 0 To UBound(ind1.x)
            ind1.x(i) = fun_cruce_int(i, ind1, ind2, a)
            ind2.x(i) = fun_cruce_int(i, ind2, ind1, a)
        Next
    End Sub

    Public Function posicion_random(ByRef ind As individuo)
        Microsoft.VisualBasic.VBMath.Randomize()
        Dim r As Integer
        r = Int((UBound(ind.x) + 1) * Rnd())
        Return r
    End Function
    Function valor_random()
        'valor random de 0 a 1
        Microsoft.VisualBasic.VBMath.Randomize()
        Dim m As Double
        m = Rnd()
        Return m
    End Function
    Public Function random(ByVal low, ByVal high)
        Microsoft.VisualBasic.VBMath.Randomize()
        Dim r As Integer
        r = (high - low + 1) * Rnd() + low
        Return r
    End Function

End Class

Well.
Since you're using ByRef for the arguments, then line 12 can be changed into simply this: "cslsMethods.Method(var1, var2)".
Ie, remove the "Dim value As Object = " part.

Does this solution work for you?

here a short example...

Sub Main()
	Dim msc As New MySubClass
		For i = 0 To 1000 ' A long for statement
			If radiobutton1.checked = True Then
				CallByName(msc, "Methode1", CallType.Method, New Object() {var1, var2})
			ElseIf radiobutton2.checked = True Then
				CallByName(msc, "Methode2", CallType.Method, New Object() {var1, var2})
			Else
				CallByName(msc, "Methode3", CallType.Method, New Object() {var1, var2})
			End If
		Next
	End Sub

Class MySubClass 'holds all methods that needs to be called

	Public Sub Methode1(ByVal s As String, ByVal i As Integer)
		Console.WriteLine(String.Format("string: {0}, Integer: {1}", s, i))
	End Sub

	Public Sub Methode2(ByVal s As String, ByVal i As String)
		Console.WriteLine(String.Format("String: {0}, Second string: {1}", s, i))
	End Sub

End Class

I see.
But your original question was "Is it possible to assign a method to a variable?".
And the answer is No, which is why I gave you a solution, that you built your own solution on.

Now I'm asking you, does it work?
Is your problem solved?

I see.
But your original question was "Is it possible to assign a method to a variable?".
And the answer is No, which is why I gave you a solution, that you built your own solution on.

Now I'm asking you, does it work?
Is your problem solved?

It wasn't me who wrote that last post.
Now I have another question. When I do this:

clsMethods.Method(pob.ind(i), pob.ind(i + 1))

I have this error:

Error 1 Value of type 'templateag3.Form1.individuo' cannot be converted to 'templateag3.Cruce.individuo'.

I copied the struct "individuo" to the class, but I need that same struct in the Form1 as well. How can I use just one struct that is valid for both class and form?

Oops. Didn't look at the name of the poster. My bad. :)

You can create a structure outside the class and make it public.
Now it will be accessible from anywhere.

Public Structure individuo
   Dim x() As Double
   Dim fx As Double
End Structure
Public Structure poblacion
   Dim ind() As individuo
End Structure

Public Class Cruce
...
End Class

Thank you! It works now!

Solved, sorry. Moved the "Dim clsMethods As New Cruce" at the top. Didn't work before because the "if statement" was in a separate Sub from the "for statement".


I just runned the program with the debug mode, and it does not work. At first it gave me an error and generated this for me:
The error:

Error 1 Argument not specified for parameter 'NameOfMethod' of 'Public Sub New(NameOfMethod As String)'.

Sub New()
        ' TODO: Complete member initialization 
    End Sub

This is the code you gave me, and the program ignores it:

Sub New(ByVal NameOfMethod As String)
        Me.strMethodName = NameOfMethod
    End Sub

It just goes to the "else" when it compares the name of the method. That's why it seemed to work. What can I do?

The error is here:

Dim clsMethods As New Cruce

I suggest that you follow the coding in the second snippet I gave in my first respons to you.
It states, with the name of your class:

Dim clsMethods As Cruce
If radiobutton1.checked = true then
   clsMethods = New Cruce("method1")
ElseIf radiobutton2.checked = true then
   clsMethods = New Cruce("method2")
Else
   clsMethods = New Cruce("method3")
End If

clsMethods.Method(pob.ind(i), pob.ind(i + 1))
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.