Clustering of sites using OR tools (CP solver) - python-3.x

I am trying to make clusters of sites based on their distance from each other. I am using or tools cp solver to achieve this. The program runs fine for 40 to 50 number of sites but when i try to run for about 200 sites with each cluster containing 10 sites the program gets stuck and does not give any output. I am using the cp_model for this.
Please below the code I am using :
from ortools.sat.python import cp_model
import pandas as pd,sys,os,requests,re
matrix_data = pd.read_csv(''.join([filepath,'//matrix.csv']),
matrix = matrix_data.values.tolist()
#data = {}
#data['distance_matrix'] = []
distance_matrix = []
for i in matrix:
distance_matrix.append(i)
def main():
"""Entry point of the program."""
num_nodes = len(distance_matrix)
print('Num nodes =', num_nodes)
# Number of groups to split the nodes, must divide num_nodes.
num_groups = 10
# Model.
model = cp_model.CpModel()
# Variables.
neighbors = {}
obj_vars = []
obj_coeffs = []
for n1 in range(num_nodes - 1):
for n2 in range(n1 + 1, num_nodes):
same = model.NewBoolVar('neighbors_%i_%i' % (n1, n2))
neighbors[n1, n2] = same
obj_vars.append(same)
obj_coeffs.append(distance_matrix[n1][n2] + distance_matrix[n2][n1])
# Number of neighborss:
for n in range(num_nodes):
model.Add(sum(neighbors[m, n] for m in range(n)) +
sum(neighbors[n, m] for m in range(n + 1, num_nodes)) ==
group_size - 1)
# Enforce transivity on all triplets.
for n1 in range(num_nodes - 2):
for n2 in range(n1 + 1, num_nodes - 1):
for n3 in range(n2 + 1, num_nodes):
model.Add(
neighbors[n1, n3] + neighbors[n2, n3] + neighbors[n1, n2] != 2)
# Redundant constraints on total sum of neighborss.
model.Add(sum(obj_vars) == num_groups * group_size * (group_size - 1) // 2)
# Minimize weighted sum of arcs.
model.Minimize(
sum(obj_vars[i] * obj_coeffs[i] for i in range(len(obj_vars))))
# Solve and print out the solution.
solver = cp_model.CpSolver()
solver.parameters.log_search_progress = True
solver.parameters.num_search_workers = 6
status = solver.Solve(model)
print(solver.ResponseStats())
visited = set()
for g in range(num_groups):
flonglist = []
flatlist = []
for n in range(num_nodes):
if not n in visited:
visited.add(n)
output = str(n)
for o in range(n + 1, num_nodes):
if solver.BooleanValue(neighbors[n, o]):
visited.add(o)
output += ' ' + str(o)
print('Group', g, ':', output)
print(site_list)
break
if __name__ == '__main__':
main()
print("-- %s seconds ---" % (time.time() - start_time))
The matrix file contain the distance of sites from each other in matrix format.
need some help.

Related

'>=' not supported between instances of 'list' and 'float' for numpy where

I am new to coding and I'm working on my college project on which I need to make a bio-inspired algorithm teacher learning-based Algorithm, but here is some error is coming
here is my tlbo code
class Student:
def __init__(self, fitness, dim, minx, maxx, seed):
self.rnd = random.Random(seed)
# a list of size dim
# with 0.0 as value of all the elements
self.position = [0.0 for i in range(dim)]
# loop dim times and randomly select value of decision var
# value should be in between minx and maxx
for i in range(dim):
self.position[i] = ((maxx - minx) *
self.rnd.random() + minx)
# compute the fitness of student
self.fitness = fitness(self.position)
def tlbo(fitness, max_iter, n, dim, minx, maxx):
rnd = random.Random(0)
# create n random students
classroom = [Student(fitness, dim, minx, maxx, i) for i in range(n)]
# compute the value of best_position and best_fitness in the classroom
Xbest = [0.0 for i in range(dim)]
Fbest = sys.float_info.max
for i in range(n): # check each Student
if classroom[i].fitness < Fbest:
Fbest = classroom[i].fitness
Xbest = copy.copy(classroom[i].position)
# convergence graph
convergence1 = []
timerStart = time.time()
# main loop of tlbo
Iter = 0
while Iter < max_iter:
# after every 10 iterations
# print iteration number and best fitness value so far
if Iter % 10 == 0 and Iter > 1:
print("Iter = " + str(Iter) + " best fitness = %.3f" % Fbest)
if Iter % 1 ==0 :
convergence1.append(Fbest)
# for each student of classroom
for i in range(n):
### Teaching phase of ith student
# compute the mean of all the students in the class
Xmean = [0.0 for i in range(dim)]
for k in range(n):
for j in range(dim):
Xmean[j] += classroom[k].position[j]
for j in range(dim):
Xmean[j] /= n;
# initialize new solution
Xnew = [0.0 for i in range(dim)]
# teaching factor (TF)
# either 1 or 2 ( randomly chosen)
TF = random.randint(1, 3)
# best student of the class is teacher
Xteacher = Xbest
# compute new solution
for j in range(dim):
Xnew[j] = classroom[i].position[j] + rnd.random() * (Xteacher[j] - TF * Xmean[j])
# if Xnew < minx OR Xnew > maxx
# then clip it
for j in range(dim):
Xnew[j] = max(Xnew[j], minx)
Xnew[j] = min(Xnew[j], maxx)
# compute fitness of new solution
fnew = fitness(Xnew)
# if new solution is better than old
# replace old with new solution
if (fnew < classroom[i].fitness):
classroom[i].position = Xnew
classroom[i].fitness = fnew
# update best student
if (fnew < Fbest):
Fbest = fnew
Xbest = Xnew
### learning phase of ith student
# randomly choose a solution from classroom
# chosen solution should not be ith student
p = random.randint(0, n - 1)
while (p == i):
p = random.randint(0, n - 1)
# partner solution
Xpartner = classroom[p]
Xnew = [0.0 for i in range(dim)]
if (classroom[i].fitness < Xpartner.fitness):
for j in range(dim):
Xnew[j] = classroom[i].position[j] + rnd.random() * (
classroom[i].position[j] - Xpartner.position[j])
else:
for j in range(dim):
Xnew[j] = classroom[i].position[j] - rnd.random() * (
classroom[i].position[j] - Xpartner.position[j])
# if Xnew < minx OR Xnew > maxx
# then clip it
for j in range(dim):
Xnew[j] = max(Xnew[j], minx)
Xnew[j] = min(Xnew[j], maxx)
# compute fitness of new solution
fnew = fitness(Xnew)
# if new solution is better than old
# replace old with new solution
if (fnew < classroom[i].fitness):
classroom[i].position = Xnew
classroom[i].fitness = fnew
# update best student
if (fnew < Fbest):
Fbest = fnew
Xbest = Xnew
Iter += 1
# end-while
timerEnd = time.time()
print(timerEnd-timerStart)
y = np.array(convergence1, dtype=np.longdouble)
x = np.arange(0, max_iter, dtype=int) + 1
print(x)
print(y)
timerEnd = time.time()
print('Completed in', (timerEnd - timerStart))
fire = round((timerEnd - timerStart), 2)
plt.plot(x, y, 'o-')
plt.xlabel("Iterations")
plt.ylabel("Fitness")
plt.title(
f"Convergence_curve for CSO for parameter including population "
f"{n}, \niteration {max_iter},and max fitness is:{round(min(convergence1), 3)}")
plt.show()
opts = {"p": Xbest, 'c': round(min(convergence1), 3), "ti": fire}
return opts
and here is my fitness function
def fitness_function(positions):
print(positions)
features = np.where(positions >= 0.4999)[0]
# print('selected_features:', features)
# print(train_df.head())
train_xf = train_x.iloc[:, features]
test_xf = test_x.iloc[:, features]
knn_classifier = Pipeline([('s', StandardScaler()), ('t', MinMaxScaler()),
('m', RandomForestClassifier(n_estimators=100, n_jobs=14))])
knn_classifier.fit(train_xf, train_y)
accuracy = knn_classifier.score(test_xf, test_y)
# print('Accuracy:', accuracy)
w = 0.9
return -(w * accuracy + (1 - w) * 1 / (len(features)))
here the main problem which is coming is ,
Traceback (most recent call last):
self.fitness = fitness(self.position)
features = np.where(positions >= 0.4999)[0]
TypeError: '>' not supported between instances of 'list' and 'float'
the main problem is my tlbo code is generating values for the best-fit position [0.456621, -0.616164564] and I need to convert it to [1,2] so that I can run knn and get accuracy result and RUC curve, so what I should do now?
Replace the line with features = np.where(np.array(positions) >= 0.4999)[0]

Simpson's rule 3/8 for n intervals in Python

im trying to write a program that gives the integral approximation of e(x^2) between 0 and 1 based on this integral formula:
Formula
i've done this code so far but it keeps giving the wrong answer (Other methods gives 1.46 as an answer, this one gives 1.006).
I think that maybe there is a problem with the two for cycles that does the Riemman sum, or that there is a problem in the way i've wrote the formula. I also tried to re-write the formula in other ways but i had no success
Any kind of help is appreciated.
import math
import numpy as np
def f(x):
y = np.exp(x**2)
return y
a = float(input("¿Cual es el limite inferior? \n"))
b = float(input("¿Cual es el limite superior? \n"))
n = int(input("¿Cual es el numero de intervalos? "))
x = np.zeros([n+1])
y = np.zeros([n])
z = np.zeros([n])
h = (b-a)/n
print (h)
x[0] = a
x[n] = b
suma1 = 0
suma2 = 0
for i in np.arange(1,n):
x[i] = x[i-1] + h
suma1 = suma1 + f(x[i])
alfa = (x[i]-x[i-1])/3
for i in np.arange(0,n):
y[i] = (x[i-1]+ alfa)
suma2 = suma2 + f(y[i])
z[i] = y[i] + alfa
int3 = ((b-a)/(8*n)) * (f(x[0])+f(x[n]) + (3*(suma2+f(z[i]))) + (2*(suma1)))
print (int3)
I'm not a math major but I remember helping a friend with this rule for something about waterplane area for ships.
Here's an implementation based on Wikipedia's description of the Simpson's 3/8 rule:
# The input parameters
a, b, n = 0, 1, 10
# Divide the interval into 3*n sub-intervals
# and hence 3*n+1 endpoints
x = np.linspace(a,b,3*n+1)
y = f(x)
# The weight for each points
w = [1,3,3,1]
result = 0
for i in range(0, 3*n, 3):
# Calculate the area, 4 points at a time
result += (x[i+3] - x[i]) / 8 * (y[i:i+4] * w).sum()
# result = 1.4626525814387632
You can do it using numpy.vectorize (Based on this wikipedia post):
a, b, n = 0, 1, 10**6
h = (b-a) / n
x = np.linspace(0,n,n+1)*h + a
fv = np.vectorize(f)
(
3*h/8 * (
f(x[0]) +
3 * fv(x[np.mod(np.arange(len(x)), 3) != 0]).sum() + #skip every 3rd index
2 * fv(x[::3]).sum() + #get every 3rd index
f(x[-1])
)
)
#Output: 1.462654874404461
If you use numpy's built-in functions (which I think is always possible), performance will improve considerably:
a, b, n = 0, 1, 10**6
x = np.exp(np.square(np.linspace(0,n,n+1)*h + a))
(
3*h/8 * (
x[0] +
3 * x[np.mod(np.arange(len(x)), 3) != 0].sum()+
2 * x[::3].sum() +
x[-1]
)
)
#Output: 1.462654874404461

How to alternate color of the graphs between blue and white?

I have a list D containing 50 sub-lists. The number of elements in these sub-lists are decreasing. I visualize the list D by
for i, array in enumerate(D):
plt.scatter([i]*len(array), array)
I have 50 functions taking values from St_Sp, and Y is a list containing 50 elements, each of them is the output of each function. I visualize these functions
fig, ax = plt.subplots()
for i in range(len(Y)):
ax.plot(St_Sp, Y[i])
I found that too many colors are not easy to eyes. I would like to ask how to alternate color of the graphs between blue and white? I mean the color of the functions and dots in D are white > blue > white > blue ...
Could you please elaborate on how to do so?
##### Import packages
import numpy as np
import scipy.linalg as la
import time
import matplotlib
import matplotlib.pyplot as plt
##### Initial conditions
N = 100
lamda = 7
mu = 2
a = np.exp(-0.05)
r = - np.log(a).copy()
St_Sp = np.arange(- N, N + 1)
Card = St_Sp.shape[0]
##### Define infintesimal generator
def LL(x, y):
if x == N or x == - N: re = 0
elif x - y == - 1: re = lamda
elif x - y == 1: re = mu
elif x - y == 0: re = - (mu + lamda)
else: re = 0
return re
def L(x):
return - LL(x, x)
##### Define function Phi
def Phi(x):
return max(x, 0)
Phi = np.vectorize(Phi)
##### Define vector b
b = np.array(Phi(St_Sp))
##### Define function Psi
def Psi(x):
return L(x) / (L(x) + r)
Psi = np.vectorize(Psi)
##### Generate a Boolean vector whose all elements are False
d = np.array([0] * Card).astype(bool)
##### Define matrix A
A = np.zeros((Card, Card))
for i in range(Card):
for j in range(Card):
if (i != j) & (L(St_Sp[i]) != 0):
A[i, j] = LL(St_Sp[i], St_Sp[j]) / L(St_Sp[i])
elif (i != j) & (L(St_Sp[i]) == 0):
A[i, j] = 0
elif (i == j) & (Psi(St_Sp[i]) != 0):
A[i, j] = - 1 / Psi(St_Sp[i])
else: A[i, j] = 1
##### Row names of A
rows = np.arange(0, Card)
##### Define matrix B
B = np.zeros((Card, Card))
for i in range(Card):
for j in range(Card):
if i != j:
B[i, j] = LL(St_Sp[i], St_Sp[j])
else: B[i, j] = LL(St_Sp[i], St_Sp[j]) - r
start = time.time()
##### Generate I_0
I = [np.array([1] * Card).astype(bool), d.copy()]
Z = np.array(b.copy())
Z = Z.astype(float)
D = [St_Sp]
index0 = np.matmul(B, Z) <= 0
index1 = ~ index0
Y = [b.copy()]
##### Iterations
for i in range(1, Card):
I = [I[0] & index0, I[1] | index1]
Z = np.array(b.copy())
Z = Z.astype(float)
A1 = A[np.ix_(rows[I[1]], rows[I[1]])]
A2 = A[np.ix_(rows[I[1]], rows[I[0]])]
Z[I[1]] = la.solve(A1, - np.matmul(A2, Z[I[0]]))
Y = np.concatenate((Y, [Z]))
D.append(St_Sp[I[0]])
index = np.matmul(B[I[0]], Z) <= 0
index0, index1 = d.copy(), d.copy()
index0[I[0]], index1[I[0]] = index, ~ index
if (I[0] == index0).all() == True: break
for i, array in enumerate(D):
plt.scatter([i]*len(array), array)
fig, ax = plt.subplots()
for i in range(len(Y)):
ax.plot(St_Sp, Y[i])
The easiest approach is to set a custom color cycler. Instead of cycling between the 10 typical colors, the default colors for the plots will cycle through the given colors.
from cycler import cycler
custom_cycler = cycler(color=['white', 'blue'])
plt.gca().set_prop_cycle(custom_cycler)
for i, array in enumerate(D[:-1]):
plt.scatter([i] * len(array), array)
plt.scatter([len(D) - 1] * len(D[-1]), D[-1], color='crimson')
fig, ax = plt.subplots()
ax.set_prop_cycle(custom_cycler)
for i in range(len(Y) - 1):
ax.plot(St_Sp, Y[i])
ax.plot(St_Sp, Y[len(Y) - 1], color='crimson')
plt.show()

How to give x and y labels while plotting a graph in python using networkx module?

How to plot a graph with x and y labels in networkx ?
def particles_visualization(self,neighbour_listx,particles):
G=nx.Graph()
print(particles)
print(neighbour_listx)
for i in range(len(particles)):
G.add_node(particles[i][0], pos=(particles[i][1], particles[i[2]))
for i in range(len(neighbour_listx)):
G.add_edge(neighbour_listx[i][0], neighbour_listx[i][1])
pos = nx.get_node_attributes(G, 'pos')
#nx.draw_networkx_labels(G, pos)
plt.title("CLUSTERING NETWORK'S")
# Limits for the Y axis
plt.ylim(0, 100)
# Create names
plt.xlim(0,100)
plt.xlabel('X-AXIS')
plt.ylabel('Y-AXIS')
nx.draw(G, pos, with_labels=True)
plt.draw()
plt.show()
IMAGE URL: https://cdn-images-1.medium.com/max/1600/0*Jwm3mV92c3qRhqEl.
i want output with grid x and y labels as shown in the picture visit IMAGE URL
import sys
import os
import time
import random
import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
class wireless_sensor_networks:
def __init__(self):
self.user_input()
def user_input(self):
print("ENTER THE DIMENSION OF THE FIELD AS (Length Breadth [as Int]) : ")
length,breadth=list(map(int,input().split(" ")))
print("ENTER THE NUMBER OF NODES THAT IS NEEDED TO BE DEPLOYED [as INT] :")
nodes=int(input())
print(length,breadth,nodes)
self.cluster_creation(length,breadth,nodes)
def cluster_creation(self,length,breadth,nodes):
print("""ENTER TYPE OF CLUSTER CREATION:
1. AREA WISE CLUSTER CREATION
2. DEFAULT (NOT KNOWS AS OF NOW) :""")
cluster_option=int(input())
if cluster_option==1:
self.cluster_area_wise(length,breadth,nodes)
elif cluster_option==2:
pass
else:
pass
def cluster_area_wise(self,length,breadth,nodes):
print("ENTER THE NUMBER OF CLUSTERS YOU WANT TO CREATE :")
number_of_clusters=int(input()) #can be changed to user input later on
x=length//(number_of_clusters**0.5)
y=breadth//(number_of_clusters**0.5)
cluster_list=[]
cluster_count=1
x=int(x)
y=int(y)
print(length,breadth,x,y)
#THE CLUSTERING ASSIGNMENT CAUSES ERROR DURING UNEVEN LENGTH AND BREADTH ASSIGNMENT
for x_axis in range(0,length,x):
for y_axis in range(0,breadth,y):
cluster_number="CLUSTER "+str(cluster_count)
cluster_count+=1
cluster_list.append([cluster_number,[],[[x_axis,x_axis+x],[y_axis,y_axis+y]]])
#print(cluster_list)
self.deployment(length,breadth,nodes,cluster_list)
def sergation_of_nodes_in_cluster(self,length,breadth,nodes,cluster_list,particles):
for each_partilcle in particles:
for node_cluster in cluster_list:
if ((each_partilcle[1][0]>=node_cluster[2][0][0] and each_partilcle[1][0]<node_cluster[2][0][1]) and (each_partilcle[1][1]>=node_cluster[2][1][0] and each_partilcle[1][1]<node_cluster[2][1][1])):
node_cluster[1].append(each_partilcle)
break
#print(cluster_list)
for each in cluster_list:
print(each[0],each[1],len(each[1])/nodes)
print(cluster_list)
self.visualization(length,breadth,cluster_list,particles)
def deployment(self,length,breadth,nodes,cluster_list):
print("""CHOOSE A DEPLOYMENT TYPE AS OPTIONS -
1. RANDOM DEPLOYMENT
2. SPIRAL DEPPLYMENT
3. SQUARE DEPLYMENT
4. DEFAULT DEPLOYMENT""")
deployment_option=int(input())
print(deployment_option)
if deployment_option==1:
self.random_deployment(length,breadth,nodes,cluster_list)
elif deployment_option==2:
self.spiral_deployment(length,breadth,nodes,cluster_list)
elif deployment_option==3:
self.square_deployment(length,breadth,nodes,cluster_list)
else:
self.default_deployment(length,breadth,nodes,cluster_list)
def random_deployment(self,length,breadth,nodes,cluster_list):
no_of_particles = nodes
particles = []
for i in range(no_of_particles):
id = i+1 # creates a id of the particles
x_cordinate = round(random.randrange(0,length),2)+round(random.random(),2)# creates the x cordinate of the particle in the range 0-100 units
y_cordinate = round(random.randrange(0,breadth),2)+round(random.random(),2) # creates the y cordinate of the particles in the range 0-100 units
# print(x_cordinate,y_cordinate)
battery=0 #change it later on
particles.append([id,[x_cordinate,y_cordinate],[battery]])
print(particles)
self.sergation_of_nodes_in_cluster(length,breadth,nodes,cluster_list,particles)
def spiral_deployment(self,length,breadth,nodes,cluster_list):
listx = []
particles=[]
def spiralPrint(m, n):
k = 0
l = 0
''' k - starting row index
m - ending row index
l - starting column index
n - ending column index
i - iterator '''
while (k < m and l < n):
# Print the first row from
# the remaining rows
for i in range(l, n):
particles.append([k, i])
#print("({},{})".format(k + 0.5, i + 0.5), end=" ")
k += 1
# Print the last column from
# the remaining columns
for i in range(k, m):
particles.append([i, n - 1])
#print("({},{})".format(i + 0.5, n - 1 + 0.5), end=" ")
n -= 1
# Print the last row from
# the remaining rows
if (k < m):
for i in range(n - 1, (l - 1), -1):
#print("({},{})".format(m - 1 + 0.5, i + 0.5), end=" ")
particles.append([m - 1, i])
m -= 1
# Print the first column from
# the remaining columns
if (l < n):
for i in range(m - 1, k - 1, -1):
#print("({},{})".format(i + 0.5, l + 0.5), end=" ")
particles.append([i, l])
l += 1
spiralPrint(length, breadth)
listx=particles
print("""ENTER THE TIME INTERVAL IN UNITS""")
time_interval=int(input())
time_interval=time_interval/nodes
node_interval=len(listx)//nodes
time=0
id=1
particles=[]
battery=0
for i in range(0,len(listx),node_interval):
particles.append([id,[listx[i][0],listx[i][1]],[battery],time])
time+=time_interval
id+=1
print(particles)
self.sergation_of_nodes_in_cluster(length, breadth, nodes, cluster_list, particles)
def square_deployment(self,length,breadth,nodes,cluster_list):
print("""ENTER THE TIME INTERVAL IN UNITS""")
time_interval = int(input())
time_interval=time_interval/nodes
no_of_particles = nodes
particles = []
timex=0
breadth_sqr=breadth
no_of_clusters=len(cluster_list)
breadth_start=int(breadth_sqr-((breadth_sqr//(no_of_clusters**0.5))//2))
breadth_incx=int(breadth_sqr//(no_of_clusters**0.5))
id=0
flx=0
while(breadth_start>0):
y_cordinate=breadth_start
flx+=1
temp=[]
battery=0 #change it later on
for i in range(0, int(no_of_particles // (no_of_clusters ** 0.5))):
temp.append(random.randrange(0, length))
if (flx % 2 != 0):
temp = sorted(temp)
else:
temp = sorted(temp, reverse=True)
for x_cordinate in temp:
id += 1
timex+=time_interval
particles.append([id, [x_cordinate, y_cordinate], [battery], timex])
breadth_start = breadth_start - breadth_incx
print(particles)
self.sergation_of_nodes_in_cluster(length, breadth, nodes, cluster_list, particles)
def default_deployment(self,length,breadth,nodes,cluster_list):
pass
def visualization(self,length,breadth,cluster_list,particles):
G=nx.Graph()
for each in particles:
G.add_node(each[0],pos=(each[1][0],each[1][1]))
#pos = nx.get_node_attributes(G, 'pos')
pos = {}
for each in particles:
pos[each[0]] = (each[1][0], each[1][1])
#nx.draw_networkx_labels(G, pos)
nx.draw_networkx(G,pos=pos)
plt.title("CLUSTERING NETWORK'S")
plt.xlabel('X-AXIS')
plt.ylabel('Y-AXIS')
# Limits for the Y and Yaxis
incx=(len(cluster_list)**0.5)
#plt.ylim(0, breadth)
#plt.xlim(0, length)
plt.xticks(np.arange(0, length+1, length//incx))
plt.yticks(np.arange(0, breadth+1, breadth//incx))
#plt.plot([lambda x: x[1][0] for x in particles],[lambda y: y[1][1] for y in particles[1][1]],'ro')
plt.grid()
plt.savefig("WSN_labels.png")
plt.show()
for each in cluster_list:
for i in range(0, len(each[1])-1):
for j in range(i + 1, len((each[1]))):
G.add_edge(each[1][i][0], each[1][j][0])
#nx.draw(G,pos, with_labels=True)
nx.draw_networkx(G, pos=pos,with_labels=True)
plt.xticks(np.arange(0, length + 1, length // incx))
plt.yticks(np.arange(0, breadth + 1, breadth // incx))
plt.grid()
plt.savefig("WSN_CLUSTER.png")
plt.show()
obj1=wireless_sensor_networks()

How to write cos(1)

I need to find a way to write cos(1) in python using a while loop. But i cant use any math functions. Can someone help me out?
for example I also had to write the value of exp(1) and I was able to do it by writing:
count = 1
term = 1
expTotal = 0
xx = 1
while abs(term) > 1e-20:
print("%1d %22.17e" % (count, term))
expTotal = expTotal + term
term=term * xx/(count)
count+=1
I amm completely lost as for how to do this with the cos and sin values though.
Just change your expression to compute the term to:
term = term * (-1 * x * x)/( (2*count) * ((2*count)-1) )
Multiplying the count by 2 could be changed to increment the count by 2, so here is your copypasta:
import math
def cos(x):
cosTotal = 1
count = 2
term = 1
x=float(x)
while abs(term) > 1e-20:
term *= (-x * x)/( count * (count-1) )
cosTotal += term
count += 2
print("%1d %22.17e" % (count, term))
return cosTotal
print( cos(1) )
print( math.cos(1) )
You can calculate cos(1) by using the Taylor expansion of this function:
You can find more details on Wikipedia, see an implementation below:
import math
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n-1)
def cos(order):
a = 0
for i in range(0, order):
a += ((-1)**i)/(factorial(2*i)*1.0)
return a
print cos(10)
print math.cos(1)
This gives as output:
0.540302305868
0.540302305868
EDIT: Apparently the cosine is implemented in hardware using the CORDIC algorithm that uses a lookup table to calculate atan. See below a Python implementation of the CORDIS algorithm based on this Google group question:
#atans = [math.atan(2.0**(-i)) for i in range(0,40)]
atans =[0.7853981633974483, 0.4636476090008061, 0.24497866312686414, 0.12435499454676144, 0.06241880999595735, 0.031239833430268277, 0.015623728620476831, 0.007812341060101111, 0.0039062301319669718, 0.0019531225164788188, 0.0009765621895593195, 0.0004882812111948983, 0.00024414062014936177, 0.00012207031189367021, 6.103515617420877e-05, 3.0517578115526096e-05, 1.5258789061315762e-05, 7.62939453110197e-06, 3.814697265606496e-06, 1.907348632810187e-06, 9.536743164059608e-07, 4.7683715820308884e-07, 2.3841857910155797e-07, 1.1920928955078068e-07, 5.960464477539055e-08, 2.9802322387695303e-08, 1.4901161193847655e-08, 7.450580596923828e-09, 3.725290298461914e-09, 1.862645149230957e-09, 9.313225746154785e-10, 4.656612873077393e-10, 2.3283064365386963e-10, 1.1641532182693481e-10, 5.820766091346741e-11, 2.9103830456733704e-11, 1.4551915228366852e-11, 7.275957614183426e-12, 3.637978807091713e-12, 1.8189894035458565e-12]
def cosine_sine_cordic(beta,N=40):
# in hardware, put this in a table.
def K_vals(n):
K = []
acc = 1.0
for i in range(0, n):
acc = acc * (1.0/(1 + 2.0**(-2*i))**0.5)
K.append(acc)
return K
#K = K_vals(N)
K = 0.6072529350088812561694
x = 1
y = 0
for i in range(0,N):
d = 1.0
if beta < 0:
d = -1.0
(x,y) = (x - (d*(2.0**(-i))*y), (d*(2.0**(-i))*x) + y)
# in hardware put the atan values in a table
beta = beta - (d*atans[i])
return (K*x, K*y)
if __name__ == '__main__':
beta = 1
cos_val, sin_val = cosine_sine_cordic(beta)
print "Actual cos: " + str(math.cos(beta))
print "Cordic cos: " + str(cos_val)
This gives as output:
Actual cos: 0.540302305868
Cordic cos: 0.540302305869

Resources