Skip to content

Commit

Permalink
feat(bop): implement minimum and maximum path weights
Browse files Browse the repository at this point in the history
  • Loading branch information
DerYeger committed Sep 30, 2024
1 parent f092996 commit 277e792
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 14 deletions.
3 changes: 2 additions & 1 deletion ml/scripts/encode-bop.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ time bun node_modules/@cm2ml/cli/bin/cm2ml.mjs batch-uml-bag-of-paths ../models/
--edge-blacklist 'owner' --edge-blacklist 'ownedElement' --edge-blacklist 'association' --edge-blacklist 'associationClass' \
--min-path-length 1 --max-path-length 2 \
--step-weighting '@type.exists >>> 2000' \
--step-weighting '@type.not.exists >>> 0' \
--step-weighting '@type.not.exists >>> -9999' \
--path-weight step-sum \
--min-path-weight 0 \
--max-paths 0 \
--prune-method 'encoding' \
--node-templates '@name.exists >>> {{name}} $eu.yeger${{type}}$eu.yeger$' \
Expand Down
2 changes: 2 additions & 0 deletions packages/encoder/bag-of-paths-encoder/src/bop-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export interface PathParameters {
pathWeight: PathWeight
maxPaths: number
allowCycles: boolean
minPathWeight: number
maxPathWeight: number
order: SortOrder
}

