Find minimal elements of set of vectors - algorithm

I have a set of vectors, and I need to write algorithm in java, to find minimal elements of this set. Problem is, that there are elements which are incomparable. E.g. minset{(1,4,6),(3,2,5),(2,3,4),(5,4,6)} = {(1,4,6),(3,2,5),(2,3,4)}. For set of minimal element "minset" following holds: every vector from the original set is either in "minset" or >= than some vector in the new set in every component. E.g. minset{(2,3,4),(2,3,5)} = {(2,3,4)}. I've already have algorithm for this, but I think it can be done with better computional complexity. My algorithm takes one element, mark it as minimal, then take other element, compare them, if there are incomparable, mark both as minimal, if second is smaller then mark only it as minimal etc... Is it possible to use mergesort or heapsort to optimize this algorithm? Thank for all responses.

I created a runnable example. It uses Java's builtin Arrays.sort() and a Comparator which compares two vectors of size L. You could do something similar using Collections.sort() if you prefer to use List data structures over arrays.
From the Java API Specification:
This algorithm offers guaranteed n*log(n) performance.
import java.util.*;
import java.lang.*;
class Main
{
public static void main (String[] args) throws java.lang.Exception
{
final int L = 3;
int[][] vectors = {
{1, 4, 6},
{3, 2, 5},
{2, 3, 4},
{5, 4, 6},
{7, 7, 7},
{3, 3, 5},
{8, 8, 8},
};
Comparator<int[]> cmp = new Comparator<int[]>() {
public int compare(int[] v1, int[] v2) {
int cmp0 = Integer.signum(v1[0] - v2[0]);
for (int i = 0; i < L; i++) {
int cmp1 = Integer.signum(v1[i] - v2[i]);
if (cmp1 != 0) {
if (cmp1 != cmp0) {
return 0;
}
cmp0 = cmp1;
}
}
return cmp0;
}
};
Arrays.sort(vectors, cmp);
System.out.println("minset:");
int i = 0;
int[] vPref = vectors[0];
while (cmp.compare(vectors[i], vPref) == 0) {
for (int x : vectors[i]){
System.out.print(x + ", ");
}
System.out.println();
vPref = vectors[i];
i++;
}
}
}

