Traversal of EdgeReversedGraph - jgrapht

I created a SimpleDirectedGraph and traversed it using a BreadthFirstIterator. Then I created an EdgeReversedGraph of the first graph and traversed that. I was expected the output to be inverted but it's basically the same.
The code is:
public class TestJGraphT {
private static Graph<String, DefaultEdge> createStringGraph() {
Graph<String, DefaultEdge> g = new SimpleDirectedGraph<>(DefaultEdge.class);
String v1 = "v1";
String v2 = "v2";
String v3 = "v3";
String v4 = "v4";
String v5 = "v5";
String v6 = "v6";
String v7 = "v7";
// add the vertices
g.addVertex(v1);
g.addVertex(v2);
g.addVertex(v3);
g.addVertex(v4);
g.addVertex(v5);
g.addVertex(v6);
g.addVertex(v7);
// add edges
g.addEdge(v1, v2);
g.addEdge(v1, v3);
g.addEdge(v3, v4);
g.addEdge(v4, v5);
g.addEdge(v5, v7);
g.addEdge(v3, v6);
g.addEdge(v6, v7);
return g;
}
public static void main(String[] args) {
Graph<String, DefaultEdge> stringGraph = createStringGraph();
BreadthFirstIterator<String, DefaultEdge> iterator = new BreadthFirstIterator<>(stringGraph);
System.out.println("\n\n\nGraph BreadthFirst\n");
while (iterator.hasNext()) {
String node = iterator.next();
System.out.println(node);
}
Graph<String, DefaultEdge> stringGraphReversed = new EdgeReversedGraph<String, DefaultEdge>(stringGraph);
BreadthFirstIterator<String, DefaultEdge> iteratorReversed = new BreadthFirstIterator<>(stringGraphReversed);
System.out.println("\n\n\nReversed Graph BreadthFirst\n");
while (iteratorReversed.hasNext()) {
String node = iteratorReversed.next();
System.out.println(node);
}
}
}
The output is:
Graph BreadthFirst
v1
v2
v3
v4
v6
v5
v7
Reversed Graph BreadthFirst
v1
v2
v3
v4
v5
v6
v7
I was expecting the EdgeReversedGraph to print v7, v6, v5 ...
How do I visit the nodes in the first graph depth first where v7 is considered the "deepest" node?

I see. I need to pass the starting node to the iterator:
BreadthFirstIterator<String, DefaultEdge> iteratorRev = new BreadthFirstIterator<>(stringGraphReversed, "v7");

Related

JFreeChart disable vertical gray areas of XYPlot

