Parameter hint assignment through a function in LMFIT - python

I want to set the parameter hints for models held in a dictionary. I have created a function which is called for setting the hints. First, a primary model is created and then I want to create different models, identical to the primary, but with different prefixes. The set_hints function accepts a parameter comp which defined what hints will be set. This is a simplified part of my code:
import lmfit
def foo (x, a):
return x + a
def set_hints(mod, comp="2"):
mod.set_param_hint("a", value=1, vary=True)
if comp == "2":
mod.set_param_hint("a", value=0, vary=False)
return mod.param_hints
m = lmfit.Model(foo)
models = {}
for i in range(2):
hints = set_hints(m, comp="2")
models["m%i" % i] = lmfit.Model(m.func, m.independent_vars,
prefix="m%i" %i,
param_names=m.param_names)
for par in m.param_names:
models["m%i" % i].param_hints[par] = hints[par]
# models["m%i" % i].param_hints = hints
for key in models.keys():
print key
print "value:"
print models[key].param_hints["a"]["value"]
print "vary:"
print models[key].param_hints["a"]["vary"]
which outputs:
m0
value:
1
vary:
True
m1
value:
0
vary:
False
Which doesn't make any sense to me! The value and vary hints should be 0 and False respectively in both cases. It is like at the second iteration of the loop, the condition comp == "2" of the set_hints function is not satisfied for the 1st iteration of the loop and the hints are changed retroactively! If I uncomment the commented line and not set the hints iteratively, the result is good. But what is happening now I find it completely absurd. Please help me understand what is happening!

The code seems very weird, but I assume it comes from a larger design. I think this must be a bug, though I'm not certain what that is. I will create an Issue on the lmfit github site.

Related

Multiply method for a binary list

I am passing parameters x and y to this multIter class in the console as follows:
import BigInteger as bi
x =bi.BigInteger([1,0,1,1])
y= bi.BigInteger([1,0,0,1])
bi.BigInteger.multIter(x,y)
I am currently getting the wrong answers when I call this method. There is some logical error in the line answer = self.add(x), that I am not able to figure out.
def multIter(self,y):
a_bits = self._bits
b_bits = y._bits
answer = 0
for i in range(0,len(b_bits)):
if(b_bits[i] == 1):
x= self.multByPow2(i)
answer = self.add(x)
return answer
There is indeed a logical error at the statement you indicate. In each iteration that has a 1-bit, that answer = self.add(x) assignment ignores the previous value of answer, and just overwrites it. You should not add x to self, but add x to answer. For that to work, answer must be initialised as an instance of BigInteger, and not as 0.
So replace that part of the code with:
answer = bi.BigInteger([0])
for i in range(0,len(b_bits)):
if b_bits[i] == 1:
x = self.multByPow2(i)
answer = answer.add(x)
This will work fine assuming the other used methods of BigInteger have been correctly implemented.

How do I access the parameters of the function one by one?

