Using Cumulative function for Rectangular Placement - constraint-programming

I have a rectangular placement problem. What I want is to place rectangles of size x by y into another rectangle without overlapping. What I want in the end is the starting point of each rectange.
I made this part OF code for it, the logic was that it would cumulatively check for x and y axis along the height and width of the function. However, when I run this, it works for a few instances but not for others. So I posted one of the specific instances for which it gives repeat points here to ask what the issue is and what changes can be made.
Thank you
constraint cumulative(start, x, y, height);
constraint cumulative(starty, y, x, width);

It should work if you add the diffn constraint which constraint the boxes to be non overlapping, i.e.
include(globals.mzn);
....
constraint diffn(start,starty,x,y);
...
See https://www.minizinc.org/doc-2.4.3/en/lib-globals.html?highlight=diffn for more about diffn.
One of the 10752 solutions is:
15 15
10
1: 3 3 0 9
2: 3 4 12 0
3: 3 5 12 10
4: 3 6 12 4
5: 3 7 9 8
6: 3 8 9 0
7: 3 9 0 0
8: 3 12 3 0
9: 3 15 6 0
10: 6 3 0 12
I checked on paper that this is a proper solution, i.e. no overlapping and all cells in the 15x15 box are covered.

Cumulative will only check the resource usage in it's single dimension (which is useful and can give good pruning sometimes), it does not ensure the no-overlaps property. The diffn global constraint is the canonical one to use for ensuring no-overlap.

Related

Naming a behavior in Excel

I have a dataset on height that looks like below.
Height Phase
0 A
2 A
3 A
4 P
4 P
3 D
2 D
1 D
0 D .
I want to create a second column called Phase as above that tells Ascent, Peak, or Descent at corresponding height. I tried to use the IF function as IF(HeiPh="A",B3>=B2,IF(HeiPh="P",4,"D")) . However i'm not getting the required result. I have a big dataset and there are height that is same for few times i.e. like 0 2 2 3 4 5 5 5 5 6 and so on
Try this:
=IF(A2=MAX(A:A),"P",IF(ROW(A2)<MATCH(MAX(A:A),A:A,0),"A","D"))
You can do this =IF(MAX($A$4:$A$13)=A4,"P",IFS(A5>=A4,"A",A5<A4,"D"))

slicing table into two parts and box it afterwards