The code below plots a graph with unwanted vertical gray areas (stripes) corresponding with alternate domain ticks.
I have tried unsuccessfully to remove them from the graph to obtain a plot with white background.
I have been searching through the methods of XYPlot or NumberAxis (last try was setting to null xyplot.setDomainTickBandPaint(null); and xyplot.setRangeTickBandPaint(null);), but I have not experience enough with JFreeChart to know what method to use.
This is the code for the above graph:
public class MyPlotChart {
private static Color MetalColor = new Color(255, 152, 0);
static double[] yData = new double[] { 49.68, 49.18, 49.78, 49.65, 48.94, 50.02, 50.27};
static String[] labels = new String[] { "2021-10-28", "2021-10-29", "2021-11-01", "2021-11-02", "2021-11-03", "2021-11-04", "2021-11-05"};
public static void plot(String metal, int samples) throws IOException {
XYSeries series = new XYSeries(metal);
int i = 0;
for (i = 0; i < yData.length; i++) {
series.add(i, yData[i]);
}
XYDataset dataset = new XYSeriesCollection(series);
NumberAxis domain = new SymbolAxis(null, labels);
NumberAxis verticalAxis = new NumberAxis(null);
verticalAxis.setAutoRangeIncludesZero(false);
domain.setTickUnit(new NumberTickUnit(1.0));
domain.setMarkerBand(null);
double vericalTickUnit = (series.getMaxY() - series.getMinY()) / 5;
NumberFormat numberFormat = NumberFormat.getInstance(Locale.getDefault());
numberFormat.setRoundingMode(RoundingMode.HALF_DOWN);
numberFormat.setMinimumFractionDigits(2);
numberFormat.setMaximumFractionDigits(2);
NumberTickUnit nt = new NumberTickUnit(vericalTickUnit, numberFormat);
verticalAxis.setTickUnit(nt);
verticalAxis.setAutoRange(true);
verticalAxis.setRange(new Range(series.getMinY()-0.1, series.getMaxY()+0.1));
verticalAxis.setTickMarksVisible(true);
verticalAxis.setTickMarkInsideLength(3f);
XYSplineRenderer r = new XYSplineRenderer(10);
r.setSeriesPaint(0, MetalColor);
r.setDefaultShapesVisible(false);
r.setSeriesStroke(0, new BasicStroke(3.0f));
XYPlot xyplot = new XYPlot(dataset, domain, verticalAxis, r);
xyplot.getDomainAxis().setVerticalTickLabels(true);
xyplot.setDomainGridlinesVisible(false);
xyplot.setBackgroundImage(null);
xyplot.setBackgroundPaint(Color.WHITE);
Font font = xyplot.getDomainAxis().getTickLabelFont();
Font fontnew = new Font(font.getName(), Font.BOLD, 14);
xyplot.getDomainAxis().setTickLabelFont(fontnew);
xyplot.getRangeAxis().setTickLabelFont(fontnew);
JFreeChart chart = new JFreeChart(xyplot);
chart.removeLegend();//Remove legend
chart.setBackgroundPaint(Color.WHITE);
String fileName = "myChart"+metal+samples+"TEST.png";
ChartUtils.saveChartAsPNG(new File(fileName), chart, 600, 600);
}
public static void main(String[] args) throws IOException {
MyPlotChart.plot("metal", 7);
}
}
As suggested in the comment, I opted to use DateAxis which do not implement alternating background and also gives more accurate treatment for tick labels when the data is time related.
I have attached the code and the plot obtained:
public class MyPlotChart {
private static Color MetalColor = new Color(255, 152, 0);
static double[] yData = new double[] { 49.68, 49.18, 49.78, 49.65, 48.94, 50.02, 50.27 };
static String[] labels = new String[] { "2021-10-28", "2021-10-29", "2021-11-01", "2021-11-02", "2021-11-03",
"2021-11-04", "2021-11-05" };
public static void plot(String metal, int samples) throws IOException, ParseException {
SimpleDateFormat dateformatyyyy_MM_dd = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat dateformatdd_MM_yyyy = new SimpleDateFormat("dd-MM-yyyy");
XYSeries series = new XYSeries(metal);
for (int i = 0; i < yData.length; i++) {
Date date = dateformatyyyy_MM_dd.parse(labels[i]);
series.add(date.getTime(), yData[i]);
}
//Configure Vertical Axis
NumberAxis verticalAxis = new NumberAxis(null);
NumberFormat numberFormat = NumberFormat.getInstance(Locale.getDefault());
numberFormat.setRoundingMode(RoundingMode.HALF_DOWN);
numberFormat.setMinimumFractionDigits(2);
numberFormat.setMaximumFractionDigits(2);
double vericalTickUnit = (series.getMaxY() - series.getMinY()) / 7;
NumberTickUnit nt = new NumberTickUnit(vericalTickUnit, numberFormat);
verticalAxis.setTickUnit(nt);
double percentOverRange = 0.05;// 2%
double initalRange = series.getMaxY() - series.getMinY();
double increase = initalRange * percentOverRange;
verticalAxis.setRange(new Range(series.getMinY()-increase, series.getMaxY()+increase));
verticalAxis.setAutoRange(true);
verticalAxis.setAutoRangeIncludesZero(false);
verticalAxis.setTickMarksVisible(true);
verticalAxis.setTickMarkInsideLength(3f);
//Configure Domain Axis
DateAxis domainAxis = new DateAxis(null);
domainAxis.setTickUnit(new DateTickUnit(DateTickUnitType.DAY, 1, dateformatdd_MM_yyyy));
//Configure Renderer
XYSplineRenderer r = new XYSplineRenderer(10);
r.setSeriesPaint(0, MetalColor);
r.setDefaultShapesVisible(false);
r.setSeriesStroke(0, new BasicStroke(3.0f));
XYDataset dataset = new XYSeriesCollection(series);
XYPlot xyplot = new XYPlot(dataset, domainAxis, verticalAxis, r);
xyplot.getDomainAxis().setVerticalTickLabels(true);
xyplot.setDomainGridlinesVisible(false);
xyplot.setBackgroundImage(null);
xyplot.setBackgroundPaint(Color.WHITE);
Font font = xyplot.getDomainAxis().getTickLabelFont();
Font fontnew = new Font(font.getName(), Font.BOLD, 14);
xyplot.getDomainAxis().setTickLabelFont(fontnew);
xyplot.getRangeAxis().setTickLabelFont(fontnew);
JFreeChart chart = new JFreeChart(xyplot);
chart.removeLegend();// Remove legend
chart.setBackgroundPaint(Color.WHITE);
String fileName = "myChart" + metal + samples + "TEST.png";
ChartUtils.saveChartAsPNG(new File(fileName), chart, 600, 600);
}
public static void main(String[] args) throws IOException, ParseException {
MyPlotChart.plot("metal", 7);
}
}

