adding variables in the case of symmetric TSP - python

I have to implement a symmetrical TSP. When I go to add the variables:
x = m.addVars (Costs.Keys (), vtype = GRB.BINARY, obj = Costs, name = 'x')
It gives me the error:
'list' object has no attribute 'Key '.
I have the data saved in a list, is there a way to add the variable or do I necessarily have to save the data in a dictionary?

Seems like Costs is a list. Typically, use a dictionary of distances, indexed by the edge pairs i,j. See the Gurobi tsp.py example code for an illustration.

Related

Python 3.8+ Tuple to variable index?

I have a variable, jdata, that holds data read from a JSON data file. It consists of many levels of dictionaries and lists of dictionaries. I have a search routine that returns a tuple containing path-like information to the element I want to access. I'm struggling to turn the tuple into a variable index. For example, the search routine may return ('name', 5, 'pic', 3). So I want to access jdata['name'][5]['pic'][3]. The number of levels down into the data can change for each search, so the tuple length is variable.
Addendum:
for everyone asking for code and what I've done:
I don't have code to share because I don't know how to do it and that's why I'm asking here. My first thought was to try and create the text for accessing the variable, for the example above,
"x = jdata['name'][5]['pic'][3]"
and then looking for a python way of executing that line of code. I figured there has to be a more elegant solution.
I thought the description of tuple to variable access was pretty straight forward, but here is an expanded version of my problem.
jdata = { 'thing1': 1,
'name': [
{},
{},
{},
{},
{},
{ 'thing11': 1,
'pic': [ 'LocationOfPicA',
'LocationOfPicB',
'LocationOfPicC',
'LocationOfPicD',
'LocationOfPicE'],
'thing12: 2},
{},
{} ],
'thing2': 2}
I searched for 'PicD' and my search code returns: ('name', 5, 'pic', 3)
Now I want to do some stuff, for example, accessing the value 'LocationOfPicD', copy the file located there to some other place, and update the value of 'LocationOfPicD' to the new value. All of this I can code. I just need to be able to turn the tuple into an accessible variable.
Edit: I was just reading about mutability in python. Instead of generating a path to an element in the dictionary, I think I can just assign that element value to a variable (x, for example) that gets passed back up the recursion chain of the initial search. From my understanding, I can change x and that also changes the element within the jdata variable. If that doesn't work, I can resort to using the eval() command on my generated text statement using the tuple as originally planned.
If I understand the problem correctly, you just need to avoid getting the lowest level item by value. So, you could do something like
indexes = ('name', 5, 'pic', 3)
x = jdata
for index in indexes[:-1]:
x = x[index]
x[indexes[-1]] = <new_value_here>
Easy and quick recursive implementation.
def get_d(d, tup, ind=0):
if ind == len(tup) - 1: # last item just return value
return d[tup[ind]]
return get_d(d[tup[ind]], tup, ind + 1) # else keep getting sub-item
# input input datastructure (could be dict, list, or gettable item) and tuple of items to recursively get
value = get_d(jdata, ('name', 5, 'pic', 3))
Note: this implementation is super basic and has no error handling. It's just here to give you an idea on how it could be done.

How to iterate to create variables in a list

Suppose I have the following code:
classifiers_name_all = [('AdaBoostClassifier', AdaBoostClassifier(), 'AdaBoost'),
('BernoulliNB', BernoulliNB(), 'Bernoulli Naive Bayes'),
('DummyClassifier', DummyClassifier(), 'Dummy Classifier')]
clf_values = []
for clf_na in classifiers_name_all:
clf_values.append((locals()['score_'+clf_na[0]+'_mean'], locals()['score_'+clf_na[0]+'_stddev']))
clf_values
The code above doesn't quite work.
I want to get a list which contains the variables:
clf_values = [(score_AdaBoostClassifier_mean, score_AdaBoostClassifier_stddev),
(score_BernoulliNB_mean, score_BernoulliNB_stddev)
(score_DummyClassifier_mean, score_DummyClassifier_stddev)]
How do I do this? Many thanks.
From whatever info you have given so far, I infer that there are no key errors and the resultant list is a list containing nones.
This can only mean, that your code works fine but the variables u are trying to access have 'None' values assigned to them. Check why your values are having None values and once that is fixed, this list will get desired values.

Variable indexed by an indexed Set with Pyomo

im trying to figure out how to index a variable with an indexed Set:
For example:
model = AbstractModel()
model.J = Set()
model.O = Set(model.J)
I want to define a variable indexed over both Sets. Can Someone help me? I tried the following:
model.eb=Param(model.J, model.O)
which gives
TypeError("Cannot index a component with an indexed set")
Has anyone any suggestions on how to define this variable properly?
Pyomo doesn't support indexed Sets like that (I'm actually unaware of use cases for indexed sets in Pyomo, although they seem to be a thing in GAMS). You could approach this as follows (using ConcreteModel here, for illustration):
Define Sets for all unique values of jobs and operations (I assume you have some data structure which maps the operations to the jobs):
import pyomo.environ as po
import itertools
model = po.ConcreteModel()
map_J_O = {'J1': ['O11', 'O12'],
'J2': ['O21']}
unique_J = map_J_O.keys()
model.J = po.Set(initialize=unique_J)
unique_O = set(itertools.chain.from_iterable(map_J_O.values()))
model.O = po.Set(initialize=unique_O)
Then you could define a combined Set which contains all valid combinations of J and O:
model.J_O = po.Set(within=model.J * model.O,
initialize=[(j, o) for j in map_J_O for o in map_J_O[j]])
model.J_O.display()
# Output:
#J_O : Dim=0, Dimen=2, Size=3, Domain=J_O_domain, Ordered=False, Bounds=None
# [('J1', 'O11'), ('J1', 'O12'), ('J2', 'O21')]
Create the parameter using the combined Set:
model.eb = po.Param(model.J_O)
This last line will throw an error the parameter is initialized using any non-valid combination of J and O. Alternatively, you can also initialize the parameter for all combinations
po.Param(model.J * model.O)
and only initialize for the valid combinations, but this might bite you later. Also, model.J_O might be handy also for variables and constraints, depending on your model formulation.

