Posted
Comments None

The best strategy to generate the 6 Boolean Grammars of GeneXproTools (The All Gates Grammar, the NOT-AND-OR Grammar, the NAND Grammar, the NOR Grammar, the MUX Grammar, and the NOT-AND-XOR Grammar or Reed-Muller Grammar) for any programming language is to choose as template the built-in programming language that is closest to the language we want to add.

Perhaps the most important consideration in this phase is the comparison of code structures in both the template and the new language, especially the use of function prototypes and the placement of helper or auxiliary functions.

Additionally, the number and type of built-in logical functions in both the template and the new language also plays an important role, particularly the XOR function which in some languages (for example, in Matlab, Octave and R) is not implemented as a logical operator (the XOR function is essential for creating the Reed-Muller Grammar, which is a universal logical system using NOT, AND, and XOR).

And since the Go language also has a Boolean XOR operator with the syntax "x0 != x1" (see the previous post "Go Language: Boolean Xor Operator"), we can use any of the C languages (C, C++ or C#) as our starting point. As an example, I'm going to use C# because, like Go, it doesn't use function prototypes, which simplifies greatly the clean-up of all the new Boolean grammars.

So now that we've made our choice for the template, we just have to open all the C# Boolean Grammars of GeneXproTools and save them as Go.Boolean.01.AllGates.grm.xml, Go.Boolean.02.NotAndOrGates.grm.xml, Go.Boolean.03.NandGates.grm.xml, and so on.

And now we start doing the required transformations (useful tip: opening all the new Boolean grammars in Visual Studio is a good choice as it allows to make the changes at once in all open documents). I won't be going here over all the details, but the changes you'll have to make are pretty straightforward as all the blocks in the xml code are well documented and you just have to make the appropriate changes to implement your new programming language in GeneXproTools. For example, straight on top of the xml files you have to change the language name and file extension to "Go" and "go".

Other common changes to all 6 Boolean grammars are the keywords that determine which words show in blue in the Model Panel. So for Go we have "package", "func", "const", "return", "true", and "false".

Then you also have to make the adjustments to the Opening and Closing Statements, to the Default Header and the formatting of the Random Constants and Label Constants. For example, in Go we have "package gepModel{CRLF}{CRLF}" as the opening statement; as the header we have "{CRLF}{CRLF}func gepModel(d []bool) bool {"; the random constants as formatted as "{TAB}const {labelname} = {labelindex}{CRLF}"; and so on.

But anyway, the idea here is to make the appropriate changes in the template and then test them in the GeneXproTools environment in order to see if anything else needs to be done.

But going back to our Go All Gates Grammar and its basic components.

The first basic component is the list of all logic functions. There are 258 of them, most of which are functions of 3 and 4 arguments. And since most programming languages only implement the basic Boolean functions (NOT, AND, and OR) plus XOR, the changes we need to make are very few. For example, for the Go language we just have to change the definition of the XOR function by replacing "^"with "!=".

Next come the Helper Functions, which are 245 in total. You'll notice that they are all defined using just the Boolean operators NOT, AND, and OR, and so they can be used by any language that implements these logical operators. This is very handy for implementing all kinds of Custom Programming Languages (well, besides the functional languages such as Lisp, I don't know of any language that implements the basic AND and OR operators as "And(x,y)" or "Or(x,y)" but I wouldn't be surprised if they existed) since they all implement the Boolean operators AND and OR similarly (only the names and symbols change from language to language).

So, for example, for the Go language we don't have to make any changes in the definitions of the Helper Functions as both C# and Go use "&&", "||", and "!" for AND, OR, and NOT, respectively. We need, however, to take care of the function headers which are different in both languages (this is the kind of change that is easily done in all Boolean grammars at once, as we only have 4 different headers that must be replaced: one for the functions of 1 argument, another for the functions of 2 and also 3 and 4 arguments).

And that's all for the All Gates Grammar for the Go language!

So let's play a little with this new grammar and show some code generated with it.

For example, this simple Go code is a minimal logic circuit for the 5-Majority function created using just the basic Boolean functions NOT, AND, and OR:

package gepModel

func gepModel(d []bool) bool {
    y := false

    y = ((d[2] && (d[1] || d[3])) && (d[0] || d[4]))
    y = y || (d[4] && (d[1] && d[3]))
    y = y || ((d[2] || d[0]) && ((d[1] || d[4]) && d[3]))
    y = y || ((d[2] || d[1]) && (d[0] && d[4]))

    return y
}

But the beauty of GeneXproTools is that it lets you play with all kinds of logic functions! For example, the code below is another minimal logic circuit for the 5-Majority function designed with NOT, AND, OR, NAND, NOR, XOR, and NXOR just to show you the use of helper functions in the code:

package gepModel

func gepModel(d []bool) bool {
    y := false

    y = (d[4] && (d[1] && d[0]))
    y = y || (gepNor(gepNor(d[2],d[3]),gepNor(d[0],d[1])) && d[4])
    y = y || (gepNor((!((d[4] != d[1]))),gepNor(d[2],d[0])) && d[3])
    y = y || (d[0] && (!(gepNand((d[3] != d[1]),d[2]))))

    return y
}

func gepNand(x, y bool) bool {
    return (!(x && y))
}

func gepNor(x, y bool) bool {
    return (!(x || y))
}

And we can choose even wilder architectures such as a universal logical system based on the 3-multiplexer function (this is also for the 5-Majority function):

package gepModel

func gepModel(d []bool) bool {
    y := false

    y = gepMux(gepMux(gepMux(d[0],d[3],d[1]),gepMux(d[3],d[4],d[2]),
      gepMux(d[2],d[3],d[1])),d[4], gepMux(gepMux(d[2],d[4],d[1]),d[0],
      gepMux(d[3],d[2],d[1])))

    return y
}

func gepMux(x, y, z bool) bool {
    return (((!(x)) && y) || (x && z))
}

In the next post I'll show you how to generate and use the Boolean universal system of NOT, AND, and OR for the Go language.

Author

Posted
Comments None

Finding out that the Go programming language has already a built-in XOR operator (see the previous post "Go Language: Boolean Grammars") resulted in having to update two of the Go Boolean Grammars of GeneXproTools: the All Gates Grammar and the Reed Muller System Grammar.

The changes are very simple for both Boolean Grammars. For the All Gates Grammar I just had to replace the gepXor function "gepXor(x0,x1)" with the built-in XOR operator of Go "(x0 != x1)".

For the Reed-Muller System Grammar, I first had to revert to the C++ template and then replace all the function definitions with the C++ encoding. Then I just replaced the C++ XOR operator "^" with "!=".

As an example, here's the Go code for a minimal logic circuit for the 5-Majority function built using the functions NOT, AND, NAND, XOR, and NXOR:

package gepModel

func gepModel(d []bool) bool {
    y := false

    y = gepNand(gepNand(d[3],d[2]),((!(d[0])) && gepNand(d[4],d[1])))
    y = y && (!((gepNxor(d[1],(!(d[0]))) && (gepNand(d[2],d[4]) && (!(d[3]))))))
    y = y && (!(((!(d[4])) && (gepNand(d[2],d[0]) && gepNand(d[3],d[1])))))
    y = y && gepNxor(d[4],d[4])

    return y
}

func gepNxor(x, y bool) bool {
    return ((!((x || y))) || (x && y))
}

func gepNand(x, y bool) bool {
    return (!(x && y))
}

And here's the automatic conversion of the above code to the Reed-Muller System with only NOT, AND, and XOR:

package gepModel

func gepModel(d []bool) bool {
    y := false

    y = (!((!(d[3] && d[2])) && ((!(d[0])) && (!(d[4] && d[1])))))
    y = y && (!(((!(d[1] != (!(d[0])))) && ((!(d[2] && d[4])) && (!(d[3]))))))
    y = y && (!(((!(d[4])) && ((!(d[2] && d[0])) && (!(d[3] && d[1]))))))
    y = y && (!(d[4] != d[4]))

    return y
}

In the next post I'll start introducing the Go Boolean Grammars and how they can be easily generated using the C++ Boolean Grammars as template.

Author

Posted
Comments 5

As part of the new project "New Project: Cross-Validation, Var Importance & More", we are also adding support for the Go programming language in Logic Synthesis. And as usual, this includes support for 6 different Boolean Grammars: The All Gates Grammar, the NOT-AND-OR Grammar, the NAND Grammar, the NOR Grammar, the MUX Grammar, and the Reed-Muller Grammar (or NOT-AND-XOR Grammar).

As mentioned in the post "Support for the Go Language in GeneXproTools", the support for the Go language in GeneXproTools was spearheaded by Glenn Lewis, who also shared with the GeneXproTools community 5 of the Go Boolean Grammars. We've now tested Glenn's Boolean Grammars and also added the missing Reed-Muller Grammar.

Creating the grammar for the Reed-Muller System (NOT-AND-XOR system) can be a little bit tricky for programming languages such as Go that don't have a built-in XOR function for booleans. And I must say that of all programming languages supported by GeneXproTools (Ada, C, C++, C#, Excel VBA, Fortran, Go, Java, JavaScript, Matlab, Octave, Pascal, Perl, PHP, Python, R, Visual Basic, VB.Net, Verilog, and VHDL), Go is the only one without a built-in XOR!

This could be really problematic because we would have to go from the most common encoding of "x XOR y" used in almost all programming languages to "XOR(x,y)". And I can tell you this is no easy task, especially if you're doing this for the first time for all the 258 built-in Boolean functions of GeneXproTools!

But fortunately we don't have to do this from scratch! We already have in GeneXproTools two programming languages that use the required "XOR(x,y)" encoding: Matlab and Octave (the R language is another odd ball, but the R Boolean Grammars will only be added to GeneXproTools with this mini-release). Both these languages have a built-in XOR function that for whatever reason is implemented as a function call. This means that we can use the Matlab Grammar for the Reed-Muller System as template to create the Go Reed-Muller Grammar!

I must say I was very relieved when I realized that I could use the Matlab Grammar as template for the Reed-Muller System. For a couple of hours I just cursed the Go language and whoever decided not to include a XOR function. But then I went back to my archives and that's when I found the work I've done several years ago for the Reed-Muller System in Matlab (I must have cursed Matlab then, but I don't remember). But anyway, the world returned to its axis and I couldn't care less about the nonexistence of XOR in Go (although I should say, it would be a nice addition to the language).

Over the next posts I'll talk more about each of these Boolean systems and how to generate them for the Go language.

Update:

It turns out there's already an XOR operator in Go! It was buried so deep we had some trouble getting it out, but here it is:

x != y

Many thanks, Tony! I'll have to update the Grammars now…

Author

Posted
Comments None

To generate the Go code for the new 39 math functions that were introduced in GeneXproTools with Mini-Release 1, I decided to use the VB.Net code instead of the C++ code like Glenn did for the Go Math Grammar (see the previous post "Support for the Go Language in GeneXproTools"). And the main reason for this choice is that I can use "Then", "End If", "Else" and "ElseIf" to put the curly braces of the Go language neatly in place.

There are also other reasons for choosing the VB.Net Grammar as template instead of the C++ Grammar and that includes the fact that both Go and VB.Net have built-in min and max functions, which, in this particular case of the new 39 math functions, means less modifications to the code as we are evaluating min and max values in quite a few places in the code.

So, in all, the required modifications to the VB.Net code include replacing "Then" by "{", "End If" by "}", "Else" by "} else {", "ElseIf" by "} else if", "If" by "if", "Return" by "return", "End Function" by "}", "<>" by "!=", "And" by "&&", "Min" by "math.Min", "Max" by "math.Max", "Constant SLACK As Double" by "const SLACK", "As Double =" and "As Integer =" by ":=" and then remove "Dim" and change the comment marks to "//".

And finally, we also need to take care of the function declarations, which are different in both programming languages. But again, these are easily done by replacing each of the four templates (one for each of the four types of functions: functions of 1, 2, 3, and 4 arguments) by the correct one.

So here's the Go code for the new 39 math functions that were added to the built-in math functions of GeneXproTools 5.0 with Mini-Release 1 (note however that the Go Programming Language will only be available in GeneXproTools with the next mini-release):

func gepRamp1(x float64) float64 {
    if x > 0.0 {
        return x
    } else {
        return 0.0
    }
}

func gepRamp2(x float64) float64 {
    if x > 0.0 {
        return 0.0
    } else {
        return x
    }
}

func gepRamp3(x float64) float64 {
    if x > 0.0 {
        return 0.0
    } else {
        return -x
    }
}

func gepRamp4(x float64) float64 {
    if x > 0.0 {
        return -x
    } else {
        return 0.0
    }
}

func gepStep1(x float64) float64 {
    if x > 0.0 {
        return 1.0
    } else {
        return -1.0
    }
}

func gepStep2(x float64) float64 {
    if x > 0.0 {
        return 1.0
    } else {
        return 0.0
    }
}

func gepStep3(x float64) float64 {
    if x >= 1.0 {
        return 1.0
    } else if x <= -1.0 {
        return -1.0
    } else {
        return x
    }
}

func gepStep4(x float64) float64 {
    if x >= 1.0 {
        return 1.0
    } else if x <= 0.0 {
        return 0.0
    } else {
        return x
    }
}

func gepCL2A(x, y float64) float64 {
    if x > 0.0 && y > 0.0 {
        return 1.0
    } else {
        return -1.0
    }
}

func gepCL2B(x, y float64) float64 {
    if x >= 0.0 && y < 0.0 {
        return -1.0
    } else {
        return 1.0
    }
}

func gepCL2C(x, y float64) float64 {
    if x > 1.0 && y < -1.0 {
        return -1.0
    } else {
        return 1.0
    }
}

func gepCL2D(x, y float64) float64 {
    if x > 0.0 && y > 0.0 {
        return 1.0
    } else {
        return 0.0
    }
}

func gepCL2E(x, y float64) float64 {
    if x >= 0.0 && y <= 0.0 {
        return 0.0
    } else {
        return 1.0
    }
}

func gepCL2F(x, y float64) float64 {
    if x > 1.0 && y < -1.0 {
        return 0.0
    } else {
        return 1.0
    }
}

func gepCL3A(x, y float64) float64 {
    if x > 0.0 && y < 0.0 {
        return 1.0
    } else if x < 0.0 && y > 0.0 {
        return -1.0
    } else {
        return 0.0
    }
}

func gepCL3B(x, y float64) float64 {
    if x >= 1.0 && y >= 1.0 {
        return 1.0
    } else if x <= -1.0 && y <= -1.0 {
        return -1.0
    } else {
        return 0.0
    }
}

func gepCL3C(x, y float64) float64 {
    if x > 0.0 && y > 0.0 {
        return 1.0
    } else if x < 0.0 && y < 0.0 {
        return -1.0
    } else {
        return 0.0
    }
}

func gepMap3A(x, y float64) float64 {
    const SLACK = 10.0
    if y < (x - SLACK) {
        return -1.0
    } else if y > (x + SLACK) {
        return 1.0
    } else {
        return 0.0
    }
}

func gepMap3B(x, y, z float64) float64 {
    minValue := math.Min(x,y)
    maxValue := math.Max(x,y)
    if z < minValue {
        return -1.0
    } else if z > maxValue {
        return 1.0
    } else {
        return 0.0
    }
}

func gepMap3C(a, b, c, d float64) float64 {
    minValue := math.Min(math.Min(a,b),c)
    maxValue := math.Max(math.Max(a,b),c)
    if d < minValue {
        return -1.0
    } else if d > maxValue {
        return 1.0
    } else {
        return 0.0
    }
}

func gepMap4A(x, y float64) float64 {
    const SLACK = 10.0
    outVal := 0.0
    if y < (x - SLACK) {
        outVal = 0.0
    } else if y >= (x - SLACK) && y < x {
        outVal = 1.0
    } else if y >= x && y < (x + SLACK) {
        outVal = 2.0
    } else if y >= (x + SLACK) {
        outVal = 3.0
    }
    return outVal
}

func gepMap4B(x, y, z float64) float64 {
    // evaluate minValue(x,y), maxValue(x,y) and midrange
    minValue := math.Min(x,y)
    maxValue := math.Max(x,y)
    midrange := (maxValue + minValue)/2.0
    
    outVal := 0.0
    if z < minValue {
        outVal = 0.0
    } else if z >= minValue && z < midrange {
        outVal = 1.0
    } else if z >= midrange && z < maxValue {
        outVal = 2.0
    } else if z >= maxValue {
        outVal = 3.0
    }
    return outVal
}

func gepMap4C(a, b, c, d float64) float64 {
    // evaluate minValue(a,b,c), maxValue(a,b,c) and midleValue(a,b,c)
    //
    // evaluate minValue(a,b,c) and argMin(a,b,c)
    minValue := a
    argMin := 0
    if minValue > b {
        minValue = b
        argMin = 1
    }
    if minValue > c {
        minValue = c
        argMin = 2
    }
    // evaluate maxValue(a,b,c) and argMax(a,b,c)
    maxValue := a
    argMax := 0
    if maxValue < b {
        maxValue = b
        argMax = 1
    }
    if maxValue < c {
        maxValue = c
        argMax = 2
    }
    // evaluate midleValue(a,b,c)
    midleValue := c
    if 0 != argMin && 0 != argMax {
        midleValue = a
    }
    if 1 != argMin && 1 != argMax {
        midleValue = b
    }

    outVal := 0.0
    if d < minValue {
        outVal = 0.0
    } else if d >= minValue && d < midleValue {
        outVal = 1.0
    } else if d >= midleValue && d < maxValue {
        outVal = 2.0
    } else if d >= maxValue {
        outVal = 3.0
    }
    return outVal
}

func gepMap5A(x, y float64) float64 {
    const SLACK = 15.0
    outVal := 0.0
    if y < (x - SLACK) {
        outVal = 0.0
    } else if y >= (x - SLACK) && y < (x - SLACK/3.0) {
        outVal = 1.0
    } else if y >= (x - SLACK/3.0) && y < (x + SLACK/3.0) {
        outVal = 2.0
    } else if y >= (x + SLACK/3.0) && y < (x + SLACK) {
        outVal = 3.0
    } else if y >= (x + SLACK) {
        outVal = 4.0
    }
    return outVal
}

func gepMap5B(x, y, z float64) float64 {
    // evaluate minValue(x,y), maxValue(x,y), midpoint1, midpoint2
    minValue := math.Min(x,y)
    maxValue := math.Max(x,y)
    intervalLength := (maxValue - minValue)/3.0
    midpoint1 := minValue + intervalLength
    midpoint2 := minValue + 2.0*intervalLength
    
    outVal := 0.0
    if z < minValue {
        outVal = 0.0
    } else if z >= minValue && z < midpoint1 {
        outVal = 1.0
    } else if z >= midpoint1 && z < midpoint2 {
        outVal = 2.0
    } else if z >= midpoint2 && z < maxValue {
        outVal = 3.0
    } else if z >= maxValue {
        outVal = 4.0
    }
    return outVal
}

func gepMap5C(a, b, c, d float64) float64 {
    // evaluate minValue(a,b,c), maxValue(a,b,c), midleValue(a,b,c), midrange1, midrange2
    //
    // evaluate minValue(a,b,c) and argMin(a,b,c)
    minValue := a
    argMin := 0
    if minValue > b {
        minValue = b
        argMin = 1
    }
    if minValue > c {
        minValue = c
        argMin = 2
    }
    // evaluate maxValue(a,b,c) and argMax(a,b,c)
    maxValue := a
    argMax := 0
    if maxValue < b {
        maxValue = b
        argMax = 1
    }
    if maxValue < c {
        maxValue = c
        argMax = 2
    }
    // evaluate midleValue(a,b,c)
    midleValue := c
    if 0 != argMin && 0 != argMax {
        midleValue = a
    }
    if 1 != argMin && 1 != argMax {
        midleValue = b
    }
    midrange1 := (minValue + midleValue)/2.0
    midrange2 := (midleValue + maxValue)/2.0

    outVal := 0.0
    if d < minValue {
        outVal = 0.0
    } else if d >= minValue && d < midrange1 {
        outVal = 1.0
    } else if d >= midrange1 && d < midrange2 {
        outVal = 2.0
    } else if d >= midrange2 && d < maxValue {
        outVal = 3.0
    } else if d >= maxValue {
        outVal = 4.0
    }
    return outVal
}

func gepMap6A(x, y float64) float64 {
    const SLACK = 10.0
    outVal := 0.0
    if y < (x - SLACK) {
        outVal = 0.0
    } else if y >= (x - SLACK) && y < (x - SLACK/2.0) {
        outVal = 1.0
    } else if y >= (x - SLACK/2.0) && y < x {
        outVal = 2.0
    } else if y >= x && y < (x + SLACK/2.0) {
        outVal = 3.0
    } else if y >= (x + SLACK/2.0) && y < (x + SLACK) {
        outVal = 4.0
    } else if y >= (x + SLACK) {
        outVal = 5.0
    }
    return outVal
}

func gepMap6B(x, y, z float64) float64 {
    minValue := math.Min(x,y)
    maxValue := math.Max(x,y)
    midrange := (minValue + maxValue)/2.0
    midpoint1 := (minValue + midrange)/2.0
    midpoint2 := (midrange + maxValue)/2.0
    
    outVal := 0.0
    if z < minValue {
        outVal = 0.0
    } else if z >= minValue && z < midpoint1 {
        outVal = 1.0
    } else if z >= midpoint1 && z < midrange {
        outVal = 2.0
    } else if z >= midrange && z < midpoint2 {
        outVal = 3.0
    } else if z >= midpoint2 && z < maxValue {
        outVal = 4.0
    } else if z >= maxValue {
        outVal = 5.0
    }
    return outVal
}

func gepMap6C(a, b, c, d float64) float64 {
    // evaluate minValue(a,b,c), maxValue(a,b,c), midleValue(a,b,c), midrange1, midrange2
    //
    // evaluate minValue(a,b,c) and argMin(a,b,c)
    minValue := a
    argMin := 0
    if minValue > b {
        minValue = b
        argMin = 1
    }
    if minValue > c {
        minValue = c
        argMin = 2
    }
    // evaluate maxValue(a,b,c) and argMax(a,b,c)
    maxValue := a
    argMax := 0
    if maxValue < b {
        maxValue = b
        argMax = 1
    }
    if maxValue < c {
        maxValue = c
        argMax = 2
    }
    // evaluate midleValue(a,b,c)
    midleValue := c
    if 0 != argMin && 0 != argMax {
        midleValue = a
    }
    if 1 != argMin && 1 != argMax {
        midleValue = b
    }
    // evaluate midrange1 and midrange2
    midrange1 := (minValue + midleValue)/2.0
    midrange2 := (midleValue + maxValue)/2.0

    outVal := 0.0
    if d < minValue {
        outVal = 0.0
    } else if d >= minValue && d < midrange1 {
        outVal = 1.0
    } else if d >= midrange1 && d < midleValue {
        outVal = 2.0
    } else if d >= midleValue && d < midrange2 {
        outVal = 3.0
    } else if d >= midrange2 && d < maxValue {
        outVal = 4.0
    } else if d >= maxValue {
        outVal = 5.0
    }
    return outVal
}

func gepECL3A(x, y, z float64) float64 {
    if y > x && z < x {
        return 1.0
    } else if y < x && z > x {
        return -1.0
    } else {
        return 0.0
    }
}

func gepECL3B(x, y, z float64) float64 {
    if y > x && z > x {
        return 1.0
    } else if y < x && z < x {
        return -1.0
    } else {
        return 0.0
    }
}

func gepECL3C(x, y, z float64) float64 {
    if y >= x && z >= x {
        return 1.0
    } else if y <= -x && z <= -x {
        return -1.0
    } else {
        return 0.0
    }
}

func gepECL3D(a, b, c, d float64) float64 {
    minValue := math.Min(a,b)
    maxValue := math.Max(a,b)
    if c >= maxValue && d >= maxValue {
        return 1.0
    } else if c <= minValue && d <= minValue {
        return -1.0
    } else {
        return 0.0
    }
}

func gepAMin2(x, y float64) float64 {
    if x < y {
        return 0.0
    } else {
        return 1.0
    }
}

func gepAMin3(x, y, z float64) float64 {
    temp := x
    argMin := 0.0
    if temp >= y {
        temp = y
        argMin = 1.0
    }
    if temp >= z {
        argMin = 2.0
    }
    return argMin
}

func gepAMin4(a, b, c, d float64) float64 {
    temp := a
    argMin := 0.0
    if temp >= b {
        temp = b
        argMin = 1.0
    }
    if temp >= c {
        temp = c
        argMin = 2.0
    }
    if temp >= d {
        argMin = 3.0
    }
    return argMin
}

func gepAMax2(x, y float64) float64 {
    if x >= y {
        return 0.0
    } else {
        return 1.0
    }
}

func gepAMax3(x, y, z float64) float64 {
    temp := x
    argMax := 0.0
    if temp < y {
        temp = y
        argMax = 1.0
    }
    if temp < z {
        argMax = 2.0
    }
    return argMax
}

func gepAMax4(a, b, c, d float64) float64 {
    temp := a
    argMax := 0.0
    if temp < b {
        temp = b
        argMax = 1.0
    }
    if temp < c {
        temp = c
        argMax = 2.0
    }
    if temp < d {
        argMax = 3.0
    }
    return argMax
}

Author

Posted
Comments None

The Go Math Grammar that Glenn Lewis shared with the GeneXproTools community a while back (see the forum post "New experimental Go programming language grammar") has now been tested and extended with the new 39 math functions and new linking functions and will be added to the built-in math grammars of GeneXproTools with the next mini-release. This means that you'll be able to generate automatically Go code for all the models you create in GeneXproTools. As an example, here's the Go code for a nonlinear regression model generated for the Concrete Compressive Strength dataset:

//------------------------------------------------------------------------
// Regression model generated by GeneXproTools 5.0 on 1/29/2014 11:20:26 PM
// GEP File: C:\Program Files\GeneXproTools 50\SampleRuns\ConcreteStrength.gep
// Training Records:  687
// Validation Records:   343
// Fitness Function:  RMSE
// Training Fitness:  137.565058431653
// Training R-square: 0.852312063342217
// Validation Fitness:   137.37013713748
// Validation R-square:  0.870907944666967
//------------------------------------------------------------------------

package gepModel

import (
    "math"
)

func gepModel(d []float64) float64 {
    const G1C2 = 10.0317076770048
    const G2C5 = -2.76934946429679
    const G2C1 = 0.187640123844098
    const G3C9 = 119.482546094589
    const G4C0 = 14.5621350025957
    const G4C2 = -23.4923495987762
    const G4C9 = -19.2121721668995
    const G4C6 = 20.3393546847688
    const G5C5 = 17.2829378598944
    const G5C8 = 6.74868204486149
    const G5C3 = 5.92062389951742
    const G6C1 = -4.4417257533308
    const G6C6 = 11.4706172591873
    const G6C8 = -5.94326755831537
    const G6C4 = -1.78502761925108

    y := 0.0

    y = (gep3Rt(((d[1]*d[7])+(d[0]*d[7])))+(((d[1]/G1C2)+gep3Rt(d[6]))/2.0))
    y += gep3Rt(((math.Min((d[1]*d[2]),(d[0]-d[3]))/(d[1]-G2C1))*G2C5))
    y += ((((1.0-(d[1]+d[1]))+math.Pow(d[4],2.0))/2.0)/(((G3C9-d[5])+(d[0]+d[3]))/2.0))
    y += (G4C0*(((d[7]-d[4])/((d[2]+G4C9)/2.0))/(math.Min(G4C6,d[1])-G4C2)))
    y += ((gep3Rt(((G5C3*d[0])*(d[0]-d[4])))+(math.Min(G5C5,d[7])+math.Min(G5C8,d[4])))/2.0)
    y += (((math.Max(d[3],d[2])/G6C1)-(G6C6/d[7]))-((G6C8+G6C4)*(d[2]/d[3])))

    return y
}

func gep3Rt(x float64) float64 {
    if x < 0.0 {
        return -math.Pow(-x, (1.0 / 3.0))
    }
    return math.Pow(x, (1.0 / 3.0))
}

GeneXproTools allows you to create custom grammars for your favorite programming languages and we can use the Go programming language to show how that can be easily done using existing grammars as templates. For example, Glenn used the C++ Grammar as template for his Go Grammar, which is a great choice given that the calculator of GeneXproTools is also in C++. But the idea is to use the grammar template that results in less work and less bugs upon translation, which often involves choosing the programming language that we are most comfortable with.

In the next post I'll show how to generate the Go code for the new 39 math functions that were introduced with GeneXproTools 5.0 MR1. I'll also do a series of posts on how to create a custom math grammar using the Go programming language as an example, guiding you through the main components of a math grammar, from basic functions to helper functions and code structure.

Author

← Older Newer →