Why is PyOpenGL rendering shapes that have been removed? - python
I am making an implementation of the marching cubes algorithm using PyQt5 and PyOpenGL. I have finally got it to march, draw points, and draw a mesh using the following code. The only issue is that when it cycles back, the meshes from the previous cycle are drawn. Even if the filter has changed, the original meshes are drawn.
What am I doing wrong?
cubes.py:
import sys
from PyQt5.QtWidgets import (
QApplication, QMainWindow, QSlider,
QOpenGLWidget, QLabel, QPushButton
)
from PyQt5.QtCore import Qt
from OpenGL.GL import (
glLoadIdentity, glTranslatef, glRotatef,
glClear, glBegin, glEnd,
glColor3fv, glVertex3fv,
GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT,
GL_QUADS, GL_LINES
)
from OpenGL.GLU import gluPerspective
from numerics import sin, cos, tan, avg, rnd
from classes import *
from lookup import table
import random, time
class mainWindow(QMainWindow): #Main class.
shapes = [] #place all instaces of shapes in this list in order to have them rendered.
dataPoints = []
zoomLevel = -10
rotateDegreeV = -90
rotateDegreeH = 0
marchActive = False
limit = -1
meshPoints = []
meshSectors = []
def keyPressEvent(self, event): #This is the keypress detector.
try:
key = event.key()
except:
key = -1
#print(key)
if key == 87:
self.rotateV(5)
elif key == 65:
self.rotateH(5)
elif key == 83:
self.rotateV(-5)
elif key == 68:
self.rotateH(-5)
elif key == 67:
self.zoom(1)
elif key == 88:
self.zoom(-1)
elif key == 77:
self.marchStep()
def __init__(self):
super(mainWindow, self).__init__()
self.currentStep = 0
self.width = 700 #Variables used for the setting of the size of everything
self.height = 600
self.setGeometry(0, 0, self.width + 50, self.height) #Set the window size
self.initData(3, 3, 3)
def setupUI(self):
self.openGLWidget = QOpenGLWidget(self) #Create the GLWidget
self.openGLWidget.setGeometry(0, 0, self.width, self.height)
self.openGLWidget.initializeGL()
self.openGLWidget.resizeGL(self.width, self.height) #Resize GL's knowledge of the window to match the physical size?
self.openGLWidget.paintGL = self.paintGL #override the default function with my own?
self.filterSlider = QSlider(Qt.Vertical, self)
self.filterSlider.setGeometry(self.width + 10, int(self.height / 2) - 100, 30, 200)
self.filterSlider.valueChanged[int].connect(self.filter)
self.limitDisplay = QLabel(self)
self.limitDisplay.setGeometry(self.width, int(self.height / 2) - 130, 50, 30)
self.limitDisplay.setAlignment(Qt.AlignCenter)
self.limitDisplay.setText('-1')
self.marchButton = QPushButton(self)
self.marchButton.setGeometry(self.width, int(self.height / 2) - 160, 50, 30)
self.marchButton.setText('March!')
self.marchButton.clicked.connect(self.marchStep)
def initData(self, sizeX, sizeY, sizeZ):
marchSizeX = sizeX - 1
marchSizeY = sizeY - 1
marchSizeZ = sizeZ - 1
xOff = -(sizeX / 2) + 0.5
yOff = -(sizeY / 2) + 0.5
zOff = -(sizeZ / 2) + 0.5
xMarchOff = -(marchSizeX / 2) + 0.5
yMarchOff = -(marchSizeY / 2) + 0.5
zMarchOff = -(marchSizeZ / 2) + 0.5
self.marchPoints = []
for z in range(marchSizeZ):
for y in range(marchSizeY):
for x in range(marchSizeX):
self.marchPoints.append((x + xMarchOff, y + yMarchOff ,z + zMarchOff))
for z in range(sizeZ):
for y in range(sizeY):
for x in range(sizeX):
val = self.generate(x + xOff, y + yOff, z + zOff)
dpColor = (0, (val + 1) / 2, (val + 1) / -2 + 1)
dpShape = cube((x + xOff, y + yOff, z + zOff), drawWires = False, drawFaces = True, color = dpColor)
dp = dataPoint((x + xOff, y + yOff, z + zOff), val, dpShape)
self.dataPoints.append(dp)
self.shapes.append(dpShape)
def paintGL(self):
#This function uses shape objects, such as cube() or meshSector(). Shape objects require the following:
#a list named 'vertices' - This list is a list of points, from which edges and faces are drawn.
#a list named 'wires' - This list is a list of tuples which refer to vertices, dictating where to draw wires.
#a list named 'facets' - This list is a list of tuples which refer to vertices, ditating where to draw facets.
#a bool named 'render' - This bool is used to dictate whether or not to draw the shape.
#a bool named 'drawWires' - This bool is used to dictate whether wires should be drawn.
#a bool named 'drawFaces' - This bool is used to dictate whether facets should be drawn.
glLoadIdentity()
gluPerspective(45, self.width / self.height, 0.1, 110.0) #set perspective?
glTranslatef(0, 0, self.zoomLevel) #I used -10 instead of -2 in the PyGame version.
glRotatef(self.rotateDegreeV, 1, 0, 0) #I used 2 instead of 1 in the PyGame version.
glRotatef(self.rotateDegreeH, 0, 0, 1)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
if len(self.shapes) != 0:
glBegin(GL_LINES)
for s in self.shapes:
glColor3fv(s.color)
if s.render and s.drawWires:
for w in s.wires:
for v in w:
glVertex3fv(s.vertices[v])
glEnd()
glBegin(GL_QUADS)
for s in self.shapes:
glColor3fv(s.color)
if s.render and s.drawFaces:
for f in s.facets:
for v in f:
glVertex3fv(s.vertices[v])
glEnd()
def marchStep(self):
print(self.currentStep)
if not self.marchActive: #initialize
marchAddr = len(self.shapes)
self.marchingCube = cube(size = 1)
self.shapes.append(self.marchingCube)
self.marchActive = True
self.currentStep = 0
if self.currentStep == len(self.marchPoints): #1 step after last
self.marchingCube.hide()
self.currentStep += 1
for mp in self.meshPoints:
mp.shape.hide()
self.meshPoints = []
self.openGLWidget.update()
return
if self.currentStep == len(self.marchPoints) + 1: #2 steps after last
#print('meshPoints: {}'.format(self.meshPoints))
for mp in self.meshPoints:
#print(mp.shape)
self.shapes.remove(mp.shape)
self.meshPoints.clear()
for shape in self.shapes:
if shape in self.meshSectors:
self.shapes.remove(shape)
self.meshSectors = []
self.currentStep = -1
self.openGLWidget.update()
return
if self.currentStep == -1: #1 step before first
self.marchingCube.hide()
self.currentStep += 1
print('self.meshPoints: {}\nself.meshSectors: {}\nself.shapes: {}'.format(self.meshPoints, self.meshSectors, self.shapes))
self.openGLWidget.update()
return
self.marchingCube.show()
p = self.marchPoints[self.currentStep]
x, y, z = p
self.marchingCube.move((x, y, z))
points = []
for i in range(8):
#print(self.marchingCube.vertices[i])
point = self.getDataPointByLocation(self.marchingCube.vertices[i])
points.append(point)
#place meshpoints and highlight the active ones.
MPs = []
for pair in self.marchingCube.wires:
pointA = points[pair[0]]
pointB = points[pair[1]]
#print('pointA.value: {} pointB.value: {} limit: {}'.formatpointA.value, pointB.value, self.limit)
xA, yA, zA = pointA.location
xB, yB, zB = pointB.location
valA = (pointA.value + 1) / 2
valB = (pointB.value + 1) / 2
xC = float(avg([xA, xB]))
yC = float(avg([yA, yB]))
zC = float(avg([zA, zB]))
mp = meshPoint()
mp.place(xC, yC, zC)
mp.setShape(cube(size = 0.05, drawWires = False, drawFaces = True, color = (1, 0, 0)))
mp.shape.move((xC, yC, zC))
self.shapes.append(mp.shape)
self.meshPoints.append(mp)
MPs.append(mp)
if (pointA.value < self.limit and pointB.value > self.limit) or (pointA.value > self.limit and pointB.value < self.limit):
mp.setActive(True)
else:
mp.setActive(False)
activeConfig = 0
sector = meshSector()
self.meshSectors.append(sector)
self.shapes.append(sector)
for i in range(8):
if points[i].value > self.limit:
activeConfig += int(2 ** i)
print('Configuration number: {}'.format(activeConfig))
if activeConfig > 127:
activeConfig = 255 - activeConfig
print('Configuration number: {}'.format(activeConfig))
config = table[activeConfig]
print('Configuration: {}'.format(config))
print('number of points: {}'.format(len(MPs)))
for data in config:
a, b, c = data
locA = MPs[a].location
locB = MPs[b].location
locC = MPs[c].location
sector.addFacet((locA, locB, locC))
print('stepping')
self.currentStep += 1
self.rotateH(0)
def zoom(self, value):
self.zoomLevel += value
self.openGLWidget.update()
def rotateV(self, value):
self.rotateDegreeV += value
self.openGLWidget.update()
def rotateH(self, value):
self.rotateDegreeH += value
self.openGLWidget.update()
def filter(self, value):
self.limit = rnd((value / 49.5) -1, -2)
for d in self.dataPoints:
if d.value < self.limit:
d.shape.hide()
else:
d.shape.show()
self.limitDisplay.setText(str(self.limit))
self.openGLWidget.update()
def getDataPointByLocation(self, coord):
x, y, z = coord
#print(self.dataPoints)
#print('requested coordinates: {}'.format(coord))
for dp in self.dataPoints:
#print('dataPoint.location: {}'.format(dp.location))
if dp.location == (x, y, z):
return dp
return False
def generate2(self, xIn, yIn, zIn):
if xIn == 0 and yIn == 0 and zIn == 0:
return 0.5
return -0.5
def generate(self, xIn, yIn, zIn): #Function which produces semi-random values based on the supplied coordinates.
i = -int(xIn * yIn * (10 + zIn))
j = int(xIn * yIn * (10 + zIn))
if i < j:
mixer = random.randint(i, j + 1)
else:
mixer = random.randint(j, i + 1)
a = avg([sin(cos(xIn)), tan(tan(yIn)), cos(tan(zIn))])
out = mixer * a
while out > 10:
out -= 5
while out < -10:
out += 5
return float(out / 10)
#classes------------------------------------------------------------
app = QApplication([])
window = mainWindow()
window.setupUI()
window.show()
sys.exit(app.exec_())
classes.py:
class cube():
render = True
def __init__(self, location = (0, 0, 0), size = 0.1, drawWires = True, drawFaces = False, color = (1, 1, 1)):
self.location = location
self.size = size
self.drawWires = drawWires
self.drawFaces = drawFaces
self.color = color
self.compute()
def compute(self):
x, y, z = self.location
s = self.size / 2
self.vertices = [ #8 corner points calculated in reference to the supplied center point
(-s + x, s + y, -s + z), (s + x, s + y, -s + z),
(s + x, -s + y, -s + z), (-s + x, -s + y, -s + z),
(-s + x, s + y, s + z), (s + x, s + y, s + z),
(s + x, -s + y, s + z), (-s + x, -s + y, s + z)
]
self.wires = [ #12 tuples referencing the corner points
(0,1), (0,3), (0,4), (2,1), (2,3), (2,6),
(7,3), (7,4), (7,6), (5,1), (5,4), (5,6)
]
self.facets = [ #6 tuples referencing the corner points
(0, 1, 2, 3), (0, 1, 6, 5), (0, 3, 7, 4),
(6, 5, 1, 2), (6, 7, 4, 5), (6, 7, 3, 2)
]
def show(self):
self.render = True
def hide(self):
self.render = False
def move(self, location):
self.location = location
self.compute()
def recolor(self, col):
if type(col) is tuple:
self.color = col
class dataPoint():
def __init__(self, location = (0, 0, 0), value = 0, shape = None):
self.location = location
self.value = value
self.shape = shape
def place(self, x, y, z):
self.location = (x, y, z)
def set(self, val):
self.value = val
def setShape(self, shape):
self.shape = shape
class meshPoint():
active = False
def __init__(self, location = (0, 0, 0), shape = None):
self.location = location
self.shape = shape
if self.shape != None:
#print('{} is hiding shape'.format(self))
self.shape.hide()
def place(self, x, y, z):
self.location = (x, y, z)
def setShape(self, shape):
self.shape = shape
if self.shape != None:
#print('{} is hiding shape'.format(self))
self.shape.hide()
def setActive(self, state):
self.active = state
if self.active and self.shape != None:
#print('{} is showing shape'.format(self))
self.shape.show()
elif self.shape != None:
#print('{} is hiding shape'.format(self))
self.shape.hide()
class meshSector():
vertices = []
facets = []
wires = []
render = True
def __init__(self, drawWires = True, drawFaces = False, color = (1, 1, 1)):
self.drawWires = drawWires
self.drawFaces = drawFaces
self.color = color
def addFacet(self, coords): #takes a tuple of three location tuples.
addr = len(self.vertices)
for c in coords:
self.vertices.append(c)
self.facets.append((addr, addr + 1, addr + 2))
self.wires.append((addr, addr + 1))
self.wires.append((addr, addr + 2))
self.wires.append((addr + 1, addr + 2))
lookup.py:
table = [ #config number is line number - 2
[], #config 0
[(0, 1, 2)],
[(0, 3, 9)],
[(1, 2, 3), (2, 3, 9)],
[(3, 4, 5)],
[(0, 1, 2), (3, 4, 5)],
[(0, 4, 5), (0, 5, 9)],
[(1, 2, 9), (1, 4, 9), (4, 5, 9)],
[(1, 4, 6)],
[(0, 2, 4), (0, 2, 6)],
[(0, 3, 9), (1, 4, 6)], #config 10
[(2, 3, 4), (2, 3, 9), (2, 4, 6)],
[(1, 3, 5), (1, 5, 6)],
[(0, 2, 6), (0, 3, 6), (3, 5, 6)],
[(0, 1, 5), (0, 5, 9), (1, 5, 6)],
[(2, 5, 6), (2, 5, 9)],
[(2, 7, 10)],
[(0, 1, 7), (0, 7, 10)],
[(2, 7, 10), (0, 3, 9)],
[(1, 3, 9), (1, 7, 10), (1, 9, 10)],
[(2, 6, 10), (3, 4, 5)], #config 20
[(0, 1, 7), (0, 1, 10), (3, 4, 5)],
[(0, 4, 5), (0, 5, 9), (2, 7, 10)],
[(1, 7, 10), (1, 9, 10), (1, 5, 9), (1, 4, 5)],
[(1, 4, 6), (2, 7, 10)],
[(0, 4, 6), (0, 6, 7), (0, 7, 10)],
[(0, 3, 9), (1, 4, 6), (2, 7, 10)],
[(6, 7, 10), (3, 9, 10), (3, 4, 6)],
[(1, 3, 5), (1, 5, 6), (2, 7, 10)],
[(0, 7, 10), (0, 6, 7), (0, 5, 6), (0, 3, 5)],
[(0, 1, 2), (5, 6, 7), (5, 7, 10), (5, 9, 10)], #config 30
[(5, 6, 7), (5, 7, 10), (5, 9, 10)],
[(9, 10, 11)],
[(0, 1, 2), (9, 10, 11)],
[(0, 3, 10), (3, 10, 11)],
[(1, 2, 3), (2, 3, 10), (3, 10, 11)],
[(3, 4, 5), (9, 10, 11)],
[(0, 1, 2), (3, 4, 5), (9, 10, 11)],
[(0, 4, 5), (0, 5, 11), (0, 10, 11)],
[(2, 10, 11), (4, 5, 11), (1, 2, 4), (2, 4, 11)],
[(1, 4, 6), (9, 10, 11)], #config 40
[(0, 2, 4), (2, 4, 6), (9, 10, 11)],
[(0, 3, 10), (3, 10, 11), (1, 4, 6)],
[(2, 4, 6), (2, 3, 4), (2, 3, 11), (2, 10, 11)],
[(1, 3, 5), (1, 5, 6), (9, 10, 11)],
[(3, 5, 6), (0, 3, 6), (0, 2, 6), (9, 10, 11)],
[(0, 1, 6), (0, 5, 6), (0, 5, 11), (0, 10, 11)],
[(5, 6, 11), (6, 10, 11), (2, 6, 10)],
[(2, 7, 9), (7, 9, 11)],
[(0, 1, 7), (0, 7, 9), (7, 9, 11)],
[(0, 3, 11), (0, 2, 11), (2, 7, 11)], #config 50
[(1, 3, 11), (1, 7, 11)],
[(2, 9, 11), (1, 7, 11), (3, 4, 5)],
[(7, 9, 11), (0, 7, 9), (0, 1, 7), (3, 4, 5)],
[(2, 7, 11), (0, 2, 11), (0, 4, 11), (0, 5, 11)],
[(1, 4, 7), (1, 5, 7), (5, 7, 11)],
[(2, 7, 9), (7, 9, 11), (1, 4, 6)],
[(4, 6, 7), (0, 4, 7), (0, 7, 11), (0, 9, 11)],
[(1, 4, 6), (2, 7, 11), (0, 2, 11), (0, 3, 11)],
[(3, 7, 11), (3, 6, 7), (3, 4, 6)],
[(2, 7, 11), (2, 9, 11), (1, 3, 5), (1, 5, 6)], #config 60
[(0, 9, 11), (0, 7, 11), (0, 6, 7), (0, 3, 6), (3, 5, 6)],
[(2, 7, 11), (0, 2, 11), (0, 5, 11), (0, 1, 5), (1, 5, 6)],
[(5, 6, 7), (5, 7, 11)],
[(5, 8, 11)],
[(0, 1, 2), (5, 8, 11)],
[(0, 3, 9), (5, 8, 11)],
[(1, 2, 3), (2, 3, 9), (5, 8, 11)],
[(3, 4, 8), (3, 8, 11)],
[(3, 4, 8), (3, 8, 11), (0, 1, 2)],
[(0, 9, 11), (0, 8, 11), (0, 4, 8)], #config 70
[(2, 10, 11), (2, 3, 11), (2, 3, 4), (2, 4, 6)],
[(3, 4, 5), (9, 10, 11)],
[(1, 3, 5), (1, 5, 6), (9, 10, 11)],
[(0, 1, 2), (3, 4 ,5), (9, 10, 11)],
[(2, 3, 9), (2, 3, 4), (2, 4, 6), (5, 8, 11)],
[(3, 1, 6), (3, 6, 8), (3, 8, 11)],
[(7, 9, 10), (5, 7, 9), (1, 5, 7), (1, 4, 5)],
[(6, 7, 10), (3, 9, 10), (3, 4, 6), (3, 6, 10)],
[(6, 8, 11), (6, 9, 11), (2, 6, 9)],
[(2, 7, 10), (5, 8, 11)], #config 80
[(0, 1, 7), (0, 7, 10), (5, 8, 11)],
[(0, 3, 9), (2, 7, 10), (5, 8, 11)],
[(1, 7, 10), (1, 9, 10), (1, 3, 9), (5, 8, 11)],
[(3, 4, 8), (3, 8, 11), (2, 7, 10)],
[(0, 1, 7), (0, 7, 10), (3, 4, 8), (3, 8, 11)],
[(4, 8, 11), (4, 9, 11), (0, 4, 9), (2, 7, 10)],
[(9, 10, 11), (1, 4, 7), (4, 7, 8)],
[(1, 4, 6), (2, 7, 10), (5, 8, 11)],
[(0, 4, 6), (0, 6, 7), (0, 7, 10), (5, 8, 11)],
[(0, 3, 9), (1, 4, 6), (5, 8, 11), (2, 7, 10)], #config 90
[(3, 4, 6), (6, 7, 10), (3, 9, 10), (5, 8, 11)],
[(1, 3, 6), (3, 6, 8), (3, 8, 11), (2, 7, 10)],
[(0, 3, 10), (3, 10, 11), (6, 7, 8)],
[(0, 1, 2), (6, 7, 8), (9, 10, 11)],
[(6, 7, 8), (9, 10, 11)],
[(5, 8, 9), (8, 9, 10)],
[(0, 1, 2), (5, 8, 9), (8, 9, 10)],
[(0, 8, 10), (0, 3, 8), (3, 5, 8)],
[(2, 8, 10), (1, 2, 8), (1, 5, 8), (1, 3, 5)],
[(3, 4, 8), (3, 8, 9), (8, 9, 10)], #config 100
[(0, 1, 2), (3, 4, 8), (3, 8, 9), (8, 9, 10)],
[(0, 4, 8), (0, 8, 10)],
[(1, 4, 8), (1, 2, 8), (2, 8, 10)],
[(1, 4, 6), (5, 8, 9), (8, 9, 10)],
[(0, 4, 6), (0, 2, 6), (5, 8, 9), (8, 9, 10)],
[(1, 4, 6), (0, 8, 10), (0, 3, 5), (1, 4, 6)],
[(3, 4, 5), (2, 6, 8), (2, 8, 10)],
[(1, 6, 8), (1, 3, 8), (3, 8, 10), (3, 9, 10)],
[(0, 3, 9), (2, 6, 8), (2, 8, 10)],
[(0, 1, 10), (1, 6, 10), (6, 8, 10)], #config 110
[(2, 6, 8), (2, 8, 10)],
[(2, 5, 9), (2, 5, 8), (2, 7, 8)],
[(0, 5, 9), (0, 5, 8), (0, 1, 8), (1, 7, 8)],
[(0, 3, 5), (5, 7, 8), (0, 2, 7), (0, 5, 7)],
[(1, 3, 5), (1, 5, 8), (1, 7, 8)],
[(3, 4, 9), (4, 7, 9), (2, 7, 9), (4, 7, 8)],
[(0, 3, 9), (1, 4, 8), (1, 7, 8)],
[(0, 4, 8), (0, 7, 8), (0, 2, 7)],
[(1, 4, 7), (4, 7, 8)],
[(2, 5, 9), (1, 2, 4), (2, 4, 5), (6, 7, 8)], #config 120
[(6, 7, 8), (0, 4, 5), (0, 5, 9)],
[(0, 3, 5), (5, 7, 8), (0, 2, 7), (0, 5, 7), (1, 4, 6)],
[(3, 5, 8), (5, 7, 8), (3, 4, 7), (4, 6, 7)],
[(1, 2, 3), (2, 3, 9), (6, 7, 8)],
[(0, 3, 9), (6, 7, 8)],
[(0, 1, 2), (6, 7, 8)],
[(6, 7, 8)]
]
run.bat:
#echo off
cls
cubes.py
This is likely the largest coding project I have ever done.
I found the problem. For some reason, whenever I instantiated a new meshSector, the values from the last instance carried over. I do not understand why this happens, but my fix was to empty the variables in the __init__ function.
class meshSector():
vertices = []
facets = []
wires = []
render = True
def __init__(self, drawWires = True, drawFaces = False, color = (1, 1, 1)):
self.drawWires = drawWires
self.drawFaces = drawFaces
self.color = color
#the next four lines prevent data carry-over.
self.vertices = []
self.facets = []
self.wires = []
self.render = True
def addFacet(self, coords): #takes a tuple of three location tuples.
addr = len(self.vertices)
for c in coords:
self.vertices.append(c)
self.facets.append((addr, addr + 1, addr + 2))
self.wires.append((addr, addr + 1))
self.wires.append((addr, addr + 2))
self.wires.append((addr + 1, addr + 2))
As a pleasant side effect, this fix multiplied the performance exponentially, eliminating the lag that I had been seeing. This, I understand. Each meshSector was rendering all the wires in the meshsectors before it. Effectively, 2 sectors was 3, 3 sectors was 6, 4 sectors was 10, etc.
Related
How to set the floating point precision in Scipy?
I am using Scipy to solve the following linear programming problem. However, I have to set the precision for the decision variable r to a maximum of double-precision floating-point numbers. Can someone tell me how I can set the precision, please? I checked the linprog documentation but I don't see such an option. The implemented code: # Objective function def objective(): return [time[e] for e in edge] # setting the bounds for the decision variables def bounds(): return [(0, V[e[0]]) for e in edge] # generating the constraints def constraints(): b = [] A = [] const = [] const_2 = [] for i in region: for e in edge: if e[0] != e[1] and (e[0]==i or e[1]==i): if (e[0]==i): const.append(1) const_2.append(1) else: const.append(-1) const_2.append(0) else: const.append(0) const_2.append(0) # const 1 \sum (r_{ij} - r_{ji}) \leq V_i - D_i A.append(const) b.append(V[i] - D[i]) # const 2 \sum r_{ij} <= V_i A.append(const_2) b.append(V[i]) const = [] const_2 = [] return A, b obj_fn = objective() a_up, b_up = constraints() res = linprog(obj_fn, A_ub=a_up, b_ub=b_up, bounds=bounds()) The minimum required data to run the code: V = {0: 1, 1: 71, 2: 6, 3: 0, 4: 34, 5: 51, 6: 88, 7: 61, 8: 0, 9: 0, 10: 43, 11: 62, 12: 144, 13: 36, 14: 0, 15: 12} D = {0: 94, 1: 16, 2: 38, 3: 6, 4: 66, 5: 22, 6: 134, 7: 8, 8: 46, 9: 6, 10: 3, 11: 36, 12: 39, 13: 26, 14: 40, 15: 22} edge = [(0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), (0, 8), (0, 9), (0, 10), (0, 11), (0, 12), (0, 13), (0, 14), (0, 15), (1, 0), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8), (1, 9), (1, 10), (1, 11), (1, 12), (1, 13), (1, 14), (1, 15), (2, 0), (2, 1), (2, 3), (2, 4), (2, 5), (2, 6), (2, 7), (2, 8), (2, 9), (2, 10), (2, 11), (2, 12), (2, 13), (2, 14), (2, 15), (3, 0), (3, 1), (3, 2), (3, 4), (3, 5), (3, 6), (3, 7), (3, 8), (3, 9), (3, 10), (3, 11), (3, 12), (3, 13), (3, 14), (3, 15), (4, 0), (4, 1), (4, 2), (4, 3), (4, 5), (4, 6), (4, 7), (4, 8), (4, 9), (4, 10), (4, 11), (4, 12), (4, 13), (4, 14), (4, 15), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4), (5, 6), (5, 7), (5, 8), (5, 9), (5, 10), (5, 11), (5, 12), (5, 13), (5, 14), (5, 15), (6, 0), (6, 1), (6, 2), (6, 3), (6, 4), (6, 5), (6, 7), (6, 8), (6, 9), (6, 10), (6, 11), (6, 12), (6, 13), (6, 14), (6, 15), (7, 0), (7, 1), (7, 2), (7, 3), (7, 4), (7, 5), (7, 6), (7, 8), (7, 9), (7, 10), (7, 11), (7, 12), (7, 13), (7, 14), (7, 15), (8, 0), (8, 1), (8, 2), (8, 3), (8, 4), (8, 5), (8, 6), (8, 7), (8, 9), (8, 10), (8, 11), (8, 12), (8, 13), (8, 14), (8, 15), (9, 0), (9, 1), (9, 2), (9, 3), (9, 4), (9, 5), (9, 6), (9, 7), (9, 8), (9, 10), (9, 11), (9, 12), (9, 13), (9, 14), (9, 15), (10, 0), (10, 1), (10, 2), (10, 3), (10, 4), (10, 5), (10, 6), (10, 7), (10, 8), (10, 9), (10, 11), (10, 12), (10, 13), (10, 14), (10, 15), (11, 0), (11, 1), (11, 2), (11, 3), (11, 4), (11, 5), (11, 6), (11, 7), (11, 8), (11, 9), (11, 10), (11, 12), (11, 13), (11, 14), (11, 15), (12, 0), (12, 1), (12, 2), (12, 3), (12, 4), (12, 5), (12, 6), (12, 7), (12, 8), (12, 9), (12, 10), (12, 11), (12, 13), (12, 14), (12, 15), (13, 0), (13, 1), (13, 2), (13, 3), (13, 4), (13, 5), (13, 6), (13, 7), (13, 8), (13, 9), (13, 10), (13, 11), (13, 12), (13, 14), (13, 15), (14, 0), (14, 1), (14, 2), (14, 3), (14, 4), (14, 5), (14, 6), (14, 7), (14, 8), (14, 9), (14, 10), (14, 11), (14, 12), (14, 13), (14, 15), (15, 0), (15, 1), (15, 2), (15, 3), (15, 4), (15, 5), (15, 6), (15, 7), (15, 8), (15, 9), (15, 10), (15, 11), (15, 12), (15, 13), (15, 14)] region = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] time = {(0, 1): 1, (0, 2): 1, (0, 3): 2, (0, 4): 2, (0, 5): 2, (0, 6): 2, (0, 7): 3, (0, 8): 3, (0, 9): 3, (0, 10): 3, (0, 11): 4, (0, 12): 4, (0, 13): 3, (0, 14): 4, (0, 15): 5, (1, 0): 1, (1, 2): 1, (1, 3): 1, (1, 4): 2, (1, 5): 2, (1, 6): 2, (1, 7): 3, (1, 8): 3, (1, 9): 3, (1, 10): 3, (1, 11): 4, (1, 12): 4, (1, 13): 3, (1, 14): 4, (1, 15): 4, (2, 0): 2, (2, 1): 1, (2, 3): 1, (2, 4): 3, (2, 5): 2, (2, 6): 2, (2, 7): 2, (2, 8): 4, (2, 9): 3, (2, 10): 3, (2, 11): 3, (2, 12): 5, (2, 13): 4, (2, 14): 4, (2, 15): 4, (3, 0): 2, (3, 1): 2, (3, 2): 1, (3, 4): 3, (3, 5): 3, (3, 6): 2, (3, 7): 2, (3, 8): 4, (3, 9): 4, (3, 10): 3, (3, 11): 3, (3, 12): 5, (3, 13): 5, (3, 14): 5, (3, 15): 4, (4, 0): 2, (4, 1): 2, (4, 2): 2, (4, 3): 3, (4, 5): 1, (4, 6): 2, (4, 7): 2, (4, 8): 2, (4, 9): 2, (4, 10): 2, (4, 11): 3, (4, 12): 2, (4, 13): 3, (4, 14): 3, (4, 15): 4, (5, 0): 2, (5, 1): 2, (5, 2): 2, (5, 3): 2, (5, 4): 1, (5, 6): 2, (5, 7): 2, (5, 8): 2, (5, 9): 2, (5, 10): 2, (5, 11): 3, (5, 12): 3, (5, 13): 2, (5, 14): 3, (5, 15): 3, (6, 0): 2, (6, 1): 2, (6, 2): 2, (6, 3): 2, (6, 4): 2, (6, 5): 1, (6, 7): 1, (6, 8): 3, (6, 9): 2, (6, 10): 2, (6, 11): 2, (6, 12): 3, (6, 13): 3, (6, 14): 3, (6, 15): 3, (7, 0): 3, (7, 1): 3, (7, 2): 2, (7, 3): 2, (7, 4): 2, (7, 5): 2, (7, 6): 2, (7, 8): 3, (7, 9): 3, (7, 10): 2, (7, 11): 2, (7, 12): 4, (7, 13): 4, (7, 14): 3, (7, 15): 3, (8, 0): 3, (8, 1): 3, (8, 2): 3, (8, 3): 3, (8, 4): 1, (8, 5): 2, (8, 6): 3, (8, 7): 3, (8, 9): 2, (8, 10): 2, (8, 11): 2, (8, 12): 1, (8, 13): 2, (8, 14): 2, (8, 15): 3, (9, 0): 3, (9, 1): 3, (9, 2): 3, (9, 3): 4, (9, 4): 2, (9, 5): 2, (9, 6): 2, (9, 7): 3, (9, 8): 2, (9, 10): 2, (9, 11): 2, (9, 12): 2, (9, 13): 1, (9, 14): 2, (9, 15): 2, (10, 0): 4, (10, 1): 3, (10, 2): 3, (10, 3): 3, (10, 4): 3, (10, 5): 2, (10, 6): 2, (10, 7): 2, (10, 8): 2, (10, 9): 2, (10, 11): 2, (10, 12): 2, (10, 13): 2, (10, 14): 2, (10, 15): 2, (11, 0): 4, (11, 1): 4, (11, 2): 3, (11, 3): 2, (11, 4): 3, (11, 5): 3, (11, 6): 2, (11, 7): 2, (11, 8): 2, (11, 9): 2, (11, 10): 2, (11, 12): 2, (11, 13): 3, (11, 14): 2, (11, 15): 1, (12, 0): 3, (12, 1): 4, (12, 2): 4, (12, 3): 4, (12, 4): 2, (12, 5): 3, (12, 6): 3, (12, 7): 4, (12, 8): 1, (12, 9): 2, (12, 10): 2, (12, 11): 3, (12, 13): 1, (12, 14): 2, (12, 15): 2, (13, 0): 5, (13, 1): 3, (13, 2): 4, (13, 3): 5, (13, 4): 3, (13, 5): 3, (13, 6): 3, (13, 7): 3, (13, 8): 2, (13, 9): 2, (13, 10): 2, (13, 11): 2, (13, 12): 2, (13, 14): 1, (13, 15): 2, (14, 0): 5, (14, 1): 4, (14, 2): 4, (14, 3): 4, (14, 4): 3, (14, 5): 3, (14, 6): 3, (14, 7): 3, (14, 8): 2, (14, 9): 2, (14, 10): 2, (14, 11): 2, (14, 12): 2, (14, 13): 1, (14, 15): 1, (15, 0): 5, (15, 1): 5, (15, 2): 4, (15, 3): 4, (15, 4): 4, (15, 5): 3, (15, 6): 3, (15, 7): 3, (15, 8): 3, (15, 9): 2, (15, 10): 2, (15, 11): 2, (15, 12): 2, (15, 13): 2, (15, 14): 2} Update 1 In the code that I am working on, there are two linear programs whose results are fed to each other in a loop-like fashion Linprog 1 -> process result -> Linprog 2 -> process result -> Linprog 1 -> ..... I am analyzing the process result block but because I am not the original developer of the code, I haven't figured out if the problem is here. The program was written by using CPLEX (IPL) as the solver. When Scipy is used, the results produced by these Linprograms cause each other to be infeasible: The problem is infeasible. (HiGHS Status 8: model_status is Infeasible; primal_status is Basic). Using the same dataset, the CPLEX code works fine. When Scipy is used, it shows the warning solve Ill-conditioned matrix detected. Result is not guaranteed to be accurate. or sometimes terminates with infeasible results. The individual Scipy codes work correctly (with CPLEX results as input) When I round the results using round() the frequency of warning and infeasible results messages reduces.
All possible combinations of columns and rows in pandas DataFrame
I have this Dataframe that I want to get all possible combinations of this dataframe across both rows and columns. A_Points B_Points C_Points 0 1 1 3 5 4 9 2 4 For example a combination as follows Points = 0 + 5 + 4, or 9 + 1 + 1. Is there a builtin tool for such problem? This is what I tried, but it did not give the desired output. > import itertools > combined_dataframe = pd.DataFrame({'{}{}'.format(a, b): possible_feature_characteristicpoints[a] - possible_feature_characteristicpoints[b] for a, b in itertools.combinations(possible_feature_characteristicpoints.columns, 2)})
Use itertools.product and sum: from itertools import product out = list(map(sum, product(*df.to_numpy().tolist()))) Output: [12, 5, 7, 14, 7, 9, 13, 6, 8, 13, 6, 8, 15, 8, 10, 14, 7, 9, 13, 6, 8, 15, 8, 10, 14, 7, 9] Intermediate: list(product(*df.to_numpy().tolist())) Output: [(0, 3, 9), (0, 3, 2), (0, 3, 4), (0, 5, 9), (0, 5, 2), (0, 5, 4), ... (1, 4, 2), (1, 4, 4)]
Another way with list comprehension, import pandas as pd data = { "A_Points": [0,3,9], "B_Points": [1,5,2], "C_Points": [1,4,4], } df = pd.DataFrame(data) result = [ (i, j, k) for i in df.A_Points for j in df.B_Points for k in df.C_Points ] print(result) Output: [(0, 1, 1), (0, 1, 4), (0, 1, 4), (0, 5, 1), (0, 5, 4), (0, 5, 4), (0, 2, 1), (0, 2, 4), (0, 2, 4), (3, 1, 1), (3, 1, 4), (3, 1, 4), (3, 5, 1), (3, 5, 4), (3, 5, 4), (3, 2, 1), (3, 2, 4), (3, 2, 4), (9, 1, 1), (9, 1, 4), (9, 1, 4), (9, 5, 1), (9, 5, 4), (9, 5, 4), (9, 2, 1), (9, 2, 4), (9, 2, 4)]
Checking array for a value
I have an array as below. testgrid = [ [9, 1, 2, 4, 3, 8, 7, 5, 6], [9, 1, 2, 4, 3, 8, 7, 5, 6], [9, 1, 2, 4, 3, 8, 7, 5, 6], [9, 1, 2, 4, 3, 8, 7, 5, 6], [9, 1, 2, 4, 3, 8, 7, 5, 6], [9, 1, 2, 4, 3, 8, 7, 5, 6], [9, 1, 2, 4, 3, 8, 7, 5, 6], [9, 1, 2, 4, 3, 8, 7, 5, 6], [9, 1, 2, 4, 3, 8, 7, 5, 6]] On passing the testgrid into the following function it should return all indexes that do not contain a value of zero currently it returns (0, 0). I would expect all indexes to be returned on this grid. It seems to be checking the indexes rather than the value stored at that index. I am a noob so probably am missing something obvious here. def not_empty_location(grid): # checks if current location is empty and assign location not empty for i in range(9): for j in range(9): if grid[i][j] != 0: return (i, j) return None
Use yield instead of return: def not_empty_location(grid): # checks if current location is empty and assign location not empty for i in range(9): for j in range(9): if grid[i][j] != 0: yield (i, j) return None This would return all the values as a generator which can then simply be converted into a list. Output: [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), (0, 8), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8), (2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (2, 5), (2, 6), (2, 7), (2, 8), (3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5), (3, 6), (3, 7), (3, 8), (4, 0), (4, 1), (4, 2), (4, 3), (4, 4), (4, 5), (4, 6), (4, 7), (4, 8), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4), (5, 5), (5, 6), (5, 7), (5, 8), (6, 0), (6, 1), (6, 2), (6, 3), (6, 4), (6, 5), (6, 6), (6, 7), (6, 8), (7, 0), (7, 1), (7, 2), (7, 3), (7, 4), (7, 5), (7, 6), (7, 7), (7, 8), (8, 0), (8, 1), (8, 2), (8, 3), (8, 4), (8, 5), (8, 6), (8, 7), (8, 8)]
try by storing the index tuples in a list and return def not_empty_location(grid): result = [] # list to store the index # checks if current location is empty and assign location not empty for i in range(9): for j in range(9): if grid[i][j] != 0: result.append( (i, j) ) # In your code you are returning at your very first success of getting != 0 return result
Python: Create route from Arcs
I am working on a capacitated vehicle routing problem and have found an optimal solution with the following set of arcs on my graph active: [(0, 1), (0, 4), (0, 5), (0, 6), (0, 7), (0, 10), (1, 0), (2, 13), (3, 9), (4, 12), (5, 0), (6, 14), (7, 8), (8, 0), (9, 0), (10, 11), (11, 0), (12, 3), (13, 0), (14, 2)] the list is called arcsDelivery. I would like to restructure this list to come to my found routes stored in the list routesdelivery: [[0,1,0],[0,4,12,3,9,0],[0,5,0],[0,6,14,2,13,0],[0,7,8,0],[0,10,11,0]] However, I have been struggeling to do so, anyone with some helpful tips?
Here is a way to do it (considering that the arcsdelivery list is sorted in ascending order based on the first element of each tuple): def findTuple(elem): for t in arcsDelivery: if t[0]==elem: return t return None arcsDelivery = [(0, 1), (0, 4), (0, 5), (0, 6), (0, 7), (0, 10), (1, 0), (2, 13), (3, 9), (4, 12), (5, 0), (6, 14), (7, 8), (8, 0), (9, 0), (10, 11), (11, 0), (12, 3), (13, 0), (14, 2)] routesDelivery = [] startRoutes = len(list(filter(lambda elem: elem[0]==0, arcsDelivery))) for i in range(startRoutes): tempList = [] currentTuple = arcsDelivery[i] tempList.append(currentTuple[0]) tempList.append(currentTuple[1]) while True: if currentTuple[1]==0: break else: nextTuple = findTuple(currentTuple[1]) currentTuple = nextTuple tempList.append(currentTuple[1]) routesDelivery.append(tempList) print(routesDelivery) Output: [[0, 1, 0], [0, 4, 12, 3, 9, 0], [0, 5, 0], [0, 6, 14, 2, 13, 0], [0, 7, 8, 0], [0, 10, 11, 0]]
Python: mathematical operation of Combination on list of numbers
let's say I have a list of numbers: my_list = range(0,1001,50) I want to make every single possible combination of threes (threes = [a,b,c]) based on my_list, for example: [0,50,100], [0,50,150], ..., [0,50,1000], [0,100,150], ... Threes don't have to be stored in a list, it's just an example of data structure. And after that I want to put every single threes' values (a,b,c) to some sort of formula. How could I make that? I'm kinda beginner in Python and haven't experienced with more complicated mathematical structures yet. Or is it possible to do on some kind of loop...? Any help would be appreciated.
You can use combinations : my_list = range(0,1000,50) from itertools import combinations combinations(my_list,3) From the doc : combinations() p, r r-length tuples, in sorted order, no repeated elements It creates an iterable. Converted to a list, it looks like : [(0, 50, 100), (0, 50, 150), (0, 50, 200), (0, 50, 250), (0, 50, 300), ...
What you want is the wonderful itertools module, that has combinations() in it: >>> import itertools >>> list(itertools.combinations(range(10), 3)) [(0, 1, 2), (0, 1, 3), (0, 1, 4), (0, 1, 5), (0, 1, 6), (0, 1, 7), (0, 1, 8), (0 , 1, 9), (0, 2, 3), (0, 2, 4), (0, 2, 5), (0, 2, 6), (0, 2, 7), (0, 2, 8), (0, 2 , 9), (0, 3, 4), (0, 3, 5), (0, 3, 6), (0, 3, 7), (0, 3, 8), (0, 3, 9), (0, 4, 5 ), (0, 4, 6), (0, 4, 7), (0, 4, 8), (0, 4, 9), (0, 5, 6), (0, 5, 7), (0, 5, 8), (0, 5, 9), (0, 6, 7), (0, 6, 8), (0, 6, 9), (0, 7, 8), (0, 7, 9), (0, 8, 9), (1, 2, 3), (1, 2, 4), (1, 2, 5), (1, 2, 6), (1, 2, 7), (1, 2, 8), (1, 2, 9), (1, 3, 4), (1, 3, 5), (1, 3, 6), (1, 3, 7), (1, 3, 8), (1, 3, 9), (1, 4, 5), (1, 4, 6) , (1, 4, 7), (1, 4, 8), (1, 4, 9), (1, 5, 6), (1, 5, 7), (1, 5, 8), (1, 5, 9), ( 1, 6, 7), (1, 6, 8), (1, 6, 9), (1, 7, 8), (1, 7, 9), (1, 8, 9), (2, 3, 4), (2, 3, 5), (2, 3, 6), (2, 3, 7), (2, 3, 8), (2, 3, 9), (2, 4, 5), (2, 4, 6), (2, 4, 7), (2, 4, 8), (2, 4, 9), (2, 5, 6), (2, 5, 7), (2, 5, 8), (2, 5, 9), (2, 6, 7), (2, 6, 8), (2, 6, 9), (2, 7, 8), (2, 7, 9), (2, 8, 9), (3, 4, 5), (3, 4, 6), (3 , 4, 7), (3, 4, 8), (3, 4, 9), (3, 5, 6), (3, 5, 7), (3, 5, 8), (3, 5, 9), (3, 6 , 7), (3, 6, 8), (3, 6, 9), (3, 7, 8), (3, 7, 9), (3, 8, 9), (4, 5, 6), (4, 5, 7 ), (4, 5, 8), (4, 5, 9), (4, 6, 7), (4, 6, 8), (4, 6, 9), (4, 7, 8), (4, 7, 9), (4, 8, 9), (5, 6, 7), (5, 6, 8), (5, 6, 9), (5, 7, 8), (5, 7, 9), (5, 8, 9), (6, 7, 8), (6, 7, 9), (6, 8, 9), (7, 8, 9)] Then you can feed that to your function: def f(a,b,c): return a * b * c print [f(*x) for x in itertools.combinations(range(10), 3)]