Skip to content

Commit

Permalink
Improved overall appearance
Browse files Browse the repository at this point in the history
  • Loading branch information
IgorFilimonov committed May 8, 2024
1 parent 2860594 commit bc8df04
Show file tree
Hide file tree
Showing 10 changed files with 80 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@ class AlgorithmsController(
val layoutController: LayoutController
): Controller() {
fun convertToCFG() {
if (openedAutomaton !is PushdownAutomaton) {
if (openedAutomaton !is PushdownAutomaton || openedAutomaton.stacks.size > 1) {
tornadofx.error("Conversion is done only for pushdown automatons with a single stack!")
return
}
ConversionToCFGController(openedAutomaton).convertToCFG()
}

fun executeHellingsAlgo() {
if (openedAutomaton !is PushdownAutomaton) {
if (openedAutomaton !is PushdownAutomaton || openedAutomaton.stacks.size > 1) {
tornadofx.error("Algorithm is implemented only for pushdown automatons with a single stack!")
return
}
HellingsAlgoController(openedAutomaton, fileController, layoutController).getInputGraph()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import javafx.scene.text.Font
import tornadofx.Controller
import tornadofx.label

class ConversionToCFGController(val openedAutomaton: PushdownAutomaton): Controller() {
class ConversionToCFGController(private val openedAutomaton: PushdownAutomaton): Controller() {
fun convertToCFG() {
val conversionToCFGWindow = find<ConversionToCFGView>(mapOf(
ConversionToCFGView::grammar to openedAutomaton.convertToCFG(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import automaton.constructor.model.automaton.PushdownAutomaton
import automaton.constructor.model.element.*
import automaton.constructor.view.algorithms.HellingsAlgoExecutionView
import automaton.constructor.view.algorithms.HellingsAlgoInputView
import javafx.beans.property.SimpleBooleanProperty
import tornadofx.*

class HellingsTransition(
val nonterminal: Nonterminal,
val source: AutomatonVertex,
val target: AutomatonVertex,
var isNew: Boolean
var isNew: SimpleBooleanProperty
)

class HellingsAlgoController(
Expand All @@ -33,18 +34,21 @@ class HellingsAlgoController(
fun execute(graph: FiniteAutomaton) {
val m = observableListOf<HellingsTransition>()
val r = observableListOf<HellingsTransition>()
val grammar = getTestGrammar()
val grammar = openedAutomaton.convertToCFG()
graph.transitions.forEach { transition ->
val production = grammar.productions.find {
it.rightSide.size == 1 && it.rightSide[0] is Terminal && it.rightSide[0].getSymbol() == transition.propetiesText
}
if (production != null) {
val newHellingsTransition = HellingsTransition(production.leftSide, transition.source, transition.target, false)
val newHellingsTransition = HellingsTransition(production.leftSide, transition.source,
transition.target, SimpleBooleanProperty(false)
)
m.add(newHellingsTransition)
r.add(newHellingsTransition)
}
}

ConversionToCFGController(openedAutomaton).convertToCFG()
val hellingsAlgoExecutionWindow = find<HellingsAlgoExecutionView>(mapOf(
HellingsAlgoExecutionView::m to m,
HellingsAlgoExecutionView::r to r
Expand All @@ -54,7 +58,10 @@ class HellingsAlgoController(
hellingsAlgoExecutionWindow.nextIterationButton.action {
if (m.isEmpty()) {
hellingsAlgoExecutionWindow.close()
return@action
}
m.forEach { it.isNew.set(false) }
r.forEach { it.isNew.set(false) }
val mTransition = m.removeFirst()
val rToAdd = mutableListOf<HellingsTransition>()
do {
Expand All @@ -68,7 +75,8 @@ class HellingsAlgoController(
}.forEach { production ->
if (r.none { it.nonterminal == production.leftSide && it.source == rTransition.source && it.target == mTransition.target } &&
rToAdd.none { it.nonterminal == production.leftSide && it.source == rTransition.source && it.target == mTransition.target }) {
val newTransition = HellingsTransition(production.leftSide, rTransition.source, mTransition.target, false)
val newTransition = HellingsTransition(production.leftSide, rTransition.source,
mTransition.target, SimpleBooleanProperty(true))
m.add(newTransition)
rToAdd.add(newTransition)
}
Expand All @@ -86,33 +94,17 @@ class HellingsAlgoController(
}.forEach { production ->
if (r.none { it.nonterminal == production.leftSide && it.source == mTransition.source && it.target == rTransition.target } &&
rToAdd.none { it.nonterminal == production.leftSide && it.source == mTransition.source && it.target == rTransition.target }) {
val newTransition = HellingsTransition(production.leftSide, mTransition.source, rTransition.target, false)
val newTransition = HellingsTransition(production.leftSide, mTransition.source,
rTransition.target, SimpleBooleanProperty(true))
m.add(newTransition)
rToAdd.add(newTransition)
}
}
}
} while (rToAdd.isNotEmpty())
if (m.isEmpty()) {
hellingsAlgoExecutionWindow.nextIterationButton.text = "Close"
}
}
}

fun getTestGrammar(): ContextFreeGrammar {
val grammar = ContextFreeGrammar()
val s = Nonterminal("S").also { grammar.initialNonterminal = it }
val a = Nonterminal("A")
val b = Nonterminal("B")
val s1 = Nonterminal("S1")
grammar.addNonterminal(s)
grammar.addNonterminal(a)
grammar.addNonterminal(b)
grammar.addNonterminal(s1)
grammar.productions.addAll(listOf(
Production(s, mutableListOf(a, b)),
Production(s, mutableListOf(a, s1)),
Production(s1, mutableListOf(s, b)),
Production(a, mutableListOf(Terminal('a'))),
Production(b, mutableListOf(Terminal('b')))
))
return grammar
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class PushdownAutomaton(
I18N.messages.getString("PushdownAutomaton.Untitled")
), AutomatonWithInputTape,
AutomatonWithStacks {
private var grammar: ContextFreeGrammar? = null
init {
require(stacks.isNotEmpty()) {
"Illegal `stacks` argument when creating `PushdownAutomaton`"
Expand Down Expand Up @@ -71,7 +72,7 @@ class PushdownAutomaton(
}

private fun makeTheOnlyOneFinalState() {
if (finalVertices.isEmpty()) {
if (finalVertices.size < 2) {
return
}
val newFinalState = addState()
Expand Down Expand Up @@ -121,14 +122,17 @@ class PushdownAutomaton(
}

fun convertToCFG(): ContextFreeGrammar {
//simplify()
val grammar = ContextFreeGrammar()
if (grammar != null) {
return grammar as ContextFreeGrammar
}
simplify()
val newGrammar = ContextFreeGrammar()
val nonterminals = mutableListOf<MutableList<Nonterminal>>()
var biggestNonterminal: Nonterminal? = null
vertices.forEach { vertice1 ->
val list = mutableListOf<Nonterminal>()
vertices.forEach { vertice2 ->
val newNonterminal = grammar.addNonterminal()
val newNonterminal = newGrammar.addNonterminal()
list.add(newNonterminal)
if (vertice1.isInitial && vertice2.isFinal) {
biggestNonterminal = newNonterminal
Expand All @@ -138,12 +142,12 @@ class PushdownAutomaton(
}

for (i in nonterminals.indices) {
grammar.productions.add(Production(nonterminals[i][i], mutableListOf()))
newGrammar.productions.add(Production(nonterminals[i][i], mutableListOf()))
}
for (i in nonterminals.indices) {
for (j in nonterminals.indices) {
for (k in nonterminals.indices) {
grammar.productions.add(Production(nonterminals[i][j],
newGrammar.productions.add(Production(nonterminals[i][j],
mutableListOf(nonterminals[i][k], nonterminals[k][j])
))
}
Expand All @@ -166,17 +170,18 @@ class PushdownAutomaton(
if (transition2.readProperties()[0] != "ε") {
rightSideOfNewProduction.add(Terminal(transition2.readProperties()[0][0]))
}
grammar.productions.add(
newGrammar.productions.add(
Production(nonterminals[indexOfSource1][indexOfTarget2], rightSideOfNewProduction))
}
}
}
val initialNonterminal = Nonterminal("S")
grammar.addNonterminal(initialNonterminal)
grammar.initialNonterminal = initialNonterminal
grammar.productions.add(Production(initialNonterminal, mutableListOf(biggestNonterminal!!)))
grammar.convertToCNF()
grammar.removeUselessNonterminals()
return grammar
newGrammar.addNonterminal(initialNonterminal)
newGrammar.initialNonterminal = initialNonterminal
newGrammar.productions.add(Production(initialNonterminal, mutableListOf(biggestNonterminal!!)))
newGrammar.convertToCNF()
newGrammar.removeUselessNonterminals()
grammar = newGrammar
return newGrammar
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class AutomatonAdjacencyMatrixView(automaton: Automaton, automatonViewContext: A
automaton.vertices.forEach { map.transitions[it] = SimpleObjectProperty(listOf()) }
}
sourceColumn.text = "Source"
transitionsColumns.text = "Targets"
}

override fun registerVertex(vertex: AutomatonVertex) {
Expand Down Expand Up @@ -88,13 +89,14 @@ class AutomatonAdjacencyMatrixView(automaton: Automaton, automatonViewContext: A
p0!!.value.transitions[vertex]!!
}
addedColumn.setCellFactory { TransitionsCell(this) }
addedColumn.minWidth = computeCellWidth(addedColumn.text.length)
if (transitionsColumns.columns.none { it.text == addedColumn.text }) {
transitionsColumns.columns.add(addedColumn)
}
transitionsColumns.columns.forEach { it.prefWidth = TRANSITIONS_COLUMNS_WIDTH / transitionsColumns.columns.size }
}

override fun unregisterColumn(removedColumn: TableColumn<TransitionMap<AutomatonVertex>, List<Transition>>) {
transitionsColumns.columns.remove(removedColumn)
transitionsColumns.columns.forEach { it.prefWidth = TRANSITIONS_COLUMNS_WIDTH / transitionsColumns.columns.size }
}
}
16 changes: 6 additions & 10 deletions src/main/kotlin/automaton/constructor/view/AutomatonTableView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,6 @@ class TransitionsCell<T: TableTransitionView, K>(
VBox().apply {
item.forEach {
add(table.transitionToViewMap[it]!!)
val prefWidth = table.computeCellWidth(table.transitionToViewMap[it]!!.textLength)
this@TransitionsCell.tableColumn.minWidth =
maxOf(this@TransitionsCell.tableColumn.minWidth, prefWidth)
}
}
} else {
Expand Down Expand Up @@ -110,7 +107,7 @@ abstract class AutomatonTableView<T: TableTransitionView, K>(
val transitionsByVertices = observableListOf<TransitionMap<K>>()
val table = TableView(transitionsByVertices)
val sourceColumn = TableColumn<TransitionMap<K>, AutomatonVertex>()
val transitionsColumns = TableColumn<TransitionMap<K>, List<Transition>>("Description")
val transitionsColumns = TableColumn<TransitionMap<K>, List<Transition>>()
val controller = AutomatonRepresentationController(automaton, automatonViewContext)
val vertexToViewMap = mutableMapOf<AutomatonVertex, AutomatonBasicVertexView>()
val transitionToViewMap = mutableMapOf<Transition, T>()
Expand Down Expand Up @@ -185,8 +182,8 @@ abstract class AutomatonTableView<T: TableTransitionView, K>(
automaton.transitions.forEach { registerTransition(it) }
sourceColumn.cellValueFactory = PropertyValueFactory("source")
sourceColumn.setCellFactory { SourceCell(this) }
sourceColumn.minWidth = 150.0
transitionsColumns.minWidth = 1750.0
sourceColumn.minWidth = SOURCE_COLUMN_WIDTH
transitionsColumns.minWidth = TRANSITIONS_COLUMNS_WIDTH
table.columns.addAll(sourceColumn, transitionsColumns)

table.style {
Expand All @@ -208,10 +205,9 @@ abstract class AutomatonTableView<T: TableTransitionView, K>(

abstract fun unregisterColumn(removedColumn: TableColumn<TransitionMap<K>, List<Transition>>)

fun computeCellWidth(textLength: Int) = SYMBOL_WIDTH * textLength + ADDITIONAL_GAP

companion object {
const val SYMBOL_WIDTH = 23.0
const val ADDITIONAL_GAP = 30.0
const val TABLE_WIDTH = 1900.0
const val SOURCE_COLUMN_WIDTH = 150.0
const val TRANSITIONS_COLUMNS_WIDTH = 1750.0
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class AutomatonTransitionTableView(automaton: Automaton, automatonViewContext: A
}
}
sourceColumn.text = "State"
transitionsColumns.text = "Inputs"
}

override fun registerVertex(vertex: AutomatonVertex) {
Expand Down Expand Up @@ -114,14 +115,15 @@ class AutomatonTransitionTableView(automaton: Automaton, automatonViewContext: A
p0!!.value.transitions[addedColumn.text]!!
}
addedColumn.setCellFactory { TransitionsCell(this) }
addedColumn.minWidth = computeCellWidth(addedColumn.text.length)
if (transitionsColumns.columns.none { it.text == addedColumn.text }) {
transitionsColumns.columns.add(addedColumn)
}
transitionsColumns.columns.forEach { it.prefWidth = TRANSITIONS_COLUMNS_WIDTH / transitionsColumns.columns.size }
}

override fun unregisterColumn(removedColumn: TableColumn<TransitionMap<String>, List<Transition>>) {
filtersCount.remove(removedColumn.text)
transitionsColumns.columns.remove(removedColumn)
transitionsColumns.columns.forEach { it.prefWidth = TRANSITIONS_COLUMNS_WIDTH / transitionsColumns.columns.size }
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package automaton.constructor.view.algorithms

import automaton.constructor.controller.AlgorithmsController
import automaton.constructor.controller.algorithms.ConversionToCFGController
import automaton.constructor.model.element.CFGSymbol
import automaton.constructor.model.element.ContextFreeGrammar
Expand Down Expand Up @@ -42,7 +41,7 @@ class RightSideCell(val controller: ConversionToCFGController): TableCell<Produc
}
}

class ConversionToCFGView: View() {
class ConversionToCFGView: Fragment() {
val grammar: ContextFreeGrammar by param()
val controller: ConversionToCFGController by param()
private val productionsTableView = tableview(grammar.productions.toObservable())
Expand All @@ -54,6 +53,8 @@ class ConversionToCFGView: View() {
leftSideColumn.setCellFactory { LeftSideCell(controller) }
rightSideColumn.cellValueFactory = PropertyValueFactory("rightSide")
rightSideColumn.setCellFactory { RightSideCell(controller) }
leftSideColumn.minWidth = 100.0
rightSideColumn.minWidth = 100.0
productionsTableView.columns.addAll(leftSideColumn, rightSideColumn)
}

Expand Down
Loading

0 comments on commit bc8df04

Please sign in to comment.