Problem loading and solving old gams model

My target is basically load old Gams models to GamsPy and solve it. I started with one of the examples from official GamsPy documentation (Blend Problem).

First I tried to save it as gdx with GamsPy. I did it because I was not have a traditional GAMS model right now that I can work, also for a basic start. I am just adding last small part of the code.

b1 = Model(
    container=m,
    name="b1",
    equations=[pc],
    problem="LP",
    sense=Sense.MIN,
    objective= Sum(alloy, price[alloy] * v[alloy])
)
b1.toGams(path="gams/b1")

report = Parameter(container=m, name="report", domain=[alloy, "*"])

b1.solve()
report[alloy, "blend-1"] = v.l[alloy]
m.write("b1_test.gdx")

After getting gdx outputs, I tried to load this problem in a different repo to see if I success to work with external non python models. When I try to run this code I got an error about equations.

from gamspy import Container, Model

b1 = Container(load_from="gams/b1/b1_data.gdx")
# b1.loadRecordsFromGdx("b1_test.gdx")

model = Model(b1, "b1_model", equations=b1.getEquations(), problem="LP", sense="MIN", objective=??)
model.solve()

Error Message:

gamspy.exceptions.ValidationError: `pc` has been declared as an equation but no equation definition was found.

I also tried it on a different example again from the official documentation. I tried the watch the changes and data in model. I can see the data and definition as Equation like the other model but somehow it does not works for me. Probably I am missing something.

Thanks

GDX file does not contain the definitions of equations. The purpose of the container.write method is to save the records of the symbols. Hence, you cannot do what you want to do with simply writing a gdx file and reloading it. Instead you can serialize your container and deserialize later. Serialization saves all records and equations definitions in a zip file. For example, you can serialize the blend model as follows:

import gamspy as gp
import numpy as np

m = gp.Container()
alloy = gp.Set(
    m,
    name="alloy",
    records=["a", "b", "c", "d", "e", "f", "g", "h", "i"],
    description="products on the market",
)
elem = gp.Set(
    m,
    name="elem",
    records=["lead", "zinc", "tin"],
    description="required elements",
)

compdat = gp.Parameter(
    m,
    name="compdat",
    domain=[elem, alloy],
    records=np.array(
        [
            [10, 10, 40, 60, 30, 30, 30, 50, 20],
            [10, 30, 50, 30, 30, 40, 20, 40, 30],
            [80, 60, 10, 10, 40, 30, 50, 10, 50],
        ]
    ),
    description="composition data (pct)",
)
price = gp.Parameter(
    m,
    name="price",
    domain=alloy,
    records=np.array([4.1, 4.3, 5.8, 6.0, 7.6, 7.5, 7.3, 6.9, 7.3]),
    description="composition data (price)",
)
rb = gp.Parameter(
    m,
    name="rb",
    domain=elem,
    records=np.array([30, 30, 40]),
    description="required blend",
)

v = gp.Variable(
    m,
    name="v",
    domain=alloy,
    type="Positive",
    description="purchase of alloy (pounds)",
)

objective = gp.Sum(alloy, price[alloy] * v[alloy])
pc = gp.Equation(m, name="pc", domain=elem, description="purchase constraint")
mb = gp.Equation(m, name="mb", description="material balance")

pc[elem] = gp.Sum(alloy, compdat[elem, alloy] * v[alloy]) == rb[elem]
mb[...] = gp.Sum(alloy, v[alloy]) == 1

b1 = gp.Model(
    m,
    name="b1",
    equations=[pc],
    problem="LP",
    sense=gp.Sense.MIN,
    objective=objective,
)
gp.serialize(m, "path_to_the_zip_file.zip")

then, you can later deserialize it and solve as follows:

import gamspy as gp
m = gp.deserialize("path_to_the_zip_file.zip")
b1 = m.models["b1"]
b1.solve()

Thank you for your prompt response. Everything is works fine now. Thanks a lot

Thanks again for your previous reply. I have another question related to the same topic.

I tried the method of serializing and deserializing the container, and it worked as expected. I noticed that the compressed model .zip file contains two files: gams_state.g00 and dict.json.

After that, I wanted to try the same approach on an older GAMS model using GAMS Studio. My plan was to generate the .g00 file in GAMS Studio and then run it via GamsPy. I followed the instructions from the GAMS documentation “The Save and Restart Feature”.

I was able to generate the .g00 file, but I didn’t see any dict.json file.
When I tried to use this .g00 file with GamsPy, it gave an error because the dict.json file was missing.

Is it possible to make this work, or am I missing something?

Thanks!

The json file is generated by GAMSPy and it’s needed to deserialize a zip file.

If you want to use a restart file, you can simply set the load_from argument of the Container to the path of the save file (g00 file):

import gamspy as gp

