Else statement executing even though the if statement is true - python-3.x

for school i am making an assignment, implementing astar search with the use of dictionaries. I have been trying a few things, but now i am stuck. in my first iteration the if statement if f_next < f: is true, so why does it not break out of the loop. It immediately goes to the else statement so my closed list contains both values from the if and else statement, how can i fix this. I have provided my code, some assignment information and the input below.
Given a grid-like graph, find the shortest path using A* between the two nodes with the maximum weight. Use the Euclidean as heuristic function, which is calculated between two points in a coordinate system (x1,y1) and (x2,y2) as follows:
d = p(x2 −x1)2 + (y2 −y1)2 (1) where, the nodes of the graph are represented as such points (see the input format below). You can assume that there exists a path between the two nodes with the maximum weight, and that all nodes have a unique weight.
Data format 1. The following is the input format expected by the algorithm for Task 1.
The program takes as input a list of nodes, represented as points in a coordinate system (e.g.,(x1,y1) and their weights separated by a ;.
In a new line the data-set of the graph edges are given following the pattern ”source node (xs,ys), end node (xe,ye), edge cost; ...”.
(x1), (y1), (weight1); ...(xn), (yn), (weightn);\n
(x1), (y1), (x2), (y2), (edgecost1); ...(xs), (ys), (xe), (ye), (edgecostm);\n
The expected output is the path from the start to the end node.
(xstart), (ystart)->(xi), (yi)...->(xend), (yend)\n
Input:
0, 0, 193; 0, 1, 146; 0, 2, 121; 0, 3, 174; 0, 4, 144; 1, 0, 191; 1, 1, 123; 1, 2, 151; 1, 3, 126; 1, 4, 163; 2, 0, 182; 2, 1, 107; 2, 2, 109; 2, 3, 125; 2, 4, 165; 3, 0, 169; 3, 1, 149; 3, 2, 180; 3, 3, 199; 3, 4, 199; 4, 0, 160; 4, 1, 148; 4, 2, 123; 4, 3, 197; 4, 4, 156
0, 0, 1, 0, 1; 0, 0, 0, 1, 1; 0, 1, 1, 1, 1; 0, 1, 0, 2, 1; 0, 2, 1, 2, 1; 0, 2, 0, 3, 1; 0, 3, 1, 3, 1; 0, 3, 0, 4, 1; 0, 4, 1, 4, 1; 1, 0, 2, 0, 1; 1, 0, 1, 1, 1; 1, 1, 2, 1, 1; 1, 1, 1, 2, 1; 1, 2, 2, 2, 1; 1, 2, 1, 3, 1; 1, 3, 2, 3, 1; 1, 3, 1, 4, 1; 1, 4, 2, 4, 1; 2, 0, 3, 0, 1; 2, 0, 2, 1, 1; 2, 1, 3, 1, 1; 2, 1, 2, 2, 1; 2, 2, 3, 2, 1; 2, 2, 2, 3, 1; 2, 3, 3, 3, 1; 2, 3, 2, 4, 1; 2, 4, 3, 4, 1; 3, 0, 4, 0, 1; 3, 0, 3, 1, 1; 3, 1, 4, 1, 1; 3, 1, 3, 2, 1; 3, 2, 4, 2, 1; 3, 2, 3, 3, 1; 3, 3, 4, 3, 1; 3, 3, 3, 4, 1; 3, 4, 4, 4, 1
I am trying to find a path between (0,0) and (3,4)
import collections
import math
import sys
class Graph:
"""Class to represent a Graph, as a list of weighted nodes and edges."""
def __init__(self):
"""Function to initialize a Graph object"""
self.node_g = {}
self.edge_g = collections.defaultdict(list)
pass
def add_node(self, node_id, weight):
"""Function to add a node to a Graph object."""
self.node_g[node_id] = weight
print(self.node_g)
pass
def add_edge(self, source_id, end_id, weight):
weightedge = (end_id, weight)
self.edge_g[source_id].append(weightedge)
pass
def __repr__(self):
return "nodes:% s edges:% s" % (self.node_g, self.edge_g)
def __str__(self):
return "From str method of graph: nodes are % s, " \
"edges are % s" % (self.node_g, self.edge_g)
def build_Graph(nodes, edges):
"""Function to build a grid-like Graph object from the input data.
Parameters
----------
nodes : list of nodes, each represented as coordinates, and node_weight.
For example: x1, y1, weight; x2, y2, weight; ...
edges : list of edges, each represented as source and end node coordintates, and edge_weight.
For example: x1, y1, x2, y2, weight; x3, y3, x4, y4, weight; ...
Return
----------
A Graph object.
"""
G = Graph()
for n in nodes:
aux = n.split(', ')
temp1 = int(aux[0])
temp2 = int(aux[1])
temp_node = (temp1, temp2)
G.add_node(temp_node, weight=int(aux[2]))
for e in edges:
aux = e.split(', ')
temp1 = int(aux[0])
temp2 = int(aux[1])
temp = (temp1, temp2)
auxn1 = int(aux[2])
auxn2 = int(aux[3])
auxn = (auxn1, auxn2)
G.add_edge(temp, auxn, weight=int(aux[4]))
return G
def print_output(nodes):
"""Function to print the shortest path between the two nodes with the highest weigths.
Parameters
----------
nodes : list of list of nodes (represented as: tuples of coordinates).
"""
# nodes = [x1, y1, x2, y2, x3, y3]
# Expected output: x1, y1->x2, y2->x3, y3
def astar_shortest_path(G, source_id, end_id, heuristic):
"""Function to return the shortest path between two nodes in a Graph"""
open_set = [source_id]
#print(open_set)
closed_set = []
g = 0
h = heuristic(source_id, end_id)
f = g + h
#print(G.edge_g[open_set[0]][0])
#print(G.edge_g[source_id])
#print(G.edge_g[end_id])
while len(open_set) > 0:
if source_id == end_id:
return closed_set
for index, item in enumerate(G.edge_g[open_set[0]]):
print(item)
var = item[0]
print(var)
if not index:
next = item[0]
g_next = item[1]
h_next = heuristic(item[0], end_id)
f_next = h_next + g_next
if f_next < f:
f += f_next
h += h_next
g += g_next
open_set.append(next)
print(open_set)
closed_set.append(open_set[0])
print(closed_set)
open_set.remove(open_set[0])
print(open_set)
else:
next_2 = item[0]
g_next_2 = item[1]
h_next_2 = heuristic(item[0], end_id)
f_next_2 = g_next_2 + h_next_2
if f_next_2 < f:
f += f_next_2
h += h_next_2
g += g_next_2
closed_set.append(open_set[0])
print(closed_set)
open_set.remove(open_set[0])
print(open_set)
open_set.append(next_2)
print(open_set)
#print(open_set)
def heuristic(a, b):
#print(a, b)
"""Function to compute the Euclidean distance between two nodes."""
dx = abs(b[0] - a[0]) ** 2
#print(dx)
dy = abs(b[1] - a[1]) ** 2
#print(dy)
return math.sqrt(dx + dy)
if __name__ == '__main__':
# Read the input
# The first line is made of a list of nodes, written as tuples of cartesian coordinates.
# For example: x1, y1, weight; x2, y2, weight; ...
# In the previous example, x1, y1, weight; is the first node
nodes = input().split('; ')
# The second line is made of edges, written as source and end node coordinates, and edge_weight.
# For example: x1, y1, x2, y2, weight; x3, y3, x4, y4, weight; ...
# In the previous example, x1, y1, x2, y2, weight; is the first edge
edges = input().split('; ')
# Build a grid graph from the input nodes and edges
G = build_Graph(nodes, edges)
print(G)
sort_edge = sorted(G.node_g, key=G.node_g.get)
max1 = sort_edge[-2]
#print(max1)
max2 = sort_edge[-1]
#print(max2)
# Find the two nodes with the highest weights in the graph
source_id = (0, 0) #max1
end_id = (3, 4) #max2
# Compute the path between the two nodes with the highest weight
# The source node is the one with the highest weigth
# You are free to customize the following function
s_path = astar_shortest_path(G, source_id, end_id, heuristic)
# Expected output format: list of lists of nodes (represented as: tuples of coordinates).
# For example: x1, y1->x2, y2->x3, y3
print_output(s_path)
#############

Related

How to initialize an 3D array variable in Gekko?

I'm trying to solve a step from a three-dimensional master timetabling model, which involvs periods(5), courses(19) and locations(8).
So I have a problem to initialize these variables with an 3D array in Gekko. Without this initialization the algorithm doesn't converge, after more than 15 minutes run and 1000 iterations.
When I try initialize, this error appears:
"
raise Exception(response)
Exception: #error: Equation Definition
Equation without an equality (=) or inequality (>,<)
true
STOPPING...
"
How can I fix this problem? Follows a version of my code:
import numpy as np
from gekko import GEKKO
# Input data
# Schedule of periods and courses
sched = np.array([ [0, 1, 0, 0, 1], [0, 0, 1, 1, 0], [0, 0, 1, 1, 0], \
[0, 0, 0, 0, 1], [1, 0, 0, 0, 1], [0, 0, 0, 1, 1], [0, 1, 1, 0, 0], \
[1, 0, 0, 1, 0], [0, 1, 0, 0, 1], [1, 1, 0, 0, 0], [0, 1, 1, 0, 0], \
[0, 1, 1, 0, 0], [1, 0, 0, 1, 0], [1, 0, 0, 1, 0], [0, 0, 1, 0, 1], \
[1, 0, 1, 0, 0], [0, 1, 0, 1, 0], [0, 0, 1, 1, 0], [0, 1, 0, 0, 1] ], dtype=np.int64)
# Initial allocation of all periods, courses and locations
alloc=np.array([0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,\
0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], dtype=np.int64)
# Number of students enrolled in each course
enrol = np.array([ 60, 60, 60, 40, 40, 110, 120, 50, 60, 55, 50, \
55, 40, 64, 72, 50, 50, 55, 55], dtype=np.float64)
# Capacity of each location (classroom)
capac = np.array([ 60, 60, 120, 60, 80, 60, 60, 65], dtype=np.float64)
# Total costs of using each location
costs = np.array([ 9017.12, 9017.12, 12050.24, 9017.12, 9413.68, 9017.12, \
9017.12, 9188.96 ])
# Estimated cost of each location by period and student
ecost = np.repeat(np.array([[costs[i]*pow(enrol[j]*5,-1) for j in range(19)] for i in range(8)]), 5)
# The model construction
m = GEKKO()
# Constant arrays
x = m.Array(m.Const,(19,5))
y = m.Array(m.Const,(8,19,5))
N = m.Array(m.Const,(19))
C = m.Array(m.Const,(8))
Ec = m.Array(m.Const,(8,19,5))
Ecy = m.Array(m.Const,(8,19,5))
Alt = m.Array(m.Const,(8,19,5))
for k in range(5):
for j in range(19):
N[j] = enrol[j]
x[j,k] = sched[j,k]
for i in range(8):
C[i] = capac[i]
Ec[i,j,k] = ecost[k+j*5+i*19*5]
y[i,j,k] = alloc[k+j*5+i*19*5]
Ecy[i,j,k] = Ec[i,j,k]*y[i,j,k]
if sched[j,k]==1:
Alt[i,j,np.where(sched[j,:]==1)[0][0]]=-sched[j,k]*(1-sum(sched[j,:]))
if sum(sched[j,:])==2:
Alt[i,j,np.where(sched[j,:]==1)[0][1]]=sched[j,k]*(1-sum(sched[j,:]))
else:
Alt[i,j,k]=0
# Initialize the variable z with the initial value y:
# These commented approaches produce the error.
z = m.Array(m.Var,(8,19,5),lb=0,ub=1,integer=True)
#for i in range(8):
# for j in range(19):
# for k in range(5):
# z[i,j,k] = y[i,j,k]
# nor
#z = m.Array(m.Var,(8,19,5),value=y,lb=0,ub=1,integer=True)
# Intermediate equations
Ecz = m.Array(m.Var,(8,19,5),lb=0)
Altz = m.Array(m.Var,(8,19))
for i in range(8):
for j in range(19):
Altz[i,j]=m.Intermediate(m.sum(Alt[i,j,:]*z[i,j,:]))
for k in range(5):
Ecz[i,j,k]=m.Intermediate(Ec[i,j,k]*z[i,j,k])
# Constraints
m.Equation(m.sum(m.sum(m.sum(Ecz)))<=m.sum(m.sum(m.sum(Ecy))))
for j in range(19):
for k in range(5):
m.Equation(m.sum(z[:,j,k])==x[j,k])
for i in range(8):
for k in range(5):
m.Equation(m.sum(z[i,:,k])==m.sum(y[i,:,k]))
for i in range(8):
for j in range(19):
m.Equation(m.sum((C[i]/N[j]-x[j,:])*z[i,j,:])>=0)
# Objective: to minimize the quantity of courses allocated in different locations
# Example: with the solution y, I have 12 courses in different locations in the periods
# print(sum([sum(Alt[i,j,:]*y[i,j,:])**2 for j in range(19) for i in range(8)])/2)
for i in range(8):
for j in range(19):
m.Obj(Altz[i,j]**2/2)
# Options and final results
m.options.SOLVER=1
m.options.IMODE=2
m.solve()
print(z)
print(m.options.OBJFCNVAL)
Note: My original problem has 20 periods, 171 courses, and 18 locations.
Use z[i,j,k].value = y[i,j,k] to give an initial guess for z. Using z[i,j,k] = y[i,j,k] redefines z entries as floating point numbers instead of gekko variable types.
One other issue is that the variables Ecz and Altz are defined as Variables as m.Var and then overridden as Intermediates. Instead, try allocating them and assigning them as intermediates:
Ecz = np.empty((8,19,5),dtype=object)
Altz = np.empty((8,19),dtype=object)
Use flatten() to simplify the summation of all elements of the 3 dimensional array.
m.Equation(m.sum(Ecz.flatten())<=sum(Ecy.flatten()))
The constant arrays can be defined as numpy arrays to avoid additional symbolic processing by Gekko. This speeds up the model compile time but has no effect on the final solution.
x = np.empty((19,5))
y = np.empty((8,19,5))
N = np.empty((19))
C = np.empty((8))
Ec = np.empty((8,19,5))
Ecy = np.empty((8,19,5))
Alt = np.empty((8,19,5))
The IMODE should be 3 for optimization. IMODE=2 is for parameter regression. IMODE=2 should also work for this problem but 3 is the correct option because you aren't trying to fit to data.
m.options.IMODE=3
Try using IPOPT to obtain an initial non-integer solution and then use APOPT to find an integer solution.
m.solver_options = ['minlp_gap_tol 1.0e-2',\
'minlp_maximum_iterations 10000',\
'minlp_max_iter_with_int_sol 500',\
'minlp_branch_method 1']
Mixed Integer Nonlinear Programming (MINLP) problems can be challenging to solve so you may need to use some of the solver options to speed up the solution. Try minlp_branch_method 1 to help the solver find an initial integer solution to do better pruning. The gap tolerance can also help to speed up the solution if a sub-optimal solution is okay. Below is the complete script. Consider using remote=False to run locally instead of using the public servers, especially for large optimization problems.
import numpy as np
from gekko import GEKKO
# Input data
# Schedule of periods and courses
sched = np.array([ [0, 1, 0, 0, 1], [0, 0, 1, 1, 0], [0, 0, 1, 1, 0], \
[0, 0, 0, 0, 1], [1, 0, 0, 0, 1], [0, 0, 0, 1, 1], [0, 1, 1, 0, 0], \
[1, 0, 0, 1, 0], [0, 1, 0, 0, 1], [1, 1, 0, 0, 0], [0, 1, 1, 0, 0], \
[0, 1, 1, 0, 0], [1, 0, 0, 1, 0], [1, 0, 0, 1, 0], [0, 0, 1, 0, 1], \
[1, 0, 1, 0, 0], [0, 1, 0, 1, 0], [0, 0, 1, 1, 0], [0, 1, 0, 0, 1] ], dtype=np.int64)
# Initial allocation of all periods, courses and locations
alloc=np.array([0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,\
0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], dtype=np.int64)
# Number of students enrolled in each course
enrol = np.array([ 60, 60, 60, 40, 40, 110, 120, 50, 60, 55, 50, \
55, 40, 64, 72, 50, 50, 55, 55], dtype=np.float64)
# Capacity of each location (classroom)
capac = np.array([ 60, 60, 120, 60, 80, 60, 60, 65], dtype=np.float64)
# Total costs of using each location
costs = np.array([ 9017.12, 9017.12, 12050.24, 9017.12, 9413.68, 9017.12, \
9017.12, 9188.96 ])
# Estimated cost of each location by period and student
ecost = np.repeat(np.array([[costs[i]*pow(enrol[j]*5,-1) for j in range(19)] for i in range(8)]), 5)
# The model construction
m = GEKKO(remote=True)
# Constant arrays
x = np.empty((19,5))
y = np.empty((8,19,5))
N = np.empty((19))
C = np.empty((8))
Ec = np.empty((8,19,5))
Ecy = np.empty((8,19,5))
Alt = np.empty((8,19,5))
for k in range(5):
for j in range(19):
N[j] = enrol[j]
x[j,k] = sched[j,k]
for i in range(8):
C[i] = capac[i]
Ec[i,j,k] = ecost[k+j*5+i*19*5]
y[i,j,k] = alloc[k+j*5+i*19*5]
Ecy[i,j,k] = Ec[i,j,k]*y[i,j,k]
if sched[j,k]==1:
Alt[i,j,np.where(sched[j,:]==1)[0][0]]=-sched[j,k]*(1-sum(sched[j,:]))
if sum(sched[j,:])==2:
Alt[i,j,np.where(sched[j,:]==1)[0][1]]=sched[j,k]*(1-sum(sched[j,:]))
else:
Alt[i,j,k]=0
# Initialize the variable z with the initial value y:
# These commented approaches produce the error.
z = m.Array(m.Var,(8,19,5),lb=0,ub=1,integer=True)
for i in range(8):
for j in range(19):
for k in range(5):
z[i,j,k].value = y[i,j,k]
# nor
#z = m.Array(m.Var,(8,19,5),value=y,lb=0,ub=1,integer=True)
# Intermediate equations
Ecz = np.empty((8,19,5),dtype=object)
Altz = np.empty((8,19),dtype=object)
for i in range(8):
for j in range(19):
Altz[i,j]=m.Intermediate(m.sum(Alt[i,j,:]*z[i,j,:]))
for k in range(5):
Ecz[i,j,k]=m.Intermediate(Ec[i,j,k]*z[i,j,k])
# Constraints
m.Equation(m.sum(Ecz.flatten())<=sum(Ecy.flatten()))
for j in range(19):
for k in range(5):
m.Equation(m.sum(z[:,j,k])==x[j,k])
for i in range(8):
for k in range(5):
m.Equation(m.sum(z[i,:,k])==m.sum(y[i,:,k]))
for i in range(8):
for j in range(19):
m.Equation(m.sum((C[i]/N[j]-x[j,:])*z[i,j,:])>=0)
# Objective: to minimize the quantity of courses allocated in different locations
# Example: with the solution y, I have 12 courses in different locations in the periods
# print(sum([sum(Alt[i,j,:]*y[i,j,:])**2 for j in range(19) for i in range(8)])/2)
for i in range(8):
for j in range(19):
m.Obj(Altz[i,j]**2/2)
# Options and final results
m.options.IMODE=3
# Initialize with IPOPT
m.options.SOLVER=3
m.solve()
# Integer solution with APOPT
m.options.SOLVER=1
m.solver_options = ['minlp_gap_tol 1.0e-2',\
'minlp_maximum_iterations 10000',\
'minlp_max_iter_with_int_sol 500',\
'minlp_branch_method 1']
m.solve()
print(z)
print(m.options.OBJFCNVAL)

Finding an index in a list using 2 lists

Im trying to find the index of each 1 that is at the end of each group(sequence) of 1s. The output for the example below should be [17, 12, 9, 5, 1].
I can find the 1 at index 17 using the formula below but I also need to find the 1 at index 12. (i.e. it's the last instance of 1 in each sequence (or group) of 1s)
list = [1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0]
index_list1 = [i for i, v in enumerate(list) if v == 1]
index_list0 = [i for i, v in enumerate(list) if v == 0]
val1 = None
for i in index_list1[::-1]:
if i < index_list0[-1]:
val1 = i
break
else:
val1 = index_list1[-1]
if val1 is not None:
index1 = val1
You can simply use a conditional list comprehension:
my_list = [1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0]
results = [i for i, value in enumerate(my_list) if value == 1 and (my_list+[0])[i+1] != 1]
print(results)
this will print
[1, 5, 9, 12, 17]
The reason to append a [0] is to take care of cases where the original list ends with a 1.

Convert integer to pytorch tensor of binary bits

Given an number and an encoding length, how can I convert the number to its binary representation as a tensor?
Eg, given the number 6 and width 8, how can I obtain the tensor:
(0, 0, 0, 0, 0, 1, 1, 0)
def binary(x, bits):
mask = 2**torch.arange(bits).to(x.device, x.dtype)
return x.unsqueeze(-1).bitwise_and(mask).ne(0).byte()
If you wanna reverse the order of bits, use it with torch.arange(bits-1,-1,-1) instead.
Tiana's answer was a good one. BTW, to convert Tiana's 2-base result back to 10-base numbers, one can do like this:
import torch
import numpy as np
def dec2bin(x, bits):
# mask = 2 ** torch.arange(bits).to(x.device, x.dtype)
mask = 2 ** torch.arange(bits - 1, -1, -1).to(x.device, x.dtype)
return x.unsqueeze(-1).bitwise_and(mask).ne(0).float()
def bin2dec(b, bits):
mask = 2 ** torch.arange(bits - 1, -1, -1).to(b.device, b.dtype)
return torch.sum(mask * b, -1)
if __name__ == '__main__':
NUM_BITS = 7
d = torch.randint(0, 16, (3, 6))
b = dec2bin(d, NUM_BITS)
# print(d)
# print(b)
# print(b.shape)
# print("num of total bits: {}".format(np.prod(b.shape)))
d_rec = bin2dec(b, NUM_BITS)
# print(d_rec)
print(abs(d - d_rec).max()) # should be 0.
If the input is unsigned bytes and the output width is 8 bits:
>>> binary = np.unpackbits(np.array([0xaa, 0xf0], dtype=np.uint8))
>>> print(torch.tensor(binary))
tensor([1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0], dtype=torch.uint8)
Note that unpackbits() only operates with np.uint8.
def decimal_to_binary_tensor(value, width=0):
string = format(value, '0{}b'.format(width))
binary = [0 if c == '0' else 1 for c in string]
return torch.tensor(binary, dtype=torch.uint8)
Examples:
>>> print(decimal_to_binary_tensor(6, width=8))
tensor([0, 0, 0, 0, 0, 1, 1, 0], dtype=torch.uint8)
>>> print(decimal_to_binary_tensor(6))
tensor([1, 1, 0], dtype=torch.uint8)

calculate the sum of the intervals based on the binary array

I have two matrix:
Binary A = [[1, 0, 1, 0], [0, 0, 1, 0]];
Matrix of values B = [[100, 200, 300, 400], [400, 300, 100, 200]];
I want to calculate the sum of the intervals that are formed by the rows of the matrix A. For my exmpl. result will be follow: R = [[300, 0, 700, 0], [0, 0, 300, 0]] (generally, it is not necessary to set zeros [[300, 700], [300]] - it's right solution too)
I already wrote the code, but very very terrible (although it works correctly)
def find_halfsum(row1, row2):
i = 0
result = []
count = 0
for j in range(len(row1)):
if row1[j] == 1 and count == 0:
i = j
count += 1
elif row1[j] == 1:
count += 1
if count == 2:
if j == i + 1:
result.append(row2[i])
else:
result.append(sum(row2[i:j]))
i = j
count = 1
if j == len(row1) - 1:
result.append(sum(row2[i:j + 1]))
return result
Someone knows beautiful solutions (which will be faster)(preferably with the help of a numpy)?
Thanks
Not familiar with python, but I don't think you need that many lines
define halfSum(matrixA, matrixB):
sum = 0;
for i in range(len(matrixA)):
if matrixA[i] == 1:
sum += matrixB[i]
return sum;
You can use numpy.add.reduceat:
>>> A = np.array([[1, 0, 1, 0], [0, 0, 1, 0]])
>>> B = np.array([[100, 200, 300, 400], [400, 300, 100, 200]])
>>>
>>> [np.add.reduceat(b, np.flatnonzero(a)) for a, b in zip(A, B)]
[array([300, 700]), array([300])]

calculation of variance function equation

I have an error in this code as I want to calculate the variance between the values in the(x1) and (x2) list. any recommendation?!
def my_var(L):
s = 0
t = 0
u = 0
for i in range(0, len(L)):
s += L[i]
t = s/len(L)
u += ((L[i]-t)*(L[i]-t))
return u / len(L)
x1 = [1, 3, 4, -3, 8]
x2 = [1, -4, 7, 2]
v1 = my_var(x1)
v2 = my_var(x2)
print(v1)
print(v2)
You're doing many things incorrectly based on how I learned prob and stats. You need to calculate the average (mean) and then sum each value subtracted by the mean, squared. Then finally take that numerator and divide by 1 less than the sample size (n-1).
def my_var(L):
mean = float(sum(L) / Len(L))
numerator = 0
for i in range(0, len(L)):
numerator += (L[i]-mean)**2
return numerator / (len(L) - 1)
x1 = [1, 3, 4, -3, 8]
x2 = [1, -4, 7, 2]
v1 = my_var(x1)
v2 = my_var(x2)
print(v1)
print(v2)
Without using sum:
def my_var(L):
my_sum = 0
mean = 0
numerator = 0
for i in range(0, len(L)):
my_sum += L[i]
mean = float(my_sum / len(L))
for i in range(0, len(L)):
numerator += (L[i]-mean)**2
return numerator / (len(L) - 1)
x1 = [1, 3, 4, -3, 8]
x2 = [1, -4, 7, 2]
v1 = my_var(x1)
v2 = my_var(x2)
print(v1)
print(v2)
Try numpy.
import numpy as np
x1 = [1, 3, 4, -3, 8]
x2 = [1, -4, 7, 2]
v1 = np.var(x1)
v2 = np.var(x2)
Thank you #billy_ferguson. I have modified your code and it works. Execuse me, I am still an amateur but could you replace float and sum function and use simpler arithmetic operators as len(L) and += in this line mean = float(sum(L) / len(L))
def my_var(L):
mean = 0
numerator = 0
for i in range(0, len(L)):
mean = float(sum(L) / len(L))
numerator += (L[i]-mean)**2
return numerator / len(L)
x1 = [1, 3, 4, -3, 8]
x2 = [1, -4, 7, 2]
v1 = my_var(x1)
v2 = my_var(x2)
print(v1)
print(v2)

Resources