Pseudocode:
foreach inputVector in vectors
foreach minVector in minSet
if (all components of inputVector <= components of minVector
delete minVector
elseif (all components of inputVector >= components of minVector)
skip to next inputVector
if inputVector made it through the entire minSet, then add it to minSet

I found solution for my problem in article http://repository.cmu.edu/cgi/viewcontent.cgi?article=2758&context=compsci, where is algorithm for finding maximal elements of set of vectors which is similar problem. It works in much more better computional complexity that my firts intuitive algorithm.

Related

How to Solve Assignment Problem With Constraints?

Assume there are N people and M tasks are there and there is a cost matrix which tells when a task is assigned to a person how much it cost.
Assume we can assign more than one task to a person.
It means we can assign all of the tasks to a person if it leads to minimum cost.
I know this problem can be solved using various techniques. Some of them are below.
Bit Masking
Hungarian Algorithm
Min Cost Max Flow
Brute Force( All permutations M!)
Question: But what if we put a constraint like only consecutive tasks can be assigned to a person. 
    T1   T2  T3
P1  2   2    2
P2  3   1    4
Answer: 6 rather than 5
Explanation:
We might think that , P1->T1, P2->T2, P1->T3 = 2+1+2 =5 can be answer but it is not because (T1 and T3 are consecutive so can not be assigned to P1)
P1->T1, P1->T2, P1-T3 = 2+2+2 = 6
How to approach solving this problem?
You can solve this problem using ILP.
Here is an OPL-like pseudo-code:
**input:
two integers N, M // N persons, M tasks
a cost matrix C[N][M]
**decision variables:
X[N][M][M] // An array with values in {0, 1}
// X[i][j][k] = 1 <=> the person i performs the tasks j to k
**constraints:
// one person can perform at most 1 sequence of consecutive tasks
for all i in {1, N}, sum(j in {1, ..., M}, k in {1, ..., M}) X[i][j][k] <= 1
// each task is performed exactly once
for all t in {1, M}, sum(i in {1, ..., N}, j in {1, ..., t}, k in {t, ..., M}) X[i][j][k] = 1
// impossible tasks sequences are discarded
for all i in {1, ..., N}, for all j in {1, ..., M}, sum(k in {1, ..., j-1}) X[i][j][k] = 0
**objective function:
minimize sum(i, j, k) X[i][j][k] * (sum(t in {j, ..., k}) C[t])
I think that ILP could be the tool of choice here, since more often that not scheduling and production-planning problems are solved using it.
If you do not have experience coding LP programs, don't worry, it is much easier than it looks like, and this problem is rather easy and nice to get started.
There also exists a stackexchange dedicated to this kind of problems and solutions, the OR stack exchange.
This looks np-complete to me. If I am correct, there is not going to be a universally quick solution, and the best one can do is approach this problem using the best possible heuristics.
One approach you did not mention is a constructive approach using A* search. In this case, the search in would move along the matrix from left to right, adding candidate items to a priority queue with every step. Each item in the queue would consist of the current column index, the total cost expended so far, and the list of people who have acted so far. The remaining-cost heuristic for any given state would be the sum of the columnar minima for all remaining columns.
I'm certain that this can find a solution, I'm just not sure it is the best approach. Some quick Googling shows that A* has been applied to several types of scheduling problems though.
Edit: Here is an implementation.
public class OrderedTasks {
private class State {
private final State prev;
private final int position;
private final int costSoFar;
private final int lastActed;
public State(int position, int costSoFar, int lastActed, State prev) {
super();
this.prev = prev;
this.lastActed = lastActed;
this.position = position;
this.costSoFar = costSoFar;
}
public void getNextSteps(int[] task, Consumer<State> consumer) {
Set<Integer> actedSoFar = new HashSet<>();
State prev = this.prev;
if (prev != null) {
for (; prev!=null; prev=prev.prev) {
actedSoFar.add(prev.lastActed);
}
}
for (int person=0; person<task.length; ++person) {
if (actedSoFar.contains(person) && this.lastActed!=person) {
continue;
}
consumer.accept(new State(position+1,task[person]+this.costSoFar,
person, this));
}
}
}
public int minCost(int[][] tasksByPeople) {
int[] cumulativeMinCost = getCumulativeMinCostPerTask(tasksByPeople);
Function<State, Integer> totalCost = state->state.costSoFar+(state.position<cumulativeMinCost.length? cumulativeMinCost[state.position]: 0);
PriorityQueue<State> pq = new PriorityQueue<>((s1,s2)->{
return Integer.compare(totalCost.apply(s1), totalCost.apply(s2));
});
State state = new State(0, 0, -1, null);
for (; state.position<tasksByPeople.length; state = pq.poll()) {
state.getNextSteps(tasksByPeople[state.position], pq::add);
}
return state.costSoFar;
}
private int[] getCumulativeMinCostPerTask(int[][] tasksByPeople) {
int[] result = new int[tasksByPeople.length];
int cumulative = 0;
for (int i=tasksByPeople.length-1; i>=0; --i) {
cumulative += minimum(tasksByPeople[i]);
result[i] = cumulative;
}
return result;
}
private int minimum(int[] arr) {
if (arr.length==0) {
throw new RuntimeException("Not valid for empty arrays.");
}
int min = arr[0];
for (int i=1; i<arr.length; ++i) {
min = Math.min(min, arr[i]);
}
return min;
}
public static void main(String[] args) {
OrderedTasks ot = new OrderedTasks();
System.out.println(ot.minCost(new int[][]{{2, 3},{2,1},{2,4},{2,2}}));
}
}
I think your question is very similar to:
Finding the minimum value
Probably not the best approach if the number of workers is large, but easy to understand and implement could be
get a list all the possible combination with repetition of workers W, for example using the algorithm in https://www.geeksforgeeks.org/combinations-with-repetitions/ . This would give you things like [[W1,W3,W2,W3,W1],[W3,W5,W5,W4,W5]
Discard combinations where workers are not continuous
bool isValid=true;
for (int kk = 0; kk < workerOrder.Length; kk++)
{
int state=0;
for (int mm = 0; mm < workerOrder.Length; mm++)
{
if (workerOrder[mm] == kk && state == 0) { state = 1; } //it has appeard
if (workerOrder[mm] != kk && state == 1 ) { state = 2; } //it is not contious
if (workerOrder[mm] == kk && state == 2) { isValid = false; break; } //it appeard again
}
if (isValid==false){break;}
}
Use the filtered list of lists to check times using the table and keep the minimum one

Best approach to fit numbers

I have the following set of integers {2,9,4,1,8}. I need to divide this set into two subsets so that the sum of the sets results in 14 and 10 respectively. In my example the answer is {2,4,8} and {9,1}. I am not looking for any code. I am pretty sure there must be a standard algorithm to solve this problem. Since i was not successful in googling and finding out that myself, i posted my query here. So what will be the best way to approach this problem?
My try was like this...
public class Test {
public static void main(String[] args) {
int[] input = {2, 9, 4, 1, 8};
int target = 14;
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < input.length; i++) {
stack.add(input[i]);
for (int j = i+1;j<input.length;j++) {
int sum = sumInStack(stack);
if (sum < target) {
stack.add(input[j]);
continue;
}
if (target == sum) {
System.out.println("Eureka");
}
stack.remove(input[i]);
}
}
}
private static int sumInStack(Stack<Integer> stack) {
int sum = 0;
for (Integer integer : stack) {
sum+=integer;
}
return sum;
}
}
I know this approach is not even close to solve the problem
I need to divide this set into two subsets so that the sum of the sets results in 14 and 10 respectively.
If the subsets have to sum to certain values, then it had better be true that the sum of the entire set is the sum of those values, i.e. 14+10=24 in your example. If you only have to find the two subsets, then the problem isn't very difficult — find any subset that sums to one of those values, and the remaining elements of the set must sum to the other value.
For the example set you gave, {2,9,4,1,8}, you said that the answer is {9,1}, {2,4,8}, but notice that that's not the only answer; there's also {2,8}, {9,4,1}.

