Topology Dependent Bounds For FAQs
CC Attribution 3.0 Germany:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Langberg, Michael
Li, Shi
Jayaraman, Sai Vikneshwar Mani
Rudra, Atri
In this paper, we prove topology dependent bounds on the number of rounds needed to compute Functional Aggregate Queries (FAQs) studied by Abo Khamis et al. in a synchronous distributed network under the model considered by Chattopadhyay et al.. Unlike the recent work on computing database queries in the Massively Parallel Computation model, in the model of Chattopadhyay et al., nodes can communicate only via private point-to-point channels and we are interested in bounds that work over an arbitrary communication topology. This model, which is closer to the well-studied congest model in distributed computing and generalizes Yao's two party communication complexity model, has so far only been studied for problems that are common in the two-party communication complexity literature. This is the first work to consider more practically motivated problems in this distributed model. For the sake of exposition, we focus on two specific problems in this paper: Boolean Conjunctive Query (BCQ) and computing variable/factor marginals in Probabilistic Graphical Models (PGMs). We obtain tight bounds on the number of rounds needed to compute such queries as long as the underlying hypergraph of the query is O(1)-degenerate and has O(1)-arity. In particular, the O(1)-degeneracy condition covers most well-studied queries that are efficiently computable in the centralized computation model like queries with constant treewidth. These tight bounds depend on a new notion of `width' (namely internal-node-width) for Generalized Hypertree Decompositions (GHDs) of acyclic hypergraphs, which minimizes the number of internal nodes in a sub-class of GHDs. To the best of our knowledge, this width has not been studied explicitly in the theoretical database literature. Finally, we consider the problem of computing the product of a vector with a chain of matrices and prove tight bounds on its round complexity (over a finite field of two elements) using a novel min-entropy based argument.
 So, I'm going to talk about topology dependent bounds for FAQs and this is joint work with Michael Langberg, Shilee and Atri Rudra, all of us are at University at Buffalo. And so, let's get down to business and we'll decode the title in like sometime. So, don't. So, what is the problem, right? So, we want to compute database queries in a synchronous distributed environment over some topology. And by topology, I mean that, so, let's say you could have the tables that are distributed in say a clique where you have any pair of nodes can communicate or I could have a bipartite complete clique where I have this one set of nodes that can sort of communicate with all the other set of nodes on the other end and so on. So, yeah, these are like pretty dense topologies in that sense because they have like, if you have n vertices, they have like order of n square edges. So, what is our main result, right? So, we actually prove tight bounds has a star because I'm slipping in some logarithmic factors and stuff. So, but on the number of rounds needed to compute these database queries or any topology, okay? And so, as the title goes, these database queries are FAQs and by number of rounds, I mean, so typically number of rounds in this model is seen as a time complexity in the sense that how much time your algorithm takes to run. And you only consider the communication that's between nodes and not within nodes. You can assume that they have unlimited computational power or something of that sort. And we have some contributions. We consider a larger class of database queries compared to previous work. We present a new distributed computing model which actually shows that topology matters. And again, this is not entirely new. This was studied in the works of Chattopadhyaya et al. for like very theoretical problems say in communication and we are bringing it to joins now. And finally, we show some new connections to two-party communication and pseudo-randomness. So, let's dig this one by one now. So, first of the larger class of database queries, I should thank Max because he already brought FAQ up. And so FAQ was this paper by Mahmood Hang and Atri in part 16, so which basically studied and defined this problem which captures Boolean conjunctive query, it captures joins, exact inference on PGMs, and matrix chain vector multiplication where I have a bunch of matrices and then I have this vector and I want to do this multiplication. So now the point is, yeah, so one thing that I would like to mention here is typically many of these database models assume that the number of attributes and relations is constant. We however do not make that assumption and this is crucial for PGMs because PGMs can have a lot more variables in thousands and stuff. And we also use some techniques from this, I mean, there was this other work by Joglaker, Puttakonda and Ray in part 16 again, so which sort of studied a similar problem. So a quick recap, so VCQ is hold at for people, so I'm just going to give this instance and my goal is to check if this output of the join RST and U is empty and as I bold it there it turns out that it is not empty and one way to check this is I actually compute the join myself and I see that I have this one entry, one A that's present in all these guys. This example over looks very simple but it's going to be crucial in the later arguments. So I'm also going to give a representation of queries which is going to be very useful for my arguments. This is fairly simple, so I'm going to treat every attribute in my query as a vertex and every relation as an edge and then I have this graph. So if you go back and see I have all these relations, they have only one shared attribute, so this is sort of a star query. And I'm also going to nicely upper bound the sizes of all these relations by capital N which is Phi in the example that I took but really not relevant. So now what is our new distributed computing model, right? We are now ready to define it. So before we do that I would like to motivate naturally that it is an interesting model to consider. So one of the main reasons is it captures the square computation in the MPC model which was studied initially in a series of works by Beam et al in starting from POTS 13. And the nice thing about our model is since it also captures these varied computation settings where you have these sensor devices or IoT devices which cannot store too much of information within themselves but you still need to compute a lot of these aggregate queries. And there is also this, so this is for the topology stuff. Here is this data center interconnect which can change topologies with respect to Tor switches or something like that. So what is our model, right? So now the thing is we want to compute B C Q of H on G. Now H is a star as we saw earlier. Now G is a line. I'm considering a topology that's like least connected, barely connected. And I'm assigning these relations to players in this topology. So I have R, S, T and U. And here I'm assuming that I'm giving complete relations to the players in G. So if someone has given R, he's given R in entirety. We can get over this assumption but I'll not talk about it much. So and in each round one bit of information can be communicated across any H in G. So it's undirected, right? So you can communicate in only one direction but you can choose the direction. So again, now the question is again, how many rounds are needed to compute or check if R join, S join, T join, U is empty. And this is the question that we are interested in. Now what is the main result? So main result is that we prove tight bounds on number of rounds for computing any FAQ where H has constant average degree and constantarity and on any topology. So the nice thing about this is we cover a more general condition called the degeneracy and this actually captures most well studied, well tractable queries in the database setting. So for example, if the average degree of H is constant, then also you get constantry with etc. So now, yeah, so naturally since I defined this model and Dan is here, so it's also nice to do a comparison with some prior work. The MPC model, so I'm just restating their setup in R language. So what they do is they consider G as a clique and I'm focusing on biggest 13. And then queries are joins which also apply to BCQ in some sense. And then they also have vertex capacities on G and the number of rounds is constant or dependent on the number of relations basically. And yeah, so I just drew a clique just to be. So we saw the line that was least connected, right? Now we have a clique which is like most connected. So what is our difference here? So if you see, we actually consider general G, general topology and the queries are also more general in some sense because we consider FAQs and instead of vertex capacities, we consider H capacities on G. I think in this setup, the vertex capacities are a little more general but the H capacities is a very reasonable choice as well. And the number of rounds is a function of K and size n. But it turns out that we can sort of do some stitching and sort of instantiate their model from ours. And it turns out that when H is a star where our contribution is sort of fundamental, our results match them up to a constant factor. And they also have tight bonds and we prove tight bonds that match the number of rounds. So naturally this is accompanied by some new technical contributions, right? It's not like that. So the idea is we actually show an upper bound for practitioners which is basically accompanied by a new notion of width for acyclic queries that folks could be interested in. And as theoreticians, I always like lower bonds. So the lower bonds are related to new reductions and there is also this nice result about min entropy of matrix chain vector multiplication. So for the rest of the talk, I'm going to assume that H is a star. I'm going to deal with only the star query. G is a line and I'm mostly going to look at this assignment. And the question I'm interested in again is how many rounds is needed to check if this join is empty? So what is the trivial protocol, right? I mean the absolutely dumb protocol is basically to send everything to one player and then he computes the result. And that's what we are going to do. So what is going to do is this guy is going to send R, that guy is going to send S, and this guy is going to send T. And now if you send capital N rounds roughly, they would have sent their entire tables. Now this continues. So it's sort of sequential in that sense. Now this guy starts sending R because he has R completely. That guy starts sending S. And at two N rounds, we see that this guy just needs to send R. And the last guy basically has all the relations that he wants to compute the join at around three N rounds. So of course this is pretty dumb, right? Because I'm not using anything about the query. This might as well work for any query with four relations. So I have to do something smart. But for that, I'm going to recap our example slightly. So what I'm going to do is I'm going to take the same set of tables that I took back then. But I'm going to sort of project them to the values of A. I'm going to treat this star query as a set intersection query on A. And now I have R of A, S of A, T of A, and U of A. As you can see, S of A and T of A are pretty useless, right? Because they have all the entries anyways. So and capital N is five here. So these are subsets of this guy. Now yeah, this is something that theoretical people are always accused of. I'm going to recast this problem as set intersection. And then what I'm going to do here is basically I'm going to start with R of A's value, one. Now R is going to send this value. S is going to check if it's present and it's stable. It's present, so it's going to pass it on. T is going to do the same, pass it on. But U does not have it, as you can see. U has only two. It doesn't have one. So the result is zero of the BCQ query. But what happens with four? So R A is going to send four. S, check, agreed. T, check, agreed. U, check, agreed. So the result is one. And we have the result that computes this. So it's not too hard to see that this can be done in time that's in the order of the size of the relation because in some sense the projection is also going to be bounded by the size of the relation. And the idea here is to basically clue on set intersection. Again, this is not new. This was already studied and shut up by the Airtol's paper. But translating it to joins is the new novelty here in some sense. So yeah, like I promised earlier, topology does matter. So if you consider a more general case where you have a star with k plus one vertices, that is k relations. Now, if G is a line and you try to compute on it, you will actually do something like O of n plus k. But if G is a clique with k vertices, then you can do n by k plus k because you sort of fully exploit the power of your topology. And I mean, I'm not sure how much time I'll have to go on detail about these things, but please forgive me for that. So now the database grandma always says that if you can do something for stars, you can do something for trees as well. And we basically obey the grandma. So what we do is we start with a recursive protocol, which considers stars from bottom up and then evaluates and stores the result at the center and then continues this process. So the lower bounds, I mean, I just showed the upper bound. The lower bounds are based on fundamental connections to this two-party problem called set disjointness. And the details are in the poster. So please do visit it. The list leads to generalization. So I mean, we can extend the results to simple graph sets from stars and to hypergraphs as well with some kind of gaps, which are dependent on this average degree that I mentioned to you about. So yeah, I mean, maybe I should spend the rest of the time talking about this new connection. So yeah, I'm going to talk about this matrix chain vector multiplication. So the idea is you're given a set of players and then one guy has the vector and a bunch of these guys have these matrices. And the goal is to compute this guy, a k times blah. And the question is how many rounds are needed for computing this? So I'm going to assume k is equal to 3, but the trivial protocol is what? So the protocol is simple, right? So this p0 sends x to p1, and this guy computes a1x. He sends a1x to p2. This guy computes a2, a1x, and then so on. So this takes o of kn rounds, o of 3n rounds, right? The surprising fact is this. This bond is actually tight. So I'll show you how. So the thing is here, we have to use a more fancier version of randomness, which is called min entropy. So the idea is to, yeah, so I mean, just one thing that I would like to mention is the two party techniques that I spoke to you about give only a very weaker lower bond, but we want something that's dependent on k. So the idea is to show that up to n rounds, x is almost completely random to p1. So whatever he computes is useless. And same way, up to two rounds, a1x is almost completely random to this guy. And in 3n rounds, a3, this product is completely random to the last player. So this immediately gives us a lower bound of omega kn. That's the idea. So the idea here is still kn rounds. Whatever you get is absolutely useless. And only at the kn-th round, you will actually get something that's meaningful for you. So yeah, if I made my model very rosy, there is a reality check ahead. So we assume that the size of the input table is much larger than the size of g. There is this other paper by Afrati et al that does not make this assumption and still computes joints in the distributed setting. And we also assume that the players know both hng, which is kind of nicer. But it's also worthwhile to look at models where they don't have this awareness. And we also assume that the relations are systematically distributed to players in g. Again, so it would be nice to actually remove this assumption, but our lower bonds don't somehow generalize to those settings. So what is the road ahead? So can we address the gap between our upper and lower bonds when you have average degree d? Because when it's constant, we have tight. But when it's not constant, it turns out that it's tied to this fundamental problem in computational complexity, which is about proving super linear lower bonds when h is a clique, when you have a clique query. So and we don't handle node failures, which I think some of the models of B metaldas, we don't do that either. And when hng is same, that is the topology matches the query, the question is, can we do better? And we don't know anything in that setup either. So never let us say thanks to these people, some of whom are here actually. So thanks people. And okay. Thank you.
 So, I'm going to talk about topology dependent bounds for FAQs and this is joint work with  Michael Langberg, Shilee and Atri Rudra, all of us are at University at Buffalo.  And so, let's get down to business and we'll decode the title in like sometime.  So, don't.  So, what is the problem, right?  So, we want to compute database queries in a synchronous distributed environment over  some topology.  And by topology, I mean that, so, let's say you could have the tables that are distributed  in say a clique where you have any pair of nodes can communicate or I could have a bipartite  complete clique where I have this one set of nodes that can sort of communicate with  all the other set of nodes on the other end and so on.  So, yeah, these are like pretty dense topologies in that sense because they have like, if you  have n vertices, they have like order of n square edges.  So, what is our main result, right?  So, we actually prove tight bounds has a star because I'm slipping in some logarithmic  factors and stuff.  So, but on the number of rounds needed to compute these database queries or any topology,  okay?  And so, as the title goes, these database queries are FAQs and by number of rounds,  I mean, so typically number of rounds in this model is seen as a time complexity in the  sense that how much time your algorithm takes to run.  And you only consider the communication that's between nodes and not within nodes.  You can assume that they have unlimited computational power or something of that sort.  And we have some contributions.  We consider a larger class of database queries compared to previous work.  We present a new distributed computing model which actually shows that topology matters.  And again, this is not entirely new.  This was studied in the works of Chattopadhyaya et al. for like very theoretical problems  say in communication and we are bringing it to joins now.  And finally, we show some new connections to two-party communication and pseudo-randomness.  So, let's dig this one by one now.  So, first of the larger class of database queries, I should thank Max because he already  brought FAQ up.  And so FAQ was this paper by Mahmood Hang and Atri in part 16, so which basically studied  and defined this problem which captures Boolean conjunctive query, it captures joins, exact  inference on PGMs, and matrix chain vector multiplication where I have a bunch of matrices  and then I have this vector and I want to do this multiplication.  So now the point is, yeah, so one thing that I would like to mention here is typically  many of these database models assume that the number of attributes and relations is constant.  We however do not make that assumption and this is crucial for PGMs because PGMs can  have a lot more variables in thousands and stuff.  And we also use some techniques from this, I mean, there was this other work by Joglaker,  Puttakonda and Ray in part 16 again, so which sort of studied a similar problem.  So a quick recap, so VCQ is hold at for people, so I'm just going to give this instance and  my goal is to check if this output of the join RST and U is empty and as I bold it there  it turns out that it is not empty and one way to check this is I actually compute the  join myself and I see that I have this one entry, one A that's present in all these guys.  This example over looks very simple but it's going to be crucial in the later arguments.  So I'm also going to give a representation of queries which is going to be very useful  for my arguments.  This is fairly simple, so I'm going to treat every attribute in my query as a vertex and  every relation as an edge and then I have this graph.  So if you go back and see I have all these relations, they have only one shared attribute,  so this is sort of a star query.  And I'm also going to nicely upper bound the sizes of all these relations by capital N  which is Phi in the example that I took but really not relevant.  So now what is our new distributed computing model, right?  We are now ready to define it.  So before we do that I would like to motivate naturally that it is an interesting model  to consider.  So one of the main reasons is it captures the square computation in the MPC model which  was studied initially in a series of works by Beam et al in starting from POTS 13.  And the nice thing about our model is since it also captures these varied computation  settings where you have these sensor devices or IoT devices which cannot store too much  of information within themselves but you still need to compute a lot of these aggregate queries.  And there is also this, so this is for the topology stuff.  Here is this data center interconnect which can change topologies with respect to Tor  switches or something like that.  So what is our model, right?  So now the thing is we want to compute B C Q of H on G.  Now H is a star as we saw earlier.  Now G is a line.  I'm considering a topology that's like least connected, barely connected.  And I'm assigning these relations to players in this topology.  So I have R, S, T and U.  And here I'm assuming that I'm giving complete relations to the players in G.  So if someone has given R, he's given R in entirety.  We can get over this assumption but I'll not talk about it much.  So and in each round one bit of information can be communicated across any H in G.  So it's undirected, right?  So you can communicate in only one direction but you can choose the direction.  So again, now the question is again, how many rounds are needed to compute or check  if R join, S join, T join, U is empty.  And this is the question that we are interested in.  Now what is the main result?  So main result is that we prove tight bounds on number of rounds for computing any FAQ  where H has constant average degree and constantarity and on any topology.  So the nice thing about this is we cover a more general condition called the degeneracy  and this actually captures most well studied, well tractable queries in the database setting.  So for example, if the average degree of H is constant, then also you get constantry  with etc.  So now, yeah, so naturally since I defined this model and Dan is here, so it's also  nice to do a comparison with some prior work.  The MPC model, so I'm just restating their setup in R language.  So what they do is they consider G as a clique and I'm focusing on biggest 13.  And then queries are joins which also apply to BCQ in some sense.  And then they also have vertex capacities on G and the number of rounds is constant or  dependent on the number of relations basically.  And yeah, so I just drew a clique just to be.  So we saw the line that was least connected, right?  Now we have a clique which is like most connected.  So what is our difference here?  So if you see, we actually consider general G, general topology and the queries are also  more general in some sense because we consider FAQs and instead of vertex capacities, we  consider H capacities on G.  I think in this setup, the vertex capacities are a little more general but the H capacities  is a very reasonable choice as well.  And the number of rounds is a function of K and size n.  But it turns out that we can sort of do some stitching and sort of instantiate their model  from ours.  And it turns out that when H is a star where our contribution is sort of fundamental, our  results match them up to a constant factor.  And they also have tight bonds and we prove tight bonds that match the number of rounds.  So naturally this is accompanied by some new technical contributions, right?  It's not like that.  So the idea is we actually show an upper bound for practitioners which is basically accompanied  by a new notion of width for acyclic queries that folks could be interested in.  And as theoreticians, I always like lower bonds.  So the lower bonds are related to new reductions and there is also this nice result about min  entropy of matrix chain vector multiplication.  So for the rest of the talk, I'm going to assume that H is a star.  I'm going to deal with only the star query.  G is a line and I'm mostly going to look at this assignment.  And the question I'm interested in again is how many rounds is needed to check if this  join is empty?  So what is the trivial protocol, right?  I mean the absolutely dumb protocol is basically to send everything to one player and then  he computes the result.  And that's what we are going to do.  So what is going to do is this guy is going to send R, that guy is going to send S, and  this guy is going to send T. And now if you send capital N rounds roughly, they would  have sent their entire tables.  Now this continues.  So it's sort of sequential in that sense.  Now this guy starts sending R because he has R completely.  That guy starts sending S. And at two N rounds, we see that this guy just needs to send R.  And the last guy basically has all the relations that he wants to compute the join at around  three N rounds.  So of course this is pretty dumb, right?  Because I'm not using anything about the query.  This might as well work for any query with four relations.  So I have to do something smart.  But for that, I'm going to recap our example slightly.  So what I'm going to do is I'm going to take the same set of tables that I took back then.  But I'm going to sort of project them to the values of A. I'm going to treat this  star query as a set intersection query on A. And now I have R of A, S of A, T of A,  and U of A. As you can see, S of A and T of A are pretty useless, right?  Because they have all the entries anyways.  So and capital N is five here.  So these are subsets of this guy.  Now yeah, this is something that theoretical people are always accused of.  I'm going to recast this problem as set intersection.  And then what I'm going to do here is basically I'm going to start with R of A's value, one.  Now R is going to send this value.  S is going to check if it's present and it's stable.  It's present, so it's going to pass it on.  T is going to do the same, pass it on.  But U does not have it, as you can see.  U has only two.  It doesn't have one.  So the result is zero of the BCQ query.  But what happens with four?  So R A is going to send four.  S, check, agreed.  T, check, agreed.  U, check, agreed.  So the result is one.  And we have the result that computes this.  So it's not too hard to see that this can be done in time that's in the order of the  size of the relation because in some sense the projection is also going to be bounded  by the size of the relation.  And the idea here is to basically clue on set intersection.  Again, this is not new.  This was already studied and shut up by the Airtol's paper.  But translating it to joins is the new novelty here in some sense.  So yeah, like I promised earlier, topology does matter.  So if you consider a more general case where you have a star with k plus one vertices,  that is k relations.  Now, if G is a line and you try to compute on it, you will actually do something like  O of n plus k.  But if G is a clique with k vertices, then you can do n by k plus k because you sort  of fully exploit the power of your topology.  And I mean, I'm not sure how much time I'll have to go on detail about these things, but  please forgive me for that.  So now the database grandma always says that if you can do something for stars, you can  do something for trees as well.  And we basically obey the grandma.  So what we do is we start with a recursive protocol, which considers stars from bottom  up and then evaluates and stores the result at the center and then continues this process.  So the lower bounds, I mean, I just showed the upper bound.  The lower bounds are based on fundamental connections to this two-party problem called  set disjointness.  And the details are in the poster.  So please do visit it.  The list leads to generalization.  So I mean, we can extend the results to simple graph sets from stars and to hypergraphs as  well with some kind of gaps, which are dependent on this average degree that I mentioned to  you about.  So yeah, I mean, maybe I should spend the rest of the time talking about this new connection.  So yeah, I'm going to talk about this matrix chain vector multiplication.  So the idea is you're given a set of players and then one guy has the vector and a bunch  of these guys have these matrices.  And the goal is to compute this guy, a k times blah.  And the question is how many rounds are needed for computing this?  So I'm going to assume k is equal to 3, but the trivial protocol is what?  So the protocol is simple, right?  So this p0 sends x to p1, and this guy computes a1x.  He sends a1x to p2.  This guy computes a2, a1x, and then so on.  So this takes o of kn rounds, o of 3n rounds, right?  The surprising fact is this.  This bond is actually tight.  So I'll show you how.  So the thing is here, we have to use a more fancier version of randomness, which is called  min entropy.  So the idea is to, yeah, so I mean, just one thing that I would like to mention is the two  party techniques that I spoke to you about give only a very weaker lower bond, but we  want something that's dependent on k.  So the idea is to show that up to n rounds, x is almost completely random to p1.  So whatever he computes is useless.  And same way, up to two rounds, a1x is almost completely random to this guy.  And in 3n rounds, a3, this product is completely random to the last player.  So this immediately gives us a lower bound of omega kn.  That's the idea.  So the idea here is still kn rounds.  Whatever you get is absolutely useless.  And only at the kn-th round, you will actually get something that's meaningful for you.  So yeah, if I made my model very rosy, there is a reality check ahead.  So we assume that the size of the input table is much larger than the size of g.  There is this other paper by Afrati et al that does not make this assumption and still  computes joints in the distributed setting.  And we also assume that the players know both hng, which is kind of nicer.  But it's also worthwhile to look at models where they don't have this awareness.  And we also assume that the relations are systematically distributed to players in g.  Again, so it would be nice to actually remove this assumption, but our lower bonds don't  somehow generalize to those settings.  So what is the road ahead?  So can we address the gap between our upper and lower bonds when you have average degree  d?  Because when it's constant, we have tight.  But when it's not constant, it turns out that it's tied to this fundamental problem  in computational complexity, which is about proving super linear lower bonds when h is  a clique, when you have a clique query.  So and we don't handle node failures, which I think some of the models of B metaldas, we  don't do that either.  And when hng is same, that is the topology matches the query, the question is, can we  do better?  And we don't know anything in that setup either.  So never let us say thanks to these people, some of whom are here actually.  So thanks people.  And okay.  Thank you.