Solr's labelled relationship indexation performance

I want to move from anonymous relationships (childDocuments) to labelled.
During testing, performance degradation was detected when integrating documents into Solr on identical schemas and documents.
Solr (8.1.1) configuration (local, 1 node, default settings): solr -e cloud
Test: start integration of 500 documents several times and calculate the average integration time.
Labelled relationship example:
{
"id": "parent_xxx",
"items": [{"id": "child_xxx"}]
}
Anonymous relationship example:
{
"id": "parent_xxx",
"_childDocuments_": [{"id": "child_xxx"}]
}
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.common.SolrInputDocument;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class Scratch {
private static final int DOC_COUNT = 500;
private static final int ITERATION_COUNT = 5;
private static final boolean ANONYMOUS_CHILDREN = true;
private static final boolean LABELED_CHILDREN = false;
public static void main(String[] args) throws IOException, SolrServerException {
long anonymousTime = 0;
long labelledTime = 0;
for (int i = 0; i < ITERATION_COUNT; i++) {
List<SolrInputDocument> anonymousDocs = createSolrDocuments(ANONYMOUS_CHILDREN);
cleanSolrCollection();
anonymousTime += writeToSolr(anonymousDocs);
List<SolrInputDocument> labeledDocs = createSolrDocuments(LABELED_CHILDREN);
cleanSolrCollection();
labelledTime += writeToSolr(labeledDocs);
}
System.out.println("Avg anonymous time: " + (anonymousTime / ITERATION_COUNT));
System.out.println("Avg labelled time: " + (labelledTime / ITERATION_COUNT));
}
private static List<SolrInputDocument> createSolrDocuments(boolean isAnonymous) {
List<SolrInputDocument> request = new ArrayList<>();
for (int i = 0; i < DOC_COUNT; i++) {
SolrInputDocument parent = new SolrInputDocument();
parent.setField("id", "parent_" + i);
SolrInputDocument child = new SolrInputDocument();
child.setField("id", "child_" + i);
if (isAnonymous) {
parent.addChildDocument(child);
} else {
parent.addField("items", child);
}
request.add(parent);
}
return request;
}
private static void cleanSolrCollection() throws IOException, SolrServerException {
try (SolrClient client = getSolrClient()) {
client.deleteByQuery("main", "*:*");
}
}
private static long writeToSolr(List<SolrInputDocument> documents) throws IOException, SolrServerException {
long startAt = System.currentTimeMillis();
try (SolrClient client = getSolrClient()) {
client.add("main", documents);
}
return System.currentTimeMillis() - startAt;
}
private static SolrClient getSolrClient() {
return new HttpSolrClient.Builder("http://localhost:8983/solr")
.allowCompression(true)
.build();
}
}
Results:
500 docs with anonymous relationship ~ 29ms
500 docs with labelled relationship ~ 981ms
Is it normal behavior for Solr when working with named relationships?
I have not been able to find any information about that.
The performance difference of 20-30 times does look strange.

