Home Navigation

Wednesday, 9 November 2016

Graph representations

Graph is one of the most important data structure in computer science. There are several ways to represent graphs, each with its advantages and disadvantages. Some situations, or algorithms that we want to run with graphs as input, call for one representation, and others call for a different representation. Here, we'll see three ways to represent graphs.

Edge lists: One simple way to represent a graph is just a list, or array, of |E|∣E∣ edges, which we call an edge list. Since each edge contains just two or three numbers, the total space for an edge list is Theta Θ(E). For example, here's how we represent an edge list in JavaScript for the social network graph:

[ [0,1], [0,6], [0,8], [1,4], [1,6], [1,9], [2,4], [2,6], [3,4], [3,5],[3,8], [4,5], [4,9], [7,8], [7,9] ]

Edge lists are simple, but if we want to find whether the graph contains a particular edge, we have to search through the edge list. If the edges appear in the edge list in no particular order, that's a linear search through |∣E∣ edges.

Adjacency matrices: For a graph with |V| vertices, an adjacency matrix is a |V| times ∣V∣×∣V∣ matrix of 0s and 1s, where the entry in row i and column j is 1 if and only if the edge (i,j)(i,j) is in the graph.

[ [0, 1, 0, 0, 0, 0, 1, 0, 1, 0],
  [1, 0, 0, 0, 1, 0, 1, 0, 0, 1],
  [0, 0, 0, 0, 1, 0, 1, 0, 0, 0],
  [0, 0, 0, 0, 1, 1, 0, 0, 1, 0],
  [0, 1, 1, 1, 0, 1, 0, 0, 0, 1],
  [0, 0, 0, 1, 1, 0, 0, 0, 0, 0],
  [1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 1, 1],
  [1, 0, 0, 1, 0, 0, 0, 1, 0, 0],
  [0, 1, 0, 0, 1, 0, 0, 1, 0, 0] ]

Advantages
  • we can find out whether an edge is present in constant time

Disadvantages:
  •  First, it takes Theta(V^2) space. In other words, for a sparse graph, the adjacency matrix is mostly 0s, and we use lots of space to represent only a few edges
  • Second, if you want to find out which vertices are adjacent to a given vertex ii, you have to look at all ∣V∣ entries in row ii, even if only a small number of vertices are adjacent to vertex ii.

For an undirected graph, the adjacency matrix is symmetric: the row ii, column jj entry is 1 if and only if the row jj, column ii entry is 1. For a directed graph, the adjacency matrix need not be symmetric.

Adjacency lists: An array of linked lists is used. Size of the array is equal to number of vertices. Let the array be array[]. An entry array[i] represents the linked list of vertices adjacent to the ith vertex. This representation can also be used to represent a weighted graph. The weights of edges can be stored in nodes of linked lists
Vertex numbers in an adjacency list are not required to appear in any particular order, though it is often convenient to list them in increasing order, as in this example.

[ [1, 6, 8],
  [0, 4, 6, 9],
  [4, 6],
  [4, 5, 8],
  [1, 2, 3, 5, 9],
  [3, 4],
  [0, 1, 2],
  [8, 9],
  [0, 3, 7],
  [1, 4, 7] ]

We can get to each vertex's adjacency list in constant time, because we just have to index into an array. To find out whether an edge (i,j) is present in the graph, we go to i's adjacency list in constant time and then look for j in i's adjacency list. How long does that take in the worst case? The answer is Θ(d), where dd is the degree of vertex i, because that's how long i's adjacency list is.

for (var j = 0; j < graph[i].length; j++) {
    doStuff(graph[i][j]);
}

Wednesday, 26 October 2016

Asymptotic notation

The running time of an algorithm uses a combination of two ideas.
  • First, we need to determine how long the algorithm takes, in terms of the size of its input. 
  • The second idea is that we must focus on how fast a function grows with the input size. We call this the rate of growth of the running time. 

Here's a chart showing values of 6n^2 and 100n + 300 for values of n from 0 to 100:

We'll see three forms of asymptotic notation: big-Theta Θ notation, big-O notation and big-Omega Ώ notation.

Big-Θ (Big-Theta) notation: When we say that a particular running time is Θ(n), we're saying that once n gets large enough, the running time is at least k1.n and at most k2.n for some constants k1 and k2. Here's how to think of Θ(n):

