CSTNU Tool Releases
Binary releases of CSTNU Tool are freely available at https://profs.scienze.univr.it/~posenato/software/cstnu/bin
The source code is available at https://archive.softwareheritage.org/browse/origin/directory/?origin_url=https://profs.scienze.univr.it/posenato/svn/sw/CSTNU
RELEASE NOTES
v7.2
Date: not released yet; in development.
SVN revisions: r1181–TBD (r1181 is the first revision of this cycle, the one that opened it by moving the
version in pom.xml to 7.2; the final revision will be the release commit).
The version in pom.xml moved to 7.2 as the first act of the cycle so that the artefacts of the work that
follows — CSTNU-Tool-7.2.jar and CstnuTool-7.2.tgz, both named after ${project.version} — cannot
overwrite the 7.1 ones, which stay the published reference until the next release. codemeta.json still
describes 7.1, the released version, and moves at release time.
Updated the following classes:
STNU:applySRNCycleFinderno longer stores a generating path per node; a check of a non-controllable network costs 31% less (r1187). The back-propagation kept, for every node, the whole path towards the upper-case edge being bypassed, and copied it on every improving relaxation. Over the 1599 sparse non-controllable instances of the 2020 STNU benchmarks: 160 084 relaxations per instance, each copying a path of 44.2 edges on average (median 34, longest 632), about 7.1 million edge copies per instance, each discarded by the next relaxation. The path is now one(edge, node)pair per node — the representationSRNCycleFinderUpdatePotentialhas used since r1174 — materialised only at the five points that consume it, by the newSRNCycleFinderPathTo. A relaxation costs O(1); the memory per contingent link is O(n) instead of O(n × path length). Three further changes on the same loop:SRNCycleFinderApplyRLreturns the source node it already holds, in the new recordSRNCRelaxedEdge, instead of leaving the caller to recover it from the graph (441 022 lookups per instance); an unreachable early return is removed, together with theDeltaCparameter that only it used; one queue look-up replaces two, throughExtendedPriorityQueue.getStatusAndPriority.- Timings on vega, one process at a time, 50 instances per family, three repetitions, both jars built without
instrumentation: the sum of the
SRNCycleFindertimes over 399 instances falls from 46.23 s to 31.79 s, −31.2%; the ratio toapplyRul2021on the same instances falls from 1.475 to 0.997. Per family the reduction is between −22.7% (1000 nodes) and −38.7% (2500 nodes); above 350 contingentsSRNCycleFinderis the faster of the two. Drift control:applyRul2021, whose code did not change, measured +1.8% overall and between −7.1% and +7.6% per family, so the bench noise is about ±7%. Per-instance distribution of the post/pre ratio: median 0.924, 25th percentile 0.736, 10th percentile 0.596, 75th percentile 1.010, 90th percentile 1.079; 70% of the instances are faster, the slowest quartile is up to 8% slower, within that noise. The reduction is concentrated on the instances with long stored paths, the large and dense ones: mean path length is 19.5 edges in the densest family and 109.2 at 2500 nodes. - Output equivalence of that change: the suite asserts properties of the reported cycle, not the cycle itself. Before the change, a temporary instrumentation rebuilt every consumed path from the predecessor chain and compared it with the stored path: 1 959 685 rebuilds over the 1599 instances, zero divergences. After the change, the corpus was run again with the cycle recorded as an ordered list of edge names: the post-change run matches a pre-change run on 1599 of 1599 instances, on the verdict and on the whole cycle, edge by edge.
- The cycle reported by
applySRNCycleFinderno longer depends on the memory layout. The loop ofSRNCycleFinderBackPropagationthat generates the edgesX -> AiteratedlocalInfo.distanceFromNodeToContingent, an open hash map keyed byLabeledNode, whosehashCodeis the JVM identity hash. The adjacency of a node is insertion-ordered, so the order of that iteration became the order in whichgetInEdgesAndSourcesreturns those edges, andSRNCycleFinderUpdatePotential, called once after the loop, walks them and reports the first negative loop it meets. OnnotDC_1000nodes_100ctgs_150maxWeight_20maxCtgWeight_5lanes__093.stnuthe same network reported a cycle of value −1 under-XX:hashCode=0, 1, 2, 3 and 4 and one of value −18 under 5, both semi-reducible negative cycles of length 9; forcing the order of that single iteration swapped the two. The nodes that generate an edge are now collected first and walked in name order, which leaves the map unchanged:RULLocalInfois shared withapplyRul2021andfd_STNUgenerateBypasses, which report no witness. Only the nodes that reach the graph are ordered, not every node the back-propagation touched. After the change the six forced layouts, and three runs without them, all report the same cycle. For a given network the reported witness can differ from the one 7.1 reported; every cycle reported is a semi-reducible negative cycle of the network, and the witness is not part of any published result. STNUCheckStatus.SRNCInforeports the number of occurrences of each ordinary edge in the expanded negative cycle.getNegativeSTNUCycleInfocomputed the multiplicity of every edge of the expansion in a local map and returned only its maximum, asmaxEdgeRepetition; the multiplicity of the edges of a contingent link was available fromlowerCaseCount/upperCaseCount, that of the ordinary edges was not.PSTNuses the contingent counts as the coefficients of its optimisation problem. The new componentordinaryEdgeCountmaps each ordinary edge ofsrnExpandedto its number of occurrences. OnmagicLoop.stnu, whose 7-edge cycle expands to 22 occurrences over 12 distinct edges, it is{eC1-C2: 2, eC2-C1: 2, eC1-C3: 1, eC1-X: 1, eC3-C1: 1, eX-C1: 1}. Adding a component to the record breaks a positional construction ofSRNCInfo; the only one is inSTNU, the other consumers use the accessors.- Counting in
SRNCInfo: the counter was fed from the unexpanded cycle, derived edges included, and from the expanded sub-edges, so the map was not the multiset ofsrnExpanded. A derived edge present k times forces each of its sub-edges to be present at least k times, and the maximum agreed with an independent recount of the expansion on every non-controllable instance of the corpus. An edge is now counted when it is appended to the expansion, soordinaryEdgeCountandmaxEdgeRepetitionare functions ofsrnExpanded.maxEdgeRepetitionis 0 when the report is requested without expansion, where it described the unexpanded cycle before;SRNCFinderBenchmarkRunner, the only consumer that reads it, requests the expansion. - Edge classification in
SRNCInfo:isWait()is!isContingentEdge() && caseLabel.isUpper(), so a wait edge satisfiesisUpperCase(). Theif (edge.isWait())arm was unreachable, and a wait edge was counted inupperCaseCountunder the keyg.getSource(edge), which for a wait is not the contingent time point of a contingent link. Classification usesisOrdinaryEdge(), and an upper-case edge is counted only when it is also contingent. The kind of the edges of the cycle was decided, inside the expansion loop, by the flag of the enclosing edge instead of the edge examined; a cycle whose lower-case edges occur only inside derivations and which has no upper-case edge was reported as containing every kind. The reported kind agrees with a recount of the expansion on the 7 non-controllable instances available. - Cost of the
SRNCInforeport:getEdgePathAnnotation()rebuilds a copy of all the annotations on every call, and was called once per edge of the cycle plus once per level of recursion ofresolveEdgeDerivation. One rebuild takes 34 µs onnotDC002(384 annotations, 3231 path edges), and the loop performed sixteen of them. The accessor is called once per report and the result is passed down;resolveEdgeDerivationmemoises its resolutions, which makes resolving a cycle O(distinct derived edges × derivation size) instead of O(occurrences × derivation size). Times for the report alone, best of five rounds of 200 calls after warm-up, 7.2 jar against the new classes:notDC002204 815 → 23 103 ns,notDC03364 544 → 9 398 ns,magicLoop10 727 → 5 358 ns.resolveEdgeDerivationreturns an immutable list, and on a cyclic set of annotations it throwsIllegalStateExceptionnaming the edge instead of exhausting the stack. - Iteration order of the three multiplicity maps of
SRNCInfo: they are returned to the caller and their keys inherit the JVM identity hash, so they iterated in an order that depended on the memory layout of the run, andPSTNbuilds fromlowerCaseCount.keySet()the order of the variables it passes to the optimiser. All three areObject2IntLinkedOpenHashMapand iterate in order of first occurrence in the cycle, which the traversal supplies; the by-name order that r1178 imposed inSRNCycleFinderBackPropagationcost 4%. The maps remain mutable —PSTNremoves entries from them — and a removal preserves the order of the remaining entries. The key sequences of the three maps are equal across two runs on 4 instances, and under-XX:hashCode=0, 1, 3, 4 and 5. - Tests: ten cases in
STNUTestforSRNCInfo, withassertNegativeSRNCInfochecking the invariants of the three maps at every existing call site, andSTNUTest#srncGeneratingPathsMatchTheEdgesTheyAnnotatefor the path rebuilt bySRNCycleFinderPathTo, which must sum to the value of the edge it annotates.src/test/resources/magicLoop.stnuwas added:notDC002,notDC020andnotDC033contain derived edges and reportmaxEdgeRepetition == 1.PSTNis not run — it calls an external optimisation engine and the repository has no probabilistic instance — so the order of its variables is verified on the mechanism it uses, anObjectArraySetbuilt fromlowerCaseCount.keySet()and completed withupperCaseCount.keySet(), on 3 instances under-XX:hashCode=0 and 5.
SRNCFinderBenchmarkRunner: one CSV column added,srncEdges, the reported cycle as an ordered list of edge names joined by|. Code that reads those CSVs by column position must account for one more field per row.
v7.1
Date: 2026-09-08
SVN revisions: r1164–r1179 (r1164 opened the cycle by moving the version in pom.xml to 7.1, r1179 is the
release commit).
The release extends the set of algorithms that report the negative cycle behind an inconsistent answer, and
removes from LabeledNode the working state of four of them: a node goes from 1430 to 156 bytes.
Updated the following classes:
GraphAlgs:-
SSSP_BFCT— Bellman-Ford with Tarjan's subtree disassembly — moved here fromSTN, with its helpersSUBTREE_DISASSEMBLYandPRINT_STATUS_NODES_BFCTand withREMOVE_INTERNAL_EDGES_WITH_PREFIX, which was private inSTN.STNUcalls it to extract the negative cycle of the LO graph. Migration: callGraphAlgs.SSSP_BFCTinstead ofSTN.SSSP_BFCT; the signature is unchanged. -
The search state of
SSSP_BFCT— predecessor tree, sibling lists, reached/labeled/scanned mark — is in local arrays indexed by a dense node id instead of in the fields ofLabeledNode. The method is re-entrant: two checks on the same graph cannot interfere, and a repaint during a check cannot render a half-built search tree. The distances are returned through an optional out parameter on a new overload; the five-argument form delegates with null. The three node states are the enumBFCTNodeStatusrather than bare ints;BFCT_NONEstays an int, being the absent index in the parent and sibling arrays and not a state. -
New
GET_NEGATIVE_CYCLE(int[]): from a parent array it returns the cycle it contains, in the conventionSSSP_BFCTuses — a closed list of nodes in traversal order, consecutive pairs being edges. It is not a verdict:IS_NEGATIVE_CYCLEremains the verdict. -
GET_SSSP_BellmanFordloses thesetNodePotentialparameter, its returned map being the authoritative state. -
GET_BellmanFord_Potentialuses a queue with Tarjan's subtree disassembly instead of a round-based scan. On a network whose LO graph has a negative cycle the updates never cease, so the scan could not stop early and ran its whole budget of n rounds over m edges before answering. The queue is mirrored to the inverted update the method performs: it holds the nodes whose potential grew, and popping one rescans the edges whose destination it is. Same fixpoint, same map, samenullon a negative cycle. When the potential fails, the parent chain holds the cycle, which the method publishes inSTNCheckStatus.negativeCycleafter validating it: every consecutive pair must be an edge of the graph and the weights must sum negative, or nothing is published. Measured on the 2020 non-controllable benchmarks, in one JVM, the RUL2021 check and its potential side by side:whole RUL2021 check of which the potential with BFCT the check would be 2000 nodes, 10 instances 54.4 ms 45.8 ms (84%) 9.0 ms —6.0× 1000 nodes, 10 instances 16.3 ms 6.4 ms (39%) 10.2 ms — 1.6× Per instance the gain ranged from 5× to 102×, and it grows with the network because the term that disappears is Θ(n·m). On a controllable network nothing changes end to end: the potential is about 1.6% of a RUL2021 check and 0.5% of an MDE run.
-
STN:-
Yen's algorithm returns the negative cycle, in all three variants (
Yen,YenSingleSink,BannisterEppstein). It already maintained the parent array and walked it to detect the cycle, and then discarded it; the cycle now reaches the caller inSTNCheckStatus.negativeCycle, validated before publication. The verdict still comes fromIS_NEGATIVE_CYCLE, unchanged, so no network changes its answer. Yen keeps its distances in a local array instead of in the nodes; the random variant shuffles the node order with Fisher-Yates instead of writing random values into the node potentials. -
New
CheckAlgorithm.canGiveTheNegativeCycle(): true forBFCTand the Yen family. The two Bellman-Ford entry points report only the node where the network failed (negativeLoopNode), Floyd-Warshall and Johnson report neither, and Dijkstra does not detect negative cycles at all. For an STN the cycle is therefore always within reach: when the check ran with one of the others, one further call toSSSP_BFCTproduces one, at the 8 to 10 ms measured below, paid only on the negative answer. -
MAKE_NODES_REACHABLE_BYbecomes public, soGraphAlgscan reach it, andSSSP_BFCTmoves out (seeGraphAlgs). -
Measured on an STN of 2001 nodes and 6328 constraints (release build, best of six runs in a warm JVM, three alternating rounds against the revision before this work):
before after graph load 25.0–26.3 ms 25.0–25.6 ms BFCT 72.1–74.1 ms 7.8–10.2 ms Yen 73.3–79.8 ms 71.2–76.6 ms Yen single-sink 67.0–72.4 ms 62.7–71.9 ms Bellman-Ford 1.8–2.2 ms 2.0–2.2 ms BFCT is about eight times faster, its search state being in local arrays instead of in the nodes. Yen cost 5% more at first, an array indexed by a scattered index being less cache-friendly than a field of an object the loop already touches; removing the index lookup it performed per node per round, asking a map for a value that was the loop variable, more than paid for it.
-
STNU:-
The first step of RUL2021, RUL2018 and the FD algorithms is the potential of the LO graph, now computed with BFCT (see
GraphAlgs.GET_BellmanFord_Potential): a non-controllable network is refused sooner, andSTNCheckStatus.negativeCycleis filled by those checks too. 55% of the non-controllable instances at 1000 nodes and 68% at 2000 and 2500 are refused there, by the potential, before any upper-case edge is bypassed. The remaining refusals come from the upper-case bypass and their witness is a semi-reducible cycle involving contingent links, which is not a negative cycle of any static weighted graph:SRNCycleFinderis the only way to obtain those. Measured on STNU networks of 2001 nodes: RUL2021 0.270–0.273 s before against 0.271–0.277 s after,SRNCycleFinder0.412–0.432 s against 0.398–0.403 s, MDE 6.73–6.77 s against 6.57–6.71 s. -
findSRNCycleInLOGraphreuses the cycle the potential has already found, and keeps its ownSSSP_BFCTcall only as a fallback. -
SRNCycleFinderUpdatePotentialkeeps one edge per node instead of a whole path. It recorded, for every node whose potential it raised, the entire generating path, rebuilt by copying the path of the node the value came from, so every relaxation cost a copy of everything found so far. It records the edge that raised the node and where that edge leads, and walks that chain back only when a negative loop is detected. The cycles produced are identical over ten instances at 2000 nodes; the gain is 2 to 4% at 2000 nodes and nothing at 1000. The premium this was meant to recover —SRNCycleFinderagainst RUL2021, +44% at 1000 nodes and +114% at 2000 — was mostly the round-based potential, which the change above removed; what remains is +22% and +30%. -
Fixed:
applySRNCycleFindercould report a different negative cycle on different runs of the same network. The verdict was never in doubt, only which of the network's negative cycles came back, and five consecutive runs agree; it takes forcing different memory layouts with-XX:+UnlockExperimentalVMOptions -XX:hashCode=Nto see it. Over thirty non-controllable instances of the 2020 benchmarks, one answered with two different cycles; none does after the fix. The cause wasunStartedUCEdges, keyed byLabeledNode, which inherits the identity hash: iterating it visited the nodes in the order the objects happened to occupy in memory, and that order decides which upper-case edge is bypassed first.SRNCycleFinderBackPropagationiterates it in order of node name, the one place where the order is observable;rul2021BackPropagation, which iterates the same map, does not sort, reporting a verdict and no cycle. Fifty non-controllable instances per size, two rounds, minimum per instance, against the map iterated as it comes:1000 nodes RUL2021 / SRNCycleFinder 2000 nodes RUL2021 / SRNCycleFinder map, no order (reference) 1.418 s / 1.732 s 2.394 s / 3.269 s insertion order everywhere +0.0% / +7.3% +8.5% / +11.1% name order, only where observable −0.4% / +3.9% −0.4% / +4.2% The cost is not the container and not the sort — a few hundred names are nothing — but which order the algorithm walks, since that changes how soon a cycle closes: the order the identity hash produced was lucky on this corpus, and of the two deterministic orders, name order recovers about half of what insertion order lost. Per instance the penalty has median +1.3% and +0.4%, and at 2000 nodes 22 instances out of 43 are faster: the aggregate is a tail, not a shift. Scoping matters: an earlier version made the collection insertion-ordered for both algorithms and cost RUL2021 8.5% at 2000 nodes for a determinism it does not need. That 4% is measured on one corpus and is not a property; another corpus could invert the ranking of the two deterministic orders. What is structural is that RUL2021 pays nothing, and that name order is reproducible across releases, which insertion order is not — it follows the traversal, and the traversal changes when the code does.
-
MDELocalInfokeeps the same collection as anObjectArrayListrather than theObjectArraySetit was: nothing looks a node up in it, and a duplicate cannot arrive there because rigid components partition the nodes, so the array set paid a linear scan on every add to exclude something impossible. Its insertion order is already deterministic. -
distanceFromNodeToContingentkeeps the same exposure in principle, being iterated bykeySet()in the twin loops ofSRNCycleFinderBackPropagationandrul2021BackPropagation. No instance of the corpus was seen to depend on it, and closing it costs a further 6%, so it is documented rather than paid for blind. (Fixed in 7.2, forSRNCycleFinderBackPropagation, where an instance was found that does depend on it.) -
A checking algorithm no longer writes into the network it was given: collapsing a rigid component adjusted the log-normal distribution of a contingent duration with
setShifton the object read from the node, and the clone constructors ofLabeledNodeshare that object, so the shift reached through every copy of the node, including the one in the caller's own network. The representative gets a new parameter object (seeLogNormalDistributionParameter).
-
LabeledNode: a node goes from 1430 to 156 bytes, measured over 20 000 nodes; construction is about four times faster.predecessor,before,after,statusand theStatusenum are removed. They were the search state ofSSSP_BFCT, used in thirty-two places, all insideGraphAlgs, which now keeps them in local arrays.potentialis removed, with itsgetPotential/setPotentialand its line intoString(). It was working state of Yen and of BFCT, an output channel for the distances, and something the editor displayed. Migration: ask the algorithm for the distances instead of reading them off the nodes.labeledUpperPotentialandlabeledPotentialCountare removed: they were the working state ofCSTNPotentialand of nothing else, neither persisted nor part ofNetworkFingerprintnor displayed.labeledPotentialstays — the writer saves it, the fingerprint includes it, the editor shows it — but it is allocated on the first write and dropped byclearPotential(), and reads answer from a shared empty view. A node with a labeled potential still costs about 1200 bytes: only the nodes that need the map pay for it.
CSTNPotential: owns the two labeled maps thatLabeledNodeused to hold, per node, allocated on first use and cleared ininitAndCheck, reachable through the newgetUpperPotential/putUpperPotential.updatePotentialCountis no longer static.LabeledALabelIntTreeMap: fixed — every read-only view reported size 0. The view shares the map of the object it views but not its cached count, andsize()returned that count, soisEmpty()answered true whatever the view contained, andnode.getULCaseLabeledPotential().isEmpty()lied about every node that had a potential. The view computes its size from the map it shares, which also keeps the answer live. The sister view of the plain labeled map was never affected, which is why the GraphML writer and the fingerprint, which ask that one, have always saved potentials correctly.LogNormalDistributionParameter: immutable.setShiftis gone — it had exactly one caller, the rigid-component collapsing inSTNU— andshiftis final. Migration: build a shifted parameter with the three-argument constructor.DenseTCGraph:setAllPotentialremoved, no callers.EditorController: when an STN check fails and no cycle is available, the message adds that running BFCT or Yen would produce one. For an STNU it shows the cycle when the check published one, and otherwise states that the network is not controllable because of a cycle involving the contingent links and thatSRNCycleFinderis the algorithm that produces those.EditorView: the node tooltip no longer shows a scalar potential,LabeledNode.potentialbeing removed.
v7.0
Date: 2026-08-31
SVN revisions: r1032–r1162 (r1162 is the release commit).
This release removes JUNG from the project and introduces two interchangeable backends behind
TemporalConstraintGraph: SparseTCGraph, the default for every kind of network, and DenseTCGraph, for the
dense-specific operations and for callers that ask for it explicitly. Algorithms that need only the common graph
API preserve the concrete backend of their input. Nothing in the library depends on JUNG any longer — not the graph
model, not GraphML I/O, not the algorithms, and not the editor, which draws through plain Java2D.
The Swing editor has been rewritten from scratch in the new it.univr.di.cstnu.gui package, replacing the
JUNG-based one. It is backend-agnostic, it draws and interacts through plain Java2D, and its controller is
headless-testable, so the editor is covered by the ordinary test suite instead of being exercised by hand.
Public API migration notes:
- The following public class names were renamed to make the representation explicit:
TNGraph→DenseTCGraph,TCNGraph→SparseTCGraph,TNPredecessorGraph→TCPredecessorGraph,TNGraphMLReader→TCGraphMLReader,TNGraphMLWriter→TCGraphMLWriter, andTNGraphBaselineRunner→TCGraphBaselineRunner(with the corresponding test classes). The nestedTNGraph.NetworkTypeenumeration is now the top-levelTemporalConstraintNetworkType. This is a source-incompatible API change. - Algorithms that formerly accepted a concrete dense graph now take
TemporalConstraintGraphin their constructors and methods. The dense-only overloads survived for a while as deprecated adapters that only cast their argument, and have been removed before the release, this version being the one that introduces the distinction: pass aTemporalConstraintGrapheverywhere,STN.MAKE_MINIMAL_DISPATCHABLE(TemporalConstraintGraph)included. A dense graph is one, so a caller holding aDenseTCGraphneeds no change. - Use
getGraph()andgetCheckedGraph()on the migrated algorithm classes instead of the deprecated dense-onlygetG()andgetGChecked()accessors. These, unlike the constructors, are still there: they narrow the returned graph to the dense backend, which the JUNG editor and the GraphML writer still require. - Use
graph.renameNode(node, name)andgraph.renameEdge(edge, name)instead of changing the name of a graph-owned node or edge throughsetName. newInstance(...)replaces ad-hoc construction of auxiliary graphs in generic code: it creates a graph of the receiver's concrete backend, whiletarget.newInstance(source)creates a faithful copy of any source graph in the backend chosen bytarget.- Every algorithm class has an
XXX()constructor that builds a sparse network and anXXX(boolean useDenseGraph)one for asking the dense backend. Code that relied onCSTNPSU(),OSTNU()orPCSTNU()returning a dense graph must now say so:new OSTNU(true). No kind of network is dense-only any more:CSTNPSU/FTNU,OSTNUandPCSTNU, documented as dense-only in the first part of this release cycle, work on both backends and default to sparse like their siblings. InSTN,STNUand the CSTN-family algorithms the graph fields and the auxiliary paths useTemporalConstraintGraph, and fresh working graphs are created throughnewInstance, which preserves the selected backend. - Use
equalsByNameinstead ofequalsto compare two nodes or edges by name.Component.equalsis deprecated: it is identity comparison, inherited fromObject, which is what a graph needs internally but rarely what a caller means. The name is the identity of a component within its graph, andequalsByNamesays so explicitly.
Removed the following dependencies:
- JUNG 2.1.1 (
net.sf.jung:jung-*) and Guava: no class of the library uses them any more. Theit.univr.di.cstnu.visualizationpackage, which held the old JUNG-based editor together withJungGraphAdapter,TNEditorApi, the graph-mouse plugins andSpringLayoutRunner, has been deleted; the new editor init.univr.di.cstnu.guireplaces it. Guava came in only through JUNG and through two uses of its own (com.google.common.base.SupplierandLists.cartesianProduct), both replaced byjava.util.function.Supplierand by explicit enumeration. The distribution archive shrank from 9.0 MB to 6.9 MB, and the project no longer carries Guava's known vulnerabilities. Users who imported anything fromit.univr.di.cstnu.visualization, or who relied on the JUNG graph interfaces being implemented by the graph classes, must migrate: the graph classes now implement onlyTemporalConstraintGraph.Luke2GraphML, which used the JUNG spring layout to give coordinates to a format that carries none, uses the newFruchtermanReingoldLayoutinstead, so its output still opens in the editor with a sensible layout. net.openhft:affinityand the--nCPUsoption ofChecker,CSTNU2CSTNPSU, andSTNUDensifier: the tools now process their input files sequentially.--nCPUsparallelized only independent files, never an algorithm on one graph; measurements and verification found no real throughput gain, while concurrent jobs contend for memory bandwidth, caches, garbage collection, and possibly NUMA memory. CPU pinning does not remove that contention, and a standard Java pool would retain both it and needless complexity. Removing Affinity also eliminates its transitive JNA native-access dependencies from the distribution.
Added the following classes:
-
AbstractBenchmarkRunner: shared base for the benchmark runners. It holds the common command-line options (input files, output CSV, number of repetitions, timeout, save, version), the output-stream management, and therepeatMeasureengine that executes an algorithm on a fresh instance for a given number of repetitions and collects the execution-time statistics. -
CheckOutcomeandDispatchabilityOutcome: the two stored assertions, each a record with its own textual form.CheckOutcome.currentToolVersion()readsImplementation-Versionfrom the manifest and answersdevwhen there is none, which is the answer for a run from a build tree or from the test suite.- A network carries the outcome of a check into its file through them. The two properties are persisted, and
they are independent, because a network can be controllable and only afterwards be made dispatchable:
CheckOutcomerecords the kind of check — consistency for the STNs, dynamic consistency for the CSTNs, dynamic controllability for the STNUs, the CSTNUs and the CSTNPSUs, agile controllability for the OSTNUs — its result, the algorithm that produced it and the version of the tool;DispatchabilityOutcomerecords whether the network is in dispatchable or in minimal form, and by which algorithm. - An outcome read from a file is an assertion by whoever wrote it, so it is stored together with the fingerprint
of the network and is believed only while that fingerprint still matches (see
NetworkFingerprint). When the fingerprint is missing, or of a version this tool cannot compare, or simply different, both properties are dropped in silence and the network loads normally: a stale verdict is not a malformed file. - What writes them is every checker: every check entry point, and every
initAndCheck, clears the two stored outcomes before touching the network, and every check records its verdict when it ends, the negative one too, while a check that is cancelled or that exhausts its cycle budget records nothing, because the absence of an outcome is how “not known” is represented. Which check records what is underSTN,STNUandCSTN. - Everything that mutates a network drops the two properties before starting: a claim belongs to the network it
was established on, and the fingerprint cannot catch a claim attached to a network that has changed since,
precisely because it is computed when the file is written, so it would match. What a copy and a content move do
with them is under
DenseTCGraph, and what an edit in the editor does is underEditorDocument.
- A network carries the outcome of a check into its file through them. The two properties are persisted, and
they are independent, because a network can be controllable and only afterwards be made dispatchable:
-
CurvaturePolicy: the automatic edge routing is decided in one place for both the screen and the exported figures, which previously disagreed: antiparallel edges were drawn apart on screen and superimposed in the exported TikZ. -
DenseTCGraph: JUNG-independent dense implementation ofTemporalConstraintGraph. It retains the adjacency matrix needed by dense-specific operations (findEdgeremainsO(1)) and its incrementally maintained incidence indexes. -
EdgeRoute: an edge can carry an explicit routing: up to two control points, expressed relative to the chord joining the endpoints, which the user drags to lay out bundles of nearby edges so that they do not overlap, and optionally the angles at which the edge leaves its source and reaches its destination, dragged through two further handles constrained to the node circles. The routing is part of the document and is persisted in GraphML under the new per-edge keyRoute(seeTCGraphMLWriter); its absence means automatic routing (seeCurvaturePolicy), so every existing file keeps opening and saving exactly as before. -
GraphAnnotation: a network can carry annotations: free text placed on the drawing, which belongs to the document, is persisted in GraphML, and is reproduced by the SVG and TikZ exporters, so a figure prepared in the editor needs no retouching afterwards. An annotation is left out ofNetworkFingerprint. -
MDEBenchmarkRunner: benchmark runner for the MDE family on DC STNUs (the inputs need not already be dispatchable). At least one algorithm-selection option is required:--MDE(or-MDE) executes MDE, whereas--MDE2(or-MDE2) is accepted as a forward-compatible placeholder but is not implemented and reportsmethod not yet implemented.in its CSV columns. For every input graph and selected implementation, the runner executes--numRepetitionDCCheckrepetitions (30 by default), each on a fresh copy of the original STNU; it records mean and standard-deviation execution time, resulting edge count, and status. A timed-out or failed execution contributes neither time nor edge count to the global summary. The shared options are positional GraphML STNU input files,-o/--outputfor an append-mode CSV output,--timeOut(1800 seconds by default),--saveto write successful checked networks, and-v/--version. -
NetworkFingerprint: the canonical semantic form of a network and its digest, written assha256:v1:<hex>. The form holds the kind of the network, the nodes in name order with what the algorithms read from them, and the edges ordered by their endpoints with constraint type, ordinary value, labeled values and case label. An A-Label is written with its letters in lexicographic order rather than throughALabel.toString(), which orders them by position in the global registry: otherwise the digest would have depended on what had been loaded earlier in the same JVM. The version in the prefix lets a future change of the form make an old fingerprint unknown instead of mismatched, whichisVersionComparabletells apart.- The SHA-256 digest is of that semantic form and not of the file: were it computed on the GraphML, adding a key — as the
new
Routekey just did — would invalidate every fingerprint already stored. Coordinates, routing, annotations, the graph name and the name of an edge are left out of the form, so moving a node keeps a verdict while changing a weight drops it.
- The SHA-256 digest is of that semantic form and not of the file: were it computed on the GraphML, adding a key — as the
new
-
PhaseStatsBenchmarkRunner: temporary, study-only runner for a focused comparison of the phase statistics ofMDE(-MDE),SIMP-SEQ(-SimpSeq), andSIMP-SEQ-MINUS(-SimpSeqMinus) on DC STNU GraphML inputs. It repeats each selected algorithm through--numRepetitionDCCheck(10 by default) to average phase times, retains deterministic edge counts, aggregates the final values over the complete input set, and emits two\pgfplotstableread{...}blocks ready for the experimental article. It is not a production API: it and the associatedPHASE-STATSinstrumentation inSTNUmay be removed once the study is complete. -
SparseTCGraph: JUNG-independent sparse implementation ofTemporalConstraintGraph, optimized for the project's usual sparse temporal-constraint networks. It stores only existing edges and maintains indexes by edge name, ordered endpoint pair, and incoming/outgoing incidence. Endpoint and edge lookup are expectedO(1), incidence enumeration isO(degree), andtranspose()isO(|E|). -
TCGraphBaselineRunner: command-line, non-JUnit benchmark for a reproducible comparison ofDenseTCGraphandSparseTCGraphon external GraphML STNU files.--backend DenseTCGraph|SparseTCGraph|bothselects the measured representation (bothby default). It writes individual and mean CSV rows; its JVM used-memory deltas are marked approximate, because they are informative only and not reliable allocation metrics. The checked-inTNGRAPH_BENCHMARK_BASELINE.mdrecords the initial 500–2500-node sparse and dense comparison. -
TCPredecessorGraph,TCGraphMLReader, andTCGraphMLWriter: backend-neutral predecessor-graph and GraphML services. The reader/writer operate throughTemporalConstraintGraph, allowing GraphML networks and algorithm-produced copies to remain dense or sparse as requested by the caller. -
TemporalConstraintGraph: JUNG-independent data-structure API for temporal-constraint graphs. Besides basic graph operations, it now provides backend-preserving factories (newInstance), generic GraphML-facing mutation operations, safe graph-owned node/edge renaming (renameNode,renameEdge), and faithful copying. DirectsetNameis rejected after insertion into a graph, preventing stale name indexes without per-component listeners or overhead on ordinary graph construction/removal.ownsEdgeandownsNode. Within a graph an element is identified by its name, socontainsEdgeandgetSource/getDestanswer by name and resolve a foreign but homonymous element to the local one; the two new methods answer by identity, for the callers that need actual membership. The documentation of the name-based methods was corrected accordingly. Their first use inside the library isSTNU.minDEremoveStandInEdges(seeSTNU).clearOutcomes,recordCheckOutcomeandrecordDispatchabilityOutcome, through which a check stores its verdict on the graph (seeCheckOutcome), andaddAnnotation,getAnnotations,removeAnnotationandclearAnnotationsfor the free text placed on the drawing (seeGraphAnnotation).
Updated the following classes:
CSTN: the CSTN family —CSTN,CSTNU,CSTNPSU,OSTNUand their subclasses — writes the verdict of a check on the checked graph and on the cleaned copy thatgetCheckedGraph()returns, since there the two are different objects (seeCheckOutcome).CSTN2CSTN0: took its own consistency from the finished flag of the transformed check instead of from its consistency, so it declared consistent every instance whose inner check ran to the end, which also madeCheckerprint that an inconsistent instance is DC. Corrected because that verdict now reaches a file, where a wrong one would be believed.DenseTCGraph:- Safe, atomic node and edge renaming through
TemporalConstraintGraph.renameNodeandrenameEdge, in this backend and inSparseTCGraph. A node rename updates structural indexes, name-keyed caches, A-label references, case labels, upper/lower-case values, and labeled potentials; collisions are merged by the established minimum-value semantics. A graph-owned component can no longer be renamed directly withsetName, preventing corrupt indexes. The editor uses these operations and reports a failed rename without invalidating its checked graph. - A graph that receives a parameter node now calls itself a PCSTNU, in this backend and in
SparseTCGraph, so that the kind of a network follows its content instead of staying whatever it was when the graph was created. - Assigning an observed proposition, or an oracle, to a node already inserted in a graph updates the graph's
observer index (see
SparseTCGraph, whose defect it was). This backend was already correct here, apart from one point: on the duplicate branch it restored the node's previous proposition only insideif (Debug.ON), so a release build detected the duplicate, kept it on the node and skipped the invalidation of its index, while a build with debug enabled restored it. The behaviour no longer depends on that constant; only the log message does. - A fresh copy carries no stored outcome, in this backend and in
SparseTCGraph, because it is a different network and starts without claims about itself, whiletakeFromandreplaceContentsFrom— which move a finished content into another object and keep its identity, as the editor does to keep the result's object stable after a check — carry both, since dropping them there would lose a verdict just established, immediately before the file is saved.DenseTCGraph.copyused to copy the two properties by reference into a deep clone, so a cloned network was born asserting something about another one.
- Safe, atomic node and edge renaming through
DispatchabilityBenchmarkRunner: refactored onto the newAbstractBenchmarkRunnerbase (single repetition/measurement engine, shared option validation). Dropped the--MDEoption and its CSV columns: the MDE family is now benchmarked by the dedicatedMDEBenchmarkRunner. Fixed a minimization repetition that failed but still contributed to the timing statistics, and unified the timeout accounting across the two testers.EditorDocument: two behaviours of the old editor were corrected.- An element of the computed network is now shown read-only, because editing it used to mark the document dirty and silently discard the result of the check while leaving the input network untouched.
- A document edit that changes only how the network is drawn — node coordinates, edge routing — no longer invalidates the result of the check, which it has no reason to affect. A structural edit removes the verdict stored on the network; moving a node or rerouting an edge does not. A completed check leaves its verdict on the network shown as the result and on the input network as well — consistency and controllability are properties of the network, and a check preserves equivalence — so an ordinary Save records it, while the dispatchable form, which is a property of the result alone, stays with the result.
FTNU: the no-argument constructor installed no graph, soFTNU.maindied with aNullPointerExceptionwhile reading the input file, before the check could start; the class now installs a graph like its siblings.FTNU.mainparsed no argument at all and checked nothing, so the class was reachable only from code; it now behaves like the other mains.GraphAlgs: rewrote the strongly-connected-components routines (GET_STRONG_CONNECTED_COMPONENTSandGET_STRONG_CONNECTED_COMPONENTS_OL) from recursion to an explicit iterative Tarjan, so that graphs with thousands of nodes can no longer overflow the JVM call stack (component and emission orders are unchanged). SimplifiedgetDepthFirstOrderby removing the redundantisVisitedmap (a node is visited iff its DFS status is finished). Optimized the graph-basedGET_BellmanFord_Potentialby extracting the significant edge weights once into parallelintarrays and by keeping node potentials in a denseint[]indexed by node id instead of a hash map. Hoisted loop-invariant lookups out ofUPDATE_DISTANCESand pre-sized internal maps. Its migrated routines, including predecessor-subgraph construction, SCC, Floyd-Warshall, Bellman-Ford, reweighting, and the generic minimal-dispatchable path, now acceptTemporalConstraintGraphand preserve the input backend.APSP_Johnsonremains explicitly dense-only.GraphML2Luke: instnuPlainWriter, the Num Ordinary Edges header is now the actual number of ordinary constraints written (counting the ordinary value carried by contingent/wait edges too), instead of an incorrect formula based on edge, contingent, and wait counts. Removed a redundant anonymous block.Luke2GraphML: accepts anESTNUheader and its optional# Waitssection, converting each wait into the corresponding upper-case edge. It gives coordinates throughFruchtermanReingoldLayoutinstead of the JUNG spring layout (see Removed the following dependencies).OSTNU: the no-argument constructor installed no graph, with the same effect onOSTNU.mainas inFTNU; the class now installs a graph, andOSTNU()became public.PCSTNU: the no-argument constructor installed no graph, with the same effect onPCSTNU.mainas inFTNU; the class now installs a graph.SparseTCGraph: assigning an observed proposition, or an oracle, to a node already inserted in a graph now updates the graph's observer index. This backend used to record observers only when the node was added, so a proposition assigned afterwards — the normal order of events in the editor, and in any code that builds a node and then makes it an observer — stayed invisible:getObserverreturnednull,getPropositionsdid not list it, and a second node could take a proposition that was already taken. Clearing a proposition left a stale entry behind. Renaming, the PCSTNU kind on a parameter node, and what a copy and a content move do with a stored outcome are shared withDenseTCGraph.STN:MINIMALis recorded formakeDispatchableandmakeMinimalDispatchable, which for a network without waits are the same thing (seeCheckOutcome).- An interrupted
consistencyCheckwas indistinguishable from a completed one, since the method overwrote thefinishedflag thatAPSP_FloydWarshallsets to false when the thread is interrupted — and the editor cancels a check exactly by interrupting its thread, so a cancelled check would have recorded a verdict it never established.
STNU:-
Replaced the previous two-pass minimal-dispatchability workflow with the current
MDEimplementation, which converts a DC STNU into its minimal-dispatchable ESTNU form in a single integrated pass. Compared with the previousFDplus minimal-dispatchability sequence, worst-caseO(n^3), the currentMDEalgorithm costsO(mn + kn^2 + n^2 log n), strictly better thanO(n^3)on sparse networks, and, by keeping special stand-in edges, it handles semi-rigid cycles (a cycle in the ordinary+wait graph formed by a wait edge(V, C:-v, A)and an ordinary path(A, v, V)): a case for which prior algorithms can produce a non-equivalent dispatchable network. All themde*methods implementingMDEwere added:mdeM1: Step M1 entry — back-propagates from every UC edge to generate the undominated UC-bypass edges; returns the LO-graph potential.mdeM1BpPlus: back-propagates from one UC edge, resuming recursively through still-unstarted UC edges.mdeM1TryBpPlus: for a contingent node, back-propagates the mdd values along the incoming LO edges and decides which bypass edges/waits to add.mdeM2: Step M2 — for each LC edge, forward-propagates from the contingent node to generate the undominated LC-bypass edges.mdeM3: Step M3 entry — computes the ordinary+wait-graph potential, builds the AllMax reverse-predecessor graph, marks semi-rigid cycles, and generates the stand-in edges.mdeM3buildMultiRevPredGraph: builds the reverse-predecessor graph of the AllMax projection (tight ordinary/UC/wait arcs).mdeM3AddSucc: appends an arc to a node's successor list in that graph.mdeM3fasterBetterGenStandIns: back-propagates from each targetW, generating the undominated (and special) stand-in edges while tracking non-negative descendants.mdeM3backPropOrds: the back-propagation step along ordinary edges, updating distances and non-negative-descendant sets.mdeM3processWaits: projects a contingent link's waits during the back-propagation and records regular/special stand-in needs.mdeM4: Step M4 entry — collapses the rigid components and runs the STNU-adapted dispatchable-STN minimization on the collapsed graph.mdeM4b4ManageRCsForStnDisp: preprocessing — finds and collapses the rigid components of the tight ordinary graph into representatives and builds the collapsed graphg'.mdeM4buildRPG: builds the reweighted reverse-predecessor tree/DAG used to find undominated predecessors.mdeM4accUndomPreds: forward-propagates the need / non-negative-descendant statistics to accumulate the undominated predecessors of a target.mdeM4stnDispESTNU: runs the adaptedstnDispover all targets to classify edges as dominated/undominated.mdeM4processSpecialStandins: decides which special stand-in edges (those derived from semi-rigid cycles) must be preserved.mdeM4representativeOf: returns the representative of a node after rigid-component collapse.mdeM4resetRpgi: resets the per-target reverse-predecessor-graph scratch structure.mdeM4addOrUpdateOrdinary: adds or updates an ordinary edge ing'.mdeM4addOrUpdateLabeled: adds or updates an LC/UC/wait labeled edge ing'.mdeM4addOrReplaceAdjacency: adds or replaces an adjacency entry in the working adjacency maps.mdeM4putUndomPred: records an undominated predecessor together with its distance.mdeM4putMinStandIn: keeps the minimum stand-in value for a(source, dest)pair.mdeM4oreO: combines two “need” values (the ⊕ operator on the need markers/sets).mdeM4mergeNeed: merges a need value into a node's current need value.mdeM4copyNeedSet: copies a need-set value.mdeM4isEmptyNeed: tests whether a need value is empty.mdeM4firstByName: picks a deterministic node from a set (the first by name).mdeM5: Step M5 — removes the dominated stand-in edges, restores the rigid components, and builds the final minimal dispatchable ESTNU.
The supporting data structures were introduced as well (
MDELocalInfo,MDELocalInfoM2,MDELocalInfoM3, and theMDEM4RCInfo/MDEM4*records);MDELocalInfouses pre-sized maps and a reused priority queue across its per-update scans. Themde*methods are not optimized with respect to memory usage and running time. -
applyMDE()returns aboolean(wasvoid):truewhen the network was successfully turned into its minimal dispatchable form,falsewhen the computation could not complete because the network isnull(empty), not DC, or a timeout occurred (the detailed reason is always ingetCheckStatus()); a@see #applyMDE()was added to everymde*auxiliary method. The obsolete earlier minimal-dispatchability implementation (mdeRUL2021Plus,mdeRUL2021BpPlus,mdeTryBackPropPlus,mdeGetWaitsMarkedToRemove, and the nested support types used only by that implementation) has been removed.CheckAlgorithm.MDEis now the only MDE-family algorithm exposed bySTNU;MDEBenchmarkRunnermeasures--MDEand keeps--MDE2only as a not-yet-implemented placeholder. -
Fixed a bug in Step M3 (
mdeM3fasterBetterGenStandIns): the removal of the dominated waits terminating at an activation node (pseudocodeE_w.delete) identified the correct waits (distToW[V] <= -v) but deleted them only from an internal bookkeeping set that is never read again, so the dominated waits survived into the final network. They are now actually removed from the graph (the wait value is reset on the edge, and the edge is dropped if nothing else remains on it), producing the correct minimal number of wait edges. Removed the now-unused fieldwaitEdgesfromMDELocalInfoM3. -
Step M3 follows the revised pseudocode — the potential function is computed on the ordinary+wait graph instead of the ordinary+wait+upper-case one, the reverse predecessor graph no longer holds the upper-case edges, and
srHashis filled by comparing the rigid-component representatives of the two endpoints of every wait instead of walking the components in search of tight waits. It was adopted after measuring that it changes nothing: networks identical edge by edge on the sixty 1000-node instances, with and without semi-rigid cycles, and on the twenty-four test fixtures; it is not faster either. Step M3 also skips a wait whose source is the destination being processed, whose stand-in edge would be a useless self-loop. -
The representative of a rigid component is now chosen the same way at every site that chooses one, through two shared helpers,
mdeAssignReps(selection, tie-break and offsets) andmdeReOrientEdgeWeight(the re-orientation weightdelta + offset[measured] - offset[other]). The tie-break is part of the specification rather than of the implementation: an ordered preference list whose last element is the total order on names, so the representative is a function of the input and never of the iteration order of a hash map. One behaviour changed: inGET_REPRESENTATIVE_RIGID_COMPONENTS, used bymakeOrdinaryConstraintMinimalDispatchableand hence by the minimization of the FD phase 5 as well as byMDE, the zero time point Z was taken as representative as soon as it was met, whatever its distance; it is now preferred only among the time points that attain the minimum. An unconditional preference contradicts that minimum and can make some offsets negative, and their non-negativity is what the argumentx' = offset[A] + x >= x > 0of Step M4 rests on. -
Fixed two rigid-component bugs in
collapseRigidComponents(used bymakeOrdinaryConstraintMinimalDispatchable, hence by bothMDE/applyBetterMinDispESTNUand the FD phase-5 minimization) that could corrupt a contingent link or drop a required constraint when a contingent time-point falls inside a rigid component. (1) When a rerouted wait (an upper-case value on a non-contingent edge, for whichisWait()is true) was merged onto an edge that happened to be the genuine upper-case edge of a contingent link, the code calledresetLabeledValue()on it, stripping the UC label and demoting the edge fromcontingenttorequirement(destroying the contingent upper bound). The wait merge is now skipped when the target edge is contingent. (2) When a dominated weak stand-in edge was rerouted onto a pre-existing genuine (non-weak) edge whose ordinary value was not updated by the merge, theweakEdgesbookkeeping wrongly marked the genuine edge as a stand-in, so it was later dropped byminDEremoveStandInEdges; a pre-existing genuine edge now stays a real constraint (anewOutEdge/newInEdgeis treated as weak only if it was itself weak or was freshly created for the reroute). In addition,applyBetterMinDispESTNUnow re-types any survivinginternalstand-in edge (e.g., a repurposed VAC-companion whose value became undominated) asderived, so the final minimal dispatchable network no longer containsinternal-typed real constraints (whichGET_SPFromActivations_JohnsonOwould otherwise skip as stand-ins). -
upperContingentEdgebecame a linked hash map, and with it the algorithm became a function of its input. Keyed byLabeledNode, whosehashCodeis the identity hash of the JVM by design — a node can be renamed, so the hash cannot depend on the name — a plain open hash map iterated in an order that depended on the heap, and the recursivemdeM1used that order to decide which contingent link to process out of turn: the same network could therefore produce different, equally correct results in different runs of the same JVM. The same map is iterated byapplySRNCycleFinder, whose negative cycles were affected in the same way. -
MDErequires a dynamically controllable input and does not verify it – its own javadoc says so – and a network that is not controllable made it produce a contingent link with a negative minimum duration, silently. Two things now prevent that. Step M4 checks, for every contingent link it re-expresses between the representatives of the collapsed rigid components, that the offset of the contingent time point is zero and that of the activation time point is non-negative; those two facts are what makes the translated link legal, and they hold because a contingent time point is always the earliest member of its own rigid component – a time point rigidly tied to it and occurring earlier would have to be scheduled by the agent before the contingent duration is observed, which no dynamically controllable strategy can do. The check is not conditioned onDebug.ON: a release build is exactly where a silently illegal network must become a loud failure. And the public entry point now refusesMDEunless the controllability of the network has been established: either the graph carries a storedCheckOutcomesaying so – captured before the check clears it, since a check establishes a new verdict – or a check already completed on that same object. A network whose file declares it not controllable gets a message saying so, rather than the generic one. A freshly built check status reportsisControllable()as true before any check has run, so the condition also requires that a check actually finished and named its algorithm. -
In the editor, asking for the dispatchable form with
MDEselected on a network with no verdict does not fail with an exception and does not manufacture the verdict behind the user's back by checking a hidden copy: it reports that a dynamic-controllability algorithm other thanMDEmust be selected, the check run, and the network saved – because the outcome is saved with it, andMDEthen starts without re-verifying anything. A verdict the user did establish is honoured: it is transferred explicitly from the input network onto the working copy, since a copy is born without claims and this is the one place that re-derives that conclusion for itself. -
The form the class produces is recorded with the verdict (see
CheckOutcome):MINIMALforMDEand forapplyBetterMinDispESTNU,DISPATCHABLEforFD_STNU,FD_STNU_IMPROVEDandMorris2014Dispatchable.CheckAlgorithm.FD_STNU_IMPROVEDwas assigned nowhere, so the improved variant reported itself asFD_STNU. -
minDEremoveStandInEdgesuses the identity check (seeTemporalConstraintGraph.ownsEdge), since it mutates and removes the very object it is given.
-
STNUAddSemiRigidCycles: the tool that completes an instance built with nested diamonds by adding the constraints that close a semi-rigid cycle on each diamond. It no longer connects theWnodes, because the generator now does it itself, and it therefore requires that work to be already done: an instance where someWis still a sink is refused, since a diamond whoseWconstrains nothing makes a useless benchmark instance. With the W-connection go the--addEdges4WUoption, the random choice of the target nodes, the retry loop over those choices and the intermediate_connectedWoutput; the single remaining output carries the suffix_withSRCycles, placed before the index of the instance so that the index stays last:dc_500nodes_..._withOne4NestedDiamond_027.stnubecomesdc_500nodes_..._withOne4NestedDiamond_withSRCycles_027.stnu.- It now works on the 4-nested structure as well, and not by counting indexes: the chain of diamonds is discovered by walking the nesting edges
A(i+1) -> V(i)downwards from theUnode. That is necessary, because the diamond gadget is inserted into a random lane network, and the contingent nodes created before it shift the whole numbering – for the same option the chain was observed to start at 1, at 2 and at 3. The value of each added edge is computed instead of written down: a semi-rigid cycle needs an ordinary path fromAtoVwhose length equals the magnitude of the wait the gadget generates, that isy - vc, whereyis the upper bound of the contingent link andvcthe value ofV -> C, so the tool reads both from the graph and subtracts the edge the generator already provides – the nesting edge, orU -> Vfor the last diamond, which has no nesting edge of its own. With the generator's current constants this yields the same 5 and 4 that the previous version had hardcoded, and it stays tight if those constants ever change. - The added constraints are
requirementedges. They used to be typedinternal, which insideSTNUdenotes a stand-in edge:applyBetterMinDispESTNUre-typed them asderived, so an instance presented its own constraints as produced by the checker. The step that restores dynamic controllability now protects the edges the tightness depends on rather than their endpoint nodes, which frees the unrelated lane constraints incident to the activation time points, and a final check refuses to save an instance whose paths are no longer tight – the relaxation being the one thing that could break a tightness the protection was meant to preserve. Measured over 200 generated instances, 196 are completed. The four that are not have an interruption cycle whose only negative contributions are case values of contingent links and zero-valued lane constraints, so no requirement edge is left to relax; the tool reports them and moves on. - An instance it writes carries the name of its own file and the outcome of the check that accepted it (see
STNURandomGenerator).
- It now works on the 4-nested structure as well, and not by counting indexes: the chain of diamonds is discovered by walking the nesting edges
STNUEdge: fixed the Javadoc ofGET_MIN_VALUE_BETWEEN_ORDINARY_AND_WAIT; addedGET_MIN_VALUE_BETWEEN_ORDINARY_AND_WAIT_UPPER, which returns the minimum among the ordinary value, the wait value, and the upper-case value.STNURandomGenerator:- The
Wnode of a diamond gadget was a sink, so the gadget constrained nothing outside itself and the instances of the 2025 benchmark were sound only because a separate tool connectedWafterwards. The generator now adds three requirement edges fromWitself and restores dynamic controllability around them, insidebuildAPairRndTNInstances, so an instance obtained through the API carries the invariant too, and one that cannot is discarded rather than handed over.--withDiamondscould produce nothing at all: twointarguments were passed in the wrong order, where the compiler could not see it, and the per-slot bound for the ordinary nodes ignored the nodes each diamond adds. - An instance written by this generator and by
STNUAddSemiRigidCyclesnow carries the name of its own file and the outcome of the check that accepted it. Neither was the case before, for a mechanical reason: both tools run the controllability check on a copy of the network – the instance has to remain the un-propagated one, without the derived edges the check adds – so the verdict was recorded on the copy and thrown away with it, while a fresh copy carries no claim of its own. The verdict is now written onto the graph that is actually saved, with the algorithm taken from the check status, at the three points where a network has just been accepted as controllable and is not mutated afterwards; no dispatchability outcome is recorded, since these instances are not in dispatchable form.makeDenseInstanceis left alone: it runs no check of its own, so it has no verified fact to assert. The name was empty for a subtler reason: the generator created the graph without one and wrote an emptyNameelement, and the reader, finding the element present but empty, returns that empty string rather than falling back to the file name – so the emptiness survived every read-and-resave. Both tools now set the name of the file they are writing, extension included. The two additions are independent by construction, becauseNetworkFingerprintleaves the graph name out of its canonical form: setting the name cannot invalidate the verdict stored beside it. - The Benchmarks page of the website (
src/site/tex/benchmarks.tex) declaresSTNUw4DiamondsBenchmark2025andSTNUw6DiamondsBenchmark2025obsolete and no longer distributed, and drops the links to them. The reason is theWsink above: the nodeWof a diamond gadget receives the stand-in edge of every diamond of the structure and has no edge leaving it, so the structure takes constraints and propagates none, and does not constrain the rest of the network at all – verified on the published files, where not one of the 240 instances has an edge leaving aW. The tables and figures of that section are kept, because they document the evaluation published for TIME 2025, which was run on those instances. A new section describes the four archives that replace them –STNUw4DiamondsBenchmark2026andSTNUw6DiamondsBenchmark2026, plus the twoWithSRCyclescompanions – with their generation parameters, what a semi-rigid cycle is and how many each instance carries, the fact that the two halves match one to one so that a measurement can be repeated on the same network with and without the cycles, and the two pieces of information every instance now carries about itself.
- The
TCGraphMLReader:- It honours the
NetworkTypedeclared in the file instead of inferring the kind from the edge classes and ignoring the declaration in silence; a file that contradicts itself — a CSTNU holding a parameter node — is rejected rather than read as something else, and six instances of the repository that declared a kind which was not theirs were corrected. - It reads the per-edge
Routekey (seeEdgeRoute), the graph annotations (seeGraphAnnotation) and the two stored outcomes, which it drops when the stored fingerprint does not match the network (seeCheckOutcome).
- It honours the
TCGraphMLWriter:- The project website gains a File format page, under Overview, that documents the GraphML dialect the tool
reads and writes: the keys of the graph, of the nodes and of the edges, which of them exist for which kind of
network, the format of each value, and complete examples. It also states how a contingent link is represented —
the lower-case value on
A → Cand the upper-case one onC → A, in two edges — which is the most common source of malformed files. A test fails if a key emitted byTCGraphMLWriteris missing from that page, so the documentation cannot fall behind the format without the build noticing. - It emits the new per-edge
Routekey (seeEdgeRoute), the graph annotations (seeGraphAnnotation) and the two stored outcomes with the fingerprint of the network (seeCheckOutcome).
- The project website gains a File format page, under Overview, that documents the GraphML dialect the tool
reads and writes: the keys of the graph, of the nodes and of the edges, which of them exist for which kind of
network, the format of each value, and complete examples. It also states how a contingent link is represented —
the lower-case value on
TikzExporter: the LaTeX escaping now covers every non-ASCII domain symbol that can reach an exported label — the empty label⊡, the empty upper-case label◇, the unknown-literal marker¿, the contingency symbol↕, the tuple delimiters❮/❯, and the GreekΩused as the horizon-node name in some instances — so an exported figure compiles under pdflatex (previously the raw⊡/Ωin labels made the document fail with «Unicode character not set up»). Both the standalone document and the fragment's required-packages comment now loadamssymbalongsidetikz, which the emitted math symbols (\boxdot,\Diamond,\bowtie) need.TNEditor: replaced with a restructured implementation. All per-network-type knowledge (edge implementation, file extensions, help text) now lives in a single static registry; all check/init buttons go through one generic execution engine instead of ~20 duplicated listener classes; checking algorithms run in a backgroundSwingWorkerso the GUI stays responsive; the command row is rebuilt on demand for the current network type.- The editing and transforming mouse modes of the old editor are gone: there is a single interaction mode. The window shows the input network and the result of a computation side by side, each with its own view controls, a single status bar, and an attribute inspector.
- The editor is what
java -jar CSTNU-Tool-7.0.jarand thetnEditor.shscript start: both used to launch the old JUNG-based editor, which is no longer the one being maintained. The editor accepts no command-line options:-cleaned,-ctgAsOrdinaryand-extraButtonsare gone. Managing contingent links also as ordinary constraints remains available, as a setting of the window rather than a switch chosen before startup. On macOS the menu bar is drawn inside the window;-Dapple.laf.useScreenMenuBar=trueasks for the system menu bar instead, at the price of a defect of the native menu, which keeps the entries of theFilemenu greyed out after a file dialog is dismissed withCancel. - It can import Luke plain STNU files and export an STNU as
plainStnu, without changing the document's associated GraphML file (seeLuke2GraphMLfor the conversion). Long-running checks show their elapsed time and can be cancelled; the completed elapsed time remains visible until another network is opened or imported. The resulting graph permits deletion of selected nodes without changing the input network, and its automatic edge routing is already correct after the first MDE check. - A contingent link is entered by its ordinary bounds alone for CSTNU, OSTNU and PCSTNU. The extended form, which also accepts upper- and lower-case values differing from the ordinary bounds, is offered only for the network kind where such a difference is meaningful, CSTNPSU/FTNU. Contingent nodes of an OSTNU carry their oracle in the same inspector, validated against the propositions already in use. Drawing on a window where no network kind has been chosen is no longer possible: it used to produce a document that belonged to no kind and could not be saved, losing the work.
- A
{@link}in the editor'sNetworkTypeRegistry, which named a class the file does not import and so resolved to nothing and left a diagnostic marker in the published documentation, is now fully qualified. - An element of the computed network is shown read-only, and an edit that changes only the drawing does not
invalidate the result of a check (see
EditorDocument).
spotbugs-exclude.xmlandpom.xml: the build configuration suppresses non-deterministicRCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUEandNP_NONNULL_RETURN_VIOLATIONfalse positives on the@Nonnullgetters/record accessors ofSTNUand its inner classes, and the sameRCN/NPfalse positives onDenseTCGraph(whose reported set shifts with the bytecode layout). The javadoc configuration inpom.xmlno longer declaresimplSpecandimplNoteas custom tags, since both have been standard javadoc tags since JDK 8 and no comment in the project used them.
Tests:
CliPrototypeNPERegressionTest: one case per command-linemainand per “String graphML” constructor, each loading an instance through the very code path itsmainuses, so theNullPointerExceptionthat killed those tools on start cannot come back unnoticed.CSTNFamilyCheckOutcomeTest: each class of the CSTN family records the kind of check it performs, with the algorithm that ran, for a positive and for a negative verdict; the verdict is written on the cleaned copy as well;initAndCheckclears an outcome set beforehand.DenseTCGraphTestandSparseTCGraphTest: backend-preserving construction, GraphML I/O and safe rename semantics (including A-label rewriting and cache invalidation); with theGraphAlgsand algorithm tests, equivalent algorithmic results on both backends and predecessor-graph reuse.DispatchabilityBenchmarkRunnerTest: smoke test that runs the runner on a small DC instance with all algorithms enabled and checks the structure of the produced CSV (header, per-instance data row field count, global-statistics section) and the option validation.EditorOutcomePropagationTest: drives the controller without a display and checks the editor's side — the verdict of a completed check reaches the input network and the document becomes worth saving, without the result being declared stale; the dispatchable form stays on the result alone; a structural edit clears the verdict and a layout edit does not; a command that installs a different network, such as the conversion of a CSTNU into a CSTN, leaves the input network without a verdict; and both files, the input one and the result one, keep what they were given when they are written and read again.FDPlusMinusEquivalenceSlowIT: holds the two 501-node instances thatFDPlusMinusEquivalenceTestused to run. Each of the three bugs that test guards was reintroduced in turn to find out which instance actually catches it: the two small ones catch all three, the two large ones catch nothing more at a hundred times the cost. The default build no longer runs them, and the test class documents how to.FDPlusMinusEquivalenceTest: regression test guarding thecollapseRigidComponentsfixes. It runsapplyFD_STNUPlusMinimization(FD phase-5 minimization followed byapplyBetterMinDispESTNU) andapplyFD_STNUPlusMinimizationMinus(the same minimization without the redundant phase-5 pass) on instances whose rigid components involve contingent time-points, and asserts that the two produce identical networks (edge set, ordinary/labeled values, and constraint type). Before the fixes the two diverged, because the extra phase-5 pass masked the rigid-component bugs.GraphMLOutcomeTest: the stored outcomes round-trip through GraphML, and are dropped when the fingerprint is missing, of a version this tool cannot compare, or no longer matching; a file written before the outcome keys existed loads normally.MDEBenchmarkRunnerTest: the same smoke test asDispatchabilityBenchmarkRunnerTest, forMDEBenchmarkRunner.MDEPhasesTest: characterization tests for the individual phases of theapplyMDE()algorithm (M1, M2, M3, M4, M5) on the reference networktime26-fig26a.stnu. For each phase the test renders the resulting graph in Luke's plain format (the graphgfor M1/M2/M3/M5, the collapsed graphgPrimefor M4) and checks it against the expected output stored insrc/test/resources/time26-fig26a_M<phase>.expected.MDEStatsRunnerTest: runsapplyMDE()phase by phase on500_000.stnu(removing the Z node afterinitAndCheck, as the reference simulator has no horizon) and asserts the per-step ordinary/wait edge counts, guarding the dominated-wait fix (input 1447 ordinary/0 wait; final 2397 ordinary/7 wait). It lives in theit.univr.di.cstnu.algorithmstest package to reach the package-privatemde*phase methods without widening any visibility.NetworkFingerprintTest: the fingerprint is the same for a network held in the sparse and in the dense backend, although the two do not iterate in the same order, and the same whatever the registration order of the A-labels; moving a node, changing a route or an annotation leaves it alone, while changing a weight, a case label or a constraint type changes it; it survives a save and a read.OrderInsensitive: test helper that canonicalizes thetoString()of collections whose element order is not semantically meaningful (predecessor edges, undominated edges, strongly connected components, observation nodes), so that order-fragile assertions compare content rather than the incidental iteration order.OSTNUTest(extended): two networks from the literature became tests. Figure 4 of “Agile Controllability in Simple Temporal Networks with Uncertainty and Oracles” is asserted both in its outcome and in the whole map of propositions assigned to the pairs, so a change altering which proposition goes with which pair cannot pass while the boolean outcome stays right. Figure 2 of the TIME 2024 paper on the same subject is asserted not agilely controllable: the paper declares it controllable, the implementation is right, and the arithmetic is recorded with the test so that nobody “fixes” the checker to agree with the paper.OutcomeSemanticsTest: the outcomes follow the copy rules — no outcome in a copy, on either backend, both outcomes in a content move throughtakeFromandreplaceContentsFrom—clearOutcomesclears both, and the two record-building entry points produce the expected records.STNCheckOutcomeTest:STNrecords the kind of check it performs, with the algorithm that ran, for a positive and for a negative verdict;initAndCheckclears an outcome set beforehand;makeMinimalDispatchablerecords the minimal form.STNTest.testVelocity: removed. A flaky performance micro-benchmark (it asserted a for-loop is faster than a stream, recursed on itself, and built 10001-node graphs, causing intermittentOutOfMemoryError); it verified no behavior of the project's code.STNUAddSemiRigidCyclesTest: drives the tool on instances generated for both diamond flavours – the depth is discovered as 4 and as 6, the expected number of edges is added with the values the previous version hardcoded, every path is still tight after the repair, and the result is dynamically controllable – and checks that an instance whoseWwas left unconnected, and a 3-nested instance, which has noUnode at all, are both refused.STNUCheckOutcomeTest:MDEyields the minimal form andFD_STNU_IMPROVEDthe dispatchable one;applyBetterMinDispESTNUturns a dispatchable network into a minimal one without disturbing the verdict of the check that preceded it;initAndCheckclears an outcome set beforehand;MDEruns when a stored outcome or a previous check on the same object declares the network controllable, and refuses it otherwise.STNURandomGeneratorTest: everyWof a generated diamond has an edge leaving it, for the single and for the 3-nested structure, and--withDiamondsproduces instances again.TemporalConstraintGraphContractTest: the shared graph contract, backend-preserving construction and GraphML I/O. The observer index is verified on the mutation path as well — a proposition assigned after the node is inserted, changed, cleared, and a duplicate attempted by mutation — with every case run against both backends, so the two cannot drift apart again.
v6.6
Date: 2026-05-30
Added the following classes:
CompactLogFormatter: compact formatter forjava.util.loggingrecords. It supports the usualSimpleFormatterarguments and adds arguments for printing source method and source class names without their packages.
Updated the following classes:
Debug: the development default ofDebug.ONis now true. Release package builds still compile with debug code disabled through the Maven build configuration and then restore the source value.GraphML2Luke: fixed the conversion of contingent links to Luke's plain STNU format. The converter now reconstructs activation node, contingent node, lower bound, and upper bound from both raw and initialized STNU encodings, writes only one line per contingent link, and exposesconvert(File)andconvert(File, File)utility methods.STNU: extended theCHECK_ACTIVATION_UNIQUENESSmethods to reject networks containing contingent links in sequence: a contingent node cannot be the activation node of another contingent link. The same check also enforces that distinct contingent links cannot share the same activation node. TheinitAndCheckmethod now uses the inverse contingent-node map for these checks when available. A check was also added to reject lower-case edges having the zero node as contingent.SRNCycleFinderBackPropagationlogging/status handling was cleaned, and the MDE stand-in edge generation now avoids producing a self stand-in edge. The class Javadoc was updated to document that forbidden contingent-link configurations must be separated by inserting one or more support nodes connected by zero-distance constraints.CSTNU,CSTNPSU,OSTNU,PSTN: updated the class Javadocs to document that well-defined networks must not contain contingent links in sequence and that distinct contingent links cannot share the same activation node.
v6.5
Date: 2026-01-26
STNU: fixed a bug in theMinDispESTNU (MDE)algorithm: it now manages rigid components containing activation timepoints correctly. MethodapplyMinDispatchableESTNUwas renamed toapplyBetterMinDispESTNU.STNUEdge: addedsetWait()method and fixedupdateWait().
v6.4
Date: 2025-12-29
STNU: addedMinDispESTNU (MDE)algorithm.
v6.3
Date: 2025-09-05
STNU: renamedapplyFastDispatchable_STNUtoapplyFD_STNU. Improved the method that collapses rigid components: it can now correctly collapse rigid components that also contain contingent links.OSTNU: fixed a bug in the determination of execution time. It was limited to cases where the network was not agile.
v6.2
Date: 2025-05-30
Updated the following classes:
STNU: added the methodminDEbetterGetStandInEdgesAssumingManyDiamonds, which can determine stand-in edges in instances containing nested diamond structures better thanminDEgetStandInEdges. To use this optimization when finding the minimal dispatchable version of a network, callapplyMinDispatchableESTNU(true).STNUEdge: added theGET_MIN_VALUE_BETWEEN_ORDINARY_AND_WAITmethod.STNURandomGenerator: added an option to generate instances containing a 6-deep nested diamond.Constants:sumWithOverflowCheckno longer throws an exception if the sum is +/-∞; it returns the result as +/-∞.DispatchabilityBenchmarkRunner: improved the handling of non-well-formed instances. They are now ignored without stopping the process.
v6.1
Date: 2025-04-09
Updated the following classes:
STN: cleaned up several methods. In particular,GET_SSSP_BellmanFordandGET_SSSP_Dijkstranow contain all variants of the corresponding algorithms. Renamed all static methods by capitalizing their names.STNU: added the static methodGET_APSP_JohnsonOto determine the APSP graph, considering only the ordinary values of the network. Extended the methodapplyMinDispatchableESTNU: it is possible to request the fastMinDispatch algorithm published in L. Hunsberger and R. Posenato, “Faster Algorithm for Converting an STNU into Minimal Dispatchable Form,” in 31st International Symposium on Temporal Representation and Reasoning (TIME 2024), in LIPIcs, vol. 318. 2024, p. 11:1-11:14. DOI: 10.4230/LIPICS.TIME.2024.11. (Algorithm 2, newGenStandIns). This variant is faster only when the network contains at least 4-nested diamond structures.OSTNU: fixed a bug that did not handle some cases derived from the scenario where two contingent timepoints require both their oracles to be scheduled. The class cannot handle such a case. Now, the dynamic check returns false in such cases.ExtendedPriorityQueue.java: added a new constructor that allows the user to specify the initial size.STNEdge.java: added the functional interfaceEdgeValue.
New classes/interfaces:
GraphAlgs.java: moved a lot of graph algorithms fromSTN.javato this file to rationalize the possible variants.GraphDistance.java: new representation of a graph distance based on a double hash map to speed up the retrieval of distances by specifying the node endpoints of a distance.
v6.0
Date: 2024-10-20
The update of the library fastutil to version 8.5.14 revealed a subtle weakness of all classes in the subpackage it.univr.di.labeledvalue and, as a consequence, in the subpackage it.univr.di.cstnu.graph.
Therefore, it was necessary to adjust some methods in the classes of it.univr.di.labeledvalue and to reconsider the opportunity of some methods in the interface it.univr.di.graph.CSTNEdge and all its derived interfaces.
While the modifications in it.univr.di.labeledvalue are conservative, the ones made in it.univr.di.cstnu.graph are not.
In particular, from this version, it.univr.di.graph.CSTNEdge and its derived interfaces do not allow direct access to maps containing the labeled values of an edge and offer only one method, getLabeledValues(), to have a directed view of all map entries.
This method must be used only to scan all the entries in a fast, read-only mode. This is because the validity of the returned set is guaranteed if and only if the corresponding map is not modified during the scan.
Moreover, if any of the entries of the returned set are modified directly, the validity of the set of labeled values is not guaranteed.
All possible maps (labeled values, upper-case labeled values, lower-case labeled values, etc.) must be modified using the methods for adding/merging/removing labeled values present in the it.univr.di.graph.CSTNEdge and its derived interfaces.
If one needs to scan all labeled values of an edge to remove/modify some of them quickly, a safe way is:
- Retrieve the set of all the labels of the labeled values using the method
getLabelsOfLabeledValues(), - Scan such a set of labels
- Retrieve each labeled value using the method
getValue(Label label) - Modify/remove the labeled value using one of the methods
mergeLabeledValue(Label l, int i),putLabeledValue(Label l, int i), orremoveLabeledValue(Label l)
- Retrieve each labeled value using the method
The same approach is valid for upper-case/lower-case labeled values using the corresponding methods.
v5.0
Date: 2024-10-07
The dependency on the MATLAB library present in version 4.13 was too strong.
So, I decided to split the project into two projects. This division affects only the use of the class PSTN.
- CSTNU Tool (this project).
It is the core project and, limited to the class
PSTN, it contains its definition and relative algorithms that cannot be used directly because the object instantiation requires an external actor class that implements theit.univr.di.cstnu.util.OptimizationEnginefunctional interface to be executed. The CSTNU Tool project does not contain any implementation of theOptimizationEnginebecause I haven't found a full-fledged open-source implementation of a nonlinear optimization problem solver. - MatLabPlugin4CSTNUTool.
It offers an implementation of the
it.univr.di.cstnu.util.OptimizationEnginefunctional interface using the MATLAB software. This plugin, together with CSTNU Tool, allows users to create and use PSTN objects. Refer to the MatLabPlugin4CSTNUTool website to discover how to compile and use this plugin within this project.
Added the following classes:
OptimizationEngine: a functional interface that represents a method for solving a nonlinear optimization problem. ClassPSTNdepends on this interface. A possible implementation of this interface is offered in the project MatLabPlugin4CSTNUTool.LogNormalDistribution: represents log-normal distribution parameters. It was a subclass ofPSTN.
Added three test files: notDC002.stnu, notDC020.stnu, and notDC033.stnu.
Removed the following classes:
MatLabEngine: moved to MatLabPlugin4CSTNUToolPSTNTest: moved to MatLabPlugin4CSTNUToolPSTNBenchmarkRunner: moved to MatLabPlugin4CSTNUTool
Updated the following classes:
STNUEdge,STNUEdgeInt: MethodupdateValue(int)cannot stay in interfaceSTNUEdge, otherwise in classSTNUEdgeIntthe method is overridden by the methodupdateValue(int)of the superclassSTNEdgeInt. Therefore,updateValue(int)was moved intoSTNUEdgeInt.STNURTE: parameters--envand--rtednow accept values ofStrategyEnum.LabeledNode,TNGraphMLReader,PSTN: the dependency on the classPSTN.LogNormalDistributionis now updated to classLogNormalDistribution.PSTN: the class's constructors require an object of typeOptimizationEngine.
v4.13
Date: 2024-07-09
Added the following classes:
PSTN: Probabilistic Simple Temporal Network. A specialized version of STNU where each contingent link duration can be described by a log-normal probability distribution Since the networks are represented as distance graphs, the edges associated with a contingent link of a PSTN are still represented as upper-case and lower-case edges. This representation is also useful because the DC checking/execution of a PSTN is done considering its correlated STNU. Hence, the log-normal distribution parameters are stored in the contingent node as a fieldPSTN.LogNormalDistributionParameter logNormalDistributionParameter. Determining an approximating (correlated) STNU of a PSTN requires solving a nonlinear optimization problem. In this release, such a problem is solved using MATLAB'sfminconfunction. Therefore, if it is required to use thePSTNclass, executing the library offering access to a MATLAB-licensed engine is necessary. The core MATLAB engine must be extended with the modules “Optimization Toolbox” and “Statistics and Machine Learning Toolbox” (thanks to Kim van den Houten and Léon Planken for clarification). For macOS systems, where MATLAB is usually installed in/Applications/MATLAB_R2024a.app/, it is enough to add-Djava.library.path=/Applications/MATLAB_R2024a.app/bin/maca64to thejavacommand.
Updated the following classes:
LabeledNode: added a field to represent log-normal parameters for contingent duration in contingent links of a PSTN. This field is significant and considered only on the contingent nodes of a PSTN. See the description of PSTN.ALabel: added methodgetALetter()ExtendedPriorityQueue: added methodgetFirstPriority()STN: made serializable.STNU: added the methodapplySRNCycleFinder()that can be called withCheckAlgorithm.SRNCycleFinderduring the DC checking phase. This method returns detailed information about the possible semi-negative cycle found during a check. This information is inside the objectSTNUCheckStatusreturned bydynamicControllabilityCheck(CheckAlgorithm, SRNCycleFinder).STNURTE: added the possibility to specify an execution strategy as a parameter. Some standard execution strategies are given in the enumSTNURTE.StrategyEnum. Thanks to Kim van den Houten and Léon Planken for the first implementation of this idea.TNGraph,TNGraphReader,andTNGraphWriterexpanded to managePSTN.
v4.12
Date: 2024-03-08
Added the following classes:
OSTNU: class representing Simple Temporal Networks with Uncertainty and Oracles.
Updated the following classes:
STNURTE: fixed minor bugs when executing networks that had useless wait constraints involving contingent timepoints.STNU: simplified some checks inapplyMinDispatchableESTNU()methods. Added the original FD_STNU algorithm implementation. Therefore, there are now two implementations of FD_STNU:FD_STNU(the original) andFD_STNU_IMPROVED(as the original, but it does not add waits that are more negative than the duration of the relative contingent link).
v4.11
Date: 2024-02-14
Added the following classes:
STNURTE: class for implementing a Real-Time Execution algorithm for STNUs.TimeInterval: utility class represents a time interval where the lower bound is guaranteed to be ≤ upper bound.ActiveWaits: utility class to represent an active wait.
Updated the following classes:
- Class
STNU: implemented theMinDispatchableESTNUalgorithm. Changed the name of some methods. Fixed minor bugs. - Class
STN: fixed a bug inGET_STRONG_CONNECTED_COMPONENTSandGET_STRONG_CONNECTED_COMPONENTS_HELPERmethods. Changed the name of some methods. - Class
TNGraphMLReader.java: reads the name of the graph from the attributed Name in the document. - Class
TNGraph:addEdgethrows an exception if the edge already exists. Returning a false value was not sufficient to avoid some errors. Added the methodsmakeNewEdgeandgetUniqueEdgeName. - Class
ExtendedPriorityQueue.java: renamed fromMinPriorityQueue. Renamed some of its methods to represent a generic priority queue (min or max). Now, it depends on a better heap library.
v4.10
Date: 2023-11-02
Switched to Java 21.
To Apple macOS users: it seems that OpenJDK 17 has some problems running the TNEditor because of missing system libraries. I recommend using Temurin 21 (https://adoptium.net/): I tested it, and it works without problems.
- Class
STN: methodmakeFastDispatchMinimizationadds constraints from the source node to guarantee that the source node can reach any node. - Class
TNEditor: for STN instances, the dispatchable version is determined using themakeFastDispatchMinimizationmethod.
v4.9
Date: 2023-07-20
- Class
AbstractCSTN: thereset()method does not remove the internal graph. - Class
PriorityQueue: added methodsdelete()andgetElements(). - Class
TNEditor: addedCapturefunction for saving networks shown in the application as PNG images. - Class
FTNU: added a constructor that accepts an XML string describing the network. - Class
CSTNPSU: methodgetEMaxDistanceInContingencyGraph(contingencyGraph)replaced bygetMaxPathContingencySpanInContingencyGraph(nodeName, contingencyGraph). Added the methodconfigureSubNetworks(subNetworks, n). - Fixed several minor bugs.
- Code cleaned in most of the classes.
v4.8
Date: 2022-12-28
- Class
CSTNPSU: added methodgetPrototypalLink()for determining Prototypal Link with contingency (PLC). - Class
FTNU(Flexible Temporal Network with Uncertainty): it is an alternative name for the classCSTNPSU. - Cleaned the code of many classes.
v4.7
Date: 2022-11-01
Added the new class PCSTNU (Parameterized CSTNU) to represent CSTNU with parameter timepoints.
- Interface
Node: added methods for checking if a node is a parameter one. - Class
AbstractNode: default methods were removed because they were moved into theNodeinterface. - Class
LabeledNode: added a new field to identify parameter timepoints. - Class
TNGraph: added code for managing PCSTNU instances and improved some logging code.
Fixed some minor issues:
- Class
AbstractCSTN: improved the determination of the max-edge value. - Class
CSTNPSU: improved the determination of all constraints when the parameterpropagationOnlyToZis false. - Class
STN: A useless annotation was removed.
v4.6
Date: 2022-06-03
The project has been updated to run with Java 17.
Moreover, from this release, the source code is tested by spotbugs configured with maximum effort and minimal threshold parameters.
- Class
STNUDensifier: improved, allowing the requirement of an exact number of edges (which can require removing edges). - Class
STNU: Changed the name of the fast dispatch algorithm. - Class
Checker: Made the long parameter specifications prefixed by--. - Class
STNURandomGenerator: improved the documentation of the README.txt generated to describe a benchmark.
v4.5
Date: 2022-03-30
- Class
Checker: Two statistical indices are added when STNU is checked. - Class
PriorityQueue: An open hash now realizes the map of entries for better performance. Removed throws of exceptions when it is not necessary. - Class
STN: Generalized all methods to accept edges that extend STNEdge. In this way, the STNU class can also use some static methods. Fixed a bug in thegetStrongComponentsmethod. - Class
STNU: addedfastSTNUdispatchabilitymethod. Changed the name of the methodRUL2020toRUL2021. Fixed some bugs with other methods and improved the efficiency of some methods. - Classes
ComponentandAbstractComponent: removed thecolorattribute because it is necessary to have lightweight components. All complementary attributes will be removed. - Interface
STNUEdge: improved the representation ofcontingent/waitedges, representing such data as an object of the internal classContingentCasePair. - Class
STNEdgeInt: improved default constructor. - Class
STNUEdgeInt: improved default constructor. - Improved the representation of
contingent/waitedges, representing such data as an object of the internal classContingentCasePair. - Class
TNGraph: changed internal maps representation and added two caches to speed up thegetInEdgesAndNodesandgetOutEdgesAndNodesmethods. Theremoving observerinstruction in theremoveEdgemethod is removed for performance reasons. Now, when an edge is removed from a graph, all its observing graphs are removed. This is not the correct behavior, but removing only the correct graph requires too much time for the library method. This issue will be fixed in a future release. The copy constructor of a graph clones the internallabelAlphabetso thatlabelAlphabetis not shared by different graphs. - Class
CSTNPSU: fixed a bug in the initAndCheck method that did not allow the specification of a guarded link with a label in the external bounds. - Class
TNEditor: added visualization of cursor position coordinates. - Class
CSTNULabelEditingGraphMousePlugin: fixed the bug that made acontingent edgeordinary after an edit of its value. - Class
CSTNU: added a check to guarantee that an activation node is associated with only one contingent node. - New class
TNPredecessorGraph: class for representing predecessor TNGraph very compactly.
v4.4
Date: 2022-01-03
- Improved the parser of labeled value map/set.
- Class
AbstractCSTN: improvedcheckAndInit: all negative edges going to an observation timepoint are checked and cleaned. - Class
STN: improved all SSSP algorithms, making each node reachable by Z in the case of forward search. Fixed a bug in themakeDispatchable()method: it did not remove all dominated edges if their opposites were absent. Added methodsgetAccumumulateUndominateEdgesandgetFastDispatchMinimization, a faster method for determining the dispatchable version of a network. - Class
PriorityQueue: removed the ambiguous methodvalue. - Class
TNGraph: introduced theunmodifiable(TNGraph)static method. - Class
ALabelAlphabet: added a new constructor. - Class
LabeledNode: started its refactoring. The next releases will specialize this class to optimize its memory footprint.
v4.3
Date: 2021-10-20
- Class
LabeledNode: extended for the Tarjan algorithm. - Class
STN: added BFCT (a.k.a. Tarjan algorithm) algorithm in STN class. This algorithm can return a negative cycle if the network is inconsistent. - Class
NodePriorityHeap: renamed asPriorityQueueand made generic. - Class
LabeledNode: removed rendering code. - Class
NodeRendering: new class to customize the rendering of LabeledNode inTNEditor. - Class
TNEditor: cleaned the GUI a little bit. - Removed the dependency on the FreeHep library because FreeHep does not work with JRE > 8.
- Removed ‘normal’ and ‘constraint’ types for
Edgein favor ofrequirementbecause in Temporal Networks,requirementis more appropriate. - Improved all documentation (now, there is only one README.md). Added the BUILDING.md document, which explains how to build a package and
- The preliminary steps to take before a commit (only for developers).
v4.2
Date: 2021-10-07
- Fixed the main method of the STN class: now it checks a given network.
- Fixed an initialization error of the graphic driver in
TNEditorand improved the Save dialog.
v4.1
Date: 2021-08-17
- Program
CSTNEditoris renamed asTNEditor. - Removed all unnecessary exceptions.
v4.0
Date: 2021-08-01
- Relevant change: the library is now a JVM 11 library but is still compatible with JVM 8.
- Improved Javadoc for almost all classes/methods.
- Fixed all
spotbugsbugs/errors at medium level and max effort.
v3.6
Date: 2021-06-20
- Fixed a bug in the
CSTNPotentialclass: thedynamicCheck()method worked correctly, but, in the end, the edges in the checked graph were wrongly saved in reverse. - Refactored classes
GraphMLReaderandGraphMLWriterto make them more general. Now,GraphMLReadercan build aTNGraphfrom a string representing it in GraphML format, andGraphMLWritercan serialize aTNGraphin GraphML format. - Class
CSTNU: added the constructor CSTNU(String) for building an instance from a GraphML string. - Class
AbstractCSTN: added the method String getGCheckedAsGraphML().
v3.5
Date: 2021-06-14
- Fixed a small bug in the Dijkstra method in the STN class.
- Class
NodePriorityHeaprefactored.
v3.4
Date: 2021-06-03
- CSTNU Check also propagates the bounds of a contingent link as normal constraints to avoid a contingent link having an upper-case value different from the negated upper bound.
- Fixed a graphical interface initialization error.
v3.3
Date: 2021-05-23
- CSTN(U)CheckStatus also stores the node that has a negative loop when the network is NOT DC.
- All DC checking methods save the resulting graph into a file before returning the check status.
- Improved some Javadoc comments.
v3.2
Date: 2021-01-14
- Fixed a coding error when saving a network to a file. From this release, the file encoding is UTF-8, independent of the execution platform.
- Fixed an initialization error in the CSTNU class.
- Fixed almost all Javadoc errors.
v3.1
Date: 2020-12-28
- Some cleanup actions.
- Added copyright and licenses for publication on
archive.softwareheritage.org.
v3.0
Date: 2020-11-15
- STNU class added with different DC checking algorithms: Morris2016, RUL2018, and RUL2020 faster one.
- CSTNPSU class offers a DC check sound-and-complete that can also adjust guarded links to the right ranges for an execution.
- Fixed some minor bugs.
v2.11
Date: 2020-02-02
- Graphical interface simplified.
- Now, it is more intuitive to add/remove nodes/edges.
- CSTNPSU class offers a sound-and-complete DC check.
v2.10
Date: 2020-02-02
- CSTN class restored to previous algorithms.
- Removed the possibility of checking without using unknown literals.
- This version considers the new rule and algorithm names published in a work presented at ICAPS 2020.
- CSTN class implements two DC checking algorithms. With option
--limitedToZ, the algorithm is the one presented at IJCAI18 (algorithmHR_18). Without--limitedToZ, the algorithm is the one presented at ICAPS19 (algorithmHR_19). This last version is not as efficient as IJCAI18. - For a very efficient version, consider the
CSTNPotentialclass (reintroduced but in a new form) that makes DC checking assuming IR semantics and nodes without labels (algorithmHR_20). CSTNPotentialclass implements the new DC checking algorithm based on single-sink shortest paths and potential R0 and potential R3 rules.- For all objects containing a labeled values field, the default implementation class is LabeledIntTreeMap. To change to this default class, I modified the field
DEFAULT_LABELEDINTMAP_CLASSof LabeledIntMapSupplier and recompiled the sources. CSTNPSUclass allows the representation and the verification of temporal constraints containing guarded links. The DC checking algorithm is sound but not complete. Moreover, the guarded link bounds are not guaranteed to be shrunk correctly.
v2.00
Date: 2019-11-07
- CSTN class implements a 3-rule DC algorithm. This algorithm consists of three rules (LP, R0, and R3*) for generating the
-∞value and six rules for managing-∞values stored as potential values in nodes. - Added CSTNSPFA class that implements the DC checking algorithm as a single-sink Bellman-Ford one. Therefore, only node potential values are generated. This class uses only three rules.
v1.26.vassar
Date: 2019-10-21
- Rewrote many classes to represent edges and graphs for STN networks efficiently.
- Removed class CSTNPotential (last svn-version 296).
- Added class STN & companions for some STN-specific algorithms.
v1.26.0
Date: 2019-03-23
- CSTNU class has a new field, contingentAlsoAsOrdinary, default false. When true, the DC checking method also propagates contingent links as ordinary constraints. This allows users to see some ordinary values more accurately.
v1.25.0
Date: 2018-11-22
- Minor code optimization and minor bug fixes.
- From this release, the software must be run using JRE 1.8.
v1.24.0
Date: 2018-07-18
- CSTN class allows the DC checking without using the unknown literals (necessary for completeness): it is just a tool for studying the necessity of unknown literals.
- Literal and Label classes are now immutable.
- Minor code optimization.
v1.23.2
Date: 2018-02-21
- Class CSTNU cleaned and optimized. From this release, the DC checking algorithm is sound and complete.
- A contingent link can have a label even if it is not required for sound and completeness.
- Class CSTNPSU.java added.
- Subpackage ‘attic’ removed. (last svn revision 243).
- SVN version: 245.
v1.22.4
Date: 2018-01-10
- Code cleaning
v1.22.3
Date: 2017-12-14
- Class CSTNU optimized.
- Class CSTNURunningTime removed.
- Class CSTNRunningTime was renamed Checker.
v1.22.2
Date: 2017-11-24
- Code optimization
v1.22.1
Date: 2017-11-22
- The following classes have been renamed, reordering inside terms:
CSTNEpsilon.javaCSTNEpsilon3R.javaCSTNEpsilon3RwoNodeLabels.javaCSTNEpsilonwoNodeLabels.javaCSTNIR.javaCSTNIR3R.javaCSTNIR3RwoNodeLabels.javaCSTNIRwoNodeLabels.java
v1.22.0
Date: 2017-11-21
- Introduced new classes and renamed old ones. There are 13 classes for checking CSTN/CSTNU:
1. it.univr.di.algorithms.CSTN.java
2. it.univr.di.algorithms.CSTN2CSTN0.java
3. it.univr.di.algorithms.CSTN3RIR.java: as IR CSTN, but DC checking uses only three rules.
4. it.univr.di.algorithms.CSTN3RwoNodeLabelEpsilon.java
5. it.univr.di.algorithms.CSTN3RwoNodeLabelIR.java
6. it.univr.di.algorithms.CSTNEpsilon.java
7. it.univr.di.algorithms.CSTNIR.java
8. it.univr.di.algorithms.CSTNU.java
9. it.univr.di.algorithms.CSTNU2CSTN.java
10. it.univr.di.algorithms.CSTNU2UppaalTiga.java
11. it.univr.di.algorithms.CSTNwoNodeLabel.java
12. it.univr.di.algorithms.CSTNwoNodeLabelEpsilon.java
13. it.univr.di.algorithms.CSTNwoNodeLabelIR.java
- Replaced Ω node with equivalent constraints in all CSTN classes.
- Removed Ω node from LabeledIntGraph and the relative reader/writer.
- Improved CSTN Layout for laying out nodes without explicit temporal relation with Z.
- Started classes re-factoring and exploiting Java 8's new features.
CSTNRunningTimeandCSTNURunningTimeare made multithreaded.
v1.21.0
Date: 2017-11-09
- Class
CSTNUGraphMLReadercan read CSTN files that do not contain meta-information about UC and LC values. CSTNirRestrictedrenamedCSTNir3R.CSTNwoNodeLabelcleaned.- Added classes
CSTNirwoNodeLabelandCSTNir3RwoNodeLabel. - Simplified
CSTNRunningTime.
v1.20.0
Date: 2017-11-03
- The Jung library has been upgraded to version 2.1.1.
- This update required an adaptation of all GUI classes.
- CSTNU DC checking algorithm is now sound and complete.
CSTNEditornow allows you to view a graph in a bigger window and save it as a PDF or other graphical format. The export menu is accessible by clicking the mouse inside the window containing the graph to export.- There are now six classes for checking CSTN/CSTNU:
it.univr.di.algorithms.CSTN: it checks a CSTN instance assuming the standard semantics.it.univr.di.algorithms.CSTNepsilon: it checks a CSTN instance assuming a not-zero reaction time (epsilon).it.univr.di.algorithms.CSTNir: it checks a CSTN instance assuming instantaneous reactions.it.univr.di.algorithms.CSTNirRestricted: asit.univr.di.algorithms.CSTNir, but the used rules are three instead of 6. This checking can be faster thanit.univr.di.algorithms.CSTNir.it.univr.di.algorithms.CSTNU: it checks a CSTNU instance assuming instantaneous reactions.it.univr.di.algorithms.CSTNwoNodeLabel: it checks a CSTN instance assuming the standard semantics. The instance is translated into an equivalent CSTN instance without node labels and then checked.
GraphMLReaderhas been rewritten because it is based on JungGraphMLReader2, which cannot manage big attribute data.GraphMLReaderhas been renamedCSTNUGraphMLReader.GraphMLWriterhas been renamedCSTNUGraphMLWriter.
v1.10.0
Date: 2017-06-22
- Package reorganization.
CSTNEditorcleaned and optimized.
v1.9.0
Date: 2016-03-31
- Labels are represented more compactly.
- Labeled value sets require less memory. Choosing which representation to use for labeled value sets is still possible.
v1.8.0
Date: 2016-02-24
- A new optimized class represents graphs.
v1.7.9
Date: 2015-11-26
- Added the new feature to CSTN DC-checking. Now, the DC-checking algorithm considers a user-specified ‘reaction time’ ε (ε > 0) of the system during the checking of a network. A reaction time ε means that an engine that executes a CSTN reacts in at least ε time units to a setting of a true value to a proposition.
v1.7.8
Date: 2015-10-28
- A new sanity check about the correctness of an input CSTNU was added. Each contingent time point has to have one incoming edge of the type ‘contingent’ and one outgoing edge of the type ‘contingent’ from/to the same node, representing the activation time point.
v1.7.7
Date: 2015-10-22
- Fixed another issue with instantaneous reaction in CSTNU. Thanks to Dian Liu for his help in discovering this error.
- I repeat that, even in this release, it is better to set any timepoint—that depends on an observation timepoint or follows a contingent timepoint—to a non-zero distance from the considered observation timepoint or the contingent one.
v1.7.6
Date: 2015-09-30
- Fixed a subtle bug in the generation of new edges. Thanks to Dian Liu for his help in discovering this error.
v1.7.5
Date: 2015-09-23
- Cleaned some log messages.
- We have discovered that the instantaneous reaction feature requires a sharp adjustment in the network semantics.
- We are currently working on introducing an ε-reaction (with ε ≥ 0) feature.
- In the meantime, for CSTN, it is possible to DC check assuming instantaneous reaction (ε = 0), while for CSTNU, it is only possible to check DC assuming non-instantaneous reaction (ε > 0).
- For now, it is better to set any timepoint—that depends on an observation timepoint or follows a contingent timepoint—to a non-zero distance from the considered observation timepoint or contingent one.
v1.7.4
Date: 2015-09-13
- In this release, a stricter check of contingent links has been introduced. Bounds of a contingent link A==[x, y]⇒B must observe the property
0<x<y<∞. Moreover, since for CSTNU instances, the concept of ‘instantaneous reactions’ has not yet been defined, it is not possible to define a CSTNU instance in which there exists a constraint like C–[0,0]→B, where B is contingent. This constraint requires that C be executed simultaneously with the contingent time point B. However, this is impossible because the environment decides B, and the runtime engine must observe it before executing a standard node like C.
v1.7.3
Date: 2015-09-10
- This release contains some minor bug fixes and a revision of the public methods of
class
it.univr.di.cstnu.algorithms.CSTNU. - Now, it is possible to check the controllability of a CSTN instance by instantiating a CSTNU object and calling its
dynamicControllabilityCheck(LabeledIntGraph)method. - To check the controllability of a CSTNU instance, create a
LabeledIntGraphobject representing the instance (theLabeledIntGraphclass also has a method for loading an instance from a file written in GraphML format), instantiate a CSTNU object, and call its methoddynamicControllabilityCheck(LabeledIntGraph), passing the created graph. Moreover, added the classit.univr.di.cstnu.algorithms.CSTNURunningTimeand the scriptCSTNURunningTimefor checking a bundle of CSTNU instances and getting some execution time statistics.
v1.7.2
Date: 2015-06-24
- This release contains minor bug fixes and a README file explaining the proposed examples of CSTNU/CSTN instances.
- Thanks to Huan Wang for his comments.
v1.7.1
Date: 2015-05-28
- This release contains a faster Dynamic Consistency check for CSTNs.
- The Java class
CSTN.javahas been completely rewritten and almost optimized for a faster check.
v1.7.0
Date: 2015-03-23
- This release is the first public release.