Oxyplot- WPF: Adding data from a List of double to DataPoint

I am new to WPF and the project I'm working on requires me to plot a list of double on XY chart. I added Oxyplot to my project for the charting but I'm having challenges to get a plot.
I followed the example on Oxyplot site (see code below), but I discovered that the DataPoint can only accept double values of x and y not array or list of doubles.
How can I plot List<double> for XValues and List<double> for YValues?
namespace WpfApplication2
{
using System.Collections.Generic;
using OxyPlot;
public class MainViewModel
{
public MainViewModel()
{
this.Title = "Example 2";
this.Points = new List<DataPoint>
{
new DataPoint(0, 4),
new DataPoint(10, 13),
new DataPoint(20, 15),
new DataPoint(30, 16),
new DataPoint(40, 12),
new DataPoint(50, 12)
};
}
public string Title { get; private set; }
public IList<DataPoint> Points { get; private set; }
}
}
I really don't see why you cannot directly store a list of DataPoint... but let's say you're stucked with your 2 lists and I'm assuming that your lists have same length (if not you have an issue since all points to draw should have an X and Y value).
So I guess something like that:
List<double> XValues = new List<double> { 0, 5, 10, 22, 30 };
List<double> YValues = new List<double> { 2, 11, 4, 15, 20 };
for (int i = 0; i < XValues.Count; ++i)
{
Points.Add(new DataPoint(XValues[i], YValues[i]));
}
It's not really elegant and if you are the one creating the lists you should merge them into a list of DataPoint like said #PaoloGo. If you prefer to use a custom object in case you don't use oxyplot, you can create a simple one like that for example:
public struct ChartPoint
{
public double X;
public double Y;
public ChartPoint(double x, double y)
{
X = x;
Y = y;
}
}
And then you store this:
List<ChartPoint> points;

Shuffle list to maximise distances between similar elements