m = gp.Container(load_from="path to your g00 file")

This would start the container from the restart state.

I hope that helps.

I tried it and did not get any error while reading the .g00 file. However I got the same previous error I asked first:

gamspy.exceptions.ValidationError: `cost` has been declared as an equation but no equation definition was found.

This is the code:

from gamspy import Container, Model

m= Container(load_from="s1.g00")

model = Model(m, "s1_model", equations=m.getEquations(), problem="LP", sense="MIN")
model.solve()

I tried to add .g00 file but forum did not allowed.

If you want to go from GAMS to GAMSPy, you have to redefine your equations for now. We are working on a solution which won’t require that in the future.

I also tried creating the dict.json file myself, but unfortunately, that didn’t work either. It seems like the only option now is to wait for the release.
Wishing you all the best, and looking forward to the updates!

No, it’s not your only option. Let’s take blend model as an example. Let’s say you ran the model with gams and generated a gdx file called “saved.gdx”.

You can redefine the equations as follows:

import gamspy as gp

m = gp.Container(load_from="saved.gdx")
alloy, compdat, elem, v, rb = m.getSymbols(["alloy", "compdat", "elem", "v", "rb"])
pc, mb = m.getSymbols(["pc", "mb"])

pc[elem] = gp.Sum(alloy, compdat[elem, alloy] * v[alloy]) == rb[elem]
mb[...] = gp.Sum(alloy, v[alloy]) == 1

b2 = gp.Model(
    m,
    name="b2",
    equations=[pc, mb],
    problem="LP",
    sense="min",
    objective=gp.Sum(alloy, compdat["price", alloy] * v[alloy]),
)
b2.solve()

I started conversion of equations into GamsPy like you said. I could not succeed this part and I could use little help :slight_smile:

This is the GAMS version
Defining sets:

* ------------ Define sets for number of Finite elements and collocation points, reaction rates, components, inlets
set
phase   /1*1/
;
Set
* Number of different inlets into the system
in      /1*1/
alias(in,inin)
;    

Defining variable:

N_Feed(phase,in)             Volume flow into the network (L|s)
parameters
*Boundaries
FeedFix /1/
N_Feed.fx(phase,in)           = FeedFix/(card(in)*card(phase));

I tried this definition but it was not the true definition:

from gamspy import Container, Card, Sum

# Loading gdx
model = Container(load_from="path_to_model.gdx")
# Get sets 
phase, inn, out, rr, m, f = model.getSymbols(["phase", "in","out", "rr", "m", "f" ])
# Positive network variables
n_Feed, n_Bypass, n_Outlet, c_Outlet = model.getSymbols([
    "N_Feed", 
    "N_Bypass", 
    "N_Outlet", 
    "C_Outlet"])

feedFix = model.getSymbols(["FeedFix"])
n_Feed.fx[phase, inn] = feedFix / ( Card(inn) * Card(phase) )

I got this warning:

AttributeError: 'list' object has no attribute 'gamsRepr'

I tried to just get the necessary part from the code. I hope I did not miss anything.

Thank you

Can you please send the whole script and the stack trace if possible? Just seeing the error message does not help too much for this case.

Here is the full error message. And just to be clear, do you ask me for full python script?

Traceback (most recent call last):
  File "C:\Users\ctc1733\Desktop\gamspy_playground\network.py", line 143, in <module>
    n_Feed.fx[phase, inn] = feedFix / (Card(inn) * Card(phase))
                            ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
  File "C:\Users\ctc1733\Desktop\gamspy_playground\.env\Lib\site-packages\gamspy\_algebra\operable.py", line 76, in __rtruediv__
    return expression.Expression(other, "/", self)
           ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
  File "C:\Users\ctc1733\Desktop\gamspy_playground\.env\Lib\site-packages\gamspy\_algebra\expression.py", line 101, in __init__
    self._representation = self._create_output_str()
                           ~~~~~~~~~~~~~~~~~~~~~~~^^
  File "C:\Users\ctc1733\Desktop\gamspy_playground\.env\Lib\site-packages\gamspy\_algebra\expression.py", line 222, in _create_output_str
    left_str, right_str = self._get_operand_representations()
                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
  File "C:\Users\ctc1733\Desktop\gamspy_playground\.env\Lib\site-packages\gamspy\_algebra\expression.py", line 194, in _get_operand_representations
    else self.left.gamsRepr()
         ^^^^^^^^^^^^^^^^^^
AttributeError: 'list' object has no attribute 'gamsRepr'

Yeah. i would be nice to be able to reproduce the issue to get the bottom of it.

getSymbols returns a list. So, you need to declare feedFix as follows:

feedFix = model.getSymbols(["FeedFix"])[0]

1 Like

Yeah you are right. I completely missed it. Thank you for your help