inner function changing the variable value of outer function - python-3.x

def swap(i,r,c,mat):
for j in range(i+1,c):
if(abs(mat[j][j])>0):
mat[[j,i]] = mat[[i,j]]
break
return mat
def upper_triMat(matA,r,c):
np.set_printoptions(precision=4)
# forward elimination
for i in range(0,c-1):
if matA[i][i] == 0:
matA = swap(i,r,c,matA)
for j in range(i+1,r):
multiplier = matA[j][i]/matA[i][i]
for k in range(0,c):
matA[j][k] = matA[j][k] - multiplier*matA[i][k]
return matA
def dolittle(A):
A = np.array(A)
r,c = np.shape(A)
print(A)
U = upper_triMat(A,r,c) # Here the value of A is changed U.
print(A)
l = np.eye(r,c)
for i in range(0,r-1):
for j in range(i+1,r):
sum = 0
for k in range(0,r):
if i != k:
sum = sum + U[k][i]*l[j][k]
l[j][i] = (A[j][i]-sum)/U[i][i]
return l,U
A = [[3,-0.1,-0.2],
[0.1,7,-0.3],
[0.3,-0.2,10]]
dolittle(A)
When i call the upper_triMat function "A" changes in dolittle function. Why?? A is A and the upper_triMat function assigning it to U. But A is also getting the value of U. Using Jupyter Notebook. I am doing LU decomposition

upper_triMat mutates its parameter matA. And since matA is a reference to A, it's being modified.
Maybe you could fix it that way
U = upper_triMat(A.copy(),r,c) # pass a copy of the list instead of the reference of the original one.

Related

OR-TOOLS - how to solve ordered allocation problem?

I have 'n' tables and I have 'm' boxes.
The job is to stack all the boxes on tables.
Question:
what are the different possible combinations?
important note: all the boxes are ordered when put on a table, like stacks. I need to know the rank of each box in the stack.
how to implement that problem with ORTOOL constraint programming / SAT?
what is the best strategy? what variables / constraints?
(I dont expect code, but just advices... unless you are a fast developer :)
Thanks
from ortools.sat.python import cp_model
class VarArraySolutionPrinter(cp_model.CpSolverSolutionCallback):
def __init__(self, variables):
cp_model.CpSolverSolutionCallback.__init__(self)
self.__variables = variables
self.__solution_count = 0
def on_solution_callback(self):
self.__solution_count += 1
for v in self.__variables:
print('%s=%i' % (v, self.Value(v)))
print("")
def solution_count(self):
return self.__solution_count
def main():
variables = []
model = cp_model.CpModel()
#################################################
nb_tables = 3
nb_boxes = 4
for box in range(nb_boxes):
box_to_table = model.NewIntVar(0, nb_tables - 1, 'box_'+str(box)+'_to_table')
variables.append(box_to_table)
ranking_variables = []
for box in range(nb_boxes):
rank_of_box_on_its_table = model.NewIntVar(0, nb_boxes - 1, 'rank_of_box_'+str(box)+'_on_its_table')
variables.append(rank_of_box_on_its_table)
ranking_variables.append(rank_of_box_on_its_table)
# the next line is not good because the ranking is global
# and not local to each table. how to manage that?
model.AddAllDifferent(ranking_variables)
#################################################
solver = cp_model.CpSolver()
solution_printer = VarArraySolutionPrinter(variables)
status = solver.SearchForAllSolutions(model, solution_printer)
print('Status = %s' % solver.StatusName(status))
print('Number of solutions found: %i' % solution_printer.solution_count())
main()
And with the boolean version:
#################################################
nb_tables = 3
nb_boxes = 4
for box in range(nb_boxes):
this_box_vars = []
for table in range(nb_tables):
box_in_table = model.NewBoolVar('box_'+str(box)+'_in_table_' + str(table))
variables.append(box_in_table)
this_box_vars.append(box_in_table)
model.Add(sum(this_box_vars) == 1)
ranking_variables = []
for box in range(nb_boxes):
rank_of_box_on_its_table = model.NewIntVar(0, nb_boxes - 1, 'rank_of_box_'+str(box)+'_on_its_table')
variables.append(rank_of_box_on_its_table)
ranking_variables.append(rank_of_box_on_its_table)
# the next line is not good because the ranking is global
# and not local to each table. how to manage that?
model.AddAllDifferent(ranking_variables)
#################################################
Don't use integer variables.
Rule of the thumb:
if you see an AllDifferent constraint, remove it, and replace the integer variable by a list of Boolean variables.
Add Sum(bool_vars) == 1
x[i][j][k] is a Boolean variable indicating that box i is on table j at position k.
y[j][k] indicates if a box in on table j at position k.
each box appears exactly once:
forall i: Sum on j, k box[i][j][k] == 1
each position is occupied by at most one box:
forall j, k: sum on i box[i][k][k] <= 1
if a box is somewhere, it means this somewhere is occupied:
forall i, j, k: box[i][j][k] implies y[j][k]
if a position is occupied, there must be a box at this position:
forall j, k: bool_or([y[j][k].Not(), box[0][j][k], .., box[n - 1][j][k]])
positions must be densely occupied starting from 0 on a table:
forall j, k (except last position): y[j][k].Not() implies y[j][k + 1].Not()
If you want the rank of a box
forall i: rank[i] == sum over j, k box[i][j][k] * k

Python how to calculate average of range list?

