Two arrays A,B are given of same length (not sorted).
Make pairs of their entries (one from A and one from B), such that average difference in the entries (|a1-b1|,|a2-b2|,....) is minimum.
I have thought of sorting them and then making pairs of same index entries.
Will this work ?
If yes, how ? else some other solution with proof.
I'm assuming that this problem can be formally stated as follows: given two n-element vectors A and B, find permutations A' of A and B' of B so as to minimize the L1 norm of A' - B'.
If so, then your proposed algorithm is correct. Suppose that we have a solution with an inversion, that is, a1 matched with b2 and a2 matched with b1 such that a1 < a2 and b1 < b2. The contribution of these pairs to the L1 norm is
|a1 - b2| + |a2 - b1| >= |a1 - b1| + |a2 - b2|,
where the inequality follows from an inelegant case argument that we defer for the moment. Accordingly, by rematching a1 with b1 and a2 with b2, we decrease the number of inversions without increasing the cost. It follows by induction that the matching with no inversions is optimal.
Case argument: symmetrically (by interchanging A and B), there are three possible interleavings.
(1) a1 <= a2 <= b1 <= b2
(2) a1 <= b1 <= a2 <= b2
(3) a1 <= b1 <= b2 <= a2
In case (1),
|a1 - b2| + |a2 - b1| = b2 - a1 + b1 - a2
= b1 - a1 + b2 - a2
= |a1 - b1| + |a2 - b2|.
In case (2),
|a1 - b2| + |a2 - b1| = b2 - a1 + a2 - b1
>= b2 - a1 + a2 - b1 - 2 (a2 - b1)
= b1 - a1 + b2 - a2
= |a1 - b1| + |a2 - b2|.
In case (3),
|a1 - b2| + |a2 - b1| = b2 - a1 + a2 - b1
>= b2 - a1 + a2 - b1 - 2 (b2 - b1)
= b1 - a1 + a2 - b2
= |a1 - b1| + |a2 - b2|.
Edit: misread the question, the below describes why the sum of differences is maximized when you sort the two lists in opposite order
Here is another way to see that the algorithm you described gives you the optimal solution. Note that when you write out |x - y| it equals either x - y or y - x. Thus,
|a_1 - b_1| + |a_2 - b_2| + ... + |a_n - b_n|
can be thought of as summing the numbers a_1, ..., a_n, b_1, ... , b_n, except that exactly n of them have their sign flipped. Clearly, this is maximized when you choose to negate the n smallest numbers out of a_1, ..., a_n, b_1, ..., b_n. And indeed, that is exactly what your algorithm does.
Related
I am trying to solve a Pacman problem using PDDL. The main thing I need to do is soft code the power duration without using functions or fluents. It returns no error but somehow I feel like it inits Powerlose(n2, n0). I never init Powerlose(n2, n0) or change Powerlose in the effect. But the initial value it gives to c is n2. So what's wrong? Thanks in advance.
You can check the problem and domain through this link:
http://editor.planning.domains/#edit_session=bD5G0tIIl1vyWDf
I tried to use exists statement instead of Powerlose(cPlus1, c) on line 34 of the domain file, it does not work. It still init c with n2. I am so confused.
Here is my domain file:
(define
(domain pacman_hard)
(:requirements :strips :typing :equality :adl)
(:types
pos int
)
(:predicates
(PacmanAt ?p - pos)
(GhostAt ?p - pos)
(FoodAt ?p - pos)
(CapsuleAt ?p - pos)
(PowerCurr ?n - int)
(PowerLose ?n1 ?n2 - int)
(PowerGain ?n1 ?n2 - int)
(Adjacent ?p1 ?p2 - pos)
)
(:action move
:parameters (?posCurr ?posNext - pos ?cPlus1 ?c ?MaxPower - int)
:precondition (and
(and
; check if there is any food left,
; which guarantees all ghosts are eaten before last food
(exists (?p - pos) (FoodAt ?p))
(PacmanAt ?posCurr)
(Adjacent ?posCurr ?posNext)
(PowerCurr ?cPlus1)
(PowerGain ?cPlus1 ?MaxPower)
)
(or
(PowerLose ?cPlus1 ?c) ;powered
(not (GhostAt ?posNext))
)
)
:effect (and
(PacmanAt ?posNext)
(not (PacmanAt ?posCurr))
; update power status accordingly/with priority
; first reduce the time of power
(when (PowerLose ?cPlus1 ?c); could minus 1
(and
(not (PowerCurr ?cPlus1))
(PowerCurr ?c)
(not (GhostAt ?posNext))
)
)
; refresh the power time if in next pos its a capsule
(when (CapsuleAt ?posNext)
(and
(not (PowerCurr ?cPlus1))
(not (PowerCurr ?c))
(PowerCurr ?MaxPower)
)
)
(not (FoodAt ?posNext))
(not (CapsuleAt ?posNext))
)
)
)
The problem file:
problem map
| 1 | 2 | 3 | 4 | 5 |
-|---|--- ---|---|---|
a| P | _ | _ | G | F |
b| _ | C | _ | G | C |
|---|---|---|---|---|
(define
(problem pacman-level-1)
(:domain pacman_hard)
(:objects
a1 a2 a3 a4 a5 b1 b2 b3 b4 b5 - pos
n0 n1 n2 - int
)
(:init
(PacmanAt a1)
(GhostAt a4)
(GhostAt b4)
(CapsuleAt b2)
(CapsuleAt b5)
(FoodAt a5)
(PowerCurr n0)
(PowerLose n1 n0)
(PowerLose n2 n1)
(PowerGain n0 n2)
(PowerGain n1 n2)
(PowerGain n2 n2)
(Adjacent a1 a2)
(Adjacent a1 b1)
(Adjacent b1 a1)
(Adjacent b1 b2)
(Adjacent a2 a1)
(Adjacent a2 b2)
(Adjacent a2 a3)
(Adjacent b2 a2)
(Adjacent b2 b1)
(Adjacent b2 b3)
(Adjacent a3 a2)
(Adjacent a3 b3)
(Adjacent a3 a4)
(Adjacent b3 b2)
(Adjacent b3 a3)
(Adjacent b3 b4)
(Adjacent a4 a3)
(Adjacent a4 b4)
(Adjacent a4 a5)
(Adjacent b4 b3)
(Adjacent b4 a4)
(Adjacent b4 b5)
(Adjacent a5 a4)
(Adjacent a5 b5)
(Adjacent b5 b4)
(Adjacent b5 a5)
)
(:goal
; this would guarantee the pacman has eaten all food and ghosts.
(forall (?p - pos)
(and (not (FoodAt ?p)) (not (GhostAt ?p)))
)
)
)
The plan it returns:
(move a1 b1 n0 n2 n2)
(move b1 b2 n0 n2 n2)
(move b2 b3 n2 n2 n2)
(move b3 b4 n2 n1 n2)
(move b4 a4 n1 n0 n2)
(move a4 a5 n0 n2 n2)
The correct plan:
(move a1 b1) (move b1 b2) (move b2 b3) (move b3 b4) (move b4 b5) (move b5 b4) (move b4 a4) (move a4 a5)
As an aside, it's always useful to specify what planner (and it's configuration) that you're using.
I loaded your problem into the online editor:
http://editor.planning.domains/#read_session=A1Dk7n8YAz
It gave a similar plan (at least start of plan) when I tried solving. I'd suggest doing the same (Solve button is at the top), and looking at the plan. The right side shows the grounded action. First thing to notice is that your Powerlose precondition is part of an or clause, and the other part is certainly satisfied (i.e., (ghostat b1) is false). So that aspect of the precondition is satisfied.
Hopefully, this clears up what might be going on!
I have two (1d) arrays, a long one A (size m) and a shorter one B (size n). I want to update the long array by adding each element of the short array at a particular index.
Schematically the arrays are structured like this,
A = [a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 ... am]
B = [ b1 b2 b3 b4 b5 b6 b7 b8 b9 ... bn ]
and I want to update A by adding the corresponding elements of B.
The most straightforward way is to have some index array indarray (same size as B) which tells us which index of A corresponds to B(i):
Option 1
do i = 1, size(B)
A(indarray(i)) = A(indarray(i)) + B(i)
end do
However, there is an organization to this problem which I feel should allow for some better performance:
There should be no barrier to doing this in vectorized way. I.e. the updates for each i are independent and can be done in any order.
There is no need to jump back and forth in array A. The machine should know to just loop once through the arrays only updating A where necessary.
There should be no need for any temporary arrays.
What is the best way to do this in Fortran?
Option 2
One way might be using PACK, UNPACK, and a boolean mask M (same size as A) that serves the same purpose as indarray:
A = [a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 ... am]
B = [ b1 b2 b3 b4 b5 b6 b7 b8 b9 ... bn ]
M = [. T T T . T T . . T . T T T T . ]
(where T represents .true. and . is .false.).
And the code would just be
A = UNPACK(PACK(A, M) + B, M, A)
This is very concise and maybe satisfies (1) and sort of (2) (seems to do two loops through the arrays instead of just one). But I fear the machine will be creating a few temporary arrays in the process which seems unnecessary.
Option 3
What about using where with UNPACK?
where (M)
A =A + UNPACK(B, M, 0.0d0)
end where
This seems about the same as option 2 (two loops and maybe creates temporary arrays). It also has to fill the M=.false. elements of the UNPACK'd array with 0's which seems like a total waste.
Option 4
In my situation the .true. elements of the mask will usually be in continuous blocks (i.e. a few true's in a row then a bunch of false's, then another block of true's, etc). Maybe this could lead to something similar to option 1. Let's say there's K of these .true. blocks. I would need an array indstart (of size K) giving the index into A of the start of each true block, and an index blocksize (size K) with the length of the true block.
j = 1
do i = 1, size(indstart)
i0 = indstart(i)
i1 = i0 + blocksize(i) - 1
A(i0:i1) = A(i0:i1) + B(j:j+blocksize(i)-1)
j = j + blocksize(i)
end do
At least this only does one loop through. This code seems more explicit about the fact that there's no jumping back and forth within the arrays. But I don't think the compiler will be able to figure that out (blocksize could have negative values for example). So this option probably won't result in a vectorized result.
--
Any thoughts on a nice way to do this? In my situation the arrays indarray, M, indstart, and blocksize would be created once but the adding operation must be done many times for different arrays A and B (though these arrays will have constant sizes). The where statement seems like it could be relevant.
I am confused to convert a 2D array into 1D array.
I want to write a neighboring 8 elements for "a11" (which is at (1,1)) in the form of width ,rows and cols format without using for loop.
|<--Width--->|
cols
____________
| a00 a01 a02
rows | a10 a11 a12
| a20 a21 a22
I tried in this way :
a00 = pSrc[(cols-1)+ (rows - 1)*width];
a02 = pSrc[(cols-1)+ (rows + 1)*width];
a10 = pSrc[cols+ (rows -1)*width];
a12 = pSrc[cols+ (rows +1)*width];
a20 = pSrc[(cols+1)+ (rows - 1)*width];
a22 = pSrc[(cols+1)+ (rows + 1)*width];
a01 = pSrc[(cols-1)+ (rows )*width];
a21 = pSrc[(cols+1)+ (rows )*width];
But I think I did some mistake .Can any one help me in that .
It isn't clear how pSrc is defined since you don't show its definition. However, your code is consistent with it being declared as a 1D array:
int pSrc[9]; // Or a larger dimension
Your code can sensibly be written so it is more uniformly laid out:
a00 = pSrc[(cols-1) + (rows-1)*width];
a01 = pSrc[(cols-1) + (rows+0)*width];
a02 = pSrc[(cols-1) + (rows+1)*width];
a10 = pSrc[(cols+0) + (rows-1)*width];
a12 = pSrc[(cols+0) + (rows+1)*width];
a20 = pSrc[(cols+1) + (rows-1)*width];
a21 = pSrc[(cols+1) + (rows+0)*width];
a22 = pSrc[(cols+1) + (rows+1)*width];
The +0 will be ignored by even the most simple-minded compiler, almost certainly without even turning the optimizer on, but it makes the code much easier to read. I also resequenced the entries so the row above are listed first, then the row in the middle, and then the bottom row. Again, it makes it easier to see the patterns.
It is then clear that you are using 'rows' and 'cols' backwards. You actually need:
a00 = pSrc[(cols-1) + (rows-1)*width];
a01 = pSrc[(cols+0) + (rows-1)*width];
a02 = pSrc[(cols+1) + (rows-1)*width];
a10 = pSrc[(cols-1) + (rows+0)*width];
a12 = pSrc[(cols+1) + (rows+0)*width];
a20 = pSrc[(cols-1) + (rows+1)*width];
a21 = pSrc[(cols+0) + (rows+1)*width];
a22 = pSrc[(cols+1) + (rows+1)*width];
Ok, Say, I got a table that have 3 columns: c1, c2, c3
C1 - C2 - C3
A2 - B2 - N2
K1 - B2 - N1
K1 - B3 - N1
L1 - A2 - C1
Ok, when users search for any combination of A1, A2, A3, B1, B2, ... then the system can be able to pick the rows with the closet match (it means as long as the word appears in 1 column, the system will pick it, the more words appear in more columns the closer it matches) & order them according to the closest match
Ex1: a user searches for "K1 A2 C1 N1", the system will show:
K1 - B2 - N1
K1 - B3 - N1
A2 - B2 - N2
L1 - A2 - C1
Ex2: a user searches for "K1 A2 C1 N2 B2", the system will show:
A2 - B2 - N2
L1 - A2 - C1
K1 - B2 - N1
K1 - B3 - N1
My solution is to split the search string into separate words & then search each of these words against the columns in the table. But I am not sure it is the optimum query since the DB have to search in many loops.
So if u r expert in DB, then what is the best query in this scenario?
select c1
,c2
,c3
,case when c1 in ('K1','A2','C1','N1') then 1 else 0 end
+case when c2 in ('K1','A2','C1','N1') then 1 else 0 end
+case when c3 in ('K1','A2','C1','N1') then 1 else 0 end as sortweight
from theTable
where c1 in ('K1','A2','C1','N1')
or c2 in ('K1','A2','C1','N1')
or c3 in ('K1','A2','C1','N1') order by sortweight desc
,c1
,c2
,c3
Someone from other forum suggested the above query
I need to generate possible ranking of all possible ranking of n documents. I understand that the permutations of an array {1, 2,..., n} will give me the set of all possible rankings.
My problem is a bit more complex as each document could take one of 2 possible types. Therefore, in all there are n!*2n possible rankings.
For instance, let us say I have 3 documents a, b, and c. Then possible rankings are the following:
a1 b1 c1
a1 b1 c2
a1 b2 c1
a1 b2 c2
a2 b1 c1
a2 b1 c2
a2 b2 c1
a2 b2 c2
a1 c1 b1
a1 c1 b2
a1 c2 b1
a1 c2 b2
a2 c1 b1
a2 c1 b2
a2 c2 b1
a2 c2 b2
b1 a1 c1
b1 a1 c2
b1 a2 c1
b1 a2 c2
b2 a1 c1
b2 a1 c2
...
What would be an elegant way to generate such rankings?
It's a kind of cross product between the permutations of B={a,b, ...} and the k-combinations of T{1,2} where k is the the number of elements in B. Say we take a p from Perm(B), e.g. p=(b,c,a) and a c from 3-Comb(T), e.g. c=(2,1,1) then we would merge p and c into (b2,c1,a1).
I don't really know if it's elegant but I would choose an algorithm to generate sequentially the permutations of B (cf TAOCP Volume 4 fascicle 2b) and for each permutation apply the above "product" with all the k-combinations generated sequentially (or stored in an array if k is small) (cf TAOCP Volume 4 fascicle 3a).
B={a,b,c, ... }
T={1,2}
k=length(B)
reset_perm(B)
do
p = next_perm(B)
reset_comb(T,k)
do
c = next_kcomb(T,k)
output product(p,c)
while not last_kcomb(T,k)
while not last_perm(B)