Tiling, how to use recursion in this case? - python

I am trying to make an algorithm that's able to solve a big tileset in the tiling problem. Right now it's able to find the correct Tiles to place based on their width and height, but there are some problems with making it properly recursive.
As you can see the idea is that after each tile that's placed the field will be separated in a Field Right and a Field Below. The algorithm will first try to fill the Field Right and as soon as that's done it has to start trying to fill Field Below.
The problem I have is that once Field Right is solved it has to be "send back" in a way (I think using recursion, though this is quite complex) to get it to go back a Tile and go to the Field Below that belongs to that Tile. I put the idea in some pseudocode to make it a bit easier to follow.
As you can see when FieldRightWidth is solved and the FieldBelowHeight is also solved I want to make it return to the previous tile to check if FieldBelow is solved. I think that's where I need to put some code to make this work, but after hours of Googling I still have no clue.
Pseudocode:
def Methods:
create global tileset
create local tileset (without duplicates)
If globaltiles is empty:
solved
end
else:
if fieldRightWidth == solved:
if fieldBelowHeight == solved:
return True???
#FIELD BELOW
else:
Search for Tile
Place Tile
Return Methods
#FIELD RIGHT
else:
Search for Tile
Place Tile
Return Methods
And a picture of what I want the algorithm to do:
And all of the code:
http://pastebin.com/8t4PeiZP
http://www.filedropper.com/tilingnew
I'm still a newbie in coding, so any advice or help is very appreciated!

alright, let's think the area you want to calculate are either square or rectangular,(not rotated), it start from minimum [x,y] and end maximum [x,y] right, like so:
SMaxX = 5
SMinX = 0
SMaxY = 5
SMinY = 0
or if you are familiar with 2D vector you can optimize it like so:
S = [5,5]
you might know about 2D vector, just in case i explain what is vector in 2D cartesian coordinate:
S = [5,5] means, if S start from [0,0], it will end at [5,5], (simpler right?)
so boxes also will be like so:
#space each box taking
box1 = [3,3]
box2 = [2,2]
box3 = [1,1]
and since there is priority for each box, let's say:
#priority of each box
box1 = 6
box2 = 4
box3 = 2
we can merge both space and priority into dictionary like so:
#Items
dic = {'box1':{'space':[3,3] , 'priority ':6},
'box2':{'space':[2,2] , 'priority ':4},
'box3':{'space':[1,1] , 'priority ':2}}
having priority and spaces of each boxes, looks like Knapsack problem algorithm.
if you are familiar about Knapsack problem algorithm, in a table we are trying to find the highest priority that fill the space perfectly, or in other word best possible way of fitting boxes. check this link1 and link2.
however Knapsack problem algorithm's chart is 1D solution, which if you do it, you will get 10, so Box1 and Box2. but since it's 2D and you have different height and width, so the standard 1D formula wont work, maybe you need to look into it see if you can come up with 2D formula or ask around see if someone done that before.
other than Knapsack problem algorithm you can try Flood fill algorithm which is a bit slower if you have huge area, but it work just like how Tetris game is.
you need to set standard size like 1x1, and then define the whole area with 1x1 data, and store it in a variable and set each True (Boolean), then with higher priority of boxes fill the area and set those 1x1 date to False, then really easy you can check if how many of the them are True and what area are they taking.
anyway, i'm trying to figure out the same thing in irregular shape, so that was all i found out, hope that help you.
(check this link as well, i got some useful answers.)
Edit: okay, if you use Tetris idea with defining the area and Knapsack problem algorithm in one axis and then base on standard Tetris area, use Knapsack problem algorithm again in other axis should work perfectly.

Related

Is there a chain constraint work around for CVXPY?

