ampl syntax error >>> x[ <<< - optimization

I am new to AMPL and can't seem to get past the following syntax error:
set I := {1, 2, 3, 4};
set J := {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
set K := {1, 2, 3, 4, 5, 6};
var d >=0;
var x binary;
CODE.txt, line 18 (offset 332):
syntax error
context: minimize Total_Cost: sum {i in I, j in J, k in K} >>> x[ <<< i,j,k] * d[i];
I can't see why the error seemingly occurs at the square bracket as I thought that subscripts should always be defined within square brackets.
Any tips would be lovely!
Thanks in advance.

After some experimentation, I found my mistake so will share it here in case anyone else encounters the same issue.
I merely forgot to specify the subscripts when initially stating the variable
Find below my modified (working) code:
set I := {1, 2, 3, 4};
set J := {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
set K := {1, 2, 3, 4, 5, 6};
var d{I} >=0;
var x{I,J,K} binary;
minimize Total_Cost: sum {i in I, j in J, k in K} x[i,j,k] * d[i];

When you declare a variable you must to declare his indexes too. In your case the problem is in the "x".
You must write your model like this:
set I := {1, 2, 3, 4};
set J := {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
set K := {1, 2, 3, 4, 5, 6};
var d{i in I} integer >=0;
var x{i in I, j in J, k in K} binary;
Regards!

Related

Extract specific number from a textboxes

How can I extract from this Textbox, for example what is in parentheses (9,2,8)
Textbox1.Text =
1, 3, 5, 6, 7, 11, 12, 13, 14, 20 (9)
5, 6, 10, 11, 12, 15, 17, 18, 19, 20 (2)
2, 3, 5, 6, 11, 13, 17, 18, 19, 20 (8)
And display in another textbox, Textbox2.Text = 9,2,8
There is another way of doing it.
Imports System.Text.RegularExpressions
Module Module1
Sub Main()
Dim s1 = "1, 3, 5, 6, 7, 11, 12, 13, 14, 20 (9)
5, 6, 10, 11, 12, 15, 17, 18, 19, 20 (2)
2, 3, 5, 6, 11, 13, 17, 18, 19, 20 (8)"
Dim re = New Regex("\(([^)]*)\)")
Dim things = re.Matches(s1)
For Each m As Match In things
Console.WriteLine(m.Groups(1).Value)
Next
Console.ReadLine()
End Sub
End Module
Outputs:
9
2
8
For this regular expression, I think a railroad diagram helps to explain what it does:
From https://regexper.com/#%5C%28%28%5B%5E%29%5D*%29%5C%29
You can achieve your desired result using a simple While loop
<TestMethod()>
Public Sub ExtractNumbersInParentheses()
Dim inputString As String = "1, 3, 5, 6, 7, 11, 12, 13, 14, 20 (9)
5, 6, 10, 11, 12, 15, 17, 18, 19, 20 (2)
2, 3, 5, 6, 11, 13, 17, 18, 19, 20 (8)"
Dim finalResult As String = String.Empty
Dim startingPosition As Integer = inputString.IndexOf("(", 0)
While (startingPosition > 0)
If (finalResult.Length > 0) Then finalResult += ", "
Dim extractedText = inputString.Substring(startingPosition + 1, 1)
finalResult += extractedText
startingPosition = inputString.IndexOf("(", startingPosition + 1)
End While
Debug.Print(finalResult)
End Sub
The key part is the .IndexOf function and each time you query the inputString you move the starting position to be beyond the current position otherwhise you will see the same parenthesis
After I ran this test, the output was:
9, 2, 8

Assign an integer variable to an integer variable and change name dynamic

Dim LastNumber as Integer = 1
Dim num_0() as Integer = {1, 2, 3, 4, 5}
Dim num_1() as Integer = {6, 7, 8, 9, 10}
Dim num_2() as Integer = {20, 21, 14, 36, 0}
Dim y() As Integer
y(0) = num_0(2)
When I use this code it executes perfectly
But the problem is I want to change the "0" in num_0(2)
When I do...
y(0) = num_ & LastNumber & (2)
This doesnt work
Or
y(0) = ("num_" & LastNumber & "(2)")
This gives me an error that converting a string to an integer is not possible
My question is How can I replace the "0" in num_0(2) with the LastNumber integer variable... so it reads the "8" out of the array num_1(2)
You can use multidimensional array (AKA rectangular array):
Dim num As Integer(,) = { {1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}, {20, 21, 14, 36, 0} }
y(0) = num(LastNumber, 2)
or jagged array (array of arrays) :
Dim num As Integer()() = { ({1, 2, 3, 4, 5}), ({6, 7, 8, 9, 10}), ({20, 21, 14, 36, 0}) }
y(0) = num(LastNumber)(2)

VB.NET - How to calculate the parity bit of a byte array

What is the most efficient way calculate the parity bit (if the number of active bits are odd or even) in a byte array? I have though about iterating through all the bits and summing up the active bits, but that would be very impractical purely based on the number of iterations required on larger byte arrays/files.
For your convenience (and my curiosity), I have done some timing tests with a parity lookup table compared to the other two methods suggested so far:
Module Module1
Dim rand As New Random
Dim parityLookup(255) As Integer
Sub SetUpParityLookup()
' setBitsCount data from http://stackoverflow.com/questions/109023/how-to-count-the-number-of-set-bits-in-a-32-bit-integer
Dim setBitsCount = {
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
}
For i = 0 To 255
parityLookup(i) = setBitsCount(i) And 1
Next
End Sub
' Method using lookup table
Function ParityOfArray(a() As Byte) As Integer
Dim parity As Integer = 0 ' use an Integer because they are faster
For i = 0 To a.Length - 1
parity = parity Xor parityLookup(a(i))
Next
Return parity
End Function
' Method by Alireza
Function ComputeParity(bytes() As Byte) As Byte
Dim parity As Boolean = False
For i As Integer = 0 To bytes.Length - 1
Dim b As Byte = bytes(i)
While b <> 0
parity = Not parity
b = CByte(b And (b - 1))
End While
Next
Return Convert.ToByte(parity)
End Function
' Method by dbasnett
Function CountBits(byteArray As Byte()) As Integer
Dim rv As Integer = 0
For Each b As Byte In byteArray
Dim count As Integer = b
count = ((count >> 1) And &H55) + (count And &H55)
count = ((count >> 2) And &H33) + (count And &H33)
count = ((count >> 4) And &HF) + (count And &HF)
rv += count
Next
Return rv
End Function
Sub FillWithRandomBytes(ByRef a() As Byte)
rand.NextBytes(a)
End Sub
Sub Main()
SetUpParityLookup()
Dim nBytes = 10000
Dim a(nBytes - 1) As Byte
FillWithRandomBytes(a)
Dim p As Integer
Dim sw As New Stopwatch
sw.Start()
p = ParityOfArray(a)
sw.Stop()
Console.WriteLine("ParityOfArray - Parity: {0} Time: {1}", p, sw.ElapsedTicks)
sw.Restart()
p = ComputeParity(a)
sw.Stop()
Console.WriteLine("ComputeParity - Parity: {0} Time: {1}", p, sw.ElapsedTicks)
sw.Restart()
p = CountBits(a)
sw.Stop()
' Note that the value returned from CountBits should be And-ed with 1.
Console.WriteLine("CountBits - Parity: {0} Time: {1}", p And 1, sw.ElapsedTicks)
Console.ReadLine()
End Sub
End Module
Typical ouput:
ParityOfArray - Parity: 0 Time: 386
ComputeParity - Parity: 0 Time: 1014
CountBits - Parity: 0 Time: 695
An efficient way to do this is to use the x & (x - 1) operation in a loop, until x becomes zero. This way you will loop only by the number of bits set to 1.
In VB.NET for a byte array:
Function ComputeParity(bytes() As Byte) As Byte
Dim parity As Boolean = False
For i As Integer = 0 To bytes.Length - 1
Dim b As Byte = bytes(i)
While b <> 0
parity = Not parity
b = b And (b - 1)
End While
Next
Return Convert.ToByte(parity)
End Function
Here is a function that counts bits.
Private Function CountBits(byteArray As Byte()) As Integer
Dim rv As Integer = 0
For x As Integer = 0 To byteArray.Length - 1
Dim b As Byte = byteArray(x)
Dim count As Integer = b
count = ((count >> 1) And &H55) + (count And &H55)
count = ((count >> 2) And &H33) + (count And &H33)
count = ((count >> 4) And &HF) + (count And &HF)
rv += count
Next
Return rv
End Function
Note: this code came from a collection of bit twiddling hacks I found some years ago. I converted it to VB.

Sort 3 x one dimensional arrays in parallell

I have 3 x one dimensional arrays of type integer, each array is the same length (between 5 - 20 million values) and I would like to sort them in parallel (ie keeping the relative position) by the second array, then the third array, then the first array. Does anyone have any ideas on the most efficient way to do this in vb.net?
If it helps, the first array is just a record of the initial position (the three arrays will be re-sorted to this order once various calculations are done). I need to sort them to determine the number of unique combinations of the second and third arrays (a combination is determined by the position in the array - in the example below the combinations are (0-1-4), (1-1-6) etc). Once that is determined I will resort them back based on the first array.
I looked at array.sort but that only covers 2 parallel arrays. I'm a bit wary of putting the values in tuples (or any other format), as it would (I assume - perhaps not) be a big overhead when converting 5 - 20 million records before processing.
For example:
Record Number Array: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
Link Array: {1, 1, 2, 1, 1, 2, 2, 2, 1, 2}
Line Number Array: {4, 6, 3, 5, 6, 7, 3, 2, 3, 4}
Having sorted / ordered by the second, then third, then first array, the expected output would be:
Record Number (1st Array): {8, 0, 3, 1, 4, 7, 2, 6, 9, 5}
Link Array (2nd Array): {1, 1, 1, 1, 1, 2, 2, 2, 2, 2}
Line Number Array (3rd Array): {3, 4, 5, 6, 6, 2, 3, 3, 4, 7}
Array.sort only allows you to sort 2 arrays in parallel and i'm a little confused by the options available in LinQ.
Does anyone have any suggestions on the best way to solve this problem?
Cheers,
I think you can get a backup of your Link Array. Then sort Link Array with Record Array, then you can sort un-sorted Link Array with Line Number Array. Can you please try it?
You didn't say if you want efficient in terms of time or space, but this takes about 3 seconds to transfer 20 million records from arrays to a list, and then about 30 seconds to do the sort on them, using less than 1GB of RAM. On my computer.
Option Infer On
Module Module1
Class Grouped
Property RecNo As Integer
Property Link As Integer
Property LineNo As Integer
Public Overrides Function ToString() As String
Return String.Format("({0}, {1}, {2})", Me.RecNo, Me.Link, Me.LineNo)
End Function
End Class
Sub Main()
' First try with the test data to show the correct result is obtained
Dim recNos = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
Dim links = {1, 1, 2, 1, 1, 2, 2, 2, 1, 2}
Dim lineNos = {4, 6, 3, 5, 6, 7, 3, 2, 3, 4}
' transfer the arrays to a List
Dim xs As New List(Of Grouped)
xs.Capacity = recNos.Length
For i = 0 To recNos.Length() - 1
xs.Add(New Grouped With {.RecNo = recNos(i), .Link = links(i), .LineNo = lineNos(i)})
Next
' sort the data
Dim ys = xs.OrderBy(Function(x) x.Link).ThenBy(Function(x) x.LineNo).ToList()
Console.WriteLine(String.Join(", ", ys))
' Now try with twenty million records
Dim rand = New Random()
Dim nRecs As Integer = 20000000
recNos = Enumerable.Range(0, nRecs - 1).ToArray()
ReDim links(nRecs - 1)
ReDim lineNos(nRecs - 1)
For i = 0 To nRecs - 1
links(i) = rand.Next(0, 9)
lineNos(i) = rand.Next(1, 9)
Next
Dim sw As New Stopwatch
sw.Start()
xs.Clear()
xs.Capacity = nRecs
For i = 0 To recNos.Length() - 1
xs.Add(New Grouped With {.RecNo = recNos(i), .Link = links(i), .LineNo = lineNos(i)})
Next
sw.Stop()
Console.WriteLine(sw.ElapsedMilliseconds.ToString())
sw.Restart()
ys = xs.OrderBy(Function(x) x.Link).ThenBy(Function(x) x.LineNo).ToList()
sw.Stop()
Console.WriteLine(sw.ElapsedMilliseconds.ToString())
Console.ReadLine()
End Sub
End Module

How to set an array to a list of values in VB.NET?

I cannot figure out how to set an array to one of two sets of numbers (there will be more later), every way that I have tried throws some kind of error. I have tried to Dim the array inside the case statements, but then I cannot use the array in the For Each, which makes this worthless.... any ideas would be appreciated.
Code:
Dim HourArray() As Integer
Select Case CurrentShapeRow(ROW_PERIOD)
Case "ON", "2X16"
HourArray = {6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21}
Case "2X8", "5X8"
HourArray = {0, 1, 2, 3, 4, 5, 22, 23}
Case Else
Throw New Exception(String.Format("Unhandled Period: {0}", CurrentShapeRow(ROW_PERIOD)))
End Select
For Each HourCount As Integer In HourArray()
'DO SOME STUFF HERE
Next
HourArray = New Integer() {1,2,3,4,5,6,7,8,9}
When you assign an array to an existing variable you must use a constructor explicitly:
HourArray = New Integer() { 6, 7, 8, 9, 10, 11, 12, 13 }
This differs from a declaration and assignment where the constructor is optional:
Dim HourArray() As Integer = { 6, 7, 8, 9, 10, 11, 12, 13 }
Dim hourArray As List(Of Integer)
Select Case CurrentShapeRow(ROW_PERIOD)
Case "ON", "2X16"
hourArray.AddRange(New Integer() {6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21})
Case "2X8", "5X8"
hourArray.AddRange(New Integer() {0, 1, 2, 3, 4, 5, 22, 23})
Case Else
Throw New Exception(String.Format("Unhandled Period: {0}", CurrentShapeRow(ROW_PERIOD)))
End Select
For Each i As Integer In hourArray
Console.WriteLine(i)
Next