Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "PatchCat"]
path = PatchCat
url = https://github.com/karineek/PatchCat
1 change: 1 addition & 0 deletions PatchCat
Submodule PatchCat added at 693e2e
5 changes: 4 additions & 1 deletion src/main/java/gin/util/GP.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ public abstract class GP extends Sampler {
@Argument(alias = "pb", description = "Probability of combined")
protected Double combinedProbablity = 0.5;

@Argument(alias = "pc", description = "Enable patchCat")
protected Boolean patchCat = false;

// Allowed edit types for sampling: parsed from editType
protected List<Class<? extends Edit>> editTypes;

Expand Down Expand Up @@ -159,7 +162,7 @@ protected void writeNewHeader() {
}
}

protected void writePatch(int iteration, int evaluationNumber, UnitTestResultSet results, String methodName, double fitness, double improvement) {
protected void writePatch(int iteration, int evaluationNumber, UnitTestResultSet results, String methodName, Double fitness, double improvement) {
String[] entry = { methodName
, Integer.toString(iteration)
, Integer.toString(evaluationNumber)
Expand Down
131 changes: 120 additions & 11 deletions src/main/java/gin/util/LocalSearchSimple.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import gin.edit.llm.LLMMaskedStatement;
import gin.edit.llm.LLMReplaceStatement;
import gin.test.UnitTest;
import gin.test.UnitTestResult;
import gin.test.UnitTestResultSet;
import org.pmw.tinylog.Logger;

Expand All @@ -21,7 +22,11 @@
import java.util.List;
import java.util.Map;
import java.util.Random;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Method-based LocalSearchSimple search.
Expand Down Expand Up @@ -90,6 +95,64 @@ private void SetLLMedits () {
@Override
protected abstract boolean fitnessThreshold(UnitTestResultSet results, double orig);

public String clusterAction(int cluster) throws IOException{
switch (cluster) {
case 4:
case 10:
case 15:
case 17:
return "A";
case 0:
case 3:
case 5:
case 7:
case 8:
case 9:
case 11:
case 12:
case 13:
case 14:
case 16:
return "B";
case 1:
case 2:
case 6:
return "C";
}
throw new IOException("Clustering Failed");
}

public void implementClusterAction(String action, String className, String methodName, List<UnitTest> tests, Patch patch, Patch bestPatch, Double orig, Double best, int iteration) {
// ACTION C - Throw away patch
if (action == "C") {
return;
}

// ACTION B - Proceed as normal
if (action == "B") {

//Calculate fitness
UnitTestResultSet results = testPatch(className, tests, patch, null);
double newFitness = fitness(results);
super.writePatch(iteration, iteration, results, methodName, newFitness, compareFitness(newFitness, orig));

// Check if better
if (compareFitness(newFitness, best) > 0) {
best = newFitness;
bestPatch = patch;
}
return;
}

// ACTION A- Skip testing and keep patch- we need to figure out how to do this
else {
//Add dummy fitness entry as we don't want to test the patch
UnitTestResultSet results = new UnitTestResultSet(patch, "", true, new ArrayList<Boolean>(), true, "", true, new ArrayList<UnitTestResult>()); //CH: two empty strings here OK?
super.writePatch(iteration, iteration, results, methodName, null, 0); //CH: is iteration for evaluationNumber here correct?
bestPatch = patch;
}
}

/*============== Implementation of abstract methods ==============*/

/*====== Search ======*/
Expand Down Expand Up @@ -118,16 +181,62 @@ protected void search(TargetMethod method, Patch origPatch) {

// Add a mutation
Patch patch = neighbour(bestPatch);

// Calculate fitness
results = testPatch(className, tests, patch, null);
double newFitness = fitness(results);
super.writePatch(i, i, results, methodName, newFitness, compareFitness(newFitness, orig));

// Check if better
if (compareFitness(newFitness, best) > 0) {
best = newFitness;
bestPatch = patch;
Logger.info("Patch is: " + patch.toString());
Logger.info("Original Patch is: " + origPatch.toString());

try {
// Support for PatchCat Integration
if (Boolean.TRUE.equals(patchCat)) {
Logger.info("Running PatchCat");

ProcessBuilder builder = new ProcessBuilder(
"python3",
"../gin-llm/clustering/PatchCat/PatchCat.py",
patch.toString(), origPatch.toString()
);

builder.environment().put("PYTHONUNBUFFERED", "1");

Process process = builder.start();
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream())
);
String line = reader.readLine();
int cluster = -1;

Logger.info("Line is: " + line);
if (line != null && !line.isEmpty()) {
// Regex to capture digits inside [..], e.g. [13]
Pattern pattern = Pattern.compile("\\[(\\d+)]");
Matcher matcher = pattern.matcher(line);

if (matcher.find()) {
String numStr = matcher.group(1); // "13"
cluster = Integer.parseInt(numStr);
Logger.info("Cluster is: " + cluster);
}
}

String action = clusterAction(cluster);

int exit = process.waitFor();

implementClusterAction(action, className, methodName, tests, patch, bestPatch, orig, best, i);
} else { // Regular Local Search without PatchCat
// Calculate fitness
results = testPatch(className, tests, patch, null);
double newFitness = fitness(results);
super.writePatch(i, i, results, methodName, newFitness, compareFitness(newFitness, orig));

// Check if better
if (compareFitness(newFitness, best) > 0) {
best = newFitness;
bestPatch = patch;
}
}
} catch (IOException | InterruptedException e) {
Logger.info("Running PatchCat Failed");
e.printStackTrace();
}
}
}
Expand Down
Loading