VERSION 1.0 CLASS BEGIN MultiUse = -1 'True END Attribute VB_Name = "clsOSInstance" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = False Attribute VB_PredeclaredId = False Attribute VB_Exposed = False Option Explicit Option Base 1 '***************** Code Start ****************** 'This code was originally written by Terry Kreft. 'It is not to be altered or distributed, 'except as part of an application. 'You are free to use it in any application, 'provided the copyright notice is left unchanged. ' 'Code Courtesy of 'Terry Kreft Private Const STARTF_USESHOWWINDOW& = &H1 Private Const NORMAL_PRIORITY_CLASS = &H20& Private Const INFINITE = -1& Private Type STARTUPINFO cb As Long lpReserved As String lpDesktop As String lpTitle As String dwX As Long dwY As Long dwXSize As Long dwYSize As Long dwXCountChars As Long dwYCountChars As Long dwFillAttribute As Long dwFlags As Long wShowWindow As Integer cbReserved2 As Integer lpReserved2 As Long hStdInput As Long hStdOutput As Long hStdError As Long End Type Private Type PROCESS_INFORMATION hProcess As Long hThread As Long dwProcessID As Long dwThreadID As Long End Type Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal _ hHandle As Long, ByVal dwMilliseconds As Long) As Long Private Declare Function CreateProcessA Lib "kernel32" (ByVal _ lpApplicationName As Long, ByVal lpCommandLine As String, ByVal _ lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, _ ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _ ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As Long, _ lpStartupInfo As STARTUPINFO, lpProcessInformation As _ PROCESS_INFORMATION) As Long Private Declare Function CloseHandle Lib "kernel32" (ByVal _ hObject As Long) As Long '***************** Code End Terry Kreft **************** 'Basic Parameters Public numVar As Long Public numCon As Long Public numNonz As Long Public byCol As Boolean Public isMax As Boolean Public probName As String Public osilInstance As String Private Const POSINFINITY = 1E+308 ' XML Data Structures Private osinstance As DOMDocument60 ' 'create the element nodes ' Private osil As IXMLDOMElement Private instanceData As IXMLDOMNode Private name As IXMLDOMElement Private instanceHeader As IXMLDOMNode Private variables As IXMLDOMElement Private var As IXMLDOMElement Private objectives As IXMLDOMElement Private obj As IXMLDOMElement Private coef As IXMLDOMElement Private constraints As IXMLDOMElement Private con As IXMLDOMElement Private linearConstraintCoefficients As IXMLDOMElement Private start As IXMLDOMElement Private value As IXMLDOMElement Private rowIdx As IXMLDOMElement Private colIdx As IXMLDOMElement Private el As IXMLDOMElement ' define the attribute nodes ' ' variable attributes Private schemaLocation As IXMLDOMAttribute Private xsiNamespace As IXMLDOMAttribute Private osNamespace As IXMLDOMAttribute Private numberOfVariables As IXMLDOMAttribute Private varName As IXMLDOMAttribute Private varUB As IXMLDOMAttribute Private varLB As IXMLDOMAttribute Private varType As IXMLDOMAttribute ' objective function attributes Private numberOfObjectives As IXMLDOMAttribute Private objName As IXMLDOMAttribute Private objMaxOrMin As IXMLDOMAttribute Private numberOfObjCoef As IXMLDOMAttribute Private coefIdx As IXMLDOMAttribute ' constraint attribute Private numberOfConstraints As IXMLDOMAttribute Private conName As IXMLDOMAttribute Private conLB As IXMLDOMAttribute Private conUB As IXMLDOMAttribute ' linear constraintCoefficients attributes Private numberOfValuesAtt As IXMLDOMAttribute ' ' ' 'Define the Get properties Property Get PosInf() As Double PosInf = POSINFINITY End Property Public Sub OSinitModel() Dim ns As String Set osinstance = New DOMDocument60 Set osil = osinstance.createElement("osil") 'Set osNamespace = osinstance.createAttribute("xmlns") 'osNamespace.Text = "os.optimizationservices.org" Set schemaLocation = osinstance.createAttribute("xsi:schemaLocation") 'local validationo schemaLocation.Text = "os.optimizationservices.org C:\schemas\OSiL.xsd" ' remote validation -- does notwork on my machine 'schemaLocation.Text = "os.optimizationservices.org http://www.optimizationservices.org/schemas/OSiL.xsd" Set xsiNamespace = osinstance.createAttribute("xmlns:xsi") xsiNamespace.Text = "http://www.w3.org/2001/XMLSchema-instance" osil.setAttributeNode xsiNamespace osil.setAttributeNode schemaLocation osinstance.appendChild osil Set instanceHeader = osinstance.createElement("instanceHeader") instanceHeader.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab) Set name = osinstance.createElement("name") name.Text = Me.probName instanceHeader.appendChild name instanceHeader.appendChild osinstance.createTextNode(vbNewLine + vbTab) Set instanceData = osinstance.createElement("instanceData") instanceData.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab) End Sub Public Sub OSgenerateVariables(varLBArray() As Double, varUBArray() As Double, varTypeArray() As String) Dim I As Long ' generate the variables ' Set variables = osinstance.createElement("variables") Set numberOfVariables = osinstance.createAttribute("numberOfVariables") numberOfVariables.Text = Me.numVar variables.setAttributeNode numberOfVariables 'generate the var children For I = 1 To Me.numVar variables.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab + vbTab) Set var = osinstance.createElement("var") If varUBArray(I) < POSINFINITY Then 'define the variable upper bound attribute Set varUB = osinstance.createAttribute("ub") varUB.Text = varUBArray(I) var.setAttributeNode varUB End If If varLBArray(I) <> 0 Then 'define the variable lower bound attribute Set varLB = osinstance.createAttribute("lb") varLB.Text = varLBArray(I) var.setAttributeNode varLB End If If varTypeArray(I) <> "C" Then ' define the variable type Set varType = osinstance.createAttribute("type") varType.Text = varTypeArray(I) var.setAttributeNode varType End If variables.appendChild var Next I instanceData.appendChild variables variables.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab) instanceData.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab) End Sub Public Sub OSgenerateConstraints(conLBArray() As Double, conUBArray() As Double) Dim I As Long ' generate the variables ' Set constraints = osinstance.createElement("constraints") Set numberOfConstraints = osinstance.createAttribute("numberOfConstraints") numberOfConstraints.Text = Me.numCon constraints.setAttributeNode numberOfConstraints 'generate the con children For I = 1 To Me.numCon constraints.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab + vbTab) Set con = osinstance.createElement("con") 'define the constraint upper bound attribute If conUBArray(I) < POSINFINITY Then 'define the constraint upper bound attribute Set conUB = osinstance.createAttribute("ub") conUB.Text = conUBArray(I) con.setAttributeNode conUB End If If conLBArray(I) > -POSINFINITY Then 'define the constraint lower bound attribute Set conLB = osinstance.createAttribute("lb") conLB.Text = conLBArray(I) con.setAttributeNode conLB End If constraints.appendChild con Next I instanceData.appendChild constraints constraints.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab) instanceData.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab) End Sub Public Sub OSgenerateObjective(objCoefArray() As Double) ' ' generated the objectives ' Dim I As Long Set objectives = osinstance.createElement("objectives") Set numberOfObjectives = osinstance.createAttribute("numberOfObjectives") numberOfObjectives.Text = "1" objectives.setAttributeNode numberOfObjectives 'generate the obj children 'for now assume we can have only one objective Set obj = osinstance.createElement("obj") Set objName = osinstance.createAttribute("name") objName.Text = "Objective Function" ' if maxOrMinRange not defined, assume a maximum problem If Me.isMax = True Then Set objMaxOrMin = osinstance.createAttribute("maxOrMin") objMaxOrMin.Text = "max" Else Set objMaxOrMin = osinstance.createAttribute("maxOrMin") objMaxOrMin.Text = "min" End If Set numberOfObjCoef = osinstance.createAttribute("numberOfObjCoef") numberOfObjCoef.Text = Me.numVar obj.setAttributeNode objName obj.setAttributeNode objMaxOrMin obj.setAttributeNode numberOfObjCoef 'we treat objective function as a dense vector 'number of coef is equal to number of var objectives.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab + vbTab) objectives.appendChild obj For I = 1 To Me.numVar obj.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab + vbTab + vbTab) Set coefIdx = osinstance.createAttribute("idx") coefIdx.Text = I - 1 Set coef = osinstance.createElement("coef") coef.Text = objCoefArray(I) coef.setAttributeNode coefIdx obj.appendChild coef Next I obj.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab + vbTab) objectives.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab) instanceData.appendChild objectives End Sub Public Sub OSgenerateLinearConstraintMatrix(starts() As Long, indexes() As Long, values() As Double) ' ' generated the linearConstraintCoefficients ' Dim I As Long instanceData.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab) Set linearConstraintCoefficients = osinstance.createElement("linearConstraintCoefficients") Set numberOfValuesAtt = osinstance.createAttribute("numberOfValues") numberOfValuesAtt.Text = Me.numNonz linearConstraintCoefficients.setAttributeNode numberOfValuesAtt 'generate the start el elements Set start = osinstance.createElement("start") 'for now we assume matrix stored by column If Me.byCol = True Then For I = 1 To Me.numVar + 1 start.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab + vbTab + vbTab) Set el = osinstance.createElement("el") el.Text = starts(I) - 1 start.appendChild el Next I Else For I = 1 To Me.numCon + 1 start.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab + vbTab + vbTab) Set el = osinstance.createElement("el") el.Text = starts(I) - 1 start.appendChild el Next I End If start.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab + vbTab) If Me.byCol = True Then ' 'generate row indexes Set rowIdx = osinstance.createElement("rowIdx") For I = 1 To Me.numNonz rowIdx.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab + vbTab + vbTab) Set el = osinstance.createElement("el") el.Text = indexes(I) - 1 rowIdx.appendChild el Next I rowIdx.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab + vbTab) Else ' 'generate col indexes Set colIdx = osinstance.createElement("colIdx") For I = 1 To Me.numNonz colIdx.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab + vbTab + vbTab) Set el = osinstance.createElement("el") el.Text = indexes(I) - 1 colIdx.appendChild el Next I colIdx.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab + vbTab) End If ' ' 'generate matrix values Set value = osinstance.createElement("value") For I = 1 To Me.numNonz value.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab + vbTab + vbTab) Set el = osinstance.createElement("el") el.Text = values(I) value.appendChild el Next I value.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab + vbTab) ' linearConstraintCoefficients.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab + vbTab) linearConstraintCoefficients.appendChild start linearConstraintCoefficients.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab + vbTab) If Me.byCol = True Then linearConstraintCoefficients.appendChild rowIdx Else linearConstraintCoefficients.appendChild colIdx End If linearConstraintCoefficients.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab + vbTab) linearConstraintCoefficients.appendChild value instanceData.appendChild linearConstraintCoefficients linearConstraintCoefficients.appendChild osinstance.createTextNode(vbNewLine + vbTab + vbTab) End Sub Public Sub OSfinishModel() osil.appendChild osinstance.createTextNode(vbNewLine + vbTab) osil.appendChild instanceHeader osil.appendChild osinstance.createTextNode(vbNewLine + vbTab) osil.appendChild instanceData instanceData.appendChild osinstance.createTextNode(vbNewLine + vbTab) osil.appendChild osinstance.createTextNode(vbNewLine) osilInstance = osinstance.XML Dim child As IXMLDOMNode 'MsgBox osil.ChildNodes.Length 'For Each child In osil.ChildNodes ' MsgBox child.nodeName 'Next End Sub Public Sub OSWriteInstanceToFile(filename As String) Dim fileObject, xmlFile Set fileObject = CreateObject("Scripting.FileSystemObject") fileObject.createTextFile filename Set xmlFile = fileObject.OpenTextFile(filename, 2, -2) Dim child1 As IXMLDOMElement Dim child2 As IXMLDOMNode ' For Each child1 In osinstance.ChildNodes ' MsgBox child1.Attributes.Length ' For Each child2 In child1.Attributes ' MsgBox child2.nodeName ' Set osNamespace = child2 ' Next 'child1.createAttribute ("xmlns") 'child1.setAttributeNode osNamespace 'osNamespace.Text = "os.optimizationservices.org" 'child1.setAttributeNode (osNamespace) ' Dim MyNode As IXMLDOMNode 'Set MyNode = osinstance.createNode(2, "xmlns", "") 'Set osNamespace = osinstance.createAttribute("xmlns") 'osNamespace.Text = "os.optimizationservices.org" 'child1.setAttributeNode MyNode 'Total kludge by Kipp Dim str1 As String Dim str2 As String str1 = " 0 Then With ws.Range("A1") Set objRange = ws.Range(.Cells(1, 1), .Cells(2, 1)) End With objRange.name = "objValue" objRange.Cells(1, 1) = "Optimal Value" For Each objNode In objValNodes objRange.Cells(2, 1) = objNode.Text Next objNode End If ' print the primal values if available If primalValNodes.Length > 0 Then With ws.Range("B1") Set primalRange = ws.Range(.Cells(1, 1), .Cells(primalValNodes.Length + 1, 2)) End With primalRange.name = "primalValues" primalRange.Cells(1, 1) = "Variable" primalRange.Cells(1, 2) = "Value" I = 1 For Each primalNode In primalValNodes primalRange.Cells(I + 1, 1) = I - 1 primalRange.Cells(I + 1, 2) = primalNode.Text I = I + 1 Next primalNode End If ' ' print the dual values If dualValNodes.Length > 0 Then With ws.Range("F1") Set dualRange = ws.Range(.Cells(1, 1), .Cells(primalValNodes.Length + 1, 2)) End With dualRange.name = "dualValues" dualRange.Cells(1, 1) = "Constraint" dualRange.Cells(1, 2) = "Dual Value" I = 1 For Each dualNode In dualValNodes dualRange.Cells(I + 1, 1) = I - 1 dualRange.Cells(I + 1, 2) = dualNode.Text I = I + 1 Next dualNode End If ' print the reduced cost values If reducedCostNodes.Length > 0 Then With ws.Range("D1") Set reducedCostRange = ws.Range(.Cells(1, 1), .Cells(reducedCostNodes.Length + 1, 1)) End With reducedCostRange.name = "reducedCostValues" reducedCostRange.Cells(1, 1) = "Reduced Cost" I = 1 For Each reducedCostNode In reducedCostNodes reducedCostRange.Cells(I + 1, 1) = reducedCostNode.Text I = I + 1 Next reducedCostNode End If End Sub Public Sub OSSolveASync(Pathname As String, Optional WindowStyle As Long) Shell Pathname, WindowStyle End Sub '***************** Code Start ****************** 'This code was originally written by Terry Kreft. 'It is not to be altered or distributed, 'except as part of an application. 'You are free to use it in any application, 'provided the copyright notice is left unchanged. ' 'Code Courtesy of 'Terry Kreft Public Sub OSSolveSync(Pathname As String, Optional WindowStyle As Long) Dim proc As PROCESS_INFORMATION Dim start As STARTUPINFO Dim ret As Long ' Initialize the STARTUPINFO structure: With start .cb = Len(start) If Not IsMissing(WindowStyle) Then .dwFlags = STARTF_USESHOWWINDOW .wShowWindow = WindowStyle End If End With ' Start the shelled application: ret& = CreateProcessA(0&, Pathname, 0&, 0&, 1&, _ NORMAL_PRIORITY_CLASS, 0&, 0&, start, proc) ' Wait for the shelled application to finish: ret& = WaitForSingleObject(proc.hProcess, INFINITE) ret& = CloseHandle(proc.hProcess) End Sub '***************** Code End Terry Kreft ****************