So, I'm still learning how to code and I'm making this higher or lower game, and I made a function that pulls out info from a huge list with dictionaries inside it called "data":
Here is my code so far:
def choice_of_oponents(opponent1, opponent2):
"""
Gets the info on 2 people randomly and assigns them to the variables 'opponent1' and 'opponent2'
"""
opponent1 = random.choice(data)
opponent2 = random.choice(data)
def winner(opponent1, opponent2):
#This function is supposed to pull out the info stored in the parameters in the first function and determine the winner based on the data
I'm not sure how to write the second function or if it is even possible to pull out info from the parameters of the 1st function without making extra variables. Can someone help solve this?
Maybe what you're missing is the concept of return-ing the output of a function. Also, you don't need any inputs to your first function (note that you didn't use them anyway).
Try something like this:
def choice_of_opponents():
"""
Gets the info on 2 people randomly and assigns them to the variables
'opponent1' and 'opponent2'
"""
opponent1_result = random.choice(data)
opponent2_result = random.choice(data)
return opponent1_result, opponent2_result
def winner(opponent1, opponent2):
if opponent1 > opponent2:
return 1
elif opponent2 > opponent1:
return 2
else:
return 0 # A tie
op1, op2 = choice_of_opponents()
print(winner(op1, op2))

Python TypeError: 'function' object is not subscriptable in nested function when i try to implement switch case

I am trying to code a random decision between 3 machines.
Since Python does not have any switch/case function, I resorted to if and elif.
Each machine (line1(),line2(),line3()) has its own function as well.
However, I have been getting errors.
Please advise me on what is going wrong.
machine_choice = [1,2,3]
selected_machine = random.choice(machine_choice)
print(selected_machine)
def machines(selected_machine):
if selected_machine == 1:
print("machine 1 randomly selected")
line1()
elif selected_machine == 2:
print("machine 2 randomly selected")
line2()
else:
print("machine 3 randomly selected")
line3()
machines(selected_machine)
def line1():
if machine1["hardness"] < rev[i][1]["condition"]:
print("\tMachine 1 hardness breached, will take 30mins for changing the system")
machine1["hardness"] = 10
time = line1
machine1["schedule"].append([d,"machine 1",time,"change",30.,time.add(minutes=30)])
print("\tno activities from {} to {}".format(time,time.add(minutes=30)))
time = time.add(minutes=30)
print("\tdone changing at time: ",time)
print("\tcurrent log: ",machine1["schedule"],"\n")
d+=1
line1=time
#line1 = max(time,line1,line2)
machine1["schedule"].append([d,"machine 1",line1,"feeding",5.,line1.add(minutes=5)])
line1 = line1.add(minutes=5)
d+=1
machine1["schedule"].append([d,"machine 1",line1,rev[i][0],rev[i][1]["duration"],line1.add(minutes=rev[i][1]["duration"])])
line1 = line1.add(minutes=rev[i][1]["duration"])
time = time.add(minutes=5)
d+=1
if rev[i][1]["quantity"] == 0:
i += 1
I am trying to code a random decision between 3 machines.
In Python, functions are nothing special, you can use them just like any other object.
def machine_one():
return 'Machine One'
def machine_two():
return 'Machine Two'
def machine_three():
return 'Machine Three'
machines = [machine_one, machine_two, machine_three]
print(random.choice(machines)())
The message means that you try to access to some python object defined as a function as if it were an array. The most likely candidate looking as the code you provided is machine_choice.
But please provide a working minimal example, which in that case means including import of necessary modules (random) and lines function.
Regarding the purpose of the code (faking a switch) the cascaded if solution is usually not a very good solution. Using random.choice with an array or a dictionnary or an array with random number as key or index would be much more pythonic.
Also using switch is a common code smell in OO programming and is often best replaced using object polymorphism and a factory.
You may have a look at python switch replacement for details.

Checking that array doesn't contain negative numbers, and running function again if it does

My task today is to create a way for checking if a function's output contains negative numbers, and if it does, then I must run the function until it contains no negative numbers.
I'll post the full code later in the post, but this is my attempt at a solution:
def evecs(matrixTranspose):
evectors = numpy.linalg.eig(matrixTranspose)[1][:,0]
return evectors
if any(x<0 for x in evectors) == False:
print(evectors)
evecs() is my function, and evectors is the output array, but I only want to print evectors if there are no negative entries in it. I also want to later add that if there are negative entries in it, the code should run the evecs function again until it finds an evectors that has no negative entries.
However, whenever I run it I get the error:
global name evectors is not defined
Here's a link to my code, and the full output from the iPython console. http://pastebin.com/3Bk9h1gq
Thanks!
You have not declared the variable evectors other than within the scope of your function evecs.
evectors = evecs(matrixTranspose)
if any(x<0 for x in evectors) == False:
print(evectors)
EDIT
There are several issues:
Indentation is VERY important in Python. MarkovChain and evecs are two seperate functions. You had your evacs function indented an extra level in, embeddeding it within MarkovChain.
MarkovChain should return matrixTransponse if you plan to use it in another function call.
As a result of the above issue, your function call to MarkovChain needs to be assigned to a variable, matrixTranponse, otherwise you will get an error stating that matrixTranspose is not defined when you make your function call to evecs with it.
Since the initialization of the variable matrixTranspose isn't set until the function call to MarkovChain is completed, the remainder of your logic will need to be re-ordered.
I have applied all the above changes below and added comments to the changed areas:
def MarkovChain(n,s) :
"""
"""
matrix = []
for l in range(n) :
lineLst = []
sum = 0
crtPrec = precision
for i in range(n-1) :
val = random.randrange(crtPrec)
sum += val
lineLst.append(float(val)/precision)
crtPrec -= val
lineLst.append(float(precision - sum)/precision)
matrix2 = matrix.append(lineLst)
print("The intial probability matrix.")
print(tabulate(matrix))
matrix_n = numpy.linalg.matrix_power(matrix, s)
print("The final probability matrix.")
print(tabulate(matrix_n))
matrixTranspose = zip(*matrix_n)
return matrixTransponse # issue 2
# issue 1
def evecs(matrixTranspose):
evectors = numpy.linalg.eig(matrixTranspose)[1][:,0]
return evectors
matrixTranponse = MarkovChain(4, 10000000000) # issue 3
# issue 4
evectors = evecs(matrixTranspose)
if any(x<0 for x in evectors) == False:
print(evectors)

Matching Binary operators in Tuples to Dictionary Items

So, I'm working on a Pybrain-type project and I'm stuck on part of it.
So far the program takes in a tuple and assigns a variable to it using 'one of them fancy vars()['string'] statements. Specifically, it takes in a tuple of numbers and assigns it to a 'layerx' value, where x is the number of the layer (in order, layer 1, 2, 3, etc), such that the numbers are the dimensions of that layer.
The part of the program I desperately and humbly come to you for help in is what should be the next step in the program; it takes in a tuple of tuples (the number of tuples must = the number of layers), and the tuples contain 1/0's.
It is supposed to determine what type of Pybrain Layer to use in what layer, and then plugs in that layer's dimension value and, essentially, creates that layer-variable. I've...played with it for a while, and I've gotten a really...twisted...confusing block of code.
Please pardon the convoluted variable names, I thought I was being smart by making them somewhat specific:
moduleconbuff = 0
modulebuffer = 'module'
correspondinglayerbuff = 0
moduleconfigcopy = tuple(moduleconfig)
try: #Always triggers except, but it's pretty screwed up
while correspondinglayerbuff <= len(self.layers): #keeps track of how many layer/module pairs have been assigned
for elm in moduleconfigcopy:
for x in elm:
if x == 1:
moduledimmension = [layerbuff+'%s'%(correspondinglayerbuff)]
modulesdict = {1: pybrain.GaussianLayer(moduledimmension), 2: pybrain.LinearLayer(moduledimmension),\
3: pybrain.LSTMLayer(moduledimmension),4: pybrain.SigmoidLayer(moduledimmension),5: pybrain.TanhLayer(moduledimmension)} #this dict pairs integers with pybrain modules
vars()[modulebuffer +'%s'%(correspondinglayerbuff)]=modulesdict(moduleconbuff) #should return something like 'Module1 = pybrain.GaussianLayer(5) when complete
print vars()[modulebuffer+'%s'%(correspondinglayerbuff)]
moduleconbuff=0
correspondinglayerbuff+=1
print 'Valid: ', moduleconfigcopy, elm
continue
else:
elm = elm[1:]
print 'Invalid: ', moduleconfigcopy, elm
moduleconbuff+=1
except:
print 'Invalid!!!'
I honestly lost track of what was going on in it. The tuple "moduleconfig" in the beginning
was supposed to be a tuple of tuples (nested tuples) with binary operators, it was supposed to stop when one of the tuples has a 1, match that operator with the right module in Pybrain, and then plug this in so the corresponding layer = that module with the dimmensions already listed.
Obviously something went terribly wrong, and it's so fargone that my brain can't make any sense of it...it's lost all it's reason and every time I look at it I get scared...please help me or tell me I created an abomination or something, I guess...
One huge hindrance that's affecting code readability for you is variable naming and style. I've tried to clean it up a little bit for you. It still might not work, but now it's a LOT easier to see what's going on. Please refer to PEP 8, the Python style guide
For starters, I renamed some variables, below. Note that in python, variables should be all lowercase, with separate words connected by an underscore. Constants should be ALL_UPPERCASE:
assigned_layers = correspondinglayerbuff = 0
tuple_of_tuples = moduleconfigcopy = ((0, 1), (0, 0, 1), (0, 1))
dimension = moduledimension
MOD_BUFFER = modulebuffer = 'buffer'
c_buff = moduleconbuff = 0
And here is the while loop (with variable names replaced, and properly indented, with the try... except block removed:
while assigned_layers <= len(self.layers):
for element_tuple in tuple_of_tuples:
for item in element_tuple:
if item: # in python, 0 is treated as boolean False, 1 or any other value is treated as boolean True.
dimension = [layerbuff + str(assigned_layers)] #what is layerbuff?
modules_dict = {
1: pybrain.GaussianLayer(dimension),
2: pybrain.LinearLayer(dimension),
3: pybrain.LSTMLayer(dimension),
4: pybrain.SigmoidLayer(dimension),
5: pybrain.TanhLayer(dimension)
} # Notice how this dict is much easier to read.
vars()[MOD_BUFFER + str(assigned_layers)] = modules_dict[c_buff] #modules_dict is a dict and not a callable object
c_buff = 0
assigned_layers +=1
#No need for continue here, since that's what the if...else does here.
else:
element_tuple = element_tuple[1:] #what is this for?
print 'Invalid: ', tuple_of_tuples, element_tuple
I'm not sure exactly what you are trying to do in this line:
vars()[MOD_BUFFER + str(assigned_layers)] = modules_dict[c_buff] #modules_dict is a dict and not a callable object
Also, you originally had modules_dict(moduleconbuff) which will raise a TypeError as a dict is not a callable object. I'm assuming you meant to retrieve a value by key.
As I said, I'm not quite sure what your trying to do here (probably because I haven't seen the rest of your code), but renaming your variables and using good style should go a long way towards you being able to debug your code. I will continue to edit if you answer my questions/comment.

Categories