public LGEdge(LCNode _info, LGVertex _s, LGVertex _d) { this.id = 0; this.PLCInfo = _info; this.Source = _s; this.Destination = _d; }
/// <summary> /// 将制定的点设为终点 /// </summary> public void SetTerminate(int id) { if (id <= 0 || id > vertexs.Count) { throw new ArgumentOutOfRangeException(); } LGVertex lgv = vertexs[id - 1]; if (terminates.Contains(lgv)) { return; } lgv.IsTerminate = true; terminates.Add(lgv); }
/// <summary> /// 将制定的点设为起点 /// </summary> public void SetStart(int id) { if (id <= 0 || id > vertexs.Count) { throw new ArgumentOutOfRangeException(); } LGVertex lgv = vertexs[id - 1]; if (starts.Contains(lgv)) { return; } lgv.IsStart = true; starts.Add(lgv); }
} /// <summary> /// 得到点标记中点标号的对应位 /// </summary> /// <param name="lge">给定的边</param> /// <param name="id">给定的点标号</param> /// <returns>对应的位的值(0或1,1返回true)</returns> private bool _VertexGetFlag(LGVertex lgv, int id) { if (id <= 32) { return(((lgv[1] >> (id - 1)) & 1) != 0); } if (id <= 64) { return(((lgv[2] >> (id - 33)) & 1) != 0); } if (id <= 96) { return(((lgv[3] >> (id - 65)) & 1) != 0); } if (id <= 128) { return(((lgv[4] >> (id - 97)) & 1) != 0); } throw new IndexOutOfRangeException(); }
/// <summary> /// 从当前边开始前向查询,得到到达所有节点的通行情况,保存在标记中 /// </summary> /// <param name="lgv">当前要查询的边</param> private void _EdgeSearch(LGVertex lgv) { foreach (LGEdge lge in lgv.Edges) { // 指向的点未被访问,标记为空 if (_VertexEmptyFlag(lge.Destination)) { _EdgeSearch(lge.Destination); } // 将边的标记设为指向点的标记 lge[1] = lge.Destination[1]; lge[2] = lge.Destination[2]; lge[3] = lge.Destination[3]; lge[4] = lge.Destination[4]; // 能够指向该点,添加通行信息 _EdgeSetFlag(lge, lge.Destination.Id); // 该点统计所有前向边 lgv[1] |= lge[1]; lgv[2] |= lge[2]; lgv[3] |= lge[3]; lgv[4] |= lge[4]; } }
/// <summary> /// 判断这个点的所有标记是否为空 /// </summary> /// <param name="lgv">给定的点</param> /// <returns>是否为空,为空返回true</returns> private bool _VertexEmptyFlag(LGVertex lgv) { return(lgv[1] == 0 && lgv[2] == 0 && lgv[3] == 0 && lgv[4] == 0); }
/// <summary> /// 检查是否短路,在逻辑图中体现为单向环 /// </summary> public bool checkShortCircuit() { // 做一次拓扑排序来检查 // 初始化每个节点的访问标记和后向计数 foreach (LGVertex lgv in vertexs) { lgv[4] = 0; } foreach (LGEdge lge in edges) { lge.Destination[4]++; } // 开始拓扑排序,将计数为0的点加入队列中 Queue <LGVertex> queue = new Queue <LGVertex>(); foreach (LGVertex lgv in vertexs) { if (lgv[4] == 0) { queue.Enqueue(lgv); } } // 记录已经进行拓扑排序的节点数量 int solveCount = 0; while (queue.Count > 0) { solveCount++; LGVertex lgv = queue.Dequeue(); foreach (LGEdge lge in lgv.Edges) { if ((--lge.Destination[4]) == 0) { queue.Enqueue(lge.Destination); } } } // 若存在节点未被排序,则在环中 if (solveCount < vertexs.Count) { return(true); } // 还存在一种短路情况,分支后面出现线路指令(INV,MEP,MEF)时 /* * foreach (LGVertex lgv in vertexs) * { * if (lgv.Edges.Count() > 1) * { * foreach (LGEdge lge in lgv.Edges) * { * switch (lge.PLCInfo.Type) * { * case "INV": case "MEP": case "MEF": * return true; * } * } * } * } */ return(false); }
/// <summary> /// 生成该节点对应的表达式 /// </summary> public void GenExpr() { if (!this.Expr.Equals("null")) { return; } // 若为起点则表达式为1 if (this.IsStart) { this.Expr = "1"; return; } // 生成所有子项表达式 List <String> subexprs = new List <String>(); foreach (LGEdge lge in BackEdges) { LGVertex pv = lge.Source; // 若前向边指向的节点未访问(表达式为"null"),则生成表达式 if (pv.Expr.Equals("null")) { pv.GenExpr(); } string uexpr = lge.PLCInfo.Expr; // 若与运算两边的表达式其中为“1”,则忽略这个“1” if (uexpr.Equals("1")) { lge.Expr = pv.Expr; } else if (pv.Expr.Equals("1")) { lge.Expr = uexpr; } else { lge.Expr = String.Format("{0:s}&&{1:s}", pv.Expr, uexpr); } } // 如果有多个表达式需要或运算 if (BackEdges.Count > 1) { // 按照ASCII码来排序,为后续合并工作做准备 Comparison <LGEdge> sortByExpr = delegate(LGEdge v1, LGEdge v2) { return(v1.Expr.CompareTo(v2.Expr)); }; BackEdges.Sort(sortByExpr); foreach (LGEdge lge in BackEdges) { subexprs.Add(lge.Expr); } // 表达式合并 bool hasor = false; Expr = ExprHelper.Merge(subexprs, 0, subexprs.Count - 1, ref hasor); if (hasor) { Expr = "(" + Expr + ")"; } } // 如果存在前向边 else if (BackEdges.Count > 0) { this.Expr = BackEdges[0].Expr; } else { this.Expr = "1"; } }