Approximation Algorithm for non-intersecting paths in a grid

I recently came across this question and thought I could share it here, since I wasn't able to get it.
We are given a 5*5 grid numbered from 1-25, and a set of 5 pairs of points,that are start and end points of a path on the grid.
Now we need to find 5 corresponding paths for the 5 pairs of points, such that no two paths should overlap. Also note that only vertical and horizontal moves are allowed. Also the combined 5 path should cover the entire grid.
For example we are given the pair of points as:
P={1,22},{4,17},{5,18},{9,13},{20,23}
Then the corresponding paths will be
1-6-11-16-21-22
4-3-2-7-12-17
5-10-15-14-19-18
9-8-13
20-25-24-23
What I have thought of so far:
Maybe i can compute all paths from source to destination for all pairs of points and then check if there's no common point in the paths. However this seems to be of higher time complexity.
Can anyone propose a better algorithm? I would be glad if one could explain through a pseudo code.Thanks
This problem is essentially the Hamiltonian path/cycle problem problem (since you can connect the end of one path to the start of another, and consider all the five paths as a part of one big cycle). There are no known efficient algorithms for this, as the problem is NP-complete, so you do essentially need to try all possible paths with backtracking (there are fancier algorithms, but they're not much faster).
Your title asks for an approximation algorithm, but this is not an optimization problem - it's not the case that some solutions are better than others; all correct solutions are equally good, and if it isn't correct, then it's completely wrong - so there is no possibility for approximation.
Edit: The below is a solution to the original problem posted by the OP, which did not include the "all cells must be covered" constraint. I'm leaving it up for those that might face the original problem.
This can be solved with a maximum flow algorithm, such as Edmonds-Karp.
The trick is to model the grid as a graph where there are two nodes per grid cell; one "outgoing" node and one "incoming" node. For each adjacent pair of cells, there are edges from the "outgoing" node in either cell to the "incoming" node in the other cell. Within each cell, there is also an edge from the "incoming" to the "outgoing" node. Each edge has the capacity 1. Create one global source node that has an edge to all the start nodes, and one global sink node to which all end nodes have an edge.
Then, run the flow algorithm; the resulting flow shows the non-intersecting paths.
This works because all flow coming in to a cell must pass through the "internal" edge from the "incoming" to the "ougoing" node, and as such, the flow through each cell is limited to 1 - therefore, no paths will intersect. Also, Edmonds-Karp (and all Floyd-Warshall based flow algorithms) will produce integer flows as long as all capacities are integers.
Here's a program written in Python that walks all potential paths. It uses recursion and backtracking to find the paths, and it marks a grid to see which locations are already being used.
One key optimization is that it marks the start and end points on the grid (10 of the 25 points).
Another optimization is that it generates all moves from each point before starting the "walk" across the grid. For example, from point 1 the moves are to points 2 & 6; from point 7, the moves are to points 2, 6, 8 & 12.
points = [(1,22), (4,17), (5,18), (9,13), (20,23)]
paths = []
# find all moves from each position 0-25
moves = [None] # set position 0 with None
for i in range(1,26):
m = []
if i % 5 != 0: # move right
m.append(i+1)
if i % 5 != 1: # move left
m.append(i-1)
if i > 5: # move up
m.append(i-5)
if i < 21: # move down
m.append(i+5)
moves.append(m)
# Recursive function to walk path 'p' from 'start' to 'end'
def walk(p, start, end):
for m in moves[start]: # try all moves from this point
paths[p].append(m) # keep track of our path
if m == end: # reached the end point for this path?
if p+1 == len(points): # no more paths?
if None not in grid[1:]: # full coverage?
print
for i,path in enumerate(paths):
print "%d." % (i+1), '-'.join(map(str, path))
else:
_start, _end = points[p+1] # now try to walk the next path
walk(p+1, _start, _end)
elif grid[m] is None: # can we walk onto the next grid spot?
grid[m] = p # mark this spot as taken
walk(p, m, end)
grid[m] = None # unmark this spot
paths[p].pop() # backtrack on this path
grid = [None for i in range(26)] # initialize the grid as empty points
for p in range(len(points)):
start, end = points[p]
paths.append([start]) # initialize path with its starting point
grid[start] = grid[end] = p # optimization: pre-set the known points
start, end = points[0]
walk(0, start, end)
Well, I started out thinking about a brute force algorithm, and I left that below, but it turns out it's actually simpler to search for all answers rather than generate all configurations and test for valid answers. Here's the search code, which ended up looking much like #Brent Washburne's. It runs in 53 milliseconds on my laptop.
import java.util.Arrays;
class Puzzle {
final int path[][];
final int grid[] = new int[25];
Puzzle(int[][] path) {
// Make the path endpoints 0-based for Java arrays.
this.path = Arrays.asList(path).stream().map(pair -> {
return new int[] { pair[0] - 1, pair[1] - 1 };
}).toArray(int[][]::new);
}
void print() {
System.out.println();
for (int i = 0; i < grid.length; i += 5)
System.out.println(
Arrays.toString(Arrays.copyOfRange(grid, i, i + 5)));
}
void findPaths(int ip, int i) {
if (grid[i] != -1) return; // backtrack
grid[i] = ip; // mark visited
if(i == path[ip][1]) // path complete
if (ip < path.length - 1) findPaths(ip + 1, path[ip + 1][0]); // find next path
else print(); // solution complete
else { // continue with current path
if (i < 20) findPaths(ip, i + 5);
if (i > 4) findPaths(ip, i - 5);
if (i % 5 < 4) findPaths(ip, i + 1);
if (i % 5 > 0) findPaths(ip, i - 1);
}
grid[i] = -1; // unmark
}
void solve() {
Arrays.fill(grid, -1);
findPaths(0, path[0][0]);
}
public static void main(String[] args) {
new Puzzle(new int[][]{{1, 22}, {4, 17}, {5, 18}, {9, 13}, {20, 23}}).solve();
}
}
Old, bad answer
This problem is doable by brute force if you think about it "backward:" assign all the grid squares to paths and test to see if the assignment is valid. There are 25 grid squares and you need to construct 5 paths, each with 2 endpoints. So you know the paths these 10 points lie on. All that's left is to label the remaining 15 squares with the paths they lie on. There are 5 possibilities for each, so 5^15 in all. That's about 30 billion. All that's left is to build an efficient checker that says whether a given assignment is a set of 5 valid paths. This is simple to do by linear time search. The code below finds your solution in about 2 minutes and takes a bit under 11 minutes to test exhaustively on my MacBook:
import java.util.Arrays;
public class Hacking {
static class Puzzle {
final int path[][];
final int grid[] = new int[25];
Puzzle(int[][] path) { this.path = path; }
void print() {
System.out.println();
for (int i = 0; i < grid.length; i += 5)
System.out.println(
Arrays.toString(Arrays.copyOfRange(grid, i, i + 5)));
}
boolean trace(int p, int i, int goal) {
if (grid[i] != p) return false;
grid[i] = -1; // mark visited
boolean rtn =
i == goal ? !Arrays.asList(grid).contains(p) : nsew(p, i, goal);
grid[i] = p; // unmark
return rtn;
}
boolean nsew(int p, int i, int goal) {
if (i < 20 && trace(p, i + 5, goal)) return true;
if (i > 4 && trace(p, i - 5, goal)) return true;
if (i % 5 < 4 && trace(p, i + 1, goal)) return true;
if (i % 5 > 0 && trace(p, i - 1, goal)) return true;
return false;
}
void test() {
for (int ip = 0; ip < path.length; ip++)
if (!trace(ip, path[ip][0] - 1, path[ip][1] - 1)) return;
print();
}
void enumerate(int i) {
if (i == grid.length) test();
else if (grid[i] != -1) enumerate(i + 1); // already known
else {
for (int ip = 0; ip < 5; ip++) {
grid[i] = ip;
enumerate(i + 1);
}
grid[i] = -1;
}
}
void solve() {
Arrays.fill(grid, -1);
for (int ip = 0; ip < path.length; ip++)
grid[path[ip][0] - 1] = grid[path[ip][1] - 1] = ip;
enumerate(0);
}
}
public static void main(String[] args) {
new Puzzle(new int[][]{{1, 22}, {4, 17}, {5, 18}, {9, 13}, {20, 23}}).solve();
}
}
The starting array:
[ 0, -1, -1, 1, 2]
[-1, -1, -1, 3, -1]
[-1, -1, 3, -1, -1]
[-1, 1, 2, -1, 4]
[-1, 0, 4, -1, -1]
The result:
[ 0, 1, 1, 1, 2]
[ 0, 1, 3, 3, 2]
[ 0, 1, 3, 2, 2]
[ 0, 1, 2, 2, 4]
[ 0, 0, 4, 4, 4]

how to save shortest path in dijkstra algorithm

So first let's define Dijkstra algorithm:
Dijkstra's algorithm finds single-source shortest paths in a directed graph with non-negative edge weights.
I want to know how can I save the shortest path form s to t with Dijkstra algorithm.
I searched on google, but I couldn't find anything particular; I also changed Dijkstra algorithm, but I could't get any answer. How can I save the shortest path from s to t with Dijkstra?
I know my question is basic and unprofessional, but any help would be appreciated. Thanks for considering my question.
If you look at the pseudocode from the Wikipedia link you gave, you'll see an array in there called prev[]. This array contains, for each node v in the graph, the previous node u in the shortest path between the source node s and v. (This array is also called the predecessor or parent array.)
In other words, the shortest path between s and v is:
s -> u -> v
where u = prev[v]
The path from s to u might have several nodes in between, so to reconstruct the path from s to v, you just walk back along the path defined by the prev[] array using the code snippet below the main pseudocode (target is v):
1 S ← empty sequence
2 u ← target
3 while prev[u] is defined: // Construct the shortest path with a stack S
4 insert u at the beginning of S // Push the vertex onto the stack
5 u ← prev[u] // Traverse from target to source
6 end while
One extremely short way to do so is to use recursion and a "parent array."
If you initialize all of the points' parents to -1, and then as you complete dijkstra's, update the parent array, you are able to recurse back from any point till you get to the source and print out the path. Here is a very short and easy to understand recursion snippet:
// Function to print shortest path from source to j using parent array
void path(parent array, int j)
{
    // Base Case : If j is source
    if (jth element of parent is -1) return;
 
    path(parent, jth element of parent);
  print j;
}
Note that instead of printing "j" out, you can store it in a global vector (or other datatype for languages that are not C-related) for later use.
just a modify form there
# define INF 0x3f3f3f3f
// iPair ==> Integer Pair
typedef pair<int, int> iPair;
void addEdge(vector <pair<int, int> > adj[], int u, int v, int wt)
{
adj[u].push_back(make_pair(v, wt));
adj[v].push_back(make_pair(u, wt));
}
void shortestPath(vector<pair<int, int> > adj[], int V, int src, int target)
{
priority_queue< iPair, vector <iPair>, greater<iPair> > pq;
vector<int> dist(V, INF);
vector<bool> visited(V, false);
vector<int> prev(V, -1);
pq.push(make_pair(0, src));
dist[src] = 0;
while (!pq.empty() && !visited[target])
{
int u = pq.top().second;
pq.pop();
if (visited[u]) {
continue;
}
visited[u] = true;
for (auto x : adj[u])
{
int v = x.first;
int weight = x.second;
if (dist[v] > dist[u] + weight)
{
//relax
dist[v] = dist[u] + weight;
pq.push(make_pair(dist[v], v));
prev[v] = u;
}
}
}
vector<int> res;
res.push_back(target);
int temp = target;
while (temp != 0)
{
temp = prev[temp];
res.push_back(temp);
}
//cout << res;
}
int main()
{
const int V = 9;
vector<iPair > adj[V];
addEdge(adj, 0, 1, 4);
addEdge(adj, 0, 7, 8);
addEdge(adj, 1, 2, 8);
addEdge(adj, 1, 7, 11);
addEdge(adj, 2, 3, 7);
addEdge(adj, 2, 8, 2);
addEdge(adj, 2, 5, 4);
addEdge(adj, 3, 4, 9);
addEdge(adj, 3, 5, 14);
addEdge(adj, 4, 5, 10);
addEdge(adj, 5, 6, 2);
addEdge(adj, 6, 7, 1);
addEdge(adj, 6, 8, 6);
addEdge(adj, 7, 8, 7);
shortestPath(adj, V, 0, 6); //the last one means target
return 0;
}
Most libraries that use this algorithm will likely give you a way to do this. But in general just keep track of the path to each node. Ie give each node an attrribute shortestPathToNode in which you store the list of nodes

Sum array values with sum equals X

I have an integer collection. I need to get all possibilites that sum of values are equal to X.
I need something like this.
It can be written in: delphi, c#, php, RoR, python, cobol, vb, vb.net
That's a subset sum problem. And it is NP-Complete.
The only way to implement this would be generate all possible combinations and compare the sum values. Optimization techniques exists though.
Here's one in C#:
static class Program
{
static int TargetSum = 10;
static int[] InputData = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
static void Main()
{
// find all permutations
var permutations = Permute(InputData);
// check each permutation for the sum
foreach (var item in permutations) {
if (item.Sum() == TargetSum) {
Console.Write(string.Join(" + ", item.Select(n => n.ToString()).ToArray()));
Console.Write(" = " + TargetSum.ToString());
Console.WriteLine();
}
}
Console.ReadKey();
}
static IEnumerable<int[]> Permute(int[] data) { return Permute(data, 0); }
static IEnumerable<int[]> Permute(int[] data, int level)
{
// reached the edge yet? backtrack one step if so.
if (level >= data.Length) yield break;
// yield the first #level elements
yield return data.Take(level + 1).ToArray();
// permute the remaining elements
for (int i = level + 1; i < data.Length; i++) {
var temp = data[level];
data[level] = data[i];
data[i] = temp;
foreach (var item in Permute(data, level + 1))
yield return item;
temp = data[i];
data[i] = data[level];
data[level] = temp;
}
}
}
Dynamic Programming would yield the best runtime for an exact solution. The Subset Sum Problem page on Wikipedia has some pseudo-code for the algorithm. Essentially you order all the numbers and add up all the possible sequences in order such that you minimize the number of additions. The runtime is pseudo-polynomial.
For a polynomial algorithm you could use an Approximation Algorithm. Pseudo-code is also available at the Subset Sum Problem page.
Of the two algorithms I would choose the dynamic programming one since it is straight-forward and has a good runtime with most data sets.
However if the integers are all non-negative and fit with the description on the Wikipedia page then you could actually do this in polynomial time with the approximation algorithm.

Resources