@rimbu/graph
Version:
Immutable Graph data structures for TypeScript
354 lines • 15.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ValuedGraphNonEmpty = void 0;
var tslib_1 = require("tslib");
var map_custom_1 = require("@rimbu/collection-types/map-custom");
var common_1 = require("@rimbu/common");
var stream_1 = require("@rimbu/stream");
var ValuedGraphNonEmpty = /** @class */ (function (_super) {
tslib_1.__extends(ValuedGraphNonEmpty, _super);
function ValuedGraphNonEmpty(isDirected, context, linkMap, connectionSize) {
var _this = _super.call(this) || this;
_this.isDirected = isDirected;
_this.context = context;
_this.linkMap = linkMap;
_this.connectionSize = connectionSize;
return _this;
}
ValuedGraphNonEmpty.prototype.copy = function (linkMap, connectionSize) {
if (linkMap === this.linkMap && connectionSize === this.connectionSize) {
return this;
}
return this.context.createNonEmpty(linkMap, connectionSize);
};
ValuedGraphNonEmpty.prototype.copyE = function (linkMap, connectionSize) {
if (linkMap.nonEmpty()) {
return this.copy(linkMap, connectionSize);
}
return this.context.empty();
};
ValuedGraphNonEmpty.prototype.assumeNonEmpty = function () {
return this;
};
ValuedGraphNonEmpty.prototype.asNormal = function () {
return this;
};
ValuedGraphNonEmpty.prototype.forEach = function (f, options) {
if (options === void 0) { options = {}; }
var _a = options.state, state = _a === void 0 ? (0, common_1.TraverseState)() : _a;
var mapIter = this.linkMap[Symbol.iterator]();
var done = Symbol();
var targetsEntry;
while (!state.halted && done !== (targetsEntry = mapIter.fastNext(done))) {
var _b = tslib_1.__read(targetsEntry, 2), node = _b[0], targets = _b[1];
if (targets.isEmpty) {
f([node], state.nextIndex(), state.halt);
}
else {
var targetsIter = targets[Symbol.iterator]();
var target = void 0;
while (!state.halted &&
done !== (target = targetsIter.fastNext(done))) {
var _c = tslib_1.__read(target, 2), targetNode = _c[0], value = _c[1];
f([node, targetNode, value], state.nextIndex(), state.halt);
}
}
}
};
ValuedGraphNonEmpty.prototype.stream = function () {
return this.linkMap.stream().flatMap(function (_a) {
var _b = tslib_1.__read(_a, 2), node = _b[0], targets = _b[1];
if (!targets.nonEmpty())
return [[node]];
return targets
.stream()
.map(function (_a) {
var _b = tslib_1.__read(_a, 2), target = _b[0], value = _b[1];
return [node, target, value];
});
});
};
Object.defineProperty(ValuedGraphNonEmpty.prototype, "nodeSize", {
get: function () {
return this.linkMap.size;
},
enumerable: false,
configurable: true
});
ValuedGraphNonEmpty.prototype.streamNodes = function () {
return this.linkMap.streamKeys();
};
ValuedGraphNonEmpty.prototype.streamConnections = function () {
return this.linkMap
.stream()
.flatMap(function (_a) {
var _b = tslib_1.__read(_a, 2), node1 = _b[0], targets = _b[1];
return targets
.stream()
.map(function (_a) {
var _b = tslib_1.__read(_a, 2), node2 = _b[0], value = _b[1];
return [node1, node2, value];
});
});
};
ValuedGraphNonEmpty.prototype.hasNode = function (node) {
return this.linkMap.hasKey(node);
};
ValuedGraphNonEmpty.prototype.hasConnection = function (node1, node2) {
var _a;
var targets = this.linkMap.get(node1);
return (_a = targets === null || targets === void 0 ? void 0 : targets.hasKey(node2)) !== null && _a !== void 0 ? _a : false;
};
ValuedGraphNonEmpty.prototype.getValue = function (node1, node2, otherwise) {
var targets = this.linkMap.get(node1);
if (undefined === targets)
return (0, common_1.OptLazy)(otherwise);
return targets.get(node2, otherwise);
};
ValuedGraphNonEmpty.prototype.getConnectionStreamFrom = function (node1) {
var targets = this.linkMap.get(node1);
if (undefined === targets)
return stream_1.Stream.empty();
return targets
.stream()
.map(function (_a) {
var _b = tslib_1.__read(_a, 2), node2 = _b[0], value = _b[1];
return [node1, node2, value];
});
};
ValuedGraphNonEmpty.prototype.getConnectionStreamTo = function (node) {
if (this.isDirected) {
return this.streamConnections().filter(function (_a) {
var _b = tslib_1.__read(_a, 2), _ = _b[0], node2 = _b[1];
return node2 === node;
});
}
var targets = this.linkMap.get(node);
if (undefined === targets)
return stream_1.Stream.empty();
return targets
.stream()
.map(function (_a) {
var _b = tslib_1.__read(_a, 2), node1 = _b[0], value = _b[1];
return [node1, node, value];
});
};
ValuedGraphNonEmpty.prototype.getConnectionsFrom = function (node1) {
return this.linkMap.get(node1, this.context.linkConnectionsContext.empty());
};
ValuedGraphNonEmpty.prototype.isSink = function (node) {
var _a;
var targets = this.linkMap.get(node);
return (_a = targets === null || targets === void 0 ? void 0 : targets.isEmpty) !== null && _a !== void 0 ? _a : false;
};
ValuedGraphNonEmpty.prototype.isSource = function (node) {
return (this.linkMap.hasKey(node) &&
this.linkMap.streamValues().every(function (targets) { return !targets.hasKey(node); }));
};
ValuedGraphNonEmpty.prototype.addNode = function (node) {
return this.copy(this.linkMap
.modifyAt(node, { ifNew: this.context.linkConnectionsContext.empty })
.assumeNonEmpty(), this.connectionSize);
};
ValuedGraphNonEmpty.prototype.addNodes = function (nodes) {
var builder = this.toBuilder();
builder.addNodes(nodes);
return builder.build().assumeNonEmpty();
};
ValuedGraphNonEmpty.prototype.removeNode = function (node) {
var builder = this.toBuilder();
builder.removeNode(node);
return builder.build();
};
ValuedGraphNonEmpty.prototype.removeNodes = function (nodes) {
var builder = this.toBuilder();
builder.removeNodes(nodes);
return builder.build();
};
ValuedGraphNonEmpty.prototype.connect = function (node1, node2, value) {
var _this = this;
var newLinkMap = this.linkMap.modifyAt(node1, {
ifNew: this.context.linkConnectionsContext.of([node2, value]),
ifExists: function (targets) { return targets.set(node2, value); },
});
if (newLinkMap === this.linkMap)
return this;
var newConnectionSize = this.connectionSize + 1;
if (Object.is(node1, node2) || this.isDirected) {
return this.context.createNonEmpty(newLinkMap.assumeNonEmpty(), newConnectionSize);
}
return this.copy(newLinkMap
.modifyAt(node2, {
ifNew: function () {
if (_this.isDirected) {
return _this.context.linkConnectionsContext.empty();
}
return _this.context.linkConnectionsContext.of([node1, value]);
},
})
.assumeNonEmpty(), newConnectionSize);
};
ValuedGraphNonEmpty.prototype.connectAll = function (links) {
var builder = this.toBuilder();
builder.connectAll(links);
return builder.build().assumeNonEmpty();
};
ValuedGraphNonEmpty.prototype.modifyAt = function (node1, node2, options) {
var _this = this;
var newConnectionSize = this.connectionSize;
var addedOrUpdatedValue;
var newLinkMap = this.linkMap.modifyAt(node1, {
ifNew: function (none) {
if (undefined === options.ifNew)
return none;
var newValue = (0, common_1.OptLazyOr)(options.ifNew, none);
if (none === newValue)
return none;
addedOrUpdatedValue = newValue;
newConnectionSize++;
return _this.context.linkMapContext.of([node2, newValue]);
},
ifExists: function (valueMap) {
var ifExists = options.ifExists;
if (undefined === ifExists)
return valueMap;
return valueMap.modifyAt(node2, {
ifNew: function (none) {
if (undefined === options.ifNew)
return none;
var newValue = (0, common_1.OptLazyOr)(options.ifNew, none);
if (none === newValue)
return none;
addedOrUpdatedValue = newValue;
newConnectionSize++;
return newValue;
},
ifExists: function (currentValue, remove) {
var newValue = ifExists instanceof Function
? ifExists(currentValue, remove)
: ifExists;
if (Object.is(newValue, currentValue))
return currentValue;
if (remove === newValue) {
newConnectionSize--;
}
else {
addedOrUpdatedValue = newValue;
}
return newValue;
},
});
},
});
if (newLinkMap === this.linkMap)
return this;
if (this.isDirected) {
return this.copy(newLinkMap.assumeNonEmpty(), newConnectionSize);
}
// edge graph, need to update counterpart
if (newConnectionSize === this.connectionSize) {
// value was updated
var newLinkMap2_1 = newLinkMap.modifyAt(node2, {
ifNew: function () {
return _this.context.linkMapContext.of([node1, addedOrUpdatedValue]);
},
ifExists: function (valueMap) { return valueMap.set(node1, addedOrUpdatedValue); },
});
return this.copy(newLinkMap2_1.assumeNonEmpty(), newConnectionSize);
}
if (newConnectionSize < this.connectionSize) {
// value was removed
var newLinkMap2_2 = newLinkMap.modifyAt(node2, {
ifExists: function (valueMap) { return valueMap.removeKey(node1); },
});
return this.copy(newLinkMap2_2.assumeNonEmpty(), newConnectionSize);
}
// value was added
var newLinkMap2 = newLinkMap.modifyAt(node2, {
ifNew: function () { return _this.context.linkMapContext.of([node1, addedOrUpdatedValue]); },
ifExists: function (valueMap) { return valueMap.set(node1, addedOrUpdatedValue); },
});
return this.copy(newLinkMap2.assumeNonEmpty(), newConnectionSize);
};
ValuedGraphNonEmpty.prototype.disconnect = function (node1, node2) {
if (!this.linkMap.context.isValidKey(node1) ||
!this.linkMap.context.isValidKey(node2))
return this;
var newLinkMap = this.linkMap.updateAt(node1, function (targets) {
return targets.removeKey(node2);
});
if (newLinkMap === this.linkMap)
return this;
var newConnectionSize = this.connectionSize - 1;
if (this.isDirected)
return this.copy(newLinkMap, newConnectionSize);
return this.copy(newLinkMap.updateAt(node2, function (targets) { return targets.removeKey(node1); }), newConnectionSize);
};
ValuedGraphNonEmpty.prototype.disconnectAll = function (links) {
var builder = this.toBuilder();
builder.disconnectAll(links);
return builder.build().assumeNonEmpty();
};
ValuedGraphNonEmpty.prototype.removeUnconnectedNodes = function () {
var _this = this;
if (!this.isDirected) {
var newLinkMap = this.linkMap.filter(function (_a) {
var _b = tslib_1.__read(_a, 2), _ = _b[0], targets = _b[1];
return targets.nonEmpty();
});
return this.copyE(newLinkMap, this.connectionSize);
}
var unconnectedNodes = this.linkMap
.stream()
.collect(function (_a, _, skip) {
var _b = tslib_1.__read(_a, 2), source = _b[0], targets = _b[1];
if (targets.isEmpty &&
!_this.linkMap.streamValues().some(function (t) { return t.hasKey(source); })) {
return source;
}
return skip;
});
return this.removeNodes(unconnectedNodes);
};
ValuedGraphNonEmpty.prototype.mapValues = function (mapFun) {
var newLinkMap = this.linkMap.mapValues(function (targets, node1) {
return targets.mapValues(function (value, node2) { return mapFun(value, node1, node2); });
});
return this.context.createNonEmpty(newLinkMap, this.connectionSize);
};
ValuedGraphNonEmpty.prototype.toString = function () {
var connector = this.isDirected ? '->' : '<->';
return this.linkMap.stream().join({
start: "".concat(this.context.typeTag, "(\n "),
sep: ',\n ',
end: '\n)',
valueToString: function (_a) {
var _b = tslib_1.__read(_a, 2), node = _b[0], targets = _b[1];
return "".concat(node, " ").concat(connector, " ").concat(targets.stream().join({
start: '[',
sep: ', ',
end: ']',
valueToString: function (_a) {
var _b = tslib_1.__read(_a, 2), node2 = _b[0], value = _b[1];
return "{".concat(node2, ": ").concat(value, "}");
},
}));
},
});
};
ValuedGraphNonEmpty.prototype.toJSON = function () {
return {
dataType: this.context.typeTag,
value: this.linkMap
.stream()
.map(function (entry) { return [entry[0], entry[1].toArray()]; })
.toArray(),
};
};
ValuedGraphNonEmpty.prototype.toBuilder = function () {
return this.context.createBuilder(this);
};
return ValuedGraphNonEmpty;
}(map_custom_1.NonEmptyBase));
exports.ValuedGraphNonEmpty = ValuedGraphNonEmpty;
//# sourceMappingURL=non-empty.cjs.map