combstruct 0.1.0a0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- combstruct/__init__.py +60 -0
- combstruct/__main__.py +5 -0
- combstruct/catalog.py +293 -0
- combstruct/data/ecs00/ecs_0001.json +35 -0
- combstruct/data/ecs00/ecs_0002.json +37 -0
- combstruct/data/ecs00/ecs_0003.json +35 -0
- combstruct/data/ecs00/ecs_0004.json +35 -0
- combstruct/data/ecs00/ecs_0005.json +35 -0
- combstruct/data/ecs00/ecs_0006.json +39 -0
- combstruct/data/ecs00/ecs_0007.json +39 -0
- combstruct/data/ecs00/ecs_0008.json +39 -0
- combstruct/data/ecs00/ecs_0009.json +40 -0
- combstruct/data/ecs00/ecs_0010.json +38 -0
- combstruct/data/ecs00/ecs_0011.json +38 -0
- combstruct/data/ecs00/ecs_0012.json +38 -0
- combstruct/data/ecs00/ecs_0013.json +38 -0
- combstruct/data/ecs00/ecs_0014.json +38 -0
- combstruct/data/ecs00/ecs_0015.json +37 -0
- combstruct/data/ecs00/ecs_0016.json +35 -0
- combstruct/data/ecs00/ecs_0017.json +38 -0
- combstruct/data/ecs00/ecs_0018.json +37 -0
- combstruct/data/ecs00/ecs_0019.json +37 -0
- combstruct/data/ecs00/ecs_0020.json +40 -0
- combstruct/data/ecs00/ecs_0021.json +38 -0
- combstruct/data/ecs00/ecs_0022.json +38 -0
- combstruct/data/ecs00/ecs_0023.json +39 -0
- combstruct/data/ecs00/ecs_0024.json +37 -0
- combstruct/data/ecs00/ecs_0025.json +37 -0
- combstruct/data/ecs00/ecs_0026.json +37 -0
- combstruct/data/ecs00/ecs_0027.json +38 -0
- combstruct/data/ecs00/ecs_0028.json +37 -0
- combstruct/data/ecs00/ecs_0029.json +38 -0
- combstruct/data/ecs00/ecs_0030.json +38 -0
- combstruct/data/ecs00/ecs_0031.json +38 -0
- combstruct/data/ecs00/ecs_0032.json +38 -0
- combstruct/data/ecs00/ecs_0033.json +37 -0
- combstruct/data/ecs00/ecs_0034.json +37 -0
- combstruct/data/ecs00/ecs_0035.json +38 -0
- combstruct/data/ecs00/ecs_0036.json +36 -0
- combstruct/data/ecs00/ecs_0037.json +36 -0
- combstruct/data/ecs00/ecs_0038.json +38 -0
- combstruct/data/ecs00/ecs_0039.json +35 -0
- combstruct/data/ecs00/ecs_0040.json +37 -0
- combstruct/data/ecs00/ecs_0041.json +36 -0
- combstruct/data/ecs00/ecs_0042.json +37 -0
- combstruct/data/ecs00/ecs_0043.json +35 -0
- combstruct/data/ecs00/ecs_0044.json +35 -0
- combstruct/data/ecs00/ecs_0045.json +35 -0
- combstruct/data/ecs00/ecs_0046.json +38 -0
- combstruct/data/ecs00/ecs_0047.json +38 -0
- combstruct/data/ecs00/ecs_0048.json +41 -0
- combstruct/data/ecs00/ecs_0049.json +39 -0
- combstruct/data/ecs00/ecs_0050.json +38 -0
- combstruct/data/ecs00/ecs_0051.json +39 -0
- combstruct/data/ecs00/ecs_0052.json +42 -0
- combstruct/data/ecs00/ecs_0053.json +39 -0
- combstruct/data/ecs00/ecs_0054.json +38 -0
- combstruct/data/ecs00/ecs_0055.json +39 -0
- combstruct/data/ecs00/ecs_0056.json +35 -0
- combstruct/data/ecs00/ecs_0057.json +35 -0
- combstruct/data/ecs00/ecs_0058.json +35 -0
- combstruct/data/ecs00/ecs_0059.json +35 -0
- combstruct/data/ecs00/ecs_0060.json +35 -0
- combstruct/data/ecs00/ecs_0061.json +35 -0
- combstruct/data/ecs00/ecs_0062.json +35 -0
- combstruct/data/ecs00/ecs_0063.json +35 -0
- combstruct/data/ecs00/ecs_0064.json +37 -0
- combstruct/data/ecs00/ecs_0065.json +37 -0
- combstruct/data/ecs00/ecs_0066.json +35 -0
- combstruct/data/ecs00/ecs_0067.json +36 -0
- combstruct/data/ecs00/ecs_0068.json +39 -0
- combstruct/data/ecs00/ecs_0069.json +36 -0
- combstruct/data/ecs00/ecs_0070.json +35 -0
- combstruct/data/ecs00/ecs_0071.json +39 -0
- combstruct/data/ecs00/ecs_0072.json +39 -0
- combstruct/data/ecs00/ecs_0073.json +37 -0
- combstruct/data/ecs00/ecs_0074.json +35 -0
- combstruct/data/ecs00/ecs_0075.json +37 -0
- combstruct/data/ecs00/ecs_0076.json +40 -0
- combstruct/data/ecs00/ecs_0077.json +38 -0
- combstruct/data/ecs00/ecs_0078.json +36 -0
- combstruct/data/ecs00/ecs_0079.json +35 -0
- combstruct/data/ecs00/ecs_0080.json +38 -0
- combstruct/data/ecs00/ecs_0081.json +38 -0
- combstruct/data/ecs00/ecs_0082.json +38 -0
- combstruct/data/ecs00/ecs_0083.json +38 -0
- combstruct/data/ecs00/ecs_0084.json +38 -0
- combstruct/data/ecs00/ecs_0085.json +38 -0
- combstruct/data/ecs00/ecs_0086.json +38 -0
- combstruct/data/ecs00/ecs_0087.json +38 -0
- combstruct/data/ecs00/ecs_0088.json +38 -0
- combstruct/data/ecs00/ecs_0089.json +35 -0
- combstruct/data/ecs00/ecs_0090.json +35 -0
- combstruct/data/ecs00/ecs_0091.json +35 -0
- combstruct/data/ecs00/ecs_0092.json +37 -0
- combstruct/data/ecs00/ecs_0093.json +37 -0
- combstruct/data/ecs00/ecs_0094.json +37 -0
- combstruct/data/ecs00/ecs_0095.json +35 -0
- combstruct/data/ecs00/ecs_0096.json +35 -0
- combstruct/data/ecs00/ecs_0097.json +38 -0
- combstruct/data/ecs00/ecs_0098.json +38 -0
- combstruct/data/ecs00/ecs_0099.json +36 -0
- combstruct/data/ecs01/ecs_0100.json +35 -0
- combstruct/data/ecs01/ecs_0101.json +38 -0
- combstruct/data/ecs01/ecs_0102.json +35 -0
- combstruct/data/ecs01/ecs_0103.json +38 -0
- combstruct/data/ecs01/ecs_0104.json +38 -0
- combstruct/data/ecs01/ecs_0105.json +38 -0
- combstruct/data/ecs01/ecs_0106.json +38 -0
- combstruct/data/ecs01/ecs_0107.json +35 -0
- combstruct/data/ecs01/ecs_0108.json +35 -0
- combstruct/data/ecs01/ecs_0109.json +38 -0
- combstruct/data/ecs01/ecs_0110.json +36 -0
- combstruct/data/ecs01/ecs_0111.json +36 -0
- combstruct/data/ecs01/ecs_0112.json +38 -0
- combstruct/data/ecs01/ecs_0113.json +35 -0
- combstruct/data/ecs01/ecs_0114.json +38 -0
- combstruct/data/ecs01/ecs_0115.json +39 -0
- combstruct/data/ecs01/ecs_0116.json +38 -0
- combstruct/data/ecs01/ecs_0117.json +35 -0
- combstruct/data/ecs01/ecs_0118.json +35 -0
- combstruct/data/ecs01/ecs_0119.json +35 -0
- combstruct/data/ecs01/ecs_0120.json +36 -0
- combstruct/data/ecs01/ecs_0121.json +38 -0
- combstruct/data/ecs01/ecs_0122.json +36 -0
- combstruct/data/ecs01/ecs_0123.json +34 -0
- combstruct/data/ecs01/ecs_0124.json +37 -0
- combstruct/data/ecs01/ecs_0125.json +36 -0
- combstruct/data/ecs01/ecs_0126.json +35 -0
- combstruct/data/ecs01/ecs_0127.json +38 -0
- combstruct/data/ecs01/ecs_0128.json +35 -0
- combstruct/data/ecs01/ecs_0129.json +35 -0
- combstruct/data/ecs01/ecs_0130.json +36 -0
- combstruct/data/ecs01/ecs_0131.json +37 -0
- combstruct/data/ecs01/ecs_0132.json +38 -0
- combstruct/data/ecs01/ecs_0133.json +38 -0
- combstruct/data/ecs01/ecs_0134.json +38 -0
- combstruct/data/ecs01/ecs_0135.json +38 -0
- combstruct/data/ecs01/ecs_0136.json +38 -0
- combstruct/data/ecs01/ecs_0137.json +35 -0
- combstruct/data/ecs01/ecs_0138.json +39 -0
- combstruct/data/ecs01/ecs_0139.json +38 -0
- combstruct/data/ecs01/ecs_0140.json +38 -0
- combstruct/data/ecs01/ecs_0141.json +35 -0
- combstruct/data/ecs01/ecs_0142.json +38 -0
- combstruct/data/ecs01/ecs_0143.json +38 -0
- combstruct/data/ecs01/ecs_0144.json +34 -0
- combstruct/data/ecs01/ecs_0145.json +38 -0
- combstruct/data/ecs01/ecs_0146.json +38 -0
- combstruct/data/ecs01/ecs_0147.json +38 -0
- combstruct/data/ecs01/ecs_0148.json +35 -0
- combstruct/data/ecs01/ecs_0149.json +36 -0
- combstruct/data/ecs01/ecs_0150.json +38 -0
- combstruct/data/ecs01/ecs_0151.json +39 -0
- combstruct/data/ecs01/ecs_0152.json +35 -0
- combstruct/data/ecs01/ecs_0153.json +37 -0
- combstruct/data/ecs01/ecs_0154.json +36 -0
- combstruct/data/ecs01/ecs_0155.json +38 -0
- combstruct/data/ecs01/ecs_0156.json +37 -0
- combstruct/data/ecs01/ecs_0157.json +36 -0
- combstruct/data/ecs01/ecs_0158.json +38 -0
- combstruct/data/ecs01/ecs_0159.json +37 -0
- combstruct/data/ecs01/ecs_0160.json +36 -0
- combstruct/data/ecs01/ecs_0161.json +35 -0
- combstruct/data/ecs01/ecs_0162.json +35 -0
- combstruct/data/ecs01/ecs_0163.json +38 -0
- combstruct/data/ecs01/ecs_0164.json +38 -0
- combstruct/data/ecs01/ecs_0165.json +38 -0
- combstruct/data/ecs01/ecs_0166.json +35 -0
- combstruct/data/ecs01/ecs_0167.json +34 -0
- combstruct/data/ecs01/ecs_0168.json +38 -0
- combstruct/data/ecs01/ecs_0169.json +38 -0
- combstruct/data/ecs01/ecs_0170.json +38 -0
- combstruct/data/ecs01/ecs_0171.json +38 -0
- combstruct/data/ecs01/ecs_0172.json +36 -0
- combstruct/data/ecs01/ecs_0173.json +36 -0
- combstruct/data/ecs01/ecs_0174.json +38 -0
- combstruct/data/ecs01/ecs_0175.json +38 -0
- combstruct/data/ecs01/ecs_0176.json +38 -0
- combstruct/data/ecs01/ecs_0177.json +38 -0
- combstruct/data/ecs01/ecs_0178.json +38 -0
- combstruct/data/ecs01/ecs_0179.json +38 -0
- combstruct/data/ecs01/ecs_0180.json +38 -0
- combstruct/data/ecs01/ecs_0181.json +38 -0
- combstruct/data/ecs01/ecs_0182.json +38 -0
- combstruct/data/ecs01/ecs_0183.json +38 -0
- combstruct/data/ecs01/ecs_0184.json +38 -0
- combstruct/data/ecs01/ecs_0185.json +38 -0
- combstruct/data/ecs01/ecs_0186.json +38 -0
- combstruct/data/ecs01/ecs_0187.json +38 -0
- combstruct/data/ecs01/ecs_0188.json +38 -0
- combstruct/data/ecs01/ecs_0189.json +38 -0
- combstruct/data/ecs01/ecs_0190.json +38 -0
- combstruct/data/ecs01/ecs_0191.json +38 -0
- combstruct/data/ecs01/ecs_0192.json +38 -0
- combstruct/data/ecs01/ecs_0193.json +38 -0
- combstruct/data/ecs01/ecs_0194.json +38 -0
- combstruct/data/ecs01/ecs_0195.json +38 -0
- combstruct/data/ecs01/ecs_0196.json +38 -0
- combstruct/data/ecs01/ecs_0197.json +38 -0
- combstruct/data/ecs01/ecs_0198.json +38 -0
- combstruct/data/ecs01/ecs_0199.json +38 -0
- combstruct/data/ecs02/ecs_0200.json +38 -0
- combstruct/data/ecs02/ecs_0201.json +38 -0
- combstruct/data/ecs02/ecs_0202.json +39 -0
- combstruct/data/ecs02/ecs_0203.json +39 -0
- combstruct/data/ecs02/ecs_0204.json +38 -0
- combstruct/data/ecs02/ecs_0205.json +38 -0
- combstruct/data/ecs02/ecs_0206.json +38 -0
- combstruct/data/ecs02/ecs_0207.json +38 -0
- combstruct/data/ecs02/ecs_0208.json +38 -0
- combstruct/data/ecs02/ecs_0209.json +39 -0
- combstruct/data/ecs02/ecs_0210.json +38 -0
- combstruct/data/ecs02/ecs_0211.json +38 -0
- combstruct/data/ecs02/ecs_0212.json +39 -0
- combstruct/data/ecs02/ecs_0213.json +38 -0
- combstruct/data/ecs02/ecs_0214.json +38 -0
- combstruct/data/ecs02/ecs_0215.json +38 -0
- combstruct/data/ecs02/ecs_0216.json +38 -0
- combstruct/data/ecs02/ecs_0217.json +38 -0
- combstruct/data/ecs02/ecs_0218.json +38 -0
- combstruct/data/ecs02/ecs_0219.json +38 -0
- combstruct/data/ecs02/ecs_0220.json +38 -0
- combstruct/data/ecs02/ecs_0221.json +38 -0
- combstruct/data/ecs02/ecs_0222.json +38 -0
- combstruct/data/ecs02/ecs_0223.json +38 -0
- combstruct/data/ecs02/ecs_0224.json +38 -0
- combstruct/data/ecs02/ecs_0225.json +38 -0
- combstruct/data/ecs02/ecs_0226.json +38 -0
- combstruct/data/ecs02/ecs_0227.json +38 -0
- combstruct/data/ecs02/ecs_0228.json +38 -0
- combstruct/data/ecs02/ecs_0229.json +38 -0
- combstruct/data/ecs02/ecs_0230.json +38 -0
- combstruct/data/ecs02/ecs_0231.json +37 -0
- combstruct/data/ecs02/ecs_0232.json +39 -0
- combstruct/data/ecs02/ecs_0233.json +38 -0
- combstruct/data/ecs02/ecs_0234.json +38 -0
- combstruct/data/ecs02/ecs_0235.json +38 -0
- combstruct/data/ecs02/ecs_0236.json +38 -0
- combstruct/data/ecs02/ecs_0237.json +38 -0
- combstruct/data/ecs02/ecs_0238.json +38 -0
- combstruct/data/ecs02/ecs_0239.json +38 -0
- combstruct/data/ecs02/ecs_0240.json +38 -0
- combstruct/data/ecs02/ecs_0241.json +38 -0
- combstruct/data/ecs02/ecs_0242.json +38 -0
- combstruct/data/ecs02/ecs_0243.json +38 -0
- combstruct/data/ecs02/ecs_0244.json +38 -0
- combstruct/data/ecs02/ecs_0245.json +38 -0
- combstruct/data/ecs02/ecs_0246.json +38 -0
- combstruct/data/ecs02/ecs_0247.json +36 -0
- combstruct/data/ecs02/ecs_0248.json +38 -0
- combstruct/data/ecs02/ecs_0249.json +38 -0
- combstruct/data/ecs02/ecs_0250.json +38 -0
- combstruct/data/ecs02/ecs_0251.json +38 -0
- combstruct/data/ecs02/ecs_0252.json +38 -0
- combstruct/data/ecs02/ecs_0253.json +38 -0
- combstruct/data/ecs02/ecs_0254.json +39 -0
- combstruct/data/ecs02/ecs_0255.json +38 -0
- combstruct/data/ecs02/ecs_0256.json +38 -0
- combstruct/data/ecs02/ecs_0257.json +38 -0
- combstruct/data/ecs02/ecs_0258.json +38 -0
- combstruct/data/ecs02/ecs_0259.json +38 -0
- combstruct/data/ecs02/ecs_0260.json +38 -0
- combstruct/data/ecs02/ecs_0261.json +38 -0
- combstruct/data/ecs02/ecs_0262.json +38 -0
- combstruct/data/ecs02/ecs_0263.json +38 -0
- combstruct/data/ecs02/ecs_0264.json +37 -0
- combstruct/data/ecs02/ecs_0265.json +34 -0
- combstruct/data/ecs02/ecs_0266.json +37 -0
- combstruct/data/ecs02/ecs_0267.json +39 -0
- combstruct/data/ecs02/ecs_0268.json +39 -0
- combstruct/data/ecs02/ecs_0269.json +39 -0
- combstruct/data/ecs02/ecs_0270.json +38 -0
- combstruct/data/ecs02/ecs_0271.json +38 -0
- combstruct/data/ecs02/ecs_0272.json +38 -0
- combstruct/data/ecs02/ecs_0273.json +38 -0
- combstruct/data/ecs02/ecs_0274.json +38 -0
- combstruct/data/ecs02/ecs_0275.json +38 -0
- combstruct/data/ecs02/ecs_0276.json +38 -0
- combstruct/data/ecs02/ecs_0277.json +38 -0
- combstruct/data/ecs02/ecs_0278.json +38 -0
- combstruct/data/ecs02/ecs_0279.json +38 -0
- combstruct/data/ecs02/ecs_0280.json +38 -0
- combstruct/data/ecs02/ecs_0281.json +38 -0
- combstruct/data/ecs02/ecs_0282.json +38 -0
- combstruct/data/ecs02/ecs_0283.json +38 -0
- combstruct/data/ecs02/ecs_0284.json +38 -0
- combstruct/data/ecs02/ecs_0285.json +38 -0
- combstruct/data/ecs02/ecs_0286.json +38 -0
- combstruct/data/ecs02/ecs_0287.json +38 -0
- combstruct/data/ecs02/ecs_0288.json +38 -0
- combstruct/data/ecs02/ecs_0289.json +38 -0
- combstruct/data/ecs02/ecs_0290.json +38 -0
- combstruct/data/ecs02/ecs_0291.json +35 -0
- combstruct/data/ecs02/ecs_0292.json +35 -0
- combstruct/data/ecs02/ecs_0293.json +35 -0
- combstruct/data/ecs02/ecs_0294.json +35 -0
- combstruct/data/ecs02/ecs_0295.json +35 -0
- combstruct/data/ecs02/ecs_0296.json +35 -0
- combstruct/data/ecs02/ecs_0297.json +38 -0
- combstruct/data/ecs02/ecs_0298.json +37 -0
- combstruct/data/ecs02/ecs_0299.json +36 -0
- combstruct/data/ecs03/ecs_0300.json +36 -0
- combstruct/data/ecs03/ecs_0301.json +36 -0
- combstruct/data/ecs03/ecs_0302.json +36 -0
- combstruct/data/ecs03/ecs_0303.json +36 -0
- combstruct/data/ecs03/ecs_0304.json +38 -0
- combstruct/data/ecs03/ecs_0305.json +38 -0
- combstruct/data/ecs03/ecs_0306.json +38 -0
- combstruct/data/ecs03/ecs_0307.json +38 -0
- combstruct/data/ecs03/ecs_0308.json +38 -0
- combstruct/data/ecs03/ecs_0309.json +38 -0
- combstruct/data/ecs03/ecs_0310.json +38 -0
- combstruct/data/ecs03/ecs_0311.json +38 -0
- combstruct/data/ecs03/ecs_0312.json +38 -0
- combstruct/data/ecs03/ecs_0313.json +38 -0
- combstruct/data/ecs03/ecs_0314.json +38 -0
- combstruct/data/ecs03/ecs_0315.json +38 -0
- combstruct/data/ecs03/ecs_0316.json +38 -0
- combstruct/data/ecs03/ecs_0317.json +38 -0
- combstruct/data/ecs03/ecs_0318.json +38 -0
- combstruct/data/ecs03/ecs_0319.json +38 -0
- combstruct/data/ecs03/ecs_0320.json +38 -0
- combstruct/data/ecs03/ecs_0321.json +38 -0
- combstruct/data/ecs03/ecs_0322.json +38 -0
- combstruct/data/ecs03/ecs_0323.json +38 -0
- combstruct/data/ecs03/ecs_0324.json +38 -0
- combstruct/data/ecs03/ecs_0325.json +38 -0
- combstruct/data/ecs03/ecs_0326.json +38 -0
- combstruct/data/ecs03/ecs_0327.json +38 -0
- combstruct/data/ecs03/ecs_0328.json +38 -0
- combstruct/data/ecs03/ecs_0329.json +38 -0
- combstruct/data/ecs03/ecs_0330.json +38 -0
- combstruct/data/ecs03/ecs_0331.json +38 -0
- combstruct/data/ecs03/ecs_0332.json +38 -0
- combstruct/data/ecs03/ecs_0333.json +38 -0
- combstruct/data/ecs03/ecs_0334.json +38 -0
- combstruct/data/ecs03/ecs_0335.json +38 -0
- combstruct/data/ecs03/ecs_0336.json +38 -0
- combstruct/data/ecs03/ecs_0337.json +38 -0
- combstruct/data/ecs03/ecs_0338.json +38 -0
- combstruct/data/ecs03/ecs_0339.json +38 -0
- combstruct/data/ecs03/ecs_0340.json +38 -0
- combstruct/data/ecs03/ecs_0341.json +38 -0
- combstruct/data/ecs03/ecs_0342.json +38 -0
- combstruct/data/ecs03/ecs_0343.json +38 -0
- combstruct/data/ecs03/ecs_0344.json +38 -0
- combstruct/data/ecs03/ecs_0345.json +39 -0
- combstruct/data/ecs03/ecs_0346.json +38 -0
- combstruct/data/ecs03/ecs_0347.json +38 -0
- combstruct/data/ecs03/ecs_0348.json +38 -0
- combstruct/data/ecs03/ecs_0349.json +38 -0
- combstruct/data/ecs03/ecs_0350.json +38 -0
- combstruct/data/ecs03/ecs_0351.json +39 -0
- combstruct/data/ecs03/ecs_0352.json +38 -0
- combstruct/data/ecs03/ecs_0353.json +38 -0
- combstruct/data/ecs03/ecs_0354.json +38 -0
- combstruct/data/ecs03/ecs_0355.json +38 -0
- combstruct/data/ecs03/ecs_0356.json +38 -0
- combstruct/data/ecs03/ecs_0357.json +38 -0
- combstruct/data/ecs03/ecs_0358.json +38 -0
- combstruct/data/ecs03/ecs_0359.json +38 -0
- combstruct/data/ecs03/ecs_0360.json +38 -0
- combstruct/data/ecs03/ecs_0361.json +38 -0
- combstruct/data/ecs03/ecs_0362.json +38 -0
- combstruct/data/ecs03/ecs_0363.json +38 -0
- combstruct/data/ecs03/ecs_0364.json +38 -0
- combstruct/data/ecs03/ecs_0365.json +38 -0
- combstruct/data/ecs03/ecs_0366.json +38 -0
- combstruct/data/ecs03/ecs_0367.json +38 -0
- combstruct/data/ecs03/ecs_0368.json +38 -0
- combstruct/data/ecs03/ecs_0369.json +38 -0
- combstruct/data/ecs03/ecs_0370.json +38 -0
- combstruct/data/ecs03/ecs_0371.json +39 -0
- combstruct/data/ecs03/ecs_0372.json +38 -0
- combstruct/data/ecs03/ecs_0373.json +38 -0
- combstruct/data/ecs03/ecs_0374.json +38 -0
- combstruct/data/ecs03/ecs_0375.json +38 -0
- combstruct/data/ecs03/ecs_0376.json +38 -0
- combstruct/data/ecs03/ecs_0377.json +38 -0
- combstruct/data/ecs03/ecs_0378.json +38 -0
- combstruct/data/ecs03/ecs_0379.json +38 -0
- combstruct/data/ecs03/ecs_0380.json +38 -0
- combstruct/data/ecs03/ecs_0381.json +38 -0
- combstruct/data/ecs03/ecs_0382.json +38 -0
- combstruct/data/ecs03/ecs_0383.json +38 -0
- combstruct/data/ecs03/ecs_0384.json +38 -0
- combstruct/data/ecs03/ecs_0385.json +34 -0
- combstruct/data/ecs03/ecs_0386.json +38 -0
- combstruct/data/ecs03/ecs_0387.json +34 -0
- combstruct/data/ecs03/ecs_0388.json +38 -0
- combstruct/data/ecs03/ecs_0389.json +38 -0
- combstruct/data/ecs03/ecs_0390.json +35 -0
- combstruct/data/ecs03/ecs_0391.json +35 -0
- combstruct/data/ecs03/ecs_0392.json +38 -0
- combstruct/data/ecs03/ecs_0393.json +38 -0
- combstruct/data/ecs03/ecs_0394.json +38 -0
- combstruct/data/ecs03/ecs_0395.json +37 -0
- combstruct/data/ecs03/ecs_0396.json +37 -0
- combstruct/data/ecs03/ecs_0397.json +38 -0
- combstruct/data/ecs03/ecs_0398.json +38 -0
- combstruct/data/ecs03/ecs_0399.json +38 -0
- combstruct/data/ecs04/ecs_0400.json +37 -0
- combstruct/data/ecs04/ecs_0401.json +38 -0
- combstruct/data/ecs04/ecs_0402.json +38 -0
- combstruct/data/ecs04/ecs_0403.json +38 -0
- combstruct/data/ecs04/ecs_0404.json +34 -0
- combstruct/data/ecs04/ecs_0405.json +38 -0
- combstruct/data/ecs04/ecs_0406.json +38 -0
- combstruct/data/ecs04/ecs_0407.json +38 -0
- combstruct/data/ecs04/ecs_0408.json +38 -0
- combstruct/data/ecs04/ecs_0409.json +38 -0
- combstruct/data/ecs04/ecs_0410.json +38 -0
- combstruct/data/ecs04/ecs_0411.json +38 -0
- combstruct/data/ecs04/ecs_0412.json +38 -0
- combstruct/data/ecs04/ecs_0413.json +39 -0
- combstruct/data/ecs04/ecs_0414.json +38 -0
- combstruct/data/ecs04/ecs_0415.json +37 -0
- combstruct/data/ecs04/ecs_0416.json +37 -0
- combstruct/data/ecs04/ecs_0417.json +38 -0
- combstruct/data/ecs04/ecs_0418.json +38 -0
- combstruct/data/ecs04/ecs_0419.json +38 -0
- combstruct/data/ecs04/ecs_0420.json +38 -0
- combstruct/data/ecs04/ecs_0421.json +37 -0
- combstruct/data/ecs04/ecs_0422.json +38 -0
- combstruct/data/ecs04/ecs_0423.json +37 -0
- combstruct/data/ecs04/ecs_0424.json +38 -0
- combstruct/data/ecs04/ecs_0425.json +38 -0
- combstruct/data/ecs04/ecs_0426.json +38 -0
- combstruct/data/ecs04/ecs_0427.json +38 -0
- combstruct/data/ecs04/ecs_0428.json +34 -0
- combstruct/data/ecs04/ecs_0429.json +34 -0
- combstruct/data/ecs04/ecs_0430.json +34 -0
- combstruct/data/ecs04/ecs_0431.json +38 -0
- combstruct/data/ecs04/ecs_0432.json +38 -0
- combstruct/data/ecs04/ecs_0433.json +38 -0
- combstruct/data/ecs04/ecs_0434.json +38 -0
- combstruct/data/ecs04/ecs_0435.json +38 -0
- combstruct/data/ecs04/ecs_0436.json +38 -0
- combstruct/data/ecs04/ecs_0437.json +38 -0
- combstruct/data/ecs04/ecs_0438.json +38 -0
- combstruct/data/ecs04/ecs_0439.json +34 -0
- combstruct/data/ecs04/ecs_0440.json +38 -0
- combstruct/data/ecs04/ecs_0441.json +37 -0
- combstruct/data/ecs04/ecs_0442.json +38 -0
- combstruct/data/ecs04/ecs_0443.json +37 -0
- combstruct/data/ecs04/ecs_0444.json +38 -0
- combstruct/data/ecs04/ecs_0445.json +38 -0
- combstruct/data/ecs04/ecs_0446.json +35 -0
- combstruct/data/ecs04/ecs_0447.json +38 -0
- combstruct/data/ecs04/ecs_0448.json +36 -0
- combstruct/data/ecs04/ecs_0449.json +38 -0
- combstruct/data/ecs04/ecs_0450.json +36 -0
- combstruct/data/ecs04/ecs_0451.json +38 -0
- combstruct/data/ecs04/ecs_0452.json +38 -0
- combstruct/data/ecs04/ecs_0453.json +38 -0
- combstruct/data/ecs04/ecs_0454.json +38 -0
- combstruct/data/ecs04/ecs_0455.json +38 -0
- combstruct/data/ecs04/ecs_0456.json +38 -0
- combstruct/data/ecs04/ecs_0457.json +38 -0
- combstruct/data/ecs04/ecs_0458.json +38 -0
- combstruct/data/ecs04/ecs_0459.json +38 -0
- combstruct/data/ecs04/ecs_0460.json +38 -0
- combstruct/data/ecs04/ecs_0461.json +38 -0
- combstruct/data/ecs04/ecs_0462.json +38 -0
- combstruct/data/ecs04/ecs_0463.json +38 -0
- combstruct/data/ecs04/ecs_0464.json +38 -0
- combstruct/data/ecs04/ecs_0465.json +38 -0
- combstruct/data/ecs04/ecs_0466.json +38 -0
- combstruct/data/ecs04/ecs_0467.json +38 -0
- combstruct/data/ecs04/ecs_0468.json +38 -0
- combstruct/data/ecs04/ecs_0469.json +38 -0
- combstruct/data/ecs04/ecs_0470.json +38 -0
- combstruct/data/ecs04/ecs_0471.json +38 -0
- combstruct/data/ecs04/ecs_0472.json +38 -0
- combstruct/data/ecs04/ecs_0473.json +38 -0
- combstruct/data/ecs04/ecs_0474.json +38 -0
- combstruct/data/ecs04/ecs_0475.json +38 -0
- combstruct/data/ecs04/ecs_0476.json +38 -0
- combstruct/data/ecs04/ecs_0477.json +38 -0
- combstruct/data/ecs04/ecs_0478.json +38 -0
- combstruct/data/ecs04/ecs_0479.json +38 -0
- combstruct/data/ecs04/ecs_0480.json +38 -0
- combstruct/data/ecs04/ecs_0481.json +38 -0
- combstruct/data/ecs04/ecs_0482.json +38 -0
- combstruct/data/ecs04/ecs_0483.json +38 -0
- combstruct/data/ecs04/ecs_0484.json +38 -0
- combstruct/data/ecs04/ecs_0485.json +38 -0
- combstruct/data/ecs04/ecs_0486.json +38 -0
- combstruct/data/ecs04/ecs_0487.json +38 -0
- combstruct/data/ecs04/ecs_0488.json +38 -0
- combstruct/data/ecs04/ecs_0489.json +38 -0
- combstruct/data/ecs04/ecs_0490.json +38 -0
- combstruct/data/ecs04/ecs_0491.json +38 -0
- combstruct/data/ecs04/ecs_0492.json +38 -0
- combstruct/data/ecs04/ecs_0493.json +38 -0
- combstruct/data/ecs04/ecs_0494.json +38 -0
- combstruct/data/ecs04/ecs_0495.json +38 -0
- combstruct/data/ecs04/ecs_0496.json +38 -0
- combstruct/data/ecs04/ecs_0497.json +38 -0
- combstruct/data/ecs04/ecs_0498.json +38 -0
- combstruct/data/ecs04/ecs_0499.json +38 -0
- combstruct/data/ecs05/ecs_0500.json +38 -0
- combstruct/data/ecs05/ecs_0501.json +38 -0
- combstruct/data/ecs05/ecs_0502.json +38 -0
- combstruct/data/ecs05/ecs_0503.json +38 -0
- combstruct/data/ecs05/ecs_0504.json +38 -0
- combstruct/data/ecs05/ecs_0505.json +38 -0
- combstruct/data/ecs05/ecs_0506.json +38 -0
- combstruct/data/ecs05/ecs_0507.json +38 -0
- combstruct/data/ecs05/ecs_0508.json +38 -0
- combstruct/data/ecs05/ecs_0509.json +38 -0
- combstruct/data/ecs05/ecs_0510.json +38 -0
- combstruct/data/ecs05/ecs_0511.json +38 -0
- combstruct/data/ecs05/ecs_0512.json +38 -0
- combstruct/data/ecs05/ecs_0513.json +38 -0
- combstruct/data/ecs05/ecs_0514.json +38 -0
- combstruct/data/ecs05/ecs_0515.json +38 -0
- combstruct/data/ecs05/ecs_0516.json +38 -0
- combstruct/data/ecs05/ecs_0517.json +38 -0
- combstruct/data/ecs05/ecs_0518.json +38 -0
- combstruct/data/ecs05/ecs_0519.json +38 -0
- combstruct/data/ecs05/ecs_0520.json +38 -0
- combstruct/data/ecs05/ecs_0521.json +38 -0
- combstruct/data/ecs05/ecs_0522.json +38 -0
- combstruct/data/ecs05/ecs_0523.json +38 -0
- combstruct/data/ecs05/ecs_0524.json +38 -0
- combstruct/data/ecs05/ecs_0525.json +38 -0
- combstruct/data/ecs05/ecs_0526.json +38 -0
- combstruct/data/ecs05/ecs_0527.json +38 -0
- combstruct/data/ecs05/ecs_0528.json +38 -0
- combstruct/data/ecs05/ecs_0529.json +38 -0
- combstruct/data/ecs05/ecs_0530.json +38 -0
- combstruct/data/ecs05/ecs_0531.json +38 -0
- combstruct/data/ecs05/ecs_0532.json +38 -0
- combstruct/data/ecs05/ecs_0533.json +38 -0
- combstruct/data/ecs05/ecs_0534.json +38 -0
- combstruct/data/ecs05/ecs_0535.json +38 -0
- combstruct/data/ecs05/ecs_0536.json +38 -0
- combstruct/data/ecs05/ecs_0537.json +38 -0
- combstruct/data/ecs05/ecs_0538.json +38 -0
- combstruct/data/ecs05/ecs_0539.json +38 -0
- combstruct/data/ecs05/ecs_0540.json +38 -0
- combstruct/data/ecs05/ecs_0541.json +38 -0
- combstruct/data/ecs05/ecs_0542.json +38 -0
- combstruct/data/ecs05/ecs_0543.json +38 -0
- combstruct/data/ecs05/ecs_0544.json +38 -0
- combstruct/data/ecs05/ecs_0545.json +38 -0
- combstruct/data/ecs05/ecs_0546.json +38 -0
- combstruct/data/ecs05/ecs_0547.json +38 -0
- combstruct/data/ecs05/ecs_0548.json +38 -0
- combstruct/data/ecs05/ecs_0549.json +38 -0
- combstruct/data/ecs05/ecs_0550.json +38 -0
- combstruct/data/ecs05/ecs_0551.json +38 -0
- combstruct/data/ecs05/ecs_0552.json +38 -0
- combstruct/data/ecs05/ecs_0553.json +38 -0
- combstruct/data/ecs05/ecs_0554.json +38 -0
- combstruct/data/ecs05/ecs_0555.json +38 -0
- combstruct/data/ecs05/ecs_0556.json +38 -0
- combstruct/data/ecs05/ecs_0557.json +38 -0
- combstruct/data/ecs05/ecs_0558.json +38 -0
- combstruct/data/ecs05/ecs_0559.json +38 -0
- combstruct/data/ecs05/ecs_0560.json +38 -0
- combstruct/data/ecs05/ecs_0561.json +38 -0
- combstruct/data/ecs05/ecs_0562.json +38 -0
- combstruct/data/ecs05/ecs_0563.json +38 -0
- combstruct/data/ecs05/ecs_0564.json +38 -0
- combstruct/data/ecs05/ecs_0565.json +38 -0
- combstruct/data/ecs05/ecs_0566.json +38 -0
- combstruct/data/ecs05/ecs_0567.json +38 -0
- combstruct/data/ecs05/ecs_0568.json +38 -0
- combstruct/data/ecs05/ecs_0569.json +38 -0
- combstruct/data/ecs05/ecs_0570.json +38 -0
- combstruct/data/ecs05/ecs_0571.json +38 -0
- combstruct/data/ecs05/ecs_0572.json +38 -0
- combstruct/data/ecs05/ecs_0573.json +38 -0
- combstruct/data/ecs05/ecs_0574.json +38 -0
- combstruct/data/ecs05/ecs_0575.json +38 -0
- combstruct/data/ecs05/ecs_0576.json +38 -0
- combstruct/data/ecs05/ecs_0577.json +38 -0
- combstruct/data/ecs05/ecs_0578.json +38 -0
- combstruct/data/ecs05/ecs_0579.json +38 -0
- combstruct/data/ecs05/ecs_0580.json +38 -0
- combstruct/data/ecs05/ecs_0581.json +38 -0
- combstruct/data/ecs05/ecs_0582.json +38 -0
- combstruct/data/ecs05/ecs_0583.json +38 -0
- combstruct/data/ecs05/ecs_0584.json +38 -0
- combstruct/data/ecs05/ecs_0585.json +38 -0
- combstruct/data/ecs05/ecs_0586.json +38 -0
- combstruct/data/ecs05/ecs_0587.json +38 -0
- combstruct/data/ecs05/ecs_0588.json +38 -0
- combstruct/data/ecs05/ecs_0589.json +38 -0
- combstruct/data/ecs05/ecs_0590.json +38 -0
- combstruct/data/ecs05/ecs_0591.json +38 -0
- combstruct/data/ecs05/ecs_0592.json +38 -0
- combstruct/data/ecs05/ecs_0593.json +38 -0
- combstruct/data/ecs05/ecs_0594.json +38 -0
- combstruct/data/ecs05/ecs_0595.json +38 -0
- combstruct/data/ecs05/ecs_0596.json +38 -0
- combstruct/data/ecs05/ecs_0597.json +38 -0
- combstruct/data/ecs05/ecs_0598.json +38 -0
- combstruct/data/ecs05/ecs_0599.json +38 -0
- combstruct/data/ecs06/ecs_0600.json +38 -0
- combstruct/data/ecs06/ecs_0601.json +38 -0
- combstruct/data/ecs06/ecs_0602.json +38 -0
- combstruct/data/ecs06/ecs_0603.json +38 -0
- combstruct/data/ecs06/ecs_0604.json +38 -0
- combstruct/data/ecs06/ecs_0605.json +38 -0
- combstruct/data/ecs06/ecs_0606.json +38 -0
- combstruct/data/ecs06/ecs_0607.json +38 -0
- combstruct/data/ecs06/ecs_0608.json +38 -0
- combstruct/data/ecs06/ecs_0609.json +38 -0
- combstruct/data/ecs06/ecs_0610.json +38 -0
- combstruct/data/ecs06/ecs_0611.json +38 -0
- combstruct/data/ecs06/ecs_0612.json +38 -0
- combstruct/data/ecs06/ecs_0613.json +38 -0
- combstruct/data/ecs06/ecs_0614.json +38 -0
- combstruct/data/ecs06/ecs_0615.json +38 -0
- combstruct/data/ecs06/ecs_0616.json +38 -0
- combstruct/data/ecs06/ecs_0617.json +38 -0
- combstruct/data/ecs06/ecs_0618.json +38 -0
- combstruct/data/ecs06/ecs_0619.json +38 -0
- combstruct/data/ecs06/ecs_0620.json +38 -0
- combstruct/data/ecs06/ecs_0621.json +38 -0
- combstruct/data/ecs06/ecs_0622.json +38 -0
- combstruct/data/ecs06/ecs_0623.json +38 -0
- combstruct/data/ecs06/ecs_0624.json +38 -0
- combstruct/data/ecs06/ecs_0625.json +38 -0
- combstruct/data/ecs06/ecs_0626.json +38 -0
- combstruct/data/ecs06/ecs_0627.json +38 -0
- combstruct/data/ecs06/ecs_0628.json +38 -0
- combstruct/data/ecs06/ecs_0629.json +38 -0
- combstruct/data/ecs06/ecs_0630.json +38 -0
- combstruct/data/ecs06/ecs_0631.json +38 -0
- combstruct/data/ecs06/ecs_0632.json +38 -0
- combstruct/data/ecs06/ecs_0633.json +38 -0
- combstruct/data/ecs06/ecs_0634.json +38 -0
- combstruct/data/ecs06/ecs_0635.json +38 -0
- combstruct/data/ecs06/ecs_0636.json +38 -0
- combstruct/data/ecs06/ecs_0637.json +38 -0
- combstruct/data/ecs06/ecs_0638.json +38 -0
- combstruct/data/ecs06/ecs_0639.json +38 -0
- combstruct/data/ecs06/ecs_0640.json +38 -0
- combstruct/data/ecs06/ecs_0641.json +38 -0
- combstruct/data/ecs06/ecs_0642.json +38 -0
- combstruct/data/ecs06/ecs_0643.json +38 -0
- combstruct/data/ecs06/ecs_0644.json +38 -0
- combstruct/data/ecs06/ecs_0645.json +38 -0
- combstruct/data/ecs06/ecs_0646.json +38 -0
- combstruct/data/ecs06/ecs_0647.json +38 -0
- combstruct/data/ecs06/ecs_0648.json +38 -0
- combstruct/data/ecs06/ecs_0649.json +38 -0
- combstruct/data/ecs06/ecs_0650.json +38 -0
- combstruct/data/ecs06/ecs_0651.json +38 -0
- combstruct/data/ecs06/ecs_0652.json +38 -0
- combstruct/data/ecs06/ecs_0653.json +38 -0
- combstruct/data/ecs06/ecs_0654.json +37 -0
- combstruct/data/ecs06/ecs_0655.json +37 -0
- combstruct/data/ecs06/ecs_0656.json +37 -0
- combstruct/data/ecs06/ecs_0657.json +37 -0
- combstruct/data/ecs06/ecs_0658.json +38 -0
- combstruct/data/ecs06/ecs_0659.json +37 -0
- combstruct/data/ecs06/ecs_0660.json +37 -0
- combstruct/data/ecs06/ecs_0661.json +37 -0
- combstruct/data/ecs06/ecs_0662.json +38 -0
- combstruct/data/ecs06/ecs_0663.json +37 -0
- combstruct/data/ecs06/ecs_0664.json +37 -0
- combstruct/data/ecs06/ecs_0665.json +37 -0
- combstruct/data/ecs06/ecs_0666.json +37 -0
- combstruct/data/ecs06/ecs_0667.json +38 -0
- combstruct/data/ecs06/ecs_0668.json +38 -0
- combstruct/data/ecs06/ecs_0669.json +38 -0
- combstruct/data/ecs06/ecs_0670.json +38 -0
- combstruct/data/ecs06/ecs_0671.json +38 -0
- combstruct/data/ecs06/ecs_0672.json +37 -0
- combstruct/data/ecs06/ecs_0673.json +38 -0
- combstruct/data/ecs06/ecs_0674.json +38 -0
- combstruct/data/ecs06/ecs_0675.json +38 -0
- combstruct/data/ecs06/ecs_0676.json +38 -0
- combstruct/data/ecs06/ecs_0677.json +38 -0
- combstruct/data/ecs06/ecs_0678.json +38 -0
- combstruct/data/ecs06/ecs_0679.json +37 -0
- combstruct/data/ecs06/ecs_0680.json +37 -0
- combstruct/data/ecs06/ecs_0681.json +37 -0
- combstruct/data/ecs06/ecs_0682.json +37 -0
- combstruct/data/ecs06/ecs_0683.json +37 -0
- combstruct/data/ecs06/ecs_0684.json +37 -0
- combstruct/data/ecs06/ecs_0685.json +37 -0
- combstruct/data/ecs06/ecs_0686.json +37 -0
- combstruct/data/ecs06/ecs_0687.json +37 -0
- combstruct/data/ecs06/ecs_0688.json +38 -0
- combstruct/data/ecs06/ecs_0689.json +38 -0
- combstruct/data/ecs06/ecs_0690.json +38 -0
- combstruct/data/ecs06/ecs_0691.json +37 -0
- combstruct/data/ecs06/ecs_0692.json +37 -0
- combstruct/data/ecs06/ecs_0693.json +38 -0
- combstruct/data/ecs06/ecs_0694.json +37 -0
- combstruct/data/ecs06/ecs_0695.json +37 -0
- combstruct/data/ecs06/ecs_0696.json +37 -0
- combstruct/data/ecs06/ecs_0697.json +38 -0
- combstruct/data/ecs06/ecs_0698.json +37 -0
- combstruct/data/ecs06/ecs_0699.json +37 -0
- combstruct/data/ecs07/ecs_0700.json +37 -0
- combstruct/data/ecs07/ecs_0701.json +38 -0
- combstruct/data/ecs07/ecs_0702.json +36 -0
- combstruct/data/ecs07/ecs_0703.json +38 -0
- combstruct/data/ecs07/ecs_0704.json +38 -0
- combstruct/data/ecs07/ecs_0705.json +38 -0
- combstruct/data/ecs07/ecs_0706.json +36 -0
- combstruct/data/ecs07/ecs_0707.json +34 -0
- combstruct/data/ecs07/ecs_0708.json +36 -0
- combstruct/data/ecs07/ecs_0709.json +37 -0
- combstruct/data/ecs07/ecs_0710.json +38 -0
- combstruct/data/ecs07/ecs_0711.json +34 -0
- combstruct/data/ecs07/ecs_0712.json +36 -0
- combstruct/data/ecs07/ecs_0713.json +34 -0
- combstruct/data/ecs07/ecs_0714.json +38 -0
- combstruct/data/ecs07/ecs_0715.json +38 -0
- combstruct/data/ecs07/ecs_0716.json +38 -0
- combstruct/data/ecs07/ecs_0717.json +38 -0
- combstruct/data/ecs07/ecs_0718.json +38 -0
- combstruct/data/ecs07/ecs_0719.json +38 -0
- combstruct/data/ecs07/ecs_0720.json +34 -0
- combstruct/data/ecs07/ecs_0721.json +36 -0
- combstruct/data/ecs07/ecs_0722.json +38 -0
- combstruct/data/ecs07/ecs_0723.json +38 -0
- combstruct/data/ecs07/ecs_0724.json +37 -0
- combstruct/data/ecs07/ecs_0725.json +38 -0
- combstruct/data/ecs07/ecs_0726.json +38 -0
- combstruct/data/ecs07/ecs_0727.json +37 -0
- combstruct/data/ecs07/ecs_0728.json +38 -0
- combstruct/data/ecs07/ecs_0729.json +34 -0
- combstruct/data/ecs07/ecs_0730.json +34 -0
- combstruct/data/ecs07/ecs_0731.json +36 -0
- combstruct/data/ecs07/ecs_0732.json +34 -0
- combstruct/data/ecs07/ecs_0733.json +38 -0
- combstruct/data/ecs07/ecs_0734.json +38 -0
- combstruct/data/ecs07/ecs_0735.json +38 -0
- combstruct/data/ecs07/ecs_0736.json +37 -0
- combstruct/data/ecs07/ecs_0737.json +38 -0
- combstruct/data/ecs07/ecs_0738.json +34 -0
- combstruct/data/ecs07/ecs_0739.json +36 -0
- combstruct/data/ecs07/ecs_0740.json +37 -0
- combstruct/data/ecs07/ecs_0741.json +38 -0
- combstruct/data/ecs07/ecs_0742.json +38 -0
- combstruct/data/ecs07/ecs_0743.json +38 -0
- combstruct/data/ecs07/ecs_0744.json +38 -0
- combstruct/data/ecs07/ecs_0745.json +34 -0
- combstruct/data/ecs07/ecs_0746.json +36 -0
- combstruct/data/ecs07/ecs_0747.json +37 -0
- combstruct/data/ecs07/ecs_0748.json +38 -0
- combstruct/data/ecs07/ecs_0749.json +38 -0
- combstruct/data/ecs07/ecs_0750.json +38 -0
- combstruct/data/ecs07/ecs_0751.json +38 -0
- combstruct/data/ecs07/ecs_0752.json +38 -0
- combstruct/data/ecs07/ecs_0753.json +38 -0
- combstruct/data/ecs07/ecs_0754.json +34 -0
- combstruct/data/ecs07/ecs_0755.json +34 -0
- combstruct/data/ecs07/ecs_0756.json +38 -0
- combstruct/data/ecs07/ecs_0757.json +38 -0
- combstruct/data/ecs07/ecs_0758.json +38 -0
- combstruct/data/ecs07/ecs_0759.json +36 -0
- combstruct/data/ecs07/ecs_0760.json +34 -0
- combstruct/data/ecs07/ecs_0761.json +35 -0
- combstruct/data/ecs07/ecs_0762.json +36 -0
- combstruct/data/ecs07/ecs_0763.json +38 -0
- combstruct/data/ecs07/ecs_0764.json +35 -0
- combstruct/data/ecs07/ecs_0765.json +35 -0
- combstruct/data/ecs07/ecs_0766.json +35 -0
- combstruct/data/ecs07/ecs_0767.json +34 -0
- combstruct/data/ecs07/ecs_0768.json +34 -0
- combstruct/data/ecs07/ecs_0769.json +36 -0
- combstruct/data/ecs07/ecs_0770.json +36 -0
- combstruct/data/ecs07/ecs_0771.json +36 -0
- combstruct/data/ecs07/ecs_0772.json +35 -0
- combstruct/data/ecs07/ecs_0773.json +34 -0
- combstruct/data/ecs07/ecs_0774.json +35 -0
- combstruct/data/ecs07/ecs_0775.json +36 -0
- combstruct/data/ecs07/ecs_0776.json +35 -0
- combstruct/data/ecs07/ecs_0777.json +38 -0
- combstruct/data/ecs07/ecs_0778.json +36 -0
- combstruct/data/ecs07/ecs_0779.json +34 -0
- combstruct/data/ecs07/ecs_0780.json +34 -0
- combstruct/data/ecs07/ecs_0781.json +35 -0
- combstruct/data/ecs07/ecs_0782.json +34 -0
- combstruct/data/ecs07/ecs_0783.json +34 -0
- combstruct/data/ecs07/ecs_0784.json +34 -0
- combstruct/data/ecs07/ecs_0785.json +36 -0
- combstruct/data/ecs07/ecs_0786.json +35 -0
- combstruct/data/ecs07/ecs_0787.json +36 -0
- combstruct/data/ecs07/ecs_0788.json +35 -0
- combstruct/data/ecs07/ecs_0789.json +36 -0
- combstruct/data/ecs07/ecs_0790.json +35 -0
- combstruct/data/ecs07/ecs_0791.json +36 -0
- combstruct/data/ecs07/ecs_0792.json +34 -0
- combstruct/data/ecs07/ecs_0793.json +36 -0
- combstruct/data/ecs07/ecs_0794.json +34 -0
- combstruct/data/ecs07/ecs_0795.json +36 -0
- combstruct/data/ecs07/ecs_0796.json +34 -0
- combstruct/data/ecs07/ecs_0797.json +38 -0
- combstruct/data/ecs07/ecs_0798.json +35 -0
- combstruct/data/ecs07/ecs_0799.json +36 -0
- combstruct/data/ecs08/ecs_0800.json +35 -0
- combstruct/data/ecs08/ecs_0801.json +35 -0
- combstruct/data/ecs08/ecs_0802.json +36 -0
- combstruct/data/ecs08/ecs_0803.json +34 -0
- combstruct/data/ecs08/ecs_0804.json +35 -0
- combstruct/data/ecs08/ecs_0805.json +36 -0
- combstruct/data/ecs08/ecs_0806.json +35 -0
- combstruct/data/ecs08/ecs_0807.json +38 -0
- combstruct/data/ecs08/ecs_0808.json +36 -0
- combstruct/data/ecs08/ecs_0809.json +34 -0
- combstruct/data/ecs08/ecs_0810.json +36 -0
- combstruct/data/ecs08/ecs_0811.json +34 -0
- combstruct/data/ecs08/ecs_0812.json +37 -0
- combstruct/data/ecs08/ecs_0813.json +37 -0
- combstruct/data/ecs08/ecs_0814.json +36 -0
- combstruct/data/ecs08/ecs_0815.json +35 -0
- combstruct/data/ecs08/ecs_0816.json +36 -0
- combstruct/data/ecs08/ecs_0817.json +38 -0
- combstruct/data/ecs08/ecs_0818.json +38 -0
- combstruct/data/ecs08/ecs_0819.json +36 -0
- combstruct/data/ecs08/ecs_0820.json +37 -0
- combstruct/data/ecs08/ecs_0821.json +34 -0
- combstruct/data/ecs08/ecs_0822.json +35 -0
- combstruct/data/ecs08/ecs_0823.json +34 -0
- combstruct/data/ecs08/ecs_0824.json +36 -0
- combstruct/data/ecs08/ecs_0825.json +35 -0
- combstruct/data/ecs08/ecs_0826.json +36 -0
- combstruct/data/ecs08/ecs_0827.json +35 -0
- combstruct/data/ecs08/ecs_0828.json +36 -0
- combstruct/data/ecs08/ecs_0829.json +38 -0
- combstruct/data/ecs08/ecs_0830.json +36 -0
- combstruct/data/ecs08/ecs_0831.json +37 -0
- combstruct/data/ecs08/ecs_0832.json +36 -0
- combstruct/data/ecs08/ecs_0833.json +36 -0
- combstruct/data/ecs08/ecs_0834.json +38 -0
- combstruct/data/ecs08/ecs_0835.json +36 -0
- combstruct/data/ecs08/ecs_0836.json +38 -0
- combstruct/data/ecs08/ecs_0837.json +36 -0
- combstruct/data/ecs08/ecs_0838.json +38 -0
- combstruct/data/ecs08/ecs_0839.json +36 -0
- combstruct/data/ecs08/ecs_0840.json +34 -0
- combstruct/data/ecs08/ecs_0841.json +34 -0
- combstruct/data/ecs08/ecs_0842.json +36 -0
- combstruct/data/ecs08/ecs_0843.json +34 -0
- combstruct/data/ecs08/ecs_0844.json +35 -0
- combstruct/data/ecs08/ecs_0845.json +37 -0
- combstruct/data/ecs08/ecs_0846.json +36 -0
- combstruct/data/ecs08/ecs_0847.json +36 -0
- combstruct/data/ecs08/ecs_0848.json +36 -0
- combstruct/data/ecs08/ecs_0849.json +38 -0
- combstruct/data/ecs08/ecs_0850.json +34 -0
- combstruct/data/ecs08/ecs_0851.json +36 -0
- combstruct/data/ecs08/ecs_0852.json +35 -0
- combstruct/data/ecs08/ecs_0853.json +38 -0
- combstruct/data/ecs08/ecs_0854.json +36 -0
- combstruct/data/ecs08/ecs_0855.json +36 -0
- combstruct/data/ecs08/ecs_0856.json +37 -0
- combstruct/data/ecs08/ecs_0857.json +34 -0
- combstruct/data/ecs08/ecs_0858.json +35 -0
- combstruct/data/ecs08/ecs_0859.json +36 -0
- combstruct/data/ecs08/ecs_0860.json +37 -0
- combstruct/data/ecs08/ecs_0861.json +36 -0
- combstruct/data/ecs08/ecs_0862.json +34 -0
- combstruct/data/ecs08/ecs_0863.json +36 -0
- combstruct/data/ecs08/ecs_0864.json +36 -0
- combstruct/data/ecs08/ecs_0865.json +35 -0
- combstruct/data/ecs08/ecs_0866.json +34 -0
- combstruct/data/ecs08/ecs_0867.json +34 -0
- combstruct/data/ecs08/ecs_0868.json +36 -0
- combstruct/data/ecs08/ecs_0869.json +34 -0
- combstruct/data/ecs08/ecs_0870.json +36 -0
- combstruct/data/ecs08/ecs_0871.json +36 -0
- combstruct/data/ecs08/ecs_0872.json +35 -0
- combstruct/data/ecs08/ecs_0873.json +37 -0
- combstruct/data/ecs08/ecs_0874.json +38 -0
- combstruct/data/ecs08/ecs_0875.json +38 -0
- combstruct/data/ecs08/ecs_0876.json +38 -0
- combstruct/data/ecs08/ecs_0877.json +38 -0
- combstruct/data/ecs08/ecs_0878.json +38 -0
- combstruct/data/ecs08/ecs_0879.json +38 -0
- combstruct/data/ecs08/ecs_0880.json +38 -0
- combstruct/data/ecs08/ecs_0881.json +38 -0
- combstruct/data/ecs08/ecs_0882.json +38 -0
- combstruct/data/ecs08/ecs_0883.json +38 -0
- combstruct/data/ecs08/ecs_0884.json +38 -0
- combstruct/data/ecs08/ecs_0885.json +38 -0
- combstruct/data/ecs08/ecs_0886.json +38 -0
- combstruct/data/ecs08/ecs_0887.json +38 -0
- combstruct/data/ecs08/ecs_0888.json +38 -0
- combstruct/data/ecs08/ecs_0889.json +38 -0
- combstruct/data/ecs08/ecs_0890.json +38 -0
- combstruct/data/ecs08/ecs_0891.json +38 -0
- combstruct/data/ecs08/ecs_0892.json +38 -0
- combstruct/data/ecs08/ecs_0893.json +38 -0
- combstruct/data/ecs08/ecs_0894.json +38 -0
- combstruct/data/ecs08/ecs_0895.json +38 -0
- combstruct/data/ecs08/ecs_0896.json +38 -0
- combstruct/data/ecs08/ecs_0897.json +38 -0
- combstruct/data/ecs08/ecs_0898.json +38 -0
- combstruct/data/ecs08/ecs_0899.json +38 -0
- combstruct/data/ecs09/ecs_0900.json +38 -0
- combstruct/data/ecs09/ecs_0901.json +38 -0
- combstruct/data/ecs09/ecs_0902.json +38 -0
- combstruct/data/ecs09/ecs_0903.json +38 -0
- combstruct/data/ecs09/ecs_0904.json +38 -0
- combstruct/data/ecs09/ecs_0905.json +38 -0
- combstruct/data/ecs09/ecs_0906.json +38 -0
- combstruct/data/ecs09/ecs_0907.json +38 -0
- combstruct/data/ecs09/ecs_0908.json +38 -0
- combstruct/data/ecs09/ecs_0909.json +38 -0
- combstruct/data/ecs09/ecs_0910.json +38 -0
- combstruct/data/ecs09/ecs_0911.json +38 -0
- combstruct/data/ecs09/ecs_0912.json +38 -0
- combstruct/data/ecs09/ecs_0913.json +38 -0
- combstruct/data/ecs09/ecs_0914.json +38 -0
- combstruct/data/ecs09/ecs_0915.json +38 -0
- combstruct/data/ecs09/ecs_0916.json +38 -0
- combstruct/data/ecs09/ecs_0917.json +38 -0
- combstruct/data/ecs09/ecs_0918.json +38 -0
- combstruct/data/ecs09/ecs_0919.json +38 -0
- combstruct/data/ecs09/ecs_0920.json +38 -0
- combstruct/data/ecs09/ecs_0921.json +38 -0
- combstruct/data/ecs09/ecs_0922.json +38 -0
- combstruct/data/ecs09/ecs_0923.json +38 -0
- combstruct/data/ecs09/ecs_0924.json +38 -0
- combstruct/data/ecs09/ecs_0925.json +38 -0
- combstruct/data/ecs09/ecs_0926.json +38 -0
- combstruct/data/ecs09/ecs_0927.json +38 -0
- combstruct/data/ecs09/ecs_0928.json +38 -0
- combstruct/data/ecs09/ecs_0929.json +38 -0
- combstruct/data/ecs09/ecs_0930.json +38 -0
- combstruct/data/ecs09/ecs_0931.json +38 -0
- combstruct/data/ecs09/ecs_0932.json +38 -0
- combstruct/data/ecs09/ecs_0933.json +38 -0
- combstruct/data/ecs09/ecs_0934.json +38 -0
- combstruct/data/ecs09/ecs_0935.json +38 -0
- combstruct/data/ecs09/ecs_0936.json +38 -0
- combstruct/data/ecs09/ecs_0937.json +38 -0
- combstruct/data/ecs09/ecs_0938.json +38 -0
- combstruct/data/ecs09/ecs_0939.json +38 -0
- combstruct/data/ecs09/ecs_0940.json +38 -0
- combstruct/data/ecs09/ecs_0941.json +38 -0
- combstruct/data/ecs09/ecs_0942.json +38 -0
- combstruct/data/ecs09/ecs_0943.json +38 -0
- combstruct/data/ecs09/ecs_0944.json +38 -0
- combstruct/data/ecs09/ecs_0945.json +38 -0
- combstruct/data/ecs09/ecs_0946.json +38 -0
- combstruct/data/ecs09/ecs_0947.json +38 -0
- combstruct/data/ecs09/ecs_0948.json +38 -0
- combstruct/data/ecs09/ecs_0949.json +38 -0
- combstruct/data/ecs09/ecs_0950.json +38 -0
- combstruct/data/ecs09/ecs_0951.json +38 -0
- combstruct/data/ecs09/ecs_0952.json +38 -0
- combstruct/data/ecs09/ecs_0953.json +38 -0
- combstruct/data/ecs09/ecs_0954.json +38 -0
- combstruct/data/ecs09/ecs_0955.json +38 -0
- combstruct/data/ecs09/ecs_0956.json +38 -0
- combstruct/data/ecs09/ecs_0957.json +38 -0
- combstruct/data/ecs09/ecs_0958.json +38 -0
- combstruct/data/ecs09/ecs_0959.json +38 -0
- combstruct/data/ecs09/ecs_0960.json +38 -0
- combstruct/data/ecs09/ecs_0961.json +38 -0
- combstruct/data/ecs09/ecs_0962.json +38 -0
- combstruct/data/ecs09/ecs_0963.json +38 -0
- combstruct/data/ecs09/ecs_0964.json +38 -0
- combstruct/data/ecs09/ecs_0965.json +38 -0
- combstruct/data/ecs09/ecs_0966.json +38 -0
- combstruct/data/ecs09/ecs_0967.json +38 -0
- combstruct/data/ecs09/ecs_0968.json +38 -0
- combstruct/data/ecs09/ecs_0969.json +38 -0
- combstruct/data/ecs09/ecs_0970.json +38 -0
- combstruct/data/ecs09/ecs_0971.json +38 -0
- combstruct/data/ecs09/ecs_0972.json +38 -0
- combstruct/data/ecs09/ecs_0973.json +38 -0
- combstruct/data/ecs09/ecs_0974.json +38 -0
- combstruct/data/ecs09/ecs_0975.json +38 -0
- combstruct/data/ecs09/ecs_0976.json +38 -0
- combstruct/data/ecs09/ecs_0977.json +38 -0
- combstruct/data/ecs09/ecs_0978.json +38 -0
- combstruct/data/ecs09/ecs_0979.json +38 -0
- combstruct/data/ecs09/ecs_0980.json +38 -0
- combstruct/data/ecs09/ecs_0981.json +38 -0
- combstruct/data/ecs09/ecs_0982.json +38 -0
- combstruct/data/ecs09/ecs_0983.json +38 -0
- combstruct/data/ecs09/ecs_0984.json +38 -0
- combstruct/data/ecs09/ecs_0985.json +38 -0
- combstruct/data/ecs09/ecs_0986.json +38 -0
- combstruct/data/ecs09/ecs_0987.json +38 -0
- combstruct/data/ecs09/ecs_0988.json +38 -0
- combstruct/data/ecs09/ecs_0989.json +38 -0
- combstruct/data/ecs09/ecs_0990.json +38 -0
- combstruct/data/ecs09/ecs_0991.json +38 -0
- combstruct/data/ecs09/ecs_0992.json +38 -0
- combstruct/data/ecs09/ecs_0993.json +38 -0
- combstruct/data/ecs09/ecs_0994.json +38 -0
- combstruct/data/ecs09/ecs_0995.json +38 -0
- combstruct/data/ecs09/ecs_0996.json +38 -0
- combstruct/data/ecs09/ecs_0997.json +38 -0
- combstruct/data/ecs09/ecs_0998.json +38 -0
- combstruct/data/ecs09/ecs_0999.json +38 -0
- combstruct/data/ecs10/ecs_1000.json +38 -0
- combstruct/data/ecs10/ecs_1001.json +38 -0
- combstruct/data/ecs10/ecs_1002.json +38 -0
- combstruct/data/ecs10/ecs_1003.json +38 -0
- combstruct/data/ecs10/ecs_1004.json +38 -0
- combstruct/data/ecs10/ecs_1005.json +38 -0
- combstruct/data/ecs10/ecs_1006.json +38 -0
- combstruct/data/ecs10/ecs_1007.json +38 -0
- combstruct/data/ecs10/ecs_1008.json +38 -0
- combstruct/data/ecs10/ecs_1009.json +38 -0
- combstruct/data/ecs10/ecs_1010.json +38 -0
- combstruct/data/ecs10/ecs_1011.json +38 -0
- combstruct/data/ecs10/ecs_1012.json +38 -0
- combstruct/data/ecs10/ecs_1013.json +38 -0
- combstruct/data/ecs10/ecs_1014.json +38 -0
- combstruct/data/ecs10/ecs_1015.json +38 -0
- combstruct/data/ecs10/ecs_1016.json +38 -0
- combstruct/data/ecs10/ecs_1017.json +38 -0
- combstruct/data/ecs10/ecs_1018.json +38 -0
- combstruct/data/ecs10/ecs_1019.json +38 -0
- combstruct/data/ecs10/ecs_1020.json +38 -0
- combstruct/data/ecs10/ecs_1021.json +38 -0
- combstruct/data/ecs10/ecs_1022.json +38 -0
- combstruct/data/ecs10/ecs_1023.json +38 -0
- combstruct/data/ecs10/ecs_1024.json +38 -0
- combstruct/data/ecs10/ecs_1025.json +38 -0
- combstruct/data/ecs10/ecs_1026.json +38 -0
- combstruct/data/ecs10/ecs_1027.json +38 -0
- combstruct/data/ecs10/ecs_1028.json +38 -0
- combstruct/data/ecs10/ecs_1029.json +38 -0
- combstruct/data/ecs10/ecs_1030.json +38 -0
- combstruct/data/ecs10/ecs_1031.json +38 -0
- combstruct/data/ecs10/ecs_1032.json +38 -0
- combstruct/data/ecs10/ecs_1033.json +38 -0
- combstruct/data/ecs10/ecs_1034.json +38 -0
- combstruct/data/ecs10/ecs_1035.json +38 -0
- combstruct/data/ecs10/ecs_1036.json +38 -0
- combstruct/data/ecs10/ecs_1037.json +38 -0
- combstruct/data/ecs10/ecs_1038.json +38 -0
- combstruct/data/ecs10/ecs_1039.json +38 -0
- combstruct/data/ecs10/ecs_1040.json +38 -0
- combstruct/data/ecs10/ecs_1041.json +38 -0
- combstruct/data/ecs10/ecs_1042.json +38 -0
- combstruct/data/ecs10/ecs_1043.json +38 -0
- combstruct/data/ecs10/ecs_1044.json +38 -0
- combstruct/data/ecs10/ecs_1045.json +38 -0
- combstruct/data/ecs10/ecs_1046.json +38 -0
- combstruct/data/ecs10/ecs_1047.json +38 -0
- combstruct/data/ecs10/ecs_1048.json +38 -0
- combstruct/data/ecs10/ecs_1049.json +38 -0
- combstruct/data/ecs10/ecs_1050.json +38 -0
- combstruct/data/ecs10/ecs_1051.json +38 -0
- combstruct/data/ecs10/ecs_1052.json +38 -0
- combstruct/data/ecs10/ecs_1053.json +38 -0
- combstruct/data/ecs10/ecs_1054.json +38 -0
- combstruct/data/ecs10/ecs_1055.json +38 -0
- combstruct/data/ecs10/ecs_1056.json +38 -0
- combstruct/data/ecs10/ecs_1057.json +38 -0
- combstruct/data/ecs10/ecs_1058.json +38 -0
- combstruct/data/ecs10/ecs_1059.json +38 -0
- combstruct/data/ecs10/ecs_1060.json +38 -0
- combstruct/data/ecs10/ecs_1061.json +38 -0
- combstruct/data/ecs10/ecs_1062.json +38 -0
- combstruct/data/ecs10/ecs_1063.json +38 -0
- combstruct/data/ecs10/ecs_1064.json +38 -0
- combstruct/data/ecs10/ecs_1065.json +38 -0
- combstruct/data/ecs10/ecs_1066.json +38 -0
- combstruct/data/ecs10/ecs_1067.json +38 -0
- combstruct/data/ecs10/ecs_1068.json +38 -0
- combstruct/data/ecs10/ecs_1069.json +38 -0
- combstruct/data/ecs10/ecs_1070.json +38 -0
- combstruct/data/ecs10/ecs_1071.json +38 -0
- combstruct/data/ecs10/ecs_1072.json +38 -0
- combstruct/data/ecs10/ecs_1073.json +38 -0
- combstruct/data/ecs10/ecs_1074.json +38 -0
- combstruct/data/ecs10/ecs_1075.json +38 -0
- combstruct/py.typed +1 -0
- combstruct/specification.py +180 -0
- combstruct/terms.py +1034 -0
- combstruct-0.1.0a0.dist-info/METADATA +230 -0
- combstruct-0.1.0a0.dist-info/RECORD +1089 -0
- combstruct-0.1.0a0.dist-info/WHEEL +5 -0
- combstruct-0.1.0a0.dist-info/entry_points.txt +2 -0
- combstruct-0.1.0a0.dist-info/licenses/LICENSE.md +494 -0
- combstruct-0.1.0a0.dist-info/licenses/LICENSES/CC-BY-SA-4.0.txt +427 -0
- combstruct-0.1.0a0.dist-info/licenses/NOTICE.md +55 -0
- combstruct-0.1.0a0.dist-info/top_level.txt +1 -0
combstruct/terms.py
ADDED
|
@@ -0,0 +1,1034 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Parse ECS specifications and compute their sequence terms.
|
|
3
|
+
|
|
4
|
+
The evaluator uses truncated ordinary generating functions for unlabelled
|
|
5
|
+
structures and exponential generating functions for labelled structures.
|
|
6
|
+
All arithmetic is exact.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
import json
|
|
13
|
+
import math
|
|
14
|
+
from collections.abc import Iterable, Sequence
|
|
15
|
+
from fractions import Fraction
|
|
16
|
+
from functools import cache
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from typing import Any
|
|
19
|
+
|
|
20
|
+
from . import specification as _specification
|
|
21
|
+
from .catalog import (
|
|
22
|
+
StructureNotFoundError,
|
|
23
|
+
_load_record,
|
|
24
|
+
default_dataset,
|
|
25
|
+
)
|
|
26
|
+
from .specification import (
|
|
27
|
+
Cardinality,
|
|
28
|
+
Expression,
|
|
29
|
+
Reference,
|
|
30
|
+
SpecificationError,
|
|
31
|
+
parse_specification,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# Historical imports from ``compute_terms.py`` remain available while the
|
|
35
|
+
# repository's maintenance scripts transition to the package-level API.
|
|
36
|
+
Constructor = _specification.Constructor
|
|
37
|
+
Parser = _specification.Parser
|
|
38
|
+
TOKEN_RE = _specification.TOKEN_RE
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class UnsupportedConstruction(SpecificationError):
|
|
42
|
+
"""The specification is valid but cannot be expanded safely by this evaluator."""
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
ExactNumber = int | Fraction
|
|
46
|
+
Series = list[Fraction]
|
|
47
|
+
CoefficientSeries = list[ExactNumber]
|
|
48
|
+
|
|
49
|
+
__all__ = [
|
|
50
|
+
"TOKEN_RE",
|
|
51
|
+
"Cardinality",
|
|
52
|
+
"CoefficientCompiler",
|
|
53
|
+
"CoefficientNode",
|
|
54
|
+
"Constructor",
|
|
55
|
+
"EulerSelectionNode",
|
|
56
|
+
"Evaluator",
|
|
57
|
+
"ExpNode",
|
|
58
|
+
"Expression",
|
|
59
|
+
"InverseOneMinusNode",
|
|
60
|
+
"LiteralNode",
|
|
61
|
+
"LogOneMinusNode",
|
|
62
|
+
"Parser",
|
|
63
|
+
"ProductNode",
|
|
64
|
+
"Reference",
|
|
65
|
+
"ReferenceNode",
|
|
66
|
+
"ScaleNode",
|
|
67
|
+
"Series",
|
|
68
|
+
"SpecificationError",
|
|
69
|
+
"SubstituteNode",
|
|
70
|
+
"SumNode",
|
|
71
|
+
"UnlabelledCycleNode",
|
|
72
|
+
"UnsupportedConstruction",
|
|
73
|
+
"add_series",
|
|
74
|
+
"atom_series",
|
|
75
|
+
"binomial_row",
|
|
76
|
+
"build_argument_parser",
|
|
77
|
+
"compact_number",
|
|
78
|
+
"component_bounds",
|
|
79
|
+
"compute_terms",
|
|
80
|
+
"decimal_digit_count",
|
|
81
|
+
"default_dataset",
|
|
82
|
+
"divide_exact",
|
|
83
|
+
"divisors",
|
|
84
|
+
"euler_totient",
|
|
85
|
+
"integer_value",
|
|
86
|
+
"is_nonnegative_integer",
|
|
87
|
+
"labelled_cycle_series",
|
|
88
|
+
"labelled_set_series",
|
|
89
|
+
"load_record",
|
|
90
|
+
"main",
|
|
91
|
+
"multiply_series",
|
|
92
|
+
"one_series",
|
|
93
|
+
"power_series",
|
|
94
|
+
"product_series",
|
|
95
|
+
"require_nonnegative_integers",
|
|
96
|
+
"scale_series",
|
|
97
|
+
"sequence_series",
|
|
98
|
+
"substitute_power",
|
|
99
|
+
"unlabelled_cycle_series",
|
|
100
|
+
"unlabelled_selection_series",
|
|
101
|
+
"zero_series",
|
|
102
|
+
]
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def zero_series(degree: int) -> Series:
|
|
106
|
+
return [Fraction(0) for _ in range(degree + 1)]
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def one_series(degree: int) -> Series:
|
|
110
|
+
result = zero_series(degree)
|
|
111
|
+
result[0] = Fraction(1)
|
|
112
|
+
return result
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def atom_series(degree: int) -> Series:
|
|
116
|
+
result = zero_series(degree)
|
|
117
|
+
if degree >= 1:
|
|
118
|
+
result[1] = Fraction(1)
|
|
119
|
+
return result
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def add_series(*series: Series) -> Series:
|
|
123
|
+
if not series:
|
|
124
|
+
raise SpecificationError("Union requires at least one argument")
|
|
125
|
+
return [sum((value[index] for value in series), Fraction(0)) for index in range(len(series[0]))]
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def multiply_series(left: Series, right: Series) -> Series:
|
|
129
|
+
degree = len(left) - 1
|
|
130
|
+
result = zero_series(degree)
|
|
131
|
+
for left_degree, left_coefficient in enumerate(left):
|
|
132
|
+
if not left_coefficient:
|
|
133
|
+
continue
|
|
134
|
+
for right_degree in range(degree - left_degree + 1):
|
|
135
|
+
right_coefficient = right[right_degree]
|
|
136
|
+
if right_coefficient:
|
|
137
|
+
result[left_degree + right_degree] += left_coefficient * right_coefficient
|
|
138
|
+
return result
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def product_series(series: Sequence[Series], degree: int) -> Series:
|
|
142
|
+
result = one_series(degree)
|
|
143
|
+
for factor in series:
|
|
144
|
+
result = multiply_series(result, factor)
|
|
145
|
+
return result
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def power_series(series: Series, exponent: int) -> Series:
|
|
149
|
+
degree = len(series) - 1
|
|
150
|
+
result = one_series(degree)
|
|
151
|
+
factor = series
|
|
152
|
+
remaining = exponent
|
|
153
|
+
while remaining:
|
|
154
|
+
if remaining & 1:
|
|
155
|
+
result = multiply_series(result, factor)
|
|
156
|
+
remaining //= 2
|
|
157
|
+
if remaining:
|
|
158
|
+
factor = multiply_series(factor, factor)
|
|
159
|
+
return result
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def scale_series(series: Series, scalar: Fraction) -> Series:
|
|
163
|
+
return [scalar * coefficient for coefficient in series]
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def substitute_power(series: Series, exponent: int) -> Series:
|
|
167
|
+
degree = len(series) - 1
|
|
168
|
+
result = zero_series(degree)
|
|
169
|
+
for index in range(degree // exponent + 1):
|
|
170
|
+
result[index * exponent] = series[index]
|
|
171
|
+
return result
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def component_bounds(cardinality: Cardinality | None, degree: int) -> tuple[int, int]:
|
|
175
|
+
constraint = cardinality or Cardinality()
|
|
176
|
+
maximum = degree if constraint.maximum is None else constraint.maximum
|
|
177
|
+
return constraint.minimum, maximum
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def sequence_series(component: Series, cardinality: Cardinality | None) -> Series:
|
|
181
|
+
degree = len(component) - 1
|
|
182
|
+
minimum, maximum = component_bounds(cardinality, degree)
|
|
183
|
+
if component[0] and (cardinality is None or cardinality.maximum is None):
|
|
184
|
+
raise UnsupportedConstruction("An unrestricted Sequence cannot contain size-zero objects")
|
|
185
|
+
|
|
186
|
+
result = zero_series(degree)
|
|
187
|
+
current = one_series(degree)
|
|
188
|
+
for count in range(maximum + 1):
|
|
189
|
+
if count >= minimum:
|
|
190
|
+
result = add_series(result, current)
|
|
191
|
+
current = multiply_series(current, component)
|
|
192
|
+
return result
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def labelled_set_series(component: Series, cardinality: Cardinality | None) -> Series:
|
|
196
|
+
degree = len(component) - 1
|
|
197
|
+
minimum, maximum = component_bounds(cardinality, degree)
|
|
198
|
+
if component[0] and (cardinality is None or cardinality.maximum is None):
|
|
199
|
+
raise UnsupportedConstruction(
|
|
200
|
+
"An unrestricted labelled Set cannot contain size-zero objects"
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
result = zero_series(degree)
|
|
204
|
+
current = one_series(degree)
|
|
205
|
+
factorial = 1
|
|
206
|
+
for count in range(maximum + 1):
|
|
207
|
+
if count:
|
|
208
|
+
factorial *= count
|
|
209
|
+
if count >= minimum:
|
|
210
|
+
result = add_series(result, scale_series(current, Fraction(1, factorial)))
|
|
211
|
+
current = multiply_series(current, component)
|
|
212
|
+
return result
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def require_nonnegative_integers(component: Series, construction: str) -> list[int]:
|
|
216
|
+
coefficients: list[int] = []
|
|
217
|
+
for coefficient in component:
|
|
218
|
+
if coefficient.denominator != 1 or coefficient < 0:
|
|
219
|
+
raise UnsupportedConstruction(
|
|
220
|
+
f"Unlabelled {construction} requires nonnegative integer component coefficients",
|
|
221
|
+
)
|
|
222
|
+
coefficients.append(coefficient.numerator)
|
|
223
|
+
return coefficients
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def unlabelled_selection_series(
|
|
227
|
+
component: Series,
|
|
228
|
+
cardinality: Cardinality | None,
|
|
229
|
+
*,
|
|
230
|
+
distinct: bool,
|
|
231
|
+
) -> Series:
|
|
232
|
+
"""Evaluate an unlabelled multiset (Set) or distinct selection (PowerSet)."""
|
|
233
|
+
|
|
234
|
+
degree = len(component) - 1
|
|
235
|
+
coefficients = require_nonnegative_integers(component, "PowerSet" if distinct else "Set")
|
|
236
|
+
if coefficients[0]:
|
|
237
|
+
if not distinct:
|
|
238
|
+
raise UnsupportedConstruction("An unlabelled Set cannot contain size-zero objects")
|
|
239
|
+
if cardinality is not None:
|
|
240
|
+
raise UnsupportedConstruction("Cardinality constraints on PowerSet are not supported")
|
|
241
|
+
|
|
242
|
+
minimum, maximum = component_bounds(cardinality, degree)
|
|
243
|
+
table = [zero_series(degree) for _ in range(maximum + 1)]
|
|
244
|
+
table[0][0] = Fraction(2 ** coefficients[0] if distinct else 1)
|
|
245
|
+
|
|
246
|
+
for size, type_count in enumerate(coefficients[1:], 1):
|
|
247
|
+
if not type_count:
|
|
248
|
+
continue
|
|
249
|
+
updated = [zero_series(degree) for _ in range(maximum + 1)]
|
|
250
|
+
for old_count in range(maximum + 1):
|
|
251
|
+
for old_size, old_value in enumerate(table[old_count]):
|
|
252
|
+
if not old_value:
|
|
253
|
+
continue
|
|
254
|
+
limit = min(maximum - old_count, (degree - old_size) // size)
|
|
255
|
+
if distinct:
|
|
256
|
+
limit = min(limit, type_count)
|
|
257
|
+
for chosen in range(limit + 1):
|
|
258
|
+
ways = (
|
|
259
|
+
math.comb(type_count, chosen)
|
|
260
|
+
if distinct
|
|
261
|
+
else math.comb(type_count + chosen - 1, chosen)
|
|
262
|
+
)
|
|
263
|
+
updated[old_count + chosen][old_size + chosen * size] += old_value * ways
|
|
264
|
+
table = updated
|
|
265
|
+
|
|
266
|
+
result = zero_series(degree)
|
|
267
|
+
for count in range(minimum, maximum + 1):
|
|
268
|
+
result = add_series(result, table[count])
|
|
269
|
+
return result
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def euler_totient(value: int) -> int:
|
|
273
|
+
result = value
|
|
274
|
+
factor = 2
|
|
275
|
+
remaining = value
|
|
276
|
+
while factor * factor <= remaining:
|
|
277
|
+
if remaining % factor == 0:
|
|
278
|
+
while remaining % factor == 0:
|
|
279
|
+
remaining //= factor
|
|
280
|
+
result -= result // factor
|
|
281
|
+
factor += 1
|
|
282
|
+
if remaining > 1:
|
|
283
|
+
result -= result // remaining
|
|
284
|
+
return result
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def labelled_cycle_series(component: Series, cardinality: Cardinality | None) -> Series:
|
|
288
|
+
degree = len(component) - 1
|
|
289
|
+
minimum, maximum = component_bounds(cardinality or Cardinality(1), degree)
|
|
290
|
+
minimum = max(1, minimum)
|
|
291
|
+
if component[0] and (cardinality is None or cardinality.maximum is None):
|
|
292
|
+
raise UnsupportedConstruction(
|
|
293
|
+
"An unrestricted labelled Cycle cannot contain size-zero objects"
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
result = zero_series(degree)
|
|
297
|
+
current = one_series(degree)
|
|
298
|
+
for count in range(1, maximum + 1):
|
|
299
|
+
current = multiply_series(current, component)
|
|
300
|
+
if count >= minimum:
|
|
301
|
+
result = add_series(result, scale_series(current, Fraction(1, count)))
|
|
302
|
+
return result
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def unlabelled_cycle_series(component: Series, cardinality: Cardinality | None) -> Series:
|
|
306
|
+
degree = len(component) - 1
|
|
307
|
+
if component[0]:
|
|
308
|
+
raise UnsupportedConstruction("An unlabelled Cycle cannot contain size-zero objects")
|
|
309
|
+
minimum, maximum = component_bounds(cardinality or Cardinality(1), degree)
|
|
310
|
+
minimum = max(1, minimum)
|
|
311
|
+
result = zero_series(degree)
|
|
312
|
+
|
|
313
|
+
for count in range(minimum, maximum + 1):
|
|
314
|
+
fixed_count = zero_series(degree)
|
|
315
|
+
for divisor in range(1, count + 1):
|
|
316
|
+
if count % divisor:
|
|
317
|
+
continue
|
|
318
|
+
substituted = substitute_power(component, divisor)
|
|
319
|
+
contribution = power_series(substituted, count // divisor)
|
|
320
|
+
fixed_count = add_series(
|
|
321
|
+
fixed_count,
|
|
322
|
+
scale_series(contribution, Fraction(euler_totient(divisor), count)),
|
|
323
|
+
)
|
|
324
|
+
result = add_series(result, fixed_count)
|
|
325
|
+
return result
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
class Evaluator:
|
|
329
|
+
def __init__(self, equations: dict[str, Expression], degree: int, labelled: bool):
|
|
330
|
+
self.equations = equations
|
|
331
|
+
self.degree = degree
|
|
332
|
+
self.labelled = labelled
|
|
333
|
+
|
|
334
|
+
def compute(self, symbol: str) -> Series:
|
|
335
|
+
if symbol not in self.equations:
|
|
336
|
+
raise SpecificationError(f"Specification does not define {symbol!r}")
|
|
337
|
+
|
|
338
|
+
values = {name: zero_series(self.degree) for name in self.equations}
|
|
339
|
+
iteration_limit = max(100, (self.degree + 1) * max(1, len(values)) * 4)
|
|
340
|
+
for _ in range(iteration_limit):
|
|
341
|
+
updated = {
|
|
342
|
+
name: self._evaluate(expression, values)
|
|
343
|
+
for name, expression in self.equations.items()
|
|
344
|
+
}
|
|
345
|
+
if updated == values:
|
|
346
|
+
return updated[symbol]
|
|
347
|
+
values = updated
|
|
348
|
+
raise UnsupportedConstruction(
|
|
349
|
+
f"The recursive system did not stabilize through degree {self.degree}; "
|
|
350
|
+
"it may not be well founded",
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
def _evaluate(self, expression: Expression, values: dict[str, Series]) -> Series:
|
|
354
|
+
if isinstance(expression, Reference):
|
|
355
|
+
if expression.name in ("Atom", "Z") and expression.name not in self.equations:
|
|
356
|
+
return atom_series(self.degree)
|
|
357
|
+
if expression.name == "Epsilon":
|
|
358
|
+
return one_series(self.degree)
|
|
359
|
+
if expression.name not in values:
|
|
360
|
+
raise SpecificationError(f"Undefined symbol {expression.name!r}")
|
|
361
|
+
return values[expression.name]
|
|
362
|
+
|
|
363
|
+
arguments = [self._evaluate(argument, values) for argument in expression.arguments]
|
|
364
|
+
name = expression.name.lower()
|
|
365
|
+
if name == "union":
|
|
366
|
+
if expression.cardinality is not None:
|
|
367
|
+
raise SpecificationError("Union does not accept a cardinality constraint")
|
|
368
|
+
return add_series(*arguments)
|
|
369
|
+
if name == "prod":
|
|
370
|
+
if expression.cardinality is not None:
|
|
371
|
+
raise SpecificationError("Prod does not accept a cardinality constraint")
|
|
372
|
+
return product_series(arguments, self.degree)
|
|
373
|
+
if len(arguments) != 1:
|
|
374
|
+
raise SpecificationError(f"{expression.name} requires exactly one component argument")
|
|
375
|
+
|
|
376
|
+
component = arguments[0]
|
|
377
|
+
if name == "sequence":
|
|
378
|
+
return sequence_series(component, expression.cardinality)
|
|
379
|
+
if name == "set":
|
|
380
|
+
if self.labelled:
|
|
381
|
+
return labelled_set_series(component, expression.cardinality)
|
|
382
|
+
return unlabelled_selection_series(
|
|
383
|
+
component,
|
|
384
|
+
expression.cardinality,
|
|
385
|
+
distinct=False,
|
|
386
|
+
)
|
|
387
|
+
if name == "cycle":
|
|
388
|
+
if self.labelled:
|
|
389
|
+
return labelled_cycle_series(component, expression.cardinality)
|
|
390
|
+
return unlabelled_cycle_series(component, expression.cardinality)
|
|
391
|
+
if name == "powerset":
|
|
392
|
+
if self.labelled:
|
|
393
|
+
raise UnsupportedConstruction("PowerSet is only defined for unlabelled structures")
|
|
394
|
+
if expression.cardinality is not None:
|
|
395
|
+
raise UnsupportedConstruction("PowerSet cardinality constraints are not supported")
|
|
396
|
+
return unlabelled_selection_series(component, None, distinct=True)
|
|
397
|
+
raise UnsupportedConstruction(f"Unsupported constructor {expression.name!r}")
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
class CoefficientNode:
|
|
401
|
+
def __init__(self, compiler: CoefficientCompiler):
|
|
402
|
+
self.compiler = compiler
|
|
403
|
+
self.coefficients: CoefficientSeries = [0 for _ in range(compiler.degree + 1)]
|
|
404
|
+
compiler.nodes.append(self)
|
|
405
|
+
|
|
406
|
+
def value(self, degree: int) -> ExactNumber:
|
|
407
|
+
raise NotImplementedError
|
|
408
|
+
|
|
409
|
+
def update(self, degree: int) -> bool:
|
|
410
|
+
value = compact_number(self.value(degree))
|
|
411
|
+
if value == self.coefficients[degree]:
|
|
412
|
+
return False
|
|
413
|
+
self.coefficients[degree] = value
|
|
414
|
+
return True
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
def compact_number(value: ExactNumber) -> ExactNumber:
|
|
418
|
+
if isinstance(value, Fraction) and value.denominator == 1:
|
|
419
|
+
return value.numerator
|
|
420
|
+
return value
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
def divide_exact(value: ExactNumber, divisor: int) -> ExactNumber:
|
|
424
|
+
if isinstance(value, int):
|
|
425
|
+
quotient, remainder = divmod(value, divisor)
|
|
426
|
+
return quotient if remainder == 0 else Fraction(value, divisor)
|
|
427
|
+
return compact_number(value / divisor)
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
def is_nonnegative_integer(value: ExactNumber) -> bool:
|
|
431
|
+
return value >= 0 and (isinstance(value, int) or value.denominator == 1)
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
def integer_value(value: ExactNumber) -> int:
|
|
435
|
+
return value if isinstance(value, int) else value.numerator
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
@cache
|
|
439
|
+
def binomial_row(degree: int) -> tuple[int, ...]:
|
|
440
|
+
row = [1]
|
|
441
|
+
for index in range(1, degree + 1):
|
|
442
|
+
row.append(row[-1] * (degree - index + 1) // index)
|
|
443
|
+
return tuple(row)
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
def decimal_digit_count(value: int) -> int:
|
|
447
|
+
value = abs(value)
|
|
448
|
+
if value == 0:
|
|
449
|
+
return 1
|
|
450
|
+
digits = int((value.bit_length() - 1) * math.log10(2)) + 1
|
|
451
|
+
if value >= 10**digits:
|
|
452
|
+
return digits + 1
|
|
453
|
+
if value < 10 ** (digits - 1):
|
|
454
|
+
return digits - 1
|
|
455
|
+
return digits
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
class LiteralNode(CoefficientNode):
|
|
459
|
+
def __init__(self, compiler: CoefficientCompiler, nonzero_degree: int | None):
|
|
460
|
+
self.nonzero_degree = nonzero_degree
|
|
461
|
+
super().__init__(compiler)
|
|
462
|
+
|
|
463
|
+
def value(self, degree: int) -> ExactNumber:
|
|
464
|
+
return int(degree == self.nonzero_degree)
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
class ReferenceNode(CoefficientNode):
|
|
468
|
+
def __init__(self, compiler: CoefficientCompiler, name: str):
|
|
469
|
+
self.name = name
|
|
470
|
+
super().__init__(compiler)
|
|
471
|
+
|
|
472
|
+
def value(self, degree: int) -> ExactNumber:
|
|
473
|
+
try:
|
|
474
|
+
return self.compiler.roots[self.name].coefficients[degree]
|
|
475
|
+
except KeyError as error:
|
|
476
|
+
raise SpecificationError(f"Undefined symbol {self.name!r}") from error
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
class SumNode(CoefficientNode):
|
|
480
|
+
def __init__(self, compiler: CoefficientCompiler, children: Sequence[CoefficientNode]):
|
|
481
|
+
self.children = tuple(children)
|
|
482
|
+
super().__init__(compiler)
|
|
483
|
+
|
|
484
|
+
def value(self, degree: int) -> ExactNumber:
|
|
485
|
+
return sum(child.coefficients[degree] for child in self.children)
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
class ProductNode(CoefficientNode):
|
|
489
|
+
def __init__(
|
|
490
|
+
self, compiler: CoefficientCompiler, left: CoefficientNode, right: CoefficientNode
|
|
491
|
+
):
|
|
492
|
+
self.left = left
|
|
493
|
+
self.right = right
|
|
494
|
+
super().__init__(compiler)
|
|
495
|
+
|
|
496
|
+
def value(self, degree: int) -> ExactNumber:
|
|
497
|
+
weights = binomial_row(degree) if self.compiler.labelled else None
|
|
498
|
+
return sum(
|
|
499
|
+
(
|
|
500
|
+
(weights[index] if weights else 1)
|
|
501
|
+
* self.left.coefficients[index]
|
|
502
|
+
* self.right.coefficients[degree - index]
|
|
503
|
+
for index in range(degree + 1)
|
|
504
|
+
),
|
|
505
|
+
0,
|
|
506
|
+
)
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
class ScaleNode(CoefficientNode):
|
|
510
|
+
def __init__(self, compiler: CoefficientCompiler, child: CoefficientNode, scalar: Fraction):
|
|
511
|
+
self.child = child
|
|
512
|
+
self.scalar = scalar
|
|
513
|
+
super().__init__(compiler)
|
|
514
|
+
|
|
515
|
+
def value(self, degree: int) -> ExactNumber:
|
|
516
|
+
return self.scalar * self.child.coefficients[degree]
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
class SubstituteNode(CoefficientNode):
|
|
520
|
+
def __init__(self, compiler: CoefficientCompiler, child: CoefficientNode, exponent: int):
|
|
521
|
+
self.child = child
|
|
522
|
+
self.exponent = exponent
|
|
523
|
+
super().__init__(compiler)
|
|
524
|
+
|
|
525
|
+
def value(self, degree: int) -> ExactNumber:
|
|
526
|
+
if degree % self.exponent:
|
|
527
|
+
return 0
|
|
528
|
+
return self.child.coefficients[degree // self.exponent]
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
class InverseOneMinusNode(CoefficientNode):
|
|
532
|
+
def __init__(self, compiler: CoefficientCompiler, child: CoefficientNode):
|
|
533
|
+
self.child = child
|
|
534
|
+
super().__init__(compiler)
|
|
535
|
+
|
|
536
|
+
def value(self, degree: int) -> ExactNumber:
|
|
537
|
+
if self.child.coefficients[0]:
|
|
538
|
+
raise UnsupportedConstruction(
|
|
539
|
+
"An unrestricted Sequence cannot contain size-zero objects"
|
|
540
|
+
)
|
|
541
|
+
if degree == 0:
|
|
542
|
+
return 1
|
|
543
|
+
weights = binomial_row(degree) if self.compiler.labelled else None
|
|
544
|
+
return sum(
|
|
545
|
+
(
|
|
546
|
+
(weights[index] if weights else 1)
|
|
547
|
+
* self.child.coefficients[index]
|
|
548
|
+
* self.coefficients[degree - index]
|
|
549
|
+
for index in range(1, degree + 1)
|
|
550
|
+
),
|
|
551
|
+
0,
|
|
552
|
+
)
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
class ExpNode(CoefficientNode):
|
|
556
|
+
def __init__(self, compiler: CoefficientCompiler, child: CoefficientNode):
|
|
557
|
+
self.child = child
|
|
558
|
+
super().__init__(compiler)
|
|
559
|
+
|
|
560
|
+
def value(self, degree: int) -> ExactNumber:
|
|
561
|
+
if self.child.coefficients[0]:
|
|
562
|
+
raise UnsupportedConstruction(
|
|
563
|
+
"An exponential construction cannot contain size-zero objects"
|
|
564
|
+
)
|
|
565
|
+
if degree == 0:
|
|
566
|
+
return 1
|
|
567
|
+
if self.compiler.labelled:
|
|
568
|
+
weights = binomial_row(degree - 1)
|
|
569
|
+
return sum(
|
|
570
|
+
(
|
|
571
|
+
weights[index - 1]
|
|
572
|
+
* self.child.coefficients[index]
|
|
573
|
+
* self.coefficients[degree - index]
|
|
574
|
+
for index in range(1, degree + 1)
|
|
575
|
+
),
|
|
576
|
+
0,
|
|
577
|
+
)
|
|
578
|
+
total = sum(
|
|
579
|
+
(
|
|
580
|
+
index * self.child.coefficients[index] * self.coefficients[degree - index]
|
|
581
|
+
for index in range(1, degree + 1)
|
|
582
|
+
),
|
|
583
|
+
0,
|
|
584
|
+
)
|
|
585
|
+
return divide_exact(total, degree)
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
class LogOneMinusNode(CoefficientNode):
|
|
589
|
+
def __init__(self, compiler: CoefficientCompiler, child: CoefficientNode):
|
|
590
|
+
self.child = child
|
|
591
|
+
self.inverse = InverseOneMinusNode(compiler, child)
|
|
592
|
+
super().__init__(compiler)
|
|
593
|
+
|
|
594
|
+
def value(self, degree: int) -> ExactNumber:
|
|
595
|
+
if degree == 0:
|
|
596
|
+
return 0
|
|
597
|
+
if self.compiler.labelled:
|
|
598
|
+
weights = binomial_row(degree - 1)
|
|
599
|
+
return sum(
|
|
600
|
+
(
|
|
601
|
+
weights[index - 1]
|
|
602
|
+
* self.child.coefficients[index]
|
|
603
|
+
* self.inverse.coefficients[degree - index]
|
|
604
|
+
for index in range(1, degree + 1)
|
|
605
|
+
),
|
|
606
|
+
0,
|
|
607
|
+
)
|
|
608
|
+
total = sum(
|
|
609
|
+
(
|
|
610
|
+
index * self.child.coefficients[index] * self.inverse.coefficients[degree - index]
|
|
611
|
+
for index in range(1, degree + 1)
|
|
612
|
+
),
|
|
613
|
+
0,
|
|
614
|
+
)
|
|
615
|
+
return divide_exact(total, degree)
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
def divisors(value: int) -> list[int]:
|
|
619
|
+
small: list[int] = []
|
|
620
|
+
large: list[int] = []
|
|
621
|
+
candidate = 1
|
|
622
|
+
while candidate * candidate <= value:
|
|
623
|
+
if value % candidate == 0:
|
|
624
|
+
small.append(candidate)
|
|
625
|
+
if candidate * candidate != value:
|
|
626
|
+
large.append(value // candidate)
|
|
627
|
+
candidate += 1
|
|
628
|
+
return small + list(reversed(large))
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
class EulerSelectionNode(CoefficientNode):
|
|
632
|
+
"""Unrestricted unlabelled Set or PowerSet via its logarithm."""
|
|
633
|
+
|
|
634
|
+
def __init__(self, compiler: CoefficientCompiler, child: CoefficientNode, distinct: bool):
|
|
635
|
+
self.child = child
|
|
636
|
+
self.distinct = distinct
|
|
637
|
+
self.log_coefficients: CoefficientSeries = [0 for _ in range(compiler.degree + 1)]
|
|
638
|
+
super().__init__(compiler)
|
|
639
|
+
|
|
640
|
+
def value(self, degree: int) -> ExactNumber:
|
|
641
|
+
constant = self.child.coefficients[0]
|
|
642
|
+
if not is_nonnegative_integer(constant):
|
|
643
|
+
raise UnsupportedConstruction(
|
|
644
|
+
"Unlabelled selections require nonnegative integer coefficients"
|
|
645
|
+
)
|
|
646
|
+
if constant and not self.distinct:
|
|
647
|
+
raise UnsupportedConstruction("An unlabelled Set cannot contain size-zero objects")
|
|
648
|
+
if degree == 0:
|
|
649
|
+
return 2 ** integer_value(constant) if self.distinct else 1
|
|
650
|
+
|
|
651
|
+
logarithm: ExactNumber = 0
|
|
652
|
+
for divisor in divisors(degree):
|
|
653
|
+
coefficient = self.child.coefficients[degree // divisor]
|
|
654
|
+
if not is_nonnegative_integer(coefficient):
|
|
655
|
+
raise UnsupportedConstruction(
|
|
656
|
+
"Unlabelled selections require nonnegative integer component coefficients",
|
|
657
|
+
)
|
|
658
|
+
sign = -1 if self.distinct and divisor % 2 == 0 else 1
|
|
659
|
+
logarithm += sign * Fraction(integer_value(coefficient), divisor)
|
|
660
|
+
self.log_coefficients[degree] = compact_number(logarithm)
|
|
661
|
+
total = sum(
|
|
662
|
+
(
|
|
663
|
+
index * self.log_coefficients[index] * self.coefficients[degree - index]
|
|
664
|
+
for index in range(1, degree + 1)
|
|
665
|
+
),
|
|
666
|
+
0,
|
|
667
|
+
)
|
|
668
|
+
return divide_exact(total, degree)
|
|
669
|
+
|
|
670
|
+
|
|
671
|
+
class UnlabelledCycleNode(CoefficientNode):
|
|
672
|
+
def __init__(self, compiler: CoefficientCompiler, child: CoefficientNode):
|
|
673
|
+
self.logarithm = LogOneMinusNode(compiler, child)
|
|
674
|
+
super().__init__(compiler)
|
|
675
|
+
|
|
676
|
+
def value(self, degree: int) -> ExactNumber:
|
|
677
|
+
if degree == 0:
|
|
678
|
+
return Fraction(0)
|
|
679
|
+
return sum(
|
|
680
|
+
(
|
|
681
|
+
Fraction(euler_totient(divisor), divisor)
|
|
682
|
+
* self.logarithm.coefficients[degree // divisor]
|
|
683
|
+
for divisor in divisors(degree)
|
|
684
|
+
),
|
|
685
|
+
Fraction(0),
|
|
686
|
+
)
|
|
687
|
+
|
|
688
|
+
|
|
689
|
+
class CoefficientCompiler:
|
|
690
|
+
def __init__(self, equations: dict[str, Expression], degree: int, labelled: bool):
|
|
691
|
+
self.equations = equations
|
|
692
|
+
self.degree = degree
|
|
693
|
+
self.labelled = labelled
|
|
694
|
+
self.nodes: list[CoefficientNode] = []
|
|
695
|
+
self.roots: dict[str, CoefficientNode] = {}
|
|
696
|
+
self._powers: dict[tuple[int, int], CoefficientNode] = {}
|
|
697
|
+
self._fixed_msets: dict[tuple[int, int], CoefficientNode] = {}
|
|
698
|
+
self.zero = LiteralNode(self, None)
|
|
699
|
+
self.one = LiteralNode(self, 0)
|
|
700
|
+
self.atom = LiteralNode(self, 1)
|
|
701
|
+
|
|
702
|
+
def compute(self, symbol: str, max_digits: int | None = None) -> CoefficientSeries:
|
|
703
|
+
if symbol not in self.equations:
|
|
704
|
+
raise SpecificationError(f"Specification does not define {symbol!r}")
|
|
705
|
+
equation_order, recursive = self.equation_order()
|
|
706
|
+
for name in equation_order:
|
|
707
|
+
self.roots[name] = self.compile(self.equations[name])
|
|
708
|
+
|
|
709
|
+
for degree in range(self.degree + 1):
|
|
710
|
+
if not recursive:
|
|
711
|
+
for node in self.nodes:
|
|
712
|
+
node.update(degree)
|
|
713
|
+
else:
|
|
714
|
+
iteration_limit = max(100, len(self.nodes) * 4)
|
|
715
|
+
for _ in range(iteration_limit):
|
|
716
|
+
changed = False
|
|
717
|
+
for node in self.nodes:
|
|
718
|
+
changed = node.update(degree) or changed
|
|
719
|
+
if not changed:
|
|
720
|
+
break
|
|
721
|
+
else:
|
|
722
|
+
raise UnsupportedConstruction(
|
|
723
|
+
f"The recursive system did not stabilize at degree {degree}; "
|
|
724
|
+
"it may not be well founded",
|
|
725
|
+
)
|
|
726
|
+
|
|
727
|
+
if max_digits is not None:
|
|
728
|
+
value = self.roots[symbol].coefficients[degree]
|
|
729
|
+
if isinstance(value, Fraction) and value.denominator != 1:
|
|
730
|
+
raise UnsupportedConstruction(
|
|
731
|
+
f"Coefficient of size {degree} does not yield an integer count: {value}",
|
|
732
|
+
)
|
|
733
|
+
if decimal_digit_count(integer_value(value)) > max_digits:
|
|
734
|
+
return self.roots[symbol].coefficients[:degree]
|
|
735
|
+
return self.roots[symbol].coefficients
|
|
736
|
+
|
|
737
|
+
def equation_order(self) -> tuple[list[str], bool]:
|
|
738
|
+
dependencies = {
|
|
739
|
+
name: self.expression_references(expression) & self.equations.keys()
|
|
740
|
+
for name, expression in self.equations.items()
|
|
741
|
+
}
|
|
742
|
+
order: list[str] = []
|
|
743
|
+
temporary: set[str] = set()
|
|
744
|
+
permanent: set[str] = set()
|
|
745
|
+
recursive = False
|
|
746
|
+
|
|
747
|
+
def visit(name: str) -> None:
|
|
748
|
+
nonlocal recursive
|
|
749
|
+
if name in permanent:
|
|
750
|
+
return
|
|
751
|
+
if name in temporary:
|
|
752
|
+
recursive = True
|
|
753
|
+
return
|
|
754
|
+
temporary.add(name)
|
|
755
|
+
for dependency in dependencies[name]:
|
|
756
|
+
visit(dependency)
|
|
757
|
+
temporary.remove(name)
|
|
758
|
+
permanent.add(name)
|
|
759
|
+
order.append(name)
|
|
760
|
+
|
|
761
|
+
for name in self.equations:
|
|
762
|
+
visit(name)
|
|
763
|
+
return order, recursive
|
|
764
|
+
|
|
765
|
+
@classmethod
|
|
766
|
+
def expression_references(cls, expression: Expression) -> set[str]:
|
|
767
|
+
if isinstance(expression, Reference):
|
|
768
|
+
return {expression.name}
|
|
769
|
+
references: set[str] = set()
|
|
770
|
+
for argument in expression.arguments:
|
|
771
|
+
references.update(cls.expression_references(argument))
|
|
772
|
+
return references
|
|
773
|
+
|
|
774
|
+
def compile(self, expression: Expression) -> CoefficientNode:
|
|
775
|
+
if isinstance(expression, Reference):
|
|
776
|
+
if expression.name == "Epsilon":
|
|
777
|
+
return self.one
|
|
778
|
+
if expression.name in ("Atom", "Z") and expression.name not in self.equations:
|
|
779
|
+
return self.atom
|
|
780
|
+
return ReferenceNode(self, expression.name)
|
|
781
|
+
|
|
782
|
+
children = [self.compile(argument) for argument in expression.arguments]
|
|
783
|
+
name = expression.name.lower()
|
|
784
|
+
if name == "union":
|
|
785
|
+
if expression.cardinality is not None:
|
|
786
|
+
raise SpecificationError("Union does not accept a cardinality constraint")
|
|
787
|
+
return self.sum(children)
|
|
788
|
+
if name == "prod":
|
|
789
|
+
if expression.cardinality is not None:
|
|
790
|
+
raise SpecificationError("Prod does not accept a cardinality constraint")
|
|
791
|
+
return self.product(children)
|
|
792
|
+
if len(children) != 1:
|
|
793
|
+
raise SpecificationError(f"{expression.name} requires exactly one component argument")
|
|
794
|
+
|
|
795
|
+
child = children[0]
|
|
796
|
+
if name == "sequence":
|
|
797
|
+
return self.sequence(child, expression.cardinality)
|
|
798
|
+
if name == "set":
|
|
799
|
+
return (
|
|
800
|
+
self.labelled_set(child, expression.cardinality)
|
|
801
|
+
if self.labelled
|
|
802
|
+
else self.mset(
|
|
803
|
+
child,
|
|
804
|
+
expression.cardinality,
|
|
805
|
+
)
|
|
806
|
+
)
|
|
807
|
+
if name == "cycle":
|
|
808
|
+
return self.cycle(child, expression.cardinality)
|
|
809
|
+
if name == "powerset":
|
|
810
|
+
if self.labelled:
|
|
811
|
+
raise UnsupportedConstruction("PowerSet is only defined for unlabelled structures")
|
|
812
|
+
if expression.cardinality is not None:
|
|
813
|
+
raise UnsupportedConstruction("PowerSet cardinality constraints are not supported")
|
|
814
|
+
return EulerSelectionNode(self, child, distinct=True)
|
|
815
|
+
raise UnsupportedConstruction(f"Unsupported constructor {expression.name!r}")
|
|
816
|
+
|
|
817
|
+
def sum(self, children: Sequence[CoefficientNode]) -> CoefficientNode:
|
|
818
|
+
if not children:
|
|
819
|
+
return self.zero
|
|
820
|
+
if len(children) == 1:
|
|
821
|
+
return children[0]
|
|
822
|
+
return SumNode(self, children)
|
|
823
|
+
|
|
824
|
+
def product(self, children: Sequence[CoefficientNode]) -> CoefficientNode:
|
|
825
|
+
if not children:
|
|
826
|
+
return self.one
|
|
827
|
+
result: CoefficientNode = children[0]
|
|
828
|
+
for child in children[1:]:
|
|
829
|
+
result = ProductNode(self, result, child)
|
|
830
|
+
return result
|
|
831
|
+
|
|
832
|
+
def scale(self, child: CoefficientNode, scalar: Fraction) -> CoefficientNode:
|
|
833
|
+
return child if scalar == 1 else ScaleNode(self, child, scalar)
|
|
834
|
+
|
|
835
|
+
def power(self, child: CoefficientNode, exponent: int) -> CoefficientNode:
|
|
836
|
+
key = (id(child), exponent)
|
|
837
|
+
if key in self._powers:
|
|
838
|
+
return self._powers[key]
|
|
839
|
+
if exponent == 0:
|
|
840
|
+
result: CoefficientNode = self.one
|
|
841
|
+
else:
|
|
842
|
+
result = self.one
|
|
843
|
+
for _ in range(exponent):
|
|
844
|
+
result = ProductNode(self, result, child)
|
|
845
|
+
self._powers[key] = result
|
|
846
|
+
return result
|
|
847
|
+
|
|
848
|
+
@staticmethod
|
|
849
|
+
def bounds(cardinality: Cardinality | None, default_minimum: int = 0) -> tuple[int, int | None]:
|
|
850
|
+
if cardinality is None:
|
|
851
|
+
return default_minimum, None
|
|
852
|
+
return max(default_minimum, cardinality.minimum), cardinality.maximum
|
|
853
|
+
|
|
854
|
+
def sequence(self, child: CoefficientNode, cardinality: Cardinality | None) -> CoefficientNode:
|
|
855
|
+
minimum, maximum = self.bounds(cardinality)
|
|
856
|
+
if maximum is not None:
|
|
857
|
+
return self.sum([self.power(child, count) for count in range(minimum, maximum + 1)])
|
|
858
|
+
inverse = InverseOneMinusNode(self, child)
|
|
859
|
+
return self.product([self.power(child, minimum), inverse])
|
|
860
|
+
|
|
861
|
+
def labelled_set(
|
|
862
|
+
self, child: CoefficientNode, cardinality: Cardinality | None
|
|
863
|
+
) -> CoefficientNode:
|
|
864
|
+
minimum, maximum = self.bounds(cardinality)
|
|
865
|
+
if maximum is not None:
|
|
866
|
+
return self.sum(
|
|
867
|
+
[
|
|
868
|
+
self.scale(self.power(child, count), Fraction(1, math.factorial(count)))
|
|
869
|
+
for count in range(minimum, maximum + 1)
|
|
870
|
+
],
|
|
871
|
+
)
|
|
872
|
+
unrestricted = ExpNode(self, child)
|
|
873
|
+
excluded = self.sum(
|
|
874
|
+
[
|
|
875
|
+
self.scale(self.power(child, count), Fraction(1, math.factorial(count)))
|
|
876
|
+
for count in range(minimum)
|
|
877
|
+
],
|
|
878
|
+
)
|
|
879
|
+
return self.sum([unrestricted, self.scale(excluded, Fraction(-1))])
|
|
880
|
+
|
|
881
|
+
def fixed_mset(self, child: CoefficientNode, count: int) -> CoefficientNode:
|
|
882
|
+
key = (id(child), count)
|
|
883
|
+
if key in self._fixed_msets:
|
|
884
|
+
return self._fixed_msets[key]
|
|
885
|
+
if count == 0:
|
|
886
|
+
result: CoefficientNode = self.one
|
|
887
|
+
else:
|
|
888
|
+
terms = []
|
|
889
|
+
for part in range(1, count + 1):
|
|
890
|
+
substituted = SubstituteNode(self, child, part)
|
|
891
|
+
terms.append(ProductNode(self, substituted, self.fixed_mset(child, count - part)))
|
|
892
|
+
result = self.scale(self.sum(terms), Fraction(1, count))
|
|
893
|
+
self._fixed_msets[key] = result
|
|
894
|
+
return result
|
|
895
|
+
|
|
896
|
+
def mset(self, child: CoefficientNode, cardinality: Cardinality | None) -> CoefficientNode:
|
|
897
|
+
minimum, maximum = self.bounds(cardinality)
|
|
898
|
+
if maximum is not None:
|
|
899
|
+
return self.sum(
|
|
900
|
+
[self.fixed_mset(child, count) for count in range(minimum, maximum + 1)]
|
|
901
|
+
)
|
|
902
|
+
unrestricted = EulerSelectionNode(self, child, distinct=False)
|
|
903
|
+
excluded = self.sum([self.fixed_mset(child, count) for count in range(minimum)])
|
|
904
|
+
return self.sum([unrestricted, self.scale(excluded, Fraction(-1))])
|
|
905
|
+
|
|
906
|
+
def fixed_cycle(self, child: CoefficientNode, count: int) -> CoefficientNode:
|
|
907
|
+
if self.labelled:
|
|
908
|
+
return self.scale(self.power(child, count), Fraction(1, count))
|
|
909
|
+
terms = []
|
|
910
|
+
for divisor in divisors(count):
|
|
911
|
+
substituted = SubstituteNode(self, child, divisor)
|
|
912
|
+
term = self.power(substituted, count // divisor)
|
|
913
|
+
terms.append(self.scale(term, Fraction(euler_totient(divisor), count)))
|
|
914
|
+
return self.sum(terms)
|
|
915
|
+
|
|
916
|
+
def cycle(self, child: CoefficientNode, cardinality: Cardinality | None) -> CoefficientNode:
|
|
917
|
+
minimum, maximum = self.bounds(cardinality, default_minimum=1)
|
|
918
|
+
if maximum is not None:
|
|
919
|
+
return self.sum(
|
|
920
|
+
[self.fixed_cycle(child, count) for count in range(minimum, maximum + 1)]
|
|
921
|
+
)
|
|
922
|
+
unrestricted = (
|
|
923
|
+
LogOneMinusNode(self, child) if self.labelled else UnlabelledCycleNode(self, child)
|
|
924
|
+
)
|
|
925
|
+
excluded = self.sum([self.fixed_cycle(child, count) for count in range(1, minimum)])
|
|
926
|
+
return self.sum([unrestricted, self.scale(excluded, Fraction(-1))])
|
|
927
|
+
|
|
928
|
+
|
|
929
|
+
def compute_terms(
|
|
930
|
+
specification: str,
|
|
931
|
+
*,
|
|
932
|
+
labelled: bool,
|
|
933
|
+
term_count: int,
|
|
934
|
+
symbol: str = "S",
|
|
935
|
+
max_digits: int | None = None,
|
|
936
|
+
) -> list[int]:
|
|
937
|
+
"""Return counts a(0) through a(term_count - 1) for a specification."""
|
|
938
|
+
|
|
939
|
+
if term_count <= 0:
|
|
940
|
+
raise ValueError("term_count must be positive")
|
|
941
|
+
equations = parse_specification(specification)
|
|
942
|
+
coefficients = CoefficientCompiler(equations, term_count - 1, labelled).compute(
|
|
943
|
+
symbol,
|
|
944
|
+
max_digits=max_digits,
|
|
945
|
+
)
|
|
946
|
+
|
|
947
|
+
terms: list[int] = []
|
|
948
|
+
for degree, coefficient in enumerate(coefficients):
|
|
949
|
+
count = coefficient
|
|
950
|
+
if isinstance(count, Fraction) and count.denominator != 1:
|
|
951
|
+
raise UnsupportedConstruction(
|
|
952
|
+
f"Coefficient of size {degree} does not yield an integer count: {count}",
|
|
953
|
+
)
|
|
954
|
+
terms.append(integer_value(count))
|
|
955
|
+
return terms
|
|
956
|
+
|
|
957
|
+
|
|
958
|
+
def load_record(dataset: Path, structure_id: int) -> dict[str, Any]:
|
|
959
|
+
try:
|
|
960
|
+
return _load_record(dataset, structure_id)
|
|
961
|
+
except StructureNotFoundError as error:
|
|
962
|
+
raise SpecificationError(str(error)) from error
|
|
963
|
+
|
|
964
|
+
|
|
965
|
+
def build_argument_parser() -> argparse.ArgumentParser:
|
|
966
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
967
|
+
source = parser.add_mutually_exclusive_group(required=True)
|
|
968
|
+
source.add_argument("--id", type=int, help="ECS structure number to load from the dataset")
|
|
969
|
+
source.add_argument("--spec", help="Specification text, for example '{S = Sequence(Z)}'")
|
|
970
|
+
parser.add_argument("--dataset", type=Path, default=default_dataset())
|
|
971
|
+
parser.add_argument(
|
|
972
|
+
"--terms", type=int, default=20, help="number of terms, beginning with a(0)"
|
|
973
|
+
)
|
|
974
|
+
parser.add_argument("--symbol", default="S", help="root symbol to enumerate (default: S)")
|
|
975
|
+
parser.add_argument(
|
|
976
|
+
"--max-digits", type=int, help="stop before a term exceeds this many digits"
|
|
977
|
+
)
|
|
978
|
+
universe = parser.add_mutually_exclusive_group()
|
|
979
|
+
universe.add_argument("--labelled", action="store_true", help="use labelled/EGF semantics")
|
|
980
|
+
universe.add_argument("--unlabelled", action="store_true", help="use unlabelled/OGF semantics")
|
|
981
|
+
parser.add_argument(
|
|
982
|
+
"--plain", action="store_true", help="print comma-separated integers instead of JSON"
|
|
983
|
+
)
|
|
984
|
+
return parser
|
|
985
|
+
|
|
986
|
+
|
|
987
|
+
def main(argv: Iterable[str] | None = None) -> int:
|
|
988
|
+
parser = build_argument_parser()
|
|
989
|
+
arguments = parser.parse_args(argv)
|
|
990
|
+
|
|
991
|
+
record = None
|
|
992
|
+
if arguments.id is not None:
|
|
993
|
+
record = load_record(arguments.dataset, arguments.id)
|
|
994
|
+
specification = record["specification"]
|
|
995
|
+
labelled = bool(record["labeled"])
|
|
996
|
+
symbol = record.get("symbol") or arguments.symbol
|
|
997
|
+
else:
|
|
998
|
+
if not arguments.labelled and not arguments.unlabelled:
|
|
999
|
+
parser.error("--spec requires either --labelled or --unlabelled")
|
|
1000
|
+
specification = arguments.spec
|
|
1001
|
+
labelled = arguments.labelled
|
|
1002
|
+
symbol = arguments.symbol
|
|
1003
|
+
|
|
1004
|
+
try:
|
|
1005
|
+
terms = compute_terms(
|
|
1006
|
+
specification,
|
|
1007
|
+
labelled=labelled,
|
|
1008
|
+
term_count=arguments.terms,
|
|
1009
|
+
symbol=symbol,
|
|
1010
|
+
max_digits=arguments.max_digits,
|
|
1011
|
+
)
|
|
1012
|
+
except (SpecificationError, ValueError) as error:
|
|
1013
|
+
parser.exit(2, f"error: {error}\n")
|
|
1014
|
+
|
|
1015
|
+
if arguments.plain:
|
|
1016
|
+
print(", ".join(map(str, terms)))
|
|
1017
|
+
return 0
|
|
1018
|
+
|
|
1019
|
+
output = {
|
|
1020
|
+
"id": arguments.id,
|
|
1021
|
+
"symbol": symbol,
|
|
1022
|
+
"labelled": labelled,
|
|
1023
|
+
"terms": [str(term) for term in terms],
|
|
1024
|
+
}
|
|
1025
|
+
if record is not None:
|
|
1026
|
+
stored = [str(term) for term in record.get("terms", [])]
|
|
1027
|
+
overlap = min(len(stored), len(terms))
|
|
1028
|
+
output["matches_stored_prefix"] = stored[:overlap] == output["terms"][:overlap]
|
|
1029
|
+
print(json.dumps(output, indent=2))
|
|
1030
|
+
return 0
|
|
1031
|
+
|
|
1032
|
+
|
|
1033
|
+
if __name__ == "__main__":
|
|
1034
|
+
raise SystemExit(main())
|