Expand Down
26 changes: 19 additions & 7 deletions packages/encoder/bag-of-paths-encoder/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,17 @@ const PathBuilder = definePlugin({
description: 'Maximum number of paths to collect',
group: 'Paths',
},
pruneMethod: {
type: 'string',
allowedValues: pruneMethods,
defaultValue: pruneMethods[0],
description: 'Prune method for paths that are subsequences of other paths',
helpText: `"none" performs no pruning. "node" checks if both nodes and their encodings are equal. "encoding" checks if the encoding of two nodes is equal.`,
group: 'Paths',
minPathWeight: {
type: 'number',
defaultValue: 0,
description: 'Minimum weight of paths',
group: 'Weighting',
},
maxPathWeight: {
type: 'number',
defaultValue: Number.MAX_SAFE_INTEGER,
description: 'Maximum weight of paths',
group: 'Weight',
},
order: {
type: 'string',
Expand All @@ -104,6 +108,14 @@ const PathBuilder = definePlugin({
description: 'Weighting strategy for paths',
group: 'Weighting',
},
pruneMethod: {
type: 'string',
allowedValues: pruneMethods,
defaultValue: pruneMethods[0],
description: 'Prune method for paths that are subsequences of other paths',
helpText: `"none" performs no pruning. "node" checks if both nodes and their encodings are equal. "encoding" checks if the encoding of two nodes is equal.`,
group: 'Paths',
},
},
invoke: ({ data, metadata }: { data: GraphModel | ExecutionError, metadata: CompiledTemplates }, parameters) => {
if (data instanceof ExecutionError) {
Expand Down
1 change: 1 addition & 0 deletions packages/encoder/bag-of-paths-encoder/src/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export function collectPaths(model: GraphModel, parameters: PathParameters, step
}
},
)
.filter(({ weight }) => weight >= parameters.minPathWeight && weight <= parameters.maxPathWeight)
.toArray()
.sort(pathOrder(parameters.order))
if (parameters.maxPaths > 0) {
Expand Down
58 changes: 58 additions & 0 deletions packages/encoder/bag-of-paths-encoder/test/paths.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ describe('paths', () => {
allowCycles: false,
minPathLength: 1,
maxPathLength: 3,
minPathWeight: 0,
maxPathWeight: Number.MAX_SAFE_INTEGER,
pathWeight: 'length',
maxPaths: -1,
order: 'desc',
Expand Down Expand Up @@ -87,6 +89,8 @@ describe('paths', () => {
allowCycles: true,
minPathLength: 1,
maxPathLength: 3,
minPathWeight: 0,
maxPathWeight: Number.MAX_SAFE_INTEGER,
pathWeight: 'length',
maxPaths: -1,
order: 'desc',
Expand Down Expand Up @@ -148,6 +152,8 @@ describe('paths', () => {
allowCycles: false,
minPathLength: 1,
maxPathLength: 3,
minPathWeight: 0,
maxPathWeight: Number.MAX_SAFE_INTEGER,
pathWeight: 'length',
maxPaths: -1,
order: 'desc',
Expand Down Expand Up @@ -192,6 +198,8 @@ describe('paths', () => {
allowCycles: true,
minPathLength: 1,
maxPathLength: 3,
minPathWeight: 0,
maxPathWeight: Number.MAX_SAFE_INTEGER,
pathWeight: 'length',
maxPaths: -1,
order: 'desc',
Expand Down Expand Up @@ -254,6 +262,8 @@ describe('paths', () => {
allowCycles: false,
minPathLength: 1,
maxPathLength: 3,
minPathWeight: 0,
maxPathWeight: Number.MAX_SAFE_INTEGER,
pathWeight: 'length',
maxPaths: 1,
order: 'desc',
Expand Down Expand Up @@ -282,6 +292,8 @@ describe('paths', () => {
allowCycles: false,
minPathLength: 2,
maxPathLength: 3,
minPathWeight: 0,
maxPathWeight: Number.MAX_SAFE_INTEGER,
pathWeight: 'length',
maxPaths: -1,
order: 'desc',
Expand Down Expand Up @@ -322,6 +334,8 @@ describe('paths', () => {
allowCycles: false,
minPathLength: 1,
maxPathLength: 1,
minPathWeight: 0,
maxPathWeight: Number.MAX_SAFE_INTEGER,
pathWeight: 'length',
maxPaths: -1,
order: 'desc',
Expand Down Expand Up @@ -368,6 +382,8 @@ describe('paths', () => {
allowCycles: false,
minPathLength: 0,
maxPathLength: 0,
minPathWeight: 0,
maxPathWeight: Number.MAX_SAFE_INTEGER,
pathWeight: 'length',
maxPaths: -1,
order: 'desc',
Expand Down Expand Up @@ -415,6 +431,8 @@ describe('paths', () => {
allowCycles: false,
minPathLength: 2,
maxPathLength: 3,
minPathWeight: 0,
maxPathWeight: Number.MAX_SAFE_INTEGER,
pathWeight: 'length',
maxPaths: -1,
order: 'desc',
Expand All @@ -428,6 +446,8 @@ describe('paths', () => {
allowCycles: false,
minPathLength: 2,
maxPathLength: 4,
minPathWeight: 0,
maxPathWeight: Number.MAX_SAFE_INTEGER,
pathWeight: 'length',
maxPaths: 1,
order: 'desc',
Expand All @@ -441,6 +461,8 @@ describe('paths', () => {
allowCycles: false,
minPathLength: 2,
maxPathLength: 3,
minPathWeight: 0,
maxPathWeight: Number.MAX_SAFE_INTEGER,
pathWeight: 'length',
maxPaths: -1,
order: 'desc',
Expand All @@ -456,6 +478,8 @@ describe('paths', () => {
allowCycles: false,
minPathLength: 1,
maxPathLength: 3,
minPathWeight: 0,
maxPathWeight: Number.MAX_SAFE_INTEGER,
pathWeight: 'length',
maxPaths: -1,
order: 'desc',
Expand All @@ -469,6 +493,8 @@ describe('paths', () => {
allowCycles: false,
minPathLength: 1,
maxPathLength: 2,
minPathWeight: 0,
maxPathWeight: Number.MAX_SAFE_INTEGER,
pathWeight: 'step-product',
maxPaths: -1,
order: 'desc',
Expand All @@ -482,12 +508,44 @@ describe('paths', () => {
allowCycles: false,
minPathLength: 1,
maxPathLength: 2,
minPathWeight: 0,
maxPathWeight: Number.MAX_SAFE_INTEGER,
pathWeight: 'step-sum',
maxPaths: -1,
order: 'desc',
}, ['@source.id = a >>> 3', '2'].map(compileStepWeighting))
expect(snapshottify(paths).map(({ weight }) => weight)).toEqual([5, 3, 2])
})

it('can set a minimum path-weight', () => {
const model = createTestModel(['a', 'b', 'c'], [['a', 'b'], ['b', 'c']])
const paths = collectPaths(model, {
allowCycles: false,
minPathLength: 1,
maxPathLength: 1,
minPathWeight: 3,
maxPathWeight: Number.MAX_SAFE_INTEGER,
pathWeight: 'step-sum',
maxPaths: -1,
order: 'desc',
}, ['@source.id = a >>> 3', '2'].map(compileStepWeighting))
expect(snapshottify(paths).map(({ weight }) => weight)).toEqual([3])
})

it('can set a maximum path-weight', () => {
const model = createTestModel(['a', 'b', 'c'], [['a', 'b'], ['b', 'c']])
const paths = collectPaths(model, {
allowCycles: false,
minPathLength: 1,
maxPathLength: 1,
minPathWeight: 0,
maxPathWeight: 2,
pathWeight: 'step-sum',
maxPaths: -1,
order: 'desc',
}, ['@source.id = a >>> 3', '2'].map(compileStepWeighting))
expect(snapshottify(paths).map(({ weight }) => weight)).toEqual([2])
})
})
})
})
4 changes: 4 additions & 0 deletions packages/encoder/bag-of-paths-encoder/test/prune.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ describe('pruning', () => {
allowCycles: false,
minPathLength: 1,
maxPathLength: 3,
minPathWeight: 0,
maxPathWeight: Number.MAX_SAFE_INTEGER,
pathWeight: 'length',
maxPaths: -1,
order: 'asc',
Expand Down Expand Up @@ -64,6 +66,8 @@ describe('pruning', () => {
allowCycles: false,
minPathLength: 1,
maxPathLength: 3,
minPathWeight: 0,
maxPathWeight: Number.MAX_SAFE_INTEGER,
pathWeight: 'length',
maxPaths: -1,
order: 'asc',
Expand Down
10 changes: 5 additions & 5 deletions packages/visualizer/src/components/Parameters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ export function Parameters({ parameters, setValues, values }: Props) {
<Card>
<CardContent className="px-4 py-2">
<CardHeader className="p-0 pb-2">
<div className="@container flex items-center justify-between">
<div className="flex items-center justify-between @container">
<Label>Parameters</Label>
<Button variant="ghost" onClick={resetParameters} className="text-primary -mr-2 gap-2 first-line:flex ">
<span className="@xs:inline hidden">Reset</span>
<Button variant="ghost" onClick={resetParameters} className="-mr-2 gap-2 text-primary first-line:flex ">
<span className="hidden @xs:inline">Reset</span>
<SymbolIcon className="size-4" />
</Button>
</div>
Expand Down Expand Up @@ -329,7 +329,7 @@ function StringListInput({
<CollapsibleContent>
<Container>
{input}
<Button variant="ghost" onClick={() => onChange([])} className="text-primary mx-auto flex gap-2" disabled={values.length === 0}>
<Button variant="ghost" onClick={() => onChange([])} className="mx-auto flex gap-2 text-primary" disabled={values.length === 0}>
Clear
<TrashIcon className="size-4" />
</Button>
Expand Down Expand Up @@ -455,7 +455,7 @@ function ParameterLabel({ name, label }: { name: string, label: string }) {

function Description({ description, helpText }: { description: string, helpText: string | undefined }) {
return (
<div className="text-muted-foreground flex cursor-default items-center gap-2 text-balance text-xs">
<div className="flex cursor-default items-center gap-2 text-balance text-xs text-muted-foreground">
<span>
{description}
</span>
Expand Down
2 changes: 1 addition & 1 deletion packages/visualizer/src/components/model/ModelForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ export function ModelForm() {

function Or() {
return (
<span className="text-muted-foreground mx-auto flex w-full items-center gap-2 text-xs">
<span className="mx-auto flex w-full items-center gap-2 text-xs text-muted-foreground">
<Separator className="shrink" />
or
<Separator className="shrink" />
Expand Down

0 comments on commit 277e792

Please sign in to comment.