Could somebody tell me what I am doing wrong?
I am gotting error Vidurkis = sum(B)/len(B)
TypeError: 'int' object is not callable
A = int(input('Betkoks skaicius'))
if A == 0:
print('Ačiū')
if A <= 10 and A>=-10:
if A<0:
print('Neigiamas vienženklis')
if A>0:
print('Teigiamas vienženklis')
else:
print('| {:^20} |'.format('Autorius: '))
for r in range(10,A,1):
Vidurkis = sum(r)/len(r)
print(Vidurkis)
after
sum = 0
sum is no longer the built-in sum function! You would have to rename that variable. The real error is, however, that you are applying functions that take iterables as arguments to integers (Your loop variable B is an int while sum and len would expect a list or similar). The following would suffice:
r = range(10, A, 1) # == range(10, A)
Vidurkis = sum(r)/len(r) # only works for A > 10, otherwise ZeroDivisionError

Function call changing its argument python

I am trying to reduce a matrix to its echlon form using a function but upon the calling the function, it is also changing its arguments. Here is the code
def GaussE(E,r):
N = np.size(r)
for i in range(0,N-1):
for j in range(i+1,N):
f=(E[j,i]/E[i,i])
r[j]= r[j] -(f)*r[i]
for k in range(i,N):
E[j,k] = E[j,k]-(f*E[i,k])
return(E,r)
A = np.array([[5.10,8.70],[2.40,4.10]])
b = np.array([9.48,4.48])
print(A,b)
output: [[ 5.1 8.7] [ 2.4 4.1]] [ 9.48 4.48]
X = GaussE(A[:],b[:])
print(A,b) # Why is A and b changing? they should not change
output:[[ 5.10000000e+00 8.70000000e+00]
[ 0.00000000e+00 5.88235294e-03]] [ 9.48 0.01882353]
In python every variable refers to an object. It refers to the object pointer so it is using the object itself.
In that function you are referencing E like E[j,k] and r like r[j] and assigning to it which means you are using that same object and means you are manipulating it.
Try to use copy at the first of your function (from copy import copy)
from copy import copy
def GaussE(E,r):
E = copy(E)
r = copy(r)
N = np.size(r)
for i in range(0,N-1):
for j in range(i+1,N):
f=(E[j,i]/E[i,i])
r[j]= r[j] -(f)*r[i]
for k in range(i,N):
E[j,k] = E[j,k]-(f*E[i,k])
return(E,r)
A = np.array([[5.10,8.70],[2.40,4.10]])
b = np.array([9.48,4.48])
print(A,b)

Function's input appear to be a list

I have a nested list and a header which is the column name.
I want to find maximum in column and print out the maximum's row information.
Here's my code.
def find_col(v):
for i in range(1,31):
if header[i]==v:
return i
def col_list(col):
list = []
for row in linelist:
list.append(row[int(col)])
return list
def M(col):
def max(li):
inf = -float('inf')
maxnumber = inf
for i, value in enumerate(li):
if value>maxnumber:
maxnumber = value
return maxnumber
return max(col_list(col))
def max_row(col):
li = col_list(col)
m = M(col)
for i, j in enumerate(li):
if j == m:
return i
def col_max(name):
col = find_col(name)
return M(col)
def pri(name):
column = find_col(name)
maxima = M(column)
li = col_list(column)
maxrow = max_row(li)
print(linelist[maxrow][1], linelist[maxrow][4], maxima)
pri('MP')
The problem is at function col_list, but I can't figure out how 'col' appear to be a list.
The problem seams to be that in the function pri(name) you call max_row in the statement maxrow = max_row(li) where li is what col_list returns (a list...) so you call max_row(<somelist>). However, max_row then goes ahead and calls col_list with its input parameter (so a list, since it was passed a list...) that's where things go wrong.
How to fix it depends on what exactly you want to do. If I understand your intentions correctly something like:
li = []
for row in <imputParameter>: ## in your case its called col, but its a list...
li.append(max(row)) ## or some other way to compute the value you want from that...
##continue function as in your case...
hope that helps.

power (a, n) in PYTHON

POwer in Python. How to write code to display a ^ n using funсtion?
why doesn't this code working?
a = int(input())
n = int(input())
def power(a, n):
for i in range (n):
a=1
a *= n
print(power (a, n))
Few errors:
Changing a will lose your power parameter, use result (or something else).
Move setting result = 1 outside your loop to do so once.
Multiply by a not by n.
Use return to return a value from the function
def power(a, n):
result = 1 # 1 + 2
for _ in range (n):
result *= a # 3
return result # 4
Style notes:
Setting/mutating a parameter is considered bad practice (unless explicitly needed), even if it is immutable as is here.
If you're not going to use the loop variable, you can let the reader know by using the conventional _ to indicate it (_ is a legal variable name, but it is conventional to use it when not needing the variable).
Tip: you can simple use a**n
It doesn't work because your function doesn't return the end value. Add return a to the end of the function.
ALSO:
That is not how a to the power of n is is calculated.
A proper solution:
def power(a,n):
pow_a = a
if n is 0:
return 1
for _ in range(n-1): # Substracting 1 from the input variable n
pow_a *= a # because n==2 means a*a already.
return pow_a
and if you want to be really cool, recursion is the way:
def power_recursive(a,n):
if n is 0:
return 1
elif n is 1:
return a
else:
a *= power_recursive(a,n-1)
return a

Resources