Matrix view concepts

A matrix view in the Syside VS Code Extension relates two sets of elements. Each row and each column is an element, and each cell says whether a relationship joins that pair, such as a requirement allocated to a component, a system requirement derived from a stakeholder requirement or two parts connected. The exact attributes are listed in Matrix view structure.

Three views, three selections

A matrix is made of three sub-views, and each one selects its elements on its own, with its own expose, filter and include flags:

  • rowView and columnView select the axes. Each works the way a flat table selects its rows, so the rows can come from one package and the columns from another, and be of different kinds. An element an axis reaches twice is still one row or column.

  • cellView selects the relationships that can mark a cell. Its filter decides which relationships count, but it does not prune (see Include flags in grid views). A relationship usually sits inside the part or definition that contains the parts it connects, so under expose X::** with filter hastype SysML::ConnectionUsage the parts fail the filter, yet the connections among them still count.

Unlike the axes, the cell view includes reference usages by default. A usage declared directly in a package is a reference usage, so connections written at package level count without setting a flag. Ports are reference usages too, so the cell view reads connections to ports without a flag. The ports themselves appear on an axis only when that axis sets includeReferenceElements = true, and an editable matrix with ports on its axes can then write connections to them.

How a relationship marks a cell

A relationship marks the cell where one of its ends is the row element and the other the column element. This exact match is a strong mark, as opposed to the weak marks described below. A connection between two usages strongly marks the cell between those usages, never the cell between the definitions typing them:

part def Powertrain {
    part engine : Engine;
    part transmission : Transmission;

    connect engine to transmission;
}

With engine and transmission on the axes, the connection marks their cell. With Engine and Transmission on the axes instead, it marks nothing, because neither end is a definition. A relationship between definitions is a definition itself, and this one marks the cell between Engine and Transmission:

connection def { end : Engine; end : Transmission; }

By default a matrix ignores which end of a relationship is which. Setting direction makes the matrix count only relationships whose source is on one axis and whose target is on the other. For a requirement derivation, the #original and #derive tags decide which end is the source, not the order the ends are written in.

Usage and definition traceability

Because the match is exact, a matrix traces one of two separate things:

Usage traceability

Definition traceability

Relates

Features in one particular system: engine and transmission inside Powertrain

Definitions, wherever they are used: Engine and Transmission

Rows and columns

Usages

Definitions

A relationship is

A usage, such as connect engine to transmission;

A definition, such as connection def { end : Engine; end : Transmission; }

Holds

In the context it is written in. The same two parts can be connected in one system and not in another.

Everywhere the definitions are used

Strong marks never cross between the two. A connection between engine and transmission leaves the Engine × Transmission cell empty, and a connection definition between Engine and Transmission leaves the engine × transmission cell empty. A matrix with usages on one axis and definitions on the other therefore shows no strong marks, and on matching axes only the relationships of the same side count. With weak marks on, a usage relationship can still weakly mark the definitions its ends are declared in.

When a usage axis should read like a definition axis, representDefinition labels each header with the definition typing the element, when exactly one does. The rows are still the usages, so two usages typed by the same definition are two rows with the same label.

Weak marks

A relationship can sit between elements nested inside the rows and columns rather than between the rows and columns themselves:

part def Drone {
    part propulsion {
        part motor;
    }
    part power {
        part battery;
    }

    connect propulsion.motor to power.battery;
}

With propulsion and power on the axes, the connection marks nothing, because its ends are motor and battery. Setting showWeakTraceability on the cell view adds a weak mark to the propulsion × power cell: something inside the row is related to something inside the column.

A relationship marks a cell weakly when each of its ends is the row or column element or lies inside it. An end lies inside an element in one of three ways:

  • It is declared inside the element, at any depth: motor is declared inside propulsion.

  • It is reached through the element: the end propulsion.motor is named through propulsion. This counts even when motor is declared in the definition typing propulsion rather than in propulsion itself.

  • For relationships between definitions, its definition specializes the element. A connection definition with an end typed by SportsCar weakly marks the Car row when SportsCar :> Car, but never the other way round.

When a cell has both a strong and a weak mark, the strong mark is shown. A weak cell is never editable: the relationship it reflects was made between other elements, so it cannot be added or removed from that cell.

Port transparency

Connections are often wired through ports, while the matrix is about the parts that own them:

part def System {
    part sender {
        port output;
    }
    part receiver {
        port input;
    }

    connect sender.output to receiver.input;
}

With sender and receiver on the axes, the connection’s ends are the ports, so it marks their cell only weakly, and only when weak marks are on. Setting portsAreTransparent on the cell view treats a port end as the element the connection reaches it through: sender.output counts as sender, and the cell gets a strong mark. A port written without a path, inside the part that has it, counts as the element the connection is declared in. The same applies to allocation and derivation usages, but not to relationship definitions: their ends are definitions, not ports.

What an editable matrix writes

An editable matrix creates one kind of relationship, and the view has to say which. isEditable = true turns editing on, and the cell view’s filter picks the kind: it must admit exactly one of the six relationship kinds, and every new cell becomes that kind. The default cell view admits all six, so isEditable on its own leaves the matrix read-only, as does a filter that admits several kinds. A banner explains why.

Where a new relationship goes depends on whether it is a usage or a definition:

  • A usage relationship is written into one context. A connection between usages only holds where it is written: the same two parts can be connected inside one system and not inside another. So the cell view names one context, and each new connection is written into it, with its ends as paths from the context to the row and column elements. A row or column element that does not appear exactly once inside the context has no single path, so its cells are disabled.

  • A definition relationship is written into a namespace. A connection definition holds wherever its definitions are used, so it only needs a place to live: a writable namespace the cell view exposes the members of, so that the new definition is read back.

The exact expose each side needs is listed in Relationship kinds.

A row or column that does not fit the kind, such as a usage in a matrix that writes definitions, has its cells disabled (see why a row or column is disabled). Relationships in libraries, or inherited from a supertype of the context, cannot be removed from the matrix either, since they are written outside the context.

Build a matrix view builds an editable derivation matrix step by step, and Make a matrix editable covers making an existing matrix editable.