I have a table like the following
0 1 2 3
4 5 6 7
8 9 10 11
and I want to make the following structure.
┌──────┬──┐
│0 1 2│ 3│
│4 5 6│ 7│
│8 9 10│11│
└──────┴──┘
Could anyone please help me?
And in J there is always another way!
]a=. i. 3 4
0 1 2 3
4 5 6 7
8 9 10 11
('' ;1 0 0 1) <;.1 a
┌──────┬──┐
│0 1 2│ 3│
│4 5 6│ 7│
│8 9 10│11│
└──────┴──┘
This uses the dyadic cut conjunction (;.) with the general form of x u ;. n y
y is the argument that we would like to partition, x specifies where the partitions are to be put, n is positive if we would like the frets (the partition positions) included in the result and a value of 1 means that we work from left to right, and u is the verb that we would like to apply to the partition.
One tricky point:
x is ('';1 0 0 1) because we want the entire first dimension of the array (rows) after which the 1's indicate the partition start. In this case we take all the rows and make the first partition the first 3 columns, and the final 1 makes the last partition its own column.
There is much going on in this solution, and that allows it to be used in many different ways, depending on the needs of the programmer.
The title of your question ("slicing table into two parts and box it afterwards") suggests that the example you sketch may not reflect what you want to learn.
My impression is that you think of your resulting noun as a two-axis table boxed into two sections. The main problem with that interpretation is that boxes divide their contents very thoroughly. It takes special effort to make the numbers in your second box look like they've been trimmed from the structure in the first box. Such effort is rarely worthwhile.
If it is natural to need to take the 3 7 11 and remove it as a unit from the structure in which it occurs, there is an advantage to making it a row of the table, rather than a column. A 2-axis table is always a list of 1-axis lists. If your problem is a matter of segregating items, this orientation of the atoms makes it simpler to do.
Putting this into practice, here we deal with rows instead of columns:
aa=: |:i.3 4
aa
0 4 8
1 5 9
2 6 10
3 7 11
(}: ; {:) aa
+------+------+
|0 4 8|3 7 11|
|1 5 9| |
|2 6 10| |
+------+------+
The program, in parentheses, can be read literally as "curtail link tail". This is the sort of program I'd expect from the title of your question.
Part of effective J programming is orienting the data (nouns) so that they are more readily manipulated by the programs (verbs).
Here is one way:
]a=: i. 3 4
0 1 2 3
4 5 6 7
8 9 10 11
3 ({."1 ; }."1) a
┌──────┬──┐
│0 1 2│ 3│
│4 5 6│ 7│
│8 9 10│11│
└──────┴──┘
In other words "take the first 3 items in each row of a and Link (;) with the result of dropping the first 3 items in each row of a"
Other methods and/or structures may be more appropriate depending on the exact use case.

Open boxes with a custom padding value in J

Unboxing or opening boxes with different sizes causes padding with 0 for numerals and a space with literals:
v=.1 4 8 ; 2 6 4 ; 6 8 4 5; 7 8 9; 6 3 7 4 9
>v
1 4 8 0 0
2 6 4 0 0
6 8 4 5 0
7 8 9 0 0
6 3 7 4 9
The fit (!.) conjunction is usually the thing to use for these things, but
>!. _1 v
Is not supported and throws a domain error.
I've got this, but with very large arrays it's not very fast:
(>./ # every y) {.!. _1 every y
Is there an efficient way to define the padding value for opening boxes?
Setting
f =: 3 :'(>./ # every y) {.!. _1 every y'
g =: _1&paddedOpen
and (in the same spirit as your f):
h =: 3 : '((>./# &> y)&($!._1))#> y'
I get the following performances for time and space:
(100&(6!:2) ,: 7!:2) &.> 'f L';'g L';'h L'
┌─────────┬─────────┬─────────┐
│ 0.045602│0.0832403│0.0388146│
│4.72538e6│1.76356e7│4.72538e6│
└─────────┴─────────┴─────────┘
where L is a large array:
L =. (<#(+i.)/)"1 ? 50000 2 $ 10
You can slightly improve f by making it terse; for example:
f =: ] {.!._1&>~ >./#:(#&>)
I don't think that there is much room for more improvements.
My guess is that doing the padding directly will be the path to efficiency, especially if the need is restricted to a specific structure of data (as perhaps suggested by your example.) This solution has not been subjected to performance analysis, but it shows one way to do the padding yourself.
Here I'm making the assumption that the task involves always going from boxed lists to a table, and that the data is always numeric. Additional assert. statements may be worth adding to qualify that the right argument is as expected.
v=.1 4 8 ; 2 6 4 ; 6 8 4 5; 7 8 9; 6 3 7 4 9 NB. example data
paddedOpen=: dyad define
assert. 0 = # $ x
Lengths=. #&> y
PadTo=. >./ Lengths
Padding=. x #~&.> PadTo - Lengths
y ,&> Padding
)
_1 paddedOpen v
1 4 8 _1 _1
2 6 4 _1 _1
6 8 4 5 _1
7 8 9 _1 _1
6 3 7 4 9
It is only important to first pad with a customized value when the default value cannot be used as an intermediary. If the default value can be used in passing, it will be faster to let the default padding occur then replace all default values with the preferred value. From the nature of your question I assume the default value has meaning in the main domain, so simple replacement won't serve.
Please leave comments informing us of the relative performance of different techniques, or at least whether one does or does not prove fast enough for your purposes.

Force array instead of matrix in J for "i."

The i. primitive produces a list of integers:
i. 10
0 1 2 3 4 5 6 7 8 9
If I want to produce several short lists in a row, I do this:
;i."0 each [ 2 3 4
0 1 0 1 2 0 1 2 3
(the result I want)
Boxing (that each) is a crutch here, because without it, i."0 produces a matrix.
i."0 [ 2 3 4
0 1 0 0
0 1 2 0
0 1 2 3
(the result I don't want)
Is there a better way to not have i."0 format the output to a matrix, but an array?
No, I believe you can't do any better than your current solution. There is no way for i."0 to return a vector.
The "0 adverb forces i. to accept scalars, and i. returns vectors. i. has no way of knowing that your input was a vector rather than a scalar. According to The J primer the result shape is the concatenation of the frame of the argument and the result.
The shortest "box-less" solution I've found so far is
(*#$"0~#&,i."0) 2 3 4
which is still longer than just using ;i. each 2 3 4

Converting string to numeric [duplicate]

This question already has answers here:
How to convert a factor to integer\numeric without loss of information?
(12 answers)
Closed 6 years ago.
I've imported a test file and tried to make a histogram
pichman <- read.csv(file="picman.txt", header=TRUE, sep="/t")
hist <- as.numeric(pichman$WS)
However, I get different numbers from values in my dataset. Originally I thought that this because I had text, so I deleted the text:
table(pichman$WS)
ws <- pichman$WS[pichman$WS!="Down" & pichman$WS!="NoData"]
However, I am still getting very high numbers does anyone have an idea?
I suspect you are having a problem with factors. For example,
> x = factor(4:8)
> x
[1] 4 5 6 7 8
Levels: 4 5 6 7 8
> as.numeric(x)
[1] 1 2 3 4 5
> as.numeric(as.character(x))
[1] 4 5 6 7 8
Some comments:
You mention that your vector contains the characters "Down" and "NoData". What do expect/want as.numeric to do with these values?
In read.csv, try using the argument stringsAsFactors=FALSE
Are you sure it's sep="/t and not sep="\t"
Use the command head(pitchman) to check the first fews rows of your data
Also, it's very tricky to guess what your problem is when you don't provide data. A minimal working example is always preferable. For example, I can't run the command pichman <- read.csv(file="picman.txt", header=TRUE, sep="/t") since I don't have access to the data set.
As csgillespie said. stringsAsFactors is default on TRUE, which converts any text to a factor. So even after deleting the text, you still have a factor in your dataframe.
Now regarding the conversion, there's a more optimal way to do so. So I put it here as a reference :
> x <- factor(sample(4:8,10,replace=T))
> x
[1] 6 4 8 6 7 6 8 5 8 4
Levels: 4 5 6 7 8
> as.numeric(levels(x))[x]
[1] 6 4 8 6 7 6 8 5 8 4
To show it works.
The timings :
> x <- factor(sample(4:8,500000,replace=T))
> system.time(as.numeric(as.character(x)))
user system elapsed
0.11 0.00 0.11
> system.time(as.numeric(levels(x))[x])
user system elapsed
0 0 0
It's a big improvement, but not always a bottleneck. It gets important however if you have a big dataframe and a lot of columns to convert.

Resources