When we use big-Θ notation, we're saying that we have an asymptotically tight bound on the running time. "Asymptotically" because it matters for only large values of n. "Tight bound" because consider the running time to within a constant factor above and below.

Here's a list of functions in asymptotic notation that we often encounter, listed from fastest to slowest in performance.
  • Θ(1) 
  • Θ(lgn) 
  • Θ(n) 
  • Θ(nlgn) 
  • Θ(n^2) 
  • Θ(n^2lgn) 
  • Θ(n^3) 
  • Θ(2^n)
Note that an exponential function a^n, where a>1, grows faster than any polynomial function n^b, where b is any constant.

Big-O notation: We use big-Θ notation to asymptotically bound the growth of a running time to within constant factors above and below. Sometimes we want to bound from only above. For example, although the worst-case running time of binary search is Θ(lgn), it would be incorrect to say that binary search runs in Θ(lgn) time in all cases. What if we find the target value upon the first guess? Then it runs in Θ(1) time. The running time of binary search is never worse than Θ(lgn), but it's sometimes better. It would be convenient to have a form of asymptotic notation that means "the running time grows at most this much, but it could grow more slowly." We use "big-O" notation for just such occasions.

We say that the running time is "big-O of f(n)" or just "O of f(n)." We use big-O notation for asymptotic upper bounds, since it bounds the growth of the running time from above for large enough input sizes.



Now we have a way to characterize the running time of binary search in all cases. We can say that the running time of binary search is always O(lgn). We can make a stronger statement about the worst-case running time: it's Θ(lgn). But for a blanket statement that covers all cases, the strongest statement we can make is that binary search runs in O(lgn) time.

Big-Ω(Big-Omega) notation:  Sometimes, we want to say that an algorithm takes at least a certain amount of time, without providing an upper bound. We use big-Ω notation; that's the Greek letter "omega."

If a running time is Ω(f(n)), then for large enough nn, the running time is at least k.f(n) for some constant k. Here's how to think of a running time that is Ω(f(n)):

We say that the running time is "big-Ωf(n)." We use big-Ω notation for asymptotic lower bounds, since it bounds the growth of the running time from below for large enough input sizes.

:Common Data Structure Operations:

Data Structure Time Complexity Space Complexity
Average Worst Worst
Access Search Insertion Deletion Access Search Insertion Deletion
Array Θ(1) Θ(n) Θ(n) Θ(n) O(1) O(n) O(n) O(n) O(n)
Stack Θ(n) Θ(n) Θ(1) Θ(1) O(n) O(n) O(1) O(1) O(n)
Queue Θ(n) Θ(n) Θ(1) Θ(1) O(n) O(n) O(1) O(1) O(n)
Singly-Linked List Θ(n) Θ(n) Θ(1) Θ(1) O(n) O(n) O(1) O(1) O(n)
Doubly-Linked List Θ(n) Θ(n) Θ(1) Θ(1) O(n) O(n) O(1) O(1) O(n)
Skip List Θ(log(n)) Θ(log(n)) Θ(log(n)) Θ(log(n)) O(n) O(n) O(n) O(n) O(n log(n))
Hash Table N/A Θ(1) Θ(1) Θ(1) N/A O(n) O(n) O(n) O(n)
Binary Search Tree Θ(log(n)) Θ(log(n)) Θ(log(n)) Θ(log(n)) O(n) O(n) O(n) O(n) O(n)
Cartesian Tree N/A Θ(log(n)) Θ(log(n)) Θ(log(n)) N/A O(n) O(n) O(n) O(n)
B-Tree Θ(log(n)) Θ(log(n)) Θ(log(n)) Θ(log(n)) O(log(n)) O(log(n)) O(log(n)) O(log(n)) O(n)
Red-Black Tree Θ(log(n)) Θ(log(n)) Θ(log(n)) Θ(log(n)) O(log(n)) O(log(n)) O(log(n)) O(log(n)) O(n)
Splay Tree N/A Θ(log(n)) Θ(log(n)) Θ(log(n)) N/A O(log(n)) O(log(n)) O(log(n)) O(n)
AVL Tree Θ(log(n)) Θ(log(n)) Θ(log(n)) Θ(log(n)) O(log(n)) O(log(n)) O(log(n)) O(log(n)) O(n)
KD Tree Θ(log(n)) Θ(log(n)) Θ(log(n)) Θ(log(n)) O(n) O(n) O(n) O(n) O(n)