I keep encountering the same issue while trying to solve an Integer Programming Problem with cvxpy particularly with the constraints.
Some background on my problem and use case. I am trying to write a program that optimizes cut locations for 3D objects. The goal is to have as few interfaces as possible, but there is a constraint that each section can only have a certain maximum length. To visualize, you could picture a tree. If you cut at the bottom, you only have to make one large cut, but if the tree is larger than the maximum allowed length (if you needed to move it with a trailer of certain length for example) you would need to make another or several more cuts along the tree. As you go further up, it is likely that in addition to the main stem of the tree, you would need to cut some smaller, side branches along the same horizontal plane. I have written a program that output the number of interfaces (or cuts) needed at many evenly spaced horizontal planes along the height of an object. Now I am trying to pass that data to a new piece of code that will perform an Integer Programming optimization to determine the best location(s) to cut the tree if it treats each of the horizontal cutting planes as either active or inactive.
Below is my code:
#Create ideal configuration to solve for
config = cp.Variable(layer_split_number, boolean=True)
#Create objective
objective = sum(config*layer_islands_data[0])
problem = cp.Problem(cp.Minimize(objective),[layer_height_constraint(layer_split_number,layer_height,config) <= ChunkingParameters.max_reach_z])
#solve
problem.solve(solver = cp.GLPK_MI)
Layer Height Constraint function
def layer_height_constraint(layer_split_number,layer_height,config):
#create array of the absolute height (relative to ground) of each layer
layer_height_array = (np.array(range(1,layer_split_number+1))+1)*layer_height
#filter set inactive cuts to 0
active_heights = layer_height_array * config
#filter out all 0's
active_heights_trim = active_heights[active_heights != 0]
#insert top and bottom values
active_heights = np.append(active_heights,[(layer_split_number+1)*layer_height])
active_heights_trim = np.insert(active_heights,0,0)
#take the difference between active cuts to find distance
active_heights_diff = np.diff(active_heights_trim)
#find the maximum of those differences
max_height = max(active_heights_diff)
return(max_height)
With this setup, I get the following error:
Cannot evaluate the truth value of a constraint or chain constraints, e.g., 1 >= x >= 0.
I know that the two problem spots are using the python 'max' function in the last step and the step in the middle where I filter out the 0s in the array (because this introduces another equality of sorts. However, I can't really think of another way to solve this or setup the constraints differently. Is it possible to have cvxpy just accept a value into the constraint? My function is setup to just output a singular maximum distance value based on a given configuration, so to me it would make sense if I could just feed it the value being tried for the configuration (array of 0s and 1s representing inactive and active cuts respectively) for the current iteration and function would return the result which can then just be compared to the maximum allowed distance. However, I'm pretty sure IP solvers are a bit more complex than just running a bunch of iterations but I don't really know.
Any help on this or ideas would be greatly appreciated. I have tried an exhaustive search of the solution space, but when I have 10 or even 50+ cuts an exhaustive search is super inefficient. I would need to try 2^n combinations for n number of potential cuts.

Element selection by python script - Abaqus

I am trying to generalize part of script for element selection in pre-processing and using the element sets for use in post processing. I have searched and thought I did using one of the othr questions, but I having a different error. I ran this in Abaqus PDE 2017 version.
I have read these questions at SO :
1. Selecting multiple partitioned regions in ABAQUS with findAt for setting mesh controls
2. Abaqus: script to select elements on a surface
length=float(120)
height1=float(3)
height2=float(0.7)
th=float(45)
ElemSize=float(0.1)
dms=float(4)
crack_offset=float(8.5)
a = mdb.models['sdfdsf'].rootAssembly
RP_Cent = a.ReferencePoint(point=(length-th+crack+crack_offset,2*height1+height2,0))
a.features.changeKey(fromName='RP-1', toName='RP_Cent')
e1 = a.instances['Upper_Adh'].elements
Cent = e1.getByBoundingBox( length-th+crack+crack_offset-dms/2, 2*height1+height2-ElemSize, 0,
length-th+crack+crack_offset+dms/2, 2*height1+height2, 0 )
a.Set(elements=Cent, name='Centroid_Elements')
I had expected the created set to be of element type and have 10 elements, however the set created is of geometry type and ofcourse has no elements.
Error-screenshot
All help is appreciated.
From the code you show us it seems that your bounding box is of 0 height. That method returns elements that are within the bounding box. Try to make it thicker. Also try printing the size of Cent so you can diagnose if you got the right number of elements.
#UN4
Hi sorry for the late reply. The reason it is 0 height, its because I am working on a 2D model. Having said that I did try to change the height, I am still getting the same error.
Additionally printing Cent does not help. There is no additional response and the error persists.
Also could you let me know how to extract the x,y,z co-ordinates for a particular reference point in pre-processing.

how to do a selection of specific edges on duplicated objects in Maya?

I’m new to python, so I'm sorry if my question seems to be silly.
But, I'll be grateful if someone could help.
I'm writing a script in Maya Python.
I have a set of duplicated meshes. I need to select certain poly edges and convert them into curves.
I've managed to write the last part of converting the polyEdge to Curve, but struggling to write the wildcard selection.
I was thinking to write the following way:
list = [list of objects I want to get edges of]
for i in list:
pm.select()
Kind of like that,
But to be honest I don't know what I'm doing here.
I'd appreciate any help.
Thank you
here is an example
# list of your duplicates
myDuplicatedMeshes = ['pShpere1_dup']
# select your edges in the viewport for detecting which edges to transfer
edgeInputList = cmds.ls(sl=True)
# collect the edges ids
edgeIds = [i.split('.')[-1] for i in edgeInputList]
# loop into the duplicated
for dup in myDuplicatedMeshes:
# give the edge ids
targeted_edges = ['{}.{}'.format(dup, id) for id in edgeIds]
# convert to curve
curveBuilded = cmds.polyToCurve(targeted_edges, form=2, degree=3)

Hacking a closed source program to help me sort real life objects with python/screenshot/OCR

In my job,we are using a dedicated MS ACCESS program (let's call it XYZ)to help us in our work.
I cannot access source code/API of this program, but I want to write a python script to help me automate a sorting task (which is not implemented), that I'm telling you.
We take 12 random objects/tools/pieces which are identified by a barcode with a unique id (for example 50286,50285,50277,50280 ....), we shoot them with a barcode gun scanner and in the program XYZ we get this result.
before sorting
This is a screenshot of the pc at work, I added by hand the blue colored numbers to the right just for clarity, to explain to you what I'm trying to accomplish.
Remember we took these objects randomly, now we have to sort them.
They are sorted by program XYZ keeping in mind some important sorting stuff that it isn't important to know.
This script makes two screenshot, the first before sorting the list and the second after sorting the list.
After this sorting, my list looks like this.
after sorting
I want my script to output the numbers 3,12,11,9,8,7,10,6,4,5,1,2.
I thought this was a simple task because I already managed to get for example Element_#1_in_before_list
50826 before
and Element_#11_in_after_list,
50286 after
However I cannot tell the first item is now the eleventh element because the two pictures aren't similar due to random annoying noise blue/cyan pixels (Truetype?)
I tried OCR to recognize the characters, but sometimes it fails and it's too complicated.
I tried to convert to Black and White but noise pixels become sometimes black or white and the two images don't match perfectly (I came up with the solution to perform md5sum to tell if they are the same)
How can I solve the problem?
Maybe it's simple but i'm noob.
Help me surprise the XYZ developer!!
Have you tried matching in a non-exact way? You could match each image in list 1 to the image in list 2 with the lowest MSE.
def mse(imageA, imageB):
# the 'Mean Squared Error' between the two images is the
# sum of the squared difference between the two images;
# NOTE: the two images must have the same dimension
err = np.sum((imageA.astype("float") - imageB.astype("float")) ** 2)
err /= float(imageA.shape[0] * imageA.shape[1])
# return the MSE, the lower the error, the more "similar"
# the two images are
return err
Source for MSE function: http://www.pyimagesearch.com/2014/09/15/python-compare-two-images/

How do I numerically position a barcode in reportlab?

I have a bit of a specific case that I can't seem to figure out a solution to. I'm writing a shipping label template object in ReportLab for Python. I have the following code that creates a barcode as a drawing.
uspsBarcode = createBarcodeDrawing('USPS_4State', value=self.imbval, routing=self.zip4.replace('-',''))
print uspsBarcode.getBounds() # print out of position and scale
Using that code, I later add it to a shape group, and that shape group gets returned. So I need the barcode to be positioned relative to the object. I can't seem to find any way to pass positioning to this, even though I've dug through the inheritance. Though as you can see from the print, positioning is set somwhere.
Just for anyone else that runs across this issue. It turns out that if you put the barcode drawing in a shape group, the shape group container can be moved around numerically with the shift function.
uspsBarcode = shapes.Group()
bc = createBarcodeDrawing('USPS_4State', value=self.imbVal, routing=self.zip4.replace('-',''))
uspsBarcode.add(bc)
uspsBarcode.shift(self.x+(s*0.2), self.y)

Categories

Resources