Skip to content

Commit

Permalink
feat(matching): initial implementation of assignment problem
Browse files Browse the repository at this point in the history
  • Loading branch information
jpedroh committed May 1, 2024
1 parent 31ea3c8 commit 2a1a72c
Show file tree
Hide file tree
Showing 8 changed files with 269 additions and 7 deletions.
124 changes: 118 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions bin/tests/scenarios/unordered_non_labelled/base.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
public class Main {
static {
System.out.println("I'm a static block");
}
}
9 changes: 9 additions & 0 deletions bin/tests/scenarios/unordered_non_labelled/left.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
public class Main {
static {
int x = 0;
}

static {
System.out.println("I'm a static block");
}
}
1 change: 1 addition & 0 deletions bin/tests/scenarios/unordered_non_labelled/merge.java
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
public class Main { static { int <<<<<<<<< x ========= y >>>>>>>>> = <<<<<<<<< 0 ========= 2 >>>>>>>>> ; } static { System . out . println ( "I'm a static block" ) ; } static { System . out . println ( "I don't know what's going on" ) ; } }
13 changes: 13 additions & 0 deletions bin/tests/scenarios/unordered_non_labelled/right.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
public class Main {
static {
System.out.println("I'm a static block");
}

static {
int y = 2;
}

static {
System.out.println("I don't know what's going on");
}
}
1 change: 1 addition & 0 deletions matching/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ model = { path = "../model" }
matching_handlers = { path = "../matching_handlers" }
unordered-pair = "0.2.4"
log = { workspace = true }
pathfinding = "4.9.1"

[dev-dependencies]
uuid = { workspace = true }
116 changes: 116 additions & 0 deletions matching/src/assignment_problem/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
use std::cmp::max;

use matching_handlers::MatchingHandlers;
use model::{
cst_node::{NonTerminal, Terminal},
CSTNode,
};
use pathfinding::{kuhn_munkres::Weights, matrix};
use unordered_pair::UnorderedPair;

use crate::{calculate_matchings, MatchingEntry, Matchings};

pub fn assignment_problem_unordered_tree_matching<'a>(
left: &'a CSTNode,
right: &'a CSTNode,
matching_handlers: &'a MatchingHandlers<'a>,
) -> crate::Matchings<'a> {
match (left, right) {
(
CSTNode::Terminal(Terminal {
kind: kind_left,
value: value_left,
..
}),
CSTNode::Terminal(Terminal {
kind: kind_right,
value: value_right,
..
}),
) => {
let is_perfetch_match = kind_left == kind_right && value_left == value_right;
Matchings::from_single(
UnorderedPair(left, right),
MatchingEntry::new(is_perfetch_match.into(), is_perfetch_match),
)
}
(
CSTNode::NonTerminal(NonTerminal {
kind: kind_left,
children: children_left,
..
}),
CSTNode::NonTerminal(NonTerminal {
kind: kind_right,
children: children_right,
..
}),
) => {
let root_matching: usize = (kind_left == kind_right).into();

let matchings: Vec<Vec<(usize, Matchings<'a>)>> = children_left
.iter()
.map(|left_child| {
children_right
.iter()
.map(|right_child| {
let w = calculate_matchings(left_child, right_child, matching_handlers);
let matching = w
.get_matching_entry(left_child, right_child)
.unwrap_or_default();
(matching.score, w)
})
.collect()
})
.collect();

return solve_assignment_problem(left, right, matchings, root_matching);
}
(_, _) => unreachable!("Invalid configuration reached"),
}
}

fn solve_assignment_problem<'a>(
left: &'a CSTNode,
right: &'a CSTNode,
children_matchings: Vec<Vec<(usize, Matchings<'a>)>>,
root_matching: usize,
) -> Matchings<'a> {
let m = children_matchings.len();
let n = children_matchings[0].len();
let max_size = max(m, n);

let mut matrix: Vec<Vec<i32>> = vec![vec![0; max_size]; max_size];
for i in 0..m {
for j in 0..n {
matrix[i][j] = children_matchings[i][j].0.try_into().unwrap();
}
}

let weights_matrix = matrix::Matrix::from_rows(matrix)
.expect("Could not build weights matrix for assignment problem.");
let (_, best_matches) = pathfinding::kuhn_munkres::kuhn_munkres(&weights_matrix);

let mut score = 0;

let mut result = Matchings::empty();

for i in 0..best_matches.len() {
let j = best_matches[i];
let cur_matching = weights_matrix.at(i, j);
if cur_matching > 0 {
result.extend(children_matchings[i][j].1.clone());
score += children_matchings[i][j].0;
}
}

result.extend(Matchings::from_single(
UnorderedPair(left, right),
MatchingEntry {
score: score + root_matching,
is_perfect_match: left.contents() == right.contents(),
},
));

result
}
Loading

0 comments on commit 2a1a72c

Please sign in to comment.