Array Sorting Algorithms 
Algorithm Time Complexity Space Complexity
Best Average Worst Worst
Quicksort Ω(n log(n)) Θ(n log(n)) O(n^2) O(log(n))
Mergesort Ω(n log(n)) Θ(n log(n)) O(n log(n)) O(n)
Timsort Ω(n) Θ(n log(n)) O(n log(n)) O(n)
Heapsort Ω(n log(n)) Θ(n log(n)) O(n log(n)) O(1)
Bubble Sort Ω(n) Θ(n^2) O(n^2) O(1)
Insertion Sort Ω(n) Θ(n^2) O(n^2) O(1)
Selection Sort Ω(n^2) Θ(n^2) O(n^2) O(1)
Tree Sort Ω(n log(n)) Θ(n log(n)) O(n^2) O(n)
Shell Sort Ω(n log(n)) Θ(n(log(n))^2) O(n(log(n))^2) O(1)
Bucket Sort Ω(n+k) Θ(n+k) O(n^2) O(n)
Radix Sort Ω(nk) Θ(nk) O(nk) O(n+k)
Counting Sort Ω(n+k) Θ(n+k) O(n+k) O(k)
Cubesort Ω(n) Θ(n log(n)) O(n log(n)) O(n)

Ref: Khan Academy

Wednesday, 12 October 2016

Some important file location for WebSphere Application Server

Published Application EAR File:

{WEBSHPERE_INSTALLED_LOCATION}\profiles\{PROFILE_NAME eg AppSrv1}\installedApps\{CELL_NAME eg WVWNO006C0634Node01Cell}\{YOUR_APP_NAME}

Log file Location:

{WEBSHPERE_INSTALLED_LOCATION}\profiles\{PROFILE_NAME eg AppSrv1}\logs\server1

Tuesday, 11 October 2016

How to configure custom datasource properties using websphere application server console like currentSQLID

Open WebSphere application server console, from server tab right click on the server and choose Administration->Run Administrative console

Then on the left hand side menu go to resources section and pick Data Sources

Click on the datasource you need to add/change properties

Then follow the below path

{DATA_SOURCE} -> custom properties 

Now you can pick the properties you want to change/add.

PSCP Command to transfer file from/to Unix server

PSCP is a freeware SCP (Secure CoPy) program for the Windows command line processor. You can use this program instead of FTP for copying files to or from the Unix servers at the NBER offices. FTP is not allowed from clients outside nber.org to servers inside the firewall because FTP leaves passwords in plain-text and vulnerable to eavesdropping. PSCP should work with any host supporting SSH, not just at NBER.

pscp username@yourhost:file.foo c:\temp\file.foo


pscp -v c:\"my documents"\file.foo username@nber.org:file.foo

Thursday, 6 October 2016

Some useful ant commands

Delete files inside a zip/jar/war/ear:

<project name="myproject">
<target name="updateZip">
<zip destfile="updatedZip.zip">
<zipfileset src="baseZipFromWhereToDelete.zip" excludes="path1,path2" />
</zip>
</target>
</project>

Inject/update some content inside zip/jar/war/ear:

<project name="myproject">
<target name="updateZip">
<zip update="true" destfile="theFileNeedsToBeUpdated.zip" baseDir="TheContentWhichWillBeIjected" />
</target>
</project>

How to compress/zip a set of files:

<zip destfile="TheZipFileNameWhichWillBeCreated.zip" basedir="TheContentWhichAreGoingToBeCompressed" />

Setting up data source in TomEE at EAR level

Prerequisite:
  1. Configure TomEE to deploy EAR Application in Apps directory
    • Got to the directory {TOMEE_HOME}\conf\
    • Open the file tome.xml in a text editor
    • <Deployments dir="apps" /> add this tag to tome.xml
    • And Create a directory apps in {TOMEE_HOME}
  2. Configure data source at EAR level
      • Add the data-source information according to the database you have chosen. And make sure you add the schema as well. You can copy the below schema to your application.xml file

xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd"
version="6"

      • To get the database class name please follow the below link http://tomee.apache.org/common-datasource-configurations.html
      • Now open in a text editor web.xml file from WEB-INF directory of webmodule project and declare the resource reference you created in application.xml file in EAR module. Make sure the reference name is the same as data-source name in application.xml file.  
      • You can now call the datasource from your code. Below is an example of calling datasource from a jsp page.    
      • Build the application and copy the .ear file to {TOMEE_HOME}\apps directory.
      • Test the application web application from web browser.