Store histograms in a large array depending on location in for loop

I'm trying to store histograms in an array full of nested arrays that are created in multiple for a loop.
The error that I am getting is that: 'TH1F' object has no attribute 'append'
Here's an example of how the code works (a simplified version):
hist = []
for c in range 2:
hist.append([])
for e in range 4:
hist[c].append([])
hist_m = ROOT.TH1F("some name","some name",0,0.0,50.0)
hist[c][e].append(hist_m)
for z in range 8:
hist[c][e].append([])
hist_m = ROOT.TH1F("some name","some name",0,0.0,50.0)
hist[c][e][z].append(hist_m) #crashes here
for pT in range 32:
hist[c][e][z].append([])
hist_m = ROOT.TH1F("some name","some name",0,0.0,50.0)
hist[c][e][z][pT].append(hist_m)
I'm trying to store all of these different histograms inside of this large array so that I can use them later in the code by simply using the index. But I am getting the error
'TH1F' object has no attribute 'append'
which I don't know how to fix. Any solutions?
The code crashes on this line:
hist[c][e][z].append( hist )
Thanks in advance!
Here, and in other places, you're overwriting your hist variable that otherwise points to the large "array" you're building:
hist = ROOT.TH1F("some name","some name",0,0.0,50.0)
Use a different name ...
EDIT: since you now changed the naming, consider that you first add a TH1F:
hist[c][e].append(hist_m)
and afterwards a fresh list:
hist[c][e].append([])
so now the first element of list hist[c][e] is a TH1F, the second is a new list. Ie., you have:
[[[<ROOT.TH1F object ("some name") at 0x556fd65038d0>, []]]]
and zero indexing (c == e == z == 0) selects that TH1F.
The data structure as you seem to envision (an indexing being both a histogram if no further indexing happens, but a list if it does), isn't going to work. (Granted, you can add a __getitem__ method to the TH1F class to return a list, but that'd be a rather odd thing to do.)
If you want to have a large, indexable, "array" of histograms, those histograms will all have to be on the final leaf nodes.

test for node membership in pydot graph

pydot has a huge number of bound methods for getting and setting every little thing in a dot graph, reading and writing, you-name-it, but I can't seem to find a simple membership test.
>>> d = pydot.Dot()
>>> n = pydot.Node('foobar')
>>> d.add_node(n)
>>> n in d.get_nodes()
False
is just one of many things that didn't work. It appears that nodes, once added to a graph, acquire a new identity
>>> d.get_nodes()[0]
<pydot.Node object at 0x171d6b0>
>>> n
<pydot.Node object at 0x1534650>
Can anyone suggest a way to create a node and test to see if it's in a graph before adding it so you could do something like this:
d = pydot.Dot()
n = pydot.Node('foobar')
if n not in d:
d.add_node(n)
Looking through the source code, http://code.google.com/p/pydot/source/browse/trunk/pydot.py, it seems that node names are unique values, used as the keys to locate the nodes within a graph's node dictionary (though, interestingly, rather than return an error for an existing node, it simply adds the attributes of the new node to those of the existing one).
So unless you want to add an implementation of __contains__() to one of the classes in the pydot.py file that does the following, you can just do the following in your code:
if n.get_name() not in d.obj_dict['nodes'].keys():
d.add_node(n)

Categories

Resources