In a list of URLs
http://a.com/foo
http://b.com/bar
http://a.com/monkey
http://c.com/prune
http://a.com/bear
http://b.com/walrus
http://b.com/baz
http://b.com/plugh
I want to maximise the distance between any pair of a.com's, any pair of b.com's etc. This needs to be cheap but does not have to be optimum. (I am using a list of URLs to download files from websites a.com, b.com, c.com, and do not wish to visit any particular site with a higher frequency than necessary. In the example here, we would hit the b.com site 3 times in succession, which should be avoided.)
I would ideally like a Java library but would settle for pseudocode.
Maximise sum of pairwise distances in array seems to be a similar problem but didn't have a simple answer - I simply want something that's "good enough"
Since no answers, I wrote my own. It's very crude but works. It reads a list of URLs, extracts the hosts, counts them and then fills a pigeon-hole array with indexes proportional to the inverse frequency of the hosts.
package org.xmlcml.cmine.util;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
public class URLShuffler {
public static final Logger LOG = Logger.getLogger(URLShuffler.class);
static {
LOG.setLevel(Level.DEBUG);
}
// in case we needed extra pigeonholes but it doesn't seem to for medium problems
private static int TOL = 1;
private List<String> urls;
private Multiset<String> domains;
private Map<String, Integer> currentIndexByDomain;
private Map<String, Integer> countByDomain;
private List<String> outputUrls;
public URLShuffler() {
}
public void readURLs(List<String> urls) {
this.urls= urls;
domains = HashMultiset.create();
for (String url : urls) {
String domain = getDomain(url);
domains.add(domain);
}
LOG.debug(domains);
}
// this would be better using java.net.URL
private String getDomain(String url) {
int idx = url.indexOf("//");
if (idx != -1) {
url = url.substring(idx+2);
}
idx = url.indexOf("/");
String domain = url.substring(0, idx);
return domain;
}
public List<String> getShuffledUrls() {
currentIndexByDomain = new HashMap<String, Integer>();
countByDomain = new HashMap<String, Integer>();
outputUrls = new ArrayList<String>();
for (int i = 0; i < urls.size() * TOL; i++) {
outputUrls.add("");
}
// this is a convenience method wrapping Guava sort.
for (Multiset.Entry<String> entry : CMineUtil.getEntriesSortedByCount(domains)) {
LOG.debug(entry);
countByDomain.put(entry.getElement(), entry.getCount());
currentIndexByDomain.put(entry.getElement(), entry.getCount() - 1);
}
for (String url : urls) {
String domain = getDomain(url);
Integer currentIndex = currentIndexByDomain.get(domain);
Integer count = countByDomain.get(domain);
int slot = (urls.size() * currentIndex * TOL) / count;
currentIndexByDomain.put(domain, currentIndex - 1);
addUrl(url, slot);
}
return outputUrls;
}
private void addUrl(String url, int slot) {
boolean filled = fillLower(url, slot);
if (!filled) {
fillUpper(url, slot);
}
}
// if slot is not free run upwards till next free slot
private boolean fillUpper(String url, int slot) {
for (int i = slot; i < outputUrls.size(); i++) {
if (fill(url, i)) {
return true;
}
}
return false;
}
// if slot is not free run downwards till next free slot
private boolean fillLower(String url, int slot) {
for (int i = slot; i >= 0; i--) {
if (fill(url, i)) {
return true;
}
}
return false;
}
private boolean fill(String url, int slot) {
if (outputUrls.get(slot).equals("")) {
outputUrls.set(slot, url);
return true;
}
return false;
}
}
```

to display the data obtained from button listener to list- codename one

I have a button that display the data obtained from json. below is my code for button action. I need help to display the data obtained to list.
#Override
protected void onMain_ButtonAction(final Component c, ActionEvent event) {
ConnectionRequest r = new ConnectionRequest() {
Hashtable h;
#Override
protected void postResponse() {
}
#Override
protected void readResponse(InputStream input) throws IOException {
InputStreamReader reader = new InputStreamReader(input);
JSONParser p = new JSONParser();
h = p.parse(new InputStreamReader(input));
Hashtable response = p.parse(reader);
Hashtable feed = (Hashtable)response.get("root");
for (Object s : h.values()) {
Vector vec = new Vector(100);
vec = (Vector)s;
int i;
for(i = 0; i<vec.size(); i++){
Hashtable<String, String> ht= (Hashtable<String, String>) vec.get(i);
System.out.println(ht.get("location"));
// findLabel().setText(ht.get("location"));
}
}
}
};
r.setUrl("http://ruslanapp.demo.capitaleyenepal.com/vodka-mobile-interface/getData/locations");
r.setPost(false);
InfiniteProgress prog = new InfiniteProgress();
Dialog dlg = prog.showInifiniteBlocking();
r.setDisposeOnCompletion(dlg);
NetworkManager.getInstance().addToQueue(r);
}
I want to list the data obtained frm btn above to the list below. how can I do it??
#Override
protected boolean initListModelList1(List cmp) {
cmp.setModel(new com.codename1.ui.list.DefaultListModel(new String[] {"Item 1", "Item 2", "Item 3"}));
return true;
}
You did most of the work well, I suggest avoiding a list and using an infinite container. The PropertyCross demo has pretty much this functionality (including JSON): https://www.udemy.com/learn-mobile-programming-by-example-with-codename-one/
To finish the code above create the model ArrayList above e.g. assuming you are using a MultiList:
// define this in the class variables:
private ArrayList<Map<String, String>> modelData = new ArrayList<Map<String, String>>();
// then in the code (I assumed stuff about your JSON, correct the
// code to extract the data correctly, just set the hashmap values
for (Object s : h.values()) {
Collection<Map<String, String>>) data = (Collection<Map<String, String>>))s;
for(Map<String, String> ht : data) {
String location = ht.get("location");
HashMap<String, String> entry = new HashMap<String, String>();
entry.put("Line1", location);
modelData.add(entry);
}
}
Then in:
#Override
protected boolean initListModelList1(List cmp) {
cmp.setModel(new DefaultListModel(modelData));
return true;
}
Notice that you should use showForm() to show the next form in the postResponse method.

Resources