Langberg_Li_Jayaraman_Rudra_0_131.png Langberg_Li_Jayaraman_Rudra_132_719.png Langberg_Li_Jayaraman_Rudra_720_995.png Langberg_Li_Jayaraman_Rudra_996_2591.png Langberg_Li_Jayaraman_Rudra_2592_3299.png Langberg_Li_Jayaraman_Rudra_3300_6467.png Langberg_Li_Jayaraman_Rudra_6468_9299.png Langberg_Li_Jayaraman_Rudra_9300_12683.png Langberg_Li_Jayaraman_Rudra_12684_13355.png Langberg_Li_Jayaraman_Rudra_13356_13799.png Langberg_Li_Jayaraman_Rudra_13800_15203.png Langberg_Li_Jayaraman_Rudra_15204_16007.png Langberg_Li_Jayaraman_Rudra_16008_19751.png Langberg_Li_Jayaraman_Rudra_19752_20195.png Langberg_Li_Jayaraman_Rudra_20196_20807.png Langberg_Li_Jayaraman_Rudra_20808_22883.png Langberg_Li_Jayaraman_Rudra_22884_23519.png Langberg_Li_Jayaraman_Rudra_23520_24935.png Langberg_Li_Jayaraman_Rudra_24936_25103.png Langberg_Li_Jayaraman_Rudra_25104_25223.png Langberg_Li_Jayaraman_Rudra_25224_25353.png