Related
My electric vehicle charging algorithm aims at returning the shortest path length by a charging drone. The drone will meet the electric vehicle at a rendezvous point and charge the vehicle. The vehicle selection is done based on the charging urgency of the vehicles. The total path length is calculated when all vehicles are charged based on their urgency. The pseudocode is:
EDF(List_Req)
SunchrgEV = List_Req
Pathlen = 0
Nchgreq = 0
while(SunchrgEV = 0):
U obtains the updated location of all ei element of SunchrgEV via message exchange
S'gcs = set of GCS element of Sgcs
Gr = min {Eucleadian distance between Loc(ei) and Loc(Gj)} //The closest GCS
ex = min [{Eucleadian distance between Loc(ei) and Loc(Gr)}/ResidDist(ei)] // most urgent EV
if SoC(U)<RqB2D(ex) // then U(the drone) itself needs charge and it reports its termination to the server
// the server dispatches another U(drone) to charge the remaining EVs (ei)
Gr = min {Eucleadian distance between Loc(U) and Loc(Gj)} //The closest GCS to U where U goes to full charge
end if
t = tcurrent
// Finding rendezvous point where ex and U meets
RdvLoc = FindRdvLoc(ex, Loc(ex), Loc(U),t)
if RdvLoc is out of service area of U then
Report2server(ex,'Outofservicearea')
continue
end if
Pathlen += Dist2(Loc(U),RdvLoc)
U sends RdvLoc to ex and flies to RdvLoc
if U reaches ex in ChgRng(U) then
{Pathlen += Charge(ex, RdvLoc)
Nchgreq ++
}
else
Report2server(ex, 'Outofservicearea')
endif
SunchrgEV -= ex
do
Update (Loc(U))
Gr = min {Eucleadian distance between Loc(U) and Loc(Gj)} //U returns to Gr
Pathlen += Dist2(Loc(U), Loc(Gr))
return Pathlen and Nchgreq
//Compute the expected location where U meets e on Map(e)
def FindRdvLoc(e,Le,Lu,t):
Compute X = (x,y) on Rte(e,t) so that {Dist(e,X)/Speed(e,t)} = {Dist(U, X-ChgRng(U))/Speed(U)}
return X
def Charge(ei, RdvLoc):
U starts to charge ei and follows Rte(ei,t)
eLoc = FindLoc(Map(ei), Loc(ei), ChgTime(ei), Speed(ei,t))
return DistM(Map(ei), RdvLoc, eLoc)
The code that I have written so far gives the same output regardless of the input. The code is:
import math
import sys
from typing import List, Any
class Location:
x = 0
y = 0
def __init__(self, x, y):
self.x = x
self.y = y
class Result:
path_len: int = 0
n_charge_request: int = 0
def __init__(self, path_len, n_charge_request):
self.path_len = path_len
self.n_charge_request = n_charge_request
def to_string(self):
return "path len : " + str(self.path_len) + ", n_charge_request : " + str(self.n_charge_request)
def print(self):
print(self.to_string())
#SGCs
class ChargingStation:
def __init__(self, location: Location, fuel):
self.location = location
self.fuel = fuel
#EVs(ex)
class Vehicle:
location = Location(0, 0)
fuel = 1
isNeedEmergencyFuel = False
per_fuel_distance_travel = 2
def __init__(self, id, location, fuel):
self.id = id
self.location = location
self.fuel = fuel
# Resid (U)
def residual_distance(self):
return self.fuel * self.per_fuel_distance_travel # assuming each watt or kw fuel will yield to 2 killos or milies
# RqB2D
def requested_amount_of_charge(self, nearest_charge_station_location: Location) -> int:
distance = get_distance(self.location, nearest_charge_station_location)
cover = self.fuel * self.per_fuel_distance_travel
diff = math.fabs(distance - cover)
if diff > 0:
needed_fuel = diff / self.per_fuel_distance_travel + 2
return needed_fuel
return 0
# U(i)
class Drone:
location = Location(0, 0)
fuel = 0
isFlying = False
isSendForEvCharge = False
per_fuel_distance_travel = 20
serving_radius = 15
G = [
ChargingStation(Location(20, 10), 50),
ChargingStation(Location(50, 80), 40),
ChargingStation(Location(30, 30), 60)
]
def __init__(self, location, fuel):
self.location = location
self.fuel = fuel
# Resid (U)
def residual_distance(self):
return self.fuel * self.per_fuel_distance_travel # assuming each unit of fuel will yield to 2 kilos or miles
def is_out_of_service_zone(self, vehicle_location: Location): # ----->
distance = get_distance(self.location, vehicle_location)
return distance > self.serving_radius
#staticmethod
def get_distance(from_location, to_location):
x_dis = to_location.x - from_location.x
y_dis = to_location.y - from_location.y
x_dis_sqr = math.pow(x_dis, 2)
y_dis_sqr = math.pow(y_dis, 2)
final_dis_sum = x_dis_sqr + y_dis_sqr
final = math.sqrt(final_dis_sum)
return final
class EDFGenerator:
min_fuel = 50
charging_stations_for_drones = [ChargingStation(Location(2, 10), 80), ChargingStation(Location(2, 10), 50),
ChargingStation(Location(2, 10), 100)]
list_waiting_drones = [Drone(Location(5, 10), 50), Drone(Location(2, 10), 50), Drone(Location(2, 10), 50)]
list_sent_drones = []
list_charging_drones = []
def __init__(self):
pass
def rdv_loc(self, ei: Vehicle, drone_location: Location, t: int) -> Location | None:
needed_fuel = ei.requested_amount_of_charge(drone_location)
nearest_charge_station = self.get_nearest_charge_station(ei.location, self.charging_stations_for_drones)
needed_fuel_at_nearest_station = needed_fuel / ei.per_fuel_distance_travel
if nearest_charge_station.fuel < needed_fuel_at_nearest_station:
return None
else:
return nearest_charge_station.location
#staticmethod
def get_nearest_charge_station(from_location: Location, list_of_stations: List[ChargingStation]) -> ChargingStation:
nearest = list_of_stations[0]
min_distance = get_distance(from_location, nearest.location)
for station in list_of_stations:
dis = get_distance(from_location, station.location)
if min_distance > dis:
min_distance = dis
nearest = station
return nearest
def NChgReq(self) -> int:
charging_requesters = 0
for drone in self.list_waiting_drones:
if drone.isNeedEmergencyFuel:
charging_requesters += 1
return charging_requesters
def send_drone_to_charge(self, drone: Drone): # ----->
if drone.fuel < self.min_fuel:
nearest_station = self.get_nearest_charge_station(
drone.location,
self.charging_stations_for_drones)
self.list_sent_drones.append(drone)
self.list_waiting_drones.remove(drone)
drone.isSendForEvCharge = True
# send the drone to the charging station here
print(f"Drone {drone} sent to charging station at {nearest_station}")
def check_fuel_and_send_to_charge(self): # ----->
for drone in self.list_waiting_drones:
self.send_drone_to_charge(drone)
def get_drone(self, max_try=4) -> Drone:
if max_try <= 0:
print("max try failed for get_drone")
return None
# take one time from list_waiting_drones ------->
# add to list_sent_drones
# send or return the taken item
if len(self.list_waiting_drones) == 0:
return None
else:
# lastOne = self.list_waiting_drones.pop()
self.last_one = self.list_waiting_drones.pop()
if self.last_one.fuel < self.min_fuel:
print("low fuel failed to get_drone, retry")
self.list_waiting_drones.insert(0, self.last_one)
return max_try - 1
self.list_sent_drones.append(self.last_one)
return self.last_one
def get_closest_location_from_sending_server_to_e_vehicle(self, current_vechicle_location):
min_distance = sys.maxsize
for current_server in self.charging_stations_for_drones:
distance = get_distance(current_vechicle_location, current_server.location)
if min_distance > distance:
min_distance = distance
return min_distance
def get_most_urgent_electric_vehicle(self, closest_distance_between_server_ev: int,
all_uncharged_electric_vehicles: List[Vehicle]) -> Vehicle:
final_ev = None
min_distance = sys.maxsize
for ev in all_uncharged_electric_vehicles:
g_r = self.get_closest_location_from_sending_server_to_e_vehicle(ev.location)
residual_distance = ev.residual_distance()
eq = g_r / residual_distance
if min_distance > eq:
min_distance = eq
final_ev = ev
return final_ev
def reports_termination_to_server(self, drone: Drone):
self.list_charging_drones.append(drone)
self.charge_all_waiting_drones()
def charge_all_waiting_drones(self):
# assuming the environment is not async but synchronous
for drone in self.list_charging_drones:
drone.fuel = 100
self.list_waiting_drones.insert(0, drone)
self.list_charging_drones.clear()
#staticmethod
def report_to_server(ev: Vehicle, message):
print(ev.id + " - " + message)
def get_edf(self, list_req: List[Vehicle]) -> Result:
s_uncharged_electric_vehicles = list_req
path_len = 0
n_charge_req = 0
while len(s_uncharged_electric_vehicles) > 0:
print("uncharged_ev : " + str(len(s_uncharged_electric_vehicles)))
current_uncharged_ev = s_uncharged_electric_vehicles[0]
u = self.get_drone()
if u is None:
print("no drones from any station or with min charge")
return Result(path_len, n_charge_req)
# current_uncharged_ev.location aka e----->
e = current_uncharged_ev.location
# confusion SGCS what would be the SET
g_r: int = self.get_closest_location_from_sending_server_to_e_vehicle(
e) # closest vehicle from sending location
# confusion regarding dis (loc(e), g_r) , g_r already contains the distance
e_x = self.get_most_urgent_electric_vehicle(g_r, s_uncharged_electric_vehicles)
drone_residual_distance = u.residual_distance() # Resid (U)
ev_requested_amount_of_charge = e_x.requested_amount_of_charge(u.location) # RqB2D
if drone_residual_distance < ev_requested_amount_of_charge:
self.reports_termination_to_server(u)
u = self.get_drone()
g_r_2 = self.get_closest_location_from_sending_server_to_e_vehicle(
u.location) # closest vehicle from sending location
self.reports_termination_to_server(u) # sends back the drone for charging
# ?? t is something confusing, how to include t into the equation??
rdv_loc = self.rdv_loc(e_x, u.location, 0) # t should be random
if rdv_loc is None:
self.report_to_server(e_x, "rdv location generate failed")
continue
if u.is_out_of_service_zone(rdv_loc):
self.report_to_server(e_x, "Out of Service")
continue
path_len += get_distance(u.location, rdv_loc)
u.location = rdv_loc
e_x.location = rdv_loc
# list_1 = filter(lambda x: x[3] <= 0.3 and x[2] < 5, list_1)
s_uncharged_electric_vehicles.remove(e_x)
n_charge_req = n_charge_req + 1
return Result(path_len, n_charge_req)
if __name__ == '__main__':
edf_runner = EDFGenerator()
un_charged_vehicles = [
Vehicle(1, Location(1, 1), 2),
Vehicle(2, Location(5, 10), 16),
Vehicle(3, Location(6, 10), 13),
Vehicle(4, Location(8, 11), 22),
Vehicle(5, Location(5, 6), 35),
]
edf_result = edf_runner.get_edf(un_charged_vehicles)
print("first_path_len - edf : ")
edf_result.print()
Where am I wrong? What needs fix?
I just learned how to create a balanced binary tree and how to access them. For example, if this is my tree:
date = ((1,3,None),2,((None,3,4),5,(6,7,8)))
I can create it by given code:
class tree:
def __init__(self,key):
self.key = key
self.right = None
self.left = None
node_0 = tree(2)
node_1 = tree(3)
node_2 = tree(5)
node_3 = tree(1)
node_4 = tree(3)
node_5 = tree(7)
node_6 = tree(4)
node_7 = tree(6)
node_8 = tree(8)
#connecting
node_0.left = node_1
node_0.right = node_2
node_0.left.left = node_3
node_0.right.left = node_4
node_0.right.right = node_5
node_0.right.left.left = node_6
node_0.right.right.left = node_7
node_0.right.right.right = node_8
#accesing
node_0.right.right.right.key
But this method is very inefficient and lengthy so I tried recursion in place of that:
def parse_tuple(data):
if isinstance(data,tuple) and len(data)==3:
node = (data[1])
node.left = parse_tuple(data[0])
node.right = parse_tuple(data[2])
elif data is None:
node = None
else:
node=(data)
return node
so my idea is access data = ((1,3,None),2,((None,3,4),5,(6,7,8))) , by passing into a function but there's a problem
the function work well's till node.left = parse_tuple(data[0]). Basically here's what's going on
18:10:41.43 >>> Call to parse_tuple in File "C:\Users\muzza\AppData\Local\Temp\ipykernel_17864\3153403204.py", line 4
18:10:41.43 ...... data = ((1, 3, None), 2, ((None, 3, 4), 5, (6, 7, 8)))
18:10:41.43 ...... len(data) = 3
18:10:41.43 4 | def parse_tuple(data):
18:10:41.43 6 | if isinstance(data,tuple) and len(data)==3:
18:10:41.43 7 | node = (data[1])
18:10:41.43 .............. node = 2
18:10:41.43 8 | node.left = parse_tuple(data[0])
18:10:41.44 >>> Call to parse_tuple in File "C:\Users\muzza\AppData\Local\Temp\ipykernel_17864\3153403204.py", line 4
18:10:41.44 ...... data = (1, 3, None)
18:10:41.44 ...... len(data) = 3
18:10:41.44 4 | def parse_tuple(data):
18:10:41.44 6 | if isinstance(data,tuple) and len(data)==3:
18:10:41.44 7 | node = (data[1])
18:10:41.44 .............. node = 3
18:10:41.44 8 | node.left = parse_tuple(data[0])
18:10:41.44 >>> Call to parse_tuple in File "C:\Users\muzza\AppData\Local\Temp\ipykernel_17864\3153403204.py", line 4
18:10:41.44 ...... data = 1
18:10:41.44 4 | def parse_tuple(data):
18:10:41.44 6 | if isinstance(data,tuple) and len(data)==3:
18:10:41.44 10 | elif data is None:
18:10:41.45 13 | node=(data)
18:10:41.45 .............. node = 1
18:10:41.45 14 | return node
18:10:41.45 <<< Return value from parse_tuple: 1
18:10:41.45 8 | node.left = parse_tuple(data[0])
18:10:41.46 !!! AttributeError: 'int' object has no attribute 'left'
18:10:41.46 !!! When getting attribute: node.left
18:10:41.46 !!! Call ended by exception
18:10:41.46 8 | node.left = parse_tuple(data[0])
18:10:41.47 !!! AttributeError: 'int' object has no attribute 'left'
18:10:41.47 !!! When calling: parse_tuple(data[0])
18:10:41.47 !!! Call ended by exception
I tried to fix the issue but I can't think of any option available. I want to access the data that I've passed, just like the first method above mentioned. I've come across many recursion techniques to implement binary trees but I want correction in this code so that I can know my mistake.
The problem is that your code does not call the tree constructor. Your node should be an instance of that class, yet you merely assign the key to node.
So change node = (data[1]) to node = tree(data[1]) and node=(data) to node=tree(data)
Fixing your parse_tuple recursive function
Your function parse_tuple is almost correct, but you need to call tree() at each recursive call to create all the nodes.
def parse_tuple(data, node=None):
if isinstance(data, tuple) and len(data) == 3:
l, k, r = data
node = tree(k)
node.left = parse_tuple(l)
node.right = parse_tuple(r)
elif data is None:
node = None
else:
node = tree(data)
return node
parse_tuple( ((1, 3, None), 2, ((None, 3, 4), 5, (6, 7, 8))) )
Tree creation using Tree.__init__
There is a much simpler option.
Modify your method __init__ so that it accepts right and left arguments.
Instead of:
class tree:
def __init__(self,key):
self.key = key
self.right = None
self.left = None
I suggest to use instead:
class Tree:
def __init__(self, key, left=None, right=None):
self.key = key
self.left = left
self.right = right
This way, you can create the full tree directly:
node0 = Tree(2, Tree(3, Tree(1)), Tree(5, Tree(3, Tree(4)), Tree(7, Tree(6), Tree(8))))
Or perhaps more lisibly with some indentation:
node0 = Tree(2,
Tree(3,
Tree(1)),
Tree(5,
Tree(3, Tree(4)),
Tree(7, Tree(6), Tree(8))))
I have found the code from this link:
class Node:
def __init__(self, name, weight, children):
self.children = children
self.weight = weight
self.weight_plus_children = weight
def get_all_weight(self):
if self.children is None:
return self.weight_plus_children
else:
for child in self.children:
print("child.get_all_weight()", child.get_weigth_with_children())
self.weight_plus_children += child.get_weigth_with_children()
return self.weight_plus_children
def get_weigth_with_children(self):
return self.weight_plus_children
leaf1 = Node('C1', 58, None)
leaf2 = Node('C2', 7, None)
leaf3 = Node('C3', 10, None)
leaf4 = Node('C4', 20, None)
subroot = Node('B1', 50, [leaf1, leaf2])
subroot1 = Node('B2', 50, [leaf3, leaf4])
root = Node('A', 100, [subroot, subroot1])
print(subroot.get_all_weight())
print(subroot1.get_all_weight())
print(root.get_all_weight())
Out:
child.get_all_weight() 58
child.get_all_weight() 7
115
child.get_all_weight() 10
child.get_all_weight() 20
80
child.get_all_weight() 115
child.get_all_weight() 80
295
Now, instead of child.get_all_weight(), I hope to show the nodes names on the output:
How could I generate a similar result as follows (not necessary to be exact same if it's difficult to realize)?
Value of leaf C1: 58
Value of leaf C2: 7
Sum of nodes B1: 115
Value of leaf C3: 10
Value of leaf C4: 20
Sum of nodes B2: 80
Sum of nodes A: 295
Thanks a lot at advance.
from collections import deque
class Node:
def __init__(self, name, weight, children):
self.name = name
self.children = children
self.weight = weight
self.weight_plus_children = weight
def get_all_weight(self):
if self.children is None:
return self.weight_plus_children
for child in self.children:
self.weight_plus_children += child.get_all_weight()
return self.weight_plus_children
def print_tree(root: Node):
queue = deque()
queue.append(root)
while queue:
front = queue.popleft()
print('{} = {}'.format(front.name, front.weight_plus_children))
if front.children:
for child in front.children:
if child is not None:
queue.append(child)
leaf1 = Node('C1', 58, None)
leaf2 = Node('C2', 7, None)
leaf3 = Node('C3', 10, None)
leaf4 = Node('C4', 20, None)
subroot = Node('B1', 50, [leaf1, leaf2])
subroot1 = Node('B2', 50, [leaf3, leaf4])
root = Node('A', 100, [subroot, subroot1])
root.get_all_weight()
print_tree(root)
Output:
A = 295
B1 = 115
B2 = 80
C1 = 58
C2 = 7
C3 = 10
C4 = 20
I have created my k means algorithm for 2 dimensions. I want to modify it for 8 dimensions i.e. the datapoints can take 8-dimensional values and finally return 8-dimensional centroid values.
The code is following :
import random
import math
# Input varibles
#k = 3
#Threshold = 1
DATA = [[2, 1, 1, 2, 1, 1, 1, 5], [ 6, 8, 1, 3, 4, 3, 7, 1],[4, 1, 3, 2, 1, 3, 1, 1],[3, 1, 1, 2, 1, 2, 1, 1],[3 ,1 ,1 ,1, 1, 2, 1, 1],[6, 1, 1, 1, 1, 7, 1, 1],[6, 10, 2, 8, 10, 7, 3, 3]]
BIG_NUMBER = math.pow(10, 10)
data = []
centroids = []
class DataPoint:
def __init__(self, x, y):
self.x = x
self.y = y
def set_x(self, x):
self.x = x
def get_x(self):
return self.x
def set_y(self, y):
self.y = y
def get_y(self):
return self.y
def set_cluster(self, clusterNumber):
self.clusterNumber = clusterNumber
def get_cluster(self):
return self.clusterNumber
class Centroid:
def __init__(self, x, y):
self.x = x
self.y = y
def set_x(self, x):
self.x = x
def get_x(self):
return self.x
def set_y(self, y):
self.y = y
def get_y(self):
return self.y
# Initializing The Centroids
def initialize_centroids(k,DATA):
#find data range in x and y
max_x = max(x for x,y in DATA)
max_y = max(y for x,y in DATA)
min_x = min(x for x,y in DATA)
min_y = min(y for x,y in DATA)
#chosse random x and y between this data range
#assign to centroids
for j in range(k):
#x = random.choice(DATA)
random_x = random.uniform(min_x,max_x)
random_y = random.uniform(min_y,max_y)
centroids.append(Centroid(random_x, random_y))
#print("(", centroids[j].get_x(), ",", centroids[j].get_y(), ")")
return centroids
# Assigning Datapoints to nearest Centroids
def initialize_datapoints(k,DATA):
for i in range(len(DATA)):
newpoint = DataPoint(DATA[i][0], DATA[i][1])
bestMinimum = BIG_NUMBER
data.append(newpoint)
for j in range(k):
distance = get_distance(newpoint.get_x(), newpoint.get_y(), centroids[j].get_x(), centroids[j].get_y())
if(distance < bestMinimum):
bestMinimum = distance
newpoint.set_cluster(j)
return
# Calculating Euclidean distance
def get_distance(dataPointX, dataPointY, centroidX, centroidY):
return math.sqrt(math.pow((centroidY - dataPointY), 2) + math.pow((centroidX - dataPointX), 2))
# Updating Centroid and Clusters till the threshold is met
def update_centroids_n_clusters(k,DATA,Threshold):
dist = 0.0
#print ("a")
for j in range(k):
prev_x = centroids[j].get_x()
prev_y = centroids[j].get_y()
totalX = 0
totalY = 0
totalInCluster = 0
for z in range(len(data)):
if (data[z].get_cluster() == j):
totalX += data[z].get_x()
totalY += data[z].get_y()
totalInCluster += 1
if (totalInCluster > 0):
s_x = (totalX / totalInCluster)
s_y = (totalY / totalInCluster)
centroids[j].set_x(s_x)
centroids[j].set_y(s_y)
x1 = centroids[j].get_x()
y1 = centroids[j].get_y()
x2 = prev_x
y2 = prev_y
dist += get_distance(x1,y1,x2,y2)
conv_val = (1/k)*dist
if(conv_val >= Threshold):
for i in range(len(DATA)):
bestMinimum = BIG_NUMBER
currentCluster = 0
for j in range(k):
distance = get_distance(data[i].get_x(), data[i].get_y(), centroids[j].get_x(), centroids[j].get_y())
if (distance < bestMinimum):
bestMinimum = distance
currentCluster = j
data[i].set_cluster(currentCluster)
update_centroids_n_clusters(k, DATA, Threshold)
return
# Performing K_Means
def Kmeans(k, DATA, Threshold):
initialize_centroids(k,DATA)
initialize_datapoints(k, DATA)
update_centroids_n_clusters(k, DATA, Threshold)
for i in range(k):
p = 0
print()
print("Centroid ", i, " is at")
print("(",centroids[i].get_x(), ",", centroids[i].get_y(), ")")
print("Cluster ", i, " includes:")
for j in range(len(DATA)):
if (data[j].get_cluster() == i):
#print("(", data[j].get_x(), ", ", data[j].get_y(), ")")
p += 1
print(p,"points")
return
Kmeans(3,DATA,0.1)
How should I modify my class Centroid and class DataPoint in this code? Thanks!!
Note: The code is in Python 3
Use arrays instead of x and y.
You want e.g. your distance function to be
def distance(array1, array2):
return (array1 - array2)**2
(assuming you use numpy)
So I have these three complete functions that return the desired row of a matrix, column of a matrix, and dot product of the row and column, and I need to somehow mesh them together in a fourth function in order to find the product of two matrices being multiplied together. Any suggestions?
#Test matrices
A = [[2,4], [7,0], [6,3]]
B = [[3,1], [-1,8], [-3, 3]]
C = [[4,1,9], [6,2,8], [7,3,5]]
D = [[2,9], [5,2], [1,0]]
def row(A,i):
Z = []
Z.append(A[i])
return Z[0]
def col(B,j):
Z=[]
for i in range(len(B)):
Z.append(B[i][j])
return Z
def dotProduct(x,y):
prod=0
for i in range(len(x)):
prod=prod+x[i]*y[i]
return prod
def matrixMUL(A, B):
Z = []
....
return Z
Solution with 3 more auxiliary functions:
from functools import partial
#Test matrices
A = [[2,4], [7,0], [6,3]]
B = [[3,1], [-1,8], [-3, 3]]
C = [[4,1,9], [6,2,8], [7,3,5]]
D = [[2,9], [5,2], [1,0]]
def row(A,i):
Z = []
Z.append(A[i])
return Z[0]
def col(B,j):
Z=[]
for i in range(len(B)):
Z.append(B[i][j])
return Z
def dotProduct(x,y):
prod=0
for i in range(len(x)):
prod=prod+x[i]*y[i]
return prod
def shape(A):
num_rows = len(A)
num_cols = len(A[0]) if A else 0
return num_rows, num_cols
def matrix_product_entry(A, B, i, j):
return dotProduct(row(A, i), col(B, j))
def matrix_make(rows, cols, entry_fn):
return [[entry_fn(i, j) for j in range(cols)]
for i in range(rows)]
def matrixMUL(A, B):
n1, k1 = shape(A)
print(n1, k1)
n2, k2 = shape(B)
if k1 != n2:
raise ArithmeticError("matrices shapes are not compatible!")
return matrix_make(n1, k2, partial(matrix_product_entry, A, B))
print (matrixMUL(C, D))
# returns [[22, 38], [30, 58], [34, 69]]